cdclkit 0.1.3__tar.gz → 0.1.4__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.
Files changed (45) hide show
  1. {cdclkit-0.1.3 → cdclkit-0.1.4}/PKG-INFO +8 -6
  2. {cdclkit-0.1.3 → cdclkit-0.1.4}/README.md +5 -3
  3. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/__init__.py +1 -1
  4. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit.egg-info/PKG-INFO +8 -6
  5. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit.egg-info/SOURCES.txt +1 -0
  6. cdclkit-0.1.4/cdclkit.egg-info/requires.txt +4 -0
  7. {cdclkit-0.1.3 → cdclkit-0.1.4}/pyproject.toml +3 -3
  8. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_packaging.py +25 -0
  9. cdclkit-0.1.4/tests/test_readme.py +91 -0
  10. cdclkit-0.1.3/cdclkit.egg-info/requires.txt +0 -4
  11. {cdclkit-0.1.3 → cdclkit-0.1.4}/LICENSE +0 -0
  12. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/__main__.py +0 -0
  13. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/brute.py +0 -0
  14. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/cli.py +0 -0
  15. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/encodings.py +0 -0
  16. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/heap.py +0 -0
  17. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/model.py +0 -0
  18. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/mus.py +0 -0
  19. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/native.py +0 -0
  20. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/pipeline.py +0 -0
  21. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/portfolio.py +0 -0
  22. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/preprocess.py +0 -0
  23. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/py.typed +0 -0
  24. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/pyeq.py +0 -0
  25. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit/solver.py +0 -0
  26. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit.egg-info/dependency_links.txt +0 -0
  27. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit.egg-info/entry_points.txt +0 -0
  28. {cdclkit-0.1.3 → cdclkit-0.1.4}/cdclkit.egg-info/top_level.txt +0 -0
  29. {cdclkit-0.1.3 → cdclkit-0.1.4}/setup.cfg +0 -0
  30. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_adaptive_proof.py +0 -0
  31. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_agent_docs.py +0 -0
  32. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_brute.py +0 -0
  33. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_cli_defaults.py +0 -0
  34. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_core.py +0 -0
  35. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_encodings.py +0 -0
  36. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_integration.py +0 -0
  37. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_mus.py +0 -0
  38. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_native.py +0 -0
  39. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_native_solver.py +0 -0
  40. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_pipeline.py +0 -0
  41. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_portfolio.py +0 -0
  42. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_preprocess.py +0 -0
  43. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_proof.py +0 -0
  44. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_pyeq.py +0 -0
  45. {cdclkit-0.1.3 → cdclkit-0.1.4}/tests/test_solver.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cdclkit
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: A CDCL SAT solver, preprocessor, encoding library and modelling layer, written from scratch in readable Python. Every answer comes with a certificate.
5
5
  Author: Carlo Perassi
6
6
  License-Expression: Apache-2.0
@@ -22,9 +22,9 @@ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
22
  Requires-Python: >=3.10
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: dratify>=0.1.4
25
+ Requires-Dist: dratify>=0.1.7
26
26
  Provides-Extra: native
27
- Requires-Dist: cdclkit-native==0.1.3; extra == "native"
27
+ Requires-Dist: cdclkit-native==0.1.4; extra == "native"
28
28
  Dynamic: license-file
29
29
 
30
30
  # cdclkit
