Skip to content

Commit 91d9e60

Browse files
vyasrpre-commit-ci[bot]henryiii
authored
fix: support editable installs of Cython pxd files (#516)
Editable installs of packages containing Cython currently do not properly support downstream Cython packages finding the pxd files from the editable install. The issue is that editable installs are managed using a meta path finder, and [Cython does not appear to support that for pxd files](cython/cython#5855). However, Cython does support pth files adding include paths directly, so this PR solves the pxd search issue by adding the necessary paths directly to the pth file that currently adds the meta path finder. Resolves #442 --------- Signed-off-by: Henry Schreiner <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Henry Schreiner <[email protected]>
1 parent fb51937 commit 91d9e60

File tree

12 files changed

+135
-5
lines changed

12 files changed

+135
-5
lines changed

src/scikit_build_core/build/wheel.py

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,7 @@
2929
from .generate import generate_file_contents
3030

3131
if TYPE_CHECKING:
32-
from collections.abc import Sequence
32+
from collections.abc import Iterable, Sequence
3333

3434
from ..settings.skbuild_model import ScikitBuildSettings
3535

@@ -50,6 +50,7 @@ def _make_editable(
5050
reload_dir: Path | None,
5151
settings: ScikitBuildSettings,
5252
wheel: WheelWriter,
53+
packages: Iterable[str],
5354
) -> None:
5455
modules = mapping_to_modules(mapping, libdir)
5556
installed = libdir_to_installed(libdir)
@@ -68,9 +69,14 @@ def _make_editable(
6869
f"_{name}_editable.py",
6970
editable_txt.encode(),
7071
)
72+
# Support Cython by adding the source directory directly to the path.
73+
# This is necessary because Cython does not support sys.meta_path for
74+
# cimports (as of 3.0.5).
75+
import_strings = [f"import _{name}_editable", *packages, ""]
76+
pth_import_paths = "\n".join(import_strings)
7177
wheel.writestr(
7278
f"_{name}_editable.pth",
73-
f"import _{name}_editable\n".encode(),
79+
pth_import_paths.encode(),
7480
)
7581

7682

@@ -341,6 +347,7 @@ def _build_wheel_impl(
341347
) as wheel:
342348
wheel.build(wheel_dirs)
343349

350+
str_pkgs = (str(Path.cwd().joinpath(p).parent.resolve()) for p in packages)
344351
if editable and settings.editable.mode == "redirect":
345352
reload_dir = build_dir.resolve() if settings.build_dir else None
346353

@@ -353,15 +360,13 @@ def _build_wheel_impl(
353360
settings=settings,
354361
wheel=wheel,
355362
name=normalized_name,
363+
packages=str_pkgs,
356364
)
357365
elif editable and settings.editable.mode == "inplace":
358366
if not packages:
359367
msg = "Editable inplace mode requires at least one package"
360368
raise AssertionError(msg)
361369

362-
str_pkgs = (
363-
str(Path.cwd().joinpath(p).parent.resolve()) for p in packages
364-
)
365370
wheel.writestr(
366371
f"_{normalized_name}_editable.pth",
367372
"\n".join(str_pkgs).encode(),

tests/conftest.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@ def pep518_wheelhouse(tmp_path_factory: pytest.TempPathFactory) -> Path:
5050
)
5151
packages = [
5252
"build",
53+
"cython",
5354
"hatchling",
5455
"pip>=23",
5556
"pybind11",
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
project(${SKBUILD_PROJECT_NAME} LANGUAGES C)
3+
4+
find_package(
5+
Python
6+
COMPONENTS Interpreter Development.Module
7+
REQUIRED)
8+
9+
find_program(CYTHON "cython")
10+
11+
add_custom_command(
12+
OUTPUT src/pkg1/one.c
13+
DEPENDS src/pkg1/one.pyx
14+
VERBATIM
15+
COMMAND "${CYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/src/pkg1/one.pyx"
16+
--output-file "${CMAKE_CURRENT_BINARY_DIR}/src/pkg1/one.c")
17+
18+
python_add_library(one MODULE "${CMAKE_CURRENT_BINARY_DIR}/src/pkg1/one.c"
19+
WITH_SOABI)
20+
21+
install(TARGETS one DESTINATION pkg1/)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[build-system]
2+
build-backend = "scikit_build_core.build"
3+
requires = [
4+
"cython>=3.0.0",
5+
"scikit-build-core",
6+
]
7+
8+
[project]
9+
name = "pkg1"
10+
version = "1.0.0"
11+
12+
[tool.scikit-build]
13+
wheel.packages = ["src/pkg1"]

tests/packages/cython_pxd_editable/pkg1/src/pkg1/__init__.py

Whitespace-only changes.
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
cdef int one()
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
cdef int one():
2+
return 1
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
cmake_minimum_required(VERSION 3.15)
2+
project(${SKBUILD_PROJECT_NAME} LANGUAGES C)
3+
4+
find_package(
5+
Python
6+
COMPONENTS Interpreter Development.Module
7+
REQUIRED)
8+
9+
find_program(CYTHON "cython")
10+
11+
add_custom_command(
12+
OUTPUT src/pkg2/two.c
13+
DEPENDS src/pkg2/two.pyx
14+
VERBATIM
15+
COMMAND "${CYTHON}" "${CMAKE_CURRENT_SOURCE_DIR}/src/pkg2/two.pyx"
16+
--output-file "${CMAKE_CURRENT_BINARY_DIR}/src/pkg2/two.c")
17+
18+
python_add_library(two MODULE "${CMAKE_CURRENT_BINARY_DIR}/src/pkg2/two.c"
19+
WITH_SOABI)
20+
21+
install(TARGETS two DESTINATION pkg2/)
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
[build-system]
2+
build-backend = "scikit_build_core.build"
3+
requires = [
4+
"cython>=3.0.0",
5+
"scikit-build-core",
6+
]
7+
8+
[project]
9+
name = "pkg2"
10+
version = "1.0.0"
11+
12+
[tool.scikit-build]
13+
wheel.packages = ["src/pkg2"]

tests/packages/cython_pxd_editable/pkg2/src/pkg2/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)