refactor: consume the substrait-protobuf package for core Python protobuf bindings - #532
Conversation
05c533e to
14fb2bd
Compare
…ndings Migrate the Python package to the canonical pre-generated `substrait-protobuf` PyPI package for the core `substrait` and `substrait.extensions` protobuf bindings, instead of generating its own copy. The validator now imports `Plan` from the top-level `substrait` namespace provided by that package. py/build.rs now generates Python bindings only for the validator-specific `substrait.validator` package (which substrait-protobuf does not provide). It no longer needs the Substrait submodule's protos, and it creates an __init__.py for every intermediate package directory (previously the now-absent core bindings implicitly created `substrait/__init__.py`). Verified by the full Python test suite against substrait-protobuf 0.87.0 (sv.Plan is substrait.plan_pb2.Plan).
14fb2bd to
558c212
Compare
vbarua
left a comment
There was a problem hiding this comment.
One minor comments but makes sense overall.
| // `substrait.validator` package here. The bindings for the core `substrait` | ||
| // and `substrait.extensions` packages come from the `substrait-protobuf` | ||
| // PyPI package (a runtime dependency), so we no longer need the Substrait | ||
| // submodule's protos -- nor bindings generated from them -- in this build. |
There was a problem hiding this comment.
so we no longer need the Substrait submodule's protos -- nor bindings generated from them -- in this build
minor: this portion of the comment isn't that helpful IMO. It explains the change your making, but doesn't need to live in the code as it will be stale almost immediately after you merge it.
There was a problem hiding this comment.
Good catch — dropped that clause. The comment now stops at what remains true after the merge:
// Note that we only generate Python bindings for the validator-specific
// `substrait.validator` package here. The bindings for the core `substrait`
// and `substrait.extensions` packages come from the `substrait-protobuf`
// PyPI package (a runtime dependency).Applied the same principle to two other spots in this diff that would have gone stale the same way — a still contains stale copies of the core protos that is really just contains copies of the core protos, and a the generated files now live only in ... where the now was doing the dating. Substance kept in both, tense markers gone.
Also merged main (which now includes #531) into the branch and re-verified the combination: clippy/fmt clean, 21 library tests, all 158 conformance cases, black/flake8 clean, and the Python suite at 15 passed with substrait-protobuf 0.87.0 / protobuf 6.33.6. Rebuilding from a clean tree gives exactly the intended layout, which is the thing that comment describes:
py/substrait_validator/__init__.py
py/substrait_validator/substrait/__init__.py <- intermediate, created by build.rs
py/substrait_validator/substrait/validator/tree_pb2.py
py/substrait_validator/substrait/validator/simple_extensions_pb2.py
py/substrait_validator/substrait/validator/type_system_pb2.py
no core plan_pb2.py/algebra_pb2.py, and sv.Plan is substrait.plan_pb2.Plan is True.
Per review feedback: comments that describe the migration itself go stale as soon as this merges. Keep what explains the resulting state (only the validator-specific package is generated here; the core bindings come from substrait-protobuf) and drop the rest.
py/build.rs writes the generated `substrait.validator` bindings into
py/substrait_validator/substrait/, which py/.gitignore excludes as build
output. maturin honors .gitignore when collecting python-source files, so
every wheel built from a git checkout omitted those modules and plain
`import substrait_validator` raised
ModuleNotFoundError: No module named 'substrait_validator.substrait'
Only sdists escaped, because maturin applies .gitignore solely inside a git
checkout and an unpacked sdist is not one. maturin 0.14.17, which built all
currently-published artifacts, did not do this at all; CI resolves
`maturin>=1.0,<2` to 1.14.1, so the breakage is latent rather than shipped.
Declare the bindings via an explicit `include`. The paths are deliberately
narrow: a wider glob over substrait/ would also pick up core bindings left
in an existing build tree and shadow the ones substrait-protobuf provides.
CI could not catch this. The wheel matrix installs the package editable for
its test dependencies, so the following `pip install --find-links=dist
substrait-validator` matched an already-satisfied requirement by name and
did nothing, leaving pytest to exercise the source tree rather than the
artifact. Force the reinstall so the wheel is what gets tested.
|
Added one more commit here (23d3869) for a packaging bug I hit while verifying this PR. It is pre-existing on SymptomInstalling a locally built wheel and importing gives: The wheel contains only Root cause
Why CI could not see itThe wheel rows install the package editable first (for test dependencies), so the following step matches an already-satisfied requirement by name and does nothing. Fix
VerificationMirroring CI's exact sequence — editable install, then wheel install, then pytest — the wheel is now what gets tested and Happy to split this into its own PR against |
What
Migrate the Python package to the canonical pre-generated
substrait-protobufPyPI package for the coresubstrait/substrait.extensionsprotobuf bindings, instead of generating its own copy. This is the Python counterpart to #531 (which moves the Rust crate ontosubstrait-prost), but is independent of it — this PR is based onmainand can merge in either order.Changes
py/substrait_validator/__init__.py— importPlanfrom the top-levelsubstraitnamespace (provided bysubstrait-protobuf) instead of the locally-generated.substrait.plan_pb2.py/build.rs— generate Python bindings only for the validator-specificsubstrait.validatorpackage (substrait-protobuf does not provide it); no longer reads the Substrait submodule's protos. Also creates an__init__.pyfor every intermediate package directory, since the now-absent core bindings used to be what implicitly createdsubstrait/__init__.py.py/pyproject.toml— addsubstrait-protobuf == 0.87.0(pinned to the targeted Substrait version, mirroring the Rust pin) and raise theprotobuffloor to>=5(what substrait-protobuf requires).Compatibility note
substrait-protobufrequiresprotobuf >=5and Python>=3.10(already this package'srequires-python), so this drops any lingering protobuf-4 support.Verification
15 passed) in a venv withsubstrait-protobuf 0.87.0/protobuf 6.33.6;sv.Plan is substrait.plan_pb2.PlanisTrue, and the locally-generated validator bindings coexist with substrait-protobuf with no descriptor-pool conflict.black/flake8clean.Follow-up
Once both this and #531 have merged, the core
.protofiles will no longer be needed anywhere in the repo (Rust → substrait-prost, Python → substrait-protobuf). A small follow-up will then drop the core-proto vendoring fromrs/build.rsentirely.🤖 Generated with AI