Skip to content

Commit

Permalink
Merge pull request #54 from QuantStack/fix/star-import-filtering
Browse files Browse the repository at this point in the history
Fix incorrect behavior when star importing a module
  • Loading branch information
SylvainCorlay authored Jan 28, 2021
2 parents b7b79b2 + 576401b commit 57fcaf4
Show file tree
Hide file tree
Showing 3 changed files with 28 additions and 17 deletions.
29 changes: 14 additions & 15 deletions memestra/memestra.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,29 +181,19 @@ def get_deprecated_users(self, defuse, ancestors):
deprecated_node, reason))

else:
# special node: a node imported from *; in that case we do
# selective matching
# There's a special handler in ImportFrom for these
if isinstance(deprecated_node, DeprecatedStar):
def filter_out(user):
return user.name() != deprecated_node.name
deprecated = deprecated_node.dnode
# regular symbol processing
else:
def filter_out(user):
return False
deprecated = deprecated_node

for user in defuse.chains[deprecated].users():
if filter_out(user):
continue
continue

for user in defuse.chains[deprecated_node].users():
user_ancestors = [n
for n in ancestors.parents(user.node)
if isinstance(n, _defs)]
if any(f in self.deprecated for f in user_ancestors):
continue

user_ancestor = user_ancestors[-1] if user_ancestors else user.node
deprecated_uses.append((deprecated, user.node,
deprecated_uses.append((deprecated_node, user.node,
user_ancestor,
reason))
if self.recursive and isinstance(user_ancestor, _defs):
Expand Down Expand Up @@ -241,6 +231,9 @@ def visit_ImportFrom(self, node):
def alias_extractor(deprec):
return star_alias

def alias_selector(deprec, node):
return getattr(node, 'id', None) == deprec

except ValueError:
# otherwise only pick the imported one

Expand All @@ -252,12 +245,18 @@ def alias_extractor(deprec):
except ValueError:
return None

def alias_selector(deprec, node):
return True

for deprec, reason in deprecated.items():
deprec_alias = alias_extractor(deprec)
if deprec_alias is None:
continue

for user in self.def_use_chains.chains[deprec_alias].users():
# if deprec_alias is '*' we need to be selective
if not alias_selector(deprec, user.node):
continue
self.deprecated.add(make_deprecated(user.node, reason))

def visit_Module(self, node):
Expand Down
3 changes: 3 additions & 0 deletions tests/misc/ipy/__init__.py
Original file line number Diff line number Diff line change
@@ -1 +1,4 @@
from .a import *

def useless():
pass
13 changes: 11 additions & 2 deletions tests/test_imports.py
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,7 @@ def test_forwarding_all_symbols2(self):

self.checkDeprecatedUses(
code,
[('*', '<>', 3, 4, None),
('Test', '<>', 3, 4, None)])
[('Test', '<>', 3, 4, None)])

def test_importing_non_existing_file(self):
code = '''
Expand Down Expand Up @@ -236,6 +235,16 @@ def test_import_pkg_level_star(self):
code,
[('foo', '<>', 2, 0, 'why'), ('foo', '<>', 4, 4, 'why')])

def test_import_pkg_level_star2(self):
code = '''
from ipy import *
a = useless()
b = foo()'''

self.checkDeprecatedUses(
code,
[('foo', '<>', 4, 4, 'why')])

def test_shared_cache(self):
# We have a fake description for gast in tests/share/memestra
# Setup the shared cache to use it.
Expand Down

0 comments on commit 57fcaf4

Please sign in to comment.