Skip to content

Commit

Permalink
Try #2, with less FuncDef
Browse files Browse the repository at this point in the history
  • Loading branch information
msullivan committed Oct 24, 2018
1 parent 1f1dcc9 commit 6023129
Show file tree
Hide file tree
Showing 7 changed files with 52 additions and 42 deletions.
15 changes: 7 additions & 8 deletions mypy/nodes.py
Original file line number Diff line number Diff line change
Expand Up @@ -379,7 +379,7 @@ def __str__(self) -> str:


FUNCBASE_FLAGS = [
'is_property', 'is_class', 'is_static', 'is_final', 'plugin_generated'
'is_property', 'is_class', 'is_static', 'is_final'
] # type: Final


Expand All @@ -394,7 +394,6 @@ class FuncBase(Node):
'is_static', # Uses "@staticmethod"
'is_final', # Uses "@final"
'_fullname',
'plugin_generated',
)

def __init__(self) -> None:
Expand All @@ -411,7 +410,6 @@ def __init__(self) -> None:
self.is_class = False
self.is_static = False
self.is_final = False
self.plugin_generated = False
# Name with module prefix
# TODO: Type should be Optional[str]
self._fullname = cast(Bogus[str], None)
Expand Down Expand Up @@ -2703,6 +2701,7 @@ class SymbolTableNode:
'module_hidden',
'cross_ref',
'implicit',
'plugin_generated',
'no_serialize',
)

