Skip to content

Commit

Permalink
Implement many Python methods of bytes on Bytes (#135)
Browse files Browse the repository at this point in the history
  • Loading branch information
kylebarron authored Jan 14, 2025
1 parent 78860c6 commit 2234a63
Show file tree
Hide file tree
Showing 3 changed files with 308 additions and 35 deletions.
31 changes: 6 additions & 25 deletions pyo3-bytes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,28 +52,9 @@ For more reading:

## Python type hints

PyBytes has a small type surface, making it easy to copy the relevant type hint
into your library.

```py
import sys

if sys.version_info >= (3, 12):
from collections.abc import Buffer as _Buffer
else:
from typing_extensions import Buffer as _Buffer

class Bytes(_Buffer):
"""
A buffer implementing the Python buffer protocol, allowing zero-copy access
to underlying Rust memory.
You can pass this to `memoryview` for a zero-copy view into the underlying
data.
"""

def to_bytes(self) -> bytes:
"""Copy this buffer's contents into a Python `bytes` object."""
def __repr__(self) -> str: ...
def __len__(self) -> int: ...
```
On the Python side, the exported `Bytes` class implements many of the same
methods (with the same signature) as the Python `bytes` object.

The Python type hints are available in the Github repo in the file `bytes.pyi`.
I don't know the best way to distribute this to downstream projects. If you have
an idea, create an issue to discuss.
91 changes: 91 additions & 0 deletions pyo3-bytes/bytes.pyi
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import sys

if sys.version_info >= (3, 12):
from collections.abc import Buffer
else:
from typing_extensions import Buffer

class Bytes(Buffer):
"""
A buffer implementing the Python buffer protocol, allowing zero-copy access
to underlying Rust memory.
You can pass this to `memoryview` for a zero-copy view into the underlying
data.
"""

def __add__(self, other: Buffer) -> Bytes: ...
def __contains__(self, other: Buffer) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __getitem__(self, other: int) -> int: ...
def __mul__(self, other: Buffer) -> int: ...
def __len__(self) -> int: ...
def __repr__(self) -> str: ...
def removeprefix(self, prefix: Buffer, /) -> Bytes:
"""
If the binary data starts with the prefix string, return `bytes[len(prefix):]`.
Otherwise, return the original binary data.
"""
def removesuffix(self, suffix: Buffer, /) -> Bytes:
"""
If the binary data ends with the suffix string and that suffix is not empty,
return `bytes[:-len(suffix)]`. Otherwise, return the original binary data.
"""
def isalnum(self) -> bool:
"""
Return True if all bytes in the sequence are alphabetical ASCII characters or
ASCII decimal digits and the sequence is not empty, False otherwise. Alphabetic
ASCII characters are those byte values in the sequence
b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'. ASCII decimal digits
are those byte values in the sequence b'0123456789'.
"""
def isalpha(self) -> bool:
"""
Return True if all bytes in the sequence are alphabetic ASCII characters and the
sequence is not empty, False otherwise. Alphabetic ASCII characters are those
byte values in the sequence
b'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'.
"""
def isascii(self) -> bool:
"""
Return True if the sequence is empty or all bytes in the sequence are ASCII,
False otherwise. ASCII bytes are in the range 0-0x7F.
"""
def isdigit(self) -> bool:
"""
Return True if all bytes in the sequence are ASCII decimal digits and the
sequence is not empty, False otherwise. ASCII decimal digits are those byte
values in the sequence b'0123456789'.
"""
def islower(self) -> bool:
"""
Return True if there is at least one lowercase ASCII character in the sequence
and no uppercase ASCII characters, False otherwise.
"""
def isspace(self) -> bool:
"""
Return True if all bytes in the sequence are ASCII whitespace and the sequence
is not empty, False otherwise. ASCII whitespace characters are those byte values
in the sequence b' \t\n\r\x0b\f' (space, tab, newline, carriage return, vertical
tab, form feed).
"""
def isupper(self) -> bool:
"""
Return True if there is at least one uppercase alphabetic ASCII character in the
sequence and no lowercase ASCII characters, False otherwise.
"""

def lower(self) -> Bytes:
"""
Return a copy of the sequence with all the uppercase ASCII characters converted
to their corresponding lowercase counterpart.
"""

def upper(self) -> Bytes:
"""
Return a copy of the sequence with all the lowercase ASCII characters converted
to their corresponding uppercase counterpart.
"""

def to_bytes(self) -> bytes:
"""Copy this buffer's contents into a Python `bytes` object."""
Loading

0 comments on commit 2234a63

Please sign in to comment.