Commit ea45b76a authored by Stefan Behnel's avatar Stefan Behnel

fix for module .pxd file searching: must start at package root

parent 9e567528
...@@ -123,6 +123,11 @@ class Context: ...@@ -123,6 +123,11 @@ class Context:
def find_pxd_file(self, qualified_name, pos): def find_pxd_file(self, qualified_name, pos):
# Search include path for the .pxd file corresponding to the # Search include path for the .pxd file corresponding to the
# given fully-qualified module name. # given fully-qualified module name.
# Will find either a dotted filename or a file in a
# package directory. If a source file position is given,
# the directory containing the source file is searched first
# for a dotted filename, and its containing package root
# directory is searched first for a non-dotted filename.
return self.search_include_directories(qualified_name, ".pxd", pos) return self.search_include_directories(qualified_name, ".pxd", pos)
def find_pyx_file(self, qualified_name, pos): def find_pyx_file(self, qualified_name, pos):
...@@ -134,27 +139,30 @@ class Context: ...@@ -134,27 +139,30 @@ class Context:
# Search list of include directories for filename. # Search list of include directories for filename.
# Reports an error and returns None if not found. # Reports an error and returns None if not found.
path = self.search_include_directories(filename, "", pos, path = self.search_include_directories(filename, "", pos,
split_package=False) include=True)
if not path: if not path:
error(pos, "'%s' not found" % filename) error(pos, "'%s' not found" % filename)
return path return path
def search_include_directories(self, qualified_name, suffix, pos, def search_include_directories(self, qualified_name, suffix, pos,
split_package=True): include=False):
# Search the list of include directories for the given # Search the list of include directories for the given
# file name. If a source file position is given, first # file name. If a source file position is given, first
# searches the directory containing that file. Returns # searches the directory containing that file. Returns
# None if not found, but does not report an error. # None if not found, but does not report an error.
# The 'include' option will disable package dereferencing.
dirs = self.include_directories dirs = self.include_directories
if pos: if pos:
file_desc = pos[0] file_desc = pos[0]
if not isinstance(file_desc, FileSourceDescriptor): if not isinstance(file_desc, FileSourceDescriptor):
raise RuntimeError("Only file sources for code supported") raise RuntimeError("Only file sources for code supported")
here_dir = os.path.dirname(file_desc.filename) if include:
dirs = [here_dir] + dirs dirs = [os.path.dirname(file_desc.filename)] + dirs
else:
dirs = [self.find_root_package_dir(file_desc.filename)] + dirs
dotted_filename = qualified_name + suffix dotted_filename = qualified_name + suffix
if split_package: if not include:
names = qualified_name.split('.') names = qualified_name.split('.')
package_names = names[:-1] package_names = names[:-1]
module_name = names[-1] module_name = names[-1]
...@@ -165,7 +173,7 @@ class Context: ...@@ -165,7 +173,7 @@ class Context:
path = os.path.join(dir, dotted_filename) path = os.path.join(dir, dotted_filename)
if os.path.exists(path): if os.path.exists(path):
return path return path
if split_package: if not include:
package_dir = self.check_package_dir(dir, package_names) package_dir = self.check_package_dir(dir, package_names)
if package_dir is not None: if package_dir is not None:
path = os.path.join(package_dir, module_filename) path = os.path.join(package_dir, module_filename)
...@@ -177,15 +185,27 @@ class Context: ...@@ -177,15 +185,27 @@ class Context:
return path return path
return None return None
def find_root_package_dir(self, file_path):
dir = os.path.dirname(file_path)
while self.is_package_dir(dir):
parent = os.path.dirname(dir)
if parent == dir:
break
dir = parent
return dir
def is_package_dir(self, dir):
package_init = os.path.join(dir, "__init__.py")
return os.path.exists(package_init) or \
os.path.exists(package_init + "x") # same with .pyx
def check_package_dir(self, dir, package_names): def check_package_dir(self, dir, package_names):
package_dir = os.path.join(dir, *package_names) package_dir = os.path.join(dir, *package_names)
if not os.path.exists(package_dir): if not os.path.exists(package_dir):
return None return None
for dirname in package_names: for dirname in package_names:
dir = os.path.join(dir, dirname) dir = os.path.join(dir, dirname)
package_init = os.path.join(dir, "__init__.py") if not self.is_package_dir(dir):
if not os.path.exists(package_init) and \
not os.path.exists(package_init + "x"): # same with .pyx ?
return None return None
return package_dir return package_dir
......
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