Skip to content

fix(editable): recognize Cython __init__.pxd/.pyx as package indicators#1292

Open
vyasr wants to merge 5 commits intoscikit-build:mainfrom
vyasr:fix/cython_package_dirs
Open

fix(editable): recognize Cython __init__.pxd/.pyx as package indicators#1292
vyasr wants to merge 5 commits intoscikit-build:mainfrom
vyasr:fix/cython_package_dirs

Conversation

@vyasr
Copy link
Copy Markdown
Contributor

@vyasr vyasr commented May 1, 2026

Fixes #1291.

Three targeted fixes for editable installs of Cython projects where packages have __init__.pxd or __init__.pyx files alongside (or instead of) __init__.py:

_editable_redirect.py — package detection (line 113):
"__init__.py" in fileos.path.basename(file).partition(".")[0] == "__init__" — matches any __init__.* extension, consistent with path_to_module() which already handles this correctly.

_editable_redirect.pyfind_spec (lines 154/163):
redir.endswith(("__init__.py", "__init__.pyc"))fullname in self.pkgs — uses the already-computed package list rather than re-checking file extensions.

_editable.pymapping_to_modules:
Dict comprehension → explicit loop that prefers .py/.pyc when multiple source files (e.g. __init__.py + __init__.pxd) map to the same module key.

vyasr and others added 4 commits May 1, 2026 16:43
- In ScikitBuildRedirectingFinder.__init__: use os.path.basename(file).partition('.')[0]
  == '__init__' instead of '__init__.py' in file, so any __init__.* extension
  (including .pxd and .pyx) is recognized as a package indicator.
- In find_spec: use 'fullname in self.pkgs' (already computed) instead of
  redir.endswith(('__init__.py', '__init__.pyc')) for deciding whether to pass
  submodule_search_locations, making it extension-agnostic.
- In mapping_to_modules: replace dict comprehension with explicit loop that
  prefers .py/.pyc entries over other extensions (.pxd, .pyx) when multiple
  source files map to the same module key.
@vyasr vyasr force-pushed the fix/cython_package_dirs branch from 0ae31b2 to 3f3f8d4 Compare May 1, 2026 23:43
@henryiii henryiii requested a review from Copilot May 2, 2026 00:06
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Fixes editable-install package recognition for Cython projects where packages may have __init__.pxd/__init__.pyx, preventing incorrect __path__ construction and import resolution issues (per #1291).

Changes:

  • Treat any __init__.* file as a package indicator when building package metadata for the redirecting finder.
  • Use the precomputed package list (pkgs) to decide when to attach submodule_search_locations in find_spec.
  • Make mapping_to_modules() deterministic for collisions by preferring .py/.pyc over other extensions like .pxd/.pyx.

Reviewed changes

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

File Description
src/scikit_build_core/resources/_editable_redirect.py Improves package detection and spec creation for packages whose init file isn’t .py/.pyc.
src/scikit_build_core/build/_editable.py Makes module mapping stable by preferring importable Python sources when multiple files map to the same module name.
tests/test_editable_redirect.py Adds regression tests for .pxd/.pyx init handling and mapping collision preference.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread src/scikit_build_core/resources/_editable_redirect.py
Comment on lines +67 to +69
# Prefer .py/.pyc over other extensions (e.g. .pxd, .pyx) for the same module
if module not in result or rel.suffix in (".py", ".pyc"):
result[module] = str(Path(k).resolve())
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

The logic here is a bit hard to parse, although the whole logic in these is hard to parse and could use a refactor. Iiuc mapping_to_modules is used on the src files, and libdir_to_installed is used for the CMake installed files. Why not drop all files that do not end with .py? It will interfere with importlib.resources.files, but I do not think the status-quo is helping us there either.

My proposal is to split (and rename) the inputs to _make_editable into 3 variables:

  • source_modules: mapping of python modules to source .py files. All other file types are ignored and presumed that they are compiled. Not sure how to handle .pyc though
  • installed_modules: mapping of python modules to compiled python modules or installed .py files
  • file_tree: a complete file tree of python navigable sources via importlib.resources.files. It could be a mapping of modules and list of file paths

@henryiii @vyasr what do you think? The second variable at the very least would unblock me for #1170

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Iiuc mapping_to_modules is used on the src files, and libdir_to_installed is used for the CMake installed files.

Yes this matches my recollection as well.

The split sounds reasonable. I assume file_tree will have to be modified substantially as we rework importlib.resources.files over time.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not sure how to handle .pyc though

How many realistic use cases are there for shipping pyc files in wheels? They shouldn't be there most of the time, but I'm sure there are edge cases I'm not thinking of.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

How many realistic use cases are there for shipping pyc files in wheels?

For wheels yes it does not make sense, but this part is about usage of editable install paths which is a bit more questionable. I don't know whose responsibility these are or if there is some magic to be careful about in the importlib

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Should we merge this as a fix, then work on a refactor? I could probably just feed that comment into Kimi or GPT and have it do the refactor, actually.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

👍 for me. LGTM in the current state as an intermediary.

Not sure how to handle .pyc though

will be tricky but we can move that discussion

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Editable installs: packages with __init__.pxd/__init__.pyx not recognized as packages, causing __path__ pollution

4 participants