1
# -*- coding: utf-8 -*-
6
Werkzeug is the Swiss Army knife of Python web development.
8
It provides useful classes and functions for any WSGI application to make
9
the life of a python web developer much easier. All of the provided
10
classes are independent from each other so you can mix it with any other
14
:copyright: (c) 2009 by the Werkzeug Team, see AUTHORS for more details.
15
:license: BSD, see LICENSE for more details.
17
from types import ModuleType
20
# This import magic raises concerns quite often which is why the implementation
21
# and motiviation is explained here in detail now.
23
# The majority of the functions and classes provided by Werkzeug work on the
24
# HTTP and WSGI layer. There is no useful grouping for those which is why
25
# they are all importable from "werkzeug" instead of the modules where they are
26
# implemented. The downside of that is, that now everything would be loaded at
27
# once, even if unused.
29
# The implementation of a lazy-loading module in this file replaces the
30
# werkzeug package when imported from within. Attribute access to the werkzeug
31
# module will then lazily import from the modules that implement the objects.
34
# import mapping to objects in other modules
36
'werkzeug.debug': ['DebuggedApplication'],
37
'werkzeug.local': ['Local', 'LocalManager', 'LocalProxy'],
38
'werkzeug.templates': ['Template'],
39
'werkzeug.serving': ['run_simple'],
40
'werkzeug.test': ['Client', 'EnvironBuilder', 'create_environ',
42
'werkzeug.testapp': ['test_app'],
43
'werkzeug.exceptions': ['abort', 'Aborter'],
44
'werkzeug.utils': ['escape', 'url_quote',
45
'environ_property', 'cookie_date', 'http_date',
46
'url_encode', 'url_quote_plus', 'url_fix',
47
'get_host', 'responder',
48
'SharedDataMiddleware', 'ClosingIterator',
49
'FileStorage', 'url_unquote_plus', 'url_decode',
50
'url_unquote', 'get_current_url', 'redirect',
51
'append_slash_redirect',
52
'cached_property', 'import_string',
53
'dump_cookie', 'parse_cookie', 'unescape',
54
'format_string', 'Href', 'DispatcherMiddleware',
55
'find_modules', 'header_property', 'html',
56
'xhtml', 'HTMLBuilder', 'parse_form_data',
57
'validate_arguments', 'ArgumentValidationError',
58
'bind_arguments', 'FileWrapper', 'wrap_file',
59
'pop_path_info', 'peek_path_info',
60
'LimitedStream', 'make_line_iter',
62
'werkzeug.datastructures': ['MultiDict', 'CombinedMultiDict', 'Headers',
63
'EnvironHeaders', 'ImmutableList',
64
'ImmutableDict', 'ImmutableMultiDict',
65
'TypeConversionDict', 'ImmutableTypeConversionDict',
66
'Accept', 'MIMEAccept', 'CharsetAccept',
67
'LanguageAccept', 'RequestCacheControl',
68
'ResponseCacheControl', 'ETags', 'HeaderSet',
69
'WWWAuthenticate', 'Authorization',
70
'CacheControl', 'FileMultiDict', 'CallbackDict'],
71
'werkzeug.useragents': ['UserAgent'],
72
'werkzeug.http': ['parse_etags', 'parse_date', 'parse_cache_control_header',
73
'is_resource_modified', 'parse_accept_header',
74
'parse_set_header', 'quote_etag', 'unquote_etag',
75
'generate_etag', 'dump_header',
76
'parse_list_header', 'parse_dict_header',
77
'parse_authorization_header',
78
'parse_www_authenticate_header',
79
'remove_entity_headers', 'is_entity_header',
80
'remove_hop_by_hop_headers', 'parse_options_header',
81
'dump_options_header', 'is_hop_by_hop_header',
82
'unquote_header_value',
83
'quote_header_value', 'HTTP_STATUS_CODES'],
84
'werkzeug.wrappers': ['BaseResponse', 'BaseRequest', 'Request',
85
'Response', 'AcceptMixin', 'ETagRequestMixin',
86
'ETagResponseMixin', 'ResponseStreamMixin',
87
'CommonResponseDescriptorsMixin',
88
'UserAgentMixin', 'AuthorizationMixin',
89
'WWWAuthenticateMixin',
90
'CommonRequestDescriptorsMixin'],
91
# the undocumented easteregg ;-)
92
'werkzeug._internal': ['_easteregg']
95
# modules that should be imported when accessed as attributes of werkzeug
96
attribute_modules = dict.fromkeys(['exceptions', 'routing', 'script'])
100
for module, items in all_by_module.iteritems():
102
object_origins[item] = module
105
#: the cached version of the library. We get the distribution from
106
#: pkg_resources the first time this attribute is accessed. Because
107
#: this operation is quite slow it speeds up importing a lot.
110
class module(ModuleType):
111
"""Automatically import objects from the modules."""
113
def __getattr__(self, name):
114
if name in object_origins:
115
module = __import__(object_origins[name], None, None, [name])
116
for extra_name in all_by_module[module.__name__]:
117
setattr(self, extra_name, getattr(module, extra_name))
118
return getattr(module, name)
119
elif name in attribute_modules:
120
__import__('werkzeug.' + name)
121
return ModuleType.__getattribute__(self, name)
124
"""Just show what we want to show."""
125
result = list(new_module.__all__)
126
result.extend(('__file__', '__path__', '__doc__', '__all__',
127
'__docformat__', '__name__', '__path__',
128
'__package__', '__version__'))
132
def __version__(self):
136
version = __import__('pkg_resources') \
137
.get_distribution('Werkzeug').version
142
# keep a reference to this module so that it's not garbage collected
143
old_module = sys.modules['werkzeug']
146
# setup the new module and patch it into the dict of loaded modules
147
new_module = sys.modules['werkzeug'] = module('werkzeug')
148
new_module.__dict__.update({
149
'__file__': __file__,
150
'__path__': __path__,
152
'__all__': tuple(object_origins) + tuple(attribute_modules),
153
'__docformat__': 'restructuredtext en'