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