pygx-core 0.1.0__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 (36) hide show
  1. pygx_core-0.1.0/.cargo/config.toml +7 -0
  2. pygx_core-0.1.0/.gitignore +5 -0
  3. pygx_core-0.1.0/Cargo.lock +182 -0
  4. pygx_core-0.1.0/Cargo.toml +29 -0
  5. pygx_core-0.1.0/PKG-INFO +43 -0
  6. pygx_core-0.1.0/README.md +24 -0
  7. pygx_core-0.1.0/pygx_core/__init__.py +131 -0
  8. pygx_core-0.1.0/pyproject.toml +33 -0
  9. pygx_core-0.1.0/rebuild.sh +37 -0
  10. pygx_core-0.1.0/run-differential.sh +50 -0
  11. pygx_core-0.1.0/src/container/mod.rs +1666 -0
  12. pygx_core-0.1.0/src/flags/mod.rs +189 -0
  13. pygx_core-0.1.0/src/formatting.rs +634 -0
  14. pygx_core-0.1.0/src/kernel/mod.rs +337 -0
  15. pygx_core-0.1.0/src/key.rs +137 -0
  16. pygx_core-0.1.0/src/key_specs.rs +721 -0
  17. pygx_core-0.1.0/src/keypath.rs +810 -0
  18. pygx_core-0.1.0/src/keypath_set.rs +521 -0
  19. pygx_core-0.1.0/src/lib.rs +153 -0
  20. pygx_core-0.1.0/src/object/mod.rs +2015 -0
  21. pygx_core-0.1.0/src/ops/mod.rs +10 -0
  22. pygx_core-0.1.0/src/symbolic.rs +10 -0
  23. pygx_core-0.1.0/src/typing/mod.rs +11 -0
  24. pygx_core-0.1.0/src/value_specs.rs +8452 -0
  25. pygx_core-0.1.0/tests/test_callable.py +306 -0
  26. pygx_core-0.1.0/tests/test_ctor_meta.py +107 -0
  27. pygx_core-0.1.0/tests/test_dict.py +197 -0
  28. pygx_core-0.1.0/tests/test_fields.py +237 -0
  29. pygx_core-0.1.0/tests/test_flags.py +150 -0
  30. pygx_core-0.1.0/tests/test_kernel.py +258 -0
  31. pygx_core-0.1.0/tests/test_key_specs.py +193 -0
  32. pygx_core-0.1.0/tests/test_keypath.py +64 -0
  33. pygx_core-0.1.0/tests/test_schema.py +224 -0
  34. pygx_core-0.1.0/tests/test_sym_dict.py +275 -0
  35. pygx_core-0.1.0/tests/test_sym_object.py +347 -0
  36. pygx_core-0.1.0/tests/test_value_specs.py +427 -0