Expand All @@ -2721,7 +2720,7 @@ def __init__(self,
self.implicit = implicit
self.module_hidden = module_hidden
self.cross_ref = None # type: Optional[str]
# self.plugin_generated = plugin_generated
self.plugin_generated = plugin_generated
self.no_serialize = no_serialize

@property
Expand Down Expand Up @@ -2778,8 +2777,8 @@ def serialize(self, prefix: str, name: str) -> JsonDict:
data['module_public'] = False
if self.implicit:
data['implicit'] = True
# if self.plugin_generated:
# data['plugin_generated'] = True
if self.plugin_generated:
data['plugin_generated'] = True
if self.kind == MODULE_REF:
assert self.node is not None, "Missing module cross ref in %s for %s" % (prefix, name)
data['cross_ref'] = self.node.fullname()
Expand Down Expand Up @@ -2813,8 +2812,8 @@ def deserialize(cls, data: JsonDict) -> 'SymbolTableNode':
stnode.module_public = data['module_public']
if 'implicit' in data:
stnode.implicit = data['implicit']
# if 'plugin_generated' in data:
# stnode.plugin_generated = data['plugin_generated']
if 'plugin_generated' in data:
stnode.plugin_generated = data['plugin_generated']
return stnode


Expand Down
4 changes: 0 additions & 4 deletions mypy/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -113,10 +113,6 @@ def lookup_qualified(self, name: str, ctx: Context,
suppress_errors: bool = False) -> Optional[SymbolTableNode]:
raise NotImplementedError

@abstractmethod
def add_symbol_to_type(self, info: TypeInfo, name: str, node: SymbolTableNode) -> None:
raise NotImplementedError


# A context for a function hook that infers the return type of a function with
# a special signature.
Expand Down
3 changes: 1 addition & 2 deletions mypy/plugins/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ def _add_method(
func.type = set_callable_name(signature, func)
func._fullname = info.fullname() + '.' + name
func.line = info.line
func.plugin_generated = True

info.names[name] = SymbolTableNode(MDEF, func)
info.names[name] = SymbolTableNode(MDEF, func, plugin_generated=True)
info.defn.defs.body.append(func)
4 changes: 0 additions & 4 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -3375,9 +3375,6 @@ def create_getattr_var(self, getattr_defn: SymbolTableNode,
return SymbolTableNode(GDEF, v)
return None

def add_symbol_to_type(self, info: TypeInfo, name: str, node: SymbolTableNode) -> None:
pass

def rebind_symbol_table_node(self, n: SymbolTableNode) -> Optional[SymbolTableNode]:
"""If node refers to old version of module, return reference to new version.
Expand Down Expand Up @@ -3570,7 +3567,6 @@ def name_already_defined(self, name: str, ctx: Context,
node = original_ctx.node
elif isinstance(original_ctx, SymbolNode):
node = original_ctx
# import pdb; pdb.set_trace()

if isinstance(original_ctx, SymbolTableNode) and original_ctx.kind == MODULE_REF:
# Since this is an import, original_ctx.node points to the module definition.
Expand Down
24 changes: 10 additions & 14 deletions mypy/server/aststrip.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,13 @@
"""

import contextlib
from typing import Union, Iterator, Optional
from typing import Union, Iterator, Optional, List

from mypy.nodes import (
Node, FuncDef, NameExpr, MemberExpr, RefExpr, MypyFile, FuncItem, ClassDef, AssignmentStmt,
ImportFrom, Import, TypeInfo, SymbolTable, Var, CallExpr, Decorator, OverloadedFuncDef,
SuperExpr, UNBOUND_IMPORTED, GDEF, MDEF, IndexExpr, SymbolTableNode, ImportAll, TupleExpr,
ListExpr, ForStmt, Block, FuncBase,
ListExpr, ForStmt, Block, SymbolNode, FuncBase,
)
from mypy.semanal_shared import create_indirect_imported_name
from mypy.traverser import TraverserVisitor
Expand Down Expand Up @@ -90,21 +90,17 @@ def visit_block(self, b: Block) -> None:

def visit_class_def(self, node: ClassDef) -> None:
"""Strip class body and type info, but don't strip methods."""
self.strip_type_info(node.info)
to_delete = set(self.strip_type_info(node.info))
node.type_vars = []
node.base_type_exprs.extend(node.removed_base_type_exprs)
node.removed_base_type_exprs = []
print(node.defs.body)
node.defs.body = [s for s in node.defs.body
if not (isinstance(s, FuncBase) and s.plugin_generated)]
print(node.defs.body)
if s not in to_delete]

with self.enter_class(node.info):
super().visit_class_def(node)

def strip_type_info(self, info: TypeInfo) -> None:
print("stripping", info.fullname())

def strip_type_info(self, info: TypeInfo) -> List[SymbolNode]:
info.type_vars = []
info.bases = []
info.is_abstract = False
Expand All @@ -118,12 +114,12 @@ def strip_type_info(self, info: TypeInfo) -> None:
info.declared_metaclass = None
info.metaclass_type = None

to_delete = [k for k, v in info.names.items()
if isinstance(v.node, FuncBase) and v.node.plugin_generated]
# print("YO HOW BOUT THIS", to_delete, info.names.items())
for k in to_delete:
# We need to delete any entries that were generated by plugins,
# since they will get regenerated.
to_delete = [(k, v) for k, v in info.names.items() if v.plugin_generated]
for k, _ in to_delete:
del info.names[k]
# import pdb; pdb.set_trace()
return [v.node for k, v in to_delete if v.node]

def visit_func_def(self, node: FuncDef) -> None:
if not self.recurse_into_functions:
Expand Down
18 changes: 9 additions & 9 deletions mypy/server/update.py
Original file line number Diff line number Diff line change
Expand Up @@ -846,12 +846,6 @@ def reprocess_nodes(manager: BuildManager,
module_id)
return set()

nodeset_ = set(s for s in nodeset
if not (isinstance(s.node, FuncBase) and s.node.plugin_generated))
print(nodeset_ - nodeset)
nodeset = nodeset_
print(nodeset)

file_node = manager.modules[module_id]
old_symbols = find_symbol_tables_recursive(file_node.fullname(), file_node.names)
old_symbols = {name: names.copy() for name, names in old_symbols.items()}
Expand Down Expand Up @@ -891,7 +885,6 @@ def key(node: FineGrainedDeferredNode) -> int:
fnam=file_node.path,
options=options,
active_type=deferred.active_typeinfo):
# import pdb; pdb.set_trace()
manager.semantic_analyzer.refresh_partial(deferred.node, patches)

# Third pass of semantic analysis.
Expand Down Expand Up @@ -985,7 +978,9 @@ def update_deps(module_id: str,


def lookup_target(manager: BuildManager,
target: str) -> Tuple[List[FineGrainedDeferredNode], Optional[TypeInfo]]:
target: str,
promote_generated: bool = True,
) -> Tuple[List[FineGrainedDeferredNode], Optional[TypeInfo]]:
"""Look up a target by fully-qualified name.
The first item in the return tuple is a list of deferred nodes that
Expand Down Expand Up @@ -1020,6 +1015,11 @@ def not_found() -> None:
or c not in node.names):
not_found() # Stale dependency
return [], None
if node.names[c].plugin_generated:
if not promote_generated:
return [], None
target = node.fullname()
break
node = node.names[c].node
if isinstance(node, TypeInfo):
# A ClassDef target covers the body of the class and everything defined
Expand All @@ -1040,7 +1040,7 @@ def not_found() -> None:
for name, symnode in node.names.items():
node = symnode.node
if isinstance(node, FuncDef):
method, _ = lookup_target(manager, target + '.' + name)
method, _ = lookup_target(manager, target + '.' + name, promote_generated=False)
result.extend(method)
return result, stale_info
if isinstance(node, Decorator):
Expand Down
26 changes: 25 additions & 1 deletion test-data/unit/fine-grained.test
Original file line number Diff line number Diff line change
Expand Up @@ -691,8 +691,32 @@ B(1, 2)
b.py:8: error: Argument 1 to "B" has incompatible type "int"; expected "str"
[builtins fixtures/list.pyi]

[case testDataclassUpdate3]
# flags: --python-version 3.6
from b import B
B(1, 2)
[file b.py]
from a import A
from dataclasses import dataclass
@dataclass
class B(A):
b: int
[file a.py]
from dataclasses import dataclass
@dataclass
class A:
a: int


[file a.py.2]
from dataclasses import dataclass
@dataclass
class A:
a: int
other: int
[builtins fixtures/list.pyi]
[out]
==
main:3: error: Too few arguments for "B"

[case testAddBaseClassMethodCausingInvalidOverride]
import m
Expand Down

0 comments on commit 6023129

Please sign in to comment.