A real senior engineer reference
The senior engineer reference Nehemvix wrote for pallets/itsdangerous in the same run as the example architecture review.
Same run, same commit: Architecture review · Beginner's guide
Published as Nehemvix wrote it, apart from its one-line footer.
What to notice as you read:
- A citation link. Click a file name in the text and it opens the exact lines at the commit that was read.
- The grounding score. The ring below scores the guide out of 100, and the note under it says what that covers.
- The "Names we couldn't find" list. When a guide mentions a name that isn't in the code, Nehemvix lists it at the end so you know what to check. This run found every name it used, so the list doesn't appear.
StrongGrounding 96 / 100
- Written by
- gpt-6-luna
- Repository
- pallets/itsdangerous at commit
672971d66a - Licence of that code
- BSD-3-Clause (LICENSE.txt)
What the score means: Grounding checks names, paths, citations, sections and the diagram against the code, not whether explanations are right.
ItsDangerous: an engineering reference
ItsDangerous helps applications send data in a token and check that nobody changed it.
Repository: github.com/pallets/itsdangerous · Commit:
672971d66a· Files analysed: 46 · Generated: 2026-11-10 15:49 UTC · Model: gpt-6-luna
Contents
- System overview
- Module & API reference
- Data models & persistence
- Control flow & concurrency
- Error handling & resilience
- Configuration & environment
- Testing strategy & coverage map
- Performance hotspots
- Extension points & adding a feature
- Dependency inventory
- Caveats & omitted files
System overview
Diagram source (Mermaid)
flowchart TB
accTitle: Building blocks of ItsDangerous
subgraph g_core_package["Core package"]
n_api["Public Python API"]
n_serializer["Serialization"]
n_signer["Signing"]
n_encoding["Encoding helpers"]
end
subgraph g_token_formats["Token formats"]
n_timed["Timestamped tokens"]
n_url["URL-safe tokens"]
end
subgraph g_quality["Quality"]
n_tests["Automated tests"]
end
subgraph g_project_support["Project support"]
n_docs["Documentation"]
n_config["Project configuration"]
n_ci["GitHub workflows"]
end
n_app(["Application code"])
n_app -->|"imports package"| n_api
n_api -->|"exports classes"| n_serializer
n_api -->|"exports classes"| n_signer
n_api -->|"exports classes"| n_timed
n_api -->|"exports classes"| n_url
n_serializer -->|"signs tokens"| n_signer
n_timed -->|"signs timestamps"| n_signer
n_url -->|"serializes values"| n_serializer
n_url -->|"encodes tokens"| n_encoding
n_tests -->|"checks behavior"| n_api
n_docs -->|"explains usage"| n_api
n_config -->|"configures tests"| n_tests
n_config -->|"configures builds"| n_docs
n_ci -->|"runs checks"| n_tests
n_ci -->|"publishes package"| n_api
class n_app external
class n_api interface
class n_serializer,n_signer,n_timed,n_url,n_encoding component
class n_tests tests
class n_docs docs
class n_config config
class n_ci tooling
%% path n_api src/itsdangerous/__init__.py
%% tech n_api Python module
%% path n_serializer src/itsdangerous/serializer.py
%% tech n_serializer Python module
%% path n_signer src/itsdangerous/signer.py
%% tech n_signer Python module
%% path n_timed src/itsdangerous/timed.py
%% tech n_timed Python module
%% path n_url src/itsdangerous/url_safe.py
%% tech n_url Python module
%% path n_encoding src/itsdangerous/encoding.py
%% tech n_encoding Python module
%% path n_tests tests/test_itsdangerous/
%% tech n_tests pytest tests
%% path n_docs docs/
%% tech n_docs Sphinx docs
%% path n_config pyproject.toml
%% tech n_config Python project manifest
%% path n_ci .github/workflows/
%% tech n_ci GitHub Actions
%% via n_api n_serializer imports
%% via n_api n_signer imports
%% via n_api n_timed imports
%% via n_api n_url imports
%% via n_serializer n_signer imports
%% via n_timed n_signer imports
%% via n_url n_serializer imports
%% via n_url n_encoding imports
In short: This section maps the package’s signing, serialization, and token-loading paths. Its central contract is to detect changes to signed data, not to conceal that data.
Runtime model and public surface
ItsDangerous is an imported Python library, not a server or command-line application. Application code starts at the top-level package, which re-exports the main serializers, signers, encoding helpers, and exceptions from src/itsdangerous/__init__.py. The caller supplies the signing key and chooses a token format and any relevant options; the package does not provide application-specific key management.
The core data path composes serialization with signing. A serializer turns a Python value into a payload, then signs it to produce a token. On load, it verifies the signature before decoding and returning the payload. This ordering is important: a payload is not treated as trusted serialized input until its signature has passed verification. Serializer also supports custom serializers and signers, key rotation, fallback signers, salts, and file-based methods (src/itsdangerous/serializer.py).
Signing is a separate layer. The signer operates on byte strings, derives a signing key from the configured key and options, and appends a URL-safe encoded signature. Verification can try candidate keys from newest to oldest, supporting rotation while older tokens remain in use. The signing algorithm is configurable; the module includes HMAC and no-signature algorithms (src/itsdangerous/signer.py).
Token variants and supporting contracts
- Timestamped tokens:
TimestampSigneradds a timestamp to the signed value. Its verification path can enforce a maximum age and rejects expired or future-dated signatures.TimedSerializerapplies this behavior to serialized values and preserves expiration failures rather than treating them as a reason to try a fallback signer (src/itsdangerous/timed.py). - URL-safe tokens: URL-safe serializers encode the payload with URL-safe base64. They can compress it with zlib when compression makes it sufficiently shorter; a leading dot marks a compressed payload so loading can decompress it before decoding. The URL-safe module provides both regular and timestamp-aware serializer variants, using compact JSON by default (
src/itsdangerous/url_safe.py,src/itsdangerous/_json.py). - Encoding and failures: Encoding helpers handle text-to-bytes conversion, URL-safe base64, and compact integer conversion (
src/itsdangerous/encoding.py). Shared exceptions distinguish invalid data, signature failures, and timestamp-related failures; callers can catch a specific exception or the commonBadDatabase (src/itsdangerous/exc.py).
Critical paths
Create a token: application code passes a value to a serializer; the serializer encodes it, and the signer attaches a signature. URL-safe variants may compress and encode the payload as part of this path. The README’s example uses URLSafeSerializer to produce a token and load it again (README.md).
Load a token: the serializer separates the signed value from its signature and verifies the signature before decoding the payload. Timestamp-aware variants additionally check token age. Invalid signatures, malformed data, and expiration are reported through the exception hierarchy, rather than returning an unverified value (src/itsdangerous/serializer.py, src/itsdangerous/timed.py, src/itsdangerous/exc.py).
Tests exercise the component boundaries: encoding, signing and key rotation, serializer round trips and tampering, URL-safe formats, and timestamp expiration (tests/test_itsdangerous/test_signer.py, tests/test_itsdangerous/test_serializer.py, tests/test_itsdangerous/test_url_safe.py, tests/test_itsdangerous/test_timed.py).
Module & API reference
Needs review: many statements in this section name code without citing the lines they rely on. Check them in the code before relying on them.
Diagram source (Mermaid)
flowchart LR
accTitle: Folder dependencies of itsdangerous
n_m0[["src/itsdangerous/"]]
n_m1[["tests/"]]
n_m1 -->|"11 imports"| n_m0
class n_m0 library
class n_m1 tests
%% tech n_m0 Python package
%% tech n_m1 pytest tests
In short: This section maps the package’s main modules to their roles and describes the interfaces and contracts shown in the available repository material. It focuses on how callers use serialization, signing, timestamps, URL-safe formats, encoding helpers, and exceptions.
src/itsdangerous/__init__.py
Applications start by importing the package’s public classes and exceptions from the top-level package. The available material confirms that this module exposes the main APIs, but does not list the exact exports or their signatures. A usage example in README.md creates a URLSafeSerializer with a secret key and salt, calls dumps to produce a token, and calls loads to recover the value. Signing detects changes; it does not hide the token’s contents.
src/itsdangerous/serializer.py
Serializer is the main interface for turning Python values into signed tokens and loading them after signature verification. Its constructor is Serializer.__init__; the available material does not show the constructor’s parameter list. The repository also identifies Serializer as supporting configurable serialization and signer behavior.
For data that needs a text-oriented serializer, is_text_serializer checks whether the serializer handles text. _PDataSerializer provides dumps and loads methods for its serialization path. Its loads method checks the signature before returning the deserialized value. Invalid or altered tokens are reported through the package’s exception types in src/itsdangerous/exc.py.
src/itsdangerous/signer.py
This module contains signing algorithms and the primitives used to produce and verify signatures. SigningAlgorithm.get_signature produces a signature, and SigningAlgorithm.verify_signature checks one. NoneAlgorithm.get_signature is an algorithm implementation; HMACAlgorithm is another implementation, and HMACAlgorithm.__init__ configures it. The listed interfaces do not provide full parameter or return-type signatures.
_lazy_sha1 is an internal helper. It is not presented as an application-facing API. The module summary also describes configurable algorithms and key rotation, but the available symbol details do not specify their exact configuration signatures.
src/itsdangerous/timed.py
TimestampSigner adds a timestamp to signed data. get_timestamp supplies the timestamp, and timestamp_to_datetime converts a timestamp to a datetime value. sign creates timestamped signed data; unsign verifies it and can check its age; validate checks validity. The available material does not show their exact parameter lists or return types.
Timestamp checks let applications reject expired tokens. The module summary also identifies rejection of future-dated signatures. Timestamp failures use the timestamp-related exceptions in src/itsdangerous/exc.py.
src/itsdangerous/url_safe.py
URLSafeSerializer and URLSafeTimedSerializer provide URL-safe token formats. The former combines URL-safe encoding with serialization and signing; the latter adds timestamp-based checks. URLSafeSerializerMixin.dump_payload and URLSafeSerializerMixin.load_payload handle payload encoding and decoding for these formats. Compression is optional, as needed for the URL-safe format.
src/itsdangerous/encoding.py
These helpers support the package’s token and signature operations:
want_bytesconverts supported text or byte input to bytes.base64_encodeandbase64_decodeencode and decode base64 data.int_to_bytesandbytes_to_intconvert between integers and bytes.
The available material does not specify the helpers’ complete signatures or error contracts.
src/itsdangerous/exc.py
This module defines errors for invalid data and verification failures. BadData is the base error type; BadSignature represents signature failures, and BadTimeSignature represents failures involving timestamped signatures. SignatureExpired represents expiration. BadData.__str__, BadData.__init__, BadSignature.__init__, and BadTimeSignature.__init__ define error formatting and initialization. Exact constructor parameters and message text are not shown.
src/itsdangerous/_json.py
_CompactJSON provides dumps and loads for compact JSON serialization. It is an internal helper, rather than a documented application-facing interface.
Data models & persistence
In short: ItsDangerous keeps no application records or database state; it turns caller-provided values into signed tokens. The token format and the signer settings are the important data contracts to preserve.
Persistence and in-memory data
The package has no database, filesystem store, or migration system. An application decides whether and where to store or transmit a token. While running, a Serializer holds its secret keys, salt, serializer and signer settings, fallback signer definitions, and whether its serializer returns text (src/itsdangerous/serializer.py · Serializer.__init__ (lines 108–120)). A signer holds its keys in oldest-to-newest order, along with settings such as its separator, salt, derivation choice, digest method, and algorithm (src/itsdangerous/signer.py).
Applications supply the secret key. Signing detects changes to the token, but does not conceal its payload. Treat the serialized payload as readable by anyone who obtains the token.
Token data and formats
A serializer converts a Python value to a payload, then signs it. JSON is the default serialization format; applications can supply another serializer (src/itsdangerous/_json.py · _CompactJSON (lines 7–18), src/itsdangerous/serializer.py · Serializer (lines 40–404)). The URL-safe serializer encodes payloads for use in URLs and can compress them when appropriate (src/itsdangerous/url_safe.py · URLSafeSerializerMixin (lines 15–69)). These choices determine how payload data is represented in the token.
Timestamped tokens include a timestamp that the signer checks when loading. Timestamp-related integer values use an unsigned 64-bit, big-endian representation (src/itsdangerous/timed.py · TimestampSigner (lines 22–167), src/itsdangerous/encoding.py · int_to_bytes (lines 49–50), src/itsdangerous/encoding.py · bytes_to_int (lines 53–54)). Applications can set an age limit when validating a token. This timestamp is part of the token, not a record stored by the package.
There is no database schema to migrate. However, tokens are serialized data: changing an application’s serializer or signing configuration can affect whether it can load previously issued tokens. The signer supports key rotation through configured keys and fallback signers; those settings are in-memory configuration, not persisted rotation state (src/itsdangerous/serializer.py · Serializer (lines 40–404), src/itsdangerous/signer.py).
Validation failures
Loading verifies the token before returning its payload. Failures are represented by exception objects rather than stored records. For example, BadSignature can carry a payload, BadTimeSignature can carry the signing date, and BadPayload can carry the original decoding error (src/itsdangerous/exc.py). A timestamp outside the allowed age is represented by SignatureExpired (src/itsdangerous/exc.py · SignatureExpired (lines 60–63)).
Control flow & concurrency
In short: Token operations run as ordinary calls in the application’s process. The supplied material shows no internal locking or concurrency guarantees, so callers must manage shared resources and ordering.
Token operations
The application creates a serializer or signer with its configuration, then calls it for each operation. A serializer’s dumps path serializes the value and signs the result; loading checks a signature before returning the decoded value. URL-safe serializers may also compress the payload, and timestamped variants add and check timestamps (src/itsdangerous/serializer.py, src/itsdangerous/url_safe.py, src/itsdangerous/timed.py).
When loading, the serializer checks its configured signers in turn. If none verifies the token, it raises the last BadSignature rather than returning a payload (src/itsdangerous/serializer.py, src/itsdangerous/exc.py · BadSignature (lines 22–33)). This is ordering within one load operation; the material does not describe ordering between separate operations or requests.
Threads, async, and processes
The documented usage is a direct call from application code, and the public API exposes classes and exceptions rather than a server or worker entry point (README.md, src/itsdangerous/__init__.py). The supplied material shows no async API, thread or process management, locks, or internal scheduling. It also does not establish a thread-safety guarantee for sharing a serializer or signer instance. If an application shares instances across concurrent tasks, confirm their behavior against the implementation and keep any mutable application state synchronized.
The package does not provide a global sequence or ordering mechanism for token creation. If an application needs to order operations across threads, processes, or machines, it must provide that coordination.
Shared resources and timing
dump and load operate on a caller-supplied file-like object (src/itsdangerous/serializer.py). The package summary shows no locking around that object. Concurrent reads or writes to the same stream may therefore conflict according to the stream’s behavior; use separate streams or synchronize access in the application.
Timestamp operations read the system clock through time.time (src/itsdangerous/timed.py · TimestampSigner.get_timestamp (lines 29–33)). In a multi-process or multi-host deployment, clock differences can affect age checks. The package does not provide clock synchronization. Tests can freeze time for timestamp behavior (tests/test_itsdangerous/test_timed.py · FreezeMixin.freeze (lines 24–26)), but that does not establish production clock coordination.
Error handling & resilience
In short: Token-loading failures are reported through exceptions rather than silently accepted. Callers should reject tokens when verification or decoding fails; the library does not retry operations or impose timeouts.
Token verification and loading
A signer raises BadSignature when a signed value is missing its separator or its signature does not match. An invalid base64 signature makes verification fail. A token may therefore be rejected before its payload is returned. See src/itsdangerous/signer.py and src/itsdangerous/exc.py · BadSignature (lines 22–33).
Serializer.loads tries its configured signers and, if they all fail, raises the last BadSignature. Payload decoding can fail separately: the serializer wraps deserialization failures in BadPayload and attaches the original error. JSON parsing or encoding errors can propagate from the JSON helper; when deserialization occurs through the serializer, its wrapping behavior applies. See src/itsdangerous/serializer.py and src/itsdangerous/_json.py · _CompactJSON (lines 7–18).
For URL-safe formats, base64 decoding and zlib decompression failures are wrapped in BadPayload. Base64 decoding helpers also wrap TypeError and ValueError in BadData. Text conversion uses strict UTF-8 by default, so invalid text is not silently replaced. See src/itsdangerous/url_safe.py · URLSafeSerializerMixin.load_payload (lines 23–53) and src/itsdangerous/encoding.py · base64_decode (lines 28–38).
Timestamp failures
Timestamped signers can fail for both signature and time-related reasons:
BadSignatureindicates a signature failure.BadTimeSignatureindicates a missing or malformed timestamp.SignatureExpiredindicates that the signature is outside the allowed age.
Timestamp conversion handles date-overflow errors. Where available, exceptions retain payload and signing-date context for inspection. Callers should treat these exceptions as rejection of the token, not as a reason to use its contents. Timestamp creation and checking read the system clock. See src/itsdangerous/timed.py · TimestampSigner.unsign (lines 57–62), src/itsdangerous/exc.py · BadTimeSignature (lines 36–57), and src/itsdangerous/exc.py · SignatureExpired (lines 60–63).
What callers should handle
Catch the relevant exception types around token loading and decide how the application should respond—for example, reject the request or ask the user to obtain a new token. Do not treat a decoding failure as a valid token, and do not rely on a particular failure message: the documented failure categories are the stable guidance here.
loads_unsafe is an explicit alternative that returns a (signature_valid, payload) tuple. If the payload cannot be loaded, it returns (False, None). Check the validity flag before trusting the payload; this method does not make an invalid signature safe to use. See src/itsdangerous/serializer.py · _PDataSerializer.loads (line 25).
Configuration can fail before any token is processed: an unsafe signer separator raises ValueError, and an unknown key derivation raises TypeError. These indicate a signer setup problem rather than a token that should be retried. See src/itsdangerous/signer.py.
Retry and timeout behavior
The provided code describes no automatic retries or operation timeouts. Retrying a rejected token does not fix a bad signature, malformed payload, or expired timestamp. Applications should handle each failure at the boundary where tokens are loaded and apply their own request or user-facing policy.
Configuration & environment
In short: This section lists the repository’s configuration inputs, their purpose, and where they are read. The package itself has no required environment variables; applications configure signing through Python arguments.
Application configuration
| Input | Purpose | Default | Where it is read |
|---|---|---|---|
secret_key |
Supplies key material for signing and signature checks. | No application key is supplied by the package; the application provides it. | Signer and serializer constructors in src/itsdangerous/signer.py and src/itsdangerous/serializer.py. |
salt |
Separates signing contexts so signatures made for one use are distinct from signatures made for another. | Defined by the relevant signer or serializer configuration; no universal default is stated in the provided material. | src/itsdangerous/signer.py, src/itsdangerous/serializer.py, and timed loading or unsigning methods in src/itsdangerous/timed.py. |
sep |
Sets the separator used by a signer. | Not stated in the provided material. | src/itsdangerous/signer.py. |
key_derivation |
Selects how the signing key is derived. | django-concat. |
src/itsdangerous/signer.py. |
digest_method |
Selects the HMAC hash. | SHA-1. | src/itsdangerous/signer.py; also described in docs/concepts.rst. |
algorithm |
Configures the signing algorithm. | Not stated in the provided material. | src/itsdangerous/signer.py. |
serializer, serializer_kwargs |
Choose and configure the serializer used for token data. | Not stated in the provided material. | src/itsdangerous/serializer.py. |
signer, signer_kwargs |
Choose and configure the signer used by a serializer. | Not stated in the provided material. | src/itsdangerous/serializer.py. |
fallback_signers |
Allows verification with older signer classes or settings, which can help support older tokens during key or signing-configuration changes. | Not stated in the provided material. | src/itsdangerous/serializer.py; usage is described in docs/concepts.rst and docs/serializer.rst. |
max_age, return_timestamp |
Control token-age checking and whether a timestamp is returned when loading timed tokens. | Not stated in the provided material. | Timed loading and unsigning methods in src/itsdangerous/timed.py. |
JSON dumps keyword arguments |
Override JSON serialization defaults. | The JSON implementation’s defaults apply unless overridden. | src/itsdangerous/_json.py. |
Repository and tool configuration
| Input | Purpose | Default | Where it is read |
|---|---|---|---|
| Project metadata and Python requirement | Defines package metadata and the supported Python version (>=3.10). |
Values are declared in the file. | pyproject.toml. |
| Dependency groups and tool settings | Configure development dependency groups and settings for pytest, coverage, mypy, pyright, Ruff, uv, and tox. For example, pytest uses tests as its test path, and tox lists test, style, typing, and docs environments. |
Values are declared in the file; uv’s default groups are dev, pre-commit, tests, and typing. |
pyproject.toml. |
SPHINXOPTS, SPHINXBUILD, SOURCEDIR, BUILDDIR, and optional O |
Set Sphinx options, executable, source directory, build directory, and extra options for documentation builds. | SPHINXOPTS and O are empty; SPHINXBUILD is sphinx-build; SOURCEDIR is .; BUILDDIR is _build. |
docs/Makefile; the variables can be set from the command line. |
SPHINXBUILD, SPHINXOPTS, and command-line target |
Select the Sphinx executable, supply options, and choose a build target on Windows. | The defaults for the variables are not stated in the provided material; the target comes from the command-line argument. | docs/make.bat. |
$READTHEDOCS_OUTPUT |
Specifies the Read the Docs output path. | Not stated in the provided material. | .readthedocs.yaml. |
| Python interpreter and terminal arguments | Configure the VS Code Python interpreter path and add -X dev to terminal Python arguments. |
Interpreter path is ${workspaceFolder}/.venv; terminal arguments include -X dev. |
.devcontainer/devcontainer.json. |
PATH |
Is used and modified when installing uv in the development container. | Not stated in the provided material. | .devcontainer/on-create-command.sh. |
SOURCE_DATE_EPOCH |
Sets a reproducible-build timestamp from the latest Git commit timestamp during release publishing. | Set by the workflow. | .github/workflows/publish.yaml. |
Testing strategy & coverage map
In short: This section maps the pytest suite to the behaviors it checks, shows how to run one test, and calls out limits in the available coverage evidence. Use the map to find relevant tests, but do not treat the test inventory or coverage configuration as proof that every important behavior is covered.
Framework and running tests
The project uses pytest. Its configuration points pytest at tests and treats warnings as errors (pyproject.toml). The test files live in tests/test_itsdangerous/; the provided summaries describe six files, covering encoding, serialization, signing, timestamped behavior, and URL-safe formats.
With the project’s test dependencies installed, run the full suite with:
uv run pytest
To run one test, give pytest the file path and test name after ::. For example:
uv run pytest tests/test_itsdangerous/test_encoding.py::test_want_bytes
The tests dependency group includes pytest and freezegun (pyproject.toml). The timestamp tests use frozen time so expiration checks can be exercised consistently (tests/test_itsdangerous/test_timed.py).
Coverage map
| Test file | Behaviors described in the test summary |
|---|---|
tests/test_itsdangerous/test_encoding.py |
Text and bytes conversion, base64 round trips, invalid base64, and integer-to-bytes conversion. |
tests/test_itsdangerous/test_signer.py |
Signature validation and rejection of changed data or damaged signatures; key derivation, digest methods, signing algorithms, separators, and verification with an older key. |
tests/test_itsdangerous/test_serializer.py |
Round trips with default JSON behavior and pickle; tampered signatures, payload loading errors, unsafe loading, file-like objects, salts, signer configuration, fallback signers, key iteration, and stable digests. |
tests/test_itsdangerous/test_timed.py |
Timestamp age and expiration checks, returned timestamps, missing or malformed timestamps, future timestamps, and signature failures. |
tests/test_itsdangerous/test_url_safe.py |
Reuses serializer tests for URL-safe and timed URL-safe serializers, including a long string to exercise compressed payload handling. |
Gaps and review notes
The summaries give a useful map of tested unit behaviors, but they do not establish coverage for every code path or report a coverage percentage. They also do not identify dedicated tests for areas such as performance, fuzzing, or end-to-end application integration; confirm whether those matter for the change under review rather than assuming they are covered.
Pay particular attention to the coverage configuration before relying on a coverage report: pyproject.toml sets its coverage sources to jinja2 and tests, while the package implementation is under src/itsdangerous. Verify that coverage collection and reporting include the intended package code.
The test inventory also shows shared coverage rather than a separate URL-safe test suite: tests/test_itsdangerous/test_url_safe.py reuses the regular and timed serializer tests. When changing URL-safe-specific behavior, check that the shared tests exercise the changed path.
Performance hotspots
In short: The main costs are serialization, signing, and token verification, with verification work increasing when key rotation or fallback signers are configured. Treat the repository’s hotspot ranking as a guide for where to inspect, not as runtime profiling data.
Prioritize the token paths
The hotspot facts rank src/itsdangerous/serializer.py highest by size × fan-in (405 lines, fan-in 4), followed by src/itsdangerous/signer.py (267 lines, fan-in 6). src/itsdangerous/exc.py has lower size but higher fan-in (107 lines, fan-in 10); that indicates broad use, not necessarily frequent work on successful requests. The ranking is structural, not a measurement of time spent at runtime.
- Verification scales with configured keys and signer fallbacks. A signer checks candidate keys from newest to oldest and stops at the first match. Serializer loading can also try fallback signers. Inferred: The slow path is an invalid signature or a match late in the key list, combined with multiple fallback signers; each attempted verification works over the signed value. Keep key and fallback lists to what the rotation policy requires, and remove old keys when they are no longer needed.
src/itsdangerous/signer.py·Signer(lines 76–266)src/itsdangerous/serializer.py·Serializer(lines 40–404) - Serialization and signing are sequential work. The serializer turns a value into data and then signs it; loading verifies the signature before deserializing. Inferred: Cost grows with payload size, and failed verification avoids the deserialization step. When investigating latency, measure
dumpsandloadsseparately with representative payload sizes rather than treating signing as the only cost.src/itsdangerous/serializer.py·Serializer(lines 40–404)src/itsdangerous/signer.py·Signer(lines 76–266)
Compression, encoding, and allocations
URL-safe serialization attempts zlib compression for every payload and uses the compressed form only when it saves more than one byte. It then uses URL-safe base64; loading reverses the relevant steps. Compact JSON omits optional whitespace. Inferred: These transformations can add CPU work and temporary byte strings, even when compression does not reduce the token. For large or frequently processed payloads, benchmark with realistic data and compare the configured URL-safe serializer’s compression behavior. Keep payloads appropriately sized; do not assume compact JSON or compression makes large payloads cheap. src/itsdangerous/url_safe.py · URLSafeSerializerMixin.dump_payload (lines 55–69) src/itsdangerous/url_safe.py · URLSafeSerializerMixin.load_payload (lines 23–53) src/itsdangerous/_json.py · _CompactJSON (lines 7–18)
I/O and caching
The serializer supports file-based methods, but the supplied material does not describe their I/O costs or show external I/O in the ordinary token path. Inferred: If file-based serialization is used in a latency-sensitive path, measure its I/O separately from encoding and signing. src/itsdangerous/serializer.py · Serializer (lines 40–404)
No internal cache for serialized values or signatures is described. Inferred: Do not assume repeated calls reuse prior work. Profile before adding an application-level cache; if caching is appropriate, account for token freshness and expiration, and invalidate cached values when relevant signing configuration changes. Timestamped tokens have age checks, so reusing one can change how long it remains acceptable. src/itsdangerous/timed.py · TimedSerializer (lines 170–228) src/itsdangerous/serializer.py · Serializer (lines 40–404)
Extension points & adding a feature
In short: ItsDangerous extends through configurable classes and overridable methods, not a general plugin registry. This section maps those seams and gives a practical path for adding a feature with tests and documentation.
Where to extend
- Signing algorithms:
SigningAlgorithmdefines the signing and verification operations, and the package includesNoneAlgorithmandHMACAlgorithmimplementations. To add an algorithm, follow those implementations and the algorithm-selection path insrc/itsdangerous/signer.py. Test the algorithm and its integration with signer behavior intests/test_itsdangerous/test_signer.py. - Payload formats: Serializers connect payload encoding and decoding to signing. For URL-safe formats,
URLSafeSerializerMixinprovides thedump_payloadandload_payloadmethods;URLSafeSerializerandURLSafeTimedSerializerbuild on that mixin insrc/itsdangerous/url_safe.py. Use these seams when a feature changes URL-safe payload representation. The general serialization code is insrc/itsdangerous/serializer.py. - Timestamp behavior: Timestamp creation and validation are handled by
TimestampSignerinsrc/itsdangerous/timed.py. Extend this area when a feature changes timestamp handling, and cover it intests/test_itsdangerous/test_timed.py. - Errors and public API: Shared error types are in
src/itsdangerous/exc.py. If a new public class or exception should be importable from the package’s top-level namespace, updatesrc/itsdangerous/__init__.py.
There is no general plugin registry shown in these extension points. Prefer extending the class or method responsible for the behavior, and avoid changing unrelated token formats.
Recipe: add a URL-safe payload feature
For a feature that changes how URL-safe payloads are written and read:
- Trace the existing path. Read
URLSafeSerializerMixinand itsdump_payloadandload_payloadmethods insrc/itsdangerous/url_safe.py. Check how its serializer classes use the mixin before deciding whether the change belongs there or in the shared serialization code insrc/itsdangerous/serializer.py. - Implement the behavior at the narrowest seam. If the change is specific to URL-safe payload encoding or decoding, keep it in the URL-safe implementation. Preserve the existing contract between writing and reading: tokens produced by the feature must be decoded by the corresponding load path.
- Add focused tests. Add cases to
tests/test_itsdangerous/test_url_safe.pyfor the new behavior. If it changes behavior shared with regular serialization, add or adapt coverage intests/test_itsdangerous/test_serializer.pyas well. Include a round trip and relevant invalid-input behavior; do not assume signing makes the payload confidential. - Expose new API only if needed. If the feature introduces a public class, re-export it from
src/itsdangerous/__init__.py. Internal changes do not need a new top-level export. - Update user-facing material. Document usage and constraints in
docs/url_safe.rstor the relevant feature page, and add a brief entry toCHANGES.rst. If the feature changes the package’s basic example or positioning, updateREADME.md. - Run checks. Run the relevant tests, then the project’s broader checks as appropriate.
pyproject.tomldescribes project configuration, and.github/workflows/tests.yamlshows the automated test workflow.
For a new signing algorithm, use the same general sequence but work in src/itsdangerous/signer.py and test it in tests/test_itsdangerous/test_signer.py. For a timestamp feature, work in src/itsdangerous/timed.py and cover it in tests/test_itsdangerous/test_timed.py.
Dependency inventory
Declared dependencies, parsed directly from the manifests (no AI involved).
python
| Package | Version | Scope | Declared in |
|---|---|---|---|
freezegun |
* | dev | pyproject.toml |
gha-update |
* | dev | pyproject.toml |
mypy |
* | dev | pyproject.toml |
pallets-sphinx-themes |
* | dev | pyproject.toml |
pre-commit |
* | dev | pyproject.toml |
pre-commit-uv |
* | dev | pyproject.toml |
pyright |
* | dev | pyproject.toml |
pytest |
* | dev | pyproject.toml |
pytest |
* | dev | pyproject.toml |
ruff |
* | dev | pyproject.toml |
sphinx |
* | dev | pyproject.toml |
sphinx-autobuild |
* | dev | pyproject.toml |
sphinxcontrib-log-cabinet |
* | dev | pyproject.toml |
tox |
* | dev | pyproject.toml |
tox-uv |
* | dev | pyproject.toml |
Current versions (checked 2026-11-10)
Latest versions and release dates from the package registries via deps.dev (no AI involved). New marks versions released in the last 12 months: the model may not know them, so the guide describes them only as this code uses them.
| Package | In this repository | Released | Latest | Latest released | Notes |
|---|---|---|---|---|---|
ruff |
* | — | 0.17.4 | 2026-11-05 | |
tox |
* | — | 4.67.13 | 2026-11-06 | |
tox-uv |
* | — | 1.37.7 | 2026-11-07 | |
pallets-sphinx-themes |
* | — | 2.5.0 | 2026-02-25 | |
sphinx |
* | — | 9.2.0 | 2026-10-21 | |
sphinxcontrib-log-cabinet |
* | — | 1.0.1 | 2019-07-05 | |
sphinx-autobuild |
* | — | 2025.8.25 | 2025-08-25 | |
gha-update |
* | — | 0.2.0 | 2025-07-14 | |
pre-commit |
* | — | 4.7.0 | 2026-10-12 | |
pre-commit-uv |
* | — | 4.4.2 | 2026-11-04 | |
freezegun |
* | — | 1.5.5 | 2025-08-09 | |
pytest |
* | — | 9.2.0 | 2026-10-27 | |
mypy |
* | — | 2.4.1 | 2026-10-28 | |
pyright |
* | — | 1.1.414 | 2026-09-10 |
Caveats & omitted files
This document was generated automatically from the code at commit 672971d66a2e. Its grounding score measures structure and grounding (real paths, real symbols, resolvable citations), not factual correctness. Check important details in the code.
How strongly names were checked
- Exact (parsed with Python's
ast): Python (15 files). - Not indexed: Shell (1 files), Make (1 files). Names in these files were checked against the raw repository text only.
Omitted files
| File | Why it was skipped |
|---|---|
docs/_static/itsdangerous-icon.svg |
binary or media asset |
docs/_static/itsdangerous-logo.svg |
binary or media asset |
docs/_static/itsdangerous-name.svg |
binary or media asset |
uv.lock |
lockfile |
Want this for your codebase, or an agent built the same way? Talk to AELSHA™.