8000 Alternative implementation of PEP 673 by Gobot1234 · Pull Request #13133 · python/mypy · GitHub
[go: up one dir, main page]

Skip to content

Alternative implementation of PEP 673 #13133

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 43 commits into from
Closed
Show file tree
Hide file tree
Changes from 1 commit
Commits
Show all changes
43 commits
Select commit Hold shift + click to select a range
83a7597
3rd times the charm
Gobot1234 Jul 15, 2022
3278f5f
Remove debug print
Gobot1234 Jul 15, 2022
fe0eea7
Fix CI
Gobot1234 Jul 17, 2022
7f5f286
Remove calls to inspect.stack()
Gobot1234 Jul 17, 2022
05ac624
Merge branch 'master' into piggybacking-TypeVar
Gobot1234 Jul 21, 2022
76f216a
Fix passing an instance as a SelfType
Gobot1234 Jul 30, 2022
e344a12
Merge branch 'piggybacking-TypeVar' of https://github.com/Gobot1234/m…
Gobot1234 Jul 30, 2022
708057d
Merge branch 'master' into piggybacking-TypeVar
Gobot1234 Jul 30, 2022
d8c02db
Fix CI
Gobot1234 Jul 30, 2022
3159549
Fix joining for obj if bool else self
Gobot1234 Aug 1, 2022
f031af7
Fix accessing an instance on cls
Gobot1234 Aug 1, 2022
ab62d93
Fix joining the other way round
Gobot1234 Aug 1, 2022
823168b
Show the name that's not found
Gobot1234 Aug 1, 2022
7ef77c7
Merge branch 'master' into piggybacking-TypeVar
8000 Gobot1234 Aug 8, 2022
c8e9407
I have no clue what's going on here
Gobot1234 Aug 8, 2022
39c208d
So it's fine in modules but the name just isn't present???
Gobot1234 Aug 8, 2022
f05cfec
I'm just going to leave it and construct the Instance myself
Gobot1234 Aug 8, 2022
4a2b2b6
Merge branch 'master' into piggybacking-TypeVar
Gobot1234 Aug 11, 2022
6e16093
Fix a bit of CI
Gobot1234 Aug 11, 2022
0c5c26f
Fix more CI
Gobot1234 Aug 11, 2022
6f29a2f
Fix constraints
Gobot1234 Aug 13, 2022
fb1b479
Merge branch 'master' into piggybacking-TypeVar
Gobot1234 Aug 13, 2022
379c662
Fix bug with typeddict narrowing
Gobot1234 Aug 15, 2022
af3241c
Run black
Gobot1234 Aug 15, 2022
dc93feb
Fix flake8 warnings
Gobot1234 Aug 15, 2022
e01690b
More typeddict fixes
Gobot1234 Aug 15, 2022
87a4cdf
Fix more CI issues
Gobot1234 Aug 30, 2022
a1257d1
Merge branch 'master-up' into piggybacking-TypeVar
Gobot1234 Aug 30, 2022
93a96ff
Avoid printing Self in signatures
Gobot1234 Sep 11, 2022
1ede281
fix more tests
Gobot1234 Sep 13, 2022
2f02d13
Fix attribute error message for TypeVars
Gobot1234 Sep 13, 2022
bf54da0
Fix more reprs
Gobot1234 Sep 16, 2022
2be7770
Fix more CI
Gobot1234 Sep 17, 2022
cf6ac9b
Fix some tests
Gobot1234 Sep 19, 2022
904fcb2
Merge branch 'master-up' into piggybacking-TypeVar
Gobot1234 Sep 25, 2022
c657875
Fix some more failing CI
Gobot1234 Sep 25, 2022
e226e14
Fix more CI
Gobot1234 Sep 27, 2022
1495df0
Merge branch 'master' into piggybacking-TypeVar
Gobot1234 Sep 30, 2022
74feea6
Fix more more CI
Gobot1234 Oct 2, 2022
91e139d
Merge branch 'piggybacking-TypeVar' of https://github.com/Gobot1234/m…
Gobot1234 Oct 2, 2022
15924b2
Fix more tests
Gobot1234 Oct 23, 2022
7f125e9
Fix more tests
Gobot1234 Oct 27, 2022
8e60528
Fix more tests
Gobot1234 Nov 6, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next 8000 Next commit
Fix CI
  • Loading branch information
Gobot1234 committed Jul 17, 2022
commit fe0eea78ff32dea526f41e6efa47d8a49f17858c
39 changes: 12 additions & 27 deletions mypy/semanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -712,18 +712,17 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None:

leading_type = func.type.arg_types[0]
proper_leading_type = get_proper_type(leading_type)
if isinstance(proper_leading_type, Instance): # method[[Self, ...], Self] case
if isinstance(proper_leading_type, Instance): # method[[Instance, ...], Any] case
proper_leading_type = self_type_type = SelfType("Self", proper_leading_type)
func.type = replace_implicit_first_type(func.type, proper_leading_type)
func.type.variables = [self_type_type, *func.type.variables]
elif (
isinstance(proper_leading_type, TypeType) and isinstance(proper_leading_type.item, Instance)
): # classmethod[[type[Self], ...], Self] case
): # classmethod[[type[Instance], ...], Any] case
self_type_type = SelfType("Self", proper_leading_type.item)
proper_leading_type = self.class_type(self_type_type)
func.type = replace_implicit_first_type(func.type, proper_leading_type)
elif self.is_self_type(proper_leading_type):
func.type.variables = [self_type_type, *func.type.variables]
elif self.is_self_type(proper_leading_type): # method[[Self, ...], Self] case
proper_leading_type = self_type_type = SelfType("Self", self.named_type(info.fullname))
func.type = replace_implicit_first_type(func.type, proper_leading_type)
elif isinstance(proper_leading_type, UnboundType):
# classmethod[[type[Self], ...], Self] case
node = self.lookup(proper_leading_type.name, func)
Expand All @@ -735,21 +734,15 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None:
):
self_type_type = SelfType("Self", self.named_type(info.fullname))
proper_leading_type = self.class_type(self_type_type)
func.type = replace_implicit_first_type(func.type, proper_leading_type)
else:
return
else:
return
func.type = replace_implicit_first_type(func.type, proper_leading_type)

# bind any SelfTypes in args and return types
# bind any SelfTypes in args and return types
for idx, arg in enumerate(func.type.arg_types):
if self.is_self_type(arg):
if func.is_static:
self.fail(
"Self-type annotations of staticmethods are not supported, "
"please replace the type with {}".format(self_type.type.name),
func
)
func.type.arg_types[idx] = self.named_type(
self_type.type.name
) # we replace them here for them
continue
if self_type_type.fullname == self_type_type.name:
assert isinstance(arg, UnboundType)
table_node = self.lookup(arg.name, func)
Expand All @@ -765,14 +758,6 @@ def prepare_method_signature(self, func: FuncDef, info: TypeInfo) -> None:
)
assert isinstance(table_node, SymbolTableNode) and table_node.node
self_type_type.fullname = table_node.node.fullname
if func.is_static:
self.fail(
"Self-type annotations of staticmethods are not supported, "
"please replace the type with {}".format(self_type.type.name),
func,
)
func.type.ret_type = self.named_type(self_type.type.name)
return
func.type.ret_type = self_type_type

def set_original_def(self, previous: Optional[Node], new: Union[FuncDef, Decorator]) -> bool:
Expand Down Expand Up @@ -5607,7 +5592,7 @@ def has_placeholder(typ: Type) -> bool:
return typ.accept(HasPlaceholders())


FunctionLikeT = TypeVar("FunctionLikeT", bound=FunctionLike)
FunctionLikeT = TypeVar("FunctionLikeT", CallableType, Overloaded)


def replace_implicit_first_type(sig: FunctionLikeT, new: Type) -> FunctionLikeT:
Expand Down
2 changes: 2 additions & 0 deletions mypy/subtypes.py
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,8 @@ def visit_instance(self, left: Instance) -> bool:
return False

def visit_type_var(self, left: TypeVarType) -> bool:
if isinstance(left, SelfType):
return self.visit_self_type(left)
right = self.right
if isinstance(right, TypeVarType) and left.id == right.id:
return True
Expand Down
17 changes: 11 additions & 6 deletions mypy/typeanal.py
Original file line number Diff line number Diff line change
Expand Up @@ -1143,11 +1143,16 @@ def bind_function_type_variables(
"""Find the type variables of the function type and bind them in our tvar_scope"""
if fun_type.variables:
for var in fun_type.variables:
var_node = self.lookup_qualified(var.name, defn)
assert var_node, "Binding for function type variable not found within function"
var_expr = var_node.node
assert isinstance(var_expr, TypeVarLikeExpr)
self.tvar_scope.bind_new(var.name, var_expr)
if not isinstance(var, SelfType):
var_node = self.lookup_qualified(var.name, defn)
assert var_node, "Binding for function type variable not found within function"
var_expr = var_node.node
# if isinstance(var_expr, Var) and var_expr.fullname in SELF_TYPE_NAMES:
# var_expr = TypeVarExpr("Self", var_expr.fullname, [], var.upper_bound)
assert isinstance(var_expr, TypeVarLikeExpr)
self.tvar_scope.bind_new(var.name, var_expr)
else:
self.tvar_scope.bind_existing(var)
return fun_type.variables
typevars = self.infer_type_variables(fun_type)
# Do not define a new type variable if already defined in scope.
Expand Down Expand Up @@ -1209,7 +1214,7 @@ def anal_type(self, t: Type, nested: bool = True, *, allow_param_spec: bool = Fa
return analyzed

def anal_var_def(self, var_def: TypeVarLikeType) -> TypeVarLikeType:
if isinstance(var_def, TypeVarType):
if isinstance(var_def, TypeVarType) and not isinstance(var_def, SelfType):
return TypeVarType(
var_def.name,
var_def.fullname,
Expand Down
40 changes: 25 additions & 15 deletions mypy/types.py
8000
Original file line number Diff line number Diff line change
Expand Up @@ -500,7 +500,7 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarLikeType':
class TypeVarType(TypeVarLikeType):
"""Type that refers to a type variable."""

__slots__ = ('values', 'variance')
__slots__ = ('values', 'variance', 'stack')

values: List[Type] # Value restriction, empty list if no restriction
variance: int
Expand All @@ -512,6 +512,7 @@ def __init__(self, name: str, fullname: str, id: Union[TypeVarId, int], values:
assert values is not None, "No restrictions must be represented by empty list"
self.values = values
self.variance = variance
self.stack = inspect.stack()

@staticmethod
def new_unification_variable(old: 'TypeVarType') -> 'TypeVarType':
Expand Down Expand Up @@ -555,21 +556,26 @@ def deserialize(cls, data: JsonDict) -> 'TypeVarType':
)


SELF_ID = TypeVarId(0.5) # type: ignore
# this is a hack cause I need a way to represent a number that's constant and can't be +ve or -ve
# and using TypeVarId.new() would quickly hit a huge number which is harder to read.


class SelfType(TypeVarType):
__slots__ = ()
upper_bound: 'Instance'

def __init__(self, fullname: str, upper_bound: 'Instance', line: int = -1, column: int = -1) -> None:
super().__init__(
"Self", fullname, -1, [], upper_bound, line=line, column=column
"Self",
fullname,
SELF_ID,
[],
upper_bound,
line=line,
column=column,
)

def accept(self, visitor: 'TypeVisitor[T]') -> T:
from mypy.subtypes import SubtypeVisitor
if isinstance(visitor, (TypeStrVisitor, SubtypeVisitor)):
return visitor.visit_self_type(self)
return super().accept(visitor)

def __hash__(self) -> int:
return hash(self.upper_bound)

Expand Down Expand Up @@ -1119,6 +1125,7 @@ def deserialize(cls, data: JsonDict) -> 'DeletedType':

# Fake TypeInfo to be used as a placeholder during Instance de-serialization.
NOT_READY: Final = mypy.nodes.FakeInfo("De-serialization failure: TypeInfo not fixed")
import inspect


class Instance(ProperType):
Expand Down Expand Up @@ -1152,12 +1159,13 @@ def try_getting_instance_fallback(typ: ProperType) -> Optional[Instance]:

"""

__slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value', '_hash')
__slots__ = ('type', 'args', 'invalid', 'type_ref', 'last_known_value', '_hash', 'stack')

def __init__(self, typ: mypy.nodes.TypeInfo, args: Sequence[Type],
line: int = -1, column: int = -1, *,
last_known_value: Optional['LiteralType'] = None) -> None:
super().__init__(line, column)
# self.stack = inspect.stack()
self.type = typ
self.args = tuple(args)
self.type_ref: Optional[str] = None
Expand Down Expand Up @@ -1516,6 +1524,7 @@ class CallableType(FunctionLike):
'type_guard', # T, if -> TypeGuard[T] (ret_type is bool in this case).
'from_concatenate', # whether this callable is from a concatenate object
# (this is used for error messages)
'stack',
)

def __init__(self,
Expand All @@ -1539,6 +1548,7 @@ def __init__(self,
type_guard: Optional[Type] = None,
from_concatenate: bool = False
) -> None:
self.stack = inspect.stack()
super().__init__(line, column)
assert len(arg_types) == len(arg_kinds) == len(arg_names)
if variables is None:
Expand Down Expand Up @@ -2614,12 +2624,10 @@ def get_proper_types(it: Iterable[Optional[Type]]
# to make it easier to gradually get modules working with mypyc.
# Import them here, after the types are defined.
# This is intended as a re-export also.
from mypy.type_visitor import ( # noqa
TypeVisitor as TypeVisitor,
SyntheticTypeVisitor as SyntheticTypeVisitor,
TypeTranslator as TypeTranslator,
TypeQuery as TypeQuery,
)
from mypy.type_visitor import SyntheticTypeVisitor as SyntheticTypeVisitor
from mypy.type_visitor import TypeQuery as TypeQuery
from mypy.type_visitor import TypeTranslator as TypeTranslator
from mypy.type_visitor import TypeVisitor as TypeVisitor # noqa


class TypeStrVisitor(SyntheticTypeVisitor[str]):
Expand Down Expand Up @@ -2693,6 +2701,8 @@ def visit_instance(self, t: Instance) -> str:
return s

def visit_type_var(self, t: TypeVarType) -> str:
if isinstance(t, SelfType):
return self.visit_self_type(t)
if t.name is None:
# Anonymous type variable type (only numeric id).
s = f'`{t.id}'
Expand Down
0