Skip to content

Commit e41b970

Browse files
committed
WIP (Debugging code and files)
1 parent 6438bf0 commit e41b970

File tree

14 files changed

+84
-16
lines changed

14 files changed

+84
-16
lines changed

bar.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
from mod1 import A
2+
val = A().foo()

baz.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
from mod3 import A
2+
myB = A().makeB()
3+
val = myB.foo()

foo.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
import os
2+
import parent
3+
4+
parent.a.b.value

mod1.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
from mod2 import A

mod2.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class A:
2+
def foo(self) -> int:
3+
return 42

mod3.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
from mod4 import B
2+
class A:
3+
def makeB(self) -> B:
4+
return B()

mod4.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
class B:
2+
def foo(self) -> int:
3+
return 42

mypy/build.py

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,7 @@ def default_lib_path(data_dir: str, pyversion: Tuple[int, int]) -> List[str]:
305305
PRI_HIGH = 5 # top-level "from X import blah"
306306
PRI_MED = 10 # top-level "import X"
307307
PRI_LOW = 20 # either form inside a function
308+
PRI_INDIRECT = 30 # an indirect dependency
308309
PRI_ALL = 99 # include all priorities
309310

310311

@@ -1268,7 +1269,7 @@ def load_tree(self) -> None:
12681269
self.manager.modules[self.id] = self.tree
12691270

12701271
def fix_cross_refs(self) -> None:
1271-
fixup_module_pass_one(self.tree, self.manager.modules)
1272+
fixup_module_pass_one(self.tree, self.manager.modules, self.valid_references())
12721273

12731274
def calculate_mros(self) -> None:
12741275
fixup_module_pass_two(self.tree, self.manager.modules)
@@ -1417,13 +1418,26 @@ def type_check(self) -> None:
14171418
if manager.options.semantic_analysis_only:
14181419
return
14191420
with self.wrap_context():
1420-
encountered_deps = self.dependencies + self.suppressed + self.ancestors
1421-
manager.type_checker.visit_file(self.tree, self.xpath, encountered_deps)
1421+
manager.type_checker.visit_file(self.tree, self.xpath, self.valid_references())
1422+
encountered = manager.type_checker.get_encountered()
1423+
#for dep in encountered - self.valid_references():
1424+
# self.dependencies.append(dep)
1425+
# self.priorities[dep] = PRI_INDIRECT
1426+
14221427
if manager.options.dump_inference_stats:
14231428
dump_type_stats(self.tree, self.xpath, inferred=True,
14241429
typemap=manager.type_checker.type_map)
14251430
manager.report_file(self.tree)
14261431

1432+
def valid_references(self) -> Set[str]:
1433+
valid_refs = set(self.dependencies + self.suppressed + self.ancestors)
1434+
valid_refs .add(self.id)
1435+
1436+
if "os" in valid_refs:
1437+
valid_refs.add("os.path")
1438+
1439+
return valid_refs
1440+
14271441
def write_cache(self) -> None:
14281442
if self.path and self.manager.options.incremental and not self.manager.errors.is_errors():
14291443
dep_prios = [self.priorities.get(dep, PRI_HIGH) for dep in self.dependencies]

