ACR goes for “Packt Open Source CMS Awards”!

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

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.

Lowering Tg2 memory usage by running multiple instances of an app inside same WSGI daemon process

I was recently trying to deploy one app multiple times inside the same
WSGIProcessGroup and WSGIApplicationGroup %{GLOBAL} to reduce memory
This works quite well except for all the SQLAlchemy sessions which end being
attached to the engine of the last wsgi script started.

The best solution that I have been able to get so far is to create a proxy interface to the application engine. This way each wsgi script gets binded to the same engine, but the engine itself keeps track of all the available real engines and responds to the script requests sending them to the right real engine.

class MultiSiteEngine(object):
   def __init__(self):
       self.engines = {}

   def __getattr__(self, name):
       if name == 'engines':
           return object.__getattribute__(self, name)

       if not self.engines.has_key(config['sqlalchemy.url']):
           self.engines[config['sqlalchemy.url']] = engine_from_config(config, 'sqlalchemy.')

       return getattr(self.engines[config['sqlalchemy.url']], name)

To make this work just allocate a multi_engine = MultiSiteEngine() inside your tg2 app model __init__ and change init_model method to pass multi_engine instead of the engine itself.