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
Add machinery for marking places we subvert the type system #5467
Changes from 1 commit
5e21f6a
35af440
049d88c
07caba8
e29c39c
838178d
File filter...
Jump to…
Diff settings
@@ -0,0 +1,22 @@ | |||
"""A Bogus[T] type alias for marking when we subvert the type system | |||
We need this for compiling with mypyc, which inserts runtime | |||
typechecks that cause problems when we subvert the type system. So | |||
when compiling with mypyc, we turn those places into Any, while | |||
keeping the types around for normal typechecks. | |||
Since this causes the runtype types to be Any, this is best used | |||
|
|||
in places where efficient access to properties is not important. | |||
For those cases some other technique should be used. | |||
""" | |||
|
|||
from mypy_extensions import FlexibleAlias | |||
from typing import TypeVar, Any | |||
|
|||
T = TypeVar('T') | |||
|
|||
SUPPRESS_BOGUS_TYPES = False | |||
if SUPPRESS_BOGUS_TYPES: | |||
Bogus = FlexibleAlias[T, Any] | |||
else: | |||
Bogus = FlexibleAlias[T, T] |
@@ -15,6 +15,8 @@ | |||
from mypy.util import short_type | |||
from mypy.visitor import NodeVisitor, StatementVisitor, ExpressionVisitor | |||
|
|||
from mypy.bogus_type import Bogus | |||
|
|||
|
|||
class Context: | |||
"""Base type for objects that are valid as error message locations.""" | |||
@@ -174,10 +176,10 @@ class SymbolNode(Node): | |||
# TODO do not use methods for these | |||
|
|||
@abstractmethod | |||
def name(self) -> str: pass | |||
def name(self) -> Bogus[str]: pass | |||
ilevkivskyi
Collaborator
|
|||
|
|||
@abstractmethod | |||
def fullname(self) -> str: pass | |||
def fullname(self) -> Bogus[str]: pass | |||
|
|||
@abstractmethod | |||
def serialize(self) -> JsonDict: pass | |||
@@ -195,9 +197,9 @@ class MypyFile(SymbolNode): | |||
"""The abstract syntax tree of a single source file.""" | |||
|
|||
# Module name ('__main__' for initial file) | |||
_name = None # type: str | |||
_name = None # type: Bogus[str] | |||
# Fully qualified module name | |||
_fullname = None # type: str | |||
_fullname = None # type: Bogus[str] | |||
ilevkivskyi
Collaborator
|
|||
# Path to the file (None if not known) | |||
path = '' | |||
# Top-level definitions and statements | |||
@@ -236,10 +238,10 @@ def __init__(self, | |||
else: | |||
self.ignored_lines = set() | |||
|
|||
def name(self) -> str: | |||
def name(self) -> Bogus[str]: | |||
ilevkivskyi
Collaborator
|
|||
return self._name | |||
|
|||
def fullname(self) -> str: | |||
def fullname(self) -> Bogus[str]: | |||
return self._fullname | |||
|
|||
def accept(self, visitor: NodeVisitor[T]) -> T: | |||
@@ -404,12 +406,12 @@ def __init__(self) -> None: | |||
self.is_static = False | |||
# Name with module prefix | |||
# TODO: Type should be Optional[str] | |||
self._fullname = cast(str, None) | |||
self._fullname = cast(Bogus[str], None) | |||
|
|||
@abstractmethod | |||
def name(self) -> str: pass | |||
|
|||
def fullname(self) -> str: | |||
def fullname(self) -> Bogus[str]: | |||
return self._fullname | |||
|
|||
|
|||
@@ -660,7 +662,7 @@ def __init__(self, func: FuncDef, decorators: List[Expression], | |||
def name(self) -> str: | |||
return self.func.name() | |||
|
|||
def fullname(self) -> str: | |||
def fullname(self) -> Bogus[str]: | |||
return self.func.fullname() | |||
|
|||
@property | |||
@@ -725,7 +727,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: | |||
super().__init__() | |||
self._name = name # Name without module prefix | |||
# TODO: Should be Optional[str] | |||
self._fullname = cast(str, None) # Name with module prefix | |||
self._fullname = cast(Bogus[str], None) # Name with module prefix | |||
# TODO: Should be Optional[TypeInfo] | |||
self.info = cast(TypeInfo, None) # Defining class (for member variables) | |||
self.type = type # type: Optional[mypy.types.Type] # Declared or inferred type, or None | |||
@@ -748,7 +750,7 @@ def __init__(self, name: str, type: 'Optional[mypy.types.Type]' = None) -> None: | |||
def name(self) -> str: | |||
return self._name | |||
|
|||
def fullname(self) -> str: | |||
def fullname(self) -> Bogus[str]: | |||
return self._fullname | |||
|
|||
def accept(self, visitor: StatementVisitor[T]) -> T: | |||
@@ -780,7 +782,7 @@ class ClassDef(Statement): | |||
"""Class definition""" | |||
|
|||
name = None # type: str # Name of the class without module prefix | |||
fullname = None # type: str # Fully qualified name of the class | |||
fullname = None # type: Bogus[str] # Fully qualified name of the class | |||
defs = None # type: Block | |||
type_vars = None # type: List[mypy.types.TypeVarDef] | |||
# Base class expressions (not semantically analyzed -- can be arbitrary expressions) | |||
@@ -2054,7 +2056,7 @@ class is generic then it will be a type constructor of higher kind. | |||
the appropriate number of arguments. | |||
""" | |||
|
|||
_fullname = None # type: str # Fully qualified name | |||
_fullname = None # type: Bogus[str] # Fully qualified name | |||
# Fully qualified name for the module this type was defined in. This | |||
# information is also in the fullname, but is harder to extract in the | |||
# case of nested class definitions. | |||
@@ -2195,7 +2197,7 @@ def name(self) -> str: | |||
"""Short name.""" | |||
return self.defn.name | |||
|
|||
def fullname(self) -> str: | |||
def fullname(self) -> Bogus[str]: | |||
return self._fullname | |||
|
|||
def is_generic(self) -> bool: | |||
@@ -18,6 +18,7 @@ | |||
) | |||
from mypy.sharedparse import argument_elide_name | |||
from mypy.util import IdMapper | |||
from mypy.bogus_type import Bogus | |||
|
|||
T = TypeVar('T') | |||
|
|||
@@ -341,8 +342,8 @@ def accept(self, visitor: 'TypeVisitor[T]') -> T: | |||
return visitor.visit_any(self) | |||
|
|||
def copy_modified(self, | |||
type_of_any: TypeOfAny = _dummy, | |||
original_any: Optional['AnyType'] = _dummy, | |||
type_of_any: Bogus[TypeOfAny] = _dummy, | |||
original_any: Bogus[Optional['AnyType']] = _dummy, | |||
ilevkivskyi
Collaborator
|
|||
) -> 'AnyType': | |||
if type_of_any is _dummy: | |||
type_of_any = self.type_of_any | |||
@@ -743,22 +744,22 @@ def __init__(self, | |||
self.def_extras = {} | |||
|
|||
def copy_modified(self, | |||
arg_types: List[Type] = _dummy, | |||
arg_kinds: List[int] = _dummy, | |||
arg_names: List[Optional[str]] = _dummy, | |||
ret_type: Type = _dummy, | |||
fallback: Instance = _dummy, | |||
name: Optional[str] = _dummy, | |||
definition: SymbolNode = _dummy, | |||
variables: List[TypeVarDef] = _dummy, | |||
line: int = _dummy, | |||
column: int = _dummy, | |||
is_ellipsis_args: bool = _dummy, | |||
implicit: bool = _dummy, | |||
special_sig: Optional[str] = _dummy, | |||
from_type_type: bool = _dummy, | |||
bound_args: List[Optional[Type]] = _dummy, | |||
def_extras: Dict[str, Any] = _dummy) -> 'CallableType': | |||
arg_types: Bogus[List[Type]] = _dummy, | |||
arg_kinds: Bogus[List[int]] = _dummy, | |||
arg_names: Bogus[List[Optional[str]]] = _dummy, | |||
ret_type: Bogus[Type] = _dummy, | |||
fallback: Bogus[Instance] = _dummy, | |||
name: Bogus[Optional[str]] = _dummy, | |||
definition: Bogus[SymbolNode] = _dummy, | |||
variables: Bogus[List[TypeVarDef]] = _dummy, | |||
line: Bogus[int] = _dummy, | |||
column: Bogus[int] = _dummy, | |||
is_ellipsis_args: Bogus[bool] = _dummy, | |||
implicit: Bogus[bool] = _dummy, | |||
special_sig: Bogus[Optional[str]] = _dummy, | |||
from_type_type: Bogus[bool] = _dummy, | |||
bound_args: Bogus[List[Optional[Type]]] = _dummy, | |||
def_extras: Bogus[Dict[str, Any]] = _dummy) -> 'CallableType': | |||
return CallableType( | |||
arg_types=arg_types if arg_types is not _dummy else self.arg_types, | |||
arg_kinds=arg_kinds if arg_kinds is not _dummy else self.arg_kinds, | |||
@@ -1457,8 +1458,9 @@ class TypeType(Type): | |||
# a generic class instance, a union, Any, a type variable... | |||
item = None # type: Type | |||
|
|||
def __init__(self, item: Union[Instance, AnyType, TypeVarType, TupleType, NoneTyp, | |||
CallableType], *, line: int = -1, column: int = -1) -> None: | |||
def __init__(self, item: Bogus[Union[Instance, AnyType, TypeVarType, TupleType, NoneTyp, | |||
CallableType]], *, | |||
line: int = -1, column: int = -1) -> None: | |||
ilevkivskyi
Collaborator
|
|||
"""To ensure Type[Union[A, B]] is always represented as Union[Type[A], Type[B]], item of | |||
type UnionType must be handled through make_normalized static method. | |||
""" | |||
@@ -0,0 +1,15 @@ | |||
[mypy] | |||
disallow_untyped_defs = True | |||
disallow_subclassing_any = True | |||
warn_no_return = True | |||
strict_optional = True | |||
no_implicit_optional = True | |||
disallow_any_generics = True | |||
disallow_any_unimported = True | |||
warn_redundant_casts = True | |||
warn_unused_configs = True | |||
always_true = SUPPRESS_BOGUS_TYPES | |||
|
|||
# needs py2 compatibility | |||
[mypy-mypy.test.testextensions] | |||
disallow_untyped_defs = False |
runtype -> runtime?