1Version 2.5.1 - February 07, 2012 2--------------------------------- 3- Bug fix release related to request charset in old versions of 4 WebOb. 5 6Version 2.5 - February 01, 2012 7------------------------------- 8 9Version 2.4 - January 23, 2012 10------------------------------ 11- Maintenance release. Fixed outstanding bugs related to App Engine. 12- Removed webapp2_extras/protorpc, broken since webapp2 was added 13 to App Engine. 14 15 16Version 2.3 - August 24, 2011 17----------------------------- 18- webapp2.Response.out creates a reference loop that impedes garbage 19 collection. Changing it to a property fixed this (Issue #15). 20- webapp2_extras.i18n: 21 - When in debug mode, translations are not cached, so compiling new 22 translations make them readily available (Issue #13). 23- webapp2_extras.auth: 24 - ATTENTION: auth_id is no longer converted to lower case to retrieve 25 a key or save a new user in webapp2_extras.appengine.auth.models.User. 26 This is a more general approach, as not all systems use case-insensitive 27 user ids. If you want case-insensitive auth ids, convert them to lower 28 case before passing auth ids to the auth module (Issue #14). 29 - If user data is missing attributes, don't raise AssertionError. 30 Simply don't save or return a valid session, instead. 31 - call user_model.get_id() instead of the ndb-specific user.key.id(). 32 - removed set_password_validator() and set_token_validator(). 33 They add complexity to the API without a use case to justify. 34 Extend AuthStore to achieve the same thing. 35 36 37Version 2.2.3 - August 6, 2011 38------------------------------ 39- Version 2.2.2 missed the webapp2_extras.appengine package. 40 41- get_app() and get_request() now test that app and request are set, to avoid 42 hard to debug stack traces when they are not and the local proxy is used. 43 44 45Version 2.2.2 - August 5, 2011 (more 2's than ever!) 46---------------------------------------------------- 47- A default charset is always set in the Request object: if it is not defined 48 in the constructor, environ['CONTENT_TYPE'] is checked; and if it is still 49 not defined 'utf-8' is used. 50 51- Added token_model as an attribute of the User model; it is used instead of 52 the hardcoded class. 53 54 55Version 2.2.1 - August 1st, 2011 56-------------------------------- 57- Fixed a bug in WSGIApplication.run() when running outside of App Engine: 58 CGIHandler().run(app) -> CGIHandler().run(self). (issue 9) 59 60 61Version 2.2 - July 30, 2011 62=========================== 63- Revised webapp2_extras.auth and simplified User model, by Kyle Finley. 64 Thanks! 65 66 67Version 2.1 - July 29, 2011 68=========================== 69- Added webapp2_extras.auth: high-level utilities for authentication and 70 authorization. 71 72- Added webapp2_extras.appengine.auth.models: default model implementations 73 for webapp2_extras.auth (can be overridden). 74 75- Added webapp2_extras.appengine.ndb.unique_model: a model to store unique 76 values. This was added mainly so that the default user model can have 77 multiple unique properties. 78 79- import_string() now displays useful debug information when it fails. 80 81- To make things clearly separated specially for those using webapp2 82 outside of App Engine, from now on all App Engine-specific modules will 83 be placed in webapp2_extras.appengine. Also three modules were moved to 84 the new package: 85 86 - webapp2_extras.sessions_memcache 87 - webapp2_extras.sessions_ndb 88 - webapp2_extras.users 89 90 The original modules were not removed, though: they will be kept in the same 91 place for compatibility purposes, just importing their stuff from the new 92 locations. 93 94- Config.load_config() now makes a copy of the configuration when user_values 95 are passed. That keyword is meant to override app configuration, so the 96 previous behavior was actually wrong. This is a side feature not used inside 97 webapp2 or even well documented so the change should not affect existing 98 apps. 99 100 101Version 2.0.2 - July 18, 2011 102============================= 103- cached_property now uses threading.RLock for thread-safety. 104 105 106Version 2.0.1 - July 17, 2011 107============================= 108- Little fix: use google.appengine.ext.webapp.util if available, like before. 109 110 111Version 2.0 - July 17, 2011 112=========================== 113- Added support for the (not yet released) App Engine Python 2.7 SDK. 114 115- Deprecated webapp2_extras.local_app. WSGIApplication is now thread-safe 116 by default when webapp2_extras.local is available. 117 webapp2_extras.local_app.WSGIApplication can still be imported, but it is 118 just an alias to webapp2.WSGIApplication (and a deprecation warning is 119 emitted when it is imported). 120 121- Like DomainRoute, PathPrefixRoute now only tests the nested routes if the 122 prefix matches. So now it is not only convenient but matches smartly and 123 faster. ;) 124 125- Added webapp2_extras.security, with security related helpers such as secure 126 password hashing tools. 127 128- webapp2_extras.sessions: 129 - Now uses webapp2_extras.security.create_token() to generate session IDs 130 instead of uuid. 131 - Added 'backends' configuration: get_session() can now be called passing 132 a more convenient 'backend' key. Default ones are 'securecookie', 133 'datastore' and 'memcache'. 134 135- get_build_routes() now yields (name, route) instead of simply route. This 136 will allow routes with nested routes to act as a proxy to build URIs. 137 138- webapp2.urlunsplit() was removed from the public API. 139 140- Variables names in routes must now look like python identifiers - 141 this means that they can no longer start with a number, like before. 142 143- Removed support for _anchor in uri_for() -- the documented keyword is 144 _fragment. 145 146- Removed support for handler functions receiving (request, response). The 147 correct arguments for function handlers are (request, *args, **kwargs). 148 149- webapp2_extras.json: 150 - Fixed an issue with importing json on non-GAE environments (missing 151 absolute import). 152 - Now imports simplejson directly instead of using the one from Django, 153 since it is now included in the App Engine SDK (since version 1.4.2). 154 155- Added WSGIApplication.clear_globals(). Instead of 156 app.set_globals(app=None, request=None), use app.clear_globals(). 157 158 159Version 1.8.1 - June 29, 2011 160============================= 161- Implemented an adapter mechanism to dispatch different kind of handlers: 162 webapp.RequestHandler, webapp2.RequestHandler and "view functions". 163 Instead of monkeypatching handlers (adding a 'factory' attribute), 164 handlers are wrapped by adapters that do the appropriate dispatch. 165 How handlers are adapted can be overridden using the convenience method 166 ``set_adapter()`` from the Router class, but the common cases are covered. 167 168- Function views now conveniently receive (request, *args, **kwargs), like 169 in Django. The previous arguments will work, but they are now deprecated 170 and will not be supported in the future. This is a major incompatibility 171 with previous versions but it feels a lot better than the previous 172 (request, response) behavior, as adapters make it easy to have custom 173 dispatch arguments using a unified API. 174 The webapp2.RequestHandler class remain unchanged and is instantiated with 175 (request, response). 176 177 178Version 1.8 - June 26, 2011 179=========================== 180- webap2_extras.i18n: the functions passed to I18nStore.set_locale_selector() 181 and I18nStore.set_timezone_selector() now receive (store, request) instead of 182 (request, store), for consistency with the router custom callables. 183 184- webap2_extras.json: 185 - json is imported first trying direct simplejson, then built-in json 186 (for Python >= 2.6), then the one from django.utils (for App Engine). 187 - All convenience functions now receive *args, **kwargs to be passed to 188 encode()/decode(). 189 190- Added webapp2_extras.mako. 191 192- Added webapp2.redirect_to. 193 194- Added Request.blank() parameters compatible with WebOb >= 1.0: POST and 195 **kwargs. 196 197- Increased compatibility with wsgiref.headers.Headers, used by 198 webapp.Response. 199 200 201Version 1.7.5 - June 20, 2011 202============================= 203- Implemented methods from ``wsgiref.headers.Headers``, used by 204 webapp.Response.headers. 205 206 207Version 1.7.4 - June 19, 2011 208============================= 209- Fixed bug in response.status_message. 210 211 212Version 1.7.3 - June 17, 2011 213============================= 214- Routes can now only match specific schemes, e.g., 'http' or 'https'. 215 216- Added a tutorial to use webapp2 outside of App Engine. 217 218 219Version 1.7.2 - June 16, 2011 220============================= 221- Response is now compatible with latest WebOb. 222 223- Increased Response compatibility with webapp, implementing wsgi_write() and 224 has_error(). 225 226- Changed some status messages to be the same as webapp: 227 - 203: 'Non-Authoritative Information' 228 - 302: 'Moved Temporarily' 229 - 306: 'Unused' 230 - 408: 'Request Time-out' 231 - 414: 'Request-URI Too Large' 232 - 504: 'Gateway Time-out' 233 - 505: 'HTTP Version not supported' 234 235- Copied Request from webapp, so that when using webapp2 outside of the SDK 236 they are the same. 237 238- Routes now match the Request path unquoted. See App Engine issue #2636 239 for an explanation. 240 241 242Version 1.7.1 - June 14, 2011 243============================= 244- Added standalone redirect() function. 245 246- RequestHandler.redirect and redirect_to now return a response object. 247 248- Fixed: multiple routes that define methods are tried before MethodNotAllowed 249 is raised. 250 251- Updated webapp2_extras.protorpc to work with latest ProtoRPC. 252 253 254Version 1.7 - June 4, 2011 255========================== 256- Added a simple configuration object for WSGIapplication, available in the 257 config attribute. Extras modules that use configuration (i18n, jinja2, 258 sessions) don't require app.config to be set manually anymore. Still, the 259 `secret_key` key config for sessions, if not defined, will result in an 260 exception. 261 262- Deprecated webapp2_extras.config, replaced by the simpler app dict. 263 264- Router no longer receives app on construction, for consistency with the 265 config object. App is set as global before router is initialized. 266 267- Fixed a bug in webapp2_extras.sessions that made it not save the session 268 when it was empty (like when flashes are popped). 269 270- Added standalone uri_for function, to be used in templates. 271 272 273Version 1.6.3 - June 3, 2011 274============================ 275- Added webap2_extras.local_app, with the WSGIApplication previously in 276 webap2_extras.local. This allows using LocalProxy on App Engine, without 277 actually monkeypatching the WSGI app for threaded environments. 278 279- Route now raises exc.HTTPMethodNotAllowed if methods are set and the request 280 method doesn't match. 281 282- Router.default_matcher() now raises exc.HTTPNotFound if no route matches. 283 284 285Version 1.6.2 - May 30, 2011 286============================ 287- WSGIApplication.__call__ checks if the dispatcher didn't return None to 288 accept the returned value as a response. Previously it checked if it was an 289 instance of Response. 290 291- To support returned response, RequestHandler.dispatch() returns the result of 292 the dispatched method. 293 294Version 1.6.1 - May 30, 2011 295============================ 296- Fixed an indentation bug in webapp2_extras.users. 297 298- Added back _to_utf8() to convert values for import_string() and urlunsplit(). 299 300- Added WSGIApplication.get_response(), a convenience for unit tests. 301 302 303Version 1.6 - May 29, 2011 304========================== 305- Handlers registered in WSGIApplication.error_handlers can now also be a 306 string to be lazily imported. 307 308- The request object now has the active response available as an attribute: 309 request.response. 310 311- Added a factory method to RequestHandler, to better deal with libraries that 312 use a custom webapp.RequestHandler constructors (like ProtoRPC). 313 314- Added set_dispatcher() to Router, to set extended dispatching. 315 316- Handlers and error handlers can now return a response object, which will be 317 used instead of the default response created by the WSGI app. This allows 318 webapp2 to be used following the common pattern of handlers that return a 319 response, instead of the webapp way of a handler that writes to an existing 320 response. 321 322- Request.Handler.redirect() now can receive a `code` parameter, to set the 323 status code. This is preferable than the `permanent` parameter, kept for 324 compatibility with webapp. 325 326- webapp2 is now a file webapp2.py, instead of a package with a __init__.py 327 file. 328 329- API cleanup: 330 - Removed WSGIApplication.url_for(), to_unicode(), to_utf8(). 331 - RequestHandler.url_for was renamed to uri_for, with url_for kept 332 as an alias. 333 - Renamed webapp2_extras.routes.ImprovedRoute to RedirectRoute, as it 334 basically adds redirect conveniences. 335 - For consistency with uri building parameters, RedirectHandler parameters 336 are now prefixed with a underscore: `url` becomes `_uri` and `permanent` 337 becomes `_permanent`. A parameter `_code` was added to set status code. 338 - Router.do_match and do_build renamed to default_matcher and 339 default_dispatcher. 340 - URI building accepts a _fragment argument, with _anchor as fallback. 341 342 343Version 1.5 - May 16, 2011 344========================== 345- Added webapp2_extras.local, with an extended WSGIApplication that uses 346 thread-local for globals and so can be used outside of App Engine. 347 348- Added webapp2_extras.protorpc, with support for Google ProtoRPC. 349 350- Added set_matcher() and set_builder() to Router, to set extended matcher and 351 builder. 352 353- Routes now return the route on match() or routes with nested routes cannot 354 work. So instead of returning (args, kwargs) they return 355 (route, args, kwargs). 356 357- Now handlers only receive **args if no named variables are set. Otherwise, 358 they only receive **kwargs. This allows users to use regexes that are not 359 intended to be captured, mixing named and unnamed variables. 360 361- DomainRoute now uses the same syntax used by webapp2.Route, instead of a 362 regex. The resulting keywords are added to the mathed route **kwargs. 363 This gives control of what is passed to the handler if a domain/subdomain 364 matches, and allows to not pass anything if no regex groups are defined. 365 366- Several small bugs fixed and increased test coverage in webapp2_extras. 367 368 369Version 1.3 - May 9, 2011 370========================= 371- Added webapp2_extras modules: 372 - webapp2_extras.i18n: internationalization support. 373 - webapp2_extras.sessions_memcache: memcache based sessions. 374 - webapp2_extras.sessions_ndb: datastore based sessions. 375- Several api improvements in webapp2_extras. 376 377 378Version 1.2 - May 6, 2011 379========================= 380- Removed Config from webapp2 core. It is now part of the new "webapp2_extras" 381 package. 382- Added the package webapp2_extras. These are all optional modules that 383 complement webapp2 with common functionalities. Currently they include: 384 - webapp2_extras.config: Configuration object. 385 - webapp2_extras.jinja2: Support for Jinja2 templating. 386 - webapp2_extras.json: JSON utilities. 387 - webapp2_extras.routes: Extended route classes. 388 - webapp2_extras.securecookie: Signed cookie serializer. 389 - webapp2_extras.sessions: Sessions support. 390 391 392Version 1.1 - May 5, 2011 393========================= 394- Simplified routing with an unified dispatch method for classes and functions. 395 396 397Version 1.0 - May 1st, 2011 398=========================== 399This is a major refactoring with some incompatible changes, mostly internal 400stuff that won't be noticed in common usage. 401 402- Changed signature of RequestHandler's constructor: it now receives only 403 (request, response) instead of (app, request, response). 404 405- Added RequestContext class, which should help testing. 406 407- Added .app attribute to Request, a reference to the active app. 408 409- Refactored routing scheme: 410 - Now also supports function views besides classes. 411 - Now also supports normal functions as exception handlers, and exception 412 handlers don't need to be a subclass RequestHandler (but still can). 413 - Now also supports custom handler methods besides using the request method. 414 415- Removed Request.context: was redundant with Request.registry. 416 417- Renamed WSGIApplication.wsgi_app to WSGIApplication.dispatch. 418 419- Moved ALLOWED_METHODS to WSGIApplication.allowed_methods. 420 421- Moved get_valid_methods() to RequestHandler.get_valid_methods(). 422 423 424Version 0.7 - September 26, 2010 425================================ 426- Added WSGIApplication.app and WSGIApplication.request, class attributes set 427 on each request to reference currently active app and request. 428 WSGIApplication.app is an alias to WSGIApplication.active_instance. 429 430- Fixed double escaping of + in urlunsplit(). Thanks, alkis. 431 432- IMPROVED: configuration now behaves exactly like a dictionary, still 433 auto-loading configuration values when needed and honoring required configs. 434 For example, we always used this:: 435 436 bar = self.app.get_config('foo', 'bar') 437 438 Now it is also possible to use direct access and dict methods:: 439 440 bar = self.app.config['foo']['bar'] 441 # or... 442 bar = self.app.config['foo'].get('bar') 443 # or... 444 bar = self.app.config.get('foo').get('bar') 445 446 The previous get_config() method works as always. 447 448 449Version 0.6 - August 31, 2010 450============================= 451- Fix: Anchors in generated URLs are quoted using urlib.quote, instead of 452 urlib.quote_plus. 453 454- In Router.dispatch(), if an exception occurs while handling an exception, 455 raise it instead of trying to handle it again. 456 457- Fixed bug when writing a unicode string to Response and charset is not set. 458 Thanks to martinc for the patch. 459 460- Changed: the app won't fallback anymore to the exception handler set for 461 status 500 if handlers for other status are not set. 462 463- Changed: exceptions are only logged when unhandled. It is up to exception 464 handlers to log them when appropriate. 465 466 467Version 0.5.1 - August 17, 2010 468=============================== 469- When a URL matches, some attributes are set in the request object: 470 - request.route: the matched route 471 - request.route_args: the matched positional arguments, a tuple 472 - request.route_kwargs: the matched keyword arguments, a dict 473 474- WSGIApplication.handle_exception() doesn't automatically raises the exception 475 when in debug mode: it is up to the error handler to raise it if in dev; it 476 will be raised if no error handler is defined to handle it anyway. 477 478- Added attributes, WSGIApplication.registry, Request.registry and 479 Request.context, dictionaries for objects in use during the app or request 480 lifetimes. 481 482- Before passing the request method to the RequestHandler, '-' is replaced 483 by '_', so that a method like WebDav's 'VERSION-CONTROL' can be supported. 484 485- Config.get() now only returns the passed default value when key is defined. 486 This is the intended, more predictable behavior: default is a default for 487 the key, not the module. For example:: 488 489 # If config['foo']['bar'] is not set, return 'baz'. 490 config.get('foo', 'bar', default='baz') 491 492 # If config['foo'] is not set, return None. Default is ignored here. 493 config.get('foo', default='baz') 494 495- Router initialization now receives the app as parameter, so that extended 496 routes can access app's config. 497 498 499Version 0.5 - August 13, 2010 500============================= 501- Better compatibility with webapp: 502 - webapp2.WSGIapplication can be used with webapp.RequestHandler. 503 - webapp.WSGIapplication can be used with webapp2.RequestHandler. 504 505 Although the functionality becomes limited in both cases, this should help 506 migration. 507 508- Review of Response based on observations from 509 http://pythonpaste.org/webob/differences.html#webapp-response: 510 511 - Response.out is now a reference to self, to use webob.Response's neat 512 .write() method which can handle both string and unicode. 513 - Response.clear() now sets .body = '' instead of .app_iter = []. 514 515- Added Response.write(), for compatibility with StringIO behavior in webapp 516 when calling write() passing non-basestring values (issue 2). 517 518- Removed url_escape() and url_unescape(). Unused or almost unused. 519 520- ErrorHandlers can now be defined as strings to be lazily loaded, as they 521 now use the same dispatch mechanism of other handlers. 522 523Backwards compatibility warning 524------------------------------- 525- The method handle_exception() is called from app-wide error handlers. 526 Previously, get() was called. 527 528 529Version 0.4.1 - August 08, 2010 530=============================== 531- Removed router parameter from get_routes(), get_match_routes(), 532 get_build_routes(). This simplifies multi-routes quite a bit. 533 534 535Version 0.4 - August 07, 2010 536============================= 537- redirect() and redirect_to() now accept a keyword argument 'abort' to raise 538 an exception to do the redirect. 539 540- '_netloc' can be passed to url_for() build URLs for a given domain or 541 subdomain. 542 543- Added BaseRoute, an interface for custom routes. Several improvements make 544 the routing system more extensible, while the default Route class sticks to 545 the basics. 546 547- Nested routes are now possible. As an example, `extras/routes.py` has several 548 classes that accept nested routes or extend routing in other ways: 549 550 - PathPrefixRoute: the idea of this route is to set a base path for other 551 routes:: 552 553 app = WSGIApplication([ 554 PathPrefixRoute('/users/<user:\w+>', [ 555 Route('/', UserOverviewHandler, 'user-overview'), 556 Route('/profile', UserProfileHandler, 'user-profile'), 557 Route('/projects', UserProjectsHandler, 'user-projects'), 558 ]), 559 ]) 560 561 The example above is the same as setting the following routes, just more 562 convenient as you can reuse the path prefix:: 563 564 app = WSGIApplication([ 565 Route('/users/<user:\w+>/', UserOverviewHandler, 'user-overview'), 566 Route('/users/<user:\w+>/profile', UserProfileHandler, 'user-profile'), 567 Route('/users/<user:\w+>/projects', UserProjectsHandler, 'user-projects'), 568 ]) 569 570 - NamePrefixRoute: Same as PathPrefixRoute, but prefixes the names of routes. 571 572 - HandlerPrefixRoute: Same as PathPrefixRoute, but prefixes the handlers of 573 routes. 574 575 - DomainRoute: a route used to restrict route matches to a given domain or 576 subdomain. 577 578 For example, to restrict routes to a subdomain of the appspot domain:: 579 580 SUBDOMAIN_RE = '^([^.]+)\.app-id\.appspot\.com$' 581 582 app = WSGIApplication([ 583 DomainRoute(SUBDOMAIN_RE, [ 584 Route('/foo', 'FooHandler', 'subdomain-thing'), 585 ]), 586 Route('/bar', 'BarHandler', 'normal-thing'), 587 ]) 588 589 - ImprovedRoute: a route with redirect_to and strict_slash. 590 591 - `redirect_to`: if set, the route is used to redirect to a URL. The value 592 can be a URL string or a callable that returns a URL. These two are 593 equivalent:: 594 595 route = Route('/foo', RedirectHandler, defaults={'url': '/bar'}) 596 route = Route('/foo', redirect_to='/bar') 597 598 - `strict_slash`: if True, redirects access to the same URL with different 599 trailing slash to the strict path defined in the rule. For example, take 600 these rules:: 601 602 route = Route('/foo', FooHandler, strict_slash=True) 603 route = Route('/bar/', BarHandler, strict_slash=True) 604 605 Because **strict_slash** is True, this is what will happen: 606 607 - Access to ``/foo`` will execute ``FooHandler`` normally. 608 - Access to ``/bar/`` will execute ``BarHandler`` normally. 609 - Access to ``/foo/`` will redirect to ``/foo``. 610 - Access to ``/bar`` will redirect to ``/bar/``. 611 612 613Version 0.3 - August 05, 2010 614============================= 615- Routes store the handler, as we had in 0.1. This allows custom routes to 616 have nested routes. 617- Much improved URL building, now delegated to routes. 618- added urlunsplit() helper. 619 620 621Version 0.2 - August 04, 2010 622============================= 623- Fixed a bug in Route.match() that would make it return positional arguments 624 with wrong order. Dictionary is correctly sorted now. 625- Added build_only option for routes: routes that are only used for url_for() 626 and never match. 627 628 629Version 0.1 - August 03, 2010 630============================= 631- Initial release. 632