python
ACR goes for “Packt Open Source CMS Awards”!
Friday, August 27th, 2010 | Opensource, Web | Comments
Like every year Packt Publishing organizes the Open Source CMS Awards, right now they started the nomination phase.
The following categories make up the contest.
-
Open Source CMS
-
Hall of Fame CMS
-
Most Promising Open Source Project
-
Open Source E-Commerce Applications
-
Open Source JavaScript Libraries
-
Open Source Graphics Software
We decided to propose ACR for the Most Promising Open Source Project and Open Source CMS.
Even if young our CMS is already interesting since it’s quite easy to deploy, it integrates in other turbogears applications (like we did for iJamix) in a breeze and has already most of the features you would expect from a full fledged CMS.
In our humble opinion is the best and most promising Turbogears2 based CMF/CMS out there.
Python Sequence VS Iterable protocols
Wednesday, August 25th, 2010 | Computer Science | Comments
Recently my colleague Luca got an extracted chapter of Python 3 Object Oriented Programming book to review. As I am a long time Python developer and lover I couldn’t stop myself from taking a look at the chapter so satisfy my curiosity.
A little excerpt from the chapter talks about len, reversed and zip functions illuminated me about the fact that usually due to duck typing Python developers tend to consider sequences and iterables quite the same.
The author of the books says that “The zip function takes two or more sequences and creates a new sequence of tuples” and also the help(zip) documentation says “Return a list of tuples, where each tuple contains the i-th element from each of the argument sequences”.
Indeed the zip function works on every iterable, not just sequences. Python tends to define non-formals protocols and looking around in the doc one can discover that the sequence protocol is defined as implementing __len__() and __getitem__() while the iterable protocol requires to implement __iter__() and return an iterator.
This made me think that having duck typing not only allows easier development of code, but also easier communication of concepts. In any other language commonly using formal protocols (ie interfaces, protocols, or any other formal definition of them) the author of the book would have been required to specify also the definition of the two protocols and the differences between them before the reader would have been actually able to use the zip function. In the Python case the author just had to write the sentence in natural language and the reader is aware that he/she can actually call zip on any collection, container or even generator. Anything that he unconsciously recognizes as a sequence without even having to know the existance of the protocol itself..
Indeed I recognize that duck typing and non-formal protocols tend to be more error prone, but its interesting to notice that they also help to simply communication of concepts as human tend to find easier to feel intuitions over formal definitions.
libacr published on PyPI
Wednesday, July 28th, 2010 | Computer Science, Opensource, Software Development, Web | Comments
As we are moving to make libacr a very cool and functional python CMF, we published libacr on PyPI!
Now you just need to:
pip install libacr
and you are done, as easy as saying!
More details on http://pypi.python.org/pypi/libacr/
Personalize your Error pages in Turbogears 2
Friday, August 7th, 2009 | Web | Comments
I was looking for a way to propagate exceptions from my tg2 app to the ErrorController to permit to propagate errors from controllers to the user. To generate errors and show them you usually have to redirect to /error/document and pass as parameters the error message and error code, but this isn’t really flexible and also modern languages have a really good feature to propagate errors: Exceptions.
So I was looking for a way to raise a webob.exc.HTTPForbidden, place a message inside it and let the ErrorController render the message. Usually you don’t want to tell to the user what went wrong with your 500 server side exception, but you might want to tell to the user why he can’t do what he is trying to do, let him know why it is Forbidden to him.
First thing you can easily do is check for resp.status_int inside your ErrorController.document and fetch only 403 error (the forbidden one). This permits to create a specific message for Forbidden errors, but doesn’t tell much to the user about why it is forbidden. webob.exc.HTTPForbidden permits to set a detail message and also generates an error page, but the turbogears stack when gets a status code different from 200 hooks the response and calls the ErrorController.document to generate a new response. This way your HTTPForbidden exception is lost forever.
Actually it isn’t really lost, as you can access the previous error page from request.environ.get(‘pylons.original_response’). If you want a quick solution you can hook ErrorController if status_int is 403 and return the original_response instead of rendering ErrorController.document template.
But the original response isn’t really nice and you usually want to adapt it.
My solution has been to create a new ApplicationError(webob.exc.Forbidden) class defined as the following one:
from webob.exc import HTTPForbidden
try:
from string import Template
except ImportError:
from webob.util.stringtemplate import Template
class HTTPMyAppError(HTTPForbidden):
body_template_obj = Template('''<div>${detail}</div>''')
def __init__(self, msg):
super(HTTPMyAppError, self).__init__(msg)
This by itself doesn’t change a lot as you will get the same ugly page with simply a div around your error. But now by using BeautifoulSoup you are able to get only your message from the original_response inside your ErrorController.document action.
if resp.status_int == 403: title = "Application Error" message = "We can't perform this, reason was:" details = str(BeautifulSoup(resp.body).find('div'))
Simply personalize your ErrorController.document template and display your details somewhere and you will be able to report errors to your users by simply doing something like raise HTTPMyAppError(’You have already used this registration code’)
I know that this isn’t a really great solution as you have to parse your already generated error page to fetch only the error message and generate a new error page, if anyone has a better solution that permits to directly access the exception instance feel free to tell me!
5 lines RSS reader
Tuesday, May 19th, 2009 | Software Development, Web | Comments
Recently while creating AXANT Labs we decided to put inside the page a little RSS aggregator which should mix news from our projects, at first we took a look at Planet, but it was a bit too big for our needing so we developed this short RSS feed reader using Universal Feed Parser. I’m sharing this as the sources are really compact and might be useful in other situations
import feedparser, operator, time
feeds = (”http://blog.axant.it/feed”, “http://www.lscube.org/rss.xml”)
feeds = map(lambda x : feedparser.parse(x).entries, feeds)
feeds = reduce(operator.concat, feeds)
feeds = sorted(feeds, lambda x,y : cmp(y.date_parsed, x.date_parsed))
for entry in feeds: print ‘%s (%s) -> %s’ % (entry.title, time.strftime(”%Y-%m-%d %H:%M”, entry.date_parsed), entry.description)
Using Elixir with TG2
Monday, May 4th, 2009 | Software Development, Web | Comments
I had to spend some time to permit to a project of ours to use Elixir inside TG2. Maybe someone with more experience than me might have a better answer, but I have been able to make Elixir work this way:
First of all I had to make Elixir use my TG2 metadata and session by adding to each model file that has a class inheriting from elixir.Entity this line:
from project_name.model import metadata as __metadata__, DBSession as __session__
Then I had to switch to model __init__.py and add elixir.setup_all() to init_model function just after DBSession.configure. This is really important as makes Elixir create all the SQLAlchemy tables and without this you won’t see anything happen for your elixir based models.
Also we can now import inside your model scope every elixir.Entity inherited class like we usually do for DeclarativeBase children.
Thoughts of the day
Tuesday, April 28th, 2009 | Software Development, Web | Comments
Actually this afternoon I was talking with my colleagues here at AXANT about the discussion pending over tail recursion elimination that is proceeding around Python, so they wanted me to post about that.
But, as I think that functional programming doesn’t really have to be embedded inside python if we don’t need it, I don’t really want to talk about that! (I’m not going to talk about that, so please, leave this post now, because I won’t say a word!) Usually I think about functional programming as a good tool to implement generic programming and also Tail recursion elimination can be an optimization inside compiled languages where a loop costs less than a function call as it is just an integer increment, and even so on modern architectures this might not be true, probably on Python it might even be worse.
In Python performing a function call requires: performing a function call (off course…), and iterating on something requires: incrementing an iterator (off course again?), which means performing a function call. So both would cost the same, but I think that probably function calls are best optimized than iterator incrementation inside CPython as the first is implemented in pure C while the second is mostly performed in python itself. Anyway the complexity of the algorithm from which you are eliminating tail recursion doesn’t change at all, so it isn’t a real optimization.
Fine, I ended talking about tail recursion elimination even if I didn’t want to!
Time for the real post!
This evening while surfing around the web I found an interesting consideration that makes me hope that for the future computer science might not be in the hands of business people as much as I think. In the recent years it seemed that for business people Ruby was becoming the new Java, every company thought that it could solve all its problems by just switching to it. All the interest around Ruby was confirmed by the fact that In the 2005 O’Reilly reported that Ruby books sales where up by around a 1500%, looking again at the same report now for 2008 it seems that Ruby hype is fading away (look at ObjC increment! Might that be cause of iPhone? Uhm, I think that Java will see something like that cause of Android launch).
This is making me think that maybe in the future we will be able to use Ruby for what it is and where it better behaves, instead of trying to make everything with it without being able to tell to our customers that “it isn’t a good idea” as it would receive as the only response that TechCrunch reported that “random name company” had increased its income by using Ruby. (I’m still trying to understand how it is possible that they usually don’t realize that “random name company” increased its income probably cause of what they did by using Ruby, not by the fact of using Ruby itself)
Maybe some day Italian companies will stop trying to take decisions about their IT infrastructure using stock market values and will start to realize that using Drupal, Plone or even Django might be a better solution than spending thousands of euros in implementing their own CMS from scratch using RoR just because they wanted to use RoR (At least please use Railfrog or something like that if you really want RoR!). Software development languages and frameworks should be the tool to achieve your target, not the target itself. I’m looking forward to the future or to the nearest sniper rifles shop.
Python 3.0
Saturday, December 6th, 2008 | Software Development | Comments
Python 3.0 changes have been defined “arbitrary and academic“, for no real use for real programmers. Before starting to talk about python changes, I would think about the meaning of “real programmers” in the sentence before.
How would we define a “real programmer”?
- Are hackers “real programmers”?
- Are professors of language theory “real programmers”?
- Are experts in algorithm theory “real programmers”?
- Are people who do coding for a living “real programmers”?
Probably people inside the first definition didn’t mind a lot about how Python 2.x did things and could live with it. They will just be angry because suddenly they tools and scripts will stop working. But those people can also go on with Python 2.x as they don’t tend to have complex software maintainment processes and would probably just be happy having a way to run it.
People inside the second and third definition will probably be happier as Python 3.0 clean up will satisfy their concept of elegance a bit more.
People inside the fourth definition will probably be angry thinking of how many hours they will have to spend porting their code to Python 3.0 as their code probably will have to live for the next 5 years as hundred of customers will have to use it.
This might be right, but I think that we have to go deeper inside the question to really understand the effect of those changes. I actually do code for a living, and inside the majority of our projects we try to refactor often to make long time maintaining of the code as easy as possible. As us, there will probably be hundreds of other companies who often perform refactoring, and all of us do it for one common goal: “Keeping the code as simple as possible to make it clear and obvious even after years”.
Usually this means things like:
- converting strange behaviours to standard one inside the application domain
- converting spread values to constants with a meaning
- removing code duplicates to have only one unit of work
- change function and classes to make their role as simple to understand as possible
- Separate mixed code blocks in methods/classes with a clear scope
- and things like that…
Uhm, wait for a second… isn’t this exactly what Python is doing for the 3.0 release?
- They changed the print keyword to a standard function conforming it to the behaviour of any other function inside the language.
- They removed some of the duplicated modules like urllib and urllib2
- They took care of modules that did the same things trying to localize everything in only one clear place
- They moved things inside more clear namespaces instead of having them all mixed in the global one
- They removed old modules superseded by new one that still where available.
- They renamed some things to make them conformed to python conventions.
In the end they actually forced us to perform refactoring of our own projects refactoring a piece of our projects: “the underlying library and language”. This is just the same thing that happens everyday with self written libraries that you reuse in multiple projects inside your company.
But if thousand of people are performing refactoring everyday on things from which their lives depend on, if Google is accepting Python 3.0 when most of their business uses Python (and they also hired Guido so they could probably influence Python 3.0 development a lot if they wanted) how can it be such a bad thing?
I’m starting to think that people blaming python for its changes are mostly angry because they have been forced to perform refactoring when they didn’t want to or just saw their software stop working. But actually you don’t have to change things, your software didn’t stop working and Python 2.x will be maintained for at least one year. You have the choice to do what you want.
As for me I’ll probably just thank the Python team for refactoring libraries and things that I use everyday without asking me to pay a thing. And I’ll just perform migration to 3.0 of my projects using 2to3 tool and something that I already perform everyday: code refactoring…
