Stroller goes open source

Stroller
Stroller

Stroller it is our way to do e-commerce! We have already some clients that we fit on this module written in python and easily importable to have a fully e-commerce section to work with.

Just after testing it in production for some customers and already in a stable shaped we decided to deliver it as a community edition in free software.

In fact you can now download it from pypi:

http://pypi.python.org/pypi/stroller

or just checkout the sources over our repositories:

hg clone http://repo.axant.it/hg/stroller

For now stroller does not have a site and a home ;( but fortunately all of our projects are listed in a fancy “temp house” on project.axantlabs.com as it has stroller, just checkout http://projects.axantlabs.com/Stroller

You’ll see there the main features of this art of software and enjoy the sweetness!

Updates are coming for it we have just in mind some strategic moves to make it a ‘first choice’ product.

libACR 0.6 and ACRcms 2.0 are out

As we are going deep with ACR our cms, it’s becoming a full featured product, we are using it more and more in production and we decided to release a new version on pypi.

New features include:

  • Plugins Support. You can now add your own sections to the administration panel, views to the add slice menu and implement new functions or views.
  • Multisite support, serve multiple sites from one single WSGIDaemonProcess
  • Themes Support, create your own themes for the ACRCMS
  • A simple Scripting language to automate some actions on theme setup
  • User Defined Views, create new type of contents without having to write a single line of code
  • SliceGroup Admin to permit to editors to change content of image galleries and news without have to need access to the admin panel
  • Support for Disqus comments
  • Export html slicegroups as RSS feeds
  • Various Plugins for Slideshows, Image Galleries, Accordions, etc.
  • New Script type and Script menu to make easier to add and manage javascript inside your pages
  • RDisk should now be faster and has content caching
  • Change My Password for current logged in user
  • Permit to store binary data inside contents as base64 and serve them through the /data call.
  • Integration with the Stroller eCommerce (stroller will be released opensource in the near future)

Here is the complete changelog since our latest release:

* work around to make it go with buggy sprox 0.6.10 (patched version still not released)
* Fix problem with Tg2.0 not casting headers to str
* Add delete udv and preview template for udvs
* Finalize user defined views with support for single selection fields, html and files
* Permit to serve fields encoded as per HTML5 base64 data source definition
* Add etag caching to rdisk based on file modified time
* Skeleton for user defined views
* Merge changes from master branch which improve multisite support
* Move every reference to stroller inside the stroller plugin itself
* Working delete action for slicegroup admin
* ACR might be mounted averywhere, never suppose its url, always use url() from libacr to generate acr urls
* Fix for TG2.0.3 (before tg2.1 remainder is a tuple and is not editable)
* SliceGroupAdmin plugin seems to work fine for adding things
* Make it work with Pylons1.0
* First import of sgadmin
* Stroller plugin preparatives
* Google Analytics change section
* Added new LinkedImage view same as the Image, just with a link utility. Must be evolve it, in the future to make him reuse the original view, without code duplication.
* Try to solve problems with repoze.who and repoze.what when running multiple acr sites inside the same daemon process and group
* Remove code render template from views as it collides with plugins
* Add setup script support to themes and fix default page url
* MCE options
* Fix icons and section for new plugins
* Fix for setup-app failing due to plugins
* gmap working (hopefully)
* gmap.js from static to plugin
* Merged single process mode, seems to be stable enough
* Moved GoogleMaps viewer to GoogleMaps plugin
* Disqus plugin
* Google Analytics from plugin static to site instance
* GoogleMaps key moved to database & added modify plugin
* Added tag classes for slices
* Add slice cloning
* Make rdisk_root dynamic to be able to run multiple instances in same process
* Permit to force lang from request
* Use genshi dict dotted access instead of a module
* permit to access and manipulate content from genshi slice
* add tabs plugin
* Added a class to the page as the uri of the page to make possible Custom css classes for page, hence different style for different pages
* Style fixes to administration menu
* fix crash when unable to contact pypi
* multiengine
* tests with multiengine
* engine from config
* first attemp at making a single process acr in the simplest way
* bind engine at each request
* cache session per db
* More experiments to make acr work on single process
* try to make acr work inside one single process
* Automated merge with ssh
* make section use id instead of class and declare in a less colliding way
* detect script slices also derived from default page
* Removed unused imports
* Fix done to correct the position of the excerpts under IE7
* Closes #43 it adds exception handling in case of failure of pypi version check, and just logs a warning to notify
* Minor edits
* Replaceing file templating, with python's Template string module
* Removed javascript putting css rules in place to allow 100% with of the edit menu; So added a relative container to the absolute positioned edit menu
* Minor edits
* Added new plugin to insert google analytics tracking to the site
* removed useless import
* Moved update check under helpers as it is more appropriate and, changed naming convention to follow standards
* Added new plugin to add uservoice feedback tab to pages
* add slice type class to slices, refactor properties management and add find_by_property helper
* Added help on accordion plugin, to help user interaction on creation
* Added same size of the edit button menus as the slice/slicegroup element
* Created new container for the heading admin section as pseudo-tabbed links + minor style edits on the css
* Added release update notification
* make script view wrap content with script tag and migrate existing plugins to use it
* add script slice type and menu
* Make rdisk upload view type dependant, fix videos and make deletion work on actual slice content instead of slice name
* Removed oops, console.log + Removed timestamp from end of slicegroup names to allow, reusability of the acrodion within a page, if you edit and recreate the sliceroup
* add description placement management for image slice
* Added Accordion Plugin, it will put a template for creation of Accordion galleries filters by tag on uploaded images
* fix problem with image thumbnails not showing if not logged in and add Slideshow plugin
* plugin injected resources
* add image, video and file slices to add slice menu if there is rdisk available
* themes plugin for acr
* initial work to make acr_cms working on multiple sites with only on installation, necessary to implement themes support
* improvements to edit bar

Python 3 Object Oriented Programming

Python 3 Object Oriented Programming had been reviewed already by a number of people in the python community and I’m lucky to have been given the occasion to read it as well.

As most of the other reviewers I say that the book is pleasant, it’s easy to follow and crystal clear. It gives a good overview of everything you have to expect from python.

The book is composed of 12 chapters

  • The first 5 introduce the reader to basic concepts related to object oriented programming like Objects and Classes, Exceptions and Inheritance:
    Object-oriented Design, Objects in Python, When Objects are Alike, Expecting the Unexpected, When to Use Object-oriented Programming
  • The next 2 delve into more python specific features and uses: Python Data Structures, Python Object-oriented Shortcuts
  • Two chapters on common design patterns and patterns commonly used in python follow: Python Design Patterns I, Python Design Patterns II
  • The remaining three provide some basic I/O introduction (Files and Strings) and a good intruduction to useful libraries and tools: Testing Object-oriented Programs and Common Python 3 Libraries

Each chapter share the same Introduction-Details-Case_Study-Exercise-Summary internal structure.

The book seems really good for teaching in university, it explains very clearly lots of basic concepts that usually are given as already known and introduces to concept like UML, design patterns and test driven development in a quite soft and easy way.
It is perfect for an initial object oriented programming course, if it comes along or one term before software engineering course.

  • The usage of UML is to the point and isn’t heavy at all, making it good for people that just learnt what UML is or that were going to learn it along in other courses.
  • The chapters about design patterns touch most of the commonly used patterns in python and explain why some patterns aren’t used at all. In an academic context those are quite good to show how the abstract concepts get used in the real code.
  • Since we are using a lot nose probably I’d prefer having it used while explaining unittest, still I the chapter is quite good to have somebody without previous knowledge start playing with tests.
  • The end of chapter summary and an exercise sections are quite useful for reviewing and do a bit of self check. Probably having also an appendix with the exercises solved would made the book even more student-suited.

All in all I consider this book quite well suited for Universities (both professors and students will enjoy it) and python newcomers. More skilled readers will still find it a good book to read about python3.

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.

Personalize your Error pages in Turbogears 2

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

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

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

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.