Skip to content

Commit ee09d9e

Browse files
builtins: Audit bytes arguments (#7631)
Most use the C buffer protocol, so _typeshed.ReadableBuffer is the right type. A few check specifically for bytes and bytearray.
1 parent 66bea8c commit ee09d9e

File tree

1 file changed

+74
-61
lines changed

1 file changed

+74
-61
lines changed

stdlib/builtins.pyi

Lines changed: 74 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -199,7 +199,7 @@ _NegativeInteger: TypeAlias = Literal[-1, -2, -3, -4, -5, -6, -7, -8, -9, -10, -
199199

200200
class int:
201201
@overload
202-
def __new__(cls: type[Self], __x: str | bytes | SupportsInt | SupportsIndex | SupportsTrunc = ...) -> Self: ...
202+
def __new__(cls: type[Self], __x: str | ReadableBuffer | SupportsInt | SupportsIndex | SupportsTrunc = ...) -> Self: ...
203203
@overload
204204
def __new__(cls: type[Self], __x: str | bytes | bytearray, base: SupportsIndex) -> Self: ...
205205
if sys.version_info >= (3, 8):
@@ -222,7 +222,7 @@ class int:
222222
@classmethod
223223
def from_bytes(
224224
cls: type[Self],
225-
bytes: Iterable[SupportsIndex] | SupportsBytes, # TODO buffer object argument
225+
bytes: Iterable[SupportsIndex] | SupportsBytes | ReadableBuffer,
226226
byteorder: Literal["little", "big"],
227227
*,
228228
signed: bool = ...,
@@ -288,7 +288,7 @@ class int:
288288
def __index__(self) -> int: ...
289289

290290
class float:
291-
def __new__(cls: type[Self], x: SupportsFloat | SupportsIndex | str | bytes | bytearray = ...) -> Self: ...
291+
def __new__(cls: type[Self], x: SupportsFloat | SupportsIndex | str | ReadableBuffer = ...) -> Self: ...
292292
def as_integer_ratio(self) -> tuple[int, int]: ...
293293
def hex(self) -> str: ...
294294
def is_integer(self) -> bool: ...
@@ -382,7 +382,7 @@ class str(Sequence[str]):
382382
@overload
383383
def __new__(cls: type[Self], object: object = ...) -> Self: ...
384384
@overload
385-
def __new__(cls: type[Self], object: bytes, encoding: str = ..., errors: str = ...) -> Self: ...
385+
def __new__(cls: type[Self], object: ReadableBuffer, encoding: str = ..., errors: str = ...) -> Self: ...
386386
def capitalize(self) -> str: ...
387387
def casefold(self) -> str: ...
388388
def center(self, __width: SupportsIndex, __fillchar: str = ...) -> str: ...
@@ -479,27 +479,30 @@ class bytes(ByteString):
479479
def capitalize(self) -> bytes: ...
480480
def center(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ...
481481
def count(
482-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
482+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
483483
) -> int: ...
484484
def decode(self, encoding: str = ..., errors: str = ...) -> str: ...
485485
def endswith(
486-
self, __suffix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
486+
self,
487+
__suffix: ReadableBuffer | tuple[ReadableBuffer, ...],
488+
__start: SupportsIndex | None = ...,
489+
__end: SupportsIndex | None = ...,
487490
) -> bool: ...
488491
if sys.version_info >= (3, 8):
489492
def expandtabs(self, tabsize: SupportsIndex = ...) -> bytes: ...
490493
else:
491494
def expandtabs(self, tabsize: int = ...) -> bytes: ...
492495

493496
def find(
494-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
497+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
495498
) -> int: ...
496499
if sys.version_info >= (3, 8):
497500
def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ...
498501
else:
499502
def hex(self) -> str: ...
500503

501504
def index(
502-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
505+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
503506
) -> int: ...
504507
def isalnum(self) -> bool: ...
505508
def isalpha(self) -> bool: ...
@@ -511,49 +514,52 @@ class bytes(ByteString):
511514
def isspace(self) -> bool: ...
512515
def istitle(self) -> bool: ...
513516
def isupper(self) -> bool: ...
514-
def join(self, __iterable_of_bytes: Iterable[ByteString | memoryview]) -> bytes: ...
515-
def ljust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ...
517+
def join(self, __iterable_of_bytes: Iterable[ReadableBuffer]) -> bytes: ...
518+
def ljust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytes: ...
516519
def lower(self) -> bytes: ...
517-
def lstrip(self, __bytes: bytes | None = ...) -> bytes: ...
518-
def partition(self, __sep: bytes) -> tuple[bytes, bytes, bytes]: ...
519-
def replace(self, __old: bytes, __new: bytes, __count: SupportsIndex = ...) -> bytes: ...
520+
def lstrip(self, __bytes: ReadableBuffer | None = ...) -> bytes: ...
521+
def partition(self, __sep: ReadableBuffer) -> tuple[bytes, bytes, bytes]: ...
522+
def replace(self, __old: ReadableBuffer, __new: ReadableBuffer, __count: SupportsIndex = ...) -> bytes: ...
520523
if sys.version_info >= (3, 9):
521-
def removeprefix(self, __prefix: bytes) -> bytes: ...
522-
def removesuffix(self, __suffix: bytes) -> bytes: ...
524+
def removeprefix(self, __prefix: ReadableBuffer) -> bytes: ...
525+
def removesuffix(self, __suffix: ReadableBuffer) -> bytes: ...
523526

524527
def rfind(
525-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
528+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
526529
) -> int: ...
527530
def rindex(
528-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
531+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
529532
) -> int: ...
530-
def rjust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytes: ...
531-
def rpartition(self, __sep: bytes) -> tuple[bytes, bytes, bytes]: ...
532-
def rsplit(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ...
533-
def rstrip(self, __bytes: bytes | None = ...) -> bytes: ...
534-
def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ...
533+
def rjust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytes: ...
534+
def rpartition(self, __sep: ReadableBuffer) -> tuple[bytes, bytes, bytes]: ...
535+
def rsplit(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ...
536+
def rstrip(self, __bytes: ReadableBuffer | None = ...) -> bytes: ...
537+
def split(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytes]: ...
535538
def splitlines(self, keepends: bool = ...) -> list[bytes]: ...
536539
def startswith(
537-
self, __prefix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
540+
self,
541+
__prefix: ReadableBuffer | tuple[ReadableBuffer, ...],
542+
__start: SupportsIndex | None = ...,
543+
__end: SupportsIndex | None = ...,
538544
) -> bool: ...
539-
def strip(self, __bytes: bytes | None = ...) -> bytes: ...
545+
def strip(self, __bytes: ReadableBuffer | None = ...) -> bytes: ...
540546
def swapcase(self) -> bytes: ...
541547
def title(self) -> bytes: ...
542-
def translate(self, __table: bytes | None, delete: bytes = ...) -> bytes: ...
548+
def translate(self, __table: ReadableBuffer | None, delete: bytes = ...) -> bytes: ...
543549
def upper(self) -> bytes: ...
544550
def zfill(self, __width: SupportsIndex) -> bytes: ...
545551
@classmethod
546552
def fromhex(cls: type[Self], __s: str) -> Self: ...
547553
@staticmethod
548-
def maketrans(__frm: bytes, __to: bytes) -> bytes: ...
554+
def maketrans(__frm: ReadableBuffer, __to: ReadableBuffer) -> bytes: ...
549555
def __len__(self) -> int: ...
550556
def __iter__(self) -> Iterator[int]: ...
551557
def __hash__(self) -> int: ...
552558
@overload
553559
def __getitem__(self, __i: SupportsIndex) -> int: ...
554560
@overload
555561
def __getitem__(self, __s: slice) -> bytes: ...
556-
def __add__(self, __s: bytes) -> bytes: ...
562+
def __add__(self, __s: ReadableBuffer) -> bytes: ...
557563
def __mul__(self, __n: SupportsIndex) -> bytes: ...
558564
def __rmul__(self, __n: SupportsIndex) -> bytes: ...
559565
def __mod__(self, __value: Any) -> bytes: ...
@@ -582,12 +588,15 @@ class bytearray(MutableSequence[int], ByteString):
582588
def capitalize(self) -> bytearray: ...
583589
def center(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ...
584590
def count(
585-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
591+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
586592
) -> int: ...
587593
def copy(self) -> bytearray: ...
588594
def decode(self, encoding: str = ..., errors: str = ...) -> str: ...
589595
def endswith(
590-
self, __suffix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
596+
self,
597+
__suffix: ReadableBuffer | tuple[ReadableBuffer, ...],
598+
__start: SupportsIndex | None = ...,
599+
__end: SupportsIndex | None = ...,
591600
) -> bool: ...
592601
if sys.version_info >= (3, 8):
593602
def expandtabs(self, tabsize: SupportsIndex = ...) -> bytearray: ...
@@ -596,15 +605,15 @@ class bytearray(MutableSequence[int], ByteString):
596605

597606
def extend(self, __iterable_of_ints: Iterable[SupportsIndex]) -> None: ...
598607
def find(
599-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
608+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
600609
) -> int: ...
601610
if sys.version_info >= (3, 8):
602611
def hex(self, sep: str | bytes = ..., bytes_per_sep: SupportsIndex = ...) -> str: ...
603612
else:
604613
def hex(self) -> str: ...
605614

606615
def index(
607-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
616+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
608617
) -> int: ...
609618
def insert(self, __index: SupportsIndex, __item: SupportsIndex) -> None: ...
610619
def isalnum(self) -> bool: ...
@@ -617,43 +626,46 @@ class bytearray(MutableSequence[int], ByteString):
617626
def isspace(self) -> bool: ...
618627
def istitle(self) -> bool: ...
619628
def isupper(self) -> bool: ...
620-
def join(self, __iterable_of_bytes: Iterable[ByteString | memoryview]) -> bytearray: ...
621-
def ljust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ...
629+
def join(self, __iterable_of_bytes: Iterable[ReadableBuffer]) -> bytearray: ...
630+
def ljust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytearray: ...
622631
def lower(self) -> bytearray: ...
623-
def lstrip(self, __bytes: bytes | None = ...) -> bytearray: ...
624-
def partition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ...
632+
def lstrip(self, __bytes: ReadableBuffer | None = ...) -> bytearray: ...
633+
def partition(self, __sep: ReadableBuffer) -> tuple[bytearray, bytearray, bytearray]: ...
625634
def pop(self, __index: int = ...) -> int: ...
626635
def remove(self, __value: int) -> None: ...
627636
if sys.version_info >= (3, 9):
628-
def removeprefix(self, __prefix: bytes) -> bytearray: ...
629-
def removesuffix(self, __suffix: bytes) -> bytearray: ...
637+
def removeprefix(self, __prefix: ReadableBuffer) -> bytearray: ...
638+
def removesuffix(self, __suffix: ReadableBuffer) -> bytearray: ...
630639

631-
def replace(self, __old: bytes, __new: bytes, __count: SupportsIndex = ...) -> bytearray: ...
640+
def replace(self, __old: ReadableBuffer, __new: ReadableBuffer, __count: SupportsIndex = ...) -> bytearray: ...
632641
def rfind(
633-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
642+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
634643
) -> int: ...
635644
def rindex(
636-
self, __sub: bytes | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
645+
self, __sub: ReadableBuffer | SupportsIndex, __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
637646
) -> int: ...
638-
def rjust(self, __width: SupportsIndex, __fillchar: bytes = ...) -> bytearray: ...
639-
def rpartition(self, __sep: bytes) -> tuple[bytearray, bytearray, bytearray]: ...
640-
def rsplit(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ...
641-
def rstrip(self, __bytes: bytes | None = ...) -> bytearray: ...
642-
def split(self, sep: bytes | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ...
647+
def rjust(self, __width: SupportsIndex, __fillchar: bytes | bytearray = ...) -> bytearray: ...
648+
def rpartition(self, __sep: ReadableBuffer) -> tuple[bytearray, bytearray, bytearray]: ...
649+
def rsplit(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ...
650+
def rstrip(self, __bytes: ReadableBuffer | None = ...) -> bytearray: ...
651+
def split(self, sep: ReadableBuffer | None = ..., maxsplit: SupportsIndex = ...) -> list[bytearray]: ...
643652
def splitlines(self, keepends: bool = ...) -> list[bytearray]: ...
644653
def startswith(
645-
self, __prefix: bytes | tuple[bytes, ...], __start: SupportsIndex | None = ..., __end: SupportsIndex | None = ...
654+
self,
655+
__prefix: ReadableBuffer | tuple[ReadableBuffer, ...],
656+
__start: SupportsIndex | None = ...,
657+
__end: SupportsIndex | None = ...,
646658
) -> bool: ...
647-
def strip(self, __bytes: bytes | None = ...) -> bytearray: ...
659+
def strip(self, __bytes: ReadableBuffer | None = ...) -> bytearray: ...
648660
def swapcase(self) -> bytearray: ...
649661
def title(self) -> bytearray: ...
650-
def translate(self, __table: bytes | None, delete: bytes = ...) -> bytearray: ...
662+
def translate(self, __table: ReadableBuffer | None, delete: bytes = ...) -> bytearray: ...
651663
def upper(self) -> bytearray: ...
652664
def zfill(self, __width: SupportsIndex) -> bytearray: ...
653665
@classmethod
654666
def fromhex(cls: type[Self], __string: str) -> Self: ...
655667
@staticmethod
656-
def maketrans(__frm: bytes, __to: bytes) -> bytes: ...
668+
def maketrans(__frm: ReadableBuffer, __to: ReadableBuffer) -> bytes: ...
657669
def __len__(self) -> int: ...
658670
def __iter__(self) -> Iterator[int]: ...
659671
__hash__: ClassVar[None] # type: ignore[assignment]
@@ -666,14 +678,15 @@ class bytearray(MutableSequence[int], ByteString):
666678
@overload
667679
def __setitem__(self, __s: slice, __x: Iterable[SupportsIndex] | bytes) -> None: ...
668680
def __delitem__(self, __i: SupportsIndex | slice) -> None: ...
669-
def __add__(self, __s: bytes) -> bytearray: ...
670-
def __iadd__(self: Self, __s: Iterable[int]) -> Self: ...
681+
def __add__(self, __s: ReadableBuffer) -> bytearray: ...
682+
# The superclass wants us to accept Iterable[int], but that fails at runtime.
683+
def __iadd__(self: Self, __s: ReadableBuffer) -> Self: ... # type: ignore[override]
671684
def __mul__(self, __n: SupportsIndex) -> bytearray: ...
672685
def __rmul__(self, __n: SupportsIndex) -> bytearray: ...
673686
def __imul__(self: Self, __n: SupportsIndex) -> Self: ...
674687
def __mod__(self, __value: Any) -> bytes: ...
675688
# Incompatible with Sequence.__contains__
676-
def __contains__(self, __o: SupportsIndex | bytes) -> bool: ... # type: ignore[override]
689+
def __contains__(self, __o: SupportsIndex | ReadableBuffer) -> bool: ... # type: ignore[override]
677690
def __eq__(self, __x: object) -> bool: ...
678691
def __ne__(self, __x: object) -> bool: ...
679692
def __lt__(self, __x: bytes) -> bool: ...
@@ -722,7 +735,7 @@ class memoryview(Sized, Sequence[int]):
722735
def __iter__(self) -> Iterator[int]: ...
723736
def __len__(self) -> int: ...
724737
@overload
725-
def __setitem__(self, __s: slice, __o: bytes) -> None: ...
738+
def __setitem__(self, __s: slice, __o: ReadableBuffer) -> None: ...
726739
@overload
727740
def __setitem__(self, __i: SupportsIndex, __o: SupportsIndex) -> None: ...
728741
if sys.version_info >= (3, 8):
@@ -1086,8 +1099,8 @@ if sys.version_info >= (3, 10):
10861099
# TODO: `compile` has a more precise return type in reality; work on a way of expressing that?
10871100
if sys.version_info >= (3, 8):
10881101
def compile(
1089-
source: str | bytes | AST,
1090-
filename: str | bytes | _PathLike[Any],
1102+
source: str | ReadableBuffer | AST,
1103+
filename: str | ReadableBuffer | _PathLike[Any],
10911104
mode: str,
10921105
flags: int = ...,
10931106
dont_inherit: int = ...,
@@ -1098,8 +1111,8 @@ if sys.version_info >= (3, 8):
10981111

10991112
else:
11001113
def compile(
1101-
source: str | bytes | AST,
1102-
filename: str | bytes | _PathLike[Any],
1114+
source: str | ReadableBuffer | AST,
1115+
filename: str | ReadableBuffer | _PathLike[Any],
11031116
mode: str,
11041117
flags: int = ...,
11051118
dont_inherit: int = ...,
@@ -1118,12 +1131,12 @@ def divmod(__x: _T_contra, __y: SupportsRDivMod[_T_contra, _T_co]) -> _T_co: ...
11181131
# The `globals` argument to `eval` has to be `dict[str, Any]` rather than `dict[str, object]` due to invariance.
11191132
# (The `globals` argument has to be a "real dict", rather than any old mapping, unlike the `locals` argument.)
11201133
def eval(
1121-
__source: str | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ...
1134+
__source: str | ReadableBuffer | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ...
11221135
) -> Any: ...
11231136

11241137
# Comment above regarding `eval` applies to `exec` as well
11251138
def exec(
1126-
__source: str | bytes | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ...
1139+
__source: str | ReadableBuffer | CodeType, __globals: dict[str, Any] | None = ..., __locals: Mapping[str, object] | None = ...
11271140
) -> None: ...
11281141
def exit(code: object = ...) -> NoReturn: ...
11291142

@@ -1351,7 +1364,7 @@ def open(
13511364
closefd: bool = ...,
13521365
opener: _Opener | None = ...,
13531366
) -> IO[Any]: ...
1354-
def ord(__c: str | bytes) -> int: ...
1367+
def ord(__c: str | bytes | bytearray) -> int: ...
13551368

13561369
class _SupportsWriteAndFlush(SupportsWrite[_T_contra], Protocol[_T_contra]):
13571370
def flush(self) -> None: ...
@@ -1712,7 +1725,7 @@ class UnicodeDecodeError(UnicodeError):
17121725
start: int
17131726
end: int
17141727
reason: str
1715-
def __init__(self, __encoding: str, __object: bytes, __start: int, __end: int, __reason: str) -> None: ...
1728+
def __init__(self, __encoding: str, __object: ReadableBuffer, __start: int, __end: int, __reason: str) -> None: ...
17161729

17171730
class UnicodeEncodeError(UnicodeError):
17181731
encoding: str

0 commit comments

Comments
 (0)