Browse Source

Update Flask

pull/992/merge
Ruud 13 years ago
parent
commit
b0f6f9b2ea
  1. 11
      libs/flask/__init__.py
  2. 205
      libs/flask/app.py
  3. 2
      libs/flask/blueprints.py
  4. 3
      libs/flask/config.py
  5. 132
      libs/flask/ctx.py
  6. 0
      libs/flask/debughelpers.py
  7. 49
      libs/flask/exceptions.py
  8. 0
      libs/flask/ext/__init__.py
  9. 0
      libs/flask/exthook.py
  10. 10
      libs/flask/globals.py
  11. 263
      libs/flask/helpers.py
  12. 0
      libs/flask/logging.py
  13. 0
      libs/flask/module.py
  14. 0
      libs/flask/session.py
  15. 0
      libs/flask/sessions.py
  16. 1
      libs/flask/signals.py
  17. 8
      libs/flask/templating.py
  18. 0
      libs/flask/testing.py
  19. 2
      libs/flask/views.py
  20. 18
      libs/flask/wrappers.py
  21. 2
      libs/jinja2/__init__.py
  22. 0
      libs/jinja2/_debugsupport.c
  23. 0
      libs/jinja2/_markupsafe/__init__.py
  24. 0
      libs/jinja2/_markupsafe/_bundle.py
  25. 0
      libs/jinja2/_markupsafe/_constants.py
  26. 0
      libs/jinja2/_markupsafe/_native.py
  27. 0
      libs/jinja2/_markupsafe/tests.py
  28. 0
      libs/jinja2/_stringdefs.py
  29. 0
      libs/jinja2/bccache.py
  30. 0
      libs/jinja2/compiler.py
  31. 0
      libs/jinja2/constants.py
  32. 2
      libs/jinja2/debug.py
  33. 0
      libs/jinja2/defaults.py
  34. 10
      libs/jinja2/environment.py
  35. 2
      libs/jinja2/exceptions.py
  36. 10
      libs/jinja2/ext.py
  37. 63
      libs/jinja2/filters.py
  38. 8
      libs/jinja2/lexer.py
  39. 25
      libs/jinja2/loaders.py
  40. 0
      libs/jinja2/meta.py
  41. 0
      libs/jinja2/nodes.py
  42. 0
      libs/jinja2/optimizer.py
  43. 3
      libs/jinja2/parser.py
  44. 17
      libs/jinja2/runtime.py
  45. 0
      libs/jinja2/sandbox.py
  46. 0
      libs/jinja2/tests.py
  47. 0
      libs/jinja2/testsuite/__init__.py
  48. 0
      libs/jinja2/testsuite/api.py
  49. 0
      libs/jinja2/testsuite/core_tags.py
  50. 0
      libs/jinja2/testsuite/debug.py
  51. 0
      libs/jinja2/testsuite/doctests.py
  52. 0
      libs/jinja2/testsuite/ext.py
  53. 46
      libs/jinja2/testsuite/filters.py
  54. 0
      libs/jinja2/testsuite/imports.py
  55. 0
      libs/jinja2/testsuite/inheritance.py
  56. 8
      libs/jinja2/testsuite/lexnparse.py
  57. 28
      libs/jinja2/testsuite/loader.py
  58. 0
      libs/jinja2/testsuite/regression.py
  59. 0
      libs/jinja2/testsuite/res/__init__.py
  60. 0
      libs/jinja2/testsuite/res/templates/broken.html
  61. 0
      libs/jinja2/testsuite/res/templates/foo/test.html
  62. 0
      libs/jinja2/testsuite/res/templates/syntaxerror.html
  63. 0
      libs/jinja2/testsuite/res/templates/test.html
  64. 0
      libs/jinja2/testsuite/security.py
  65. 0
      libs/jinja2/testsuite/tests.py
  66. 0
      libs/jinja2/testsuite/utils.py
  67. 33
      libs/jinja2/utils.py
  68. 0
      libs/jinja2/visitor.py
  69. 2
      libs/werkzeug/__init__.py
  70. 0
      libs/werkzeug/_internal.py
  71. 0
      libs/werkzeug/contrib/__init__.py
  72. 0
      libs/werkzeug/contrib/atom.py
  73. 0
      libs/werkzeug/contrib/cache.py
  74. 0
      libs/werkzeug/contrib/fixers.py
  75. 0
      libs/werkzeug/contrib/iterio.py
  76. 0
      libs/werkzeug/contrib/jsrouting.py
  77. 0
      libs/werkzeug/contrib/kickstart.py
  78. 0
      libs/werkzeug/contrib/limiter.py
  79. 0
      libs/werkzeug/contrib/lint.py
  80. 0
      libs/werkzeug/contrib/profiler.py
  81. 17
      libs/werkzeug/contrib/securecookie.py
  82. 5
      libs/werkzeug/contrib/sessions.py
  83. 0
      libs/werkzeug/contrib/testtools.py
  84. 0
      libs/werkzeug/contrib/wrappers.py
  85. 2
      libs/werkzeug/datastructures.py
  86. 0
      libs/werkzeug/debug/__init__.py
  87. 0
      libs/werkzeug/debug/console.py
  88. 0
      libs/werkzeug/debug/repr.py
  89. 0
      libs/werkzeug/debug/shared/FONT_LICENSE
  90. 0
      libs/werkzeug/debug/shared/debugger.js
  91. 0
      libs/werkzeug/debug/shared/jquery.js
  92. 0
      libs/werkzeug/debug/shared/style.css
  93. 0
      libs/werkzeug/debug/shared/ubuntu.ttf
  94. 0
      libs/werkzeug/debug/tbtools.py
  95. 0
      libs/werkzeug/exceptions.py
  96. 0
      libs/werkzeug/formparser.py
  97. 0
      libs/werkzeug/http.py
  98. 0
      libs/werkzeug/local.py
  99. 0
      libs/werkzeug/posixemulation.py
  100. 7
      libs/werkzeug/routing.py

11
libs/flask/__init__.py

