Skip to content

Commit

Permalink
Drop support for 3.9, make const a boolean, other stuff
Browse files Browse the repository at this point in the history
  • Loading branch information
dargueta committed Sep 15, 2024
1 parent 9b4edbf commit b8f4f9f
Show file tree
Hide file tree
Showing 20 changed files with 208 additions and 272 deletions.
4 changes: 0 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ jobs:
fail-fast: false
matrix:
include:
- python-version: "3.9"
tox-env: py39
- python-version: "3.10"
tox-env: py310
- python-version: "3.11"
Expand All @@ -19,8 +17,6 @@ jobs:
tox-env: py312
- python-version: "3.13.0-rc.1"
tox-env: py313
- python-version: "pypy-3.9"
tox-env: pypy39
- python-version: "pypy-3.10"
tox-env: pypy310
- python-version: "3.12"
Expand Down
4 changes: 2 additions & 2 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ binobj
.. |build-status| image:: https://github.com/dargueta/binobj/actions/workflows/ci.yml/badge.svg
:alt: Build status

.. |python-versions| image:: https://img.shields.io/badge/python-3.9,%203.10,%203.11,%203.12,%203.13-blue.svg
.. |python-versions| image:: https://img.shields.io/badge/python-3.10,%203.11,%203.12,%203.13-blue.svg
:alt: Python versions

.. |installs-month| image:: https://pepy.tech/badge/binobj/month
Expand Down Expand Up @@ -81,7 +81,7 @@ System Requirements

- This package will *not* work on a `mixed-endian`_ system. Those are pretty rare
nowadays so chances are you won't have a problem.
- This has been tested on CPython 3.9-3.13, PyPy 3.9-3.10.
- This has been tested on CPython 3.10-3.13, and PyPy 3.10.

.. _mixed-endian: https://en.wikipedia.org/wiki/Endianness#Mixed

Expand Down
3 changes: 1 addition & 2 deletions binobj/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@

import importlib.metadata
from typing import NamedTuple
from typing import Optional

from .errors import *
from .fields import *
Expand All @@ -18,7 +17,7 @@ class VersionInfo(NamedTuple):
major: int
minor: int
patch: int
suffix: Optional[str]
suffix: str | None

@classmethod
def from_string(cls, version: str) -> VersionInfo:
Expand Down
8 changes: 3 additions & 5 deletions binobj/decorators.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,13 +3,11 @@
from __future__ import annotations

import functools
from typing import Callable
from typing import Optional
from typing import TYPE_CHECKING
from typing import Union


if TYPE_CHECKING: # pragma: no cover
from collections.abc import Callable
from collections.abc import Iterable
from typing import Any

Expand All @@ -29,13 +27,13 @@ class ValidatorMethodWrapper:
"""

def __init__(
self, func: Union[FieldValidator, StructValidator], field_names: Iterable[str]
self, func: FieldValidator | StructValidator, field_names: Iterable[str]
):
self.func = func
self.field_names = tuple(field_names or ())
functools.wraps(func)(self)

def __call__(self, *args: Any) -> Optional[bool]:
def __call__(self, *args: Any) -> bool | None:
"""Execute the wrapped function."""
return self.func(*args)

Expand Down
50 changes: 22 additions & 28 deletions binobj/errors.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,7 @@

import typing
from typing import Any
from typing import Optional
from typing import TypeVar
from typing import Union

import more_itertools as m_iter

Expand Down Expand Up @@ -51,7 +49,7 @@ class Error(Exception):
Do not throw this exception directly.
"""

