[BUG] Make pyspark an optional extra on overture-schema-pyspark - #681
Open
Seth Fitzsimmons (sethfitz) wants to merge 1 commit into
Open
[BUG] Make pyspark an optional extra on overture-schema-pyspark#681Seth Fitzsimmons (sethfitz) wants to merge 1 commit into
Seth Fitzsimmons (sethfitz) wants to merge 1 commit into
Conversation
pyspark was a hard dependency, so installing overture-schema-pyspark resolved pyspark on every runtime, including ones (Glue, EMR) that already bundle their own PySpark and don't want this package re-resolving it underneath them. Moved it to a `spark` optional-dependency extra. Standalone environments building their own install overture-schema-pyspark[spark]; runtime-provided-PySpark environments install the bare package. Probe for pyspark in the package's __init__ so a bare install without PySpark raises an actionable ModuleNotFoundError naming the extra rather than "No module named 'pyspark'". __init__ runs on any import of any submodule, generated ones included, so one probe covers every entry path. It catches nothing, so an unrelated missing dependency -- or a pyspark that is present but broken -- still surfaces its own real error from the imports that follow. Supersedes #660, which is where this change and its changelog wording originated. Refs #659 Co-authored-by: Adam Lastowka <adamlastowka@gmail.com> Signed-off-by: Seth Fitzsimmons <seth@mojodna.net>
🗺️ Schema reference docs preview is live!
Note ♻️ This preview updates automatically with each push to this PR. |
Adam Lastowka (Rachmanin0xFF)
approved these changes
Aug 19, 2026
Roel Bollens (RoelBollens-TomTom)
approved these changes
Aug 19, 2026
Roel Bollens (RoelBollens-TomTom)
left a comment
Collaborator
There was a problem hiding this comment.
Just one thing to flag moving PySpark to an extra means the >=3.4 floor is no longer enforced. I don't think checking the version in code is a great idea, since it could drift from pyproject.toml, unless you can think of a good way to do this.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Closes #659. Supersedes #660, which is where this change and its changelog wording originated; Adam Lastowka (@Rachmanin0xFF) is credited as co-author on the commit.
Problem
overture-schema-pysparkdeclaredpyspark>=3.4as a hard dependency, so installing the package resolvedpysparkon every runtime — including ones (Glue, EMR) that already bundle their own PySpark and shouldn't have this package re-resolving a different version underneath them.Change
pysparkmoves to an optional extra:pip install overture-schema-pysparknow resolves cleanly against a runtime-provided PySpark. Standalone environments building their own installoverture-schema-pyspark[spark].That makes "PySpark isn't here" an expected first-run state rather than a broken install, so the package says what to do about it.
overture/schema/pyspark/__init__.pyprobes for pyspark before its own imports:Two properties are worth stating, because they're what make one probe sufficient:
It covers every entry path.
overture/schema/pyspark/__init__.pyis a real__init__.py— onlyovertureandoverture.schemaare PEP 420 namespaces — so it executes on any import of any submodule, including the 15 generated expression modules that importpyspark.sqldirectly. Guarding at those import sites instead would mean 22 guards (7 hand-written modules plus the generated tree, which would need a renderer change), of which only one is ever reachable: the re-export chain always hitscheck.pyfirst.It catches nothing. A
try/except ModuleNotFoundErroraround the imports would also swallow an unrelated missing dependency, and — less obviously — would misreport an installed-but-broken pyspark. Withpy4jremoved,import pysparkraisesModuleNotFoundError(name='py4j'); anexceptclause reports "PySpark isn't installed", which is false, and avoiding that requires inspectinge.name. The probe has no such branch: it asks whether pyspark is findable, and everything else surfaces its own real error from the imports that follow.Tests
tests/test_optional_pyspark.pyadds three tests. One is the gate:test_missing_pyspark_names_the_extrafails against the unguarded__init__and passes with the probe. The other two are guards, and pass both before and after —test_unrelated_missing_dependency_surfaces_its_own_errorpins the no-masking property (verified to fail against a broad-exceptimplementation), andtest_package_imports_when_pyspark_is_installedpins the normal path.The two blocking mechanisms differ on purpose. The pyspark test sets
sys.modules["pyspark"] = None, which makesfind_specreturnNone— the same signal real absence produces at the seam this code reads. The unrelated-dependency test uses ameta_pathfinder that raisesModuleNotFoundError(..., name=...), becausesys.modules[x] = NoneraisesImportErrorinstead, and a control built on it would pass under the very implementation it exists to forbid.Verified
make check TESTMON=— 6201 passed.uv pip install ./packages/overture-schema-system ./packages/overture-schema-pyspark, no pyspark): importing the package raises the actionable message; the automated test pins the branch, this pins thatfind_specis the right question.shapelyalso removed, and the worktree venv withpy4jremoved: both surface their own errors, unmasked.uv sync --locked --all-packages --all-extrasaccepts the lockfile; CI'smake checkinstalls all extras, so coverage is unaffected.overture-schema-pysparkor importspyspark.