Skip to content

Commit

Permalink
[PackageMetadata] Multiple top levels
Browse files Browse the repository at this point in the history
Another corner cases: packages that have multiple top levels.

For example Zope2 package has quite a few top levels,
that's why you can import Products.OFSP without any mention to Zope2 on
the import line (I guess).
  • Loading branch information
gforcada committed Jun 29, 2018
1 parent 5432147 commit 51dcec2
Show file tree
Hide file tree
Showing 3 changed files with 66 additions and 23 deletions.
4 changes: 2 additions & 2 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Changelog of z3c.dependencychecker
2.4 (unreleased)
----------------

- Nothing changed yet.

- Handle packages that have multiple top levels, i.e. packages like Zope2.
[gforcada]

2.3 (2018-06-21)
----------------
Expand Down
56 changes: 37 additions & 19 deletions z3c/dependencychecker/package.py
Original file line number Diff line number Diff line change
Expand Up @@ -161,22 +161,36 @@ def top_level(self):
with open(path) as top_level_file:
content = top_level_file.read().strip()

sources_top_level = os.path.join(
self.package_dir,
content,
)
top_levels = []
for candidate in content.split('\n'):
possible_top_level = os.path.join(
self.package_dir,
candidate,
)

if os.path.exists(sources_top_level):
return sources_top_level
if os.path.exists(possible_top_level):
logger.debug('Found top level %s', possible_top_level)
top_levels.append(possible_top_level)
continue

single_module = '{0}.py'.format(possible_top_level)
if os.path.exists(single_module):
logger.debug('Found top level %s', single_module)
top_levels.append(single_module)
continue

logger.warning(
'Top level %s not found but referenced '
'by top_level.txt',
possible_top_level,
)

single_module_top_level = '{0}.py'.format(sources_top_level)
if os.path.exists(single_module_top_level):
return single_module_top_level
if top_levels:
return top_levels

logger.error(
'%s does not exist but %s%stop_level.txt points there.\n'
'There are paths found in %s%stop_level.txt that do not exist.\n'
'Maybe you need to put the package in development again?',
sources_top_level,
self.egg_info_dir,
os.sep,
)
Expand Down Expand Up @@ -237,16 +251,20 @@ def set_user_mappings(self):
self.imports.add_user_mapping(package, packages_provided)

def analyze_package(self):
top_folder = self.metadata.top_level
for module_obj in MODULES:
logger.debug("Starting analyzing files using %s...", module_obj)
for source_file in module_obj.create_from_files(top_folder):
for top_folder in self.metadata.top_level:
logger.debug("Analyzing package top_level %s...", top_folder)
for module_obj in MODULES:
logger.debug(
'Searching dependencies (with %s) in file %s...',
module_obj.__name__,
source_file.path,
"Starting analyzing files using %s...",
module_obj,
)
self.imports.add_imports(source_file.scan())
for source_file in module_obj.create_from_files(top_folder):
logger.debug(
'Searching dependencies (with %s) in file %s...',
module_obj.__name__,
source_file.path,
)
self.imports.add_imports(source_file.scan())

def _load_user_config(self):
config_file_path = os.sep.join([
Expand Down
29 changes: 27 additions & 2 deletions z3c/dependencychecker/tests/test_package_metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -282,7 +282,7 @@ def test_top_level_txt_file_found(minimal_structure):
path, package_name = minimal_structure
metadata = PackageMetadata(path)

assert metadata.top_level == os.path.join(path, package_name)
assert metadata.top_level == [os.path.join(path, package_name), ]


def test_no_top_level_txt_file_found(minimal_structure):
Expand Down Expand Up @@ -337,4 +337,29 @@ def test_top_level_is_module(minimal_structure):

metadata = PackageMetadata(path)

assert metadata.top_level == top_level_module_path
assert metadata.top_level == [top_level_module_path, ]


def test_top_level_multiple(minimal_structure):
path, package_name = minimal_structure
top_level_file = os.path.join(
path,
'{0}.egg-info'.format(package_name),
'top_level.txt',
)
with open(top_level_file, 'w') as top_level:
top_level.write('one\n')
top_level.write('two\n')
top_level.write('three\n')

top_level_folders = [
'{0}/one'.format(path),
'{0}/two'.format(path),
'{0}/three'.format(path),
]
for new_top_level in top_level_folders:
os.makedirs(new_top_level)

metadata = PackageMetadata(path)

assert metadata.top_level == top_level_folders

0 comments on commit 51dcec2

Please sign in to comment.