relateby-pattern 0.7.2__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 (193) hide show
  1. relateby_pattern-0.7.2/Cargo.toml +32 -0
  2. relateby_pattern-0.7.2/PKG-INFO +14 -0
  3. relateby_pattern-0.7.2/README.md +104 -0
  4. relateby_pattern-0.7.2/benches/Cargo.toml +16 -0
  5. relateby_pattern-0.7.2/benches/benches/README.md +18 -0
  6. relateby_pattern-0.7.2/benches/benches/pattern_operations.rs +13 -0
  7. relateby_pattern-0.7.2/benches/src/lib.rs +3 -0
  8. relateby_pattern-0.7.2/crates/gram-codec/Cargo.toml +67 -0
  9. relateby_pattern-0.7.2/crates/gram-codec/README.md +387 -0
  10. relateby_pattern-0.7.2/crates/gram-codec/benches/codec_benchmarks.rs +196 -0
  11. relateby_pattern-0.7.2/crates/gram-codec/examples/advanced_usage.rs +167 -0
  12. relateby_pattern-0.7.2/crates/gram-codec/examples/basic_usage.rs +123 -0
  13. relateby_pattern-0.7.2/crates/gram-codec/examples/interop_check.rs +28 -0
  14. relateby_pattern-0.7.2/crates/gram-codec/pyproject.toml +39 -0
  15. relateby_pattern-0.7.2/crates/gram-codec/src/ast.rs +586 -0
  16. relateby_pattern-0.7.2/crates/gram-codec/src/cst/lowering.rs +176 -0
  17. relateby_pattern-0.7.2/crates/gram-codec/src/cst/mod.rs +11 -0
  18. relateby_pattern-0.7.2/crates/gram-codec/src/cst/parser.rs +583 -0
  19. relateby_pattern-0.7.2/crates/gram-codec/src/cst/syntax_node.rs +74 -0
  20. relateby_pattern-0.7.2/crates/gram-codec/src/error.rs +299 -0
  21. relateby_pattern-0.7.2/crates/gram-codec/src/json.rs +353 -0
  22. relateby_pattern-0.7.2/crates/gram-codec/src/lib.rs +253 -0
  23. relateby_pattern-0.7.2/crates/gram-codec/src/parser/annotation.rs +173 -0
  24. relateby_pattern-0.7.2/crates/gram-codec/src/parser/combinators.rs +135 -0
  25. relateby_pattern-0.7.2/crates/gram-codec/src/parser/error.rs +129 -0
  26. relateby_pattern-0.7.2/crates/gram-codec/src/parser/mod.rs +253 -0
  27. relateby_pattern-0.7.2/crates/gram-codec/src/parser/node.rs +76 -0
  28. relateby_pattern-0.7.2/crates/gram-codec/src/parser/relationship.rs +382 -0
  29. relateby_pattern-0.7.2/crates/gram-codec/src/parser/subject.rs +229 -0
  30. relateby_pattern-0.7.2/crates/gram-codec/src/parser/types.rs +214 -0
  31. relateby_pattern-0.7.2/crates/gram-codec/src/parser/value.rs +738 -0
  32. relateby_pattern-0.7.2/crates/gram-codec/src/python.rs +389 -0
  33. relateby_pattern-0.7.2/crates/gram-codec/src/serializer.rs +522 -0
  34. relateby_pattern-0.7.2/crates/gram-codec/src/standard_graph.rs +20 -0
  35. relateby_pattern-0.7.2/crates/gram-codec/src/transform.rs +494 -0
  36. relateby_pattern-0.7.2/crates/gram-codec/src/value.rs +384 -0
  37. relateby_pattern-0.7.2/crates/gram-codec/src/wasm.rs +197 -0
  38. relateby_pattern-0.7.2/crates/gram-codec/tests/advanced_features_tests.rs +286 -0
  39. relateby_pattern-0.7.2/crates/gram-codec/tests/arrow_style_variants_tests.rs +306 -0
  40. relateby_pattern-0.7.2/crates/gram-codec/tests/arrow_types_tests.rs +185 -0
  41. relateby_pattern-0.7.2/crates/gram-codec/tests/ast_integration_tests.rs +80 -0
  42. relateby_pattern-0.7.2/crates/gram-codec/tests/ast_roundtrip_tests.rs +110 -0
  43. relateby_pattern-0.7.2/crates/gram-codec/tests/corpus/mod.rs +204 -0
  44. relateby_pattern-0.7.2/crates/gram-codec/tests/corpus/parser.rs +263 -0
  45. relateby_pattern-0.7.2/crates/gram-codec/tests/corpus/runner.rs +226 -0
  46. relateby_pattern-0.7.2/crates/gram-codec/tests/corpus/validator.rs +289 -0
  47. relateby_pattern-0.7.2/crates/gram-codec/tests/corpus_integration.rs +71 -0
  48. relateby_pattern-0.7.2/crates/gram-codec/tests/cst/comment_tests.rs +138 -0
  49. relateby_pattern-0.7.2/crates/gram-codec/tests/cst/error_recovery_tests.rs +20 -0
  50. relateby_pattern-0.7.2/crates/gram-codec/tests/cst/lowering_tests.rs +215 -0
  51. relateby_pattern-0.7.2/crates/gram-codec/tests/cst/mod.rs +4 -0
  52. relateby_pattern-0.7.2/crates/gram-codec/tests/cst/parse_tests.rs +206 -0
  53. relateby_pattern-0.7.2/crates/gram-codec/tests/cst_integration.rs +8 -0
  54. relateby_pattern-0.7.2/crates/gram-codec/tests/edge_cases_tests.rs +322 -0
  55. relateby_pattern-0.7.2/crates/gram-codec/tests/interop_gram_hs_tests.rs +150 -0
  56. relateby_pattern-0.7.2/crates/gram-codec/tests/json_alignment_test.rs +101 -0
  57. relateby_pattern-0.7.2/crates/gram-codec/tests/map_roundtrip.rs +138 -0
  58. relateby_pattern-0.7.2/crates/gram-codec/tests/parser_tests.rs +177 -0
  59. relateby_pattern-0.7.2/crates/gram-codec/tests/relationship_with_edge_identifier_tests.rs +170 -0
  60. relateby_pattern-0.7.2/crates/gram-codec/tests/round_trip_tests.rs +215 -0
  61. relateby_pattern-0.7.2/crates/gram-codec/tests/schema_validation.rs +217 -0
  62. relateby_pattern-0.7.2/crates/gram-codec/tests/serializer_tests.rs +255 -0
  63. relateby_pattern-0.7.2/crates/gram-codec/tests/value_types_tests.rs +210 -0
  64. relateby_pattern-0.7.2/crates/pattern-core/API-CHANGES.md +228 -0
  65. relateby_pattern-0.7.2/crates/pattern-core/API-IMPROVEMENTS-SUMMARY.md +288 -0
  66. relateby_pattern-0.7.2/crates/pattern-core/CHANGELOG.md +102 -0
  67. relateby_pattern-0.7.2/crates/pattern-core/Cargo.toml +63 -0
  68. relateby_pattern-0.7.2/crates/pattern-core/GENERIC-VALUE-FIX.md +231 -0
  69. relateby_pattern-0.7.2/crates/pattern-core/PYTHON-DEVELOPMENT.md +292 -0
  70. relateby_pattern-0.7.2/crates/pattern-core/PYTHON-TYPE-CHECKING.md +160 -0
  71. relateby_pattern-0.7.2/crates/pattern-core/README.md +224 -0
  72. relateby_pattern-0.7.2/crates/pattern-core/TERMINOLOGY-CLEANUP-SUMMARY.md +223 -0
  73. relateby_pattern-0.7.2/crates/pattern-core/TERMINOLOGY-CORRECTION.md +191 -0
  74. relateby_pattern-0.7.2/crates/pattern-core/TRAVERSABLE_NOTES.md +193 -0
  75. relateby_pattern-0.7.2/crates/pattern-core/benches/fold_benchmarks.rs +288 -0
  76. relateby_pattern-0.7.2/crates/pattern-core/benches/ord_benchmarks.rs +330 -0
  77. relateby_pattern-0.7.2/crates/pattern-core/benches/predicate_benchmarks.rs +223 -0
  78. relateby_pattern-0.7.2/crates/pattern-core/benches/query_benchmarks.rs +278 -0
  79. relateby_pattern-0.7.2/crates/pattern-core/benches/semigroup_benchmarks.rs +235 -0
  80. relateby_pattern-0.7.2/crates/pattern-core/examples/comonad_usage.rs +284 -0
  81. relateby_pattern-0.7.2/crates/pattern-core/examples/paramorphism_usage.rs +175 -0
  82. relateby_pattern-0.7.2/crates/pattern-core/examples/standard_graph_usage.rs +179 -0
  83. relateby_pattern-0.7.2/crates/pattern-core/pyproject.toml +39 -0
  84. relateby_pattern-0.7.2/crates/pattern-core/src/graph/algorithms.rs +713 -0
  85. relateby_pattern-0.7.2/crates/pattern-core/src/graph/graph_classifier.rs +167 -0
  86. relateby_pattern-0.7.2/crates/pattern-core/src/graph/graph_query.rs +515 -0
  87. relateby_pattern-0.7.2/crates/pattern-core/src/graph/graph_view.rs +188 -0
  88. relateby_pattern-0.7.2/crates/pattern-core/src/graph/mod.rs +26 -0
  89. relateby_pattern-0.7.2/crates/pattern-core/src/graph/standard.rs +453 -0
  90. relateby_pattern-0.7.2/crates/pattern-core/src/graph/transform/context.rs +42 -0
  91. relateby_pattern-0.7.2/crates/pattern-core/src/graph/transform/map_filter_fold.rs +139 -0
  92. relateby_pattern-0.7.2/crates/pattern-core/src/graph/transform/mod.rs +11 -0
  93. relateby_pattern-0.7.2/crates/pattern-core/src/graph/transform/para.rs +280 -0
  94. relateby_pattern-0.7.2/crates/pattern-core/src/graph/transform/types.rs +49 -0
  95. relateby_pattern-0.7.2/crates/pattern-core/src/graph/transform/unfold_graph.rs +61 -0
  96. relateby_pattern-0.7.2/crates/pattern-core/src/lib.rs +727 -0
  97. relateby_pattern-0.7.2/crates/pattern-core/src/pattern/comonad.rs +147 -0
  98. relateby_pattern-0.7.2/crates/pattern-core/src/pattern/comonad_helpers.rs +227 -0
  99. relateby_pattern-0.7.2/crates/pattern-core/src/pattern/core.rs +3996 -0
  100. relateby_pattern-0.7.2/crates/pattern-core/src/pattern/mod.rs +7 -0
  101. relateby_pattern-0.7.2/crates/pattern-core/src/pattern/unfold.rs +69 -0
  102. relateby_pattern-0.7.2/crates/pattern-core/src/pattern_graph.rs +566 -0
  103. relateby_pattern-0.7.2/crates/pattern-core/src/python.rs +14 -0
  104. relateby_pattern-0.7.2/crates/pattern-core/src/reconcile.rs +355 -0
  105. relateby_pattern-0.7.2/crates/pattern-core/src/subject.rs +501 -0
  106. relateby_pattern-0.7.2/crates/pattern-core/src/test_utils/equivalence.rs +207 -0
  107. relateby_pattern-0.7.2/crates/pattern-core/src/test_utils/generators.rs +146 -0
  108. relateby_pattern-0.7.2/crates/pattern-core/src/test_utils/helpers.rs +209 -0
  109. relateby_pattern-0.7.2/crates/pattern-core/src/test_utils/mod.rs +10 -0
  110. relateby_pattern-0.7.2/crates/pattern-core/src/wasm.rs +3328 -0
  111. relateby_pattern-0.7.2/crates/pattern-core/tests/algorithms.rs +654 -0
  112. relateby_pattern-0.7.2/crates/pattern-core/tests/analysis.rs +131 -0
  113. relateby_pattern-0.7.2/crates/pattern-core/tests/analysis_balanced_tree_bug.rs +44 -0
  114. relateby_pattern-0.7.2/crates/pattern-core/tests/analysis_property.rs +15 -0
  115. relateby_pattern-0.7.2/crates/pattern-core/tests/analysis_trailing_zeros_bug.rs +87 -0
  116. relateby_pattern-0.7.2/crates/pattern-core/tests/comonad_laws.rs +293 -0
  117. relateby_pattern-0.7.2/crates/pattern-core/tests/equivalence/extracted_data.rs +24 -0
  118. relateby_pattern-0.7.2/crates/pattern-core/tests/equivalence/pattern_structure.rs +48 -0
  119. relateby_pattern-0.7.2/crates/pattern-core/tests/equivalence/test_data.rs +50 -0
  120. relateby_pattern-0.7.2/crates/pattern-core/tests/foldable_basic.rs +322 -0
  121. relateby_pattern-0.7.2/crates/pattern-core/tests/foldable_collections.rs +337 -0
  122. relateby_pattern-0.7.2/crates/pattern-core/tests/foldable_custom.rs +346 -0
  123. relateby_pattern-0.7.2/crates/pattern-core/tests/foldable_integration.rs +257 -0
  124. relateby_pattern-0.7.2/crates/pattern-core/tests/foldable_scale.rs +347 -0
  125. relateby_pattern-0.7.2/crates/pattern-core/tests/functor_laws.rs +399 -0
  126. relateby_pattern-0.7.2/crates/pattern-core/tests/graph_classifier.rs +124 -0
  127. relateby_pattern-0.7.2/crates/pattern-core/tests/graph_query.rs +632 -0
  128. relateby_pattern-0.7.2/crates/pattern-core/tests/graph_view.rs +233 -0
  129. relateby_pattern-0.7.2/crates/pattern-core/tests/hash_basic.rs +276 -0
  130. relateby_pattern-0.7.2/crates/pattern-core/tests/hash_consistency.rs +245 -0
  131. relateby_pattern-0.7.2/crates/pattern-core/tests/hash_integration.rs +341 -0
  132. relateby_pattern-0.7.2/crates/pattern-core/tests/helpers_example.rs +21 -0
  133. relateby_pattern-0.7.2/crates/pattern-core/tests/monoid_default.rs +342 -0
  134. relateby_pattern-0.7.2/crates/pattern-core/tests/monoid_identity.rs +356 -0
  135. relateby_pattern-0.7.2/crates/pattern-core/tests/monoid_integration.rs +412 -0
  136. relateby_pattern-0.7.2/crates/pattern-core/tests/ord_basic.rs +329 -0
  137. relateby_pattern-0.7.2/crates/pattern-core/tests/ord_collections.rs +436 -0
  138. relateby_pattern-0.7.2/crates/pattern-core/tests/ord_equivalence.rs +305 -0
  139. relateby_pattern-0.7.2/crates/pattern-core/tests/ord_extrema.rs +322 -0
  140. relateby_pattern-0.7.2/crates/pattern-core/tests/ord_property.rs +311 -0
  141. relateby_pattern-0.7.2/crates/pattern-core/tests/pattern_graph.rs +186 -0
  142. relateby_pattern-0.7.2/crates/pattern-core/tests/predicate_contains.rs +432 -0
  143. relateby_pattern-0.7.2/crates/pattern-core/tests/predicate_matches.rs +423 -0
  144. relateby_pattern-0.7.2/crates/pattern-core/tests/predicate_properties.rs +306 -0
  145. relateby_pattern-0.7.2/crates/pattern-core/tests/property/equality.rs +26 -0
  146. relateby_pattern-0.7.2/crates/pattern-core/tests/property/validation.rs +17 -0
  147. relateby_pattern-0.7.2/crates/pattern-core/tests/python/PHASE6-PROGRESS.md +204 -0
  148. relateby_pattern-0.7.2/crates/pattern-core/tests/python/README.md +201 -0
  149. relateby_pattern-0.7.2/crates/pattern-core/tests/query_all_values.rs +164 -0
  150. relateby_pattern-0.7.2/crates/pattern-core/tests/query_all_values_property.rs +83 -0
  151. relateby_pattern-0.7.2/crates/pattern-core/tests/query_any_value.rs +130 -0
  152. relateby_pattern-0.7.2/crates/pattern-core/tests/query_any_value_property.rs +76 -0
  153. relateby_pattern-0.7.2/crates/pattern-core/tests/query_existing.rs +287 -0
  154. relateby_pattern-0.7.2/crates/pattern-core/tests/query_filter.rs +187 -0
  155. relateby_pattern-0.7.2/crates/pattern-core/tests/query_filter_property.rs +107 -0
  156. relateby_pattern-0.7.2/crates/pattern-core/tests/query_find_first.rs +435 -0
  157. relateby_pattern-0.7.2/crates/pattern-core/tests/semigroup_basic.rs +263 -0
  158. relateby_pattern-0.7.2/crates/pattern-core/tests/semigroup_equivalence.rs +294 -0
  159. relateby_pattern-0.7.2/crates/pattern-core/tests/semigroup_integration.rs +296 -0
  160. relateby_pattern-0.7.2/crates/pattern-core/tests/semigroup_property.rs +284 -0
  161. relateby_pattern-0.7.2/crates/pattern-core/tests/snapshot/README.md +29 -0
  162. relateby_pattern-0.7.2/crates/pattern-core/tests/snapshot/analysis.rs +46 -0
  163. relateby_pattern-0.7.2/crates/pattern-core/tests/snapshot/serialization.rs +14 -0
  164. relateby_pattern-0.7.2/crates/pattern-core/tests/snapshot/validation.rs +52 -0
  165. relateby_pattern-0.7.2/crates/pattern-core/tests/snapshot_analysis.rs +68 -0
  166. relateby_pattern-0.7.2/crates/pattern-core/tests/snapshot_validation.rs +59 -0
  167. relateby_pattern-0.7.2/crates/pattern-core/tests/standard_graph_tests.rs +612 -0
  168. relateby_pattern-0.7.2/crates/pattern-core/tests/transform.rs +507 -0
  169. relateby_pattern-0.7.2/crates/pattern-core/tests/traversable_integration.rs +263 -0
  170. relateby_pattern-0.7.2/crates/pattern-core/tests/traversable_laws.rs +118 -0
  171. relateby_pattern-0.7.2/crates/pattern-core/tests/traversable_option.rs +170 -0
  172. relateby_pattern-0.7.2/crates/pattern-core/tests/traversable_result.rs +316 -0
  173. relateby_pattern-0.7.2/crates/pattern-core/tests/traversable_validate.rs +315 -0
  174. relateby_pattern-0.7.2/crates/pattern-core/tests/unit/validation.rs +112 -0
  175. relateby_pattern-0.7.2/crates/pattern-core/tests/validation.rs +120 -0
  176. relateby_pattern-0.7.2/crates/pattern-core/tests/validation_property.rs +15 -0
  177. relateby_pattern-0.7.2/crates/pattern-core/tests/verify_short_circuit_bug.rs +112 -0
  178. relateby_pattern-0.7.2/crates/pattern-core/uv.lock +873 -0
  179. relateby_pattern-0.7.2/pyproject.toml +88 -0
  180. relateby_pattern-0.7.2/relateby/__init__.py +3 -0
  181. relateby_pattern-0.7.2/relateby/_native/__init__.py +1 -0
  182. relateby_pattern-0.7.2/relateby/gram/__init__.py +302 -0
  183. relateby_pattern-0.7.2/relateby/gram/__init__.pyi +26 -0
  184. relateby_pattern-0.7.2/relateby/pattern/__init__.py +69 -0
  185. relateby_pattern-0.7.2/relateby/pattern/__init__.pyi +229 -0
  186. relateby_pattern-0.7.2/relateby/pattern/_decode.py +163 -0
  187. relateby_pattern-0.7.2/relateby/pattern/_graph_transforms.py +475 -0
  188. relateby_pattern-0.7.2/relateby/pattern/_pattern.py +422 -0
  189. relateby_pattern-0.7.2/relateby/pattern/_standard_graph.py +319 -0
  190. relateby_pattern-0.7.2/relateby/pattern/_subject.py +77 -0
  191. relateby_pattern-0.7.2/relateby/pattern/_value.py +143 -0
  192. relateby_pattern-0.7.2/relateby/py.typed +1 -0
  193. relateby_pattern-0.7.2/relateby_build/__init__.py +432 -0
