Our First Hackathon

Axant codes for food
Axant codes for food

We are coders, and we love to code. Our job is coding, and we have fun to.

Hence we decided to have fun, just by having a 24h non-stop coding experiment in our preferred and beloved Italian restaurant (well actually a taverna)!

We will have a mini-hackathon tomorrow at 3pm our time, to celebrate together the past 2011 working year, that was great! Free Food, free alcohol and a couple of cots is our necessaire for brainstorm and actuate our plan to take over the world!

Actually this “coding marathon” it has a subject, all the projects and ideas that will be developed should be related to “Food / Dining”!

The products result of the day, if useful, will be developed on field and used by a restaurant and a couple of bars, free of charge. Hence if there are good result could be a first step for a new free-software project.

In fact probably tomorrow we’ll not have just software projects cause the team is heterogeneous, built of lawyers, designers, creative people, musicians… and obviously coders!

The plan includes a couple of hours to study the problematics of a restaurant and in particular of our host. The owner will illustrate to us his business processes and we will try to understand were we could help them with our notions.

The next step is to actuate the thoughts into reality in the next 20hrs (: that’s it, nothing easier huh?

In the next post I’ll update the outcomes and the people behind it!

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

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
usage.
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.

GCC using C++

I got this news http://gcc.gnu.org/ml/gcc/2010-05/msg00705.html and it puzzled me a bit: you have the system C compiler depending on C++, making in fact it no more self hosting.

That alone makes me thing whoever decided and whoever requested that is next to suicidal. GCC is known for having _quite_ a shaky C++ standard library AND ABI, as in having at least an incompatibility every major version and sometimes even with minor ones.

I do dislike C++ usage mostly on this basis, let alone the fact is a language overly large, with not enough people dabbling it properly, let alone being proficient.

There are already compilers using C++, one that many people find interesting is llvm. It doesn’t aim to be a system compiler and it’s not exactly self hosting.

Many already stated that would switch to llvm clang front-end once it reaches full maturity (now freebsd proved that this level has been pretty well archived), I didn’t consider to fully switch to it just because it concerned me the fact it depends on C++ and how easy is to have subtle yet major breakages in that language implementations.

llvm people look to me way more capable of managing C++ than GCC ones and I saluted with please the fact they already have a libc++ implementation.

Back about being suicidal, if I have to pick between people that did well on C++ and people that botched many time on the same field, who would I pick?

The current discussions in the GCC mailing list are about C++ coding style, which features to pick and which to forbid, rearchitecture the whole beast to use a “proper” hierarchy and such, basically some/(many?) want to redo everything with the new toy. That makes me think again that llvm will be a better target for the next months/year.

I hope there are enough GCC developers and/or concerned party that will fork gcc now and keep a C branch. Probably having a radical cleanup and refactor is a completely orthogonal issue and should be done no matter they’ll pick C++ or C as their implementation language, GCC has lots of cruft, starting from their bad usage of the autotools.

VideoLAN Web Plugin: xpi vs crx

One of the main issue while preparing streaming solution is answering the obnoxious question:

  • Question: Is possible to use the service through a browser?
  • Answer: No, rtsp isn’t* http, a browser isn’t a tool for accessing any network content.
  • * Actually would be neat having rtsp support within the video tag but that’s yet another large can of worms

Once you say that you have half of your audience leaving. Non technical people is too much used to consider the browser the one and only key to internet. The remaining ones will ask something along those lines:

  • Question: My target user is a complete idiottechnically impairednaive and unaccustomed and could not be confronted with the hassle of a complex installation procedure, is there something that fits the bill?
  • Answer: VideoLAN Web Plugin

Usually that makes some people happy since it’s something they actually know or at least they have heard about. Some might start complaining since they experienced an old version and well it crashed a lot. What would you be beware of is the following one:

  • Question: Actually I need to install the VideoLAN Web Plugin and it requires attention, isn’t there a quicker route?
  • Answer: Yes xpi an crx for Firefox an Chrome

Ok, that answer is more or less from the future and it’s the main subject of this post: Seamless bundling something as big and complex as vlc and make our non tecnical and naive target user happy.

I picked the VideoLAN web plugin since it is actually quite good already, has a nice javascript interface to let you do _lots_ of nice stuff and there are people actually working on it. Additional points since it is available on windows and MacOSX. Some time ago I investigated how to use the extension facility of firefox to have the fabled “one click” install. The current way is quite straightforward and has already landed in the vlc git tree for the curious and lazy:


  
    vlc-plugin@videolan.org
    VideoLAN
    1.2.0-git
    
      
        {ec8030f7-c20a-464f-9b0e-13a3a9e97384}
        1.5
        3.6.*
      
    
  

Putting that as install.rdf in a zip containing a directory called plugins with libvlc, it’s modules and obviously the npapi plugin does the trick quite well.

Chrome now has something similar and it seems also easier so that’s what I put in the manifest.json:

{
"name": "VideoLAN",
"version": "1.2.0.99",
"description": "VideoLan Web Plugin Bundle",
"plugins": [{"path":"plugins/npvlc.dll", "public":true }]
}

Looks simpler and neater, isn’t it? Now we get to the problematic part about chrome extension packaging:

It is mostly a zip BUT you have to prepend to it a small header with more or less just the signature.

You can do that either by using chrome built-in facility or by a small ruby script. Reimplementing the same logic in Makefile using openssl is an option, for now I’ll stick with crxmake.

Then first test build for win32 are available as xpi and crx hosted on lscube.org as usual.

Sadly the crx file layout and the not so tolerant firefox xpi unpacker make impossible having a single zip containing both the manifest.xpi and the install.rdf served as xpi and crx.

by the way, wordpress really sucks

Remember me in Turbogears2

One of the problems with TG2 is that the current version doesn’t support a “standard” way to remember the user after he closes the browser. We have been able to find a quick and dirty solution that we like to share here. Keep in mind that this solution only works with recent versions of repoze.who, this works with TG2.0.3, but might not work with previous releases of TG2.

Inside the login.html we set a cookie for the remember_me option to pass it to the controller and then inside the post_login we change the cookie.

Supposing you have a #remember_me checkbox inside your login.html you can add this to set the cookie:

    function set_remember_cookie() {
        is_checked = jQuery('#remember_me:checked').length;
        if (is_checked)
            document.cookie = 'remember_me=1';
        else
            document.cookie = 'remember_me=0';
    }

    jQuery(document).ready(function() {
        set_remember_cookie();
        jQuery('#remember_me').click(set_remember_cookie);
    }

Then inside your post_login method in the root controller you can place:

        remember_me = request.cookies.get('remember_me', 0)
        try:
            remember_me = int(remember_me)
        except:
            remember_me = 0

        if remember_me:
            request.identity['max_age'] = 2252000 # 30 days
            request.identity['userdata']= "max_age" # force cookie refresh

This would remember the user for 30 days even if he closes the browser.

Turbogears authentication over mongodb users database

As we saw that there isn’t a lot of documentation around about how to perform authentication in turbogears over mongodb we decided to create a simple code snippet and public it here to help people trying to obtain the same thing.

This is mainly a proof of concept and is quick and dirty way to obtain it. You will probably have something like ming as your model, instead of directly accessing mongo.

This code also validates password over the clear text one, you will probably have hashed passwords in your database, so remember to change validate_password method as required

To make it work you will have to place this code inside your config.app_cfg, it also expects you to have you database exposed as db inside your model

from my_app.model import db
from zope.interface import implements
from repoze.who.interfaces import IAuthenticator, IMetadataProvider
from repoze.who.plugins.friendlyform import FriendlyFormPlugin
from repoze.who.plugins.auth_tkt import AuthTktCookiePlugin
from repoze.who.middleware import PluggableAuthenticationMiddleware

def validate_password(user, password):
   return user['password'] == password

class MongoAuthenticatorPlugin(object):
    implements(IAuthenticator)

    # IAuthenticator
    def authenticate(self, environ, identity):
        if not ('login' in identity and 'password' in identity):
            return None

        login = identity.get('login')
        user = db.users.find_one({'user_name':login})
        if user and validate_password(user, identity.get('password')):
            return identity['login']

class MongoUserMDPlugin(object):
    implements(IMetadataProvider)

    def add_metadata(self, environ, identity):
        user_data = {'user_name':identity['repoze.who.userid']}
        identity['user'] = db.users.find_one(user_data)

class MyAppConfig(AppConfig):
    auth_backend = 'sqlalchemy' #this is a fake, but it's needed to enable
                                #auth middleware at least on TG2.0

    login_url = '/login'
    login_handler = '/login_handler'
    post_login_url = None
    logout_handler = '/logout_handler'
    post_logout_url = None
    login_counter_name = None

    def add_auth_middleware(self, app, skip_authentication):
        cookie_secret = pylons_config.get('auth_cookie_secret', 
                                          'myapp_adsfsdfh3423')
        cookie_name = pylons_config.get('auth_cookie_name', 
                                        'myapp_auth')

        who_args = {}

        form_plugin = FriendlyFormPlugin(self.login_url,
                              self.login_handler,
                              self.post_login_url,
                              self.logout_handler,
                              self.post_logout_url,
                              login_counter_name=self.login_counter_name,
                              rememberer_name='cookie')
        challengers = [('form', form_plugin)]

        auth = MongoAuthenticatorPlugin()
        authenticators = [('mongoauth', auth)]

        cookie = AuthTktCookiePlugin(cookie_secret, cookie_name)

        identifiers = [('cookie', cookie), ('form', form_plugin)]

        provider = MongoUserMDPlugin()
        mdproviders = [('mongoprovider', provider)]

        from repoze.who.classifiers import default_request_classifier
        from repoze.who.classifiers import default_challenge_decider
        log_stream = None

        app = PluggableAuthenticationMiddleware(app,
                                          identifiers,
                                          authenticators,
                                          challengers,
                                          mdproviders,
                                          default_request_classifier,
                                          default_challenge_decider)

        return app

base_config = MyAppConfig()
base_config.renderers = []

base_config.package = my_app

#Set the default renderer
base_config.default_renderer = 'genshi'
base_config.renderers.append('genshi')
base_config.renderers.append('json')

#Configure the base SQLALchemy Setup
base_config.use_sqlalchemy = False
base_config.model = my_app.model