a little wsgi framework
Bruno Desthuilliers
bruno.42.desthuilliers at websiteburo.invalid
Tue Jul 7 05:19:46 EDT 2009
timmyt a écrit :
> i'm interested in getting opinions on a small wsgi framework i
> assembled from webob, sqlalchemy, genshi, and various code fragments i
> found on the inter-tubes
>
> here is the interesting glue - any comments / suggestions would be
> much appreciated
<meta>
Well... My first comment would be about the usefulness of yet another
Python web framework, but let's not worry about this...
</meta>
> ------------------
> the wsgi app
> ------------------
> def application(environ, start_response):
> path = environ.get('PATH_INFO', '').lstrip('/')
>
> for regex, callback in urls:
> match = re.search(regex, path)
I don't know where these "urls" come from. But anyway : if they live in
some sort of long-running process, you may want to precompile them.
> if match:
> environ['myapp.url_args'] = match.groups()
> request = webob.Request(environ)
>
> try:
> return callback(request, start_response)
> except Exception, ex:
How are redirect etc handled ?
> start_response('500 Internal Server Error', [('Content-
> Type', 'text/plain')])
> return [traceback.format_exc()]
A configuration option controlling the display of the traceback would be
fine - I surely don't want the traceback being displayed to anyone when
the app goes into production.
Also, logging the error and traceback might be useful.
> start_response('404 Not Found', [('Content-Type', 'text/plain')])
> return ["Couldn't find the URL specified."]
>
And in both cases, having the ability to use "custom" 500 and 404 pages
might be nice too.
> ----------------------------------
> the controller decorator
> ----------------------------------
> def web_decorator(filename, method='html'):
>
> def decorator(target):
May I suggest some renaming here ?
filename => path (or 'template_path' ?)
method => content_type
target => controller or function or callback or....
> def wrapper(request, start_response):
>
> #genshi TemplateLoader
> template = loader.load(filename)
>
> global config
Probably not thread-safe....
> try:
> return_dict = target(request, start_response)
> return_string = template.generate(**return_dict).render
> (method)
Renaming again:
return_dict => context
return_string => data or text or ???
> config['database.Session'].commit()
> except:
> config['database.Session'].rollback()
> raise
> finally:
> config['database.Session'].remove()
This doesn't leave much control on transactions... Sometimes you want to
handle it manually one way or another.
> #TODO: alter 'Content-Type' per method being passed
> start_response('200 OK', [('Content-Type', 'text/html')])
> return [return_string]
Ok, so here again, I don't understand how redirects can work. Also, if
you do use start_response here, I don't get why you still pass it to the
callback function.
> return wrapper
>
> return decorator
slightly OT, but preserving infos on the decorated function might help
too (introspection, debugging etc).
My 2 cents...
More information about the Python-list
mailing list