99
99
Plugin , ClassDefContext , SemanticAnalyzerPluginInterface ,
100
100
DynamicClassDefContext
101
101
)
102
- from mypy .util import (
103
- get_prefix , correct_relative_import , unmangle , module_prefix
104
- )
102
+ from mypy .util import correct_relative_import , unmangle , module_prefix
105
103
from mypy .scope import Scope
106
104
from mypy .newsemanal .semanal_shared import (
107
105
SemanticAnalyzerInterface , set_callable_name , calculate_tuple_fallback , PRIORITY_FALLBACKS
@@ -1621,44 +1619,6 @@ def visit_import(self, i: Import) -> None:
1621
1619
base = id .split ('.' )[0 ]
1622
1620
self .add_module_symbol (base , base , module_public = module_public ,
1623
1621
context = i , module_hidden = not module_public )
1624
- self .add_submodules_to_parent_modules (id , module_public )
1625
-
1626
- def add_submodules_to_parent_modules (self , id : str , module_public : bool ) -> None :
1627
- """Recursively adds a reference to a newly loaded submodule to its parent.
1628
-
1629
- When you import a submodule in any way, Python will add a reference to that
1630
- submodule to its parent. So, if you do something like `import A.B` or
1631
- `from A import B` or `from A.B import Foo`, Python will add a reference to
1632
- module A.B to A's namespace.
1633
-
1634
- Note that this "parent patching" process is completely independent from any
1635
- changes made to the *importer's* namespace. For example, if you have a file
1636
- named `foo.py` where you do `from A.B import Bar`, then foo's namespace will
1637
- be modified to contain a reference to only Bar. Independently, A's namespace
1638
- will be modified to contain a reference to `A.B`.
1639
- """
1640
- while '.' in id :
1641
- parent , child = id .rsplit ('.' , 1 )
1642
- parent_mod = self .modules .get (parent )
1643
- if parent_mod and self .allow_patching (parent_mod , child ):
1644
- child_mod = self .modules .get (id )
1645
- if child_mod :
1646
- sym = SymbolTableNode (GDEF , child_mod ,
1647
- module_public = module_public ,
1648
- no_serialize = True )
1649
- else :
1650
- # Construct a dummy Var with Any type.
1651
- any_type = AnyType (TypeOfAny .from_unimported_type ,
1652
- missing_import_name = id )
1653
- var = Var (child , any_type )
1654
- var ._fullname = child
1655
- var .is_ready = True
1656
- var .is_suppressed_import = True
1657
- sym = SymbolTableNode (GDEF , var ,
1658
- module_public = module_public ,
1659
- no_serialize = True )
1660
- parent_mod .names [child ] = sym
1661
- id = parent
1662
1622
1663
1623
def allow_patching (self , parent_mod : MypyFile , child : str ) -> bool :
1664
1624
if child not in parent_mod .names :
@@ -1671,7 +1631,6 @@ def allow_patching(self, parent_mod: MypyFile, child: str) -> bool:
1671
1631
def visit_import_from (self , imp : ImportFrom ) -> None :
1672
1632
self .statement = imp
1673
1633
import_id = self .correct_relative_import (imp )
1674
- self .add_submodules_to_parent_modules (import_id , True )
1675
1634
module = self .modules .get (import_id )
1676
1635
for id , as_id in imp .names :
1677
1636
node = module .names .get (id ) if module else None
@@ -1687,13 +1646,12 @@ def visit_import_from(self, imp: ImportFrom) -> None:
1687
1646
if mod is not None :
1688
1647
kind = self .current_symbol_kind ()
1689
1648
node = SymbolTableNode (kind , mod )
1690
- self .add_submodules_to_parent_modules (possible_module_id , True )
1691
1649
elif possible_module_id in self .missing_modules :
1692
1650
missing = True
1693
1651
# If it is still not resolved, check for a module level __getattr__
1694
1652
if (module and not node and (module .is_stub or self .options .python_version >= (3 , 7 ))
1695
1653
and '__getattr__' in module .names ):
1696
- # We use the fullname of the orignal definition so that we can
1654
+ # We use the fullname of the original definition so that we can
1697
1655
# detect whether two imported names refer to the same thing.
1698
1656
fullname = import_id + '.' + id
1699
1657
gvar = self .create_getattr_var (module .names ['__getattr__' ], imported_id , fullname )
@@ -1823,7 +1781,6 @@ def visit_import_all(self, i: ImportAll) -> None:
1823
1781
# Any names could be missing from the current namespace if the target module
1824
1782
# namespace is incomplete.
1825
1783
self .mark_incomplete ('*' , i )
1826
- self .add_submodules_to_parent_modules (i_id , True )
1827
1784
for name , node in m .names .items ():
1828
1785
if node is None :
1829
1786
continue
@@ -3457,61 +3414,16 @@ def check_fixed_args(self, expr: CallExpr, numargs: int,
3457
3414
def visit_member_expr (self , expr : MemberExpr ) -> None :
3458
3415
base = expr .expr
3459
3416
base .accept (self )
3460
- # Bind references to module attributes.
3461
3417
if isinstance (base , RefExpr ) and isinstance (base .node , MypyFile ):
3462
- # This branch handles the case foo.bar where foo is a module.
3463
- # In this case base.node is the module's MypyFile and we look up
3464
- # bar in its namespace. This must be done for all types of bar.
3465
- file = base .node
3466
- # TODO: Should we actually use this? Not sure if this makes a difference.
3467
- # if file.fullname() == self.cur_mod_id:
3468
- # names = self.globals
3469
- # else:
3470
- # names = file.names
3471
- n = file .names .get (expr .name , None )
3472
- if n and not n .module_hidden :
3473
- n = self .rebind_symbol_table_node (n )
3474
- if n :
3475
- if isinstance (n .node , PlaceholderNode ):
3476
- self .process_placeholder (expr .name , 'attribute' , expr )
3477
- return
3478
- # TODO: What if None?
3479
- expr .kind = n .kind
3480
- expr .fullname = n .fullname
3481
- expr .node = n .node
3482
- elif (file is not None and (file .is_stub or self .options .python_version >= (3 , 7 ))
3483
- and '__getattr__' in file .names ):
3484
- # If there is a module-level __getattr__, then any attribute on the module is valid
3485
- # per PEP 484.
3486
- getattr_defn = file .names ['__getattr__' ]
3487
- if not getattr_defn :
3488
- typ = AnyType (TypeOfAny .from_error ) # type: Type
3489
- elif isinstance (getattr_defn .node , (FuncDef , Var )):
3490
- if isinstance (getattr_defn .node .type , CallableType ):
3491
- typ = getattr_defn .node .type .ret_type
3492
- else :
3493
- typ = AnyType (TypeOfAny .from_error )
3494
- else :
3495
- typ = AnyType (TypeOfAny .from_error )
3496
- expr .kind = GDEF
3497
- expr .fullname = '{}.{}' .format (file .fullname (), expr .name )
3498
- expr .node = Var (expr .name , type = typ )
3499
- else :
3500
- if self .is_incomplete_namespace (file .fullname ()):
3501
- self .record_incomplete_ref ()
3418
+ # Handle module attribute.
3419
+ sym = self .get_module_symbol (base .node , expr .name )
3420
+ if sym :
3421
+ if isinstance (sym .node , PlaceholderNode ):
3422
+ self .process_placeholder (expr .name , 'attribute' , expr )
3502
3423
return
3503
- # We only catch some errors here; the rest will be
3504
- # caught during type checking.
3505
- #
3506
- # This way we can report a larger number of errors in
3507
- # one type checker run. If we reported errors here,
3508
- # the build would terminate after semantic analysis
3509
- # and we wouldn't be able to report any type errors.
3510
- full_name = '%s.%s' % (file .fullname () if file is not None else None , expr .name )
3511
- mod_name = " '%s'" % file .fullname () if file is not None else ''
3512
- if full_name in obsolete_name_mapping :
3513
- self .fail ("Module%s has no attribute %r (it's now called %r)" % (
3514
- mod_name , expr .name , obsolete_name_mapping [full_name ]), expr )
3424
+ expr .kind = sym .kind
3425
+ expr .fullname = sym .fullname
3426
+ expr .node = sym .node
3515
3427
elif isinstance (base , RefExpr ):
3516
3428
# This branch handles the case C.bar (or cls.bar or self.bar inside
3517
3429
# a classmethod/method), where C is a class and bar is a type
@@ -3851,10 +3763,11 @@ def lookup_qualified(self, name: str, ctx: Context,
3851
3763
if sym :
3852
3764
for i in range (1 , len (parts )):
3853
3765
node = sym .node
3766
+ part = parts [i ]
3854
3767
if isinstance (node , TypeInfo ):
3855
- nextsym = node .get (parts [ i ] )
3768
+ nextsym = node .get (part )
3856
3769
elif isinstance (node , MypyFile ):
3857
- nextsym = self .get_module_symbol (node , parts [ i :] )
3770
+ nextsym = self .get_module_symbol (node , part )
3858
3771
namespace = node .fullname ()
3859
3772
elif isinstance (node , PlaceholderNode ):
3860
3773
return sym
@@ -3881,27 +3794,40 @@ def lookup_type_node(self, expr: Expression) -> Optional[SymbolTableNode]:
3881
3794
return n
3882
3795
return None
3883
3796
3884
- def get_module_symbol (self , node : MypyFile , parts : List [str ]) -> Optional [SymbolTableNode ]:
3885
- """Look up a symbol from the module symbol table."""
3886
- # TODO: Use this logic in more places?
3797
+ def get_module_symbol (self , node : MypyFile , name : str ) -> Optional [SymbolTableNode ]:
3798
+ """Look up a symbol from a module.
3799
+
3800
+ Return None if no matching symbol could be bound.
3801
+ """
3887
3802
module = node .fullname ()
3888
3803
names = node .names
3889
- # Rebind potential references to old version of current module in
3890
- # fine-grained incremental mode.
3891
- if module == self .cur_mod_id :
3892
- names = self .globals
3893
- sym = names .get (parts [0 ], None )
3894
- if (not sym
3895
- and '__getattr__' in names
3896
- and not self .is_incomplete_namespace (module )
3897
- and (node .is_stub or self .options .python_version >= (3 , 7 ))):
3898
- fullname = module + '.' + '.' .join (parts )
3899
- gvar = self .create_getattr_var (names ['__getattr__' ],
3900
- parts [0 ], fullname )
3901
- if gvar :
3902
- sym = SymbolTableNode (GDEF , gvar )
3804
+ sym = names .get (name )
3805
+ if not sym :
3806
+ fullname = module + '.' + name
3807
+ if fullname in self .modules :
3808
+ sym = SymbolTableNode (GDEF , self .modules [fullname ])
3809
+ elif self .is_incomplete_namespace (module ):
3810
+ self .record_incomplete_ref ()
3811
+ elif ('__getattr__' in names
3812
+ and (node .is_stub
3813
+ or self .options .python_version >= (3 , 7 ))):
3814
+ gvar = self .create_getattr_var (names ['__getattr__' ], name , fullname )
3815
+ if gvar :
3816
+ sym = SymbolTableNode (GDEF , gvar )
3817
+ elif self .is_missing_module (fullname ):
3818
+ # We use the fullname of the original definition so that we can
3819
+ # detect whether two names refer to the same thing.
3820
+ var_type = AnyType (TypeOfAny .from_unimported_type )
3821
+ v = Var (name , type = var_type )
3822
+ v ._fullname = fullname
3823
+ sym = SymbolTableNode (GDEF , v )
3824
+ elif sym .module_hidden :
3825
+ sym = None
3903
3826
return sym
3904
3827
3828
+ def is_missing_module (self , module : str ) -> bool :
3829
+ return self .options .ignore_missing_imports or module in self .missing_modules
3830
+
3905
3831
def implicit_symbol (self , sym : SymbolTableNode , name : str , parts : List [str ],
3906
3832
source_type : AnyType ) -> SymbolTableNode :
3907
3833
"""Create symbol for a qualified name reference through Any type."""
@@ -4308,24 +4234,6 @@ def process_placeholder(self, name: str, kind: str, ctx: Context) -> None:
4308
4234
def cannot_resolve_name (self , name : str , kind : str , ctx : Context ) -> None :
4309
4235
self .fail ('Cannot resolve {} "{}" (possible cyclic definition)' .format (kind , name ), ctx )
4310
4236
4311
- def rebind_symbol_table_node (self , n : SymbolTableNode ) -> Optional [SymbolTableNode ]:
4312
- """If node refers to old version of module, return reference to new version.
4313
-
4314
- If the reference is removed in the new version, return None.
4315
- """
4316
- # TODO: Handle type variables and other sorts of references
4317
- if isinstance (n .node , (FuncDef , OverloadedFuncDef , TypeInfo , Var , TypeAlias )):
4318
- # TODO: Why is it possible for fullname() to be None, even though it's not
4319
- # annotated as Optional[str]?
4320
- # TODO: Do this for all modules in the set of modified files
4321
- # TODO: This doesn't work for things nested within classes
4322
- if n .node .fullname () and get_prefix (n .node .fullname ()) == self .cur_mod_id :
4323
- # This is an indirect reference to a name defined in the current module.
4324
- # Rebind it.
4325
- return self .globals .get (n .node .name ())
4326
- # No need to rebind.
4327
- return n
4328
-
4329
4237
def qualified_name (self , name : str ) -> str :
4330
4238
if self .type is not None :
4331
4239
return self .type ._fullname + '.' + name
0 commit comments