You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

234 lines
6.6KB

  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: 2007 Pallets
  11. :license: BSD-3-Clause
  12. """
  13. import sys
  14. from types import ModuleType
  15. __version__ = "0.15.5"
  16. # This import magic raises concerns quite often which is why the implementation
  17. # and motivation is explained here in detail now.
  18. #
  19. # The majority of the functions and classes provided by Werkzeug work on the
  20. # HTTP and WSGI layer. There is no useful grouping for those which is why
  21. # they are all importable from "werkzeug" instead of the modules where they are
  22. # implemented. The downside of that is, that now everything would be loaded at
  23. # once, even if unused.
  24. #
  25. # The implementation of a lazy-loading module in this file replaces the
  26. # werkzeug package when imported from within. Attribute access to the werkzeug
  27. # module will then lazily import from the modules that implement the objects.
  28. # import mapping to objects in other modules
  29. all_by_module = {
  30. "werkzeug.debug": ["DebuggedApplication"],
  31. "werkzeug.local": [
  32. "Local",
  33. "LocalManager",
  34. "LocalProxy",
  35. "LocalStack",
  36. "release_local",
  37. ],
  38. "werkzeug.serving": ["run_simple"],
  39. "werkzeug.test": ["Client", "EnvironBuilder", "create_environ", "run_wsgi_app"],
  40. "werkzeug.testapp": ["test_app"],
  41. "werkzeug.exceptions": ["abort", "Aborter"],
  42. "werkzeug.urls": [
  43. "url_decode",
  44. "url_encode",
  45. "url_quote",
  46. "url_quote_plus",
  47. "url_unquote",
  48. "url_unquote_plus",
  49. "url_fix",
  50. "Href",
  51. "iri_to_uri",
  52. "uri_to_iri",
  53. ],
  54. "werkzeug.formparser": ["parse_form_data"],
  55. "werkzeug.utils": [
  56. "escape",
  57. "environ_property",
  58. "append_slash_redirect",
  59. "redirect",
  60. "cached_property",
  61. "import_string",
  62. "dump_cookie",
  63. "parse_cookie",
  64. "unescape",
  65. "format_string",
  66. "find_modules",
  67. "header_property",
  68. "html",
  69. "xhtml",
  70. "HTMLBuilder",
  71. "validate_arguments",
  72. "ArgumentValidationError",
  73. "bind_arguments",
  74. "secure_filename",
  75. ],
  76. "werkzeug.wsgi": [
  77. "get_current_url",
  78. "get_host",
  79. "pop_path_info",
  80. "peek_path_info",
  81. "ClosingIterator",
  82. "FileWrapper",
  83. "make_line_iter",
  84. "LimitedStream",
  85. "responder",
  86. "wrap_file",
  87. "extract_path_info",
  88. ],
  89. "werkzeug.datastructures": [
  90. "MultiDict",
  91. "CombinedMultiDict",
  92. "Headers",
  93. "EnvironHeaders",
  94. "ImmutableList",
  95. "ImmutableDict",
  96. "ImmutableMultiDict",
  97. "TypeConversionDict",
  98. "ImmutableTypeConversionDict",
  99. "Accept",
  100. "MIMEAccept",
  101. "CharsetAccept",
  102. "LanguageAccept",
  103. "RequestCacheControl",
  104. "ResponseCacheControl",
  105. "ETags",
  106. "HeaderSet",
  107. "WWWAuthenticate",
  108. "Authorization",
  109. "FileMultiDict",
  110. "CallbackDict",
  111. "FileStorage",
  112. "OrderedMultiDict",
  113. "ImmutableOrderedMultiDict",
  114. ],
  115. "werkzeug.useragents": ["UserAgent"],
  116. "werkzeug.http": [
  117. "parse_etags",
  118. "parse_date",
  119. "http_date",
  120. "cookie_date",
  121. "parse_cache_control_header",
  122. "is_resource_modified",
  123. "parse_accept_header",
  124. "parse_set_header",
  125. "quote_etag",
  126. "unquote_etag",
  127. "generate_etag",
  128. "dump_header",
  129. "parse_list_header",
  130. "parse_dict_header",
  131. "parse_authorization_header",
  132. "parse_www_authenticate_header",
  133. "remove_entity_headers",
  134. "is_entity_header",
  135. "remove_hop_by_hop_headers",
  136. "parse_options_header",
  137. "dump_options_header",
  138. "is_hop_by_hop_header",
  139. "unquote_header_value",
  140. "quote_header_value",
  141. "HTTP_STATUS_CODES",
  142. ],
  143. "werkzeug.wrappers": [
  144. "BaseResponse",
  145. "BaseRequest",
  146. "Request",
  147. "Response",
  148. "AcceptMixin",
  149. "ETagRequestMixin",
  150. "ETagResponseMixin",
  151. "ResponseStreamMixin",
  152. "CommonResponseDescriptorsMixin",
  153. "UserAgentMixin",
  154. "AuthorizationMixin",
  155. "WWWAuthenticateMixin",
  156. "CommonRequestDescriptorsMixin",
  157. ],
  158. "werkzeug.middleware.dispatcher": ["DispatcherMiddleware"],
  159. "werkzeug.middleware.shared_data": ["SharedDataMiddleware"],
  160. "werkzeug.security": ["generate_password_hash", "check_password_hash"],
  161. # the undocumented easteregg ;-)
  162. "werkzeug._internal": ["_easteregg"],
  163. }
  164. # modules that should be imported when accessed as attributes of werkzeug
  165. attribute_modules = frozenset(["exceptions", "routing"])
  166. object_origins = {}
  167. for module, items in all_by_module.items():
  168. for item in items:
  169. object_origins[item] = module
  170. class module(ModuleType):
  171. """Automatically import objects from the modules."""
  172. def __getattr__(self, name):
  173. if name in object_origins:
  174. module = __import__(object_origins[name], None, None, [name])
  175. for extra_name in all_by_module[module.__name__]:
  176. setattr(self, extra_name, getattr(module, extra_name))
  177. return getattr(module, name)
  178. elif name in attribute_modules:
  179. __import__("werkzeug." + name)
  180. return ModuleType.__getattribute__(self, name)
  181. def __dir__(self):
  182. """Just show what we want to show."""
  183. result = list(new_module.__all__)
  184. result.extend(
  185. (
  186. "__file__",
  187. "__doc__",
  188. "__all__",
  189. "__docformat__",
  190. "__name__",
  191. "__path__",
  192. "__package__",
  193. "__version__",
  194. )
  195. )
  196. return result
  197. # keep a reference to this module so that it's not garbage collected
  198. old_module = sys.modules["werkzeug"]
  199. # setup the new module and patch it into the dict of loaded modules
  200. new_module = sys.modules["werkzeug"] = module("werkzeug")
  201. new_module.__dict__.update(
  202. {
  203. "__file__": __file__,
  204. "__package__": "werkzeug",
  205. "__path__": __path__,
  206. "__doc__": __doc__,
  207. "__version__": __version__,
  208. "__all__": tuple(object_origins) + tuple(attribute_modules),
  209. "__docformat__": "restructuredtext en",
  210. }
  211. )
  212. # Due to bootstrapping issues we need to import exceptions here.
  213. # Don't ask :-(
  214. __import__("werkzeug.exceptions")