lanky 0.0.1__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- lanky-0.0.1/.github/workflows/ci.yml +34 -0
- lanky-0.0.1/.github/workflows/publish.yml +23 -0
- lanky-0.0.1/.gitignore +39 -0
- lanky-0.0.1/LICENSE +21 -0
- lanky-0.0.1/PKG-INFO +90 -0
- lanky-0.0.1/README.md +68 -0
- lanky-0.0.1/pyproject.toml +50 -0
- lanky-0.0.1/src/lanky/__init__.py +20 -0
- lanky-0.0.1/src/lanky/cli.py +24 -0
- lanky-0.0.1/src/lanky/ledger.py +70 -0
- lanky-0.0.1/src/lanky/plugins.py +120 -0
- lanky-0.0.1/src/lanky/py.typed +0 -0
- lanky-0.0.1/tests/test_smoke.py +45 -0
- lanky-0.0.1/uv.lock +109 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
|
|
8
|
+
concurrency:
|
|
9
|
+
group: ci-${{ github.ref }}
|
|
10
|
+
cancel-in-progress: true
|
|
11
|
+
|
|
12
|
+
jobs:
|
|
13
|
+
test:
|
|
14
|
+
runs-on: ubuntu-latest
|
|
15
|
+
strategy:
|
|
16
|
+
fail-fast: false
|
|
17
|
+
matrix:
|
|
18
|
+
python-version: ["3.12", "3.13"]
|
|
19
|
+
steps:
|
|
20
|
+
- uses: actions/checkout@v5
|
|
21
|
+
|
|
22
|
+
- name: Install uv
|
|
23
|
+
uses: astral-sh/setup-uv@v7
|
|
24
|
+
with:
|
|
25
|
+
enable-cache: true
|
|
26
|
+
|
|
27
|
+
- name: Sync dependencies
|
|
28
|
+
run: uv sync --group dev --python ${{ matrix.python-version }}
|
|
29
|
+
|
|
30
|
+
- name: Lint
|
|
31
|
+
run: uv run ruff check .
|
|
32
|
+
|
|
33
|
+
- name: Test
|
|
34
|
+
run: uv run pytest -q
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
name: Publish
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags: ["v*"]
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
publish:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
permissions:
|
|
11
|
+
# Required for PyPI Trusted Publishing (OIDC).
|
|
12
|
+
id-token: write
|
|
13
|
+
steps:
|
|
14
|
+
- uses: actions/checkout@v5
|
|
15
|
+
|
|
16
|
+
- name: Install uv
|
|
17
|
+
uses: astral-sh/setup-uv@v7
|
|
18
|
+
|
|
19
|
+
- name: Build sdist and wheel
|
|
20
|
+
run: uv build
|
|
21
|
+
|
|
22
|
+
- name: Publish to PyPI
|
|
23
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
lanky-0.0.1/.gitignore
ADDED
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
# Byte-compiled / optimized / DLL files
|
|
2
|
+
__pycache__/
|
|
3
|
+
*.py[cod]
|
|
4
|
+
*$py.class
|
|
5
|
+
|
|
6
|
+
# Distribution / packaging
|
|
7
|
+
build/
|
|
8
|
+
dist/
|
|
9
|
+
sdist/
|
|
10
|
+
wheels/
|
|
11
|
+
*.egg-info/
|
|
12
|
+
*.egg
|
|
13
|
+
.eggs/
|
|
14
|
+
|
|
15
|
+
# Virtual environments
|
|
16
|
+
.venv/
|
|
17
|
+
venv/
|
|
18
|
+
env/
|
|
19
|
+
|
|
20
|
+
# Testing / coverage
|
|
21
|
+
.pytest_cache/
|
|
22
|
+
.coverage
|
|
23
|
+
.coverage.*
|
|
24
|
+
coverage.xml
|
|
25
|
+
htmlcov/
|
|
26
|
+
.tox/
|
|
27
|
+
.nox/
|
|
28
|
+
|
|
29
|
+
# Type checkers / linters
|
|
30
|
+
.mypy_cache/
|
|
31
|
+
.ruff_cache/
|
|
32
|
+
.pyre/
|
|
33
|
+
.pytype/
|
|
34
|
+
|
|
35
|
+
# Editors / OS
|
|
36
|
+
.idea/
|
|
37
|
+
.vscode/
|
|
38
|
+
*.swp
|
|
39
|
+
.DS_Store
|
lanky-0.0.1/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Xiaoyu Wei
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
lanky-0.0.1/PKG-INFO
ADDED
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: lanky
|
|
3
|
+
Version: 0.0.1
|
|
4
|
+
Summary: Python for math you can check. A Lean-hosted proof language, shaped like mypy.
|
|
5
|
+
Project-URL: Homepage, https://github.com/xywei/lanky
|
|
6
|
+
Project-URL: Repository, https://github.com/xywei/lanky
|
|
7
|
+
Author: Xiaoyu Wei
|
|
8
|
+
License-Expression: MIT
|
|
9
|
+
License-File: LICENSE
|
|
10
|
+
Keywords: formal-methods,lean,mathlib,proof,theorem-proving,type-checking
|
|
11
|
+
Classifier: Development Status :: 1 - Planning
|
|
12
|
+
Classifier: Intended Audience :: Science/Research
|
|
13
|
+
Classifier: Programming Language :: Python :: 3
|
|
14
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
15
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
16
|
+
Classifier: Topic :: Scientific/Engineering :: Mathematics
|
|
17
|
+
Classifier: Topic :: Software Development :: Quality Assurance
|
|
18
|
+
Classifier: Typing :: Typed
|
|
19
|
+
Requires-Python: >=3.12
|
|
20
|
+
Provides-Extra: lean
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
|
|
23
|
+
# lanky
|
|
24
|
+
|
|
25
|
+
Python for math you can check.
|
|
26
|
+
|
|
27
|
+
lanky is a Python-hosted proof language with Lean 4 and Mathlib as the platform,
|
|
28
|
+
shaped like mypy: hints are inert, the body is executable Python, and an external
|
|
29
|
+
command does the checking. Theorems are typed Python functions (variables are
|
|
30
|
+
parameters, hypotheses are parameters annotated with propositions, the goal is the
|
|
31
|
+
return annotation); proofs are Python programs that drive Lean tactics over a live
|
|
32
|
+
goal; the recorded tactic script is the certificate; under plain `python` the
|
|
33
|
+
theorems run as property tests. Lean is the platform, lanky is a hosted language on
|
|
34
|
+
it (the Kotlin/JVM relationship), so all of Mathlib and every Lean tactic are
|
|
35
|
+
reachable. lanky itself is a thin plugin host: it defines a ledger of facts (each
|
|
36
|
+
with a status: tested, decided, proved, certified, assumed) and four plugin
|
|
37
|
+
interfaces (theories, oracles, executors, CLI verbs).
|
|
38
|
+
|
|
39
|
+
## Status
|
|
40
|
+
|
|
41
|
+
Work in progress. This is a placeholder release to reserve the name. The
|
|
42
|
+
architecture is prepared, not implemented: the ledger and the plugin protocols are
|
|
43
|
+
written down, and nothing behind them works yet.
|
|
44
|
+
|
|
45
|
+
The sister project [loopty](https://github.com/xywei/loopty) (loop + ty for types;
|
|
46
|
+
a typed polyhedral layer over loopy, with isl as an oracle and loopy as a code
|
|
47
|
+
generator) will be lanky's first plugin.
|
|
48
|
+
|
|
49
|
+
## Name
|
|
50
|
+
|
|
51
|
+
- "Lean Annotations Natively Kernel-check Your math".
|
|
52
|
+
- LANK + y, where LANK = Lean Annotations, Native Kernel — and *lank* means long
|
|
53
|
+
and thin, next to *lean*.
|
|
54
|
+
|
|
55
|
+
## Planned architecture
|
|
56
|
+
|
|
57
|
+
- A ledger of facts, each carrying a status: tested, decided, proved, certified,
|
|
58
|
+
assumed.
|
|
59
|
+
- Four plugin interfaces: theories (decorators that turn Python objects into
|
|
60
|
+
facts), oracles (establish facts and report a trust class), executors (run a
|
|
61
|
+
decorated object), and verbs (CLI subcommands).
|
|
62
|
+
- A live Lean session via PyPantograph as the Lean oracle.
|
|
63
|
+
- A property-test executor, so theorems run as tests under plain `python`.
|
|
64
|
+
- A generated Lean file plus a source map back to the Python program as the
|
|
65
|
+
certificate.
|
|
66
|
+
- The command line: `lanky check | certify | watch | shell`.
|
|
67
|
+
|
|
68
|
+
## Install
|
|
69
|
+
|
|
70
|
+
```sh
|
|
71
|
+
uv add lanky
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
```sh
|
|
75
|
+
pip install lanky
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
Nothing works yet — installing this release gets you a `lanky` command that prints
|
|
79
|
+
its own version and this repository's URL.
|
|
80
|
+
|
|
81
|
+
## AI disclosure
|
|
82
|
+
|
|
83
|
+
This project is developed with substantial assistance from AI coding agents
|
|
84
|
+
(Anthropic's Claude, via Claude Code). Design, direction, and review are by Xiaoyu
|
|
85
|
+
Wei. Generated text and code are reviewed before release, but readers should assume
|
|
86
|
+
AI involvement throughout.
|
|
87
|
+
|
|
88
|
+
## License
|
|
89
|
+
|
|
90
|
+
MIT. See [LICENSE](LICENSE).
|
lanky-0.0.1/README.md
ADDED
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
# lanky
|
|
2
|
+
|
|
3
|
+
Python for math you can check.
|
|
4
|
+
|
|
5
|
+
lanky is a Python-hosted proof language with Lean 4 and Mathlib as the platform,
|
|
6
|
+
shaped like mypy: hints are inert, the body is executable Python, and an external
|
|
7
|
+
command does the checking. Theorems are typed Python functions (variables are
|
|
8
|
+
parameters, hypotheses are parameters annotated with propositions, the goal is the
|
|
9
|
+
return annotation); proofs are Python programs that drive Lean tactics over a live
|
|
10
|
+
goal; the recorded tactic script is the certificate; under plain `python` the
|
|
11
|
+
theorems run as property tests. Lean is the platform, lanky is a hosted language on
|
|
12
|
+
it (the Kotlin/JVM relationship), so all of Mathlib and every Lean tactic are
|
|
13
|
+
reachable. lanky itself is a thin plugin host: it defines a ledger of facts (each
|
|
14
|
+
with a status: tested, decided, proved, certified, assumed) and four plugin
|
|
15
|
+
interfaces (theories, oracles, executors, CLI verbs).
|
|
16
|
+
|
|
17
|
+
## Status
|
|
18
|
+
|
|
19
|
+
Work in progress. This is a placeholder release to reserve the name. The
|
|
20
|
+
architecture is prepared, not implemented: the ledger and the plugin protocols are
|
|
21
|
+
written down, and nothing behind them works yet.
|
|
22
|
+
|
|
23
|
+
The sister project [loopty](https://github.com/xywei/loopty) (loop + ty for types;
|
|
24
|
+
a typed polyhedral layer over loopy, with isl as an oracle and loopy as a code
|
|
25
|
+
generator) will be lanky's first plugin.
|
|
26
|
+
|
|
27
|
+
## Name
|
|
28
|
+
|
|
29
|
+
- "Lean Annotations Natively Kernel-check Your math".
|
|
30
|
+
- LANK + y, where LANK = Lean Annotations, Native Kernel — and *lank* means long
|
|
31
|
+
and thin, next to *lean*.
|
|
32
|
+
|
|
33
|
+
## Planned architecture
|
|
34
|
+
|
|
35
|
+
- A ledger of facts, each carrying a status: tested, decided, proved, certified,
|
|
36
|
+
assumed.
|
|
37
|
+
- Four plugin interfaces: theories (decorators that turn Python objects into
|
|
38
|
+
facts), oracles (establish facts and report a trust class), executors (run a
|
|
39
|
+
decorated object), and verbs (CLI subcommands).
|
|
40
|
+
- A live Lean session via PyPantograph as the Lean oracle.
|
|
41
|
+
- A property-test executor, so theorems run as tests under plain `python`.
|
|
42
|
+
- A generated Lean file plus a source map back to the Python program as the
|
|
43
|
+
certificate.
|
|
44
|
+
- The command line: `lanky check | certify | watch | shell`.
|
|
45
|
+
|
|
46
|
+
## Install
|
|
47
|
+
|
|
48
|
+
```sh
|
|
49
|
+
uv add lanky
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
```sh
|
|
53
|
+
pip install lanky
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
Nothing works yet — installing this release gets you a `lanky` command that prints
|
|
57
|
+
its own version and this repository's URL.
|
|
58
|
+
|
|
59
|
+
## AI disclosure
|
|
60
|
+
|
|
61
|
+
This project is developed with substantial assistance from AI coding agents
|
|
62
|
+
(Anthropic's Claude, via Claude Code). Design, direction, and review are by Xiaoyu
|
|
63
|
+
Wei. Generated text and code are reviewed before release, but readers should assume
|
|
64
|
+
AI involvement throughout.
|
|
65
|
+
|
|
66
|
+
## License
|
|
67
|
+
|
|
68
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "lanky"
|
|
7
|
+
version = "0.0.1"
|
|
8
|
+
description = "Python for math you can check. A Lean-hosted proof language, shaped like mypy."
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
license = "MIT"
|
|
11
|
+
license-files = ["LICENSE"]
|
|
12
|
+
requires-python = ">=3.12"
|
|
13
|
+
authors = [{ name = "Xiaoyu Wei" }]
|
|
14
|
+
keywords = ["lean", "mathlib", "proof", "theorem-proving", "formal-methods", "type-checking"]
|
|
15
|
+
classifiers = [
|
|
16
|
+
"Development Status :: 1 - Planning",
|
|
17
|
+
"Intended Audience :: Science/Research",
|
|
18
|
+
"Programming Language :: Python :: 3",
|
|
19
|
+
"Programming Language :: Python :: 3.12",
|
|
20
|
+
"Programming Language :: Python :: 3.13",
|
|
21
|
+
"Topic :: Scientific/Engineering :: Mathematics",
|
|
22
|
+
"Topic :: Software Development :: Quality Assurance",
|
|
23
|
+
"Typing :: Typed",
|
|
24
|
+
]
|
|
25
|
+
dependencies = []
|
|
26
|
+
|
|
27
|
+
[project.optional-dependencies]
|
|
28
|
+
# PyPantograph (the Lean session driver) will go here once the Lean oracle lands.
|
|
29
|
+
lean = []
|
|
30
|
+
|
|
31
|
+
[project.urls]
|
|
32
|
+
Homepage = "https://github.com/xywei/lanky"
|
|
33
|
+
Repository = "https://github.com/xywei/lanky"
|
|
34
|
+
|
|
35
|
+
[project.scripts]
|
|
36
|
+
lanky = "lanky.cli:main"
|
|
37
|
+
|
|
38
|
+
[dependency-groups]
|
|
39
|
+
dev = ["pytest", "ruff"]
|
|
40
|
+
|
|
41
|
+
[tool.ruff]
|
|
42
|
+
line-length = 100
|
|
43
|
+
src = ["src", "tests"]
|
|
44
|
+
|
|
45
|
+
[tool.ruff.lint]
|
|
46
|
+
select = ["E", "F", "I", "UP", "B"]
|
|
47
|
+
|
|
48
|
+
[tool.pytest.ini_options]
|
|
49
|
+
testpaths = ["tests"]
|
|
50
|
+
addopts = "-ra"
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
"""lanky: a Python-hosted proof language with Lean 4 and Mathlib as the platform.
|
|
2
|
+
|
|
3
|
+
lanky is shaped like mypy: hints are inert, the body is executable Python, and an
|
|
4
|
+
external command does the checking. Theorems are typed Python functions (variables
|
|
5
|
+
are parameters, hypotheses are parameters annotated with propositions, the goal is
|
|
6
|
+
the return annotation); proofs are Python programs that drive Lean tactics over a
|
|
7
|
+
live goal; the recorded tactic script is the certificate; under plain ``python`` the
|
|
8
|
+
theorems run as property tests. Lean is the platform and lanky is a hosted language
|
|
9
|
+
on it -- the Kotlin/JVM relationship -- so all of Mathlib and every Lean tactic are
|
|
10
|
+
reachable. lanky itself is a thin plugin host: it defines a ledger of facts (each
|
|
11
|
+
with a status: tested, decided, proved, certified, assumed) and four plugin
|
|
12
|
+
interfaces (theories, oracles, executors, CLI verbs).
|
|
13
|
+
|
|
14
|
+
This is a placeholder release to reserve the name. The architecture is prepared,
|
|
15
|
+
not implemented.
|
|
16
|
+
"""
|
|
17
|
+
|
|
18
|
+
__version__ = "0.0.1"
|
|
19
|
+
|
|
20
|
+
__all__ = ["__version__"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"""Command-line entry point for lanky.
|
|
2
|
+
|
|
3
|
+
The real CLI will be assembled from ``Verb`` plugins (see :mod:`lanky.plugins`).
|
|
4
|
+
For this placeholder release ``main`` only reports what lanky is and where it lives.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from lanky import __version__
|
|
10
|
+
|
|
11
|
+
REPO_URL = "https://github.com/xywei/lanky"
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
def main() -> int:
|
|
15
|
+
"""Print the name, version, status, and repository URL."""
|
|
16
|
+
print("lanky")
|
|
17
|
+
print(f"version: {__version__}")
|
|
18
|
+
print("work in progress: placeholder release")
|
|
19
|
+
print(REPO_URL)
|
|
20
|
+
return 0
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
if __name__ == "__main__":
|
|
24
|
+
raise SystemExit(main())
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""The ledger of facts.
|
|
2
|
+
|
|
3
|
+
PREPARED, NOT IMPLEMENTED.
|
|
4
|
+
|
|
5
|
+
The ledger is lanky's single source of truth about what is known and how strongly
|
|
6
|
+
it is known. Every claim a lanky program makes -- a theorem, a side condition
|
|
7
|
+
discharged by a decision procedure, an assumption deliberately left open -- becomes
|
|
8
|
+
a :class:`Fact` carrying a :class:`Status`. Plugins (theories, oracles, executors)
|
|
9
|
+
read and write facts; CLI verbs report on them.
|
|
10
|
+
|
|
11
|
+
Nothing here does any work yet: this module fixes the vocabulary that the rest of
|
|
12
|
+
lanky will be built against.
|
|
13
|
+
"""
|
|
14
|
+
|
|
15
|
+
from __future__ import annotations
|
|
16
|
+
|
|
17
|
+
import enum
|
|
18
|
+
from dataclasses import dataclass, field
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class Status(enum.Enum):
|
|
22
|
+
"""How strongly a :class:`Fact` is established.
|
|
23
|
+
|
|
24
|
+
The members are ordered from weakest to strongest evidence:
|
|
25
|
+
|
|
26
|
+
``TESTED``
|
|
27
|
+
The statement survived execution as a property test under plain ``python``.
|
|
28
|
+
Evidence, not proof.
|
|
29
|
+
``DECIDED``
|
|
30
|
+
A decision procedure (an oracle such as isl, an SMT solver, or a Lean
|
|
31
|
+
``decide``) answered affirmatively, trusted at that oracle's trust class.
|
|
32
|
+
``PROVED``
|
|
33
|
+
A proof was found and accepted by the platform, but no reproducible
|
|
34
|
+
artifact has been retained.
|
|
35
|
+
``CERTIFIED``
|
|
36
|
+
A proof was found and a certificate was recorded -- for the Lean platform,
|
|
37
|
+
a generated Lean file plus a source map back to the Python program -- so
|
|
38
|
+
the claim can be rechecked by the Lean kernel independently of lanky.
|
|
39
|
+
``ASSUMED``
|
|
40
|
+
Deliberately taken on faith: an axiom, a ``sorry``, or an interface
|
|
41
|
+
contract owed by someone else. Tracked so it can never be silently lost.
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
TESTED = "tested"
|
|
45
|
+
DECIDED = "decided"
|
|
46
|
+
PROVED = "proved"
|
|
47
|
+
CERTIFIED = "certified"
|
|
48
|
+
ASSUMED = "assumed"
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
@dataclass(frozen=True)
|
|
52
|
+
class Fact:
|
|
53
|
+
"""A single entry in the ledger.
|
|
54
|
+
|
|
55
|
+
Attributes:
|
|
56
|
+
statement: The claim itself, rendered as source text (Lean syntax on the
|
|
57
|
+
Lean platform).
|
|
58
|
+
status: How strongly the claim is established; see :class:`Status`.
|
|
59
|
+
decided_by: Name of the oracle or executor that established the claim, or
|
|
60
|
+
``None`` when nothing has established it yet (e.g. a pure assumption).
|
|
61
|
+
provenance: Free-form record of where the claim came from and how it was
|
|
62
|
+
checked -- source location, tactic script, certificate path, oracle
|
|
63
|
+
version, trust class, timing. Left untyped on purpose while the
|
|
64
|
+
architecture settles.
|
|
65
|
+
"""
|
|
66
|
+
|
|
67
|
+
statement: str
|
|
68
|
+
status: Status
|
|
69
|
+
decided_by: str | None = None
|
|
70
|
+
provenance: dict = field(default_factory=dict)
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
"""Plugin interfaces.
|
|
2
|
+
|
|
3
|
+
PREPARED, NOT IMPLEMENTED.
|
|
4
|
+
|
|
5
|
+
lanky is a thin plugin host. It owns the ledger (see :mod:`lanky.ledger`) and four
|
|
6
|
+
extension points, discovered through the entry-point groups named by the module
|
|
7
|
+
constants below. Everything domain-specific -- the Lean session, a polyhedral
|
|
8
|
+
theory, a new CLI verb -- arrives as a plugin. The sister project ``loopty``
|
|
9
|
+
(a typed polyhedral layer over ``loopy``, with ``isl`` as an oracle and ``loopy``
|
|
10
|
+
as a code generator) will be the first plugin.
|
|
11
|
+
|
|
12
|
+
The protocols here are structural: a plugin satisfies one by having the right
|
|
13
|
+
methods, with no import of lanky required at runtime.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from __future__ import annotations
|
|
17
|
+
|
|
18
|
+
from typing import Any, Protocol, runtime_checkable
|
|
19
|
+
|
|
20
|
+
#: Entry-point group for theories: vocabularies of statements and their decorators.
|
|
21
|
+
THEORY_GROUP = "lanky.theories"
|
|
22
|
+
|
|
23
|
+
#: Entry-point group for oracles: things that establish facts.
|
|
24
|
+
ORACLE_GROUP = "lanky.oracles"
|
|
25
|
+
|
|
26
|
+
#: Entry-point group for executors: things that run decorated Python objects.
|
|
27
|
+
EXECUTOR_GROUP = "lanky.executors"
|
|
28
|
+
|
|
29
|
+
#: Entry-point group for CLI verbs: subcommands of the ``lanky`` command.
|
|
30
|
+
VERB_GROUP = "lanky.verbs"
|
|
31
|
+
|
|
32
|
+
ENTRY_POINT_GROUPS = (THEORY_GROUP, ORACLE_GROUP, EXECUTOR_GROUP, VERB_GROUP)
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
@runtime_checkable
|
|
36
|
+
class Theory(Protocol):
|
|
37
|
+
"""A vocabulary of statements, exposed as a decorator.
|
|
38
|
+
|
|
39
|
+
A theory turns an ordinary Python object -- typically a typed function whose
|
|
40
|
+
parameters are the variables and hypotheses and whose return annotation is the
|
|
41
|
+
goal -- into one or more :class:`~lanky.ledger.Fact` objects. It owns the
|
|
42
|
+
translation from Python annotations into the platform's statement language, and
|
|
43
|
+
it decides what the annotations are allowed to say.
|
|
44
|
+
|
|
45
|
+
The decorator is inert in the mypy sense: it records the claim and returns
|
|
46
|
+
something still callable, so the body remains executable Python.
|
|
47
|
+
"""
|
|
48
|
+
|
|
49
|
+
name: str
|
|
50
|
+
|
|
51
|
+
def __call__(self, obj: Any, /) -> Any:
|
|
52
|
+
"""Decorate ``obj``, registering the facts it claims, and return it."""
|
|
53
|
+
...
|
|
54
|
+
|
|
55
|
+
def facts(self, obj: Any, /) -> tuple:
|
|
56
|
+
"""Return the facts claimed by a previously decorated object."""
|
|
57
|
+
...
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
@runtime_checkable
|
|
61
|
+
class Oracle(Protocol):
|
|
62
|
+
"""Something that establishes facts, and says how much it should be trusted.
|
|
63
|
+
|
|
64
|
+
Oracles are the only way a fact's status improves. A Lean session driven
|
|
65
|
+
through PyPantograph is the reference oracle: it runs tactics against a live
|
|
66
|
+
goal and can emit a certificate. A decision procedure such as ``isl`` or an SMT
|
|
67
|
+
solver is an oracle too, at a weaker trust class.
|
|
68
|
+
|
|
69
|
+
The trust class is reported, never assumed, so the ledger can distinguish a
|
|
70
|
+
kernel-checked certificate from a solver's say-so.
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
name: str
|
|
74
|
+
|
|
75
|
+
def trust_class(self) -> str:
|
|
76
|
+
"""Name the kind of evidence this oracle produces (e.g. ``"kernel"``)."""
|
|
77
|
+
...
|
|
78
|
+
|
|
79
|
+
def establish(self, fact: Any, /) -> Any:
|
|
80
|
+
"""Attempt to establish ``fact``; return it with an updated status."""
|
|
81
|
+
...
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
@runtime_checkable
|
|
85
|
+
class Executor(Protocol):
|
|
86
|
+
"""Something that runs a decorated object.
|
|
87
|
+
|
|
88
|
+
The default executor is plain ``python``: it calls the theorem's body, drawing
|
|
89
|
+
values for the parameters, so theorems double as property tests and facts reach
|
|
90
|
+
status ``TESTED``. Other executors run the object differently -- ``loopty``'s
|
|
91
|
+
code generator will hand its decorated kernels to ``loopy`` -- but all of them
|
|
92
|
+
answer the same question: what happens when this object is actually run?
|
|
93
|
+
"""
|
|
94
|
+
|
|
95
|
+
name: str
|
|
96
|
+
|
|
97
|
+
def run(self, obj: Any, /, *args: Any, **kwargs: Any) -> Any:
|
|
98
|
+
"""Run the decorated object and return its result."""
|
|
99
|
+
...
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
@runtime_checkable
|
|
103
|
+
class Verb(Protocol):
|
|
104
|
+
"""A subcommand of the ``lanky`` command-line tool.
|
|
105
|
+
|
|
106
|
+
Planned built-in verbs are ``check``, ``certify``, ``watch``, and ``shell``.
|
|
107
|
+
Plugins add their own; the host supplies argument parsing, plugin discovery, and
|
|
108
|
+
access to the ledger.
|
|
109
|
+
"""
|
|
110
|
+
|
|
111
|
+
name: str
|
|
112
|
+
help: str
|
|
113
|
+
|
|
114
|
+
def add_arguments(self, parser: Any, /) -> None:
|
|
115
|
+
"""Declare this verb's command-line arguments on ``parser``."""
|
|
116
|
+
...
|
|
117
|
+
|
|
118
|
+
def run(self, args: Any, /) -> int:
|
|
119
|
+
"""Execute the verb and return a process exit code."""
|
|
120
|
+
...
|
|
File without changes
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"""Smoke tests for the placeholder release."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
import lanky
|
|
6
|
+
from lanky import cli
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def test_version() -> None:
|
|
10
|
+
assert lanky.__version__ == "0.0.1"
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
def test_module_has_docstring() -> None:
|
|
14
|
+
assert lanky.__doc__ and "Lean" in lanky.__doc__
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def test_cli_main(capsys) -> None:
|
|
18
|
+
assert cli.main() == 0
|
|
19
|
+
out = capsys.readouterr().out
|
|
20
|
+
assert "lanky" in out
|
|
21
|
+
assert lanky.__version__ in out
|
|
22
|
+
assert "work in progress: placeholder release" in out
|
|
23
|
+
assert "https://github.com/xywei/lanky" in out
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
def test_ledger_and_plugins_import() -> None:
|
|
27
|
+
from lanky.ledger import Fact, Status
|
|
28
|
+
from lanky.plugins import ENTRY_POINT_GROUPS, Executor, Oracle, Theory, Verb
|
|
29
|
+
|
|
30
|
+
assert {s.value for s in Status} == {
|
|
31
|
+
"tested",
|
|
32
|
+
"decided",
|
|
33
|
+
"proved",
|
|
34
|
+
"certified",
|
|
35
|
+
"assumed",
|
|
36
|
+
}
|
|
37
|
+
fact = Fact(statement="1 + 1 = 2", status=Status.ASSUMED, decided_by=None, provenance={})
|
|
38
|
+
assert fact.status is Status.ASSUMED
|
|
39
|
+
assert ENTRY_POINT_GROUPS == (
|
|
40
|
+
"lanky.theories",
|
|
41
|
+
"lanky.oracles",
|
|
42
|
+
"lanky.executors",
|
|
43
|
+
"lanky.verbs",
|
|
44
|
+
)
|
|
45
|
+
assert all(p is not None for p in (Theory, Oracle, Executor, Verb))
|
lanky-0.0.1/uv.lock
ADDED
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.12"
|
|
4
|
+
|
|
5
|
+
[[package]]
|
|
6
|
+
name = "colorama"
|
|
7
|
+
version = "0.4.6"
|
|
8
|
+
source = { registry = "https://pypi.org/simple" }
|
|
9
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
|
10
|
+
wheels = [
|
|
11
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
12
|
+
]
|
|
13
|
+
|
|
14
|
+
[[package]]
|
|
15
|
+
name = "iniconfig"
|
|
16
|
+
version = "2.3.0"
|
|
17
|
+
source = { registry = "https://pypi.org/simple" }
|
|
18
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
|
19
|
+
wheels = [
|
|
20
|
+
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
|
21
|
+
]
|
|
22
|
+
|
|
23
|
+
[[package]]
|
|
24
|
+
name = "lanky"
|
|
25
|
+
version = "0.0.1"
|
|
26
|
+
source = { editable = "." }
|
|
27
|
+
|
|
28
|
+
[package.dev-dependencies]
|
|
29
|
+
dev = [
|
|
30
|
+
{ name = "pytest" },
|
|
31
|
+
{ name = "ruff" },
|
|
32
|
+
]
|
|
33
|
+
|
|
34
|
+
[package.metadata]
|
|
35
|
+
provides-extras = ["lean"]
|
|
36
|
+
|
|
37
|
+
[package.metadata.requires-dev]
|
|
38
|
+
dev = [
|
|
39
|
+
{ name = "pytest" },
|
|
40
|
+
{ name = "ruff" },
|
|
41
|
+
]
|
|
42
|
+
|
|
43
|
+
[[package]]
|
|
44
|
+
name = "packaging"
|
|
45
|
+
version = "26.3"
|
|
46
|
+
source = { registry = "https://pypi.org/simple" }
|
|
47
|
+
sdist = { url = "https://files.pythonhosted.org/packages/7d/fa/3944b40b07da9ce895c0e6303a5ab7d53da063554f534556b134a54d6093/packaging-26.3.tar.gz", hash = "sha256:94edc256424af38762eb31306eed28beb9f0efc50a8837492c9d6fd6004aed79", size = 313412, upload-time = "2026-08-04T18:15:28.737Z" }
|
|
48
|
+
wheels = [
|
|
49
|
+
{ url = "https://files.pythonhosted.org/packages/63/34/ba1c580383c9eada3711951fef0795c80b829a078d72188184bcab9dd527/packaging-26.3-py3-none-any.whl", hash = "sha256:d7193f7c8e4e93f444fde0262bf90af30e16fa0ad0ad44cb553c87339b23cd1c", size = 129956, upload-time = "2026-08-04T18:15:27.159Z" },
|
|
50
|
+
]
|
|
51
|
+
|
|
52
|
+
[[package]]
|
|
53
|
+
name = "pluggy"
|
|
54
|
+
version = "1.6.0"
|
|
55
|
+
source = { registry = "https://pypi.org/simple" }
|
|
56
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
|
57
|
+
wheels = [
|
|
58
|
+
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
59
|
+
]
|
|
60
|
+
|
|
61
|
+
[[package]]
|
|
62
|
+
name = "pygments"
|
|
63
|
+
version = "2.21.0"
|
|
64
|
+
source = { registry = "https://pypi.org/simple" }
|
|
65
|
+
sdist = { url = "https://files.pythonhosted.org/packages/49/2e/ced460408999b33da6b31b0021b0f37d329e202d4169aeb164493778f25b/pygments-2.21.0.tar.gz", hash = "sha256:610ca751c9bc2492b38eb9a38a7fbc93edbbb2d7182edaf34e66ae493dee5c8c", size = 5005329, upload-time = "2026-08-17T08:02:48.824Z" }
|
|
66
|
+
wheels = [
|
|
67
|
+
{ url = "https://files.pythonhosted.org/packages/71/46/17f022dd3e953bf20a04a028a21ec746d942f8d2af30fa0f124fa0e6a684/pygments-2.21.0-py3-none-any.whl", hash = "sha256:2363c69b61c4a97c838da3b130dcd6468f4848992b21a82f2a63ec34377137d9", size = 1250147, upload-time = "2026-08-17T08:02:44.912Z" },
|
|
68
|
+
]
|
|
69
|
+
|
|
70
|
+
[[package]]
|
|
71
|
+
name = "pytest"
|
|
72
|
+
version = "9.1.1"
|
|
73
|
+
source = { registry = "https://pypi.org/simple" }
|
|
74
|
+
dependencies = [
|
|
75
|
+
{ name = "colorama", marker = "sys_platform == 'win32'" },
|
|
76
|
+
{ name = "iniconfig" },
|
|
77
|
+
{ name = "packaging" },
|
|
78
|
+
{ name = "pluggy" },
|
|
79
|
+
{ name = "pygments" },
|
|
80
|
+
]
|
|
81
|
+
sdist = { url = "https://files.pythonhosted.org/packages/e4/47/b9efed96c114afcfa3c9d3fe98a76a1d14c74a9e266d397cf6eb64be5e01/pytest-9.1.1.tar.gz", hash = "sha256:1088fbde8f2b49d95a549a195707afa7a76a3ce9bcadc26b6d71f0ffda5fe313", size = 1636369, upload-time = "2026-06-19T10:58:32.857Z" }
|
|
82
|
+
wheels = [
|
|
83
|
+
{ url = "https://files.pythonhosted.org/packages/24/25/1de2678b631f5a49215c6c96fff41ba892b0a34df68d6d80292b1b48aa7f/pytest-9.1.1-py3-none-any.whl", hash = "sha256:37a86b45efb9a47a61a36449063e8e18d0cab3161329fc099eb21783169c4f0c", size = 386536, upload-time = "2026-06-19T10:58:31.347Z" },
|
|
84
|
+
]
|
|
85
|
+
|
|
86
|
+
[[package]]
|
|
87
|
+
name = "ruff"
|
|
88
|
+
version = "0.16.7"
|
|
89
|
+
source = { registry = "https://pypi.org/simple" }
|
|
90
|
+
sdist = { url = "https://files.pythonhosted.org/packages/82/bb/5a449b9162e49b139d72f61672bd3ac1d790221f796d3304e2241fff4c58/ruff-0.16.7.tar.gz", hash = "sha256:5f71d004ac1263b22fa39462ac5ae618a4b77d58981af2cc79bf79a29c12b1a6", size = 4924184, upload-time = "2026-09-10T18:04:06.336Z" }
|
|
91
|
+
wheels = [
|
|
92
|
+
{ url = "https://files.pythonhosted.org/packages/e3/b2/c80aeeb7f9e469c0d63a85d2f1ab6e1ebfbe10ea7a8d2438b7e09e3ff09e/ruff-0.16.7-py3-none-linux_armv6l.whl", hash = "sha256:727307773e7c7f9181d3ed3a2484186e56c1fa1874255911c74585eb2c7c19f9", size = 10048917, upload-time = "2026-09-10T18:03:30.28Z" },
|
|
93
|
+
{ url = "https://files.pythonhosted.org/packages/7b/96/20bb7bcae008004df52afcb7ac83432d4a467f2c17b672fe46d26be231c5/ruff-0.16.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:9d61c258deabf58f34c67bd4bb4d939c7f2e6b5f0e59c1cdd1cf771b11cde929", size = 10242929, upload-time = "2026-09-10T18:03:32.706Z" },
|
|
94
|
+
{ url = "https://files.pythonhosted.org/packages/90/b2/f184b0d5abec02db69cfd7e49b688ae0237554528ca777136c613bf36bee/ruff-0.16.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7ab81118df8945e0193d0240712aa4496573595b75185c3636ed825592a0f728", size = 9847245, upload-time = "2026-09-10T18:03:34.509Z" },
|
|
95
|
+
{ url = "https://files.pythonhosted.org/packages/eb/2d/db1633a641866ed801e34cc6b60ef236c5e16f9b2124ab1d49cc24a5fe4f/ruff-0.16.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c196c968874fc8019da8e7163de7a1a370f111e2309b4b7dfea0fce950198d0", size = 9961780, upload-time = "2026-09-10T18:03:36.618Z" },
|
|
96
|
+
{ url = "https://files.pythonhosted.org/packages/4d/98/edea21e1a3e38dbbc3bf6bb068b863b3b06184cf8533a4c7dbbe208a89d5/ruff-0.16.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ac8c3bd0a7e10ad31e6ce51e7a99f3cb772e69aecdd6b9ea7e99b362f62a62c0", size = 9866337, upload-time = "2026-09-10T18:03:38.805Z" },
|
|
97
|
+
{ url = "https://files.pythonhosted.org/packages/0b/11/a15e60d4c87b214646f116ca9d204475bf993ee1047459bc9a360fd4d6d1/ruff-0.16.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:398d3988edde000b5c75dc1b3f584708da9bc990de069c18909142580fec1af9", size = 10562512, upload-time = "2026-09-10T18:03:40.71Z" },
|
|
98
|
+
{ url = "https://files.pythonhosted.org/packages/29/42/eaff4c9b6d0c7cdf56df313a17e89ae854f5bbc0b0c8f9cce19be0ab7a8f/ruff-0.16.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ce05b62b770a8217c4646a9c4139fca00efe8fe5d71f87df2b243ff20d4584d1", size = 11302938, upload-time = "2026-09-10T18:03:42.607Z" },
|
|
99
|
+
{ url = "https://files.pythonhosted.org/packages/5d/43/c75aa59a4ec181fe2ec06cab30e198c1c6d107229a9f008ae3a7c16cabd8/ruff-0.16.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af1b576fddb9d9ef2ececfb5fadcd6a624b25070ed85e3cfcfe449fc3ff6a7b9", size = 10840857, upload-time = "2026-09-10T18:03:44.604Z" },
|
|
100
|
+
{ url = "https://files.pythonhosted.org/packages/21/33/81f3da371942ea031105ba679d8d6e28ec1660ccd690a45f42d381161356/ruff-0.16.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9ce7f8f22df67c93ed96c717f9128eadb797144ac2bad475cf536f31d6100c55", size = 10370001, upload-time = "2026-09-10T18:03:46.706Z" },
|
|
101
|
+
{ url = "https://files.pythonhosted.org/packages/fa/0b/6345fb4dbf6dd0ed1cfe5d18391dc9c3f59cc81622a7b0a65b84b3e730ba/ruff-0.16.7-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:06d0e93d04f392996435ebd600c153f65b47d73fbec2415aa99c5ee5756b3a5f", size = 10548735, upload-time = "2026-09-10T18:03:48.658Z" },
|
|
102
|
+
{ url = "https://files.pythonhosted.org/packages/3f/4d/c5576adf511f92a328e5569dda190ecdd430da51f1a649f3a4a2fd73e21e/ruff-0.16.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:142151a5e7b93c1b11111337142f89dd2fbfee92161225c99a97222f22e32656", size = 10108496, upload-time = "2026-09-10T18:03:50.563Z" },
|
|
103
|
+
{ url = "https://files.pythonhosted.org/packages/ff/8c/667d83c16199a17a56adc6b0bd4c3beb5b767a2babcd16a56f76f9be7fd6/ruff-0.16.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:e6651f97a342d8b35d54d8991544ca22169b86dc54111cb604666940c431b750", size = 9860136, upload-time = "2026-09-10T18:03:52.621Z" },
|
|
104
|
+
{ url = "https://files.pythonhosted.org/packages/99/75/78d401106731999a1dd20cc5a6961e37e1eb9397a3b589f73f3a5ce146a3/ruff-0.16.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:ef140c6eb935fa9a84c9c607dfb2cb1b85843c192e79265b0c54f35f557ea8e5", size = 10286290, upload-time = "2026-09-10T18:03:55.207Z" },
|
|
105
|
+
{ url = "https://files.pythonhosted.org/packages/68/49/56f9c3a8b755df93a0ad318b2147bf4ef5dae9a7e5ec61c460109c67957f/ruff-0.16.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:53e39506a730fadeee0d998ed5946f30671f0db240c6c7c73bdabbe33604bb6f", size = 10745048, upload-time = "2026-09-10T18:03:57.299Z" },
|
|
106
|
+
{ url = "https://files.pythonhosted.org/packages/5f/ea/7f9b938a63ece4bec677ad7f9f7fa02df3383db1949ed93a382441c09a87/ruff-0.16.7-py3-none-win32.whl", hash = "sha256:2ea3470fcebcbc5df2fb0c6f3b90333fa9084c534e0111c038fa4a6ab9f1c4b7", size = 10059082, upload-time = "2026-09-10T18:03:59.632Z" },
|
|
107
|
+
{ url = "https://files.pythonhosted.org/packages/39/11/480a6973a927aa653e1cead6a6416008640e03a99d05b34c0434b8c6c366/ruff-0.16.7-py3-none-win_amd64.whl", hash = "sha256:7ac26aca826e9e21d0f1cb25b54ac660760a9fdd094d3e4df9848232be98cfc6", size = 10593368, upload-time = "2026-09-10T18:04:01.999Z" },
|
|
108
|
+
{ url = "https://files.pythonhosted.org/packages/8b/4b/51327018d056f0dad2c2238f26d1fb0f53707a9d91b75dea6d1b3039f136/ruff-0.16.7-py3-none-win_arm64.whl", hash = "sha256:aab7f39e2c9df6c596216070f98eef1207b94f8516cca20c808826974971855b", size = 10412401, upload-time = "2026-09-10T18:04:04.098Z" },
|
|
109
|
+
]
|