subschema 0.0.2__tar.gz → 0.0.3__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 (51) hide show
  1. {subschema-0.0.2 → subschema-0.0.3}/PKG-INFO +1 -1
  2. {subschema-0.0.2 → subschema-0.0.3}/pyproject.toml +1 -1
  3. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/api.py +7 -3
  4. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/context.py +19 -7
  5. subschema-0.0.3/src/subschema/kernel/disjointness.py +703 -0
  6. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/driver.py +2 -0
  7. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/evaluation.py +17 -2
  8. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/finite.py +11 -15
  9. subschema-0.0.3/src/subschema/kernel/normalization.py +274 -0
  10. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/regex.py +331 -75
  11. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/sat.py +48 -1
  12. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/schemas.py +1 -0
  13. subschema-0.0.3/src/subschema/kernel/tagged_unions.py +138 -0
  14. {subschema-0.0.2 → subschema-0.0.3}/uv.lock +1 -1
  15. subschema-0.0.2/src/subschema/kernel/disjointness.py +0 -147
  16. subschema-0.0.2/src/subschema/kernel/normalization.py +0 -65
  17. {subschema-0.0.2 → subschema-0.0.3}/.gitignore +0 -0
  18. {subschema-0.0.2 → subschema-0.0.3}/LICENSE +0 -0
  19. {subschema-0.0.2 → subschema-0.0.3}/README.md +0 -0
  20. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/__init__.py +0 -0
  21. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/cli.py +0 -0
  22. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/dialects.py +0 -0
  23. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/exceptions.py +0 -0
  24. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/__init__.py +0 -0
  25. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/applicators.py +0 -0
  26. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/certificates.py +0 -0
  27. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/composition.py +0 -0
  28. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/constraints.py +0 -0
  29. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/contracts.py +0 -0
  30. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/difference.py +0 -0
  31. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/domains/__init__.py +0 -0
  32. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/domains/arrays.py +0 -0
  33. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/domains/numbers.py +0 -0
  34. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/domains/objects.py +0 -0
  35. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/domains/strings.py +0 -0
  36. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/domains/types.py +0 -0
  37. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/engine.py +0 -0
  38. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/formulas.py +0 -0
  39. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/ir.py +0 -0
  40. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/json_data.py +0 -0
  41. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/overlaps.py +0 -0
  42. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/projection.py +0 -0
  43. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/references.py +0 -0
  44. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/scalars.py +0 -0
  45. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/semantic.py +0 -0
  46. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/symbolic.py +0 -0
  47. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/validation.py +0 -0
  48. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/values.py +0 -0
  49. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/kernel/witnesses.py +0 -0
  50. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/py.typed +0 -0
  51. {subschema-0.0.2 → subschema-0.0.3}/src/subschema/types.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: subschema
3
- Version: 0.0.2
3
+ Version: 0.0.3
4
4
  Summary: A conservative JSON Schema subschema prover
5
5
  Project-URL: Homepage, https://github.com/ArakawaHenri/subschema
6
6
  Project-URL: Repository, https://github.com/ArakawaHenri/subschema
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "subschema"
7
- version = "0.0.2"
7
+ version = "0.0.3"
8
8
  description = "A conservative JSON Schema subschema prover"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.12"
@@ -15,7 +15,7 @@ from subschema.dialects import (
15
15
  validate_supported_keywords,
16
16
  )
17
17
  from subschema.kernel.contracts import ProofBudgets, ProofOptions
18
- from subschema.kernel.disjointness import schemas_are_disjoint
18
+ from subschema.kernel.disjointness import schema_is_empty_exact, schemas_are_disjoint
19
19
  from subschema.kernel.engine import ProofEngine
20
20
  from subschema.kernel.json_data import ensure_json_value
21
21
  from subschema.kernel.normalization import normalize_boolean_schemas
@@ -202,12 +202,16 @@ def is_empty(
202
202
  timeout_ms=timeout_ms,
203
203
  )
204
204
  empty_schema = empty_schema_for_dialect(resolved_dialect)
205
- return ProofEngine.for_schemas(
205
+ engine = ProofEngine.for_schemas(
206
206
  schema,
207
207
  empty_schema,
208
208
  dialect=resolved_dialect,
209
209
  options=options,
210
- ).is_subschema_bool(schema, empty_schema)
210
+ )
211
+ exact_empty = schema_is_empty_exact(schema, engine.context)
212
+ if exact_empty.status != "unsupported":
213
+ return exact_empty.as_bool(resolved_dialect)
214
+ return engine.is_subschema_bool(schema, empty_schema)
211
215
 
212
216
 
213
217
  def is_disjoint(
@@ -5,7 +5,7 @@ Proof context, policy, and budget state for the kernel.
5
5
  from __future__ import annotations
6
6
 
7
7
  from dataclasses import dataclass, field
8
- from typing import TYPE_CHECKING, Any
8
+ from typing import Any
9
9
 
10
10
  import subschema.kernel.driver as proof_driver
11
11
  from subschema.dialects import Dialect
@@ -17,9 +17,6 @@ from subschema.kernel.contracts import (
17
17
  )
18
18
  from subschema.kernel.values import stable_key
19
19
 
20
- if TYPE_CHECKING:
21
- from subschema.kernel.evaluation import EvaluationExpression
22
-
23
20
  _EXPENSIVE_PROOF_WORK_LABELS: dict[ExpensiveProofKind, str] = {
24
21
  "array_product": "array product",
25
22
  "branch_product": "branch expansion",
@@ -36,9 +33,7 @@ class ProofContext:
36
33
  dialect: Dialect
37
34
  options: ProofOptions = field(default_factory=ProofOptions)
38
35
  subproof_cache: dict[tuple[Any, ...], ProofResult] = field(default_factory=dict)
39
- evaluation_expression_cache: dict[tuple[Any, ...], EvaluationExpression] = field(
40
- default_factory=dict
41
- )
36
+ cache: dict[tuple[object, ...], object] = field(default_factory=dict)
42
37
  work_meter: ProofWorkMeter = field(init=False)
43
38
 
44
39
  def __post_init__(self) -> None:
@@ -72,6 +67,15 @@ class ProofContext:
72
67
  stable_key(rhs),
73
68
  )
74
69
 
70
+ def cache_get(self, namespace: str, key: tuple[Any, ...]) -> object | None:
71
+ return self.cache.get(self._cache_key(namespace, key))
72
+
73
+ def cache_set(self, namespace: str, key: tuple[Any, ...], value: object) -> None:
74
+ self.cache[self._cache_key(namespace, key)] = value
75
+
76
+ def _cache_key(self, namespace: str, key: tuple[Any, ...]) -> tuple[object, ...]:
77
+ return (namespace, *(_cache_key_part(part) for part in key))
78
+
75
79
  def consume_branch_expansion(self, reason: str) -> ProofResult | None:
76
80
  return self.spend_work(1, "branch expansion", reason)
77
81
 
@@ -132,3 +136,11 @@ class ProofContext:
132
136
  from subschema.kernel.projection import ProjectionEngine
133
137
 
134
138
  return ProjectionEngine(self).finite_join_projection(lhs, rhs)
139
+
140
+
141
+ def _cache_key_part(part: Any) -> object:
142
+ try:
143
+ hash(part)
144
+ except TypeError:
145
+ return stable_key(part)
146
+ return part