@@ -142,9 +142,11 @@ An optional Rust engine ([`cdclkit-native`](https://pypi.org/project/cdclkit-nat
142
142
  is **bit-exact** with the Python one — identical conflicts, decisions and
143
143
  propagations on every instance — and about **20x faster**: the geometric mean
144
144
  of per-instance ratios over the 17 benchmark instances is 20.1x, ranging from
145
- 11x to 51x. Regenerate it with `make history` (the `python` and `native`
146
- checkpoints in `bench/history.jsonl`); see [BENCHMARKS.md](BENCHMARKS.md) for
147
- the method. The pure-Python path has zero third-party
145
+ 11x to 51x. That comes from two checkpoints recorded 34 seconds apart at the
146
+ same commit, one sample per instance — good enough for the mean, not for any
147
+ single row. Regenerate it with `make history` (the `python` and `native`
148
+ entries in `bench/history.jsonl`); see [BENCHMARKS.md](BENCHMARKS.md) for the
149
+ method. The pure-Python path has zero third-party
148
150
  dependencies and is the one that must never break.
149
151
 
150
152
  ## Relationship to dratify
@@ -113,9 +113,11 @@ An optional Rust engine ([`cdclkit-native`](https://pypi.org/project/cdclkit-nat
113
113
  is **bit-exact** with the Python one — identical conflicts, decisions and
114
114
  propagations on every instance — and about **20x faster**: the geometric mean
115
115
  of per-instance ratios over the 17 benchmark instances is 20.1x, ranging from
116
- 11x to 51x. Regenerate it with `make history` (the `python` and `native`
117
- checkpoints in `bench/history.jsonl`); see [BENCHMARKS.md](BENCHMARKS.md) for
118
- the method. The pure-Python path has zero third-party
116
+ 11x to 51x. That comes from two checkpoints recorded 34 seconds apart at the
117
+ same commit, one sample per instance — good enough for the mean, not for any
118
+ single row. Regenerate it with `make history` (the `python` and `native`
119
+ entries in `bench/history.jsonl`); see [BENCHMARKS.md](BENCHMARKS.md) for the
120
+ method. The pure-Python path has zero third-party
119
121
  dependencies and is the one that must never break.
120
122
 
121
123
  ## Relationship to dratify
@@ -52,7 +52,7 @@ from .preprocess import Preprocessor, preprocess
52
52
  from dratify.proof import DRATChecker, MemoryProof, ProofWriter, check_proof
53
53
  from .solver import Config, SAT, Solver, Stats, UNKNOWN, UNSAT
54
54
 
55
- __version__ = "0.1.3"
55
+ __version__ = "0.1.4"
56
56
 
57
57
  __all__ = [
58
58
  "CNF",
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: cdclkit
3
- Version: 0.1.3
3
+ Version: 0.1.4
4
4
  Summary: A CDCL SAT solver, preprocessor, encoding library and modelling layer, written from scratch in readable Python. Every answer comes with a certificate.
5
5
  Author: Carlo Perassi
6
6
  License-Expression: Apache-2.0
@@ -22,9 +22,9 @@ Classifier: Topic :: Scientific/Engineering :: Mathematics
22
22
  Requires-Python: >=3.10
23
23
  Description-Content-Type: text/markdown
24
24
  License-File: LICENSE
25
- Requires-Dist: dratify>=0.1.4
25
+ Requires-Dist: dratify>=0.1.7
26
26
  Provides-Extra: native
27
- Requires-Dist: cdclkit-native==0.1.3; extra == "native"
27
+ Requires-Dist: cdclkit-native==0.1.4; extra == "native"
28
28
  Dynamic: license-file
29
29
 
30
30
  # cdclkit
@@ -142,9 +142,11 @@ An optional Rust engine ([`cdclkit-native`](https://pypi.org/project/cdclkit-nat
142
142
  is **bit-exact** with the Python one — identical conflicts, decisions and
143
143
  propagations on every instance — and about **20x faster**: the geometric mean
144
144
  of per-instance ratios over the 17 benchmark instances is 20.1x, ranging from
145
- 11x to 51x. Regenerate it with `make history` (the `python` and `native`
146
- checkpoints in `bench/history.jsonl`); see [BENCHMARKS.md](BENCHMARKS.md) for
147
- the method. The pure-Python path has zero third-party
145
+ 11x to 51x. That comes from two checkpoints recorded 34 seconds apart at the
146
+ same commit, one sample per instance — good enough for the mean, not for any
147
+ single row. Regenerate it with `make history` (the `python` and `native`
148
+ entries in `bench/history.jsonl`); see [BENCHMARKS.md](BENCHMARKS.md) for the
149
+ method. The pure-Python path has zero third-party
148
150
  dependencies and is the one that must never break.
149
151
 
150
152
  ## Relationship to dratify
@@ -38,4 +38,5 @@ tests/test_portfolio.py
38
38
  tests/test_preprocess.py
39
39
  tests/test_proof.py
40
40
  tests/test_pyeq.py
41
+ tests/test_readme.py
41
42
  tests/test_solver.py
@@ -0,0 +1,4 @@
1
+ dratify>=0.1.7
2
+
3
+ [native]
4
+ cdclkit-native==0.1.4
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "cdclkit"
7
- version = "0.1.3"
7
+ version = "0.1.4"
8
8
  description = "A CDCL SAT solver, preprocessor, encoding library and modelling layer, written from scratch in readable Python. Every answer comes with a certificate."
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.10"
@@ -29,13 +29,13 @@ classifiers = [
29
29
  # The only dependency is the proof checker, which itself has none. The solver
30
30
  # uses it to check its own refutations, so the checker is exercised by every
31
31
  # test run here as well as by its own suite.
32
- dependencies = ["dratify>=0.1.4"]
32
+ dependencies = ["dratify>=0.1.7"]
33
33
 
34
34
  [project.optional-dependencies]
35
35
  # The Rust accelerator, as abi3 wheels for Linux and macOS. Pinned exactly:
36
36
  # the two are bit-exact by construction and a mismatched pair is a divergence
37
37
  # nobody would look for. tests/test_packaging.py enforces the pin.
38
- native = ["cdclkit-native==0.1.3"]
38
+ native = ["cdclkit-native==0.1.4"]
39
39
 
40
40
  [project.scripts]
41
41
  cdclkit = "cdclkit.__main__:main"
@@ -103,6 +103,31 @@ class TestVersions(unittest.TestCase):
103
103
  self.assertRegex(cdclkit.__version__, r"^\d+\.\d+\.\d+([.-]\w+)?$")
104
104
 
105
105
 
106
+ class TestSmokeTestIsCurrent(unittest.TestCase):
107
+ """The post-install smoke test must ask for the modules that exist.
108
+
109
+ Its list named `cnf`, `lits` and `proof` long after they moved to
110
+ `dratify`, so `make smoke` failed on every run and nobody saw, because
111
+ nothing ran it automatically. CI now runs it; this keeps its list honest.
112
+ """
113
+
114
+ def test_the_smoke_module_list_matches_the_package(self):
115
+ import importlib.util
116
+
117
+ spec = importlib.util.spec_from_file_location(
118
+ "smoke_installed", ROOT / "tests" / "smoke_installed.py")
119
+ smoke = importlib.util.module_from_spec(spec)
120
+ spec.loader.exec_module(smoke)
121
+
122
+ on_disk = {p.stem for p in (ROOT / "cdclkit").glob("*.py")
123
+ if p.stem not in ("__init__", "__main__")}
124
+ self.assertEqual(
125
+ set(smoke.MODULES), on_disk,
126
+ "tests/smoke_installed.py MODULES does not match cdclkit/*.py. "
127
+ "A module added here and not there ships untested; one listed "
128
+ "there and not here makes the smoke test fail on every run.")
129
+
130
+
106
131
  class TestEntryPoints(unittest.TestCase):
107
132
  def test_console_script_target_exists_and_is_callable(self):
108
133
  """`cdclkit = "cdclkit.cli:main"` has to still resolve after a refactor."""
@@ -0,0 +1,91 @@
1
+ # SPDX-License-Identifier: Apache-2.0
2
+ # Copyright (c) 2026 Carlo Perassi. Licensed under the Apache License 2.0.
3
+ """Every Python example in the README has to run, and print what it says.
4
+
5
+ The README is the first code a visitor copies, and until this test existed
6
+ nothing executed it. The sibling project found its own example broken this
7
+ way: fine on the input its author tried, and failing on the first line for
8
+ the most common input there is.
9
+
10
+ Each ```python block runs in a fresh namespace from a temporary directory. A
11
+ `print(x) # value` line is an assertion: the printed value must match the
12
+ first word of the comment, so an example that runs but answers wrongly fails
13
+ too. A block preceded by `<!-- readme-test: skip ... -->` is not executed.
14
+ """
15
+
16
+ from __future__ import annotations
17
+
18
+ import contextlib
19
+ import io
20
+ import os
21
+ import pathlib
22
+ import re
23
+ import shutil
24
+ import tempfile
25
+ import unittest
26
+
27
+ ROOT = pathlib.Path(__file__).resolve().parent.parent
28
+
29
+ SKIP = re.compile(r"<!--\s*readme-test:\s*skip")
30
+ EXPECT = re.compile(r"^\s*print\(.*\)\s*#\s*(\S+)")
31
+
32
+
33
+ def blocks(markdown: str) -> list[tuple[int, str, bool]]:
34
+ """(line number, source, skipped) for every ```python block."""
35
+ lines = markdown.splitlines()
36
+ out, i = [], 0
37
+ while i < len(lines):
38
+ if lines[i].strip() == "```python":
39
+ start = i + 1
40
+ skipped = i > 0 and bool(SKIP.search(lines[i - 1]))
41
+ j = start
42
+ while lines[j].strip() != "```":
43
+ j += 1
44
+ out.append((start + 1, "\n".join(lines[start:j]) + "\n", skipped))
45
+ i = j
46
+ i += 1
47
+ return out
48
+
49
+
50
+ def expected_output(source: str) -> list[str]:
51
+ return [m.group(1) for ln in source.splitlines()
52
+ if (m := EXPECT.match(ln))]
53
+
54
+
55
+ class TestReadmeExamples(unittest.TestCase):
56
+ def setUp(self):
57
+ self.dir = pathlib.Path(tempfile.mkdtemp())
58
+ self.addCleanup(shutil.rmtree, self.dir)
59
+ self.all = blocks((ROOT / "README.md").read_text(encoding="utf-8"))
60
+
61
+ def test_the_readme_has_examples_to_test(self):
62
+ """Guards the extractor: a regex that matches nothing passes everything."""
63
+ self.assertGreaterEqual(len(self.all), 1)
64
+
65
+ def test_every_example_runs_and_prints_what_it_promises(self):
66
+ ran = 0
67
+ for lineno, source, skipped in self.all:
68
+ if skipped:
69
+ continue
70
+ with self.subTest(line=lineno):
71
+ want = expected_output(source)
72
+ out = io.StringIO()
73
+ here = os.getcwd()
74
+ os.chdir(self.dir)
75
+ try:
76
+ with contextlib.redirect_stdout(out):
77
+ exec(compile(source, "README.md", "exec"),
78
+ {"__name__": "__readme__"})
79
+ finally:
80
+ os.chdir(here)
81
+ got = out.getvalue().split()
82
+ self.assertEqual(
83
+ got, want,
84
+ f"README.md:{lineno} printed {got}, but its comments "
85
+ f"promise {want}")
86
+ ran += 1
87
+ self.assertGreater(ran, 0, "no README example was run")
88
+
89
+
90
+ if __name__ == "__main__":
91
+ unittest.main()
@@ -1,4 +0,0 @@
1
- dratify>=0.1.4
2
-
3
- [native]
4
- cdclkit-native==0.1.3
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes