__init__.py 7.0 KB

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