Skip to content

Commit d93c207

Browse files
committed
fix: include bytes as sequence and fix test
1 parent 8d22abf commit d93c207

File tree

6 files changed

+90
-7
lines changed

6 files changed

+90
-7
lines changed

mypyc/ir/rtypes.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -628,7 +628,10 @@ def is_range_rprimitive(rtype: RType) -> bool:
628628

629629
def is_sequence_rprimitive(rtype: RType) -> bool:
630630
return isinstance(rtype, RPrimitive) and (
631-
is_list_rprimitive(rtype) or is_tuple_rprimitive(rtype) or is_str_rprimitive(rtype)
631+
is_list_rprimitive(rtype)
632+
or is_tuple_rprimitive(rtype)
633+
or is_str_rprimitive(rtype)
634+
or is_bytes_rprimitive(rtype)
632635
)
633636

634637

mypyc/irbuild/builder.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,7 @@
9191
RType,
9292
RUnion,
9393
bitmap_rprimitive,
94+
bytes_rprimitive,
9495
c_pyssize_t_rprimitive,
9596
dict_rprimitive,
9697
int_rprimitive,
@@ -950,8 +951,12 @@ def get_sequence_type_from_type(self, target_type: Type) -> RType:
950951
elif isinstance(target_type, Instance):
951952
if target_type.type.fullname == "builtins.str":
952953
return str_rprimitive
953-
else:
954+
elif target_type.type.fullname == "builtins.bytes":
955+
return bytes_rprimitive
956+
try:
954957
return self.type_to_rtype(target_type.args[0])
958+
except IndexError:
959+
raise ValueError(f"{target_type!r} is not a valid sequence.") from None
955960
# This elif-blocks are needed for iterating over classes derived from NamedTuple.
956961
elif isinstance(target_type, TypeVarLikeType):
957962
return self.get_sequence_type_from_type(target_type.upper_bound)

mypyc/irbuild/for_helpers.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -207,9 +207,9 @@ def sequence_from_generator_preallocate_helper(
207207
there is no condition list in the generator and only one original sequence with
208208
one index is allowed.
209209
210-
e.g. (1) tuple(f(x) for x in a_list/a_tuple)
211-
(2) list(f(x) for x in a_list/a_tuple)
212-
(3) [f(x) for x in a_list/a_tuple]
210+
e.g. (1) tuple(f(x) for x in a_list/a_tuple/a_str/a_bytes)
211+
(2) list(f(x) for x in a_list/a_tuple/a_str/a_bytes)
212+
(3) [f(x) for x in a_list/a_tuple/a_str/a_bytes]
213213
RTuple as an original sequence is not supported yet.
214214
215215
Args:
@@ -226,7 +226,7 @@ def sequence_from_generator_preallocate_helper(
226226
"""
227227
if len(gen.sequences) == 1 and len(gen.indices) == 1 and len(gen.condlists[0]) == 0:
228228
rtype = builder.node_type(gen.sequences[0])
229-
if is_list_rprimitive(rtype) or is_tuple_rprimitive(rtype) or is_str_rprimitive(rtype):
229+
if is_sequence_rprimitive(rtype):
230230
sequence = builder.accept(gen.sequences[0])
231231
length = builder.builder.builtin_len(sequence, gen.line, use_pyssize_t=True)
232232
target_op = empty_op_llbuilder(length, gen.line)

mypyc/irbuild/specialize.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -288,7 +288,7 @@ def translate_tuple_from_generator_call(
288288
"""Special case for simplest tuple creation from a generator.
289289
290290
For example:
291-
tuple(f(x) for x in some_list/some_tuple/some_str)
291+
tuple(f(x) for x in some_list/some_tuple/some_str/some_bytes)
292292
'translate_safe_generator_call()' would take care of other cases
293293
if this fails.
294294
"""

mypyc/test-data/fixtures/tuple.pyi

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
from typing import Iterator
2+
3+
class bytes:
4+
def __iter__(self) -> Iterator[int]: pass
5+
class dict: pass
6+
class int:
7+
def __add__(self, other: int) -> int: pass
8+
class str: pass
9+
class tuple: pass

mypyc/test-data/irbuild-tuple.test

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -323,6 +323,72 @@ L4:
323323
a = r3
324324
return 1
325325

326+
[case testTupleBuiltFromBytes]
327+
def f2(val: int) -> int:
328+
return val + 2
329+
330+
def test() -> None:
331+
source = b"abc"
332+
a = tuple(f2(x) for x in source)
333+
334+
[builtins fixtures/tuple.pyi]
335+
[out]
336+
def f2(val):
337+
val, r0 :: int
338+
L0:
339+
r0 = CPyTagged_Add(val, 4)
340+
return r0
341+
def test():
342+
r0, source :: bytes
343+
r1 :: native_int
344+
r2 :: tuple
345+
r3, r4 :: native_int
346+
r5, r6, r7 :: bit
347+
r8, r9, r10, r11 :: int
348+
r12 :: object
349+
r13, x, r14 :: int
350+
r15 :: object
351+
r16 :: native_int
352+
a :: object
353+
L0:
354+
r0 = b'abc'
355+
source = r0
356+
r1 = var_object_size source
357+
r2 = PyTuple_New(r1)
358+
r3 = var_object_size source
359+
r4 = 0
360+
L1:
361+
r5 = r4 < r3 :: signed
362+
if r5 goto L2 else goto L8 :: bool
363+
L2:
364+
r6 = r4 <= 4611686018427387903 :: signed
365+
if r6 goto L3 else goto L4 :: bool
366+
L3:
367+
r7 = r4 >= -4611686018427387904 :: signed
368+
if r7 goto L5 else goto L4 :: bool
369+
L4:
370+
r8 = CPyTagged_FromInt64(r4)
371+
r9 = r8
372+
goto L6
373+
L5:
374+
r10 = r4 << 1
375+
r9 = r10
376+
L6:
377+
r11 = CPyBytes_GetItem(source, r9)
378+
r12 = box(int, r11)
379+
r13 = unbox(int, r12)
380+
x = r13
381+
r14 = f2(x)
382+
r15 = box(int, r14)
383+
CPySequenceTuple_SetItemUnsafe(r2, r4, r15)
384+
L7:
385+
r16 = r4 + 1
386+
r4 = r16
387+
goto L1
388+
L8:
389+
a = r2
390+
return 1
391+
326392
[case testTupleBuiltFromVariableLengthTuple]
327393
from typing import Tuple
328394

0 commit comments

Comments
 (0)