@@ -0,0 +1,7 @@
1
+ # macOS: CPython symbols are resolved at load time (the interpreter provides
2
+ # them), so allow undefined symbols at link time for the extension cdylib.
3
+ [target.x86_64-apple-darwin]
4
+ rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]
5
+
6
+ [target.aarch64-apple-darwin]
7
+ rustflags = ["-C", "link-arg=-undefined", "-C", "link-arg=dynamic_lookup"]
@@ -0,0 +1,5 @@
1
+ /target
2
+ *.so
3
+ *.dylib
4
+ __pycache__/
5
+ *.egg-info/
@@ -0,0 +1,182 @@
1
+ # This file is automatically @generated by Cargo.
2
+ # It is not intended for manual editing.
3
+ version = 4
4
+
5
+ [[package]]
6
+ name = "autocfg"
7
+ version = "1.5.1"
8
+ source = "registry+https://github.com/rust-lang/crates.io-index"
9
+ checksum = "f2032f911046de80f0a198e0901378627c33f59ea0ac00e363d481118bd70a53"
10
+
11
+ [[package]]
12
+ name = "heck"
13
+ version = "0.5.0"
14
+ source = "registry+https://github.com/rust-lang/crates.io-index"
15
+ checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
16
+
17
+ [[package]]
18
+ name = "indoc"
19
+ version = "2.0.7"
20
+ source = "registry+https://github.com/rust-lang/crates.io-index"
21
+ checksum = "79cf5c93f93228cf8efb3ba362535fb11199ac548a09ce117c9b1adc3030d706"
22
+ dependencies = [
23
+ "rustversion",
24
+ ]
25
+
26
+ [[package]]
27
+ name = "inventory"
28
+ version = "0.3.24"
29
+ source = "registry+https://github.com/rust-lang/crates.io-index"
30
+ checksum = "a4f0c30c76f2f4ccee3fe55a2435f691ca00c0e4bd87abe4f4a851b1d4dac39b"
31
+ dependencies = [
32
+ "rustversion",
33
+ ]
34
+
35
+ [[package]]
36
+ name = "libc"
37
+ version = "0.2.186"
38
+ source = "registry+https://github.com/rust-lang/crates.io-index"
39
+ checksum = "68ab91017fe16c622486840e4c83c9a37afeff978bd239b5293d61ece587de66"
40
+
41
+ [[package]]
42
+ name = "memoffset"
43
+ version = "0.9.1"
44
+ source = "registry+https://github.com/rust-lang/crates.io-index"
45
+ checksum = "488016bfae457b036d996092f6cb448677611ce4449e970ceaf42695203f218a"
46
+ dependencies = [
47
+ "autocfg",
48
+ ]
49
+
50
+ [[package]]
51
+ name = "once_cell"
52
+ version = "1.21.4"
53
+ source = "registry+https://github.com/rust-lang/crates.io-index"
54
+ checksum = "9f7c3e4beb33f85d45ae3e3a1792185706c8e16d043238c593331cc7cd313b50"
55
+
56
+ [[package]]
57
+ name = "portable-atomic"
58
+ version = "1.13.1"
59
+ source = "registry+https://github.com/rust-lang/crates.io-index"
60
+ checksum = "c33a9471896f1c69cecef8d20cbe2f7accd12527ce60845ff44c153bb2a21b49"
61
+
62
+ [[package]]
63
+ name = "proc-macro2"
64
+ version = "1.0.106"
65
+ source = "registry+https://github.com/rust-lang/crates.io-index"
66
+ checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934"
67
+ dependencies = [
68
+ "unicode-ident",
69
+ ]
70
+
71
+ [[package]]
72
+ name = "pygx-core"
73
+ version = "0.1.0"
74
+ dependencies = [
75
+ "pyo3",
76
+ ]
77
+
78
+ [[package]]
79
+ name = "pyo3"
80
+ version = "0.27.2"
81
+ source = "registry+https://github.com/rust-lang/crates.io-index"
82
+ checksum = "ab53c047fcd1a1d2a8820fe84f05d6be69e9526be40cb03b73f86b6b03e6d87d"
83
+ dependencies = [
84
+ "indoc",
85
+ "inventory",
86
+ "libc",
87
+ "memoffset",
88
+ "once_cell",
89
+ "portable-atomic",
90
+ "pyo3-build-config",
91
+ "pyo3-ffi",
92
+ "pyo3-macros",
93
+ "unindent",
94
+ ]
95
+
96
+ [[package]]
97
+ name = "pyo3-build-config"
98
+ version = "0.27.2"
99
+ source = "registry+https://github.com/rust-lang/crates.io-index"
100
+ checksum = "b455933107de8642b4487ed26d912c2d899dec6114884214a0b3bb3be9261ea6"
101
+ dependencies = [
102
+ "target-lexicon",
103
+ ]
104
+
105
+ [[package]]
106
+ name = "pyo3-ffi"
107
+ version = "0.27.2"
108
+ source = "registry+https://github.com/rust-lang/crates.io-index"
109
+ checksum = "1c85c9cbfaddf651b1221594209aed57e9e5cff63c4d11d1feead529b872a089"
110
+ dependencies = [
111
+ "libc",
112
+ "pyo3-build-config",
113
+ ]
114
+
115
+ [[package]]
116
+ name = "pyo3-macros"
117
+ version = "0.27.2"
118
+ source = "registry+https://github.com/rust-lang/crates.io-index"
119
+ checksum = "0a5b10c9bf9888125d917fb4d2ca2d25c8df94c7ab5a52e13313a07e050a3b02"
120
+ dependencies = [
121
+ "proc-macro2",
122
+ "pyo3-macros-backend",
123
+ "quote",
124
+ "syn",
125
+ ]
126
+
127
+ [[package]]
128
+ name = "pyo3-macros-backend"
129
+ version = "0.27.2"
130
+ source = "registry+https://github.com/rust-lang/crates.io-index"
131
+ checksum = "03b51720d314836e53327f5871d4c0cfb4fb37cc2c4a11cc71907a86342c40f9"
132
+ dependencies = [
133
+ "heck",
134
+ "proc-macro2",
135
+ "pyo3-build-config",
136
+ "quote",
137
+ "syn",
138
+ ]
139
+
140
+ [[package]]
141
+ name = "quote"
142
+ version = "1.0.45"
143
+ source = "registry+https://github.com/rust-lang/crates.io-index"
144
+ checksum = "41f2619966050689382d2b44f664f4bc593e129785a36d6ee376ddf37259b924"
145
+ dependencies = [
146
+ "proc-macro2",
147
+ ]
148
+
149
+ [[package]]
150
+ name = "rustversion"
151
+ version = "1.0.22"
152
+ source = "registry+https://github.com/rust-lang/crates.io-index"
153
+ checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d"
154
+
155
+ [[package]]
156
+ name = "syn"
157
+ version = "2.0.117"
158
+ source = "registry+https://github.com/rust-lang/crates.io-index"
159
+ checksum = "e665b8803e7b1d2a727f4023456bbbbe74da67099c585258af0ad9c5013b9b99"
160
+ dependencies = [
161
+ "proc-macro2",
162
+ "quote",
163
+ "unicode-ident",
164
+ ]
165
+
166
+ [[package]]
167
+ name = "target-lexicon"
168
+ version = "0.13.5"
169
+ source = "registry+https://github.com/rust-lang/crates.io-index"
170
+ checksum = "adb6935a6f5c20170eeceb1a3835a49e12e19d792f6dd344ccc76a985ca5a6ca"
171
+
172
+ [[package]]
173
+ name = "unicode-ident"
174
+ version = "1.0.24"
175
+ source = "registry+https://github.com/rust-lang/crates.io-index"
176
+ checksum = "e6e4313cd5fcd3dad5cafa179702e2b244f760991f45397d14d4ebf38247da75"
177
+
178
+ [[package]]
179
+ name = "unindent"
180
+ version = "0.2.4"
181
+ source = "registry+https://github.com/rust-lang/crates.io-index"
182
+ checksum = "7264e107f553ccae879d21fbea1d6724ac785e8c3bfc762137959b5802826ef3"
@@ -0,0 +1,29 @@
1
+ [package]
2
+ name = "pygx-core"
3
+ version = "0.1.0"
4
+ edition = "2021"
5
+ publish = false
6
+ description = "Minimal compiled core for pygx: Rust-validated symbolic storage for pg.Object."
7
+ license = "Apache-2.0"
8
+ readme = "README.md"
9
+
10
+ # The compiled module is `pygx_core._native`. The minimal core keeps `pg.Object`
11
+ # a Python class and only accelerates field validation + symbolic storage, so it
12
+ # needs ONLY the high-level `pyo3` bindings — no raw `pyo3-ffi` (that was the
13
+ # full-native attempt's heap-type machinery, deliberately dropped here).
14
+ [lib]
15
+ name = "_native"
16
+ crate-type = ["cdylib"]
17
+
18
+ [dependencies]
19
+ # `multiple-pymethods`: the value-spec pyclasses split their `#[pymethods]` into
20
+ # a macro-generated common block (shared `ValueSpecBase` surface) and a per-type
21
+ # hand-written block (`#[new]` / getters / `from_json` / `with_type_args`).
22
+ # Keeping them in two blocks isolates the macro-def vs call-site token hygiene
23
+ # that a single merged block trips over (a `**kwargs` resolution clash).
24
+ pyo3 = { version = "0.27", features = ["extension-module", "multiple-pymethods"] }
25
+
26
+ [profile.release]
27
+ opt-level = 3
28
+ lto = true
29
+ codegen-units = 1
@@ -0,0 +1,43 @@
1
+ Metadata-Version: 2.4
2
+ Name: pygx-core
3
+ Version: 0.1.0
4
+ Classifier: Development Status :: 4 - Beta
5
+ Classifier: Intended Audience :: Developers
6
+ Classifier: License :: OSI Approved :: Apache Software License
7
+ Classifier: Programming Language :: Rust
8
+ Classifier: Programming Language :: Python :: 3
9
+ Classifier: Programming Language :: Python :: Implementation :: CPython
10
+ Summary: Compiled native core for pygx: Rust-backed symbolic storage and construct/attribute fast paths for pg.Object.
11
+ Keywords: pygx,symbolic,rust,pyo3
12
+ Author-email: PyGX Authors <pygx-authors@google.com>
13
+ License: Apache-2.0
14
+ Requires-Python: >=3.11, <3.15
15
+ Description-Content-Type: text/markdown; charset=UTF-8; variant=GFM
16
+ Project-URL: Homepage, https://github.com/free-solo/pygx
17
+ Project-URL: Repository, https://github.com/free-solo/pygx
18
+
19
+ # pygx-core
20
+
21
+ The compiled **native core** for [PyGX](https://github.com/free-solo/pygx): a
22
+ Rust ([PyO3](https://pyo3.rs)) extension that backs `pg.Object` and the symbolic
23
+ containers with native storage and construct/attribute fast paths, reaching
24
+ dataclass/pydantic-level performance while preserving the full symbolic feature
25
+ set.
26
+
27
+ This package exposes the `pygx_core` module (the `pygx_core._native` extension).
28
+ It never imports `pygx`; `pygx` selects it via the `PYGX_CORE` environment
29
+ variable and integrates through a marker/callback contract.
30
+
31
+ Install `pygx` to use it — `pygx-core` is its compiled accelerator, not a
32
+ standalone library.
33
+
34
+ ## Compatibility
35
+
36
+ Per-version wheels are published for CPython 3.11–3.14 on Linux, macOS, and
37
+ Windows. The extension is **not** abi3 (limited-API) compatible: it installs raw
38
+ `PyTypeObject` slots that depend on the concrete CPython type layout.
39
+
40
+ ## License
41
+
42
+ Apache License 2.0.
43
+
@@ -0,0 +1,24 @@
1
+ # pygx-core
2
+
3
+ The compiled **native core** for [PyGX](https://github.com/free-solo/pygx): a
4
+ Rust ([PyO3](https://pyo3.rs)) extension that backs `pg.Object` and the symbolic
5
+ containers with native storage and construct/attribute fast paths, reaching
6
+ dataclass/pydantic-level performance while preserving the full symbolic feature
7
+ set.
8
+
9
+ This package exposes the `pygx_core` module (the `pygx_core._native` extension).
10
+ It never imports `pygx`; `pygx` selects it via the `PYGX_CORE` environment
11
+ variable and integrates through a marker/callback contract.
12
+
13
+ Install `pygx` to use it — `pygx-core` is its compiled accelerator, not a
14
+ standalone library.
15
+
16
+ ## Compatibility
17
+
18
+ Per-version wheels are published for CPython 3.11–3.14 on Linux, macOS, and
19
+ Windows. The extension is **not** abi3 (limited-API) compatible: it installs raw
20
+ `PyTypeObject` slots that depend on the concrete CPython type layout.
21
+
22
+ ## License
23
+
24
+ Apache License 2.0.
@@ -0,0 +1,131 @@
1
+ # Copyright 2026 Daiyi Peng.
2
+ #
3
+ # Licensed under the Apache License, Version 2.0 (the "License");
4
+ # you may not use this file except in compliance with the License.
5
+ # You may obtain a copy of the License at
6
+ #
7
+ # http://www.apache.org/licenses/LICENSE-2.0
8
+ #
9
+ # Unless required by applicable law or agreed to in writing, software
10
+ # distributed under the License is distributed on an "AS IS" BASIS,
11
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
+ # See the License for the specific language governing permissions and
13
+ # limitations under the License.
14
+ """pygx_core — the native (Rust) symbolic core for pygx.
15
+
16
+ Built milestone by milestone so ``pg.Object`` and the symbolic containers reach
17
+ dataclass/pydantic performance. The core never imports ``pygx`` (the import-cycle
18
+ constraint); it integrates with the oracle only through markers and injected
19
+ callbacks (see ``docs/design/rust-core/native-core-rewrite.md`` and
20
+ ``minimal-core-contract.md``).
21
+
22
+ Today the public surface is just the ABI handshake; native types land per
23
+ milestone. The compiled engine is ``pygx_core._native``.
24
+ """
25
+
26
+ # `_native` is the compiled extension pylint cannot introspect.
27
+ # pylint: disable=no-name-in-module,import-error
28
+ from pygx_core._native import abi_version
29
+ from pygx_core._native import format
30
+ from pygx_core._native import kvlist_str
31
+ from pygx_core._native import Any
32
+ from pygx_core._native import Bool
33
+ from pygx_core._native import Callable
34
+ from pygx_core._native import ConstStrKey
35
+ from pygx_core._native import Dict
36
+ from pygx_core._native import Enum
37
+ from pygx_core._native import Functor
38
+ from pygx_core._native import Field
39
+ from pygx_core._native import Float
40
+ from pygx_core._native import Int
41
+ from pygx_core._native import KeyPath
42
+ from pygx_core._native import KeyPathSet
43
+ from pygx_core._native import List
44
+ from pygx_core._native import ListKey
45
+ from pygx_core._native import Str
46
+ from pygx_core._native import StrKey
47
+ from pygx_core._native import Object
48
+ from pygx_core._native import Schema
49
+ from pygx_core._native import SymDict
50
+ from pygx_core._native import SymFieldGetter
51
+ from pygx_core._native import SymObject
52
+ from pygx_core._native import Tuple
53
+ from pygx_core._native import TupleKey
54
+ from pygx_core._native import Type
55
+ from pygx_core._native import Union
56
+
57
+ # Underscore-prefixed: the oracle seam injects its markdown-isolation callbacks
58
+ # (`_install_formatting_bridge`) and the value-spec pipeline's oracle handles
59
+ # (`_install_typing_bridge`) through these; not part of the public surface.
60
+ from pygx_core._native import (
61
+ _install_formatting_bridge as _install_formatting_bridge,
62
+ )
63
+ from pygx_core._native import (
64
+ _install_typing_bridge as _install_typing_bridge,
65
+ )
66
+ from pygx_core._native import (
67
+ _install_json_schema_fn as _install_json_schema_fn,
68
+ )
69
+ from pygx_core._native import (
70
+ _install_field_from_annotation as _install_field_from_annotation,
71
+ )
72
+ from pygx_core._native import (
73
+ _install_container_bridge as _install_container_bridge,
74
+ )
75
+ from pygx_core._native import (
76
+ _install_object_bridge as _install_object_bridge,
77
+ )
78
+ from pygx_core._native import (
79
+ _install_native_tp_init as _install_native_tp_init,
80
+ )
81
+ from pygx_core._native import (
82
+ _install_native_tp_getattro as _install_native_tp_getattro,
83
+ )
84
+ from pygx_core._native import (
85
+ _install_native_tp_getattro_fast as _install_native_tp_getattro_fast,
86
+ )
87
+
88
+ # flags-native — the five hot `flags.*` thread-local scope ops + their id
89
+ # constants, driven by the `pygx/symbolic/_flags.py` seam under the rust core.
90
+ from pygx_core._native import _flag_scope_get as _flag_scope_get
91
+ from pygx_core._native import _flag_scope_set as _flag_scope_set
92
+ from pygx_core._native import _flag_scope_has as _flag_scope_has
93
+ from pygx_core._native import _flag_scope_del as _flag_scope_del
94
+ from pygx_core._native import _FLAG_SEALED as _FLAG_SEALED
95
+ from pygx_core._native import _FLAG_ACCESSOR_WRITABLE as _FLAG_ACCESSOR_WRITABLE
96
+ from pygx_core._native import _FLAG_ALLOW_PARTIAL as _FLAG_ALLOW_PARTIAL
97
+ from pygx_core._native import _FLAG_ORIGIN_TRACKING as _FLAG_ORIGIN_TRACKING
98
+ from pygx_core._native import (
99
+ _FLAG_CHANGE_NOTIFICATION as _FLAG_CHANGE_NOTIFICATION,
100
+ )
101
+
102
+ __all__ = [
103
+ 'abi_version',
104
+ 'format',
105
+ 'kvlist_str',
106
+ 'Any',
107
+ 'Bool',
108
+ 'Callable',
109
+ 'ConstStrKey',
110
+ 'Dict',
111
+ 'Enum',
112
+ 'Field',
113
+ 'Functor',
114
+ 'Float',
115
+ 'Int',
116
+ 'KeyPath',
117
+ 'KeyPathSet',
118
+ 'List',
119
+ 'ListKey',
120
+ 'Str',
121
+ 'StrKey',
122
+ 'Object',
123
+ 'Schema',
124
+ 'SymDict',
125
+ 'SymFieldGetter',
126
+ 'SymObject',
127
+ 'Tuple',
128
+ 'TupleKey',
129
+ 'Type',
130
+ 'Union',
131
+ ]
@@ -0,0 +1,33 @@
1
+ [build-system]
2
+ requires = ["maturin>=1.13,<2.0"]
3
+ build-backend = "maturin"
4
+
5
+ [project]
6
+ name = "pygx-core"
7
+ version = "0.1.0"
8
+ description = "Compiled native core for pygx: Rust-backed symbolic storage and construct/attribute fast paths for pg.Object."
9
+ readme = "README.md"
10
+ requires-python = ">=3.11,<3.15"
11
+ license = { text = "Apache-2.0" }
12
+ authors = [{ name = "PyGX Authors", email = "pygx-authors@google.com" }]
13
+ keywords = ["pygx", "symbolic", "rust", "pyo3"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Intended Audience :: Developers",
17
+ "License :: OSI Approved :: Apache Software License",
18
+ "Programming Language :: Rust",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: Implementation :: CPython",
21
+ ]
22
+
23
+ [project.urls]
24
+ Homepage = "https://github.com/free-solo/pygx"
25
+ Repository = "https://github.com/free-solo/pygx"
26
+
27
+ [tool.maturin]
28
+ # The Rust cdylib is the `pygx_core._native` extension; the thin `pygx_core`
29
+ # Python package (./pygx_core) is the public surface. The core never imports
30
+ # pygx — it integrates with the oracle only via markers + injected callbacks
31
+ # (see docs/design/rust-core/minimal-core-contract.md).
32
+ module-name = "pygx_core._native"
33
+ python-source = "."
@@ -0,0 +1,37 @@
1
+ #!/usr/bin/env bash
2
+ # Rebuild pygx_core and install it NON-EDITABLE into the core-dev venv.
3
+ #
4
+ # WHY a venv + non-editable wheel (not the editable .pth + `maturin develop`):
5
+ # a multi-file PyO3 crate OOM-crashes (SIGKILL) on import under the editable
6
+ # `.pth` layout. A clean venv with the wheel in site-packages is stable.
7
+ #
8
+ # Dev loop:
9
+ # pygx-core/rebuild.sh # build wheel + reinstall
10
+ # .venv-coredev/bin/python -m pytest ... # run tests under the venv
11
+ #
12
+ # One-time venv setup (if .venv-coredev is missing):
13
+ # /opt/homebrew/bin/python3.13 -m venv .venv-coredev
14
+ # .venv-coredev/bin/pip install -U pip maturin pytest pytest-xdist pytest-cov
15
+ # .venv-coredev/bin/pip install -e . # pygx (oracle) + deps
16
+ set -euo pipefail
17
+
18
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
19
+ VENV="${PYGX_COREDEV_VENV:-$REPO_ROOT/.venv-coredev}"
20
+ CRATE_DIR="$REPO_ROOT/pygx-core"
21
+ PY="$VENV/bin/python"
22
+
23
+ if [[ ! -x "$PY" ]]; then
24
+ echo "core-dev venv not found at $VENV — see the one-time setup in this script." >&2
25
+ exit 1
26
+ fi
27
+
28
+ cd "$CRATE_DIR"
29
+ rm -rf target/wheels
30
+ # `env -u CONDA_PREFIX`: maturin warns / misbehaves when a conda env leaks in.
31
+ env -u CONDA_PREFIX "$VENV/bin/maturin" build --release -i "$PY" >&2
32
+ WHL="$(ls -t target/wheels/*.whl | head -1)"
33
+ # --no-deps: the wheel declares no real index deps (the oracle pygx is the
34
+ # sibling editable package, already installed). --force-reinstall: always pick
35
+ # up the freshly-built extension.
36
+ "$VENV/bin/pip" install -q --force-reinstall --no-deps "$WHL"
37
+ echo "installed $WHL into $VENV" >&2
@@ -0,0 +1,50 @@
1
+ #!/usr/bin/env bash
2
+ # Differential harness — run the FULL oracle test suite under BOTH cores.
3
+ #
4
+ # This is the safety net for the native-core rewrite: the pure-Python oracle is
5
+ # the frozen reference, and every milestone must keep the native core
6
+ # behaviour-identical. The suite asserts oracle behaviour, so "green under both
7
+ # PYGX_CORE values" == "no divergence". A failure under `rust` that passes under
8
+ # `python` is a native-core regression. See
9
+ # docs/design/rust-core/native-core-rewrite.md §6 (M0 builds this first).
10
+ #
11
+ # Runs in the core-dev venv (the only place the crate is built; the oracle CI
12
+ # never builds it — see pygx-core/rebuild.sh). Rebuilds the crate first unless
13
+ # PYGX_DIFF_SKIP_BUILD is set.
14
+ #
15
+ # Usage:
16
+ # pygx-core/run-differential.sh # rebuild + both cores, full suite
17
+ # pygx-core/run-differential.sh pygx/symbolic # both cores, a path subset
18
+ # PYGX_DIFF_SKIP_BUILD=1 pygx-core/run-differential.sh # skip the rebuild
19
+ set -euo pipefail
20
+
21
+ REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
22
+ VENV="${PYGX_COREDEV_VENV:-$REPO_ROOT/.venv-coredev}"
23
+ PY="$VENV/bin/python"
24
+
25
+ if [[ ! -x "$PY" ]]; then
26
+ echo "core-dev venv not found at $VENV — see the one-time setup in pygx-core/rebuild.sh." >&2
27
+ exit 1
28
+ fi
29
+
30
+ if [[ -z "${PYGX_DIFF_SKIP_BUILD:-}" ]]; then
31
+ echo "=== rebuilding native core ===" >&2
32
+ bash "$REPO_ROOT/pygx-core/rebuild.sh"
33
+ fi
34
+
35
+ cd "$REPO_ROOT"
36
+ status=0
37
+ for core in python rust; do
38
+ echo "=== PYGX_CORE=$core ===" >&2
39
+ if ! PYGX_CORE="$core" "$PY" -m pytest -n auto -q "$@"; then
40
+ echo "!!! suite FAILED under PYGX_CORE=$core" >&2
41
+ status=1
42
+ fi
43
+ done
44
+
45
+ if [[ "$status" -eq 0 ]]; then
46
+ echo "=== differential OK: suite green under both cores ===" >&2
47
+ else
48
+ echo "=== differential FAILED: cores diverge (see above) ===" >&2
49
+ fi
50
+ exit "$status"