Skip to content

Commit 2fd7b07

Browse files
authored
Add Slice (#59)
And replace `StrSlice`.
1 parent e2bebc5 commit 2fd7b07

3 files changed

Lines changed: 63 additions & 9 deletions

File tree

tests/test_type_eval.py

Lines changed: 40 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@
3939
Members,
4040
NewProtocol,
4141
Param,
42+
Slice,
4243
SpecialFormEllipsis,
4344
StrConcat,
44-
StrSlice,
4545
Uppercase,
4646
_BoolLiteral,
4747
)
@@ -245,12 +245,12 @@ def test_type_strings_4():
245245

246246

247247
def test_type_strings_5():
248-
d = eval_typing(StrSlice[Literal["abcd"], Literal[0], Literal[1]])
248+
d = eval_typing(Slice[Literal["abcd"], Literal[0], Literal[1]])
249249
assert d == Literal["a"]
250250

251251

252252
def test_type_strings_6():
253-
d = eval_typing(StrSlice[Literal["abcd"], Literal[1], Literal[None]])
253+
d = eval_typing(Slice[Literal["abcd"], Literal[1], Literal[None]])
254254
assert d == Literal["bcd"]
255255

256256

@@ -1492,6 +1492,43 @@ def test_eval_length_01():
14921492
assert d == Literal[None]
14931493

14941494

1495+
def test_eval_slice_01():
1496+
t = tuple[Literal[0], Literal[1], Literal[2], Literal[3], Literal[4]]
1497+
d = eval_typing(Slice[t, Literal[1], Literal[3]])
1498+
assert d == tuple[Literal[1], Literal[2]]
1499+
d = eval_typing(Slice[t, Literal[1], Literal[None]])
1500+
assert d == tuple[Literal[1], Literal[2], Literal[3], Literal[4]]
1501+
d = eval_typing(Slice[t, Literal[None], Literal[3]])
1502+
assert d == tuple[Literal[0], Literal[1], Literal[2]]
1503+
d = eval_typing(Slice[t, Literal[None], Literal[None]])
1504+
assert (
1505+
d == tuple[Literal[0], Literal[1], Literal[2], Literal[3], Literal[4]]
1506+
)
1507+
d = eval_typing(Slice[t, Literal[1], Literal[1]])
1508+
assert d == tuple[()]
1509+
1510+
1511+
def test_eval_slice_02():
1512+
t = Literal["abcde"]
1513+
d = eval_typing(Slice[t, Literal[1], Literal[3]])
1514+
assert d == Literal["bc"]
1515+
d = eval_typing(Slice[t, Literal[1], Literal[None]])
1516+
assert d == Literal["bcde"]
1517+
d = eval_typing(Slice[t, Literal[None], Literal[3]])
1518+
assert d == Literal["abc"]
1519+
d = eval_typing(Slice[t, Literal[None], Literal[None]])
1520+
assert d == Literal["abcde"]
1521+
d = eval_typing(Slice[t, Literal[1], Literal[1]])
1522+
assert d == Literal[""]
1523+
1524+
1525+
def test_eval_slice_03():
1526+
d = eval_typing(Slice[int, Literal[1], Literal[2]])
1527+
assert d == Never
1528+
d = eval_typing(Slice[dict[int, str], Literal[1], Literal[2]])
1529+
assert d == Never
1530+
1531+
14951532
def test_eval_literal_idempotent_01():
14961533
t = Literal[int]
14971534
for _ in range(5):

typemap/type_eval/_eval_operators.py

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,9 @@
3939
Members,
4040
NewProtocol,
4141
Param,
42+
Slice,
4243
SpecialFormEllipsis,
4344
StrConcat,
44-
StrSlice,
4545
Uncapitalize,
4646
Uppercase,
4747
_BoolLiteral,
@@ -955,6 +955,24 @@ def _eval_Length(tp, *, ctx) -> typing.Any:
955955
raise TypeError(f"Invalid type argument to Length: {tp} is not a tuple")
956956

957957

958+
@type_eval.register_evaluator(Slice)
959+
@_lift_over_unions
960+
def _eval_Slice(tp, start, end, *, ctx):
961+
tp = _eval_types(tp, ctx)
962+
start = _eval_literal(start, ctx)
963+
end = _eval_literal(end, ctx)
964+
if _typing_inspect.is_generic_alias(tp) and tp.__origin__ is tuple:
965+
return tp.__origin__[tp.__args__[start:end]]
966+
elif (
967+
_typing_inspect.is_generic_alias(tp)
968+
and tp.__origin__ is typing.Literal
969+
and isinstance(tp.__args__[0], str)
970+
):
971+
return tp.__origin__[tp.__args__[0][start:end]]
972+
else:
973+
return typing.Never
974+
975+
958976
# String literals
959977

960978

@@ -971,7 +989,6 @@ def func(*args, ctx):
971989
_string_literal_op(Capitalize, op=str.capitalize)
972990
_string_literal_op(Uncapitalize, op=lambda s: s[0:1].lower() + s[1:])
973991
_string_literal_op(StrConcat, op=lambda s, t: s + t)
974-
_string_literal_op(StrSlice, op=lambda s, start, end: s[start:end])
975992

976993

977994
##################################################################

typemap/typing.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,10 @@ class Length[S: tuple]:
147147
pass
148148

149149

150+
class Slice[S: str | tuple, Start: int | None, End: int | None]:
151+
pass
152+
153+
150154
class Uppercase[S: str]:
151155
pass
152156

@@ -167,10 +171,6 @@ class StrConcat[S: str, T: str]:
167171
pass
168172

169173

170-
class StrSlice[S: str, Start: int | None, End: int | None]:
171-
pass
172-
173-
174174
class NewProtocol[*T]:
175175
pass
176176

0 commit comments

Comments
 (0)