-
-
Notifications
You must be signed in to change notification settings - Fork 503
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Trac #34221: Backport PEP420 namespace package support from Cython 3
After #33011, downstream packages that use Cython and `cimport` Sage modules need to activate PEP 420 namespace package support in Cython using `with cython_namespace_package_support` (as is done in https://github.com/sagemath/sage/blob/develop/src/setup.py#L106 for sagelib). This feature is standard in the upcoming Cython 3 (#29863). Until downstream packages are updated, we can patch our Cython. Upstream backport PR: - cython/cython#4918 URL: https://trac.sagemath.org/34221 Reported by: mkoeppe Ticket author(s): Matthias Koeppe Reviewer(s): Marc Culler, John Palmieri
- Loading branch information
Showing
2 changed files
with
288 additions
and
1 deletion.
There are no files selected for viewing
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
0.29.32 | ||
0.29.32.p1 |
This file contains 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
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,287 @@ | ||
From 0dade9353e06b052d0da5e512cdc2ce04061904a Mon Sep 17 00:00:00 2001 | ||
From: Matthias Koeppe <mkoeppe@math.ucdavis.edu> | ||
Date: Sat, 23 Jul 2022 10:53:49 -0700 | ||
Subject: [PATCH 1/3] Add PEP420 namespace support | ||
|
||
Backport of https://github.com/cython/cython/pull/2946 to 0.29.x | ||
--- | ||
Cython/Compiler/Main.py | 44 +++++++++++++++---- | ||
Cython/Utils.py | 26 ++++++++--- | ||
runtests.py | 1 + | ||
.../build/cythonize_pep420_namespace.srctree | 44 +++++++++++++++++++ | ||
4 files changed, 99 insertions(+), 16 deletions(-) | ||
create mode 100644 tests/build/cythonize_pep420_namespace.srctree | ||
|
||
diff --git a/Cython/Compiler/Main.py b/Cython/Compiler/Main.py | ||
index dc4add541e..2be7a06a1c 100644 | ||
--- a/Cython/Compiler/Main.py | ||
+++ b/Cython/Compiler/Main.py | ||
@@ -801,32 +801,58 @@ def search_include_directories(dirs, qualified_name, suffix, pos, include=False) | ||
else: | ||
dirs = (Utils.find_root_package_dir(file_desc.filename),) + dirs | ||
|
||
+ # search for dotted filename e.g. <dir>/foo.bar.pxd | ||
dotted_filename = qualified_name | ||
if suffix: | ||
dotted_filename += suffix | ||
|
||
+ for dirname in dirs: | ||
+ path = os.path.join(dirname, dotted_filename) | ||
+ if os.path.exists(path): | ||
+ return path | ||
+ | ||
+ # search for filename in package structure e.g. <dir>/foo/bar.pxd or <dir>/foo/bar/__init__.pxd | ||
if not include: | ||
+ | ||
names = qualified_name.split('.') | ||
package_names = tuple(names[:-1]) | ||
module_name = names[-1] | ||
module_filename = module_name + suffix | ||
package_filename = "__init__" + suffix | ||
|
||
- for dirname in dirs: | ||
- path = os.path.join(dirname, dotted_filename) | ||
- if os.path.exists(path): | ||
- return path | ||
- | ||
- if not include: | ||
- package_dir = Utils.check_package_dir(dirname, package_names) | ||
+ # search for standard packages first - PEP420 | ||
+ namespace_dirs = [] | ||
+ for dirname in dirs: | ||
+ package_dir, is_namespace = Utils.check_package_dir(dirname, package_names) | ||
if package_dir is not None: | ||
+ | ||
+ if is_namespace: | ||
+ namespace_dirs.append(package_dir) | ||
+ continue | ||
+ | ||
+ # matches modules of the form: <dir>/foo/bar.pxd | ||
path = os.path.join(package_dir, module_filename) | ||
if os.path.exists(path): | ||
return path | ||
- path = os.path.join(package_dir, module_name, | ||
- package_filename) | ||
+ | ||
+ # matches modules of the form: <dir>/foo/bar/__init__.pxd | ||
+ path = os.path.join(package_dir, module_name, package_filename) | ||
if os.path.exists(path): | ||
return path | ||
+ | ||
+ # search for namespaces second - PEP420 | ||
+ for package_dir in namespace_dirs: | ||
+ | ||
+ # matches modules of the form: <dir>/foo/bar.pxd | ||
+ path = os.path.join(package_dir, module_filename) | ||
+ if os.path.exists(path): | ||
+ return path | ||
+ | ||
+ # matches modules of the form: <dir>/foo/bar/__init__.pxd | ||
+ path = os.path.join(package_dir, module_name, package_filename) | ||
+ if os.path.exists(path): | ||
+ return path | ||
+ | ||
return None | ||
|
||
|
||
diff --git a/Cython/Utils.py b/Cython/Utils.py | ||
index d59d67d78b..305ebf8412 100644 | ||
--- a/Cython/Utils.py | ||
+++ b/Cython/Utils.py | ||
@@ -134,16 +134,21 @@ def find_root_package_dir(file_path): | ||
else: | ||
return dir | ||
|
||
+ | ||
@cached_function | ||
-def check_package_dir(dir, package_names): | ||
+def check_package_dir(dir_path, package_names): | ||
+ namespace = True | ||
for dirname in package_names: | ||
- dir = os.path.join(dir, dirname) | ||
- if not is_package_dir(dir): | ||
- return None | ||
- return dir | ||
+ dir_path = os.path.join(dir_path, dirname) | ||
+ has_init = contains_init(dir_path) | ||
+ if not namespace and not has_init: | ||
+ return None, False | ||
+ elif has_init: | ||
+ namespace = False | ||
+ return dir_path, namespace | ||
|
||
-@cached_function | ||
-def is_package_dir(dir_path): | ||
+ | ||
+def contains_init(dir_path): | ||
for filename in ("__init__.py", | ||
"__init__.pyc", | ||
"__init__.pyx", | ||
@@ -152,6 +157,13 @@ def is_package_dir(dir_path): | ||
if path_exists(path): | ||
return 1 | ||
|
||
+ | ||
+@cached_function | ||
+def is_package_dir(dir_path): | ||
+ if contains_init(dir_path): | ||
+ return 1 | ||
+ | ||
+ | ||
@cached_function | ||
def path_exists(path): | ||
# try on the filesystem first | ||
diff --git a/runtests.py b/runtests.py | ||
index 91a0dd2570..7d04463846 100755 | ||
--- a/runtests.py | ||
+++ b/runtests.py | ||
@@ -415,6 +415,7 @@ def get_openmp_compiler_flags(language): | ||
'run.special_methods_T561_py2' | ||
]), | ||
(3,3) : (operator.lt, lambda x: x in ['build.package_compilation', | ||
+ 'build.cythonize_pep420_namespace', | ||
'run.yield_from_py33', | ||
'pyximport.pyximport_namespace', | ||
]), | ||
diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree | ||
new file mode 100644 | ||
index 0000000000..6a031e4170 | ||
--- /dev/null | ||
+++ b/tests/build/cythonize_pep420_namespace.srctree | ||
@@ -0,0 +1,44 @@ | ||
+PYTHON setup.py build_ext --inplace | ||
+PYTHON -c "import runner" | ||
+ | ||
+######## setup.py ######## | ||
+ | ||
+from Cython.Build.Dependencies import cythonize | ||
+ | ||
+from distutils.core import setup, Extension | ||
+ | ||
+setup( | ||
+ ext_modules=cythonize([ | ||
+ Extension("nsp.m1.a", ["nsp/m1/a.pyx"]), | ||
+ Extension("nsp.m2.b", ["nsp/m2/b.pyx"]) | ||
+ ]), | ||
+) | ||
+ | ||
+######## nsp/m1/__init__.py ######## | ||
+ | ||
+######## nsp/m1/a.pyx ######## | ||
+ | ||
+cdef class A: | ||
+ pass | ||
+ | ||
+######## nsp/m1/a.pxd ######## | ||
+ | ||
+cdef class A: | ||
+ pass | ||
+ | ||
+######## nsp/m2/__init__.py ######## | ||
+ | ||
+######## nsp/m2/b.pyx ######## | ||
+ | ||
+from nsp.m1.a cimport A | ||
+ | ||
+cdef class B(A): | ||
+ pass | ||
+ | ||
+######## runner.py ######## | ||
+ | ||
+from nsp.m1.a import A | ||
+from nsp.m2.b import B | ||
+ | ||
+a = A() | ||
+b = B() | ||
|
||
From fcd3e7bd1351a0964704f2921ae33b4b57250668 Mon Sep 17 00:00:00 2001 | ||
From: Fedor Alekseev <feodor.alexeev@gmail.com> | ||
Date: Mon, 9 Nov 2020 14:34:01 +0300 | ||
Subject: [PATCH 2/3] Support namespace packages inside regular packages | ||
|
||
--- | ||
Cython/Utils.py | 4 +--- | ||
tests/build/cythonize_pep420_namespace.srctree | 17 ++++++++++++++++- | ||
2 files changed, 17 insertions(+), 4 deletions(-) | ||
|
||
diff --git a/Cython/Utils.py b/Cython/Utils.py | ||
index 305ebf8412..f21d5cddba 100644 | ||
--- a/Cython/Utils.py | ||
+++ b/Cython/Utils.py | ||
@@ -141,9 +141,7 @@ def check_package_dir(dir_path, package_names): | ||
for dirname in package_names: | ||
dir_path = os.path.join(dir_path, dirname) | ||
has_init = contains_init(dir_path) | ||
- if not namespace and not has_init: | ||
- return None, False | ||
- elif has_init: | ||
+ if has_init: | ||
namespace = False | ||
return dir_path, namespace | ||
|
||
diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree | ||
index 6a031e4170..04013a3004 100644 | ||
--- a/tests/build/cythonize_pep420_namespace.srctree | ||
+++ b/tests/build/cythonize_pep420_namespace.srctree | ||
@@ -10,7 +10,8 @@ from distutils.core import setup, Extension | ||
setup( | ||
ext_modules=cythonize([ | ||
Extension("nsp.m1.a", ["nsp/m1/a.pyx"]), | ||
- Extension("nsp.m2.b", ["nsp/m2/b.pyx"]) | ||
+ Extension("nsp.m2.b", ["nsp/m2/b.pyx"]), | ||
+ Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]) | ||
]), | ||
) | ||
|
||
@@ -31,14 +32,28 @@ cdef class A: | ||
######## nsp/m2/b.pyx ######## | ||
|
||
from nsp.m1.a cimport A | ||
+from nsp.m3.c.d cimport D | ||
|
||
cdef class B(A): | ||
pass | ||
|
||
+######## nsp/m3/__init__.py ######## | ||
+ | ||
+######## nsp/m3/c/d.pyx ######## | ||
+ | ||
+cdef class D: | ||
+ pass | ||
+ | ||
+######## nsp/m3/c/d.pxd ######## | ||
+ | ||
+cdef class D: | ||
+ pass | ||
+ | ||
######## runner.py ######## | ||
|
||
from nsp.m1.a import A | ||
from nsp.m2.b import B | ||
+from nsp.m3.c.d import D | ||
|
||
a = A() | ||
b = B() | ||
|
||
From 9d61b95a6a71a4c88a51ab8f30d5b3a8b93998b8 Mon Sep 17 00:00:00 2001 | ||
From: scoder <stefan_ml@behnel.de> | ||
Date: Sat, 14 Nov 2020 09:42:09 +0100 | ||
Subject: [PATCH 3/3] Anticipate future changes. | ||
|
||
--- | ||
tests/build/cythonize_pep420_namespace.srctree | 2 +- | ||
1 file changed, 1 insertion(+), 1 deletion(-) | ||
|
||
diff --git a/tests/build/cythonize_pep420_namespace.srctree b/tests/build/cythonize_pep420_namespace.srctree | ||
index 04013a3004..99649376a3 100644 | ||
--- a/tests/build/cythonize_pep420_namespace.srctree | ||
+++ b/tests/build/cythonize_pep420_namespace.srctree | ||
@@ -11,7 +11,7 @@ setup( | ||
ext_modules=cythonize([ | ||
Extension("nsp.m1.a", ["nsp/m1/a.pyx"]), | ||
Extension("nsp.m2.b", ["nsp/m2/b.pyx"]), | ||
- Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]) | ||
+ Extension("nsp.m3.c.d", ["nsp/m3/c/d.pyx"]), | ||
]), | ||
) | ||
|