@ -10,7 +10,7 @@
:license: BSD, see LICENSE for more details.
"""
__version__ = '0.9-dev'
__version__ = '0.9'
# utilities we import from Werkzeug and Jinja2 that are unused
# in the module but are exported as public interface.
@ -22,9 +22,12 @@ from .app import Flask, Request, Response
from .config import Config
from .helpers import url_for, jsonify, json_available, flash, \
send_file, send_from_directory, get_flashed_messages, \
get_template_attribute, make_response, safe_join
from .globals import current_app, g, request, session, _request_ctx_stack
from .ctx import has_request_context
get_template_attribute, make_response, safe_join, \
stream_with_context
from .globals import current_app, g, request, session, _request_ctx_stack, \
_app_ctx_stack
from .ctx import has_request_context, has_app_context, \
after_this_request
from .module import Module
from .blueprints import Blueprint
from .templating import render_template, render_template_string

205
libs/flask/app.py

@ -19,7 +19,7 @@ from itertools import chain
from functools import update_wrapper
from werkzeug.datastructures import ImmutableDict
from werkzeug.routing import Map, Rule, RequestRedirect
from werkzeug.routing import Map, Rule, RequestRedirect, BuildError
from werkzeug.exceptions import HTTPException, InternalServerError, \
MethodNotAllowed, BadRequest
@ -28,14 +28,14 @@ from .helpers import _PackageBoundObject, url_for, get_flashed_messages, \
find_package
from .wrappers import Request, Response
from .config import ConfigAttribute, Config
from .ctx import RequestContext
from .ctx import RequestContext, AppContext, _RequestGlobals
from .globals import _request_ctx_stack, request
from .sessions import SecureCookieSessionInterface
from .module import blueprint_is_module
from .templating import DispatchingJinjaLoader, Environment, \
_default_template_ctx_processor
from .signals import request_started, request_finished, got_request_exception, \
request_tearing_down
request_tearing_down, appcontext_tearing_down
# a lock used for logger initialization
_logger_lock = Lock()
@ -148,6 +148,18 @@ class Flask(_PackageBoundObject):
#: :class:`~flask.Response` for more information.
response_class = Response
#: The class that is used for the :data:`~flask.g` instance.
#:
#: Example use cases for a custom class:
#:
#: 1. Store arbitrary attributes on flask.g.
#: 2. Add a property for lazy per-request database connectors.
#: 3. Return None instead of AttributeError on expected attributes.
#: 4. Raise exception if an unexpected attr is set, a "controlled" flask.g.
#:
#: .. versionadded:: 0.9
request_globals_class = _RequestGlobals
#: The debug flag. Set this to `True` to enable debugging of the
#: application. In debug mode the debugger will kick in when an unhandled
#: exception ocurrs and the integrated server will automatically reload
@ -249,8 +261,10 @@ class Flask(_PackageBoundObject):
'SESSION_COOKIE_HTTPONLY': True,
'SESSION_COOKIE_SECURE': False,
'MAX_CONTENT_LENGTH': None,
'SEND_FILE_MAX_AGE_DEFAULT': 12 * 60 * 60, # 12 hours
'TRAP_BAD_REQUEST_ERRORS': False,
'TRAP_HTTP_EXCEPTIONS': False
'TRAP_HTTP_EXCEPTIONS': False,
'PREFERRED_URL_SCHEME': 'http'
})
#: The rule object to use for URL rules created. This is used by
@ -327,6 +341,15 @@ class Flask(_PackageBoundObject):
#: decorator.
self.error_handler_spec = {None: self._error_handlers}
#: A list of functions that are called when :meth:`url_for` raises a
#: :exc:`~werkzeug.routing.BuildError`. Each function registered here
#: is called with `error`, `endpoint` and `values`. If a function
#: returns `None` or raises a `BuildError` the next function is
#: tried.
#:
#: .. versionadded:: 0.9
self.url_build_error_handlers = []
#: A dictionary with lists of functions that should be called at the
#: beginning of the request. The key of the dictionary is the name of
#: the blueprint this function is active for, `None` for all requests.
@ -362,6 +385,14 @@ class Flask(_PackageBoundObject):
#: .. versionadded:: 0.7
self.teardown_request_funcs = {}
#: A list of functions that are called when the application context
#: is destroyed. Since the application context is also torn down
#: if the request ends this is the place to store code that disconnects
#: from databases.
#:
#: .. versionadded:: 0.9
self.teardown_appcontext_funcs = []
#: A dictionary with lists of functions that can be used as URL
#: value processor functions. Whenever a URL is built these functions
#: are called to modify the dictionary of values in place. The key
@ -884,6 +915,10 @@ class Flask(_PackageBoundObject):
# a tuple of only `GET` as default.
if methods is None:
methods = getattr(view_func, 'methods', None) or ('GET',)
methods = set(methods)
# Methods that should always be added
required_methods = set(getattr(view_func, 'required_methods', ()))
# starting with Flask 0.8 the view_func object can disable and
# force-enable the automatic options handling.
@ -892,11 +927,14 @@ class Flask(_PackageBoundObject):
if provide_automatic_options is None:
if 'OPTIONS' not in methods:
methods = tuple(methods) + ('OPTIONS',)
provide_automatic_options = True
required_methods.add('OPTIONS')
else:
provide_automatic_options = False
# Add the required methods now.
methods |= required_methods
# due to a werkzeug bug we need to make sure that the defaults are
# None if they are an empty dictionary. This should not be necessary
# with Werkzeug 0.7
@ -1098,11 +1136,43 @@ class Flask(_PackageBoundObject):
that they will fail. If they do execute code that might fail they
will have to surround the execution of these code by try/except
statements and log ocurring errors.
When a teardown function was called because of a exception it will
be passed an error object.
"""
self.teardown_request_funcs.setdefault(None, []).append(f)
return f
@setupmethod
def teardown_appcontext(self, f):
"""Registers a function to be called when the application context
ends. These functions are typically also called when the request
context is popped.
Example::
ctx = app.app_context()
ctx.push()
...
ctx.pop()
When ``ctx.pop()`` is executed in the above example, the teardown
functions are called just before the app context moves from the
stack of active contexts. This becomes relevant if you are using
such constructs in tests.
Since a request context typically also manages an application
context it would also be called when you pop a request context.
When a teardown function was called because of an exception it will
be passed an error object.
.. versionadded:: 0.9
"""
self.teardown_appcontext_funcs.append(f)
return f
@setupmethod
def context_processor(self, f):
"""Registers a template context processor function."""
self.template_context_processors[None].append(f)
@ -1312,7 +1382,7 @@ class Flask(_PackageBoundObject):
def make_default_options_response(self):
"""This method is called to create the default `OPTIONS` response.
This can be changed through subclassing to change the default
behaviour of `OPTIONS` responses.
behavior of `OPTIONS` responses.
.. versionadded:: 0.7
"""
@ -1346,23 +1416,48 @@ class Flask(_PackageBoundObject):
string as body
:class:`unicode` a response object is created with the
string encoded to utf-8 as body
:class:`tuple` the response object is created with the
contents of the tuple as arguments
a WSGI function the function is called as WSGI application
and buffered as response object
:class:`tuple` A tuple in the form ``(response, status,
headers)`` where `response` is any of the
types defined here, `status` is a string
or an integer and `headers` is a list of
a dictionary with header values.
======================= ===========================================
:param rv: the return value from the view function
.. versionchanged:: 0.9
Previously a tuple was interpreted as the arguments for the
response object.
"""
status = headers = None
if isinstance(rv, tuple):
rv, status, headers = rv + (None,) * (3 - len(rv))
if rv is None:
raise ValueError('View function did not return a response')
if isinstance(rv, self.response_class):
return rv
if isinstance(rv, basestring):
return self.response_class(rv)
if isinstance(rv, tuple):
return self.response_class(*rv)
return self.response_class.force_type(rv, request.environ)
if not isinstance(rv, self.response_class):
# When we create a response object directly, we let the constructor
# set the headers and status. We do this because there can be
# some extra logic involved when creating these objects with
# specific values (like defualt content type selection).
if isinstance(rv, basestring):
rv = self.response_class(rv, headers=headers, status=status)
headers = status = None
else:
rv = self.response_class.force_type(rv, request.environ)
if status is not None:
if isinstance(status, basestring):
rv.status = status
else:
rv.status_code = status
if headers:
rv.headers.extend(headers)
return rv
def create_url_adapter(self, request):
"""Creates a URL adapter for the given request. The URL adapter
@ -1370,9 +1465,21 @@ class Flask(_PackageBoundObject):
so the request is passed explicitly.
.. versionadded:: 0.6
.. versionchanged:: 0.9
This can now also be called without a request object when the
UR adapter is created for the application context.
"""
return self.url_map.bind_to_environ(request.environ,
server_name=self.config['SERVER_NAME'])
if request is not None:
return self.url_map.bind_to_environ(request.environ,
server_name=self.config['SERVER_NAME'])
# We need at the very least the server name to be set for this
# to work.
if self.config['SERVER_NAME'] is not None:
return self.url_map.bind(
self.config['SERVER_NAME'],
script_name=self.config['APPLICATION_ROOT'] or '/',
url_scheme=self.config['PREFERRED_URL_SCHEME'])
def inject_url_defaults(self, endpoint, values):
"""Injects the URL defaults for the given endpoint directly into
@ -1383,11 +1490,30 @@ class Flask(_PackageBoundObject):
"""
funcs = self.url_default_functions.get(None, ())
if '.' in endpoint:
bp = endpoint.split('.', 1)[0]
bp = endpoint.rsplit('.', 1)[0]
funcs = chain(funcs, self.url_default_functions.get(bp, ()))
for func in funcs:
func(endpoint, values)
def handle_url_build_error(self, error, endpoint, values):
"""Handle :class:`~werkzeug.routing.BuildError` on :meth:`url_for`.
"""
exc_type, exc_value, tb = sys.exc_info()
for handler in self.url_build_error_handlers:
try:
rv = handler(error, endpoint, values)
if rv is not None:
return rv
except BuildError, error:
pass
# At this point we want to reraise the exception. If the error is
# still the same one we can reraise it with the original traceback,
# otherwise we raise it from here.
if error is exc_value:
raise exc_type, exc_value, tb
raise error
def preprocess_request(self):
"""Called before the actual request dispatching and will
call every as :meth:`before_request` decorated function.
@ -1429,7 +1555,7 @@ class Flask(_PackageBoundObject):
"""
ctx = _request_ctx_stack.top
bp = ctx.request.blueprint
funcs = ()
funcs = ctx._after_request_functions
if bp is not None and bp in self.after_request_funcs:
funcs = reversed(self.after_request_funcs[bp])
if None in self.after_request_funcs:
@ -1440,23 +1566,54 @@ class Flask(_PackageBoundObject):
self.save_session(ctx.session, response)
return response
def do_teardown_request(self):
def do_teardown_request(self, exc=None):
"""Called after the actual request dispatching and will
call every as :meth:`teardown_request` decorated function. This is
not actually called by the :class:`Flask` object itself but is always
triggered when the request context is popped. That way we have a
tighter control over certain resources under testing environments.
.. versionchanged:: 0.9
Added the `exc` argument. Previously this was always using the
current exception information.
"""
if exc is None:
exc = sys.exc_info()[1]
funcs = reversed(self.teardown_request_funcs.get(None, ()))
bp = _request_ctx_stack.top.request.blueprint
if bp is not None and bp in self.teardown_request_funcs:
funcs = chain(funcs, reversed(self.teardown_request_funcs[bp]))
exc = sys.exc_info()[1]
for func in funcs:
rv = func(exc)
if rv is not None:
return rv
request_tearing_down.send(self)
request_tearing_down.send(self, exc=exc)
def do_teardown_appcontext(self, exc=None):
"""Called when an application context is popped. This works pretty
much the same as :meth:`do_teardown_request` but for the application
context.
.. versionadded:: 0.9
"""
if exc is None:
exc = sys.exc_info()[1]
for func in reversed(self.teardown_appcontext_funcs):
func(exc)
appcontext_tearing_down.send(self, exc=exc)
def app_context(self):
"""Binds the application only. For as long as the application is bound
to the current context the :data:`flask.current_app` points to that
application. An application context is automatically created when a
request context is pushed if necessary.
Example usage::
with app.app_context():
...
.. versionadded:: 0.9
"""
return AppContext(self)
def request_context(self, environ):
"""Creates a :class:`~flask.ctx.RequestContext` from the given

