be Groovie

Viewing posts for Code

Aug 13 2009

Advanced Caching with Django and Beaker

After seeing more than a few blog posts and packages attempt to provide more advanced caching capability for Django, it occurs to me I should actually just blog how to use Beaker in Django, rather than just keep mumbling about how “Beaker already does that”. So, if you’ve needed caching in Django that goes beyond using just one backend at a time, or maybe can actually cope with the Dog-Pile Effect, this is the blog entry for you (Until I flesh it out further into actual docs on the Beaker site).

Install Beaker

This is simple enough, if you have easy_install available, just:


 easy_install -U Beaker

Or if you prefer to download tar files, grab the Beaker 1.4 tar.gz file

Configuring the Cache

Setting up Beaker’s cache for your Django app is pretty easy. Since only a single cache instance is needed for an app, we’ll set it up as a module global.

Create a beakercache.py file in your Django project with the following contents:


 from beaker.cache import CacheManager
 from beaker.util import parse_cache_config_options

 cache_opts = {
     'cache.type’: 'file’,
     'cache.data_dir’: 'cache/data’,
     'cache.lock_dir’: 'cache/lock’
 }

 cache = CacheManager(**parse_cache_config_options(cache_opts))

There’s a lot more options available, such as memcached, configuring multiple cache backends at once, etc. Now that you know how to provide the configuration options, further customization can be done as needed using the Beaker configuration docs. (Note the very handy cache region configurations which make it easy to toggle cache backend configurations on the fly!)

Using the Cache

Beaker provides a conveinent decorator API to make it easy to cache the results of functions. In this example we’ll just sleep and make a string including the time, add this to your views.py:


 import time
 from datetime import datetime

 from django.http import HttpResponse

 from YOURPROJECT.beakercache import cache

 def hello(request):
     @cache.cache(expire=10)
     def fetch_data():
         time.sleep(4)
         return 'Hello world, its %s’ % datetime.now()
     results = fetch_data()
     return HttpResponse(results)

In this case, the cached data is in a nested function with the decorator. It could of course be in the module elsewhere as well.

Hook the view function up in your urls.py, and hit the view. The first time it will wait a few seconds, then it will return the old time until the cache expires (10 seconds in this case).

The cached function can also accept positional (non-keyword) arguments, which will be used to key the cache. That is, different argument values will result in different copies of the cache that require those arguments to match.

That’s it, it’s really quite easy to use.

Update: It occurs to me this post does say ‘advanced’, and that example wasn’t very advanced, so here’s something a bit more interesting. Let’s configure cache regions to make it easy to toggle how long and where something is cached. Cache regions allow you to arbitrarily configure batches of settings, a ‘region’. Later you can then indicate you want to use that region, and it uses the settings you configured. This also make its easy to setup cache policies and change them in a single location.

In this case, we’ll have ‘long_term’ and ‘short_term’ cache settings, though you can of course come up with as many regions as desired, with the name of your choice. We’ll have the long_term settings use the filesystem, since we want to retain the results for quite awhile and not have them pushed out like memcached does. The short_term settings will use memcached, and be cached for only 2 minutes, long enough to help out on those random slashdog/digg hits.

In the beakercache.py file:


 from beaker.cache import CacheManager
 from beaker.util import parse_cache_config_options

 cache_opts = {
     'cache.type’: 'file’,
     'cache.data_dir’: 'cache/data’,
     'cache.lock_dir’: 'cache/lock’,
     'cache.regions’: 'short_term, long_term’,
     'cache.short_term.type’: 'ext:memcached’,
     'cache.short_term.url’: ’127.0.0.1.11211’,
     'cache.short_term.expire’: '1200’,
     'cache.long_term.type’: 'file’,
     'cache.long_term.expire’: '86400’,
 }

 cache = CacheManager(**parse_cache_config_options(cache_opts))

