8000 [WIP] Tighten Lvalues and remove all references to Node by elazarg · Pull Request #2221 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

[WIP] Tighten Lvalues and remove all references to Node #2221

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 14 commits into from
Closed
Prev Previous commit
Next Next commit
Typedef TypeMap everywhere
This change prepares the ground for making it Dict[Expression, Type] instead of Dict[Node, Type].

TypeMap has been moved to mypy.types, following existing dependencies in code that uses it.
  • Loading branch information
elazarg committed Oct 5, 2016
commit 23db5ccd8a4e512dede74ef5e4e9b94084d98205
23 changes: 7 additions & 16 deletions mypy/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
Type, AnyType, CallableType, Void, FunctionLike, Overloaded, TupleType,
Instance, NoneTyp, ErrorType, strip_type,
UnionType, TypeVarId, TypeVarType, PartialType, DeletedType, UninhabitedType,
true_only, false_only
true_only, false_only, TypeMap
)
from mypy.sametypes import is_same_type
from mypy.messages import MessageBuilder
Expand Down Expand Up @@ -82,9 +82,9 @@ class TypeChecker(NodeVisitor[Type]):
# Utility for generating messages
msg = None # type: MessageBuilder
# Types of type checked nodes
type_map = None # type: Dict[Node, Type]
type_map = None # type: TypeMap
# Types of type checked nodes within this specific module
module_type_map = None # type: Dict[Node, Type]
module_type_map = None # type: TypeMap

# Helper for managing conditional types
binder = None # type: ConditionalTypeBinder
Expand Down Expand Up @@ -2331,15 +2331,6 @@ def method_type(self, func: FuncBase) -> FunctionLike:
# particular truth value. A value of None means that the condition can
# never have that truth value.

# NB: The keys of this dict are nodes in the original source program,
# which are compared by reference equality--effectively, being *the
# same* expression of the program, not just two identical expressions
# (such as two references to the same variable). TODO: it would
# probably be better to have the dict keyed by the nodes' literal_hash
# field instead.

TypeMap = Optional[Dict[Node, Type]]


