diff --git a/info/werkzeug-figures/debug-screenshot.png b/info/werkzeug-figures/debug-screenshot.png new file mode 100644 index 00000000..14326468 Binary files /dev/null and b/info/werkzeug-figures/debug-screenshot.png differ diff --git a/info/werkzeug-figures/shortly.png b/info/werkzeug-figures/shortly.png new file mode 100644 index 00000000..96c8525d Binary files /dev/null and b/info/werkzeug-figures/shortly.png differ diff --git a/info/werkzeug.info b/info/werkzeug.info index 853c432f..0378ae52 100644 --- a/info/werkzeug.info +++ b/info/werkzeug.info @@ -1,17 +1,19 @@ This is werkzeug.info, produced by makeinfo version 6.7 from werkzeug.texi. - Werkzeug 1.0.1, Apr 19, 2021 + Werkzeug 2.1.0.dev0, Feb 01, 2022 + + Pallets Copyright © 2007 Pallets -INFO-DIR-SECTION Python +INFO-DIR-SECTION Miscellaneous START-INFO-DIR-ENTRY -* Werkzeug: (werkzeug.info). The Werkzeug reference manual. +* werkzeug: (werkzeug.info). One line description of project END-INFO-DIR-ENTRY - Generated by Sphinx 1.8.5. + Generated by Sphinx 4.3.2. File: werkzeug.info, Node: Top, Next: Getting Started, Up: (dir) @@ -19,7 +21,9 @@ File: werkzeug.info, Node: Top, Next: Getting Started, Up: (dir) Werkzeug ******** - Werkzeug 1.0.1, Apr 19, 2021 + Werkzeug 2.1.0.dev0, Feb 01, 2022 + + Pallets Copyright © 2007 Pallets @@ -30,9 +34,9 @@ Werkzeug is a comprehensive WSGI(1) web application library. It began as a simple collection of various utilities for WSGI applications and has become one of the most advanced WSGI utility libraries. -Werkzeug is Unicode aware and doesn’t enforce any dependencies. It is -up to the developer to choose a template engine, database adapter, and -even how to handle requests. +Werkzeug doesn’t enforce any dependencies. It is up to the developer to +choose a template engine, database adapter, and even how to handle +requests. * Menu: @@ -52,6 +56,10 @@ Getting Started * Werkzeug Tutorial:: * API Levels:: * Quickstart:: +* WSGI Environment:: +* Enter Request:: +* Header Parsing:: +* Responses:: Installation @@ -59,21 +67,17 @@ Installation * Dependencies:: * Virtual environments:: * Install Werkzeug:: -* Install virtualenv:: Dependencies * Optional dependencies:: +* greenlet:: Virtual environments * Create an environment:: * Activate the environment:: -Install Werkzeug - -* Living on the edge:: - Werkzeug Tutorial * Introducing Shortly:: @@ -95,17 +99,10 @@ API Levels * Example:: * High or Low?:: -Quickstart - -* WSGI Environment:: -* Enter Request:: -* Header Parsing:: -* Responses:: - Serving and Testing * Serving WSGI Applications:: -* Test Utilities:: +* Testing WSGI Applications:: * Debugging Applications:: Serving WSGI Applications @@ -125,11 +122,12 @@ SSL * Generating Certificates:: * Adhoc Certificates:: -Test Utilities +Testing WSGI Applications -* Diving In:: -* Environment Building:: -* Testing API:: +* Test Client:: +* Request Body:: +* Environment Builder:: +* API:: Debugging Applications @@ -143,7 +141,6 @@ Reference * Request / Response Objects:: * URL Routing:: * WSGI Helpers:: -* Filesystem Utilities:: * HTTP Utilities:: * Data Structures:: * Utilities:: @@ -156,23 +153,7 @@ Request / Response Objects * How they Work:: * Mutability and Reusability of Wrappers:: -* Base Wrappers:: -* Mixin Classes:: -* Extra Mixin Classes:: - -Mixin Classes - -* Common Descriptors:: -* Response Stream:: -* Accept:: -* Authentication:: -* CORS:: -* ETag:: -* User Agent:: - -Extra Mixin Classes - -* JSON:: +* Wrapper Classes:: URL Routing @@ -196,7 +177,7 @@ WSGI Helpers HTTP Utilities -* Date Functions:: +* Datetime Functions:: * Header Parsing: Header Parsing<2>. * Header Utilities:: * Cookies:: @@ -212,17 +193,12 @@ Data Structures Utilities -* HTML Helpers:: * General Helpers:: * URL Helpers:: -* UserAgent Parsing:: +* User Agent API:: * Security Helpers:: * Logging:: -URL Helpers - -* werkzeug.urls: werkzeug urls. - Middleware * X-Forwarded-For Proxy Fix:: @@ -234,17 +210,13 @@ Middleware HTTP Exceptions -* werkzeug.exceptions: werkzeug exceptions. +* Usage Example:: * Error Classes:: * Baseclass:: * Special HTTP Exceptions:: * Simple Aborting:: * Custom Errors:: -werkzeug.exceptions - -* Usage Example:: - Deployment * Application Deployment:: @@ -284,7 +256,8 @@ Additional Information * Important Terms:: * Unicode:: * Dealing with Request Data:: -* Changelog:: +* BSD-3-Clause License:: +* Changes:: Important Terms @@ -298,7 +271,6 @@ Unicode * Unicode in HTTP:: * Error Handling:: * Request and Response Objects:: -* The Filesystem:: Dealing with Request Data @@ -308,8 +280,13 @@ Dealing with Request Data * Limiting Request Data:: * How to extend Parsing?:: -Changelog +Changes +* Version 2.1.0: Version 2 1 0. +* Version 2.0.3: Version 2 0 3. +* Version 2.0.2: Version 2 0 2. +* Version 2.0.1: Version 2 0 1. +* Version 2.0.0: Version 2 0 0. * Version 1.0.1: Version 1 0 1. * Version 1.0.0: Version 1 0 0. * Version 0.16.1: Version 0 16 1. @@ -396,6 +373,10 @@ File: werkzeug.info, Node: Getting Started, Next: Serving and Testing, Prev: * Werkzeug Tutorial:: * API Levels:: * Quickstart:: +* WSGI Environment:: +* Enter Request:: +* Header Parsing:: +* Responses:: File: werkzeug.info, Node: Installation, Next: Werkzeug Tutorial, Up: Getting Started @@ -409,7 +390,6 @@ File: werkzeug.info, Node: Installation, Next: Werkzeug Tutorial, Up: Getting * Dependencies:: * Virtual environments:: * Install Werkzeug:: -* Install virtualenv:: File: werkzeug.info, Node: Python Version, Next: Dependencies, Up: Installation @@ -417,8 +397,8 @@ File: werkzeug.info, Node: Python Version, Next: Dependencies, Up: Installati 1.1.1 Python Version -------------------- -We recommend using the latest version of Python 3. Werkzeug supports -Python 3.5 and newer and Python 2.7. +We recommend using the latest version of Python. Werkzeug supports +Python 3.7 and newer. File: werkzeug.info, Node: Dependencies, Next: Virtual environments, Prev: Python Version, Up: Installation @@ -431,9 +411,10 @@ Werkzeug does not have any direct dependencies. * Menu: * Optional dependencies:: +* greenlet:: -File: werkzeug.info, Node: Optional dependencies, Up: Dependencies +File: werkzeug.info, Node: Optional dependencies, Next: greenlet, Up: Dependencies 1.1.2.1 Optional dependencies ............................. @@ -441,23 +422,32 @@ File: werkzeug.info, Node: Optional dependencies, Up: Dependencies These distributions will not be installed automatically. Werkzeug will detect and use them if you install them. - * SimpleJSON(1) is a fast JSON implementation that is compatible with - Python’s ‘json’ module. It is preferred for JSON operations if it - is installed. + * Colorama(1) provides request log highlighting when using the + development server on Windows. This works automatically on other + systems. - * Click(2) provides request log highlighting when using the - development server. - - * Watchdog(3) provides a faster, more efficient reloader for the + * Watchdog(2) provides a faster, more efficient reloader for the development server. ---------- Footnotes ---------- - (1) https://simplejson.readthedocs.io/en/latest/ + (1) https://pypi.org/project/colorama/ - (2) https://pypi.org/project/click/ + (2) https://pypi.org/project/watchdog/ - (3) https://pypi.org/project/watchdog/ + +File: werkzeug.info, Node: greenlet, Prev: Optional dependencies, Up: Dependencies + +1.1.2.2 greenlet +................ + +You may choose to use gevent or eventlet with your application. In this +case, greenlet>=1.0 is required. When using PyPy, PyPy>=7.3.7 is +required. + +These are not minimum supported versions, they only indicate the first +versions that added necessary features. You should use the latest +versions of each. File: werkzeug.info, Node: Virtual environments, Next: Install Werkzeug, Prev: Dependencies, Up: Installation @@ -477,11 +467,8 @@ Virtual environments are independent groups of Python libraries, one for each project. Packages installed for one project will not affect other projects or the operating system’s packages. -Python 3 comes bundled with the venv(1) module to create virtual -environments. If you’re using a modern version of Python, you can -continue on to the next section. - -If you’re using Python 2, see *note Install virtualenv: 23. first. +Python comes bundled with the venv(1) module to create virtual +environments. * Menu: @@ -508,15 +495,6 @@ On Windows: py -3 -m venv venv -If you needed to install virtualenv because you are on an older version -of Python, use the following command instead: - - virtualenv venv - -On Windows: - - \Python27\Scripts\virtualenv.exe venv - File: werkzeug.info, Node: Activate the environment, Prev: Create an environment, Up: Virtual environments @@ -535,7 +513,7 @@ Your shell prompt will change to show the name of the activated environment. -File: werkzeug.info, Node: Install Werkzeug, Next: Install virtualenv, Prev: Virtual environments, Up: Installation +File: werkzeug.info, Node: Install Werkzeug, Prev: Virtual environments, Up: Installation 1.1.4 Install Werkzeug ---------------------- @@ -545,59 +523,6 @@ Werkzeug: pip install Werkzeug -* Menu: - -* Living on the edge:: - - -File: werkzeug.info, Node: Living on the edge, Up: Install Werkzeug - -1.1.4.1 Living on the edge -.......................... - -If you want to work with the latest Werkzeug code before it’s released, -install or update the code from the master branch: - - pip install -U https://github.com/pallets/werkzeug/archive/master.tar.gz - - -File: werkzeug.info, Node: Install virtualenv, Prev: Install Werkzeug, Up: Installation - -1.1.5 Install virtualenv ------------------------- - -If you are using Python 2, the venv module is not available. Instead, -install virtualenv(1). - -On Linux, virtualenv is provided by your package manager: - - # Debian, Ubuntu - sudo apt-get install python-virtualenv - - # CentOS, Fedora - sudo yum install python-virtualenv - - # Arch - sudo pacman -S python-virtualenv - -If you are on Mac OS X or Windows, download get-pip.py(2), then: - - sudo python2 Downloads/get-pip.py - sudo python2 -m pip install virtualenv - -On Windows, as an administrator: - - \Python27\python.exe Downloads\get-pip.py - \Python27\python.exe -m pip install virtualenv - -Now you can continue to *note Create an environment: 25. - - ---------- Footnotes ---------- - - (1) https://virtualenv.pypa.io/en/latest/ - - (2) https://bootstrap.pypa.io/get-pip.py - File: werkzeug.info, Node: Werkzeug Tutorial, Next: API Levels, Prev: Installation, Up: Getting Started @@ -670,7 +595,7 @@ redis(2) excels at. The final result will look something like this: - [image src="shortly.png" alt="a screenshot of shortly" ] + [image src="werkzeug-figures/shortly.png" alt="a screenshot of shortly" ] ---------- Footnotes ---------- @@ -723,7 +648,7 @@ And here an expanded version that looks at the query string in the URL def application(environ, start_response): request = Request(environ) - text = 'Hello %s!' % request.args.get('name', 'World') + text = f"Hello {request.args.get('name', 'World')}!" response = Response(text, mimetype='text/plain') return response(environ, start_response) @@ -764,7 +689,7 @@ confusing: import os import redis - import urlparse + from werkzeug.urls import url_parse from werkzeug.wrappers import Request, Response from werkzeug.routing import Map, Rule from werkzeug.exceptions import HTTPException, NotFound @@ -779,7 +704,9 @@ middleware that exports all the files on the ‘static’ folder on the web: class Shortly(object): def __init__(self, config): - self.redis = redis.Redis(config['redis_host'], config['redis_port']) + self.redis = redis.Redis( + config['redis_host'], config['redis_port'], decode_responses=True + ) def dispatch_request(self, request): return Response('Hello World!') @@ -879,7 +806,7 @@ File: werkzeug.info, Node: Step 4 The Routing, Next: Step 5 The First View, P Next up is routing. Routing is the process of matching and parsing the URL to something we can use. Werkzeug provides a flexible integrated routing system which we can use for that. The way it works is that you -create a *note Map: 35. instance and add a bunch of *note Rule: 36. +create a *note Map: 2f. instance and add a bunch of *note Rule: 30. objects. Each rule has a pattern it will try to match the URL against and an “endpoint”. The endpoint is typically a string and can be used to uniquely identify the URL. We could also use this to automatically @@ -907,8 +834,8 @@ you. The way we will do it in this tutorial is by calling the method adapter = self.url_map.bind_to_environ(request.environ) try: endpoint, values = adapter.match() - return getattr(self, 'on_' + endpoint)(request, **values) - except HTTPException, e: + return getattr(self, f'on_{endpoint}')(request, **values) + except HTTPException as e: return e We bind the URL map to the current environment and get back a @@ -919,10 +846,10 @@ dictionary of values in the URL. For instance the rule for to ‘http://localhost:5000/foo’ we will get the following values back: endpoint = 'follow_short_link' - values = {'short_id': u'foo'} + values = {'short_id': 'foo'} -If it does not match anything, it will raise a *note NotFound: 37. -exception, which is an *note HTTPException: 38. All HTTP exceptions are +If it does not match anything, it will raise a *note NotFound: 31. +exception, which is an *note HTTPException: 32. All HTTP exceptions are also WSGI applications by themselves which render a default error page. So we just catch all of them down and return the error itself. @@ -947,7 +874,7 @@ Let’s start with the first view: the one for new URLs: error = 'Please enter a valid URL' else: short_id = self.insert_url(url) - return redirect('/%s+' % short_id) + return redirect(f"/{short_id}+") return self.render_template('new_url.html', error=error, url=url) This logic should be easy to understand. Basically we are checking that @@ -957,19 +884,19 @@ we need to write a function and a helper method. For URL validation this is good enough: def is_valid_url(url): - parts = urlparse.urlparse(url) + parts = url_parse(url) return parts.scheme in ('http', 'https') For inserting the URL, all we need is this little method on our class: def insert_url(self, url): - short_id = self.redis.get('reverse-url:' + url) + short_id = self.redis.get(f'reverse-url:{url}') if short_id is not None: return short_id url_num = self.redis.incr('last-url-id') short_id = base36_encode(url_num) - self.redis.set('url-target:' + short_id, url) - self.redis.set('reverse-url:' + url, short_id) + self.redis.set(f'url-target:{short_id}', url) + self.redis.set(f'reverse-url:{url}', short_id) return short_id ‘reverse-url:’ + the URL will store the short id. If the URL was @@ -1003,13 +930,13 @@ redis and redirect to it. Additionally we will also increment a counter so that we know how often a link was clicked: def on_follow_short_link(self, request, short_id): - link_target = self.redis.get('url-target:' + short_id) + link_target = self.redis.get(f'url-target:{short_id}') if link_target is None: raise NotFound() - self.redis.incr('click-count:' + short_id) + self.redis.incr(f'click-count:{short_id}') return redirect(link_target) -In this case we will raise a *note NotFound: 37. exception by hand if +In this case we will raise a *note NotFound: 31. exception by hand if the URL does not exist, which will bubble up to the ‘dispatch_request’ function and be converted into a default 404 response. @@ -1025,10 +952,10 @@ of times the link was clicked and let it default to zero if such a key does not yet exist: def on_short_link_details(self, request, short_id): - link_target = self.redis.get('url-target:' + short_id) + link_target = self.redis.get(f'url-target:{short_id}') if link_target is None: raise NotFound() - click_count = int(self.redis.get('click-count:' + short_id) or 0) + click_count = int(self.redis.get(f'click-count:{short_id}') or 0) return self.render_template('short_link_details.html', link_target=link_target, short_id=short_id, @@ -1139,7 +1066,7 @@ such as a custom 404 page. ---------- Footnotes ---------- - (1) https://github.com/pallets/werkzeug/tree/master/examples/shortly + (1) https://github.com/pallets/werkzeug/tree/main/examples/shortly File: werkzeug.info, Node: API Levels, Next: Quickstart, Prev: Werkzeug Tutorial, Up: Getting Started @@ -1166,16 +1093,16 @@ File: werkzeug.info, Node: Example, Next: High or Low?, Up: API Levels ------------- This example implements a small ‘Hello World’ application that greets -the user with the name entered: +the user with the name entered. - from werkzeug.utils import escape + from html import escape from werkzeug.wrappers import Request, Response @Request.application def hello_world(request): result = ['