Skip to main content

python-constricter

EXPERIMENTAL UNTIL v1.0.0

I want all of my python code typed.

CI Security PyPI Python OpenSSF Scorecard Test coverage: 100% Annotations: 100% License: MIT

Lint rules: every local variable is typed where it's first bound. Ships as a flake8 plugin, a pylint plugin and a standalone command (for ruff, which loads no plugins).

            /^\/^\
          _|__|  O|
\/     /~     \_/ \
  \____|__________/  \
        \_______      \
                `\     \                 \
                  |     |                  \
                  /      /                    \
                /     /                       \\
              /      /                         \ \
              /     /                            \  \
            /     /             _----_            \   \
          /     /           _-~      ~-_         |   |
          (      (        _-~    _--_    ~-_     _/   |
          \      ~-____-~    _-~    ~-_    ~-_-~    /
            ~-_           _-~          ~-_       _-~
                ~--______-~                ~-___-~

def total(items: list[int]) -> int:
    count = 0  # LVA001
    result: int = 0  # ok
    first, *rest = items  # LVA001 twice
    head: int
    tail: list[int]
    head, *tail = items  # ok: declared first
    if (n := len(items)) > 3:  # LVA001
        result = n  # ok: rebinding
    for item in items:  # LVA002
        result += item
    for other in items:  # type: int  # LVA003
        result += other
    value: int
    for value in items:  # ok: declared first
        result += value
    return result

Rules

Checked per function body, including methods and nested functions; with all-scopes, module and class bodies too. Statements are read in source order, and only a name's first binding counts (LVA008–LVA010 aside, which read every one).

Code Reports Fix
LVA001 =, unpacking, := or with ... as in a function without annotation name: T = ..., or name: T first
LVA002 an untyped for target or match capture name: T first (or a type comment)
LVA003 a for target typed only by # type: T name: T first
LVA004 with all-scopes: the same as LVA001, in a module or class body name: T = ... (ClassVar[T] in a dataclass)
LVA005 an annotation with Any, object or a generic without its parameters, past vague name the real type
LVA006 an annotation nested nesting deep (3 by default) a type alias for a part of it
LVA007 a name annotated again with the type it already has, in the same block drop the second annotation
LVA008 with every value the name ever holds known: an annotation that could narrow to them narrow it (total: int)
LVA009 a value, anywhere in the name's lifetime, whose type doesn't fit its annotation fix the value, or widen the annotation
LVA010 with every value known: a union member no value is drop the member
LVA011 an annotation listing a fixed-length tuple of more than max-length types (4 by default) name the fields (a NamedTuple, a dataclass)
LVA012 opt-in: a local bound once, outside any loop, and never rebound name: Final = ...

Exempt: comprehensions, except ... as, imports, def/class, type aliases, parameters, global/nonlocal, and _; in module and class bodies, dunder names (__all__, __slots__) and enum members (a base imported from enum, however it's aliased, or else whose name ends in Enum or Flag). And what makes a type, not a value, which an annotation would turn into a variable to a type checker: T = TypeVar("T"), a ParamSpec, a TypeVarTuple, a NewType, and a functional NamedTuple, TypedDict, Enum or collections.namedtuple, however typing, typing_extensions, enum or collections is imported.

A # type: comment (x = 1 # type: int, with f() as x: # type: T) counts as an annotation with type-comments, or automatically in a module written to run on Python 2: one that imports print_function, unicode_literals, absolute_import, division, with_statement, generators or nested_scopes from __future__.

LVA007 compares a block on its own: an if's body and its orelse, a try's body and its excepts, and the like, are different blocks, since they don't both run in the same pass.

LVA009 checks every binding of an annotated name (or parameter) in the scope, wherever and in whatever order they run, but only one whose value's type --fix would infer with certainty, and only against types whose every subclass is known: builtins, and classes the module defines on such bases. An imported class, a protocol or an alias is never compared, builtin containers are compared by the container alone (flags: tuple[str, ...] = ("-q",) fits), a copy of a union-typed name is skipped (an is None check may have narrowed it), and so is a name annotated only under if TYPE_CHECKING:. It has no --fix.

LVA008 and LVA010 also need every binding's value known (one unknown call, loop target or unpacking and the name could hold anything), and are only claimed for a function's own names: a module or class variable is state other code rebinds out of sight (mod.X = ..., self.x = ..., monkeypatch), and a nonlocal write from a nested function counts as unknown too. Neither has a --fix: --fix adds annotations, it doesn't rewrite them.

Levels

Each level makes one more code an error. The rest are warnings: the CLI prints them (as ::warning or SARIF warning in those formats) but exits 0; flake8 and pylint report errors only.

Level Errors Warnings
relaxed / 0 none LVA001–LVA004, LVA007, LVA009
strict / 1 LVA001, LVA004 (the default) LVA002, LVA003, LVA005–LVA007, LVA009, LVA011
constrict / 2 LVA001, LVA004, LVA002, LVA009 LVA003, LVA005–LVA008, LVA010, LVA011
suffocate / 3 all none

LVA005, LVA006 and LVA011 aren't reported at relaxed; LVA008 and LVA010 only from constrict. LVA012 is opt-in, reported only when selected by its full code (--extend-select LVA012, flake8's extend-select = LVA012, pylint's enable = could-be-final), at every level, and an error only at suffocate: on the corpus, 45–70% of every codebase's first bindings qualify, so it suits a codebase that wants Final everywhere it can go, not a default.

Python 3.11+, no runtime dependencies.

Use

Tool Setup Reports Suppress
CLI constricter [PATH...] [--level L] [--format F] [-q] LVA001–LVA012 # noqa: LVA001
flake8 install it (on by default) LVA001–LVA012 # noqa: LVA001
pylint load-plugins = ["constricter.plugins.pylint"] C9101–C9112 (symbols below) # noqa: LVA001 or # pylint: disable=<symbol>
ruff run the CLI after ruff; set lint.external = ["LVA"] LVA001–LVA012 # noqa: LVA001

pylint symbols: unannotated-local-variable, untyped-for-or-match-variable, comment-typed-for-variable, unannotated-module-or-class-variable, vague-annotation, deeply-nested-annotation, redundant-annotation, narrowable-annotation, mismatched-value-type, unused-union-member, long-tuple-annotation, could-be-final (off until enabled).

Options:

Option CLI [tool.constricter] flake8 (CLI or config) pylint
level --level level --constricter-level constricter-level
strictest --max: --level=suffocate for every path, --all-scopes, and the opt-in LVA012 — — —
every fix --max-fix: --max, --fix --unsafe-fixes, and --infer-with each of basedpyright, ty and pyrefly that's installed and runs — — —
type comments --type-comments type-comments --constricter-type-comments constricter-type-comments = yes
all scopes --all-scopes all-scopes --constricter-all-scopes constricter-all-scopes = yes
nesting --nesting N nesting --constricter-nesting constricter-nesting
max length --max-length N (LVA011) max-length --constricter-max-length constricter-max-length
vague --vague LEVEL (LVA005, and the fixes offered): -1 none (the default), 0 one Any inside a type that says the rest (tuple[str, Any]), N from 1 N + 1, or one alone vague --constricter-vague constricter-vague
min python --min-python VERSION (the oldest Python the code runs on, whose syntax --fix writes; default: requires-python's) min-python - -
type hierarchy - narrower (a table) --constricter-narrower constricter-narrower
fix --fix (--unsafe-fixes for guesses, --likely for those measured to hold), --diff to preview - - -
infer with --infer-with CHECKERS (basedpyright, ty, pyrefly, several: inferred types, as guesses) infer-with - -
infer from --infer-from FILE (the types python -m constricter.trace -m pytest recorded from a run, as guesses) infer-from - -
show fixes --show-fixes (each fix and how it was decided; with --fix, those made too) - - -
fix levels --fix-select, --fix-ignore, --unsafe-fix-select (mechanisms: docs/FIXES.md) fix-select, fix-ignore, unsafe-fix-select - -
fix plain bases --fix-plain-bases BASES (frameworks' classes whose subclasses' bodies --fix annotates; django's are built in) fix-plain-bases - -
fix widen --fix-widen KINDS (wider types --fix may write, each marked: untyped-parameters, empty-containers, mixed-containers, unions, vague, untyped-calls, unknown-calls; all: every one; docs/FIXES.md) fix-widen - -
select --select CODES (codes or prefixes) select flake8's own select pylint's own enable
extend select --extend-select CODES (also report these; an opt-in code by its full code) extend-select flake8's own extend-select pylint's own enable
ignore --ignore CODES ignore flake8's own extend-ignore pylint's own disable
exclude --exclude GLOB (repeatable) exclude flake8's own exclude pylint's own ignore-paths
format --format: text, full (with source), json, github, sarif, gitlab, junit, rdjson - - -
statistics --statistics (counts per code, text format) - - -
jobs --jobs N (-j; 0: one per CPU) jobs flake8's own --jobs pylint's own --jobs
baseline --baseline FILE; --write-baseline records it baseline - -
coverage --coverage, --fail-under PCT - - -
per-path levels - per-path-levels - -
per-file ignores - per-file-ignores flake8's own per-file-ignores -
stdin - as the path, --stdin-filename PATH - flake8's own - -
exit status --exit-zero - flake8's own --exit-zero pylint's own --exit-zero
output file --output-file FILE - flake8's own --output-file pylint's own --output

constricter --explain LVA002 prints a code's rationale, its fix, and the levels that report it.

The CLI reads [tool.constricter] from the nearest pyproject.toml above the current directory; its flags override it, and --exclude adds to it. An unknown key or a bad value exits 2.

[tool.constricter]
level = "constrict" # or 2
exclude = ["tests/fixtures/*"]
type-comments = false
all-scopes = true
nesting = 3
max-length = 4
vague = -1 # the default: no `Any`; 0 lets `dict[str, Any]` through, 1 `Any` itself
min-python = "3.11" # the default: your `requires-python`'s lower bound
jobs = 0
baseline = "constricter-baseline.json" # the default; relative to this pyproject.toml

# The first glob a file matches sets its level; other files get `level`.
[tool.constricter.per-path-levels]
"tests/*" = "strict"

# Codes (or prefixes) to drop for files matching a glob.
[tool.constricter.per-file-ignores]
"tests/fixtures/*" = ["LVA005", "LVA006"]

# Your own type hierarchy for LVA008–LVA010: each type, and the types it's narrower than.
[tool.constricter.narrower]
UserId = ["str"]  # an imported NewType the rules then compare
int = []          # an `int` no longer fits `float`
select = ["LVA00"]
ignore = ["LVA003"]

--fix adds the annotation where the value decides it: a literal (count = 0 becomes count: int = 0), a container whose elements agree, a constructor or a function that declares its return type or whose returns agree (in another checked file too), a copy, subscript, attribute or method call of a local whose type is known, and values computed from those; a loop's target or an unpacking's names get a declaration on the line before. --unsafe-fixes adds guesses, --likely only those measured to hold as often as a certain fix (docs/LIKELY.md), and --show-fixes lists each fix and how its value decided it, and after --fix each one made. --infer-with basedpyright (or ty, or pyrefly, or several: basedpyright,ty; each installed alongside) asks those type checkers for what --fix can't type itself, as guesses; --infer-from FILE takes the types a run bound each name to, recorded by python -m constricter.trace -m pytest, the same way. The full list is in docs/FIXES.md.

Installing and running

pip install python-constricter           # into the project's environment
uvx --from python-constricter constricter # or run it without installing: uv's tool runner
pipx run --spec python-constricter constricter  # or pipx's

On CPython 3.11 to 3.14 for Linux, macOS and Windows, pip installs a build compiled with mypyc, about a fifth faster; anywhere else, the pure Python one, which finds and fixes the same.

Tools that run flake8 or pylint (VS Code's extensions, python-lsp-server, prospector, MegaLinter, Trunk) pick the plugin up once it's installed alongside them.

Without lint.external, ruff flags # noqa: LVA00x (RUF102) and --fix deletes it.

The CLI defaults to ., checks *.py and *.ipynb, and skips hidden dirs, __pycache__, venv, site-packages, build, dist and node_modules by directory name; --exclude adds more directory names (or globs) to skip the same way, on top of matching whole paths and file names. Under a directory in a git checkout it checks only what git tracks or would, so nothing a .gitignore names (a file named on the command line is checked regardless); --no-gitignore, or gitignore = false, walks the directory whole. Exit codes: 0 no errors, 1 errors, 2 an unreadable or unparsable file, a --fix its encoding can't hold, or a bad pyproject.toml. A module is read in its PEP 263 declaration's encoding.

pre-commit, after ruff's hooks (or constricter-fix, which runs --fix first):

- repo: https://github.com/ivylikethevine/python-constricter
  rev: vX.Y.Z # the latest release; `pre-commit autoupdate` sets it
  hooks:
    - id: constricter

pre-commit.ci, tox, nox, Bazel, Pants and the GitHub Action (PR annotations, a summary table and a SARIF log) are in docs/INTEGRATIONS.md; settings for VS Code, Zed and Neovim are in docs/editors/.

Baselines

To adopt constricter on a codebase that already has offences, record them, then report only new ones:

constricter --write-baseline src # writes constricter-baseline.json next to pyproject.toml
constricter src                  # reports only offences the baseline doesn't cover

A baseline counts each file's offences by code and variable name, not line number, so it survives code moving around; another offence for a name it covers is still reported. Paths in it are relative to it. It's JSON, and like every JSON file constricter reads it may have // and /* */ comments and trailing commas. --baseline FILE or baseline in [tool.constricter] names another file; the default one is used only if it exists.

Annotation coverage

constricter --coverage src prints the share of first bindings that are typed, per file and in total; the bindings are the ones the rules cover (with --all-scopes, module and class bodies too), and # noqa doesn't make one typed. --fail-under PCT (which implies --coverage) exits 1 below PCT, so CI can hold a codebase to a share. With --format=json it prints {"typed", "total", "widened", "percent", "files"}, which a badge can read: publish that JSON somewhere (a gist, a release asset) and point shields.io's dynamic JSON badge at it with the query $.percent. This project keeps its own share at 100% in CI, so its badge is static.

Notebooks

.ipynb files are checked too (directories include them): their code cells are read as one module, IPython-only lines (%magic, !shell, obj?, %%cell magics) are skipped, and each offence is reported at its cell and line (analysis.ipynb:cell 3:2:5). JSON output has a cell field; GitHub and SARIF output point at the file and put the cell in the message. --fix and --diff edit the cells, keeping the notebook's formatting.

Adopting it on an existing codebase

  1. See the scale: constricter --statistics src counts offences per code.
  2. Record them: constricter --write-baseline src, and commit constricter-baseline.json.
  3. Enforce it for new code: add the pre-commit hook or the GitHub Action; the baseline keeps old offences quiet, and --diff / --fix clear the easy ones.
  4. Burn it down: fix a file or package at a time, then --write-baseline again to shrink the file.
  5. Tighten: raise level (or per-path-levels for the parts that are clean), then turn on all-scopes.

Output formats

--format is text (the default), json, github (workflow annotations), sarif (below), gitlab (Code Climate JSON, for GitLab's merge-request Code Quality widget: pass the file as a codequality report artifact), junit (a test suite per file, a failed test case per offence, for Jenkins, Azure Pipelines, CircleCI or GitLab's test reports) or rdjson (for reviewdog, with each certain fix as a suggestion). --output-file FILE writes the report there, and --exit-zero exits 0 even when there are errors (not when a file can't be read).

Editors (standard input)

constricter - --stdin-filename path/to/file.py checks standard input, reported as that path (which also picks its per-path level and baseline entry; a .ipynb name reads a notebook). With --fix it prints the fixed source instead of a report, and --diff diffs it. That's what editors that lint unsaved buffers through a command need (none-ls, nvim-lint, flycheck, ALE, efm-langserver, Helix).

SARIF (code scanning)

--format=sarif writes SARIF 2.1.0, with each result's level (error or warning) set by --level. Each rule has its help text and a link to Rules, and each certain fix is a SARIF fix (columns count characters: columnKind is unicodeCodePoints). In GitHub Actions, upload it to code scanning (the job needs security-events: write; the GitHub Action's sarif-file output does the same):

- run: constricter --format=sarif src > constricter.sarif
- if: ${{ !cancelled() }} # upload the findings even when the step above failed on them
  uses: github/codeql-action/upload-sarif@24c54180a607b1449ed407dd24f251e4e9147c8d # v4.38.3
  with:
    sarif_file: constricter.sarif
    category: constricter

SonarQube and SonarCloud import it with sonar.sarifReportPaths=constricter.sarif; any other tool that reads SARIF 2.1.0 takes the same file.

Development

Setting up, the checks CI runs, the corpus runs and the rules this project's own linters leave off are in docs/CONTRIBUTING.md.

Roadmap

What's done and what's next, by scope: docs/ROADMAP.md.

AI usage

Heavily inspired by Dictionarry/Profilarr's AI Transparency Statement.

I have used generative AI to write large parts of this code. All of the code here is my responsibility regardless: AI is a tool, not an owner of a project. I have personally understood, reviewed, and approved all of the AI-generated code in this repository, and mainline releases carry the same accountability to me as anything I write and publish myself.

Metadata

Release files for python-constricter 0.4.2

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for python-constricter 0.4.2
File Size Uploaded
python_constricter-0.4.2.tar.gz 644.8 kB Details

Built distributions (wheels)

Table of built distributions (wheels) for python-constricter 0.4.2
File
python_constricter-0.4.2-py3-none-any.whl Python 3 none any Details
python_constricter-0.4.2-cp314-cp314-win_amd64.whl CPython 3.14 CPython 3.14 Windows x86-64 Details
python_constricter-0.4.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.14 CPython 3.14 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
python_constricter-0.4.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.14 CPython 3.14 Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 Details
python_constricter-0.4.2-cp314-cp314-macosx_11_0_arm64.whl CPython 3.14 CPython 3.14 macOS 11.0+ ARM64 Details
python_constricter-0.4.2-cp314-cp314-macosx_10_15_x86_64.whl CPython 3.14 CPython 3.14 macOS 10.15+ x86-64 Details
python_constricter-0.4.2-cp313-cp313-win_amd64.whl CPython 3.13 CPython 3.13 Windows x86-64 Details
python_constricter-0.4.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.13 CPython 3.13 Linux glibc 2.28+ x86-64, Linux glibc 2.17+ x86-64 Details
python_constricter-0.4.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.13 CPython 3.13 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
python_constricter-0.4.2-cp313-cp313-macosx_11_0_arm64.whl CPython 3.13 CPython 3.13 macOS 11.0+ ARM64 Details
python_constricter-0.4.2-cp313-cp313-macosx_10_13_x86_64.whl CPython 3.13 CPython 3.13 macOS 10.13+ x86-64 Details
python_constricter-0.4.2-cp312-cp312-win_amd64.whl CPython 3.12 CPython 3.12 Windows x86-64 Details
python_constricter-0.4.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.12 CPython 3.12 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
python_constricter-0.4.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.12 CPython 3.12 Linux glibc 2.28+ ARM64, Linux glibc 2.17+ ARM64 Details
python_constricter-0.4.2-cp312-cp312-macosx_11_0_arm64.whl CPython 3.12 CPython 3.12 macOS 11.0+ ARM64 Details
python_constricter-0.4.2-cp312-cp312-macosx_10_13_x86_64.whl CPython 3.12 CPython 3.12 macOS 10.13+ x86-64 Details
python_constricter-0.4.2-cp311-cp311-win_amd64.whl CPython 3.11 CPython 3.11 Windows x86-64 Details
python_constricter-0.4.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ x86-64, Linux glibc 2.28+ x86-64 Details
python_constricter-0.4.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl CPython 3.11 CPython 3.11 Linux glibc 2.17+ ARM64, Linux glibc 2.28+ ARM64 Details
python_constricter-0.4.2-cp311-cp311-macosx_11_0_arm64.whl CPython 3.11 CPython 3.11 macOS 11.0+ ARM64 Details
python_constricter-0.4.2-cp311-cp311-macosx_10_9_x86_64.whl CPython 3.11 CPython 3.11 macOS 10.9+ x86-64 Details

Total release size: 75.8 MB

Release files / python_constricter-0.4.2.tar.gz

Download URL python_constricter-0.4.2.tar.gz
Size 644.8 kB
Tags Source
SHA-256 checksum
How to use checksums
05c85b3e6540f59242b3772b59837c0a9a414263d2853de07b9ab0f3d69783cc
BLAKE2b-256 checksum
How to use checksums
1b578e1ef8efc7a474c319776e0fe52954acc5393a9e1143bdc3f60a8ad1735a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-py3-none-any.whl

Download URL python_constricter-0.4.2-py3-none-any.whl
Size 668.5 kB
Tags Python 3
SHA-256 checksum
How to use checksums
e0c46163898ddf1f5fd5882358f2fd082fd415004b824250ca46238f90faf2fd
BLAKE2b-256 checksum
How to use checksums
478753fa15b555250db1d30d56cb2c72eb853db2ea804a76f0fdbb35f737aab7
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp314-cp314-win_amd64.whl

Download URL python_constricter-0.4.2-cp314-cp314-win_amd64.whl
Size 3.4 MB
Tags CPython 3.14 Windows x86-64
SHA-256 checksum
How to use checksums
edf0348cbac159218551493b3f6dea35c2971e8e925bec5ccbf3779d049cfc2f
BLAKE2b-256 checksum
How to use checksums
4fa97b8355b641224b740f7ce37791486982fcb0fdb6b17ec2ff828c34f2cfdb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL python_constricter-0.4.2-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 3.8 MB
Tags CPython 3.14 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
dd652ed52d82edd4244d1910d303f9ef134e51c7bb5bc310797aae9cded3febc
BLAKE2b-256 checksum
How to use checksums
86f57a31d31cf221f79b286b6cd2b0897621d005d26c9363458f04b8a0b2c673
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL python_constricter-0.4.2-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 3.5 MB
Tags CPython 3.14 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
f9e50f81276aee11297d2830140c3246591c442d7bfeb8720658dc07990bb596
BLAKE2b-256 checksum
How to use checksums
a9d897cc79a0a0da18a76b3ce6dd42b7e4ae225b1c0fee708885f41c022918d3
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp314-cp314-macosx_11_0_arm64.whl

Download URL python_constricter-0.4.2-cp314-cp314-macosx_11_0_arm64.whl
Size 3.8 MB
Tags CPython 3.14 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
8cac8e456f486366d3a74b5b5556a1ce69966e4df5e6af0eca668970a76b22ec
BLAKE2b-256 checksum
How to use checksums
a0ff546041e5b04f7ff257a7f839dcb747b2b3872b352bb7da85a8c55479d9c8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp314-cp314-macosx_10_15_x86_64.whl

Download URL python_constricter-0.4.2-cp314-cp314-macosx_10_15_x86_64.whl
Size 4.1 MB
Tags CPython 3.14 macOS 10.15+ x86-64
SHA-256 checksum
How to use checksums
e99210a69ce9b079a032fd18312ab65a0892b1d2bce32dabeab28aef54637009
BLAKE2b-256 checksum
How to use checksums
51e7ce1a0f62cad308b38721147c211ca55ab76c429343118ad869111efe8d1c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp313-cp313-win_amd64.whl

Download URL python_constricter-0.4.2-cp313-cp313-win_amd64.whl
Size 3.3 MB
Tags CPython 3.13 Windows x86-64
SHA-256 checksum
How to use checksums
1a771f4971f4a0aa294a6fd8bbd6f7205fc3277e663bd9d833c39b491c5df6f3
BLAKE2b-256 checksum
How to use checksums
c36b82499c926a25d54fab0ed6644f708e7d5c0d939e3572b49748c32c9f4d5e
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL python_constricter-0.4.2-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 3.9 MB
Tags CPython 3.13 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
c5a0b1b6eb2caa924e6808cf2bf942977613f37f0898061fd532fc4a61700844
BLAKE2b-256 checksum
How to use checksums
3fc3e18c40b753a9499ee20fc991b8b459a093418377a0b013480f9b7ece5ecd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL python_constricter-0.4.2-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 3.5 MB
Tags CPython 3.13 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
70d82cd38da46381c14f660b3d70c85d1e71331c111e0d250600aab885ebf869
BLAKE2b-256 checksum
How to use checksums
d58363d360ca07f2057ba98e8e759566cebda802eab2f0cdf67843ce17461100
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp313-cp313-macosx_11_0_arm64.whl

Download URL python_constricter-0.4.2-cp313-cp313-macosx_11_0_arm64.whl
Size 3.8 MB
Tags CPython 3.13 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
8a0de15423d7b0d0d824e2806ad2976510a1c71f74963331c350a9bc88b281a4
BLAKE2b-256 checksum
How to use checksums
54abf0858e5f88640c137505f74c0fc4e18cfee751054db18459d977eab9957c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp313-cp313-macosx_10_13_x86_64.whl

Download URL python_constricter-0.4.2-cp313-cp313-macosx_10_13_x86_64.whl
Size 4.1 MB
Tags CPython 3.13 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
104c5e439762d43a94307e011c0c05d07d5071e7291da11edd09ee49399d2a8e
BLAKE2b-256 checksum
How to use checksums
aad3acaea8d50279aabcc51ec8ab04d82e6254b4e4bfc9570189274664723fe0
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp312-cp312-win_amd64.whl

Download URL python_constricter-0.4.2-cp312-cp312-win_amd64.whl
Size 3.3 MB
Tags CPython 3.12 Windows x86-64
SHA-256 checksum
How to use checksums
9df0a2c32b548ef4a29ba5b55bbd9b4286aeb790e60df9a7ccde84e699051bfc
BLAKE2b-256 checksum
How to use checksums
de671bf4f2c7159110ea510e3d66bd47c8a8505c839f4bc5adcce068f80500ca
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL python_constricter-0.4.2-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 3.9 MB
Tags CPython 3.12 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
a7537713a1768747c55d5cd8fd0490af14113a919114d95e4836729e2f45dbfd
BLAKE2b-256 checksum
How to use checksums
99ebb2f0fbca02cfb44959fb8285d6438e2b261d9884e0c6c2ae8c1e9d2eca8f
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL python_constricter-0.4.2-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 3.6 MB
Tags CPython 3.12 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
489f0b7ae118b6605daa1d4daf3ec462d23c2106f5a15b04444e73ada08f55ec
BLAKE2b-256 checksum
How to use checksums
4d477eaf03e663339d48cabbcc257f6ffacd94e8460dae246976f50d12405d0c
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp312-cp312-macosx_11_0_arm64.whl

Download URL python_constricter-0.4.2-cp312-cp312-macosx_11_0_arm64.whl
Size 3.8 MB
Tags CPython 3.12 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e0360496203625eb8c0056a27ae30added7c0fb9f1bcd782fa835aa99127dded
BLAKE2b-256 checksum
How to use checksums
301f70486bf3d964844b5280262513ef15a3b1a3b8099b6533aea81a7c659a7b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp312-cp312-macosx_10_13_x86_64.whl

Download URL python_constricter-0.4.2-cp312-cp312-macosx_10_13_x86_64.whl
Size 4.2 MB
Tags CPython 3.12 macOS 10.13+ x86-64
SHA-256 checksum
How to use checksums
40aa97504e49fbdc2b766bcaeb7be9787dbf21e271f684fda39648d745a09bcd
BLAKE2b-256 checksum
How to use checksums
38c8044754d65cbe2fbbfa509af4942bade965b06761dd09dc5883a9b98ab268
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp311-cp311-win_amd64.whl

Download URL python_constricter-0.4.2-cp311-cp311-win_amd64.whl
Size 3.3 MB
Tags CPython 3.11 Windows x86-64
SHA-256 checksum
How to use checksums
ce0c5371002630576c9b53544217b6f1fc533d264e86f431993f23937d29ce4c
BLAKE2b-256 checksum
How to use checksums
f7c4fe1fbda4754a58cdddc9f4db9eea1877bb05c4374c849b7572ba0aff75fb
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl

Download URL python_constricter-0.4.2-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl
Size 3.8 MB
Tags CPython 3.11 Linux glibc 2.17+ x86-64 Linux glibc 2.28+ x86-64
SHA-256 checksum
How to use checksums
e57d16d2a4a1782ab0f9d855e47025d2aed625381a5a21ff3b903d5f8e0f8fc1
BLAKE2b-256 checksum
How to use checksums
8dfc27f53fa798ea05e986045e53bf267663238254627f15ba223a59a25dd237
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl

Download URL python_constricter-0.4.2-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl
Size 3.6 MB
Tags CPython 3.11 Linux glibc 2.17+ ARM64 Linux glibc 2.28+ ARM64
SHA-256 checksum
How to use checksums
29c858d4338a5720c2712b1c9967b0c2430a893c91ee0420813af9a2e3f470d8
BLAKE2b-256 checksum
How to use checksums
1273f78329677e0053882ea835e903f794ec6daece469bbd2d7ca91becd34775
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp311-cp311-macosx_11_0_arm64.whl

Download URL python_constricter-0.4.2-cp311-cp311-macosx_11_0_arm64.whl
Size 3.8 MB
Tags CPython 3.11 macOS 11.0+ ARM64
SHA-256 checksum
How to use checksums
e0d95b0bb680ad5b1c5964d8fc4a0436f4fa99a6f967d949bd49e5e347f86148
BLAKE2b-256 checksum
How to use checksums
658eecff1c4b34a80ca125494af0f3eec16b2fcd7fda94cf789ba10eedc75ca5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release files / python_constricter-0.4.2-cp311-cp311-macosx_10_9_x86_64.whl

Download URL python_constricter-0.4.2-cp311-cp311-macosx_10_9_x86_64.whl
Size 4.1 MB
Tags CPython 3.11 macOS 10.9+ x86-64
SHA-256 checksum
How to use checksums
6ee3b49c073b4494cc6277f8668af81ce2584064a6338fc17eecc18345770ffc
BLAKE2b-256 checksum
How to use checksums
310a9ca79a8944eb19d7b7df37126cc291b286ec9b7fd82cc72cfce0f6f4f330
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 19, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.4.2 This release

22 release files

0.4.1

26 release files

0.3.6

2 release files

0.3.5

2 release files

0.3.3

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.2.9

2 release files

0.2.8

2 release files

0.2.7

2 release files

0.2.5

2 release files

0.2.4

2 release files

0.2.3

2 release files

0.2.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page