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.
@@ -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
+ ]