The comprehensive WSGI web application library providing essential utilities and components for building Python web applications.
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Specialized data structures for handling HTTP-specific data including multi-value dictionaries, headers, file uploads, and accept headers with proper parsing and type conversion. These structures form the foundation for HTTP data processing in Werkzeug.
A dictionary-like data structure that can store multiple values for a single key, essential for handling HTTP form data and query parameters.
class MultiDict:
def __init__(self, mapping=None):
"""
Create a new MultiDict.
Parameters:
- mapping: Initial data (dict, list of tuples, or MultiDict)
"""
def get(self, key, default=None, type=None):
"""
Get the first value for a key with optional type conversion.
Parameters:
- key: Key to look up
- default: Default value if key not found
- type: Callable to convert value (e.g., int, float)
Returns:
First value for key, converted by type function if provided
"""
def getlist(self, key, type=None):
"""
Get all values for a key as a list.
Parameters:
- key: Key to look up
- type: Callable to convert each value
Returns:
List of all values for the key
"""
def add(self, key, value):
"""
Add a new value for a key without replacing existing values.
Parameters:
- key: Key to add value for
- value: Value to add
"""
def setlist(self, key, new_list):
"""
Set multiple values for a key, replacing any existing values.
Parameters:
- key: Key to set values for
- new_list: List of values to set
"""
def setlistdefault(self, key, default_list=None):
"""
Set default values for a key if it doesn't exist.
Parameters:
- key: Key to check/set
- default_list: Default list of values
Returns:
List of values for the key
"""
def items(self, multi=False):
"""
Iterate over items.
Parameters:
- multi: If True, yield all key-value pairs including duplicates
Yields:
Key-value pairs
"""
def lists(self):
"""
Iterate over keys and their complete list of values.
Yields:
(key, list_of_values) pairs
"""
def keys(self):
"""Return an iterator over all keys."""
def values(self):
"""Return an iterator over all values (first value per key)."""
def listvalues(self):
"""Return an iterator over all values (all values including duplicates)."""An immutable version of MultiDict that raises exceptions on modification attempts.
class ImmutableMultiDict(MultiDict):
def __init__(self, mapping=None):
"""
Create a new immutable MultiDict.
Parameters:
- mapping: Initial data (dict, list of tuples, or MultiDict)
"""
def copy(self):
"""
Create a mutable copy of this MultiDict.
Returns:
New MultiDict with same data
"""Combines multiple MultiDict instances into a single read-only view.
class CombinedMultiDict:
def __init__(self, dicts):
"""
Create a combined view of multiple MultiDict instances.
Parameters:
- dicts: List of MultiDict instances to combine
"""
def get(self, key, default=None, type=None):
"""
Get first value for key from any of the combined dicts.
Parameters:
- key: Key to look up
- default: Default value if key not found
- type: Callable to convert value
Returns:
First value found in any dict
"""
def getlist(self, key, type=None):
"""
Get all values for key from all combined dicts.
Parameters:
- key: Key to look up
- type: Callable to convert each value
Returns:
List of all values from all dicts
"""
def to_dict(self, flat=True):
"""
Convert to regular dict.
Parameters:
- flat: If True, use only first value per key
Returns:
Regular dict representation
"""Specialized collection for HTTP headers with case-insensitive access and proper handling of multi-value headers.
class Headers:
def __init__(self, defaults=None):
"""
Create a new Headers collection.
Parameters:
- defaults: Initial headers (dict, list of tuples, or Headers)
"""
def get(self, key, default=None, type=None):
"""
Get header value with optional type conversion.
Parameters:
- key: Header name (case-insensitive)
- default: Default value if header not found
- type: Callable to convert value
Returns:
Header value, converted by type function if provided
"""
def set(self, _key, _value, **kw):
"""
Set a header, replacing any existing values.
Parameters:
- _key: Header name
- _value: Header value
- **kw: Additional parameters for the header
"""
def add(self, _key, _value, **kw):
"""
Add a header value without replacing existing values.
Parameters:
- _key: Header name
- _value: Header value
- **kw: Additional parameters for the header
"""
def remove(self, key):
"""
Remove all values for a header.
Parameters:
- key: Header name to remove
"""
def extend(self, *args, **kwargs):
"""
Extend headers with new values from dict, list, or other Headers.
Parameters:
- *args: Headers to add (dict, list, Headers)
- **kwargs: Header key-value pairs
"""
def to_wsgi_list(self):
"""
Convert to WSGI-compatible list of (name, value) tuples.
Returns:
List of (header_name, header_value) tuples
"""
def get_all(self, name):
"""
Get all values for a header as a list.
Parameters:
- name: Header name
Returns:
List of all values for the header
"""Provides a Headers-like interface to WSGI environ HTTP headers.
class EnvironHeaders:
def __init__(self, environ):
"""
Create headers adapter for WSGI environ.
Parameters:
- environ: WSGI environment dictionary
"""
def get(self, key, default=None, type=None):
"""
Get header from WSGI environ.
Parameters:
- key: Header name
- default: Default value if not found
- type: Type conversion function
Returns:
Header value from environ
"""Represents an uploaded file with convenient access to metadata and content.
class FileStorage:
def __init__(self, stream=None, filename=None, name=None, content_type=None, content_length=None, headers=None):
"""
Create a new FileStorage instance.
Parameters:
- stream: File-like object containing the data
- filename: Original filename
- name: Form field name
- content_type: MIME type of the file
- content_length: Size of the file in bytes
- headers: Additional headers
"""
# Properties
filename: str | None # Original filename
name: str | None # Form field name
content_type: str | None # MIME type
content_length: int # File size in bytes
headers: Headers # Additional headers
stream: IO[bytes] # File data stream
def save(self, dst, buffer_size=16384):
"""
Save file to filesystem or file-like object.
Parameters:
- dst: Destination path or file-like object
- buffer_size: Buffer size for copying data
"""
def read(self, length=-1):
"""
Read data from file.
Parameters:
- length: Number of bytes to read (-1 for all)
Returns:
File data as bytes
"""
def readline(self, length=-1):
"""
Read one line from file.
Parameters:
- length: Maximum number of bytes to read
Returns:
One line as bytes
"""
def readlines(self):
"""
Read all lines from file.
Returns:
List of lines as bytes
"""
def seek(self, pos, whence=0):
"""
Seek to position in file.
Parameters:
- pos: Position to seek to
- whence: How to interpret pos (0=absolute, 1=relative, 2=from end)
"""
def tell(self):
"""
Get current position in file.
Returns:
Current byte position
"""
def close(self):
"""Close the file stream."""Specialized MultiDict for handling multiple file uploads with the same field name.
class FileMultiDict(MultiDict):
def __init__(self, mapping=None):
"""
Create MultiDict specifically for FileStorage objects.
Parameters:
- mapping: Initial file data
"""Specialized classes for parsing and handling HTTP Accept headers with quality values.
class Accept:
def __init__(self, values=None):
"""
Base class for Accept header parsing.
Parameters:
- values: Accept header values with quality parameters
"""
def best_match(self, matches, default=None):
"""
Find the best match from available options.
Parameters:
- matches: List of available content types/languages/etc.
- default: Default value if no match found
Returns:
Best matching value based on quality scores
"""
def quality(self, key):
"""
Get quality value for a specific option.
Parameters:
- key: Option to get quality for
Returns:
Quality value (0.0 to 1.0)
"""
class MIMEAccept(Accept):
def __init__(self, values=None):
"""
Parse Accept header for MIME types.
Parameters:
- values: Accept header string or parsed values
"""
@property
def accept_html(self) -> bool:
"""True if HTML is accepted."""
@property
def accept_json(self) -> bool:
"""True if JSON is accepted."""
class LanguageAccept(Accept):
def __init__(self, values=None):
"""
Parse Accept-Language header.
Parameters:
- values: Accept-Language header string or parsed values
"""
class CharsetAccept(Accept):
def __init__(self, values=None):
"""
Parse Accept-Charset header.
Parameters:
- values: Accept-Charset header string or parsed values
"""Classes for handling HTTP authentication headers.
class Authorization:
def __init__(self, auth_type, data=None, token=None, username=None, password=None, realm=None, nonce=None, uri=None, nc=None, cnonce=None, response=None, opaque=None, qop=None):
"""
Parse and represent Authorization header.
Parameters:
- auth_type: Authentication type (Basic, Digest, Bearer, etc.)
- data: Raw authorization data
- token: Bearer token
- username: Username for Basic/Digest auth
- password: Password for Basic auth
- realm, nonce, uri, nc, cnonce, response, opaque, qop: Digest auth parameters
"""
# Properties
type: str # Authentication type
username: str | None # Username
password: str | None # Password (Basic auth only)
realm: str | None # Realm
token: str | None # Bearer token
class WWWAuthenticate:
def __init__(self, auth_type=None, values=None, on_update=None):
"""
Represent WWW-Authenticate header.
Parameters:
- auth_type: Authentication type required
- values: Authentication parameters
- on_update: Callback for updates
"""
# Properties
type: str # Authentication type
realm: str | None # Authentication realmClasses for parsing and managing Cache-Control headers.
class RequestCacheControl:
def __init__(self, values=None, on_update=None):
"""
Parse request Cache-Control header.
Parameters:
- values: Cache-Control header values
- on_update: Callback for updates
"""
# Properties
no_cache: bool # no-cache directive
no_store: bool # no-store directive
max_age: int | None # max-age in seconds
max_stale: int | None # max-stale in seconds
min_fresh: int | None # min-fresh in seconds
no_transform: bool # no-transform directive
only_if_cached: bool # only-if-cached directive
class ResponseCacheControl:
def __init__(self, values=None, on_update=None):
"""
Parse response Cache-Control header.
Parameters:
- values: Cache-Control header values
- on_update: Callback for updates
"""
# Properties
no_cache: bool # no-cache directive
no_store: bool # no-store directive
max_age: int | None # max-age in seconds
s_maxage: int | None # s-maxage in seconds
public: bool # public directive
private: bool # private directive
must_revalidate: bool # must-revalidate directive
proxy_revalidate: bool # proxy-revalidate directive
no_transform: bool # no-transform directive
immutable: bool # immutable directiveClass for managing Content Security Policy headers.
class ContentSecurityPolicy:
def __init__(self, values=None, on_update=None):
"""
Parse and manage CSP header.
Parameters:
- values: CSP directive values
- on_update: Callback for updates
"""
# Common directives as properties
default_src: list[str] | None
script_src: list[str] | None
style_src: list[str] | None
img_src: list[str] | None
connect_src: list[str] | None
font_src: list[str] | None
object_src: list[str] | None
media_src: list[str] | None
frame_src: list[str] | None
def to_header(self):
"""
Convert to CSP header string.
Returns:
Complete CSP header value
"""Classes for handling HTTP Range requests and responses.
class Range:
def __init__(self, units, ranges):
"""
Parse HTTP Range header.
Parameters:
- units: Range units (usually 'bytes')
- ranges: List of range specifications
"""
units: str # Range units
ranges: list[tuple[int | None, int | None]] # List of (start, end) ranges
def range_for_length(self, length):
"""
Get range for content of specific length.
Parameters:
- length: Total content length
Returns:
Tuple of (start, stop) or None if invalid
"""
class ContentRange:
def __init__(self, units, start, stop, length=None, on_update=None):
"""
Represent Content-Range header.
Parameters:
- units: Range units
- start: Start position
- stop: Stop position
- length: Total length
- on_update: Callback for updates
"""
units: str # Range units
start: int # Start position
stop: int # Stop position
length: int | None # Total content lengthClass for handling ETag collections and validation.
class ETags:
def __init__(self, strong_etags=None, weak_etags=None, star_tag=False):
"""
Represent collection of ETags.
Parameters:
- strong_etags: List of strong ETag values
- weak_etags: List of weak ETag values
- star_tag: Whether "*" wildcard is present
"""
def contains(self, etag):
"""
Check if ETag is contained in collection.
Parameters:
- etag: ETag to check
Returns:
True if ETag matches any in collection
"""
def contains_weak(self, etag):
"""
Check if ETag matches using weak comparison.
Parameters:
- etag: ETag to check
Returns:
True if ETag matches weakly
"""
def to_header(self):
"""
Convert to header string.
Returns:
ETag header value
"""from werkzeug.datastructures import MultiDict
from werkzeug.wrappers import Request
def handle_form(environ, start_response):
request = Request(environ)
# Access form data with type conversion
age = request.form.get('age', type=int, default=0)
email = request.form.get('email', '')
# Get all values for checkboxes/multi-select
interests = request.form.getlist('interests')
# Manual MultiDict creation
form_data = MultiDict([
('name', 'John'),
('interests', 'coding'),
('interests', 'music')
])
# Add more values
form_data.add('interests', 'reading')
response = Response(f"Age: {age}, Interests: {interests}")
return response(environ, start_response)from werkzeug.datastructures import FileStorage
from werkzeug.utils import secure_filename
import os
def handle_upload(environ, start_response):
request = Request(environ)
if request.method == 'POST':
uploaded_file = request.files.get('document')
if uploaded_file and uploaded_file.filename:
# Secure the filename
filename = secure_filename(uploaded_file.filename)
# Check file type
if uploaded_file.content_type.startswith('image/'):
# Save to uploads directory
upload_path = os.path.join('/uploads', filename)
uploaded_file.save(upload_path)
response = Response(f"Image {filename} uploaded successfully")
else:
response = Response("Only image files allowed", status=400)
else:
response = Response("No file provided", status=400)
else:
response = Response('''
<form method="POST" enctype="multipart/form-data">
<input type="file" name="document" accept="image/*">
<input type="submit" value="Upload">
</form>
''', mimetype='text/html')
return response(environ, start_response)from werkzeug.datastructures import Headers
from werkzeug.wrappers import Response
def api_response():
# Create response with custom headers
response = Response('{"status": "success"}', mimetype='application/json')
# Add security headers
response.headers['X-Content-Type-Options'] = 'nosniff'
response.headers['X-Frame-Options'] = 'DENY'
response.headers['X-XSS-Protection'] = '1; mode=block'
# Add multiple values for same header
response.headers.add('Set-Cookie', 'session=abc123; HttpOnly')
response.headers.add('Set-Cookie', 'theme=dark; Path=/')
# Create headers object manually
custom_headers = Headers([
('Content-Security-Policy', "default-src 'self'"),
('Strict-Transport-Security', 'max-age=31536000')
])
# Extend response headers
response.headers.extend(custom_headers)
return responsefrom werkzeug.wrappers import Request, Response
import json
def content_negotiation(environ, start_response):
request = Request(environ)
data = {"message": "Hello World", "version": "1.0"}
# Check client preferences
if request.accept_mimetypes.accept_json:
response = Response(
json.dumps(data),
mimetype='application/json'
)
elif request.accept_mimetypes.accept_html:
html = f"<h1>{data['message']}</h1><p>Version: {data['version']}</p>"
response = Response(html, mimetype='text/html')
elif 'application/xml' in request.accept_mimetypes:
xml = f"<root><message>{data['message']}</message><version>{data['version']}</version></root>"
response = Response(xml, mimetype='application/xml')
else:
# Plain text fallback
text = f"{data['message']} (v{data['version']})"
response = Response(text, mimetype='text/plain')
return response(environ, start_response)from werkzeug.datastructures import Range
from werkzeug.wrappers import Request, Response
import os
def serve_file_with_ranges(environ, start_response):
request = Request(environ)
file_path = '/path/to/large/file.mp4'
file_size = os.path.getsize(file_path)
# Check for Range header
if request.range and request.range.ranges:
# Get first range
range_spec = request.range.ranges[0]
start, end = request.range.range_for_length(file_size)
if start is not None and end is not None:
# Serve partial content
with open(file_path, 'rb') as f:
f.seek(start)
data = f.read(end - start)
response = Response(
data,
status=206, # Partial Content
mimetype='video/mp4'
)
response.headers['Content-Range'] = f'bytes {start}-{end-1}/{file_size}'
response.headers['Accept-Ranges'] = 'bytes'
else:
# Invalid range
response = Response(status=416) # Range Not Satisfiable
response.headers['Content-Range'] = f'bytes */{file_size}'
else:
# Serve full file
with open(file_path, 'rb') as f:
data = f.read()
response = Response(data, mimetype='video/mp4')
response.headers['Accept-Ranges'] = 'bytes'
response.headers['Content-Length'] = str(file_size)
return response(environ, start_response)Install with Tessl CLI
npx tessl i tessl/pypi-werkzeug