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) ...@@ -621,32 +621,58 @@ def search_include_directories(dirs, qualified_name, suffix, pos, include=False)
else: else:
dirs = (Utils.find_root_package_dir(file_desc.filename),) + dirs dirs = (Utils.find_root_package_dir(file_desc.filename),) + dirs
# search for dotted filename e.g. <dir>/foo.bar.pxd
dotted_filename = qualified_name dotted_filename = qualified_name
if suffix: if suffix:
dotted_filename += 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: if not include:
names = qualified_name.split('.') names = qualified_name.split('.')
package_names = tuple(names[:-1]) package_names = tuple(names[:-1])
module_name = names[-1] module_name = names[-1]
module_filename = module_name + suffix module_filename = module_name + suffix
package_filename = "__init__" + suffix package_filename = "__init__" + suffix
for dirname in dirs: # search for standard packages first - PEP420
path = os.path.join(dirname, dotted_filename) namespace_dirs = []
if os.path.exists(path): for dirname in dirs:
return path package_dir, is_namespace = Utils.check_package_dir(dirname, package_names)
if not include:
package_dir = Utils.check_package_dir(dirname, package_names)
if package_dir is not None: 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) path = os.path.join(package_dir, module_filename)
if os.path.exists(path): if os.path.exists(path):
return 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): if os.path.exists(path):
return 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 return None
......
...@@ -147,22 +147,31 @@ def find_root_package_dir(file_path): ...@@ -147,22 +147,31 @@ def find_root_package_dir(file_path):
@cached_function @cached_function
def check_package_dir(dir, package_names): def check_package_dir(dir_path, package_names):
namespace = True
for dirname in package_names: for dirname in package_names:
dir = os.path.join(dir, dirname) dir_path = os.path.join(dir_path, dirname)
if not is_package_dir(dir): has_init = contains_init(dir_path)
return None if not namespace and not has_init:
return dir return None, False
elif has_init:
namespace = False
return dir_path, namespace
@cached_function @cached_function
def is_package_dir(dir_path): def contains_init(dir_path):
for filename in PACKAGE_FILES: for filename in PACKAGE_FILES:
path = os.path.join(dir_path, filename) path = os.path.join(dir_path, filename)
if path_exists(path): if path_exists(path):
return 1 return 1
def is_package_dir(dir_path):
if contains_init(dir_path):
return 1
@cached_function @cached_function
def path_exists(path): def path_exists(path):
# try on the filesystem first # try on the filesystem first
......
...@@ -428,6 +428,7 @@ VER_DEP_MODULES = { ...@@ -428,6 +428,7 @@ VER_DEP_MODULES = {
'run.special_methods_T561_py2', 'run.special_methods_T561_py2',
]), ]),
(3,3) : (operator.lt, lambda x: x in ['build.package_compilation', (3,3) : (operator.lt, lambda x: x in ['build.package_compilation',
'build.cythonize_pep420_namespace',
'run.yield_from_py33', 'run.yield_from_py33',
'pyximport.pyximport_namespace', 'pyximport.pyximport_namespace',
'run.qualname', '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