def conditional_type_map(expr: Expression,
current_type: Optional[Type],
Expand Down Expand Up @@ -2417,7 +2408,7 @@ def or_conditional_maps(m1: TypeMap, m2: TypeMap) -> TypeMap:


def find_isinstance_check(node: Expression,
type_map: Dict[Node, Type],
type_map: TypeMap,
) -> Tuple[TypeMap, TypeMap]:
"""Find any isinstance checks (within a chain of ands). Includes
implicit and explicit checks for None.
Expand All @@ -2442,8 +2433,8 @@ def find_isinstance_check(node: Expression,
# Check for `x is None` and `x is not None`.
is_not = node.operators == ['is not']
if is_not or node.operators == ['is']:
if_vars = {} # type: Dict[Node, Type]
else_vars = {} # type: Dict[Node, Type]
if_vars = {} # type: TypeMap
else_vars = {} # type: TypeMap
for expr in node.operands:
if expr.literal == LITERAL_TYPE and not is_literal_none(expr) and expr in type_map:
# This should only be true at most once: there should be
Expand Down Expand Up @@ -2490,7 +2481,7 @@ def find_isinstance_check(node: Expression,
return {}, {}


def get_isinstance_type(expr: Expression, type_map: Dict[Node, Type]) -> Type:
def get_isinstance_type(expr: Expression, type_map: TypeMap) -> Type:
type = type_map[expr]

if isinstance(type, TupleType):
Expand Down
10000 4 changes: 2 additions & 2 deletions mypy/checkexpr.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
Type, AnyType, CallableType, Overloaded, NoneTyp, Void, TypeVarDef,
TupleType, Instance, TypeVarId, TypeVarType, ErasedType, UnionType,
PartialType, DeletedType, UnboundType, UninhabitedType, TypeType,
true_only, false_only, is_named_instance
true_only, false_only, is_named_instance, TypeMap
)
from mypy.nodes import (
NameExpr, RefExpr, Var, FuncDef, OverloadedFuncDef, TypeInfo, CallExpr,
Expand Down Expand Up @@ -1727,7 +1727,7 @@ def visit_conditional_expr(self, e: ConditionalExpr) -> Type:

return res

def analyze_cond_branch(self, map: Optional[Dict[Node, Type]],
def analyze_cond_branch(self, map: TypeMap,
node: Node, context: Optional[Type]) -> Type:
with self.chk.binder.frame_context():
if map:
Expand Down
20 changes: 10 additions & 10 deletions mypy/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
from mypy.nodes import MypyFile, Node, FuncDef
from mypy import stats
from mypy.traverser import TraverserVisitor
from mypy.types import Type
from mypy.types import TypeMap


reporter_classes = {} # type: Dict[str, Callable[[Reports, str], AbstractReporter]]
Expand All @@ -38,7 +38,7 @@ def add_report(self, report_type: str, report_dir: str) -> 'AbstractReporter':
self.named_reporters[report_type] = reporter
return reporter

def file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def file(self, tree: MypyFile, type_map: TypeMap) -> None:
for reporter in self.reporters:
reporter.on_file(tree, type_map)

Expand All @@ -52,7 +52,7 @@ def __init__(self, reports: Reports, output_dir: str) -> None:
self.output_dir = output_dir

@abstractmethod
def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
pass

@abstractmethod
Expand All @@ -76,7 +76,7 @@ def __init__(self, reports: Reports, output_dir: str) -> None:

stats.ensure_dir_exists(output_dir)

def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
# Count physical lines. This assumes the file's encoding is a
# superset of ASCII (or at least uses \n in its line endings).
physical_lines = len(open(tree.path, 'rb').readlines())
Expand Down Expand Up @@ -195,7 +195,7 @@ def __init__(self, reports: Reports, output_dir: str) -> None:

stats.ensure_dir_exists(output_dir)

def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
tree_source = open(tree.path).readlines()

coverage_visitor = LineCoverageVisitor(tree_source)
Expand All @@ -222,7 +222,7 @@ class OldHtmlReporter(AbstractReporter):
variables to preserve state for the index.
"""

def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
stats.generate_html_report(tree, tree.path, type_map, self.output_dir)

def on_finish(self) -> None:
Expand Down Expand Up @@ -262,7 +262,7 @@ def __init__(self, reports: Reports, output_dir: str) -> None:
self.last_xml = None # type: etree._ElementTree
self.files = [] # type: List[FileInfo]

def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
import lxml.etree as etree

self.last_xml = None
Expand Down Expand Up @@ -347,7 +347,7 @@ class XmlReporter(AbstractXmlReporter):
that makes it fail from file:// URLs but work on http:// URLs.
"""

def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
last_xml = self.memory_xml.last_xml
if last_xml is None:
return
Expand Down Expand Up @@ -386,7 +386,7 @@ def __init__(self, reports: Reports, output_dir: str) -> None:
self.xslt_html = etree.XSLT(etree.parse(self.memory_xml.xslt_html_path))
self.param_html = etree.XSLT.strparam('html')

def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
last_xml = self.memory_xml.last_xml
if last_xml is None:
return
Expand Down Expand Up @@ -425,7 +425,7 @@ def __init__(self, reports: Reports, output_dir: str) -> None:

self.xslt_txt = etree.XSLT(etree.parse(self.memory_xml.xslt_txt_path))

def on_file(self, tree: MypyFile, type_map: Dict[Node, Type]) -> None:
def on_file(self, tree: MypyFile, type_map: TypeMap) -> None:
pass

def on_finish(self) -> None:
Expand Down
10 changes: 5 additions & 5 deletions mypy/stats.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,13 +8,13 @@
from mypy.traverser import TraverserVisitor
from mypy.types import (
Type, AnyType, Instance, FunctionLike, TupleType, Void, TypeVarType,
TypeQuery, ANY_TYPE_STRATEGY, CallableType
TypeQuery, ANY_TYPE_STRATEGY, CallableType, TypeMap
)
from mypy import nodes
from mypy.nodes import (
Node, FuncDef, TypeApplication, AssignmentStmt, NameExpr, CallExpr, MypyFile,
MemberExpr, OpExpr, ComparisonExpr, IndexExpr, UnaryExpr, YieldFromExpr
)
)


TYPE_EMPTY = 0
Expand All @@ -31,7 +31,7 @@


class StatisticsVisitor(TraverserVisitor):
def __init__(self, inferred: bool, typemap: Dict[Node, Type] = None,
def __init__(self, inferred: bool, typemap: TypeMap = None,
all_nodes: bool = False) -> None:
self.inferred = inferred
self.typemap = typemap
Expand Down Expand Up @@ -198,7 +198,7 @@ def record_line(self, line: int, precision: int) -> None:


def dump_type_stats(tree: MypyFile, path: str, inferred: bool = False,
typemap: Dict[Node, Type] = None) -> None:
typemap: TypeMap = None) -> None:
if is_special_module(path):
return
print(path)
Expand Down Expand Up @@ -265,7 +265,7 @@ def is_complex(t: Type) -> bool:
html_files = [] # type: List[Tuple[str, str, int, int]]


def generate_html_report(tree: MypyFile, path: str, type_map: Dict[Node, Type],
def generate_html_report(tree: MypyFile, path: str, type_map: TypeMap,
output_dir: str) -> None:
if is_special_module(path):
return
Expand Down
11 changes: 11 additions & 0 deletions mypy/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -1008,6 +1008,17 @@ def deserialize(cls, data: JsonDict) -> 'TypeType':
return TypeType(Type.deserialize(data['item']))



# NB: The keys of this dict are nodes in the original source program,
# which are compared by reference equality--effectively, being *the
# same* expression of the program, not just two identical expressions
# (such as two references to the same variable). TODO: it would
# probably be better to have the dict keyed by the nodes' literal_hash
# field instead.

TypeMap = Optional[Dict[mypy.nodes.Node, Type]]


#
# Visitor-related classes
#
Expand Down
0