Now in our views.py:


 import time
 from datetime import datetime

 from django.http import HttpResponse

 from testdjango.beakercache import cache

 def hello(request):
     @cache.region('long_term’)
     def fetch_data():
         time.sleep(15)
         return 'Hello world, its %s’ % datetime.now()
     results = fetch_data()
     return HttpResponse(results)

 def goodbye(request):
     @cache.region('short_term’')
     def fetch_data():
         time.sleep(4)
         return 'Bye world, its %s’ % datetime.now()
     results = fetch_data()
     return HttpResponse(results)     
Tags: Code Python
Comments
Jun 28 2009

Comments and Web Services

I’m trying out Disqus for comments on the blog, for one main reason, I just didn’t feel like implementing comments myself. I am somewhat wary of services that seem integral to a blog, like where the comments are, which is why I’ve been leery of using services like this for some time.

What happens if Disqus runs out of VC and goes belly-up? I’ve seen this with a few other web services, and no one using it is very happy when it occurs. On the other hand, I did find some irony in the fact that one of the features Disqus pitches users is, “Don’t lose your comments if the blog disappears”.

On the other hand, I really appreciate the capabilities a central service-based comment system brings. I’ve inadvertently used it on other blogs, and was very pleasantly surprised to get updates and actually be able to keep up on what was happening on the blogs I commented on.

Are other people worried about using services by new companies or am I just overly paranoid?

I’d almost feel better about it if I could pay five bucks a year or something, as I’d at least have some better reassurance that the company is actually making money like I do with Flickr. Or maybe it’d be nice if companies that are profitable to say so, though it occurs to me that even that isn’t a guarantee, as someone could come along and buy them up, then decide to terminate their functionality (like that one site that people used and were pissed about when Six Apart bought them and shut it down, but for some reason I can’t remember the name of it at all).

Comments
Jun 17 2009

Blog upgraded! Now running on Pylons + MongoDB

I’ve now updated the blog software powering my blog, which is very long overdue. In the past, this blog was run off Typo, which apparently now hosts their home site off the github (its moved a dozen times in the past 3+ years).

Typo always worked moderately well for me, however, I found it sluggish (Prolly Rails there), and incredibly horrid on ram usage. It was not at all unusual to see it running past 700 megs of RAM after running for just a few weeks, which is a bit annoying as the machine only has 4GB total and is running quite a few things.

After last weeks SF Python Meetup on MongoDB I figured it was time to get a little actual MongoDB usage under my belt. I also inadvertently implemented enough of the MovableType XMLRPC API as I didn’t want my app to be too extensive, just enough for me to post to my blog.

So in the end, I had a small set of requirements for the replacement:

  1. Not be horribly slow
  2. Not take up huge amounts of RAM
  3. Retain all existing URL’s (It really annoys me when people break their old links)
  4. Compatible with my blog software (MovableType / MetaWeblog XMLRPC API)
  5. Not screw up the RSS/Atom feeds and cause Planet Python to show all my posts as if they were new (I’ve seen this happen to a few people on occasion)

I wanted to build it myself, because of course, the world definitely needs more blog apps, and I wanted one that used MongoDB. So for those curious, here’s the source code to the blog app.

It’s rather rough, as its fairly custom built just for my needs, nor do I have any plans to expand it into some general purpose blog engine, with themes, etc. The only other thing pending at the moment is to add the ability to comment again, as I haven’t quite gotten that feature in yet. For those trying it out, the README should help get started, but its very rough (thus the name of the package).

Strings, Unidecode, and Slugs

When copying some functionality I needed from the Rails app (to retain URL compatibility), I noticed two things it did which I thought was handy. To convert a title into slug for the article, it used a fairly sophisticated scheme relying on two other packages.

First, was the use of a Ruby port of a Perl package called Text::Unidecode which is pretty cool, and converts UTF-8 chars into their closest ASCII version. I figured someone must’ve ported it to Python as well, and sure enough, someone did! It wasn’t on the cheeseshop though, which was unbearable for me, so I’ve posted it to the Cheeseshop so others can easy_install it.

Next up, was a Ruby library called stringex, which add’s a few things to Rails, including a string method called ‘to_url’. That method does a variety of transformations to remove all those funny characters from a title, and do a bunch of other neat changes of common characters to human readable versions (source for those conversions).

I ported the key module of stringex to Python, and it resides in my blog app. If someone would like to extract it and make it into its own package, or even better, if I somehow missed the fact that someone else has ported it already, let me know (tweet me @benbangert!).

I’ll be writing up my thoughts on making a small app with MongoDB, and how it differs from my experience working with CouchDB for PylonsHQ in a later post for those curious.

Comments
May 30 2009

Making a better TextArea

I’ve been working on some Javascript to enhance the TextArea elements on the PylonsHQ Snippets section, and have noticed that… well, TextArea’s suck.

The hack I’ve seen is to use one of the newer features of browsers, the editable or ‘design’ attribute’s for div elements I believe. This lets one build a very snazzy amount of features, such as syntax highlighting, code completion, etc., but I don’t think I needed to go that far.

I only have one main design goal, this TextArea is for the user to enter RestructuredText so it’d be awesome if the TextArea acted in a way that made rst a bit nicer. The obvious two things that came to mind:

  1. Tab key indents 4-spaces
  2. Hitting return on an indented line, will retain the indentation on the next line

I’ve actually gotten some Javascript, hobbled together from various parts of the net, along with an ‘enter’ key handler I wrote myself on bitbucket.

Course, it’d also be nice to have a button or key combo, that will indent/unindent a selection in the TextArea as well.

Anyone else have any Javascript they’ve hobbled together in the past to make TextArea a little nicer for restructured text?

Comments
Apr 22 2009

Beaker 1.3 is juicy caching goodness

Beaker 1.3 is out, actually, its been out for awhile and I’m just not getting around to blogging the fact. It’s a shame I’ve been a bit too busy lately to blog this earlier because in addition to some bug fixes it has some nice new features that make it even easier to use in any Python script/application/framework.

First, to air my dirty laundry, the important bug fixes in Beaker 1.3:

  • Fixed bug with (non-cookie-only) sessions not being timed out
  • Fixed bug with cookie-only sessions sending cookies when they weren’t supposed to
  • Fixed bug with non-auto sessions not properly storing their last accessed time

The worst thing with the first two of these is that they were regressions that snuck in despite unit tests that exercised the code fairly decently. They’re fixed now along with more comprehensive tests to help prevent such regressions occurring again.

Beaker has always had session’s, and caching, but except for Pylons I’ve yet to see anyone actually use Beaker’s caching utility. I’ve seen the SessionMiddleware used in other WSGI based frameworks, but not the caching, which is kind of a shame since it:

  • Supports various backends: database, file-based, dbm file-based, memcached
  • Has locking code to ensure a single-writer, multiple reader model (This avoids the dreaded dog-pile effect that caching systems such as the one in Django experience!)

For clients that hit the cached function while its already being regenerated, Beaker serves the old copy until the new content is ready. This avoids the dog-pile effect, and keeps the site snappy for as many users as possible. Since the lock used is disk-based though, this does mean you only avoid the effect per machine (unless you’re locking against NFS or a SAN), so if you have 20 machines in a cluster, the worst the dog-pile effect can get is that you’ll have 20 new copies generated and stored.

Now, in Beaker 1.3, to try and encourage its use a bit more, I’ve added a few decorators to make it easier to cache function results. Also with Mike Bayer’s suggestion, there is now cache regions to make it easier to define various caching policy short-cuts.

Cache Regions

Cache regions are just pre-defined sets of cache instructions to make it easier to use with your code. For example many people have a few common types of cache parameters they want to use:

  • Long-term, likely to a database back-end (if used in a cluster)
  • Short-term, not cached as long, perhaps to memcached

To set these up, just tell Beaker that about the regions you’re going to define, and give them the normal Beaker cache parameters for each region. For example, in this Pylons app, I define 2 cache regions in the INI:


 beaker.cache.regions = short_term, long_term
 beaker.cache.short_term.type = ext:memcached
 beaker.cache.short_term.url = 127.0.0.1:11211
 beaker.cache.short_term.expire = 3600

 beaker.cache.long_term.type = file
 beaker.cache.long_term.expire = 86400

Note: For those wondering about multiple memcached servers, just put them in as the url with a semi-colon separating them.

If you want to use the caching outside of Pylons without middleware (ie, as a plain library), that’s a bit easier now as well:


 from beaker.cache import CacheManager
 from beaker.util import parse_cache_config_options

 cache_opts = {'cache.data_dir’: './cache’,
               'cache.type’: 'file’,
               'cache.regions’: 'short_term’, 'long_term’,
               'cache.short_term.type’: 'ext:memcached’,
               'cache.short_term.url’: ’127.0.0.1:11211’,
               'cache.short_term.expire’: '3600’,
               'cache.long_term.type’: 'file’,
               'cache.long_term.expire’: '86400’,
 }

 cache = CachManager(**parse_cache_config_options(cache_opts))

And your cache instance is now ready to use. Note that using this cache object is thread-safe already, so you just need to keep one around in your framework/app (Can someone using Django explain where you’d keep a reference to this object around so that you could get to it in a Django view?).

New Cache Decorators

To make it easier to use caching in your app, Beaker now includes decorators for use with the cache object. Given the above caching setup, lets assume you want to cache the output of an expensive operation:


 # Get that cache object from wherever you put it, maybe its in environ or request?
 # In Pylons, this will be: from pylons import cache
 from wherever import cache

 def regular_function():
     # Do some boring stuff

     # Cache something
     @cache.region('short_term’, 'mysearch’)
     def expensive_search(phrase):
         # Do lookup with the phrase variable
         return something
     return expensive_search('frogs’)

The second argument to the region decorator, ‘mysearch’. That isn’t required unless you have two function’s of the same name in the same module, since Beaker records the namespace of the cache using the function name + module + extra args. For those wondering what a Beaker namespace is, its a single cache ‘block’. That is, lets say you wanted to cache 4 versions of the same thing, but change them differently depending on the input parameter. Beaker considers the thing to be a namespace, and the things that change the thing being cached are the cache keys.

Only un-named arguments are allowed on the function being cached. These act as the cache keys so that if the arguments change, a new copy is cached to those arguments. This way you can have multiple versions of the function output cached depending on the argument it was called with.

If you want to use arbitrary cache parameters, use the other decorator:


 # Get that cache object from wherever you put it, maybe its in environ or request?
 # In Pylons, this will be: from pylons import cache
 from wherever import cache

 def regular_function():
     # Do some boring stuff

     # Cache something
     @cache.cache('mysearch’, type='file’, expire=3600)
     def expensive_search(phrase):
         # Do lookup with the phrase variable
         return something
     return expensive_search('frogs’)

This allows you to toggle the cache options per use as desired.

If there’s anything else I can do to make it easier to use Beaker in your application, be sure to let me know (Yes, I know more docs would help, this blog post was a first attempt to help out on that front, more docs on the way!).

Tags: Code Python
Comments
Feb 23 2009

Pylons 0.9.7 Released

I’m pleased to announce after a rather lengthy release candidate period, that Pylons 0.9.7 is finally out. Pylons 0.9.7 brings a good amount of changes to Pylons from 0.9.6 while still retaining a fairly hefty amount of backwards compatibility to ensure a mostly painless upgrade.

Some helpful documentation on the new release:

Major changes in 0.9.7:

  • Switched to using WebOb for the request/response object
  • Various performance improvements to object initialization
  • Beaker and Routes updates
  • Middleware improvements, and optimizations

This is a huge step forward for Pylons, and I’d like to thank all of the contributers who have helped make Pylons what it is today. We’ve knocked off more bugs for this release than any before, which shows just how far the Pylons community has come:

  • 0.9.5 tickets: 45
  • 0.9.6 tickets: 64
  • 0.9.7 tickets: 160

And we have finally made a huge dent in the historical “lack of docs” problem that Pylons previously suffered from with the new Sphinx generated docs and a comprehensive Pylons book.

The full changelog which describes the major changes (Look for the bits marked with WARNING that might affect backwards compatibility).

0.9.7 (February 23, 2009)

  • WARNING: A new option is available to determine whether or not an actions
arguments should be automatically attached to ‘c’. To turn off this implicit behavior in environment.py: config[‘pylons.c_attach_args’] = False This is set to True by default.
  • WARNING: Fixed a minor security hole in the default Pylons error page that
could result in an XSS security hole.
  • WARNING: Fixed a security hole in the default project template to use the
StaticURLParser to ensure arbitrary files can’t be sent.
  • WARNING: Refactored PylonsApp to remove legacy PylonsApp, moved
session/cache and routes middleware into the project template. This will require projects to be updated to include those 3 middleware in the projects middleware.py.
  • Changed to using WebTest instead of paste.fixture for app testing.
  • Added render_mako_def to render def blocks within a mako template.
  • Changes to cache_decorator and cached_template to support Beaker API
changes in version 1.1. 1.0.3 is still supported.
  • Fix HEAD requests causing an Exception as if no content was returned
by the controller. Fixes #507. Thanks mvtellingen, Petr Kobalicek.
  • Fix a crash when returning the result of “etag_cache“ in a controller.
Fixes #508.
  • “response” flag has been removed from pylons.decorators.cache.beaker_cache,
as it sends all headers along unconditionally including cookies; additionally, the flag was taking effect in all cases previously so prior versions of beaker_cache are not secure. In its place, a new option “cache_headers” is provided, which is a tuple of specific header names to be cached. It defaults to (‘content-type’,’content-length’).
  • “invalidate_on_startup” flag added to beaker_cache, which provides a
“starttime” to the cache such that when the application is started or restarted, the cache entry is invalidated.
  • Updating host to use 127.0.0.1 for development binding.
  • Added option to specify the controller name with a controller variable
in the controller’s module. This name will be used for the controller class rather than the default naming scheme.
  • setup.py egg_info now restores projects’ paster_plugins.txt,
allowing paster shell to work again after the egg-info directory was lost. fixes #282. Thanks sevkin.
  • The paste_deploy_config.ini_tmpl template is now located at
package/config/deployment.ini_tmpl for new projects.
  • Project’s default test fixtures no longer hardcode test.ini; the ini
file used can now be specified via the nosetests —with-pylons argument (defaults to test.ini in setup.cfg). fixes #400.
  • validate now defaults to translating FormEncode error messages via Pylons' gettext catalog, then falls back to FormEncode's. fixes #296. Thanks Max Ischenko. * Fixed SQLAlchemy logging not working in paster shell. Fixes #363. Thanks Christoph Haas. * Added optionally engine initialization, to prevent Buffet from loading if there's no 'buffet.template_engines' in the config. * Updated minimal template to work with Tempita and other new templating changes. * Fixed websetup to parse location config file properly when the section isn't 'main'. Fixes #399. * Added default Mako filter of escape for all template rendering. * Fixed template for Session.remove inclusion when using SA. Fixed render_genshi to properly use fragment/format options. Thanks Antonin Enfrun. * Remove template engine from load_environment call. * Removing template controller from projects. Fixes #383. * Added signed_cookie method to WebOb Request/Response sub-classes. * Updated project template to setup appropriate template loader and controller template to doc how to import render. * Added documentation for render functions in pylons.templating. * Adding specific render functions that don't require Buffet. * Added forward controller.util function for forwarding the request to WSGI apps. Fixes #355. * Added default input encoding for Mako to utf-8. Suggested in #348. * Fixed paster controller to raise an error if the controller for it already exists. Fixes #279. * Added __init__.py to template dir in project template if the template engine is genshi or kid. Fixes #353. * Fixed jsonify to use application/json as its the proper mime-type and now used all over the net. * Fixed minimal template not replacing variables properly. Fixes #377. * Fixed validate decorator to no longer catch exceptions should they be
raised in the action that is supposed to display a form. Fixes #374.
  • Fixed paster shell command to no longer search for egg_info dir. Allows
usage of paster shell with installed packages. Suggested by Gavin Carothers.
  • Added mimetype function and MIMETypes class for registering mimetypes.
  • WARNING: Usage of pylons.Response is now deprecated. Please use
pylons.response instead.
  • Removed use of WSGIRequest/WSGIResponse and replaced with WebOb subclasses
that implement methods to make it backwards compatible with the Paste wsgiwrappers.
  • Fixed missing import in template controller.
  • Deprecated function uses string substitution to avoid Nonetype error when
Python optimization is on. Fixes #334.
  • E-tag cache no longer returns Content-Type in the headers. Fixes #323.
  • XMLRPCController now properly includes the Content-Length of the response.
Fixes #310, thanks Nicholas.
  • Added SQLAlchemy option to template, which adds SQLAlchemy setup to the
project template.
  • Switched project templating to use Tempita.
  • Updated abort/redirect_to to use appropriate Response object when WebOb is
used.
  • Updated so that 404’s properly return as Response objects when WebOb is in
use instead of WSGIResponse.
  • Added beaker_cache option to avoid caching/restoring global Response values
that were present during the first cache operation.
  • Adding StatusCodeRedirect to handle internal redirects based on the status
code returned by the app. This replaces the use of ErrorDocuments in projects.
  • Refactored error exceptions to use WebError.
  • WSGIController now uses the environ references to response, request, and
the c object for higher performance.
  • Added optional use of WebOb instead of paste.wsgiwrapper objects.
  • Fixed bug with beaker_cache defaulting to dbm rather than the beaker
cache app-wide default.
  • The —with-pylons nose plugin no longer requires a project to have been
registered with setuptools to work.
  • The config object is now included in the template namespace.
  • StaticJavascripts now accepts keyword arguments for StaticURLParser.
Suggested by Marcin Kasperski.
  • Fix pylons.database.AutoConnectHub’s doInTransaction not automatically
connecting when necessary. Fixes #327.
Comments
Oct 02 2008

Python 2.6 release and Pylons buildbots

Python 2.6 came out yesterday, so I figured I might as well see if Pylons works on it. Pylons already has a set of buildbots that builds Pylons along with some of its dependencies, so it was fairly trivial to add another builder to verify things ran swimmingly on Python 2.6.

Unfortunately, as one can see looking at the build results, things weren’t so great. It appears that nose had a Python 2.6 incompatibility which is used to run all the various Pylons tests, meaning that they all failed so far mainly because the testing tool was Python 2.6 incompatible.

Making Buildbot nicer

While I wait for the new nose to be released, I did at least discover a little bug in my new webapp that provides a nicer view of the buildbot result set. I’ve been fairly displeased with the lack of conciseness of buildbot’s waterfall display for awhile, and noticed that if only buildbot had a few more xmlrpc methods then it’d be trivial to build my own more kind interface.

I should note that the waterfall display isn’t totally horrible, the Django folks spiced their builders up with some CSS work…. which reminds me, it isn’t looking very good for those running on trunk at the moment. ;)

So after making my own little buildbot fork to add some additional custom xmlrpc methods to, I’ve come up with my own buildbot status viewer. I’m sure a more talented designer could spice it up even more, but it gives me the pertinent data I’m interested in without all the boring “builder connected, builder took a vacation” messages that cloud up the waterfall. Also, rather than displaying the cryptic “shell_21 failed” messages, it actually uses the names I attached, and shows them quite clearly for the last build.

I’ll submit some patches for these xmlrpc additions to buildbot when I get the time, but right now I mainly needed the Mercurial 1.0 hook compatibility (that was broken for quite awhile in buildbot), and a fairly specific set of information from the xmlrpc methods that I wasn’t sure others would want.

I’m looking forward to trying out the new nose so that I can hopefully verify Pylons is good to go on Python 2.6 as Phil Jenvey’s been working tirelessly on patches to Beaker and other dependencies to make them 2.6 compatible. Any suggestions or thoughts on improving my buildbot viewer are welcome. :)

Comments
Jun 13 2008

Routes 1.9 Release

I released Routes 1.9 today, which is another step on the Road to Routes 2.0. Some of the highlights that people will be most interested that I had previously blogged about now available:

Minmization is optional

Pylons 0.9.7 will default to turning minimization off (projects are free to leave it on if desired). This means that constructing a route like this with minimization off:

map.connect('/:controller/:action/')
will actually require both the controller and the action to be present, and the trailing slash. This addresses the trailing slash issue I wanted to fix as well.

Named Routes will always use the route named

This is now on by default in Routes 1.9, which results in faster url_for calls as well as the predictability that comes with knowing exactly which route will be used.

Optional non-Rails’ish syntax

You can now specify route paths in the same syntax that Routes 2 will be using:

map.connect('/{controller}/{action}/{id}')
Or if you wanted to include the requirement that the id should be 2 digits:
map.connect('/{controller}/{action}/{id:\d\d}')
Routes automatically builds the appropriate regular expression for you, keeping your routes a lot
easier to skim over than a bunch of regular expressions.

Routes 2 will be bringing redirect routes, and generation-only routes, making Routes 1.9 a great way to transition to Routes 2 when its ready.

Comments
Dec 17 2007

Beaker 0.9, cookie-stored sessions, and crypto

In the latest 0.9 release of Beaker, I’ve finally added cookie-side session storage. I was a little bit moved to finally do this by seeing that Rails 2.0 had added cookie-side session storage, and heck if I was going to miss out!

A few changes from how Rails 2 did it though, I was definitely not content to store all the data in an end-user visible form in the cookie. That only left encryption as the next logical choice, and that quickly led me down a path of quite a bit of cryptography research.

The world of cryptography is a constantly evolving and rapidly progressing field. New papers are coming out all the time with new research on ways to break, or ‘wound’ a particular encryption scheme. Providing a weak form of encryption in Beaker would be worse then not having it at all, since it’d lead someone to falsely believe the session data was secure.

After initially going with an RC4 cipher implementation, I got ahold of some crypto people that are actually in the field, and the unanimous opinion was to use AES encryption in Counter Mode, also referred to as AES-CTR along with a signature to prevent tampering (you’d be amazed what you can do to encrypted data, and it’d still technically decrypt). This led to a slight increase in requirements unfortunately, as pure Python based AES encryption is a bit slow. This means that using cookie-based sessions in Beaker requires the installation of PyCrypto, which includes a C extension (making cookie-based sessions faster than file-based, memcached, and db-based sessions).

The final solution in Beaker uses 256-bit AES-CTR with a 256-bit HMAC for authentication purposes. It’s fast, secure, and scales across a cluster without a problem. It’s not for everyone of course, cookies are rather severely limited in size, so if you’re just storing a few small tidbits of information in a session, for example:

  • a user id
  • some flags about the users status (logged in, etc)
  • a flash message

Then cookie-stored sessions might be perfect for you.

Update: Forgot to mention, in the future, Beaker will probably use pycryptopp instead of PyCrypto since the PyCrypto library’s AES-CTR implementation isn’t as efficient as it could be, and will be using VMAC’s instead of HMAC’s for even more speed. Plus, apparently Andrew Kuchling isn’t maintaining PyCrypto, as there’s quite a few patches for it sitting unanswered on the sourceforge and launchpad bug trackers.

Tags: Code Python
Comments
Dec 29 2006

Pylons 0.9.4 Released

It’s with great pleasure that I announce the release of Pylons 0.9.4. This release has quite a few bug fixes and enhancements, the most since the 0.9 milestone. It’s also likely one of the last big updates before a 1.0 release candidate (there will be some small changes in 0.9.5 and possibly a 0.9.6).

First, the most important changes for those upgrading from an existing Pylons application:

  • WARNING: Removed the lang_extract and lang_compile commands. They used
pygettext.py and its associated msgfmt.py, which lacked the ability to extract ngettext style function calls and had issues with unicode strings. The new I18NToolBox project aims to provide this functionality (and more) via the gettext command line utilities. http://i18ntoolbox.ufsoft.org
  • WARNING: Myghty’s allow_globals config var has changed, causing the
following when running pre-compiled templates: Error(TypeError): do_run_component() takes exactly 13 non-keyword arguments (5 given) Delete the compiled Myghty templates directory (specified by cache_dir or myghty_data_dir in the config file) to resolve the error.
  • WARNING: The localization function ‘_’ now uses ugettext (returns unicode
strings) instead of gettext. To preserve the old behavior, append the following line to your project’s lib.base and lib.helpers imports: from pylons.helpers import gettext as _
  • WARNING: Removed 0.8.x legacy code and backwards compatibility functions.

Please note that since some i18n functions have moved, your helpers.py will need to be updated to import _, and ungettext from pylons.i18n.

Also:

- The XMLRPC Controller got a significant update so that it now provides the full range of XML-RPC Introspection facilities for your service methods.

- SQLAlchemy convenience functions have been added to pylons.database for use with the SessionContext plugin, and to create and retain SA engines.

- Paste dependency was updated to 1.1.1, Routes to 1.6.1 (important update for map.resource functionality)

- Pylons special objects (g, c, h, request, session) now available in interactive debugger without _attach_globals.

- Controller actions can now be generators

- Pylons base WSGI app uses wsgi.org routing_args spec for easier swapping of URL resolvers.

Install

Please see http://pylonshq.com/docs/0.9.4/install for installation details.

Full Changelog

  • WARNING: Removed the lang_extract and lang_compile commands. They used pygettext.py and its associated msgfmt.py, which lacked the ability to extract ngettext style function calls and had issues with unicode strings. The new I18NToolBox project aims to provide this functionality (and more) via the gettext command line utilities. http://i18ntoolbox.ufsoft.org
  • All Pylons special objects are now available within paster shell (not just h and g).
  • WARNING: Myghty’s allow_globals config var has changed, causing the following when running pre-compiled templates:
Error(TypeError): do_run_component() takes exactly 13 non-keyword arguments (5 given) Delete the compiled Myghty templates directory (specified by cache_dir or myghty_data_dir in the config file) to resolve the error.
  • Changed i18n functions in templates to use proxy objects so that using set_lang in a template works right. Fixes #153.
  • Now allowing any template plugin to overwrite global PYLONS_VARS (such as c, g), not just pylonsmyghty.
  • Adding SQLAlchemy support to the database.py file. Saves the session engine to g to maintain it during the apps lifetime. Uses SessionContext plugin for management of the current session.
  • Updated config object so that init_app can take an optional template engine argument to declare the default template engine.
  • Updated Myghty plugin to use extra_vars_func when passed in.
  • Fixed Buffet to use extra_vars_func properly.
  • Fixed the validate decorator when there are validation errors and variable_decode=True: now passing the original params to htmlfill.render instead of the varable_decode’d version. Patch by FlimFlamMan.
  • Added ungettext function for use with pluralized i18n, and the N_ function (gettext_noop) to mark global strings for translation. Added ungettext, N_ and translator objects to be globals for templates. Refs #126.
  • WARNING: The localization function ‘_’ now uses ugettext (returns unicode strings) instead of gettext. To preserve the old behavior, append the following line to your project’s lib.base and lib.helpers imports:
from pylons.helpers import gettext as _
  • Pylons special objects are now available within the interactive debugger (deprecating _attach_locals).
  • Added setup-app run before unit tests run so that webapp has proper setup tasks handled. Fixes #113.
  • Added paste.deploy.CONFIG setup to middleware.py, websetup.py and testing files in the Pylons project templates. Closes #112.
  • Added security policy doc to index for use as Pylons security policy. Closes #91.
  • Improved the repr() of the c context object to show attributes.
  • Set environ[‘paste.testing_variables’] whenever that key is available, not just in testing mode.
  • Added capability to have an action be a generator function.
  • Added introspection capability to XMLRPCController and signature checking.
  • Updated Controller to use additional arg lookup scheme so that the source of the function args for _inspect_call can be easily overridden.
  • Updated RPCController, renamed to XMLRPCController. XMLRPCController now functions properly and will automatically return proper xmlrpc responses.
  • Added test configuration ini file to default template. Closes #114.
  • Fixed problem with pylons.database.PackageHub.get raising errors other than AttributeError when the database isn’t configured. Added new UnconfiguredConnectionError exception, instead of just KeyError or TypeError (depending on what part of the configuration failed).
  • Fixed default g init, since bare object has no init method. Reported by Ian Bicking.
  • Fixed issue with SQLObject method override having wrong name. Reported by climbus with patch. Fixes #133.
  • Moved log function to pylons.helpers and translation functions to pylons.i18n. using pylons.util purely for Pylons internal util functions.
  • WARNING: Removed 0.8.x legacy code and backwards compatibility functions.
  • PylonsApp now has option to not use Routes middleware, default resolving uses new wsgi.org routing_args spec.
  • Refactored routes dispatching to use new Routes middleware.
  • Fixed paster shell command to properly acquire mapper object without relying on the template being configured in a specific manner.
  • Added keyword argument pool_connection to pylons.database.PackageHub; if set to false then SQLObject connections won’t use pooled database connections (a new connection will be opened for each request).

Many thanks to Phil Jenvey, Ian Bicking, James Gardner, and all the other active members of the Pylons community!

Cheers,
Ben

Tags: Python Code
Comments
Page 1 of 5