mypy/checker.py

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -143,8 +143,12 @@ def __init__(self, errors: Errors, modules: Dict[str, MypyFile], options: Option
143143
self.deferred_nodes = []
144144
self.pass_num = 0
145145
self.current_node_deferred = False
146+
self.encountered = set() # type: Set[str]
146147

147-
def visit_file(self, file_node: MypyFile, path: str, current_dependencies: List[str]) -> None:
148+
def get_encountered(self) -> Set[str]:
149+
return self.encountered
150+
151+
def visit_file(self, file_node: MypyFile, path: str, valid_refs: Set[str]) -> None:
148152
"""Type check a mypy file with the given path."""
149153
self.pass_num = 0
150154
self.is_stub = file_node.is_stub
@@ -153,11 +157,8 @@ def visit_file(self, file_node: MypyFile, path: str, current_dependencies: List[
153157
self.weak_opts = file_node.weak_opts
154158
self.enter_partial_types()
155159
self.is_typeshed_stub = self.errors.is_typeshed_file(path)
156-
self.valid_module_references = set(current_dependencies)
157-
self.valid_module_references.add(file_node.fullname())
158-
159-
if "os" in self.valid_module_references:
160-
self.valid_module_references.add("os.path")
160+
self.valid_module_references = valid_refs
161+
self.encountered = set()
161162

162163
for d in file_node.defs:
163164
self.accept(d)

mypy/checkexpr.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ def visit_name_expr(self, e: NameExpr) -> Type:
7676
It can be of any kind: local, member or global.
7777
"""
7878
if e.kind == MODULE_REF and e.fullname not in self.chk.valid_module_references:
79+
self.chk.encountered.add(e.fullname)
7980
self.chk.msg.indirect_import(e.fullname, e)
8081
result = self.analyze_ref_expr(e)
8182
return self.chk.narrow_type_from_binder(e, result)
@@ -862,8 +863,10 @@ def visit_member_expr(self, e: MemberExpr) -> Type:
862863
"""Visit member expression (of form e.id)."""
863864
base = e.expr
864865
if isinstance(base, RefExpr) and base.kind == MODULE_REF:
866+
self.chk.encountered.add(base.fullname)
865867
if base.fullname not in self.chk.valid_module_references:
866-
self.chk.msg.indirect_import(base.fullname, e)
868+
pass
869+
#self.chk.msg.indirect_import(base.fullname, e)
867870
result = self.analyze_ordinary_member_access(e, False)
868871
return self.chk.narrow_type_from_binder(e, result)
869872

mypy/fixup.py

Lines changed: 22 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
"""Fix up various things after deserialization."""
22

3-
from typing import Any, Dict, Optional, cast
3+
from typing import Any, Dict, Optional, Set, cast
44

55
from mypy.nodes import (MypyFile, SymbolNode, SymbolTable, SymbolTableNode,
66
TypeInfo, FuncDef, OverloadedFuncDef, Decorator, Var,
@@ -12,8 +12,8 @@
1212
from mypy.visitor import NodeVisitor
1313

1414

15-
def fixup_module_pass_one(tree: MypyFile, modules: Dict[str, MypyFile]) -> None:
16-
node_fixer = NodeFixer(modules)
15+
def fixup_module_pass_one(tree: MypyFile, modules: Dict[str, MypyFile], valid_references: Optional[Set[str]] = None) -> None:
16+
node_fixer = NodeFixer(modules, valid_refs=valid_references, name=tree.fullname())
1717
node_fixer.visit_symbol_table(tree.names)
1818

1919

@@ -34,10 +34,12 @@ def compute_all_mros(symtab: SymbolTable, modules: Dict[str, MypyFile]) -> None:
3434
class NodeFixer(NodeVisitor[None]):
3535
current_info = None # type: Optional[TypeInfo]
3636

37-
def __init__(self, modules: Dict[str, MypyFile], type_fixer: 'TypeFixer' = None) -> None:
37+
def __init__(self, modules: Dict[str, MypyFile], type_fixer: 'TypeFixer' = None, valid_refs: Set[str] = None, name: str = None) -> None:
3838
self.modules = modules
39+
self.valid_references = valid_refs
40+
self.name = name
3941
if type_fixer is None:
40-
type_fixer = TypeFixer(self.modules)
42+
type_fixer = TypeFixer(self.modules, self.valid_references, self.name)
4143
self.type_fixer = type_fixer
4244

4345
# NOTE: This method isn't (yet) part of the NodeVisitor API.
@@ -68,6 +70,12 @@ def visit_symbol_table(self, symtab: SymbolTable) -> None:
6870
for key, value in list(symtab.items()):
6971
cross_ref = value.cross_ref
7072
if cross_ref is not None: # Fix up cross-reference.
73+
original_module = value.cross_ref.rsplit(".", 1)[0]
74+
if original_module not in self.valid_references:
75+
if self.name is not None:
76+
print(self.name)
77+
self.name = None
78+
print(' ', cross_ref)
7179
del value.cross_ref
7280
if cross_ref in self.modules:
7381
value.node = self.modules[cross_ref]
@@ -131,14 +139,22 @@ def visit_var(self, v: Var) -> None:
131139

132140

133141
class TypeFixer(TypeVisitor[None]):
134-
def __init__(self, modules: Dict[str, MypyFile]) -> None:
142+
def __init__(self, modules: Dict[str, MypyFile], valid_refs: Set[str] = None, name: str = None) -> None:
135143
self.modules = modules
144+
self.valid_references = valid_refs
145+
self.name = name
136146

137147
def visit_instance(self, inst: Instance) -> None:
138148
# TODO: Combine Instances that are exactly the same?
139149
type_ref = inst.type_ref
140150
if type_ref is None:
141151
return # We've already been here.
152+
original = type_ref.rsplit('.', 1)[0]
153+
if original not in self.valid_references:
154+
if self.name is not None:
155+
print(self.name + ' (type ref)')
156+
self.name = None
157+
print(' ', type_ref + ' (type ref)')
142158
del inst.type_ref
143159
node = lookup_qualified(self.modules, type_ref)
144160
if isinstance(node, TypeInfo):

parent/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from parent import a
2+
3+
class TestClass:
4+
def pipe(self) -> a.TestClassA:
5+
return a.TestClassA()

parent/a/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from parent.a import b
2+
3+
class TestClassA:
4+
def pipe(self) -> b.TestClassB:
5+
return b.TestClassB()

parent/a/b.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
value = 3
2+
class TestClassB:
3+
def pipe(self) -> int:
4+
return 3

0 commit comments

Comments
 (0)