def __init__(self, message: Optional[str] = None, *args: object):
def __init__(self, message: str | None = None, *args: object):
# If there is no error message, use the first line of the docstring.
if message is None and hasattr(self, "__doc__") and self.__doc__:
message = self.__doc__.splitlines()[0]
Expand Down Expand Up @@ -83,16 +81,16 @@ class ConfigurationError(Error):
The ``struct`` and ``obj`` arguments.
"""

field: Optional[FieldOrName]
struct: Optional[StructOrName]
field: FieldOrName | None
struct: StructOrName | None
obj: Any

def __init__(
self,
message: Optional[str] = None,
message: str | None = None,
*,
field: Optional[FieldOrName] = None,
struct: Optional[StructOrName] = None,
field: FieldOrName | None = None,
struct: StructOrName | None = None,
obj: object = None,
):
if not (field or struct or obj):
Expand Down Expand Up @@ -135,11 +133,11 @@ class SerializationError(Error):

def __init__(
self,
message: Optional[str] = None,
message: str | None = None,
*,
struct: Optional[Struct] = None,
field: Optional[FieldOrName] = None,
value: Optional[T] = None,
struct: Struct | None = None,
field: FieldOrName | None = None,
value: T | None = None,
):
super().__init__(message)
self.struct = struct
Expand All @@ -162,11 +160,11 @@ class DeserializationError(Error):

def __init__(
self,
message: Optional[str] = None,
message: str | None = None,
*,
field: Optional[Field[Any]] = None,
data: Optional[bytes] = None,
offset: Optional[int] = None,
field: Field[Any] | None = None,
data: bytes | None = None,
offset: int | None = None,
):
super().__init__(message)
self.field = field
Expand All @@ -185,9 +183,7 @@ class ValidationError(Error):
The invalid value.
"""

def __init__(
self, message: Optional[str] = None, *, field: Field[T], value: Optional[T]
):
def __init__(self, message: str | None = None, *, field: Field[T], value: T | None):
if not message:
message = f"Invalid value for {field}: {value!r}"

Expand All @@ -205,7 +201,7 @@ class FieldReferenceError(Error):
The name of the field that failed to be referenced.
"""

def __init__(self, message: Optional[str] = None, *, field: str):
def __init__(self, message: str | None = None, *, field: str):
if not message:
message = f"Attempted to reference a missing or undefined field: {field!r}"

Expand Down Expand Up @@ -235,8 +231,8 @@ class ImmutableFieldError(IllegalOperationError):
The ``field`` argument.
"""

def __init__(self, *, field: Optional[Field[Any]] = None):
message: Optional[str]
def __init__(self, *, field: Field[Any] | None = None):
message: str | None
if field is not None:
message = f"Cannot assign to immutable field: {field!r}"
else:
Expand Down Expand Up @@ -374,9 +370,7 @@ class UnserializableValueError(SerializationError):
Optional. The reason for the failure.
"""

def __init__(
self, *, field: Field[T], value: Optional[T], reason: Optional[str] = None
):
def __init__(self, *, field: Field[T], value: T | None, reason: str | None = None):
if reason is not None:
message = f"{field} can't serialize value: {reason}"
else:
Expand Down Expand Up @@ -407,7 +401,7 @@ class UnexpectedValueError(SerializationError):
was unexpected. Don't pass :class:`~binobj.fields.base.Field` instances.
"""

def __init__(self, *, struct: Struct, name: Union[str, Iterable[str]]):
def __init__(self, *, struct: Struct, name: str | Iterable[str]):
self.names = set(m_iter.always_iterable(name))

msg = (
Expand Down Expand Up @@ -446,7 +440,7 @@ class ArraySizeError(SerializationError):
"""

def __init__(
self, *, field: Field[Any], n_expected: int, n_given: Optional[int] = None
self, *, field: Field[Any], n_expected: int, n_given: int | None = None
):
if n_given is not None:
if n_given > n_expected:
Expand All @@ -473,7 +467,7 @@ class UnexpectedEOFError(DeserializationError):
bytes.
"""

def __init__(self, *, field: Optional[Field[Any]], size: int, offset: int):
def __init__(self, *, field: Field[Any] | None, size: int, offset: int):
super().__init__(
f"Unexpected EOF while trying to read {size} bytes at offset {offset}.",
field=field,
Expand Down
Loading

0 comments on commit b8f4f9f

Please sign in to comment.