2
libs/flask/blueprints.py

@ -25,7 +25,7 @@ class BlueprintSetupState(object):
#: a reference to the current application
self.app = app
#: a reference to the blurprint that created this setup state.
#: a reference to the blueprint that created this setup state.
self.blueprint = blueprint
#: a dictionary with all options that were passed to the

3
libs/flask/config.py

@ -106,8 +106,7 @@ class Config(dict):
'loaded. Set this variable and make it '
'point to a configuration file' %
variable_name)
self.from_pyfile(rv)
return True
return self.from_pyfile(rv, silent=silent)
def from_pyfile(self, filename, silent=False):
"""Updates the values in the config from a Python file. This function

132
libs/flask/ctx.py

@ -9,16 +9,44 @@
:license: BSD, see LICENSE for more details.
"""
import sys
from werkzeug.exceptions import HTTPException
from .globals import _request_ctx_stack
from .globals import _request_ctx_stack, _app_ctx_stack
from .module import blueprint_is_module
class _RequestGlobals(object):
"""A plain object."""
pass
def after_this_request(f):
"""Executes a function after this request. This is useful to modify
response objects. The function is passed the response object and has
to return the same or a new one.
Example::
@app.route('/')
def index():
@after_this_request
def add_header(response):
response.headers['X-Foo'] = 'Parachute'
return response
return 'Hello World!'
This is more useful if a function other than the view function wants to
modify a response. For instance think of a decorator that wants to add
some headers without converting the return value into a response object.
.. versionadded:: 0.9
"""
_request_ctx_stack.top._after_request_functions.append(f)
return f
def has_request_context():
"""If you have code that wants to test if a request context is there or
not this function can be used. For instance, you may want to take advantage
@ -51,6 +79,57 @@ def has_request_context():
return _request_ctx_stack.top is not None
def has_app_context():
"""Works like :func:`has_request_context` but for the application
context. You can also just do a boolean check on the
:data:`current_app` object instead.
.. versionadded:: 0.9
"""
return _app_ctx_stack.top is not None
class AppContext(object):
"""The application context binds an application object implicitly
to the current thread or greenlet, similar to how the
:class:`RequestContext` binds request information. The application
context is also implicitly created if a request context is created
but the application is not on top of the individual application
context.
"""
def __init__(self, app):
self.app = app
self.url_adapter = app.create_url_adapter(None)
# Like request context, app contexts can be pushed multiple times
# but there a basic "refcount" is enough to track them.
self._refcnt = 0
def push(self):
"""Binds the app context to the current context."""
self._refcnt += 1
_app_ctx_stack.push(self)
def pop(self, exc=None):
"""Pops the app context."""
self._refcnt -= 1
if self._refcnt <= 0:
if exc is None:
exc = sys.exc_info()[1]
self.app.do_teardown_appcontext(exc)
rv = _app_ctx_stack.pop()
assert rv is self, 'Popped wrong app context. (%r instead of %r)' \
% (rv, self)
def __enter__(self):
self.push()
return self
def __exit__(self, exc_type, exc_value, tb):
self.pop(exc_value)
class RequestContext(object):
"""The request context contains all request relevant information. It is
created at the beginning of the request and pushed to the
@ -85,17 +164,28 @@ class RequestContext(object):
self.app = app
self.request = app.request_class(environ)
self.url_adapter = app.create_url_adapter(self.request)
self.g = _RequestGlobals()
self.g = app.request_globals_class()
self.flashes = None
self.session = None
# Request contexts can be pushed multiple times and interleaved with
# other request contexts. Now only if the last level is popped we
# get rid of them. Additionally if an application context is missing
# one is created implicitly so for each level we add this information
self._implicit_app_ctx_stack = []
# indicator if the context was preserved. Next time another context
# is pushed the preserved context is popped.
self.preserved = False
# Functions that should be executed after the request on the response
# object. These will be called before the regular "after_request"
# functions.
self._after_request_functions = []
self.match_request()
# XXX: Support for deprecated functionality. This is doing away with
# XXX: Support for deprecated functionality. This is going away with
# Flask 1.0
blueprint = self.request.blueprint
if blueprint is not None:
@ -130,6 +220,16 @@ class RequestContext(object):
if top is not None and top.preserved:
top.pop()
# Before we push the request context we have to ensure that there
# is an application context.
app_ctx = _app_ctx_stack.top
if app_ctx is None or app_ctx.app != self.app:
app_ctx = self.app.app_context()
app_ctx.push()
self._implicit_app_ctx_stack.append(app_ctx)
else:
self._implicit_app_ctx_stack.append(None)
_request_ctx_stack.push(self)
# Open the session at the moment that the request context is
@ -139,20 +239,36 @@ class RequestContext(object):
if self.session is None:
self.session = self.app.make_null_session()
def pop(self):
def pop(self, exc=None):
"""Pops the request context and unbinds it by doing that. This will
also trigger the execution of functions registered by the
:meth:`~flask.Flask.teardown_request` decorator.
.. versionchanged:: 0.9
Added the `exc` argument.
"""
self.preserved = False
self.app.do_teardown_request()
app_ctx = self._implicit_app_ctx_stack.pop()
clear_request = False
if not self._implicit_app_ctx_stack:
self.preserved = False
if exc is None:
exc = sys.exc_info()[1]
self.app.do_teardown_request(exc)
clear_request = True
rv = _request_ctx_stack.pop()
assert rv is self, 'Popped wrong request context. (%r instead of %r)' \
% (rv, self)
# get rid of circular dependencies at the end of the request
# so that we don't require the GC to be active.
rv.request.environ['werkzeug.request'] = None
if clear_request:
rv.request.environ['werkzeug.request'] = None
# Get rid of the app as well if necessary.
if app_ctx is not None:
app_ctx.pop(exc)
def __enter__(self):
self.push()
@ -168,7 +284,7 @@ class RequestContext(object):
(tb is not None and self.app.preserve_context_on_exception):
self.preserved = True
else:
self.pop()
self.pop(exc_value)
def __repr__(self):
return '<%s \'%s\' [%s] of %s>' % (

0
libs/flask/debughelpers.py

49
libs/flask/exceptions.py

@ -0,0 +1,49 @@
# -*- coding: utf-8 -*-
"""
flask.exceptions
~~~~~~~~~~~~
Flask specific additions to :class:`~werkzeug.exceptions.HTTPException`
:copyright: (c) 2011 by Armin Ronacher.
:license: BSD, see LICENSE for more details.
"""
from werkzeug.exceptions import HTTPException, BadRequest
from .helpers import json
class JSONHTTPException(HTTPException):
"""A base class for HTTP exceptions with ``Content-Type:
application/json``.
The ``description`` attribute of this class must set to a string (*not* an
HTML string) which describes the error.
"""
def get_body(self, environ):
"""Overrides :meth:`werkzeug.exceptions.HTTPException.get_body` to
return the description of this error in JSON format instead of HTML.
"""
return json.dumps(dict(description=self.get_description(environ)))
def get_headers(self, environ):
"""Returns a list of headers including ``Content-Type:
application/json``.
"""
return [('Content-Type', 'application/json')]
class JSONBadRequest(JSONHTTPException, BadRequest):
"""Represents an HTTP ``400 Bad Request`` error whose body contains an
error message in JSON format instead of HTML format (as in the superclass).
"""
#: The description of the error which occurred as a string.
description = (
'The browser (or proxy) sent a request that this server could not '
'understand.'
)

0
libs/flask/ext/__init__.py

0
libs/flask/exthook.py

10
libs/flask/globals.py

@ -20,9 +20,17 @@ def _lookup_object(name):
return getattr(top, name)
def _find_app():
top = _app_ctx_stack.top
if top is None:
raise RuntimeError('working outside of application context')
return top.app
# context locals
_request_ctx_stack = LocalStack()
current_app = LocalProxy(partial(_lookup_object, 'app'))
_app_ctx_stack = LocalStack()
current_app = LocalProxy(_find_app)
request = LocalProxy(partial(_lookup_object, 'request'))
session = LocalProxy(partial(_lookup_object, 'session'))
g = LocalProxy(partial(_lookup_object, 'g'))

263
libs/flask/helpers.py

@ -11,7 +11,6 @@
from __future__ import with_statement
import imp
import os
import sys
import pkgutil
@ -20,7 +19,9 @@ import mimetypes
from time import time
from zlib import adler32
from threading import RLock
from werkzeug.routing import BuildError
from werkzeug.urls import url_quote
from functools import update_wrapper
# try to load the best simplejson implementation available. If JSON
# is not installed, we add a failing class.
@ -50,7 +51,8 @@ except ImportError:
from jinja2 import FileSystemLoader
from .globals import session, _request_ctx_stack, current_app, request
from .globals import session, _request_ctx_stack, _app_ctx_stack, \
current_app, request
def _assert_have_json():
@ -59,7 +61,7 @@ def _assert_have_json():
raise RuntimeError('simplejson not installed')
# figure out if simplejson escapes slashes. This behaviour was changed
# figure out if simplejson escapes slashes. This behavior was changed
# from one version to another without reason.
if not json_available or '\\/' not in json.dumps('/'):
@ -91,6 +93,78 @@ def _endpoint_from_view_func(view_func):
return view_func.__name__
def stream_with_context(generator_or_function):
"""Request contexts disappear when the response is started on the server.
This is done for efficiency reasons and to make it less likely to encounter
memory leaks with badly written WSGI middlewares. The downside is that if
you are using streamed responses, the generator cannot access request bound
information any more.
This function however can help you keep the context around for longer::
from flask import stream_with_context, request, Response
@app.route('/stream')
def streamed_response():
@stream_with_context
def generate():
yield 'Hello '
yield request.args['name']
yield '!'
return Response(generate())
Alternatively it can also be used around a specific generator:
from flask import stream_with_context, request, Response
@app.route('/stream')
def streamed_response():
def generate():
yield 'Hello '
yield request.args['name']
yield '!'
return Response(stream_with_context(generate()))
.. versionadded:: 0.9
"""
try:
gen = iter(generator_or_function)
except TypeError:
def decorator(*args, **kwargs):
gen = generator_or_function()
return stream_with_context(gen)
return update_wrapper(decorator, generator_or_function)
def generator():
ctx = _request_ctx_stack.top
if ctx is None:
raise RuntimeError('Attempted to stream with context but '
'there was no context in the first place to keep around.')
with ctx:
# Dummy sentinel. Has to be inside the context block or we're
# not actually keeping the context around.
yield None
# The try/finally is here so that if someone passes a WSGI level
# iterator in we're still running the cleanup logic. Generators
# don't need that because they are closed on their destruction
# automatically.
try:
for item in gen:
yield item
finally:
if hasattr(gen, 'close'):
gen.close()
# The trick is to start the generator. Then the code execution runs until
# the first dummy None is yielded at which point the context was already
# pushed. This item is discarded. Then when the iteration continues the
# real generator is executed.
wrapped_g = generator()
wrapped_g.next()
return wrapped_g
def jsonify(*args, **kwargs):
"""Creates a :class:`~flask.Response` with the JSON representation of
the given arguments with an `application/json` mimetype. The arguments
@ -188,36 +262,106 @@ def url_for(endpoint, **values):
For more information, head over to the :ref:`Quickstart <url-building>`.
To integrate applications, :class:`Flask` has a hook to intercept URL build
errors through :attr:`Flask.build_error_handler`. The `url_for` function
results in a :exc:`~werkzeug.routing.BuildError` when the current app does
not have a URL for the given endpoint and values. When it does, the
:data:`~flask.current_app` calls its :attr:`~Flask.build_error_handler` if
it is not `None`, which can return a string to use as the result of
`url_for` (instead of `url_for`'s default to raise the
:exc:`~werkzeug.routing.BuildError` exception) or re-raise the exception.
An example::
def external_url_handler(error, endpoint, **values):
"Looks up an external URL when `url_for` cannot build a URL."
# This is an example of hooking the build_error_handler.
# Here, lookup_url is some utility function you've built
# which looks up the endpoint in some external URL registry.
url = lookup_url(endpoint, **values)
if url is None:
# External lookup did not have a URL.
# Re-raise the BuildError, in context of original traceback.
exc_type, exc_value, tb = sys.exc_info()
if exc_value is error:
raise exc_type, exc_value, tb
else:
raise error
# url_for will use this result, instead of raising BuildError.
return url
app.build_error_handler = external_url_handler
Here, `error` is the instance of :exc:`~werkzeug.routing.BuildError`, and
`endpoint` and `**values` are the arguments passed into `url_for`. Note
that this is for building URLs outside the current application, and not for
handling 404 NotFound errors.
.. versionadded:: 0.9
The `_anchor` and `_method` parameters were added.
.. versionadded:: 0.9
Calls :meth:`Flask.handle_build_error` on
:exc:`~werkzeug.routing.BuildError`.
:param endpoint: the endpoint of the URL (name of the function)
:param values: the variable arguments of the URL rule
:param _external: if set to `True`, an absolute URL is generated.
:param _anchor: if provided this is added as anchor to the URL.
:param _method: if provided this explicitly specifies an HTTP method.
"""
ctx = _request_ctx_stack.top
blueprint_name = request.blueprint
if not ctx.request._is_old_module:
if endpoint[:1] == '.':
if blueprint_name is not None:
endpoint = blueprint_name + endpoint
else:
appctx = _app_ctx_stack.top
reqctx = _request_ctx_stack.top
if appctx is None:
raise RuntimeError('Attempted to generate a URL with the application '
'context being pushed. This has to be executed ')
# If request specific information is available we have some extra
# features that support "relative" urls.
if reqctx is not None:
url_adapter = reqctx.url_adapter
blueprint_name = request.blueprint
if not reqctx.request._is_old_module:
if endpoint[:1] == '.':
if blueprint_name is not None:
endpoint = blueprint_name + endpoint
else:
endpoint = endpoint[1:]
else:
# TODO: get rid of this deprecated functionality in 1.0
if '.' not in endpoint:
if blueprint_name is not None:
endpoint = blueprint_name + '.' + endpoint
elif endpoint.startswith('.'):
endpoint = endpoint[1:]
external = values.pop('_external', False)
# Otherwise go with the url adapter from the appctx and make
# the urls external by default.
else:
# TODO: get rid of this deprecated functionality in 1.0
if '.' not in endpoint:
if blueprint_name is not None:
endpoint = blueprint_name + '.' + endpoint
elif endpoint.startswith('.'):
endpoint = endpoint[1:]
external = values.pop('_external', False)
url_adapter = appctx.url_adapter
if url_adapter is None:
raise RuntimeError('Application was not able to create a URL '
'adapter for request independent URL generation. '
'You might be able to fix this by setting '
'the SERVER_NAME config variable.')
external = values.pop('_external', True)
anchor = values.pop('_anchor', None)
method = values.pop('_method', None)
ctx.app.inject_url_defaults(endpoint, values)
rv = ctx.url_adapter.build(endpoint, values, method=method,
appctx.app.inject_url_defaults(endpoint, values)
try:
rv = url_adapter.build(endpoint, values, method=method,
force_external=external)
except BuildError, error:
# We need to inject the values again so that the app callback can
# deal with that sort of stuff.
values['_external'] = external
values['_anchor'] = anchor
values['_method'] = method
return appctx.app.handle_url_build_error(error, endpoint, values)
rv = url_adapter.build(endpoint, values, method=method,
force_external=external)
if anchor is not None:
rv += '#' + url_quote(anchor)
return rv
@ -261,7 +405,16 @@ def flash(message, category='message'):
messages and ``'warning'`` for warnings. However any
kind of string can be used as category.
"""
session.setdefault('_flashes', []).append((category, message))
# Original implementation:
#
# session.setdefault('_flashes', []).append((category, message))
#
# This assumed that changes made to mutable structures in the session are
# are always in sync with the sess on object, which is not true for session
# implementations that use external storage for keeping their keys/values.
flashes = session.get('_flashes', [])
flashes.append((category, message))
session['_flashes'] = flashes
def get_flashed_messages(with_categories=False, category_filter=[]):
@ -305,7 +458,7 @@ def get_flashed_messages(with_categories=False, category_filter=[]):
def send_file(filename_or_fp, mimetype=None, as_attachment=False,
attachment_filename=None, add_etags=True,
cache_timeout=60 * 60 * 12, conditional=False):
cache_timeout=None, conditional=False):
"""Sends the contents of a file to the client. This will use the
most efficient method available and configured. By default it will
try to use the WSGI server's file_wrapper support. Alternatively
@ -330,7 +483,7 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
.. versionadded:: 0.5
The `add_etags`, `cache_timeout` and `conditional` parameters were
added. The default behaviour is now to attach etags.
added. The default behavior is now to attach etags.
.. versionchanged:: 0.7
mimetype guessing and etag support for file objects was
@ -338,6 +491,9 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
able to, otherwise attach an etag yourself. This functionality
will be removed in Flask 1.0
.. versionchanged:: 0.9
cache_timeout pulls its default from application config, when None.
:param filename_or_fp: the filename of the file to send. This is
relative to the :attr:`~Flask.root_path` if a
relative path is specified.
@ -354,7 +510,11 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
differs from the file's filename.
:param add_etags: set to `False` to disable attaching of etags.
:param conditional: set to `True` to enable conditional responses.
:param cache_timeout: the timeout in seconds for the headers.
:param cache_timeout: the timeout in seconds for the headers. When `None`
(default), this value is set by
:meth:`~Flask.get_send_file_max_age` of
:data:`~flask.current_app`.
"""
mtime = None
if isinstance(filename_or_fp, basestring):
@ -365,7 +525,7 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
file = filename_or_fp
filename = getattr(file, 'name', None)
# XXX: this behaviour is now deprecated because it was unreliable.
# XXX: this behavior is now deprecated because it was unreliable.
# removed in Flask 1.0
if not attachment_filename and not mimetype \
and isinstance(filename, basestring):
@ -376,7 +536,7 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
if add_etags:
warn(DeprecationWarning('In future flask releases etags will no '
'longer be generated for file objects passed to the send_file '
'function because this behaviour was unreliable. Pass '
'function because this behavior was unreliable. Pass '
'filenames instead if possible, otherwise attach an etag '
'yourself based on another value'), stacklevel=2)
@ -418,7 +578,9 @@ def send_file(filename_or_fp, mimetype=None, as_attachment=False,
rv.last_modified = int(mtime)
rv.cache_control.public = True
if cache_timeout:
if cache_timeout is None:
cache_timeout = current_app.get_send_file_max_age(filename)
if cache_timeout is not None:
rv.cache_control.max_age = cache_timeout
rv.expires = int(time() + cache_timeout)
@ -495,7 +657,8 @@ def send_from_directory(directory, filename, **options):
filename = safe_join(directory, filename)
if not os.path.isfile(filename):
raise NotFound()
return send_file(filename, conditional=True, **options)
options.setdefault('conditional', True)
return send_file(filename, **options)
def get_root_path(import_name):
@ -504,17 +667,29 @@ def get_root_path(import_name):
Not to be confused with the package path returned by :func:`find_package`.
"""
# Module already imported and has a file attribute. Use that first.
mod = sys.modules.get(import_name)
if mod is not None and hasattr(mod, '__file__'):
return os.path.dirname(os.path.abspath(mod.__file__))
# Next attempt: check the loader.
loader = pkgutil.get_loader(import_name)
# Loader does not exist or we're referring to an unloaded main module
# or a main module without path (interactive sessions), go with the
# current working directory.
if loader is None or import_name == '__main__':
# import name is not found, or interactive/main module
return os.getcwd()
# For .egg, zipimporter does not have get_filename until Python 2.7.
# Some other loaders might exhibit the same behavior.
if hasattr(loader, 'get_filename'):
filepath = loader.get_filename(import_name)
else:
# Fall back to imports.
__import__(import_name)
filepath = sys.modules[import_name].__file__
# filepath is import_name.py for a module, or __init__.py for a package.
return os.path.dirname(os.path.abspath(filepath))
@ -651,6 +826,32 @@ class _PackageBoundObject(object):
return FileSystemLoader(os.path.join(self.root_path,
self.template_folder))
def get_send_file_max_age(self, filename):
"""Provides default cache_timeout for the :func:`send_file` functions.
By default, this function returns ``SEND_FILE_MAX_AGE_DEFAULT`` from
the configuration of :data:`~flask.current_app`.
Static file functions such as :func:`send_from_directory` use this
function, and :func:`send_file` calls this function on
:data:`~flask.current_app` when the given cache_timeout is `None`. If a
cache_timeout is given in :func:`send_file`, that timeout is used;
otherwise, this method is called.
This allows subclasses to change the behavior when sending files based
on the filename. For example, to set the cache timeout for .js files
to 60 seconds::
class MyFlask(flask.Flask):
def get_send_file_max_age(self, name):
if name.lower().endswith('.js'):
return 60
return flask.Flask.get_send_file_max_age(self, name)
.. versionadded:: 0.9
"""
return current_app.config['SEND_FILE_MAX_AGE_DEFAULT']
def send_static_file(self, filename):
"""Function used internally to send static files from the static
folder to the browser.
@ -659,7 +860,11 @@ class _PackageBoundObject(object):
"""
if not self.has_static_folder:
raise RuntimeError('No static folder for this object')
return send_from_directory(self.static_folder, filename)
# Ensure get_send_file_max_age is called in all cases.
# Here, we ensure get_send_file_max_age is called for Blueprints.
cache_timeout = self.get_send_file_max_age(filename)
return send_from_directory(self.static_folder, filename,
cache_timeout=cache_timeout)
def open_resource(self, resource, mode='rb'):
"""Opens a resource from the application's resource folder. To see

0
libs/flask/logging.py

0
libs/flask/module.py

0
libs/flask/session.py

0
libs/flask/sessions.py

1
libs/flask/signals.py

@ -49,3 +49,4 @@ request_started = _signals.signal('request-started')
request_finished = _signals.signal('request-finished')
request_tearing_down = _signals.signal('request-tearing-down')
got_request_exception = _signals.signal('got-request-exception')
appcontext_tearing_down = _signals.signal('appcontext-tearing-down')

8
libs/flask/templating.py

@ -109,17 +109,19 @@ def _render(template, context, app):
return rv
def render_template(template_name, **context):
def render_template(template_name_or_list, **context):
"""Renders a template from the template folder with the given
context.
:param template_name: the name of the template to be rendered
:param template_name_or_list: the name of the template to be
rendered, or an iterable with template names
the first one existing will be rendered
:param context: the variables that should be available in the
context of the template.
"""
ctx = _request_ctx_stack.top
ctx.app.update_template_context(context)
return _render(ctx.app.jinja_env.get_template(template_name),
return _render(ctx.app.jinja_env.get_or_select_template(template_name_or_list),
context, ctx.app)

0
libs/flask/testing.py

2
libs/flask/views.py

@ -107,7 +107,7 @@ class MethodViewType(type):
rv = type.__new__(cls, name, bases, d)
if 'methods' not in d:
methods = set(rv.methods or [])
for key, value in d.iteritems():
for key in d:
if key in http_method_funcs:
methods.add(key.upper())
# if we have no method at all in there we don't want to

18
libs/flask/wrappers.py

@ -10,9 +10,9 @@
"""
from werkzeug.wrappers import Request as RequestBase, Response as ResponseBase
from werkzeug.exceptions import BadRequest
from werkzeug.utils import cached_property
from .exceptions import JSONBadRequest
from .debughelpers import attach_enctype_error_multidict
from .helpers import json, _assert_have_json
from .globals import _request_ctx_stack
@ -108,12 +108,22 @@ class Request(RequestBase):
def on_json_loading_failed(self, e):
"""Called if decoding of the JSON data failed. The return value of
this method is used by :attr:`json` when an error ocurred. The
default implementation raises a :class:`~werkzeug.exceptions.BadRequest`.
this method is used by :attr:`json` when an error ocurred. The default
implementation raises a :class:`JSONBadRequest`, which is a subclass of
:class:`~werkzeug.exceptions.BadRequest` which sets the
``Content-Type`` to ``application/json`` and provides a JSON-formatted
error description::
{"description": "The browser (or proxy) sent a request that \
this server could not understand."}
.. versionchanged:: 0.9
Return a :class:`JSONBadRequest` instead of a
:class:`~werkzeug.exceptions.BadRequest` by default.
.. versionadded:: 0.8
"""
raise BadRequest()
raise JSONBadRequest()
def _load_form_data(self):
RequestBase._load_form_data(self)

2
libs/jinja2/__init__.py

@ -27,7 +27,7 @@
:license: BSD, see LICENSE for more details.
"""
__docformat__ = 'restructuredtext en'
__version__ = '2.7-dev'
__version__ = '2.6'
# high level interface
from jinja2.environment import Environment, Template

0
libs/jinja2/_debugsupport.c

0
libs/jinja2/_markupsafe/__init__.py

0
libs/jinja2/_markupsafe/_bundle.py

0
libs/jinja2/_markupsafe/_constants.py

0
libs/jinja2/_markupsafe/_native.py

0
libs/jinja2/_markupsafe/tests.py

0
libs/jinja2/_stringdefs.py

0
libs/jinja2/bccache.py

0
libs/jinja2/compiler.py

0
libs/jinja2/constants.py

2
libs/jinja2/debug.py

@ -77,7 +77,7 @@ def make_frame_proxy(frame):
class ProcessedTraceback(object):
"""Holds a Jinja preprocessed traceback for printing or reraising."""
"""Holds a Jinja preprocessed traceback for priting or reraising."""
def __init__(self, exc_type, exc_value, frames):
assert frames, 'no frames for this traceback?'

0
libs/jinja2/defaults.py

10
libs/jinja2/environment.py

@ -67,7 +67,7 @@ def copy_cache(cache):
def load_extensions(environment, extensions):
"""Load the extensions from the list and bind it to the environment.
Returns a dict of instantiated environments.
Returns a dict of instanciated environments.
"""
result = {}
for extension in extensions:
@ -239,7 +239,7 @@ class Environment(object):
# passed by keyword rather than position. However it's important to
# not change the order of arguments because it's used at least
# internally in those cases:
# - spontaneous environments (i18n extension and Template)
# - spontaneus environments (i18n extension and Template)
# - unittests
# If parameter changes are required only add parameters at the end
# and don't change the arguments (or the defaults!) of the arguments
@ -435,7 +435,7 @@ class Environment(object):
return stream
def _generate(self, source, name, filename, defer_init=False):
"""Internal hook that can be overridden to hook a different generate
"""Internal hook that can be overriden to hook a different generate
method in.
.. versionadded:: 2.5
@ -443,7 +443,7 @@ class Environment(object):
return generate(source, self, name, filename, defer_init=defer_init)
def _compile(self, source, filename):
"""Internal hook that can be overridden to hook a different compile
"""Internal hook that can be overriden to hook a different compile
method in.
.. versionadded:: 2.5
@ -1053,7 +1053,7 @@ class TemplateStream(object):
def dump(self, fp, encoding=None, errors='strict'):
"""Dump the complete stream into a file or file-like object.
Per default unicode strings are written, if you want to encode
before writing specify an `encoding`.
before writing specifiy an `encoding`.
Example usage::

2
libs/jinja2/exceptions.py

@ -62,7 +62,7 @@ class TemplatesNotFound(TemplateNotFound):
def __init__(self, names=(), message=None):
if message is None:
message = u'none of the templates given were found: ' + \
message = u'non of the templates given were found: ' + \
u', '.join(map(unicode, names))
TemplateNotFound.__init__(self, names and names[-1] or None, message)
self.templates = list(names)

10
libs/jinja2/ext.py

@ -552,10 +552,6 @@ def babel_extract(fileobj, keywords, comment_tags, options):
The `newstyle_gettext` flag can be set to `True` to enable newstyle
gettext calls.
.. versionchanged:: 2.7
A `silent` option can now be provided. If set to `False` template
syntax errors are propagated instead of being ignored.
:param fileobj: the file-like object the messages should be extracted from
:param keywords: a list of keywords (i.e. function names) that should be
recognized as translation functions
@ -575,10 +571,8 @@ def babel_extract(fileobj, keywords, comment_tags, options):
extensions.add(InternationalizationExtension)
def getbool(options, key, default=False):
return options.get(key, str(default)).lower() in \
('1', 'on', 'yes', 'true')
options.get(key, str(default)).lower() in ('1', 'on', 'yes', 'true')
silent = getbool(options, 'silent', True)
environment = Environment(
options.get('block_start_string', BLOCK_START_STRING),
options.get('block_end_string', BLOCK_END_STRING),
@ -602,8 +596,6 @@ def babel_extract(fileobj, keywords, comment_tags, options):
node = environment.parse(source)
tokens = list(environment.lex(environment.preprocess(source)))
except TemplateSyntaxError, e:
if not silent:
raise
# skip templates with syntax errors
return

63
libs/jinja2/filters.py

@ -13,10 +13,9 @@ import math
from random import choice
from operator import itemgetter
from itertools import imap, groupby
from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode, \
unicode_urlencode
from jinja2.utils import Markup, escape, pformat, urlize, soft_unicode
from jinja2.runtime import Undefined
from jinja2.exceptions import FilterArgumentError
from jinja2.exceptions import FilterArgumentError, SecurityError
_word_re = re.compile(r'\w+(?u)')
@ -71,26 +70,6 @@ def do_forceescape(value):
return escape(unicode(value))
def do_urlencode(value):
"""Escape strings for use in URLs (uses UTF-8 encoding). It accepts both
dictionaries and regular strings as well as pairwise iterables.
.. versionadded:: 2.7
"""
itemiter = None
if isinstance(value, dict):
itemiter = value.iteritems()
elif not isinstance(value, basestring):
try:
itemiter = iter(value)
except TypeError:
pass
if itemiter is None:
return unicode_urlencode(value)
return u'&'.join(unicode_urlencode(k) + '=' +
unicode_urlencode(v) for k, v in itemiter)
@evalcontextfilter
def do_replace(eval_ctx, s, old, new, count=None):
"""Return a copy of the value with all occurrences of a substring
@ -176,12 +155,7 @@ def do_title(s):
"""Return a titlecased version of the value. I.e. words will start with
uppercase letters, all remaining characters are lowercase.
"""
rv = []
for item in re.compile(r'([-\s]+)(?u)').split(s):
if not item:
continue
rv.append(item[0].upper() + item[1:])
return ''.join(rv)
return soft_unicode(s).title()
def do_dictsort(value, case_sensitive=False, by='key'):
@ -372,25 +346,25 @@ def do_filesizeformat(value, binary=False):
bytes = float(value)
base = binary and 1024 or 1000
prefixes = [
(binary and 'KiB' or 'kB'),
(binary and 'MiB' or 'MB'),
(binary and 'GiB' or 'GB'),
(binary and 'TiB' or 'TB'),
(binary and 'PiB' or 'PB'),
(binary and 'EiB' or 'EB'),
(binary and 'ZiB' or 'ZB'),
(binary and 'YiB' or 'YB')
(binary and "KiB" or "kB"),
(binary and "MiB" or "MB"),
(binary and "GiB" or "GB"),
(binary and "TiB" or "TB"),
(binary and "PiB" or "PB"),
(binary and "EiB" or "EB"),
(binary and "ZiB" or "ZB"),
(binary and "YiB" or "YB")
]
if bytes == 1:
return '1 Byte'
return "1 Byte"
elif bytes < base:
return '%d Bytes' % bytes
return "%d Bytes" % bytes
else:
for i, prefix in enumerate(prefixes):
unit = base ** (i + 2)
unit = base * base ** (i + 1)
if bytes < unit:
return '%.1f %s' % ((base * bytes / unit), prefix)
return '%.1f %s' % ((base * bytes / unit), prefix)
return "%.1f %s" % ((bytes / unit), prefix)
return "%.1f %s" % ((bytes / unit), prefix)
def do_pprint(value, verbose=False):
@ -583,7 +557,7 @@ def do_batch(value, linecount, fill_with=None):
A filter that batches items. It works pretty much like `slice`
just the other way round. It returns a list of lists with the
given number of items. If you provide a second parameter this
is used to fill up missing items. See this example:
is used to fill missing items. See this example:
.. sourcecode:: html+jinja
@ -823,6 +797,5 @@ FILTERS = {
'round': do_round,
'groupby': do_groupby,
'safe': do_mark_safe,
'xmlattr': do_xmlattr,
'urlencode': do_urlencode
'xmlattr': do_xmlattr
}

8
libs/jinja2/lexer.py

@ -414,7 +414,7 @@ class Lexer(object):
(operator_re, TOKEN_OPERATOR, None)
]
# assemble the root lexing rule. because "|" is ungreedy
# assamble the root lexing rule. because "|" is ungreedy
# we have to sort by length so that the lexer continues working
# as expected when we have parsing rules like <% for block and
# <%= for variables. (if someone wants asp like syntax)
@ -491,7 +491,7 @@ class Lexer(object):
}
def _normalize_newlines(self, value):
"""Called for strings and template data to normalize it to unicode."""
"""Called for strings and template data to normlize it to unicode."""
return newline_re.sub(self.newline_sequence, value)
def tokenize(self, source, name=None, filename=None, state=None):
@ -571,7 +571,7 @@ class Lexer(object):
if m is None:
continue
# we only match blocks and variables if braces / parentheses
# we only match blocks and variables if brances / parentheses
# are balanced. continue parsing with the lower rule which
# is the operator rule. do this only if the end tags look
# like operators
@ -669,7 +669,7 @@ class Lexer(object):
# publish new function and start again
pos = pos2
break
# if loop terminated without break we haven't found a single match
# if loop terminated without break we havn't found a single match
# either we are at the end of the file or we have a problem
else:
# end of text

25
libs/jinja2/loaders.py

@ -330,16 +330,12 @@ class PrefixLoader(BaseLoader):
self.mapping = mapping
self.delimiter = delimiter
def get_loader(self, template):
def get_source(self, environment, template):
try:
prefix, name = template.split(self.delimiter, 1)
loader = self.mapping[prefix]
except (ValueError, KeyError):
raise TemplateNotFound(template)
return loader, name
def get_source(self, environment, template):
loader, name = self.get_loader(template)
try:
return loader.get_source(environment, name)
except TemplateNotFound:
@ -347,16 +343,6 @@ class PrefixLoader(BaseLoader):
# (the one that includes the prefix)
raise TemplateNotFound(template)
@internalcode
def load(self, environment, name, globals=None):
loader, local_name = self.get_loader(name)
try:
return loader.load(environment, local_name)
except TemplateNotFound:
# re-raise the exception with the correct fileame here.
# (the one that includes the prefix)
raise TemplateNotFound(name)
def list_templates(self):
result = []
for prefix, loader in self.mapping.iteritems():
@ -390,15 +376,6 @@ class ChoiceLoader(BaseLoader):
pass
raise TemplateNotFound(template)
@internalcode
def load(self, environment, name, globals=None):
for loader in self.loaders:
try:
return loader.load(environment, name, globals)
except TemplateNotFound:
pass
raise TemplateNotFound(name)
def list_templates(self):
found = set()
for loader in self.loaders:

0
libs/jinja2/meta.py

0
libs/jinja2/nodes.py

0
libs/jinja2/optimizer.py

3
libs/jinja2/parser.py

@ -223,7 +223,7 @@ class Parser(object):
# raise a nicer error message in that case.
if self.stream.current.type == 'sub':
self.fail('Block names in Jinja have to be valid Python '
'identifiers and may not contain hyphens, use an '
'identifiers and may not contain hypens, use an '
'underscore instead.')
node.body = self.parse_statements(('name:endblock',), drop_needle=True)
@ -698,6 +698,7 @@ class Parser(object):
arg = nodes.Const(attr_token.value, lineno=attr_token.lineno)
return nodes.Getitem(node, arg, 'load', lineno=token.lineno)
if token.type == 'lbracket':
priority_on_attribute = False
args = []
while self.stream.current.type != 'rbracket':
if args:

17
libs/jinja2/runtime.py

@ -30,8 +30,6 @@ to_string = unicode
#: the identity function. Useful for certain things in the environment
identity = lambda x: x
_last_iteration = object()
def markup_join(seq):
"""Concatenation that escapes if necessary and converts to unicode."""
@ -272,7 +270,6 @@ class LoopContext(object):
def __init__(self, iterable, recurse=None):
self._iterator = iter(iterable)
self._recurse = recurse
self._after = self._safe_next()
self.index0 = -1
# try to get the length of the iterable early. This must be done
@ -291,7 +288,7 @@ class LoopContext(object):
return args[self.index0 % len(args)]
first = property(lambda x: x.index0 == 0)
last = property(lambda x: x._after is _last_iteration)
last = property(lambda x: x.index0 + 1 == x.length)
index = property(lambda x: x.index0 + 1)
revindex = property(lambda x: x.length - x.index0)
revindex0 = property(lambda x: x.length - x.index)
@ -302,12 +299,6 @@ class LoopContext(object):
def __iter__(self):
return LoopContextIterator(self)
def _safe_next(self):
try:
return next(self._iterator)
except StopIteration:
return _last_iteration
@internalcode
def loop(self, iterable):
if self._recurse is None:
@ -353,11 +344,7 @@ class LoopContextIterator(object):
def next(self):
ctx = self.context
ctx.index0 += 1
if ctx._after is _last_iteration:
raise StopIteration()
next_elem = ctx._after
ctx._after = ctx._safe_next()
return next_elem, ctx
return next(ctx._iterator), ctx
class Macro(object):

0
libs/jinja2/sandbox.py

0
libs/jinja2/tests.py

0
libs/jinja2/testsuite/__init__.py

0
libs/jinja2/testsuite/api.py

0
libs/jinja2/testsuite/core_tags.py

0
libs/jinja2/testsuite/debug.py

0
libs/jinja2/testsuite/doctests.py

0
libs/jinja2/testsuite/ext.py

46
libs/jinja2/testsuite/filters.py

@ -84,28 +84,10 @@ class FilterTestCase(JinjaTestCase):
'{{ 1000000000000|filesizeformat(true) }}'
)
out = tmpl.render()
self.assert_equal(out, (
'100 Bytes|1.0 kB|1.0 MB|1.0 GB|1.0 TB|100 Bytes|'
'1000 Bytes|976.6 KiB|953.7 MiB|931.3 GiB'
))
def test_filesizeformat_issue59(self):
tmpl = env.from_string(
'{{ 300|filesizeformat }}|'
'{{ 3000|filesizeformat }}|'
'{{ 3000000|filesizeformat }}|'
'{{ 3000000000|filesizeformat }}|'
'{{ 3000000000000|filesizeformat }}|'
'{{ 300|filesizeformat(true) }}|'
'{{ 3000|filesizeformat(true) }}|'
'{{ 3000000|filesizeformat(true) }}'
assert out == (
'100 Bytes|0.0 kB|0.0 MB|0.0 GB|0.0 TB|100 Bytes|'
'1000 Bytes|1.0 KiB|0.9 MiB|0.9 GiB'
)
out = tmpl.render()
self.assert_equal(out, (
'300 Bytes|3.0 kB|3.0 MB|3.0 GB|3.0 TB|300 Bytes|'
'2.9 KiB|2.9 MiB'
))
def test_first(self):
tmpl = env.from_string('{{ foo|first }}')
@ -193,16 +175,6 @@ class FilterTestCase(JinjaTestCase):
def test_title(self):
tmpl = env.from_string('''{{ "foo bar"|title }}''')
assert tmpl.render() == "Foo Bar"
tmpl = env.from_string('''{{ "foo's bar"|title }}''')
assert tmpl.render() == "Foo's Bar"
tmpl = env.from_string('''{{ "foo bar"|title }}''')
assert tmpl.render() == "Foo Bar"
tmpl = env.from_string('''{{ "f bar f"|title }}''')
assert tmpl.render() == "F Bar F"
tmpl = env.from_string('''{{ "foo-bar"|title }}''')
assert tmpl.render() == "Foo-Bar"
tmpl = env.from_string('''{{ "foo\tbar"|title }}''')
assert tmpl.render() == "Foo\tBar"
def test_truncate(self):
tmpl = env.from_string(
@ -377,18 +349,6 @@ class FilterTestCase(JinjaTestCase):
tmpl = env.from_string('{{ "<div>foo</div>" }}')
assert tmpl.render() == '&lt;div&gt;foo&lt;/div&gt;'
def test_urlencode(self):
env = Environment(autoescape=True)
tmpl = env.from_string('{{ "Hello, world!"|urlencode }}')
assert tmpl.render() == 'Hello%2C%20world%21'
tmpl = env.from_string('{{ o|urlencode }}')
assert tmpl.render(o=u"Hello, world\u203d") == "Hello%2C%20world%E2%80%BD"
assert tmpl.render(o=(("f", 1),)) == "f=1"
assert tmpl.render(o=(('f', 1), ("z", 2))) == "f=1&amp;z=2"
assert tmpl.render(o=((u"\u203d", 1),)) == "%E2%80%BD=1"
assert tmpl.render(o={u"\u203d": 1}) == "%E2%80%BD=1"
assert tmpl.render(o={0: 1}) == "0=1"
def suite():
suite = unittest.TestSuite()

0
libs/jinja2/testsuite/imports.py

0
libs/jinja2/testsuite/inheritance.py

8
libs/jinja2/testsuite/lexnparse.py

@ -169,7 +169,7 @@ and bar comment #}
except TemplateSyntaxError, e:
assert str(e) == expected, 'unexpected error message'
else:
assert False, 'that was supposed to be an error'
assert False, 'that was suposed to be an error'
assert_error('{% for item in seq %}...{% endif %}',
"Encountered unknown tag 'endif'. Jinja was looking "
@ -189,7 +189,7 @@ and bar comment #}
"that needs to be closed is 'for'.")
assert_error('{% block foo-bar-baz %}',
"Block names in Jinja have to be valid Python identifiers "
"and may not contain hyphens, use an underscore instead.")
"and may not contain hypens, use an underscore instead.")
assert_error('{% unknown_tag %}',
"Encountered unknown tag 'unknown_tag'.")
@ -317,7 +317,7 @@ class SyntaxTestCase(JinjaTestCase):
self.assert_raises(TemplateSyntaxError, env.from_string,
'{% block x %}{% endblock y %}')
def test_constant_casing(self):
def test_contant_casing(self):
for const in True, False, None:
tmpl = env.from_string('{{ %s }}|{{ %s }}|{{ %s }}' % (
str(const), str(const).lower(), str(const).upper()
@ -327,7 +327,7 @@ class SyntaxTestCase(JinjaTestCase):
def test_test_chaining(self):
self.assert_raises(TemplateSyntaxError, env.from_string,
'{{ foo is string is sequence }}')
assert env.from_string('{{ 42 is string or 42 is number }}'
env.from_string('{{ 42 is string or 42 is number }}'
).render() == 'True'
def test_string_concatenation(self):

28
libs/jinja2/testsuite/loader.py

@ -182,34 +182,6 @@ class ModuleLoaderTestCase(JinjaTestCase):
tmpl_3c4ddf650c1a73df961a6d3d2ce2752f1b8fd490
assert mod.__file__.endswith('.pyc')
def test_choice_loader(self):
log = self.compile_down(py_compile=True)
assert 'Byte-compiled "a/test.html"' in log
self.mod_env.loader = loaders.ChoiceLoader([
self.mod_env.loader,
loaders.DictLoader({'DICT_SOURCE': 'DICT_TEMPLATE'})
])
tmpl1 = self.mod_env.get_template('a/test.html')
self.assert_equal(tmpl1.render(), 'BAR')
tmpl2 = self.mod_env.get_template('DICT_SOURCE')
self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
def test_prefix_loader(self):
log = self.compile_down(py_compile=True)
assert 'Byte-compiled "a/test.html"' in log
self.mod_env.loader = loaders.PrefixLoader({
'MOD': self.mod_env.loader,
'DICT': loaders.DictLoader({'test.html': 'DICT_TEMPLATE'})
})
tmpl1 = self.mod_env.get_template('MOD/a/test.html')
self.assert_equal(tmpl1.render(), 'BAR')
tmpl2 = self.mod_env.get_template('DICT/test.html')
self.assert_equal(tmpl2.render(), 'DICT_TEMPLATE')
def suite():
suite = unittest.TestSuite()

0
libs/jinja2/testsuite/regression.py

0
libs/jinja2/testsuite/res/__init__.py

0
libs/jinja2/testsuite/res/templates/broken.html

0
libs/jinja2/testsuite/res/templates/foo/test.html

0
libs/jinja2/testsuite/res/templates/syntaxerror.html

0
libs/jinja2/testsuite/res/templates/test.html

0
libs/jinja2/testsuite/security.py

0
libs/jinja2/testsuite/tests.py

0
libs/jinja2/testsuite/utils.py

33
libs/jinja2/utils.py

@ -12,10 +12,6 @@ import re
import sys
import errno
try:
from urllib.parse import quote_from_bytes as url_quote
except ImportError:
from urllib import quote as url_quote
try:
from thread import allocate_lock
except ImportError:
from dummy_thread import allocate_lock
@ -67,7 +63,7 @@ except TypeError, _error:
del _test_gen_bug, _error
# for python 2.x we create ourselves a next() function that does the
# for python 2.x we create outselves a next() function that does the
# basics without exception catching.
try:
next = next
@ -132,7 +128,7 @@ def contextfunction(f):
def evalcontextfunction(f):
"""This decorator can be used to mark a function or method as an eval
"""This decoraotr can be used to mark a function or method as an eval
context callable. This is similar to the :func:`contextfunction`
but instead of passing the context, an evaluation context object is
passed. For more information about the eval context, see
@ -195,7 +191,7 @@ def clear_caches():
def import_string(import_name, silent=False):
"""Imports an object based on a string. This is useful if you want to
"""Imports an object based on a string. This use useful if you want to
use import paths as endpoints or something similar. An import path can
be specified either in dotted notation (``xml.sax.saxutils.escape``)
or with a colon as object delimiter (``xml.sax.saxutils:escape``).
@ -353,21 +349,6 @@ def generate_lorem_ipsum(n=5, html=True, min=20, max=100):
return Markup(u'\n'.join(u'<p>%s</p>' % escape(x) for x in result))
def unicode_urlencode(obj, charset='utf-8'):
"""URL escapes a single bytestring or unicode string with the
given charset if applicable to URL safe quoting under all rules
that need to be considered under all supported Python versions.
If non strings are provided they are converted to their unicode
representation first.
"""
if not isinstance(obj, basestring):
obj = unicode(obj)
if isinstance(obj, unicode):
obj = obj.encode(charset)
return unicode(url_quote(obj))
class LRUCache(object):
"""A simple LRU Cache implementation."""
@ -412,7 +393,7 @@ class LRUCache(object):
return (self.capacity,)
def copy(self):
"""Return a shallow copy of the instance."""
"""Return an shallow copy of the instance."""
rv = self.__class__(self.capacity)
rv._mapping.update(self._mapping)
rv._queue = deque(self._queue)
@ -462,7 +443,7 @@ class LRUCache(object):
"""Get an item from the cache. Moves the item up so that it has the
highest priority then.
Raise a `KeyError` if it does not exist.
Raise an `KeyError` if it does not exist.
"""
rv = self._mapping[key]
if self._queue[-1] != key:
@ -497,7 +478,7 @@ class LRUCache(object):
def __delitem__(self, key):
"""Remove an item from the cache dict.
Raise a `KeyError` if it does not exist.
Raise an `KeyError` if it does not exist.
"""
self._wlock.acquire()
try:
@ -598,7 +579,7 @@ class Joiner(object):
# try markupsafe first, if that fails go with Jinja2's bundled version
# of markupsafe. Markupsafe was previously Jinja2's implementation of
# the Markup object but was moved into a separate package in a patchlevel
# the Markup object but was moved into a separate package in a patchleve
# release
try:
from markupsafe import Markup, escape, soft_unicode

0
libs/jinja2/visitor.py

2
libs/werkzeug/__init__.py

@ -19,7 +19,7 @@ import sys
# the version. Usually set automatically by a script.
__version__ = '0.9-dev'
__version__ = '0.8.3'
# This import magic raises concerns quite often which is why the implementation

0
libs/werkzeug/_internal.py

0
libs/werkzeug/contrib/__init__.py

0
libs/werkzeug/contrib/atom.py

0
libs/werkzeug/contrib/cache.py

0
libs/werkzeug/contrib/fixers.py

0
libs/werkzeug/contrib/iterio.py

0
libs/werkzeug/contrib/jsrouting.py

0
libs/werkzeug/contrib/kickstart.py

0
libs/werkzeug/contrib/limiter.py

0
libs/werkzeug/contrib/lint.py

0
libs/werkzeug/contrib/profiler.py

17
libs/werkzeug/contrib/securecookie.py

@ -88,6 +88,7 @@ r"""
:copyright: (c) 2011 by the Werkzeug Team, see AUTHORS for more details.
:license: BSD, see LICENSE for more details.
"""
import sys
import cPickle as pickle
from hmac import new as hmac
from time import time
@ -97,7 +98,21 @@ from werkzeug.contrib.sessions import ModificationTrackingDict
from werkzeug.security import safe_str_cmp
from hashlib import sha1 as _default_hash
# rather ugly way to import the correct hash method. Because
# hmac either accepts modules with a new method (sha, md5 etc.)
# or a hashlib factory function we have to figure out what to
# pass to it. If we have 2.5 or higher (so not 2.4 with a
# custom hashlib) we import from hashlib and fail if it does
# not exist (have seen that in old OS X versions).
# in all other cases the now deprecated sha module is used.
_default_hash = None
if sys.version_info >= (2, 5):
try:
from hashlib import sha1 as _default_hash
except ImportError:
pass
if _default_hash is None:
import sha as _default_hash
class UnquoteError(Exception):

5
libs/werkzeug/contrib/sessions.py

@ -58,7 +58,10 @@ import tempfile
from os import path
from time import time
from random import random
from hashlib import sha1
try:
from hashlib import sha1
except ImportError:
from sha import new as sha1
from cPickle import dump, load, HIGHEST_PROTOCOL
from werkzeug.datastructures import CallbackDict

0
libs/werkzeug/contrib/testtools.py

0
libs/werkzeug/contrib/wrappers.py

2
libs/werkzeug/datastructures.py

@ -2079,7 +2079,7 @@ class ETags(object):
return etag in self._strong
def __nonzero__(self):
return bool(self.star_tag or self._strong or self._weak)
return bool(self.star_tag or self._strong)
def __str__(self):
return self.to_header()

0
libs/werkzeug/debug/__init__.py

0
libs/werkzeug/debug/console.py

0
libs/werkzeug/debug/repr.py

0
libs/werkzeug/debug/shared/FONT_LICENSE

0
libs/werkzeug/debug/shared/debugger.js

0
libs/werkzeug/debug/shared/jquery.js

0
libs/werkzeug/debug/shared/style.css

0
libs/werkzeug/debug/shared/ubuntu.ttf

0
libs/werkzeug/debug/tbtools.py

0
libs/werkzeug/exceptions.py

0
libs/werkzeug/formparser.py

0
libs/werkzeug/http.py

0
libs/werkzeug/local.py

0
libs/werkzeug/posixemulation.py

7
libs/werkzeug/routing.py

@ -100,7 +100,7 @@ import posixpath
from pprint import pformat
from urlparse import urljoin
from werkzeug.urls import url_encode, url_quote
from werkzeug.urls import url_encode, url_decode, url_quote
from werkzeug.utils import redirect, format_string
from werkzeug.exceptions import HTTPException, NotFound, MethodNotAllowed
from werkzeug._internal import _get_environ
@ -715,7 +715,7 @@ class Rule(RuleFactory):
return
processed.add(data)
else:
add(url_quote(data, self.map.charset, safe='/:|+'))
add(url_quote(data, self.map.charset, safe='/:|'))
domain_part, url = (u''.join(tmp)).split('|', 1)
if append_unknown:
@ -1503,8 +1503,7 @@ class MapAdapter(object):
self.url_scheme,
self.get_host(domain_part),
posixpath.join(self.script_name[:-1].lstrip('/'),
url_quote(path_info.lstrip('/'), self.map.charset,
safe='/:|+')),
url_quote(path_info.lstrip('/'), self.map.charset)),
suffix
))

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save