@@ -0,0 +1,32 @@
1
+ [workspace]
2
+ members = [
3
+ "crates/pattern-core",
4
+ "crates/gram-codec",
5
+ "benches",
6
+ ]
7
+ exclude = ["external/tree-sitter-gram"]
8
+ resolver = "2"
9
+
10
+ [workspace.package]
11
+ version = "0.7.2"
12
+ edition = "2021"
13
+ rust-version = "1.70.0"
14
+ authors = ["gram-data"]
15
+ license = "BSD-3-Clause"
16
+ description = "Rust port of gram-hs pattern data structure and graph views"
17
+ repository = "https://github.com/relateby/pattern-rs"
18
+
19
+ [workspace.dependencies]
20
+ serde = { version = "1.0", features = ["derive"] }
21
+ serde_json = "1.0"
22
+ thiserror = "2.0"
23
+ proptest = "1.0"
24
+ insta = "1.0"
25
+ criterion = { version = "0.5", default-features = false, features = ["html_reports"] }
26
+ clap = { version = "4", features = ["derive"] }
27
+ strsim = "0.11"
28
+
29
+ # Note: Previously had `[profile.release]` with opt-level="z" and lto=true,
30
+ # but this affected ALL workspace crates (not just WASM). Removed to avoid
31
+ # performance degradation in non-WASM binaries. For WASM size optimization,
32
+ # use wasm-pack which applies appropriate settings: `wasm-pack build --release`
@@ -0,0 +1,14 @@
1
+ Metadata-Version: 2.1
2
+ Name: relateby-pattern
3
+ Version: 0.7.2
4
+ Summary: Combined Python distribution for relateby.pattern and relateby.gram
5
+ License: Apache-2.0
6
+ Requires-Python: >=3.8,<3.14
7
+ Provides-Extra: dev
8
+ Requires-Dist: maturin>=1.0,<2.0; extra == 'dev'
9
+ Requires-Dist: pytest>=7.0; extra == 'dev'
10
+ Requires-Dist: pytest-cov>=4.0; extra == 'dev'
11
+ Requires-Dist: twine>=5.0; extra == 'dev'
12
+ Requires-Dist: pdoc>=14.0; extra == 'dev'
13
+ Provides-Extra: all
14
+ Requires-Dist: relateby-pattern[dev]; extra == 'all'
@@ -0,0 +1,104 @@
1
+ # Relateby
2
+
3
+ Combined Python distribution for the pattern-rs library. One install provides both subpackages:
4
+
5
+ - **relateby.pattern** — Pattern data structures (from pattern-core)
6
+ - **relateby.gram** — Gram notation parser and serializer (from gram-codec)
7
+
8
+ The published distribution name is **relateby-pattern** while the import namespace remains `relateby.*`.
9
+
10
+ ## Install
11
+
12
+ ```bash
13
+ # Combined distribution (pattern + gram)
14
+ pip install relateby-pattern
15
+
16
+ # With optional dependencies (e.g. dev tools)
17
+ pip install relateby-pattern[dev] # maturin, pytest, pytest-cov
18
+ pip install relateby-pattern[all] # all optional extras
19
+ ```
20
+
21
+ For a local source checkout, prefer `uv` with a project-local virtual environment:
22
+
23
+ ```bash
24
+ cd python/packages/relateby
25
+ uv venv --python 3.13 .venv
26
+ source .venv/bin/activate
27
+ uv pip install '.[dev]'
28
+ ```
29
+
30
+ `python/packages/relateby` does not currently support editable installs (`pip install -e .`) because the custom build backend only implements wheel and sdist builds.
31
+ The supported Python range is `>=3.8,<3.14`; `3.13` is the recommended local development target.
32
+
33
+ After installation, run import checks and examples from outside `python/packages/relateby` so the source tree does not shadow the installed package.
34
+
35
+ ## Use
36
+
37
+ ```python
38
+ import relateby.pattern
39
+ import relateby.gram
40
+ ```
41
+
42
+ There are no top-level `pattern_core` or `gram_codec` imports; use `relateby.pattern` and `relateby.gram` only.
43
+
44
+ Representative public imports:
45
+
46
+ ```python
47
+ from relateby.pattern import Pattern, StandardGraph, StringVal, Subject
48
+ from relateby.gram import gram_validate, parse_gram, round_trip
49
+ ```
50
+
51
+ Example public workflow:
52
+
53
+ ```python
54
+ alice = Subject.from_id("alice").with_label("Person").with_property("name", StringVal("Alice"))
55
+ graph = StandardGraph.from_patterns([Pattern.point(alice)])
56
+
57
+ assert graph.node_count == 1
58
+ assert len(parse_gram("(alice:Person)")) == 1
59
+ assert gram_validate("(alice:Person)") == []
60
+ assert round_trip("(alice:Person)") == "(alice:Person)"
61
+ ```
62
+
63
+ ## JSON Interchange
64
+
65
+ `Pattern<Subject>` can be serialized to and from a plain JSON-compatible format defined by the [gram interchange schema](https://github.com/gram-data/tree-sitter-gram/blob/main/docs/pattern.schema.json). This is useful when you need to pass patterns across a process or network boundary without re-parsing gram notation on the other side.
66
+
67
+ **Producer** (parse gram → emit raw JSON):
68
+
69
+ ```python
70
+ from relateby.gram import parse_raw
71
+ import json
72
+
73
+ raw = parse_raw("(alice:Person)-[:KNOWS]->(bob:Person)")
74
+ payload = json.dumps(raw)
75
+ ```
76
+
77
+ **Consumer** (receive raw JSON → reconstruct patterns):
78
+
79
+ ```python
80
+ from relateby.pattern import pattern_from_dict, validate_payload
81
+ import json
82
+
83
+ raw = json.loads(payload)
84
+ patterns = [pattern_from_dict(item) for item in validate_payload(raw)]
85
+ ```
86
+
87
+ **Round-trip** (native ↔ JSON):
88
+
89
+ ```python
90
+ from relateby.pattern import pattern_from_dict, pattern_to_dict
91
+
92
+ raw = pattern_to_dict(pattern) # Pattern[Subject] → RawPattern dict
93
+ restored = pattern_from_dict(raw) # RawPattern dict → Pattern[Subject]
94
+ ```
95
+
96
+ `RawPattern` and `RawSubject` are `TypedDict` types exported from `relateby.pattern` for use in type annotations.
97
+
98
+ ## Building from source
99
+
100
+ From the repository root, build the wheel from the combined package directory (requires maturin and Rust; Python 3.8–3.13 for the extension build):
101
+
102
+ ```bash
103
+ cd python/packages/relateby && uv build --wheel --python 3.13 --out-dir dist
104
+ ```
@@ -0,0 +1,16 @@
1
+ [package]
2
+ name = "pattern-rs-benches"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ rust-version.workspace = true
6
+ license.workspace = true
7
+ description = "Benchmarks for pattern-rs"
8
+
9
+ [[bench]]
10
+ name = "pattern_operations"
11
+ harness = false
12
+
13
+ [dependencies]
14
+ criterion = { workspace = true }
15
+ pattern_core = { package = "relateby-pattern", path = "../crates/pattern-core" }
16
+ gram_codec = { package = "relateby-gram", path = "../crates/gram-codec" }
@@ -0,0 +1,18 @@
1
+ # Benchmark Suite
2
+
3
+ This directory contains performance benchmarks using Criterion.
4
+
5
+ ## Running Benchmarks
6
+
7
+ ```bash
8
+ cargo bench
9
+ ```
10
+
11
+ ## Benchmark Organization
12
+
13
+ - `pattern_operations.rs` - Core pattern operation benchmarks
14
+
15
+ ## WASM Compatibility
16
+
17
+ Benchmarks use conditional compilation for WASM targets due to timing limitations.
18
+
@@ -0,0 +1,13 @@
1
+ //! Benchmarks for pattern operations
2
+ //!
3
+ //! These benchmarks measure performance of pattern operations to track
4
+ //! performance over time and detect regressions.
5
+
6
+ use criterion::{black_box, criterion_group, criterion_main, Criterion};
7
+
8
+ fn benchmark_placeholder(c: &mut Criterion) {
9
+ c.bench_function("placeholder", |b| b.iter(|| black_box(42)));
10
+ }
11
+
12
+ criterion_group!(benches, benchmark_placeholder);
13
+ criterion_main!(benches);
@@ -0,0 +1,3 @@
1
+ //! Benchmark package for pattern-rs
2
+ //!
3
+ //! This package contains performance benchmarks for the pattern-rs workspace.
@@ -0,0 +1,67 @@
1
+ [package]
2
+ name = "relateby-gram"
3
+ version.workspace = true
4
+ edition.workspace = true
5
+ rust-version.workspace = true
6
+ authors.workspace = true
7
+ license.workspace = true
8
+ description = "Bidirectional codec between Gram notation and Pattern data structures"
9
+ readme = "README.md"
10
+ documentation = "https://docs.rs/relateby-gram"
11
+ repository = "https://github.com/relateby/pattern-rs"
12
+
13
+ [package.metadata.docs.rs]
14
+ all-features = false
15
+ features = []
16
+
17
+ [dependencies]
18
+ # Version must match workspace [workspace.package] version when publishing to crates.io.
19
+ pattern_core = { package = "relateby-pattern", path = "../pattern-core", version = "0.7.2" }
20
+ nom = "7"
21
+ serde = { version = "1.0", features = ["derive"] }
22
+ serde_json = "1.0"
23
+ thiserror.workspace = true
24
+ tree-sitter = { version = "0.25", optional = true }
25
+ tree-sitter-gram = { version = "0.6", optional = true }
26
+
27
+ # WASM support
28
+ wasm-bindgen = { version = "0.2", optional = true }
29
+ js-sys = { version = "0.3", optional = true }
30
+
31
+ # Python support
32
+ pyo3 = { version = "0.23", optional = true, features = ["extension-module"] }
33
+ pythonize = { version = "0.23", optional = true }
34
+
35
+ [dev-dependencies]
36
+ insta.workspace = true
37
+ criterion.workspace = true
38
+ proptest = "1.0"
39
+
40
+ [features]
41
+ default = []
42
+ wasm = ["wasm-bindgen", "js-sys"]
43
+ python = ["pyo3", "pythonize", "pyo3/abi3-py38"]
44
+ cst = ["dep:tree-sitter", "dep:tree-sitter-gram"]
45
+
46
+ [lib]
47
+ name = "gram_codec"
48
+ path = "src/lib.rs"
49
+ crate-type = ["cdylib", "rlib"]
50
+
51
+ [[bench]]
52
+ name = "codec_benchmarks"
53
+ harness = false
54
+ required-features = []
55
+
56
+ [[example]]
57
+ name = "interop_check"
58
+ path = "examples/interop_check.rs"
59
+
60
+ [[example]]
61
+ name = "basic_usage"
62
+ path = "examples/basic_usage.rs"
63
+
64
+ [[example]]
65
+ name = "advanced_usage"
66
+ path = "examples/advanced_usage.rs"
67
+
@@ -0,0 +1,387 @@
1
+ # Gram Codec
2
+
3
+ Bidirectional codec between [Gram notation](https://github.com/gram-data/tree-sitter-gram) (human-readable text format) and Pattern data structures.
4
+
5
+ [![CI Status](https://github.com/relateby/pattern-rs/workflows/CI/badge.svg)](https://github.com/relateby/pattern-rs/actions)
6
+ [![License: Apache 2.0](https://img.shields.io/badge/License-Apache%202.0-blue.svg)](https://opensource.org/licenses/Apache-2.0)
7
+
8
+ ## Features
9
+
10
+ - **Full Grammar Support**: Parses all Gram syntax forms (nodes, relationships, subject patterns, annotations)
11
+ - **Round-Trip Correctness**: Parse → serialize → parse produces structurally equivalent patterns
12
+ - **Error Recovery**: Reports all syntax errors, not just the first
13
+ - **Value Types**: Supports strings, integers, decimals, booleans, arrays, ranges, tagged strings
14
+ - **Unicode Support**: Full Unicode identifier and property value support
15
+ - **Comprehensive Testing**: 139+ tests covering all syntax forms and edge cases
16
+
17
+ ## Installation
18
+
19
+ Add to your `Cargo.toml`:
20
+
21
+ ```toml
22
+ [dependencies]
23
+ gram-codec = { path = "../gram-codec" }
24
+ pattern-core = { path = "../pattern-core" }
25
+ ```
26
+
27
+ ## Quick Start
28
+
29
+ ### Parsing Gram Notation
30
+
31
+ ```rust
32
+ use gram_codec::parse_gram;
33
+
34
+ // Parse a simple node
35
+ let patterns = parse_gram("(hello)")?;
36
+ println!("Identifier: {}", patterns[0].value.identity.0);
37
+
38
+ // Parse a relationship
39
+ let patterns = parse_gram("(alice)-[:KNOWS]->(bob)")?;
40
+ println!("Relationship with {} elements", patterns[0].elements.len());
41
+
42
+ // Parse a subject pattern
43
+ let patterns = parse_gram("[team | (alice), (bob)]")?;
44
+ println!("Team has {} members", patterns[0].elements.len());
45
+ ```
46
+
47
+ ### Serializing Patterns
48
+
49
+ ```rust
50
+ use gram_codec::{to_gram_pattern, to_gram};
51
+ use pattern_core::{Pattern, Subject, Symbol};
52
+ use std::collections::{HashMap, HashSet};
53
+
54
+ // Create a pattern
55
+ let subject = Subject {
56
+ identity: Symbol("hello".to_string()),
57
+ labels: HashSet::new(),
58
+ properties: HashMap::new(),
59
+ };
60
+ let pattern = Pattern::point(subject);
61
+
62
+ // Serialize a single pattern
63
+ let gram_text = to_gram_pattern(&pattern)?;
64
+ println!("{}", gram_text); // Output: (hello)
65
+
66
+ // Serialize multiple patterns
67
+ let multiple = to_gram(&[pattern.clone(), pattern])?;
68
+ println!("{}", multiple); // Output: (hello)\n(hello)
69
+ ```
70
+
71
+ ### Round-Trip Correctness
72
+
73
+ ```rust
74
+ use gram_codec::{parse_gram, to_gram_pattern};
75
+
76
+ let original = "(alice:Person {name: \"Alice\"})";
77
+
78
+ // Parse
79
+ let parsed = parse_gram(original)?;
80
+
81
+ // Serialize
82
+ let serialized = to_gram_pattern(&parsed[0])?;
83
+
84
+ // Re-parse
85
+ let reparsed = parse_gram(&serialized)?;
86
+
87
+ // Verify structural equivalence
88
+ assert_eq!(parsed[0].value.identity, reparsed[0].value.identity);
89
+ ```
90
+
91
+ ## Supported Gram Syntax
92
+
93
+ ### Node Patterns (0 elements)
94
+
95
+ ```gram
96
+ () // Empty node
97
+ (hello) // Node with identifier
98
+ (a:Person) // Node with label
99
+ (a:Person {name: "Alice"}) // Node with properties
100
+ ```
101
+
102
+ ### Relationship Patterns (2 elements)
103
+
104
+ The grammar accepts **multiple visual arrow styles** that normalize to **4 semantic arrow kinds**:
105
+
106
+ #### Right Arrow (`right_arrow`) - Directed left-to-right
107
+ ```gram
108
+ (a)-->(b) // Single-stroke (canonical)
109
+ (a)==>(b) // Double-stroke
110
+ (a)~~>(b) // Squiggle
111
+ (a)-[:KNOWS]->(b) // With label
112
+ (a)-[:KNOWS {since: 2020}]->(b) // With properties
113
+ ```
114
+
115
+ #### Left Arrow (`left_arrow`) - Directed right-to-left (elements reversed)
116
+ ```gram
117
+ (a)<--(b) // Single-stroke (canonical)
118
+ (a)<==(b) // Double-stroke
119
+ (a)<~~(b) // Squiggle
120
+ // Note: (a)<--(b) stores elements as [b, a] (reversed!)
121
+ ```
122
+
123
+ #### Bidirectional Arrow (`bidirectional_arrow`) - Mutual connection
124
+ ```gram
125
+ (a)<-->(b) // Single-stroke (canonical)
126
+ (a)<==>(b) // Double-stroke
127
+ ```
128
+
129
+ #### Undirected Arrow (`undirected_arrow`) - No directionality
130
+ ```gram
131
+ (a)~~(b) // Squiggle (canonical)
132
+ (a)==(b) // Double-stroke
133
+ ```
134
+
135
+ **Element Ordering:**
136
+ - **Right arrows**: Elements stored as `[left, right]` (as written)
137
+ - **Left arrows**: Elements stored as `[right, left]` (reversed from visual order!)
138
+ - **Bidirectional/Undirected**: Elements stored as `[first, second]` (as written)
139
+
140
+ ### Subject Patterns (N elements)
141
+
142
+ ```gram
143
+ [team | (alice), (bob)] // Pattern with elements
144
+ [outer | [inner | (leaf)]] // Nested patterns
145
+ [root:Type {p: 1} | e1, e2] // With identifier, label, properties
146
+ ```
147
+
148
+ ### Annotated Patterns (1 element)
149
+
150
+ ```gram
151
+ @type(node) (a) // Annotation on node
152
+ @depth(2) [x | y, z] // Annotation on subject pattern
153
+ ```
154
+
155
+ ### Property Values
156
+
157
+ ```gram
158
+ {
159
+ name: "Alice", // String
160
+ age: 30, // Integer
161
+ score: 95.5, // Decimal
162
+ active: true, // Boolean
163
+ tags: ["rust", "wasm"], // Array
164
+ range: 1..10 // Range
165
+ }
166
+ ```
167
+
168
+ ### Comments
169
+
170
+ ```gram
171
+ // This is a line comment
172
+ (hello)-->(world) // End-of-line comment
173
+ ```
174
+
175
+ ## Advanced Usage
176
+
177
+ ### Complex Relationships
178
+
179
+ ```rust
180
+ let gram_text = "(alice:Person {name: \"Alice\", age: 30})-[:KNOWS {since: 2020}]->(bob:Person {name: \"Bob\"})";
181
+ let patterns = parse_gram_notation(gram_text)?;
182
+
183
+ // Access left node
184
+ println!("Left: {}", patterns[0].elements[0].value.identity.0);
185
+
186
+ // Access edge
187
+ println!("Edge labels: {:?}", patterns[0].value.labels);
188
+
189
+ // Access right node
190
+ println!("Right: {}", patterns[0].elements[1].value.identity.0);
191
+ ```
192
+
193
+ ### Nested Patterns
194
+
195
+ ```rust
196
+ let gram_text = "[outer:Group | [inner:Team | (alice), (bob)], (charlie)]";
197
+ let patterns = parse_gram_notation(gram_text)?;
198
+
199
+ println!("Outer: {}", patterns[0].value.identity.0);
200
+ println!("Elements: {}", patterns[0].elements.len());
201
+ println!("First element is nested: {}",
202
+ !patterns[0].elements[0].elements.is_empty());
203
+ ```
204
+
205
+ ### Path Patterns
206
+
207
+ ```rust
208
+ // Chained relationships
209
+ let gram_text = "(a)-->(b)-->(c)-->(d)";
210
+ let patterns = parse_gram_notation(gram_text)?;
211
+
212
+ // Creates nested relationship structure
213
+ println!("Path pattern parsed");
214
+ ```
215
+
216
+ ### Unicode Support
217
+
218
+ ```rust
219
+ // Unicode identifiers must be quoted
220
+ let gram_text = "(\"世界\" {greeting: \"こんにちは\"})";
221
+ let patterns = parse_gram_notation(gram_text)?;
222
+
223
+ println!("Identifier: {}", patterns[0].value.identity.0);
224
+ ```
225
+
226
+ ### Error Handling
227
+
228
+ ```rust
229
+ use gram_codec::parse_gram_notation;
230
+
231
+ let invalid_gram = "(unclosed";
232
+ match parse_gram_notation(invalid_gram) {
233
+ Ok(_) => println!("Success"),
234
+ Err(e) => {
235
+ println!("Parse error: {}", e.message);
236
+ println!("Error count: {}", e.error_count());
237
+ // Access location information
238
+ println!("Location: line {}, column {}",
239
+ e.location.line, e.location.column);
240
+ }
241
+ }
242
+ ```
243
+
244
+ ## Examples
245
+
246
+ > 📚 **See [`../../examples/gram-codec-README.md`](../../examples/gram-codec-README.md) for complete examples across all platforms!**
247
+
248
+ Run the included examples:
249
+
250
+ ```bash
251
+ # Basic usage (10 examples)
252
+ cargo run --package gram-codec --example basic_usage
253
+
254
+ # Advanced usage (10 examples)
255
+ cargo run --package gram-codec --example advanced_usage
256
+
257
+ # Interactive Python demo
258
+ python examples/gram-codec-python/demo.py
259
+
260
+ # Interactive browser demo
261
+ # (After building: wasm-pack build --target web . -- --features wasm)
262
+ python3 -m http.server 8000
263
+ # Open http://localhost:8000/examples/gram-codec-wasm-web/
264
+ ```
265
+
266
+ ## Testing
267
+
268
+ Run the comprehensive test suite:
269
+
270
+ ```bash
271
+ # All tests (159 tests total)
272
+ cargo test --package gram-codec
273
+
274
+ # Specific test suite
275
+ cargo test --package gram-codec --test parser_tests # 18 tests
276
+ cargo test --package gram-codec --test serializer_tests # 15 tests
277
+ cargo test --package gram-codec --test value_types_tests # 13 tests
278
+ cargo test --package gram-codec --test arrow_types_tests # 14 tests (1 ignored)
279
+ cargo test --package gram-codec --test arrow_style_variants_tests # 19 tests
280
+ cargo test --package gram-codec --test edge_cases_tests # 28 tests
281
+ cargo test --package gram-codec --test advanced_features_tests # 22 tests
282
+ ```
283
+
284
+ ### Test Coverage
285
+
286
+ - **159 tests total** (158 passing + 1 ignored)
287
+ - Unit tests for error handling, parser core, serializer core
288
+ - Comprehensive arrow style variant tests (all 10 visual forms documented)
289
+ - Integration tests for all gram syntax forms
290
+ - Edge case handling (nesting, whitespace, comments, error recovery)
291
+ - Round-trip correctness validation
292
+
293
+ ## Grammar Authority
294
+
295
+ This codec uses [`tree-sitter-gram`](https://github.com/gram-data/tree-sitter-gram) as the authoritative grammar specification. The pure Rust implementation is validated for 100% conformance with the tree-sitter-gram test corpus.
296
+
297
+ ## Architecture
298
+
299
+ The codec consists of several modules:
300
+
301
+ - **`parser`**: Transforms Gram notation text → Pattern structures using a pure Rust `nom` implementation
302
+ - **`serializer`**: Transforms Pattern structures → Gram notation text
303
+ - **`ast`**: AST (Abstract Syntax Tree) types for cross-language JSON serialization
304
+ - **`value`**: Value enum for property types (String, Integer, Decimal, Boolean, Array, Range)
305
+ - **`error`**: Error types with location information
306
+
307
+ ## Multi-Platform Support
308
+
309
+ ### WASM (WebAssembly)
310
+
311
+ Build for browser and Node.js environments:
312
+
313
+ ```bash
314
+ # Using wasm-pack
315
+ wasm-pack build --target web crates/gram-codec -- --features wasm
316
+
317
+ # JavaScript usage
318
+ import init, { parse_gram, validate_gram, round_trip } from './pkg/gram_codec.js';
319
+ await init();
320
+ const result = parse_gram("(hello)-->(world)");
321
+ ```
322
+
323
+ **Examples:**
324
+ - `../../examples/gram-codec-wasm-web/` - Interactive browser demo with UI
325
+ - `../../examples/gram-codec-wasm-node/` - Node.js command-line examples
326
+
327
+ ### Python
328
+
329
+ Build and install Python bindings:
330
+
331
+ ```bash
332
+ pip install maturin
333
+ cd crates/gram-codec
334
+ maturin develop --features python
335
+
336
+ # Python usage
337
+ from gram_codec import parse_gram, validate_gram, round_trip
338
+ result = parse_gram("(hello)-->(world)")
339
+ print(f"Parsed {result['pattern_count']} patterns")
340
+ ```
341
+
342
+ **Examples:**
343
+ - `../../examples/gram-codec-python/demo.py` - Interactive demo with REPL mode
344
+ - `../../examples/gram-codec-python/quickstart.py` - Quick 5-minute introduction
345
+ - `../../examples/gram-codec-python/gram_codec.py` - Template with 10 example functions
346
+
347
+ See `pyproject.toml` for packaging configuration.
348
+
349
+ ## Performance
350
+
351
+ The codec includes comprehensive benchmarks:
352
+
353
+ ```bash
354
+ # Run all benchmarks
355
+ cargo bench --package gram-codec
356
+
357
+ # Specific benchmarks
358
+ cargo bench --package gram-codec --bench codec_benchmarks -- parse_simple_nodes
359
+ cargo bench --package gram-codec --bench codec_benchmarks -- round_trip
360
+ ```
361
+
362
+ Benchmarks cover:
363
+ - Parsing simple nodes (10, 100, 1000 patterns)
364
+ - Parsing relationships and chains
365
+ - Parsing subject patterns with many elements
366
+ - Serialization (single and multiple patterns)
367
+ - Round-trip correctness (parse → serialize → parse)
368
+ - Complex patterns with mixed syntax
369
+
370
+ ## License
371
+
372
+ Licensed under the Apache License, Version 2.0. See [LICENSE](../../LICENSE) for details.
373
+
374
+ ## Contributing
375
+
376
+ Contributions are welcome! Please ensure:
377
+
378
+ - All tests pass: `cargo test --package gram-codec`
379
+ - Code is formatted: `cargo fmt --all`
380
+ - No clippy warnings: `cargo clippy --package gram-codec -- -D warnings`
381
+ - Examples run successfully
382
+
383
+ ## Resources
384
+
385
+ - [Gram Notation Specification](https://github.com/gram-data/tree-sitter-gram)
386
+ - [Pattern Core Library](../pattern-core/)
387
+ - [Project Documentation](../../specs/019-gram-codec/)