Version 2.5.1 - February 07, 2012 --------------------------------- - Bug fix release related to request charset in old versions of WebOb. Version 2.5 - February 01, 2012 ------------------------------- Version 2.4 - January 23, 2012 ------------------------------ - Maintenance release. Fixed outstanding bugs related to App Engine. - Removed webapp2_extras/protorpc, broken since webapp2 was added to App Engine. Version 2.3 - August 24, 2011 ----------------------------- - webapp2.Response.out creates a reference loop that impedes garbage collection. Changing it to a property fixed this (Issue #15). - webapp2_extras.i18n: - When in debug mode, translations are not cached, so compiling new translations make them readily available (Issue #13). - webapp2_extras.auth: - ATTENTION: auth_id is no longer converted to lower case to retrieve a key or save a new user in webapp2_extras.appengine.auth.models.User. This is a more general approach, as not all systems use case-insensitive user ids. If you want case-insensitive auth ids, convert them to lower case before passing auth ids to the auth module (Issue #14). - If user data is missing attributes, don't raise AssertionError. Simply don't save or return a valid session, instead. - call user_model.get_id() instead of the ndb-specific user.key.id(). - removed set_password_validator() and set_token_validator(). They add complexity to the API without a use case to justify. Extend AuthStore to achieve the same thing. Version 2.2.3 - August 6, 2011 ------------------------------ - Version 2.2.2 missed the webapp2_extras.appengine package. - get_app() and get_request() now test that app and request are set, to avoid hard to debug stack traces when they are not and the local proxy is used. Version 2.2.2 - August 5, 2011 (more 2's than ever!) ---------------------------------------------------- - A default charset is always set in the Request object: if it is not defined in the constructor, environ['CONTENT_TYPE'] is checked; and if it is still not defined 'utf-8' is used. - Added token_model as an attribute of the User model; it is used instead of the hardcoded class. Version 2.2.1 - August 1st, 2011 -------------------------------- - Fixed a bug in WSGIApplication.run() when running outside of App Engine: CGIHandler().run(app) -> CGIHandler().run(self). (issue 9) Version 2.2 - July 30, 2011 =========================== - Revised webapp2_extras.auth and simplified User model, by Kyle Finley. Thanks! Version 2.1 - July 29, 2011 =========================== - Added webapp2_extras.auth: high-level utilities for authentication and authorization. - Added webapp2_extras.appengine.auth.models: default model implementations for webapp2_extras.auth (can be overridden). - Added webapp2_extras.appengine.ndb.unique_model: a model to store unique values. This was added mainly so that the default user model can have multiple unique properties. - import_string() now displays useful debug information when it fails. - To make things clearly separated specially for those using webapp2 outside of App Engine, from now on all App Engine-specific modules will be placed in webapp2_extras.appengine. Also three modules were moved to the new package: - webapp2_extras.sessions_memcache - webapp2_extras.sessions_ndb - webapp2_extras.users The original modules were not removed, though: they will be kept in the same place for compatibility purposes, just importing their stuff from the new locations. - Config.load_config() now makes a copy of the configuration when user_values are passed. That keyword is meant to override app configuration, so the previous behavior was actually wrong. This is a side feature not used inside webapp2 or even well documented so the change should not affect existing apps. Version 2.0.2 - July 18, 2011 ============================= - cached_property now uses threading.RLock for thread-safety. Version 2.0.1 - July 17, 2011 ============================= - Little fix: use google.appengine.ext.webapp.util if available, like before. Version 2.0 - July 17, 2011 =========================== - Added support for the (not yet released) App Engine Python 2.7 SDK. - Deprecated webapp2_extras.local_app. WSGIApplication is now thread-safe by default when webapp2_extras.local is available. webapp2_extras.local_app.WSGIApplication can still be imported, but it is just an alias to webapp2.WSGIApplication (and a deprecation warning is emitted when it is imported). - Like DomainRoute, PathPrefixRoute now only tests the nested routes if the prefix matches. So now it is not only convenient but matches smartly and faster. ;) - Added webapp2_extras.security, with security related helpers such as secure password hashing tools. - webapp2_extras.sessions: - Now uses webapp2_extras.security.create_token() to generate session IDs instead of uuid. - Added 'backends' configuration: get_session() can now be called passing a more convenient 'backend' key. Default ones are 'securecookie', 'datastore' and 'memcache'. - get_build_routes() now yields (name, route) instead of simply route. This will allow routes with nested routes to act as a proxy to build URIs. - webapp2.urlunsplit() was removed from the public API. - Variables names in routes must now look like python identifiers - this means that they can no longer start with a number, like before. - Removed support for _anchor in uri_for() -- the documented keyword is _fragment. - Removed support for handler functions receiving (request, response). The correct arguments for function handlers are (request, *args, **kwargs). - webapp2_extras.json: - Fixed an issue with importing json on non-GAE environments (missing absolute import). - Now imports simplejson directly instead of using the one from Django, since it is now included in the App Engine SDK (since version 1.4.2). - Added WSGIApplication.clear_globals(). Instead of app.set_globals(app=None, request=None), use app.clear_globals(). Version 1.8.1 - June 29, 2011 ============================= - Implemented an adapter mechanism to dispatch different kind of handlers: webapp.RequestHandler, webapp2.RequestHandler and "view functions". Instead of monkeypatching handlers (adding a 'factory' attribute), handlers are wrapped by adapters that do the appropriate dispatch. How handlers are adapted can be overridden using the convenience method ``set_adapter()`` from the Router class, but the common cases are covered. - Function views now conveniently receive (request, *args, **kwargs), like in Django. The previous arguments will work, but they are now deprecated and will not be supported in the future. This is a major incompatibility with previous versions but it feels a lot better than the previous (request, response) behavior, as adapters make it easy to have custom dispatch arguments using a unified API. The webapp2.RequestHandler class remain unchanged and is instantiated with (request, response). Version 1.8 - June 26, 2011 =========================== - webap2_extras.i18n: the functions passed to I18nStore.set_locale_selector() and I18nStore.set_timezone_selector() now receive (store, request) instead of (request, store), for consistency with the router custom callables. - webap2_extras.json: - json is imported first trying direct simplejson, then built-in json (for Python >= 2.6), then the one from django.utils (for App Engine). - All convenience functions now receive *args, **kwargs to be passed to encode()/decode(). - Added webapp2_extras.mako. - Added webapp2.redirect_to. - Added Request.blank() parameters compatible with WebOb >= 1.0: POST and **kwargs. - Increased compatibility with wsgiref.headers.Headers, used by webapp.Response. Version 1.7.5 - June 20, 2011 ============================= - Implemented methods from ``wsgiref.headers.Headers``, used by webapp.Response.headers. Version 1.7.4 - June 19, 2011 ============================= - Fixed bug in response.status_message. Version 1.7.3 - June 17, 2011 ============================= - Routes can now only match specific schemes, e.g., 'http' or 'https'. - Added a tutorial to use webapp2 outside of App Engine. Version 1.7.2 - June 16, 2011 ============================= - Response is now compatible with latest WebOb. - Increased Response compatibility with webapp, implementing wsgi_write() and has_error(). - Changed some status messages to be the same as webapp: - 203: 'Non-Authoritative Information' - 302: 'Moved Temporarily' - 306: 'Unused' - 408: 'Request Time-out' - 414: 'Request-URI Too Large' - 504: 'Gateway Time-out' - 505: 'HTTP Version not supported' - Copied Request from webapp, so that when using webapp2 outside of the SDK they are the same. - Routes now match the Request path unquoted. See App Engine issue #2636 for an explanation. Version 1.7.1 - June 14, 2011 ============================= - Added standalone redirect() function. - RequestHandler.redirect and redirect_to now return a response object. - Fixed: multiple routes that define methods are tried before MethodNotAllowed is raised. - Updated webapp2_extras.protorpc to work with latest ProtoRPC. Version 1.7 - June 4, 2011 ========================== - Added a simple configuration object for WSGIapplication, available in the config attribute. Extras modules that use configuration (i18n, jinja2, sessions) don't require app.config to be set manually anymore. Still, the `secret_key` key config for sessions, if not defined, will result in an exception. - Deprecated webapp2_extras.config, replaced by the simpler app dict. - Router no longer receives app on construction, for consistency with the config object. App is set as global before router is initialized. - Fixed a bug in webapp2_extras.sessions that made it not save the session when it was empty (like when flashes are popped). - Added standalone uri_for function, to be used in templates. Version 1.6.3 - June 3, 2011 ============================ - Added webap2_extras.local_app, with the WSGIApplication previously in webap2_extras.local. This allows using LocalProxy on App Engine, without actually monkeypatching the WSGI app for threaded environments. - Route now raises exc.HTTPMethodNotAllowed if methods are set and the request method doesn't match. - Router.default_matcher() now raises exc.HTTPNotFound if no route matches. Version 1.6.2 - May 30, 2011 ============================ - WSGIApplication.__call__ checks if the dispatcher didn't return None to accept the returned value as a response. Previously it checked if it was an instance of Response. - To support returned response, RequestHandler.dispatch() returns the result of the dispatched method. Version 1.6.1 - May 30, 2011 ============================ - Fixed an indentation bug in webapp2_extras.users. - Added back _to_utf8() to convert values for import_string() and urlunsplit(). - Added WSGIApplication.get_response(), a convenience for unit tests. Version 1.6 - May 29, 2011 ========================== - Handlers registered in WSGIApplication.error_handlers can now also be a string to be lazily imported. - The request object now has the active response available as an attribute: request.response. - Added a factory method to RequestHandler, to better deal with libraries that use a custom webapp.RequestHandler constructors (like ProtoRPC). - Added set_dispatcher() to Router, to set extended dispatching. - Handlers and error handlers can now return a response object, which will be used instead of the default response created by the WSGI app. This allows webapp2 to be used following the common pattern of handlers that return a response, instead of the webapp way of a handler that writes to an existing response. - Request.Handler.redirect() now can receive a `code` parameter, to set the status code. This is preferable than the `permanent` parameter, kept for compatibility with webapp. - webapp2 is now a file webapp2.py, instead of a package with a __init__.py file. - API cleanup: - Removed WSGIApplication.url_for(), to_unicode(), to_utf8(). - RequestHandler.url_for was renamed to uri_for, with url_for kept as an alias. - Renamed webapp2_extras.routes.ImprovedRoute to RedirectRoute, as it basically adds redirect conveniences. - For consistency with uri building parameters, RedirectHandler parameters are now prefixed with a underscore: `url` becomes `_uri` and `permanent` becomes `_permanent`. A parameter `_code` was added to set status code. - Router.do_match and do_build renamed to default_matcher and default_dispatcher. - URI building accepts a _fragment argument, with _anchor as fallback. Version 1.5 - May 16, 2011 ========================== - Added webapp2_extras.local, with an extended WSGIApplication that uses thread-local for globals and so can be used outside of App Engine. - Added webapp2_extras.protorpc, with support for Google ProtoRPC. - Added set_matcher() and set_builder() to Router, to set extended matcher and builder. - Routes now return the route on match() or routes with nested routes cannot work. So instead of returning (args, kwargs) they return (route, args, kwargs). - Now handlers only receive **args if no named variables are set. Otherwise, they only receive **kwargs. This allows users to use regexes that are not intended to be captured, mixing named and unnamed variables. - DomainRoute now uses the same syntax used by webapp2.Route, instead of a regex. The resulting keywords are added to the mathed route **kwargs. This gives control of what is passed to the handler if a domain/subdomain matches, and allows to not pass anything if no regex groups are defined. - Several small bugs fixed and increased test coverage in webapp2_extras. Version 1.3 - May 9, 2011 ========================= - Added webapp2_extras modules: - webapp2_extras.i18n: internationalization support. - webapp2_extras.sessions_memcache: memcache based sessions. - webapp2_extras.sessions_ndb: datastore based sessions. - Several api improvements in webapp2_extras. Version 1.2 - May 6, 2011 ========================= - Removed Config from webapp2 core. It is now part of the new "webapp2_extras" package. - Added the package webapp2_extras. These are all optional modules that complement webapp2 with common functionalities. Currently they include: - webapp2_extras.config: Configuration object. - webapp2_extras.jinja2: Support for Jinja2 templating. - webapp2_extras.json: JSON utilities. - webapp2_extras.routes: Extended route classes. - webapp2_extras.securecookie: Signed cookie serializer. - webapp2_extras.sessions: Sessions support. Version 1.1 - May 5, 2011 ========================= - Simplified routing with an unified dispatch method for classes and functions. Version 1.0 - May 1st, 2011 =========================== This is a major refactoring with some incompatible changes, mostly internal stuff that won't be noticed in common usage. - Changed signature of RequestHandler's constructor: it now receives only (request, response) instead of (app, request, response). - Added RequestContext class, which should help testing. - Added .app attribute to Request, a reference to the active app. - Refactored routing scheme: - Now also supports function views besides classes. - Now also supports normal functions as exception handlers, and exception handlers don't need to be a subclass RequestHandler (but still can). - Now also supports custom handler methods besides using the request method. - Removed Request.context: was redundant with Request.registry. - Renamed WSGIApplication.wsgi_app to WSGIApplication.dispatch. - Moved ALLOWED_METHODS to WSGIApplication.allowed_methods. - Moved get_valid_methods() to RequestHandler.get_valid_methods(). Version 0.7 - September 26, 2010 ================================ - Added WSGIApplication.app and WSGIApplication.request, class attributes set on each request to reference currently active app and request. WSGIApplication.app is an alias to WSGIApplication.active_instance. - Fixed double escaping of + in urlunsplit(). Thanks, alkis. - IMPROVED: configuration now behaves exactly like a dictionary, still auto-loading configuration values when needed and honoring required configs. For example, we always used this:: bar = self.app.get_config('foo', 'bar') Now it is also possible to use direct access and dict methods:: bar = self.app.config['foo']['bar'] # or... bar = self.app.config['foo'].get('bar') # or... bar = self.app.config.get('foo').get('bar') The previous get_config() method works as always. Version 0.6 - August 31, 2010 ============================= - Fix: Anchors in generated URLs are quoted using urlib.quote, instead of urlib.quote_plus. - In Router.dispatch(), if an exception occurs while handling an exception, raise it instead of trying to handle it again. - Fixed bug when writing a unicode string to Response and charset is not set. Thanks to martinc for the patch. - Changed: the app won't fallback anymore to the exception handler set for status 500 if handlers for other status are not set. - Changed: exceptions are only logged when unhandled. It is up to exception handlers to log them when appropriate. Version 0.5.1 - August 17, 2010 =============================== - When a URL matches, some attributes are set in the request object: - request.route: the matched route - request.route_args: the matched positional arguments, a tuple - request.route_kwargs: the matched keyword arguments, a dict - WSGIApplication.handle_exception() doesn't automatically raises the exception when in debug mode: it is up to the error handler to raise it if in dev; it will be raised if no error handler is defined to handle it anyway. - Added attributes, WSGIApplication.registry, Request.registry and Request.context, dictionaries for objects in use during the app or request lifetimes. - Before passing the request method to the RequestHandler, '-' is replaced by '_', so that a method like WebDav's 'VERSION-CONTROL' can be supported. - Config.get() now only returns the passed default value when key is defined. This is the intended, more predictable behavior: default is a default for the key, not the module. For example:: # If config['foo']['bar'] is not set, return 'baz'. config.get('foo', 'bar', default='baz') # If config['foo'] is not set, return None. Default is ignored here. config.get('foo', default='baz') - Router initialization now receives the app as parameter, so that extended routes can access app's config. Version 0.5 - August 13, 2010 ============================= - Better compatibility with webapp: - webapp2.WSGIapplication can be used with webapp.RequestHandler. - webapp.WSGIapplication can be used with webapp2.RequestHandler. Although the functionality becomes limited in both cases, this should help migration. - Review of Response based on observations from http://pythonpaste.org/webob/differences.html#webapp-response: - Response.out is now a reference to self, to use webob.Response's neat .write() method which can handle both string and unicode. - Response.clear() now sets .body = '' instead of .app_iter = []. - Added Response.write(), for compatibility with StringIO behavior in webapp when calling write() passing non-basestring values (issue 2). - Removed url_escape() and url_unescape(). Unused or almost unused. - ErrorHandlers can now be defined as strings to be lazily loaded, as they now use the same dispatch mechanism of other handlers. Backwards compatibility warning ------------------------------- - The method handle_exception() is called from app-wide error handlers. Previously, get() was called. Version 0.4.1 - August 08, 2010 =============================== - Removed router parameter from get_routes(), get_match_routes(), get_build_routes(). This simplifies multi-routes quite a bit. Version 0.4 - August 07, 2010 ============================= - redirect() and redirect_to() now accept a keyword argument 'abort' to raise an exception to do the redirect. - '_netloc' can be passed to url_for() build URLs for a given domain or subdomain. - Added BaseRoute, an interface for custom routes. Several improvements make the routing system more extensible, while the default Route class sticks to the basics. - Nested routes are now possible. As an example, `extras/routes.py` has several classes that accept nested routes or extend routing in other ways: - PathPrefixRoute: the idea of this route is to set a base path for other routes:: app = WSGIApplication([ PathPrefixRoute('/users/', [ Route('/', UserOverviewHandler, 'user-overview'), Route('/profile', UserProfileHandler, 'user-profile'), Route('/projects', UserProjectsHandler, 'user-projects'), ]), ]) The example above is the same as setting the following routes, just more convenient as you can reuse the path prefix:: app = WSGIApplication([ Route('/users//', UserOverviewHandler, 'user-overview'), Route('/users//profile', UserProfileHandler, 'user-profile'), Route('/users//projects', UserProjectsHandler, 'user-projects'), ]) - NamePrefixRoute: Same as PathPrefixRoute, but prefixes the names of routes. - HandlerPrefixRoute: Same as PathPrefixRoute, but prefixes the handlers of routes. - DomainRoute: a route used to restrict route matches to a given domain or subdomain. For example, to restrict routes to a subdomain of the appspot domain:: SUBDOMAIN_RE = '^([^.]+)\.app-id\.appspot\.com$' app = WSGIApplication([ DomainRoute(SUBDOMAIN_RE, [ Route('/foo', 'FooHandler', 'subdomain-thing'), ]), Route('/bar', 'BarHandler', 'normal-thing'), ]) - ImprovedRoute: a route with redirect_to and strict_slash. - `redirect_to`: if set, the route is used to redirect to a URL. The value can be a URL string or a callable that returns a URL. These two are equivalent:: route = Route('/foo', RedirectHandler, defaults={'url': '/bar'}) route = Route('/foo', redirect_to='/bar') - `strict_slash`: if True, redirects access to the same URL with different trailing slash to the strict path defined in the rule. For example, take these rules:: route = Route('/foo', FooHandler, strict_slash=True) route = Route('/bar/', BarHandler, strict_slash=True) Because **strict_slash** is True, this is what will happen: - Access to ``/foo`` will execute ``FooHandler`` normally. - Access to ``/bar/`` will execute ``BarHandler`` normally. - Access to ``/foo/`` will redirect to ``/foo``. - Access to ``/bar`` will redirect to ``/bar/``. Version 0.3 - August 05, 2010 ============================= - Routes store the handler, as we had in 0.1. This allows custom routes to have nested routes. - Much improved URL building, now delegated to routes. - added urlunsplit() helper. Version 0.2 - August 04, 2010 ============================= - Fixed a bug in Route.match() that would make it return positional arguments with wrong order. Dictionary is correctly sorted now. - Added build_only option for routes: routes that are only used for url_for() and never match. Version 0.1 - August 03, 2010 ============================= - Initial release.