Commit c2386dfe authored by Stefan Behnel's avatar Stefan Behnel Committed by GitHub

Merge pull request #2946 from CnlPepper/master

Add PEP420 namespace support.
parents b330b685 c4c23b17
......@@ -621,32 +621,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
......
......@@ -147,22 +147,31 @@ def find_root_package_dir(file_path):
@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 PACKAGE_FILES:
path = os.path.join(dir_path, filename)
if path_exists(path):
return 1
def is_package_dir(dir_path):
if contains_init(dir_path):
return 1
@cached_function
def path_exists(path):
# try on the filesystem first
......
......@@ -428,6 +428,7 @@ VER_DEP_MODULES = {
'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',
'run.qualname',
......
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()
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment