Skip to content

Commit d0eb22d

Browse files
authored
Blow away IsSubsimilar (#79)
The view seems to be that the real thing needs to be full python typing assignability, and the runtime will just need to do some the best it can. I merged some code from issubsimilar back into issubtype
1 parent 27ca663 commit d0eb22d

8 files changed

Lines changed: 41 additions & 193 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Computed Types in Python
22

3-
See [pep.rst](pep.rst) for the PEP draft and [design-qs.rst](design-qs.rst) for some design discussion not yet merged into the PEP.
3+
See [pep.rst](pep.rst) for the PEP draft.
44

55
## Development
66

design-qs.rst

Lines changed: 0 additions & 46 deletions
This file was deleted.

tests/test_type_eval.py

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@
3333
GetSpecialAttr,
3434
GetType,
3535
GetAnnotations,
36-
IsSubtype,
3736
IsSub,
3837
Iter,
3938
Length,
@@ -1408,16 +1407,6 @@ def test_eval_bool_literal_07():
14081407
d = eval_typing(IsSub[Literal[False], _BoolLiteral[False]])
14091408
assert d == _BoolLiteral[True]
14101409

1411-
d = eval_typing(IsSubtype[_BoolLiteral[True], Literal[True]])
1412-
assert d == _BoolLiteral[True]
1413-
d = eval_typing(IsSubtype[_BoolLiteral[False], Literal[False]])
1414-
assert d == _BoolLiteral[True]
1415-
1416-
d = eval_typing(IsSubtype[Literal[True], _BoolLiteral[True]])
1417-
assert d == _BoolLiteral[True]
1418-
d = eval_typing(IsSubtype[Literal[False], _BoolLiteral[False]])
1419-
assert d == _BoolLiteral[True]
1420-
14211410
d = eval_typing(Matches[_BoolLiteral[True], Literal[True]])
14221411
assert d == _BoolLiteral[True]
14231412
d = eval_typing(Matches[_BoolLiteral[False], Literal[False]])

typemap/type_eval/__init__.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
# XXX: this needs to go second due to nasty circularity -- try to fix that!!
1010
from ._eval_call import eval_call, eval_call_with_types
1111
from ._subtype import issubtype
12-
from ._subsim import issubsimilar
1312

1413
# This one is imported for registering handlers
1514
from . import _eval_operators # noqa
@@ -24,7 +23,6 @@
2423
"eval_call_with_types",
2524
"flatten_class",
2625
"issubtype",
27-
"issubsimilar",
2826
"TypeMapError",
2927
"_EvalProxy",
3028
"_get_current_context",

typemap/type_eval/_eval_operators.py

Lines changed: 8 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,7 @@
2929
GetMemberType,
3030
GetSpecialAttr,
3131
InitField,
32-
IsSubSimilar,
33-
IsSubtype,
32+
IsSub,
3433
Iter,
3534
Length,
3635
Lowercase,
@@ -236,23 +235,17 @@ def _eval_Iter(tp, *, ctx):
236235
# N.B: These handle unions on their own
237236

238237

239-
@type_eval.register_evaluator(IsSubtype)
238+
@type_eval.register_evaluator(IsSub)
240239
@_lift_evaluated
241-
def _eval_IsSubtype(lhs, rhs, *, ctx):
240+
def _eval_IsSub(lhs, rhs, *, ctx):
242241
return _BoolLiteral[type_eval.issubtype(lhs, rhs)]
243242

244243

245-
@type_eval.register_evaluator(IsSubSimilar)
246-
@_lift_evaluated
247-
def _eval_IsSubSimilar(lhs, rhs, *, ctx):
248-
return _BoolLiteral[type_eval.issubsimilar(lhs, rhs)]
249-
250-
251244
@type_eval.register_evaluator(Matches)
252245
@_lift_evaluated
253246
def _eval_Matches(lhs, rhs, *, ctx):
254247
return _BoolLiteral[
255-
type_eval.issubsimilar(lhs, rhs) and type_eval.issubsimilar(rhs, lhs)
248+
type_eval.issubtype(lhs, rhs) and type_eval.issubtype(rhs, lhs)
256249
]
257250

258251

@@ -262,8 +255,8 @@ def _eval_bool_tp(tp, ctx):
262255
else:
263256
return _BoolLiteral[
264257
any(
265-
type_eval.issubsimilar(arg, typing.Literal[True])
266-
and not type_eval.issubsimilar(arg, typing.Never)
258+
type_eval.issubtype(arg, typing.Literal[True])
259+
and not type_eval.issubtype(arg, typing.Never)
267260
for arg in _union_elems(tp, ctx)
268261
)
269262
]
@@ -1032,7 +1025,7 @@ def _eval_RaiseError(msg, *extra_types, ctx):
10321025

10331026
def _add_quals(typ, quals):
10341027
for qual in (typing.ClassVar, typing.Final):
1035-
if type_eval.issubsimilar(typing.Literal[qual.__name__], quals):
1028+
if type_eval.issubtype(typing.Literal[qual.__name__], quals):
10361029
typ = qual[typ]
10371030
return typ
10381031

@@ -1079,7 +1072,7 @@ def _eval_NewProtocol(*etyps: Member, ctx):
10791072
typ = _eval_types(typ, ctx)
10801073
tquals = _eval_types(quals, ctx)
10811074

1082-
if type_eval.issubsimilar(
1075+
if type_eval.issubtype(
10831076
typing.Literal["ClassVar"], tquals
10841077
) and _is_method_like(typ):
10851078
dct[name] = _callable_type_to_method(name, typ)

typemap/type_eval/_subsim.py

Lines changed: 0 additions & 94 deletions
This file was deleted.

typemap/type_eval/_subtype.py

Lines changed: 31 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,3 @@
1-
# XXX: This is the start of an implementation of issubtype, but
2-
# honestly it is still mostly the same as issubsimilar. I'm preserving
3-
# it for now and might still expand it some.
4-
# Largely the value of it is in the TODO comments I guess.
5-
6-
71
import typing
82

93

@@ -15,14 +9,24 @@
159

1610
def issubtype(lhs: typing.Any, rhs: typing.Any) -> bool:
1711
# TODO: Need to handle a lot of cases!
12+
# This is explicitly "best-effort", though.
1813

1914
# TODO: We will probably need to carry a context around,
2015
# and maybe recursively invoke eval_typing?
2116

2217
# N.B: All of the 'bool's in these are because black otherwise
2318
# formats the two-conditional chains in an unconscionably bad way.
2419

20+
if lhs is None:
21+
lhs = type(None)
22+
if rhs is None:
23+
rhs = type(None)
24+
2525
# Unions first
26+
if lhs is typing.Never:
27+
return True
28+
elif rhs is typing.Never:
29+
return False
2630
if _typing_inspect.is_union_type(rhs):
2731
return any(issubtype(lhs, r) for r in typing.get_args(rhs))
2832
elif _typing_inspect.is_union_type(lhs):
@@ -43,11 +47,11 @@ def issubtype(lhs: typing.Any, rhs: typing.Any) -> bool:
4347
return issubclass(lhs, rhs)
4448

4549
# literal <:? literal
46-
elif bool(
47-
_typing_inspect.is_literal(lhs) and _typing_inspect.is_literal(rhs)
48-
):
49-
rhs_args = set(typing.get_args(rhs))
50-
return all(lv in rhs_args for lv in typing.get_args(lhs))
50+
elif _typing_inspect.is_literal(lhs) and _typing_inspect.is_literal(rhs):
51+
# We need to check both value and type, since True == 1 but
52+
# Literal[True] should not be a subtype of Literal[1]
53+
rhs_args = {(t, type(t)) for t in typing.get_args(rhs)}
54+
return all((lv, type(lv)) in rhs_args for lv in typing.get_args(lhs))
5155

5256
# XXX: This case is kind of a hack, to support NoLiterals.
5357
elif rhs is typing.Literal:
@@ -71,14 +75,23 @@ def issubtype(lhs: typing.Any, rhs: typing.Any) -> bool:
7175
):
7276
return issubtype(lhs, _typing_inspect.get_origin(rhs))
7377

78+
# C[A] <:? D[B] -- just match the heads!
79+
# Super wrong!
80+
# TODO: What to do about C[A] <:? D[B]???
81+
# TODO: and we will we need to infer variance ourselves with the new syntax
82+
elif bool(
83+
_typing_inspect.is_generic_alias(lhs)
84+
and _typing_inspect.is_generic_alias(rhs)
85+
):
86+
return issubtype(
87+
_typing_inspect.get_origin(lhs), _typing_inspect.get_origin(rhs)
88+
)
89+
7490
# XXX: I think this is probably wrong, but a test currently has
7591
# an unbound type variable...
7692
elif _typing_inspect.is_type_var(lhs):
7793
return lhs is rhs
7894

79-
# TODO: What to do about C[A] <:? D[B]???
80-
# TODO: and we will we need to infer variance ourselves with the new syntax
81-
8295
# TODO: Protocols???
8396

8497
# TODO: tuple
@@ -97,4 +110,7 @@ def issubtype(lhs: typing.Any, rhs: typing.Any) -> bool:
97110
# We could have restrictions if we are willing to document them.
98111

99112
# This will probably fail
100-
return issubclass(lhs, rhs)
113+
try:
114+
return issubclass(lhs, rhs)
115+
except TypeError as e:
116+
raise TypeError(*e.args, lhs, rhs)

typemap/typing.py

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -280,12 +280,7 @@ def __bool__(self):
280280

281281

282282
@_SpecialForm
283-
def IsSubtype(self, tps):
284-
return _BoolGenericAlias(self, tps)
285-
286-
287-
@_SpecialForm
288-
def IsSubSimilar(self, tps):
283+
def IsSub(self, tps):
289284
return _BoolGenericAlias(self, tps)
290285

291286

@@ -294,9 +289,6 @@ def Matches(self, tps):
294289
return _BoolGenericAlias(self, tps)
295290

296291

297-
IsSub = IsSubSimilar
298-
299-
300292
@_SpecialForm
301293
def Bool(self, tp):
302294
return _BoolGenericAlias(self, tp)

0 commit comments

Comments
 (0)