Skip to content

[BUG] Fix validation registry discovery when loaded via zipimport - #662

Open
Adam Lastowka (Rachmanin0xFF) wants to merge 4 commits into
mainfrom
Rachmanin0xFF/661-pyspark-registry-zipimport
Open

[BUG] Fix validation registry discovery when loaded via zipimport#662
Adam Lastowka (Rachmanin0xFF) wants to merge 4 commits into
mainfrom
Rachmanin0xFF/661-pyspark-registry-zipimport

Conversation

@Rachmanin0xFF

@Rachmanin0xFF Adam Lastowka (Rachmanin0xFF) commented Aug 14, 2026

Copy link
Copy Markdown
Contributor

Fixes #661

Note

This is one of two alternative fixes for #661. The other, #663, replaces filesystem discovery with a codegen-emitted index module the registry imports. Merging either one resolves the issue.

For reference, this PR has the fix that was temporarily published to CA to unblock release here.

What

overture.schema.pyspark._registry.REGISTRY comes back empty whenever overture-schema-pyspark is loaded straight from a wheel on sys.path instead of being installed to a real directory (this is what AWS Glue does when using the --extra-py-files option like we do in data-platform). Every feature type then silently reports as unregistered and the task erroneously succeeds 🫠

Why

_registry.py discovered generated modules by walking the expressions/generated/ PEP 420 namespace package with pathlib.Path(root_path).rglob("*.py"), which works... only when a real filesystem directory is present! A namespace portion backed by a zip archive has a __path__ entry that points inside the zip, and pathlib can't traverse into one.

importlib.resources.files() looked like the natural fix (its Traversable API is meant to be zipimport-aware), but its MultiplexedPath implementation raises NotADirectoryError on Python 3.10 the moment any namespace portion isn't a real directory.

Fix

Each namespace portion is now walked directly using zipfile.ZipFile.namelist() for portions that resolve to a path inside a zip file.

Verification

  • Built a wheel and added it to sys.path without extracting it (no pip install, matching Glue's --extra-py-files): all 15 generated modules now resolve; previously len(REGISTRY) == 0.
  • Documented empty-registry behavior when expressions/generated/ is absent entirely (make clean-pyspark): unchanged, still empty and non-crashing.

REGISTRY was built by walking expressions/generated/ with
pathlib.Path.rglob, which only sees real filesystem directories. When
overture-schema-pyspark is loaded straight from a wheel on sys.path
(zipimport) instead of being extracted -- as AWS Glue does via
--extra-py-files -- the namespace package's __path__ portions point
inside the zip archive, and pathlib can't traverse into one. The walk
silently found nothing, so validate_model()/get_feature_validation()
reported every feature type as unregistered.

importlib.resources.files() looks like the fix, since its Traversable
API is meant to be zipimport-aware, but its MultiplexedPath
implementation (through at least Python 3.10) raises
NotADirectoryError the moment any namespace portion isn't a real
directory -- confirmed against a zip-imported wheel before ruling it
out.

Walk each namespace portion directly instead: pathlib for real
directories (unchanged), zipfile.ZipFile.namelist() for portions that
resolve to a path inside a zip file. Verified against a real wheel
added to sys.path without extraction (all 15 generated modules now
resolve), the existing overture-schema-pyspark test suite (3132
passed), and the documented empty-registry behavior when
expressions/generated/ is absent entirely (via make clean-pyspark).

Fixes #661

Signed-off-by: Adam Lastowka <adamlastowka@gmail.com>
Copilot AI lite review requested due to automatic review settings August 14, 2026 01:49
@Rachmanin0xFF Adam Lastowka (Rachmanin0xFF) added the change type - minor 🤏 Minor schema change. See https://lf-overturemaps.atlassian.net/wiki/x/GgDa label Aug 14, 2026
@github-actions

github-actions Bot commented Aug 14, 2026

Copy link
Copy Markdown

🗺️ Schema reference docs preview is live!

🌍 Preview https://staging.overturemaps.org/schema/pr/662/schema/index.html
🕐 Updated Aug 14, 2026 07:22 UTC
📝 Commit c9c2f84
🔧 env SCHEMA_PREVIEW true

Note

♻️ This preview updates automatically with each push to this PR.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Fixes a bug where overture.schema.pyspark._registry.REGISTRY stays empty when overture-schema-pyspark is imported from a wheel on sys.path (zipimport, e.g. AWS Glue --extra-py-files) by making generated-module discovery work for both filesystem and zip-backed namespace portions.

Changes:

  • Add zip-aware namespace portion discovery by detecting the “zip boundary” and listing .py members via zipfile.ZipFile.namelist().
  • Preserve existing behavior for real on-disk directories using pathlib.Path(...).rglob("*.py").
  • Add a changelog entry documenting the fix.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
packages/overture-schema-pyspark/src/overture/schema/pyspark/_registry.py Implements zipimport-aware generated-module discovery for namespace package portions inside wheels.
packages/overture-schema-pyspark/changelog.d/661.bugfix.md Documents the bugfix for empty registry under zipimport (AWS Glue-style loading).

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

The on-disk walk had incidental coverage but the zip branch
(_zip_boundary + ZipFile.namelist) had none: the existing test skips
under zipimport, so a regression in the wheel-on-sys.path path would go
unnoticed. Exercise it directly against a synthetic wheel, asserting
namespace __init__.py markers and members outside the generated prefix
are excluded, plus a non-zip path yields nothing.

Signed-off-by: Adam Lastowka <adamlastowka@gmail.com>
The directory branch binds `relative` to a `Path`; the zip branch reused
the same name for a `PurePosixPath`, which mypy rejects as an
incompatible reassignment. Give the zip member its own variable.

Signed-off-by: Adam Lastowka <adamlastowka@gmail.com>
Drop the em-dash asides and contrastive phrasing from the docstrings
added for the zip-walk fix, matching the comment conventions used
elsewhere in this contribution. No behaviour change.

Signed-off-by: Adam Lastowka <adamlastowka@gmail.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

change type - minor 🤏 Minor schema change. See https://lf-overturemaps.atlassian.net/wiki/x/GgDa

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Validation registry empty when overture-schema-pyspark loaded via zipimport

2 participants