Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@ jobs:
fail-fast: false
matrix:
value:
- name: "3.8"
python-version: "3.8"
extra-install: ""
- name: "3.9"
python-version: "3.9"
extra-install: ""
Expand All @@ -28,15 +25,18 @@ jobs:
- name: "3.11"
python-version: "3.11"
extra-install: ""
- name: "3.11-pre-beartype"
python-version: "3.11"
extra-install: "pip install --upgrade --pre beartype"
- name: "3.12"
python-version: "3.12"
extra-install: ""
- name: "3.12-pre-beartype"
python-version: "3.12"
extra-install: "pip install --upgrade --pre beartype"
- name: "3.13"
python-version: "3.13"
extra-install: ""
- name: "3.13-pre-beartype"
python-version: "3.13"
extra-install: "pip install --upgrade --pre beartype"

name: Test ${{ matrix.value.name }}
steps:
Expand Down
2 changes: 1 addition & 1 deletion .readthedocs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ version: 2
build:
os: ubuntu-22.04
tools:
python: "3.11"
python: "3.12"
jobs:
pre_build:
# Generate the Sphinx configuration for this Jupyter Book, so it builds.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ If you notice any issues with the new release, please open an issue.

# Installation

Plum requires Python 3.8 or higher.
Plum requires Python 3.9 or higher.

```bash
pip install plum-dispatch
Expand Down
6 changes: 2 additions & 4 deletions benchmark.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from typing import Tuple

import numpy as np
from tests.util import benchmark

Expand Down Expand Up @@ -35,12 +33,12 @@ def f2(x):


@dispatch
def g2(x: Tuple[int]):
def g2(x: tuple[int]):
pass


@dispatch
def g2(x: Tuple[str]):
def g2(x: tuple[str]):
pass


Expand Down
12 changes: 6 additions & 6 deletions check_linter_assertions.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,15 +2,15 @@
import subprocess
import sys
from collections import defaultdict
from collections.abc import Callable
from pathlib import Path
from typing import Callable, Dict, List, Tuple

FileLineInfo = Dict[Path, Dict[int, List[str]]]
FileLineInfo = dict[Path, dict[int, list[str]]]
"""type: Type of a nested dictionary that gives for a collection of files line-wise
information, where the information is of the form `list[str]`."""


def next_noncomment_line(index: int, lines: List[str], path: Path) -> int:
def next_noncomment_line(index: int, lines: list[str], path: Path) -> int:
"""Starting at `index`, find the next line with code.

Args:
Expand Down Expand Up @@ -70,7 +70,7 @@ def parse_assertions(source_dir: Path, linter: str) -> FileLineInfo:
return asserted_errors


def parse_mypy_line(line: str) -> Tuple[Path, int, str, str]:
def parse_mypy_line(line: str) -> tuple[Path, int, str, str]:
"""Parse a line of the output of `mypy`.

Args:
Expand All @@ -90,7 +90,7 @@ def parse_mypy_line(line: str) -> Tuple[Path, int, str, str]:
return Path(path).resolve(), int(line_number), status, message


def parse_pyright_line(line: str) -> Tuple[Path, int, str, str]:
def parse_pyright_line(line: str) -> tuple[Path, int, str, str]:
"""Parse a line of the output of `pyright`.

Args:
Expand All @@ -112,7 +112,7 @@ def parse_pyright_line(line: str) -> Tuple[Path, int, str, str]:
return Path(path.strip()).resolve(), int(line_number), status, message


parse_line: Dict[str, Callable[[str], Tuple[Path, int, str, str]]] = {
parse_line: dict[str, Callable[[str], tuple[Path, int, str, str]]] = {
"mypy": parse_mypy_line,
"pyright": parse_pyright_line,
}
Expand Down
10 changes: 5 additions & 5 deletions docs/types.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ that all types and type hints supported by Beartype are also supported by Plum.
Here are a few examples:

```python
from typing import Union, Optional, List, Dict
from typing import Union, Optional

from plum import dispatch

Expand All @@ -34,7 +34,7 @@ def f(x: list) -> str:


@dispatch
def f(x: List[int]) -> str:
def f(x: list[int]) -> str:
return "list of int"


Expand All @@ -44,11 +44,11 @@ def f(x: Optional[dict]) -> Optional[str]:


@dispatch
def f(x: Dict[int, str]) -> str:
def f(x: dict[int, str]) -> str:
return "dict of int to str"
```

Although parametric types such as `List[int]` and `Dict[int, str]` are fully
Although parametric types such as `list[int]` and `dict[int, str]` are fully
supported, they do incur a performance penalty.
For optimal performance, is recommended to use parametric types only where necessary.
`Union` and `Optional` do not incur a performance penalty.
Expand Down Expand Up @@ -85,7 +85,7 @@ Plum already opts into this behaviour and will use it once it becomes available.

The type system is *covariant*, as opposed to Julia's type
system, which is *invariant*.
For example, this means that `List[T1]` is a subtype of `List[T2]` whenever
For example, this means that `list[T1]` is a subtype of `list[T2]` whenever
`T1` is a subtype of `T2`.

## Performance and Faithful Types
Expand Down
10 changes: 6 additions & 4 deletions plum/__init__.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
# Plum previously exported a number of types. As of recently, the user can use the
# versions from `typing`. To not break backward compatibility, we still export these
# types.
# Plum previously exported a number of types. As of recently, the user can use
# the versions from `typing`. To not break backward compatibility, we still
# export these types.
from typing import Dict, List, Tuple, Union # noqa: F401, UP035

# isort: split
from functools import partial
from typing import Dict, List, Tuple, Union # noqa: F401

from beartype import (
BeartypeConf as _BeartypeConf,
Expand Down
6 changes: 2 additions & 4 deletions plum/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,7 @@
"""

from functools import wraps
from typing import List, TypeVar, Union, _type_repr

from .typing import get_args
from typing import TypeVar, Union, _type_repr, get_args

__all__ = ["activate_union_aliases", "deactivate_union_aliases", "set_union_alias"]

Expand Down Expand Up @@ -141,7 +139,7 @@ def deactivate_union_aliases() -> None:
_union_type.__str__ = _original_str


_ALIASED_UNIONS: List = []
_ALIASED_UNIONS: list = []


def set_union_alias(union: UnionT, alias: str) -> UnionT:
Expand Down
12 changes: 6 additions & 6 deletions plum/dispatcher.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import sys
from dataclasses import dataclass, field
from functools import partial
from typing import Any, Dict, Optional, Tuple, TypeVar, Union, overload
from typing import Any, Optional, TypeVar, Union, overload

from .function import Function
from .overload import get_overloads
Expand All @@ -13,8 +13,8 @@
T = TypeVar("T", bound=Callable[..., Any])


_dataclass_kw_args: Dict[str, Any] = {}
if sys.version_info >= (3, 10): # pragma: specific no cover 3.8 3.9
_dataclass_kw_args: dict[str, Any] = {}
if sys.version_info >= (3, 10): # pragma: specific no cover 3.9
_dataclass_kw_args |= {"slots": True}


Expand All @@ -34,8 +34,8 @@ class Dispatcher:
"""

warn_redefinition: bool = False
functions: Dict[str, Function] = field(default_factory=dict)
classes: Dict[str, Dict[str, Function]] = field(default_factory=dict)
functions: dict[str, Function] = field(default_factory=dict)
classes: dict[str, dict[str, Function]] = field(default_factory=dict)

@overload
def __call__(self, method: T, /, *, precedence: int = ...) -> T: ...
Expand Down Expand Up @@ -74,7 +74,7 @@ def __call__(
return self._add_method(method, None, precedence=precedence)

def multi(
self, *signatures: Union[Signature, Tuple[TypeHint, ...]]
self, *signatures: Union[Signature, tuple[TypeHint, ...]]
) -> Callable[[Callable], Function]:
"""Decorator to register multiple signatures at once.

Expand Down
28 changes: 14 additions & 14 deletions plum/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from copy import copy
from functools import wraps
from types import MethodType
from typing import Any, Callable, List, Optional, Protocol, Tuple, TypeVar, Union
from typing import Any, Callable, Optional, Protocol, TypeVar, Union

from .method import Method
from .resolver import AmbiguousLookupError, NotFoundLookupError, Resolver
Expand All @@ -20,7 +20,7 @@
# `typing.Self` is available for Python 3.11 and higher.
try: # pragma: specific no cover 3.11
from typing import Self
except ImportError: # pragma: specific no cover 3.8 3.9 3.10
except ImportError: # pragma: specific no cover 3.10
Self = TypeVar("Self", bound="Function")

SomeExceptionType = TypeVar("SomeExceptionType", bound=Exception)
Expand Down Expand Up @@ -96,12 +96,12 @@ def __init__(
self._warn_redefinition = warn_redefinition

# Initialise pending and resolved methods.
self._pending: List[Tuple[Callable, Optional[Signature], int]] = []
self._pending: list[tuple[Callable, Optional[Signature], int]] = []
self._resolver = Resolver(
self.__name__,
warn_redefinition=self._warn_redefinition,
)
self._resolved: List[Tuple[Callable, Signature, int]] = []
self._resolved: list[tuple[Callable, Signature, int]] = []

@property
def owner(self):
Expand All @@ -125,7 +125,7 @@ def __doc__(self) -> Optional[str]:
"""
try:
self._resolve_pending_registrations()
except NameError: # pragma: specific no cover 3.7 3.8 3.9
except NameError: # pragma: specific no cover 3.9
# When `staticmethod` is combined with
# `from __future__ import annotations`, in Python 3.10 and higher
# `staticmethod` will attempt to inherit `__doc__` (see
Expand Down Expand Up @@ -176,7 +176,7 @@ def __doc__(self, value: str) -> None:
self._doc = value if value else ""

@property
def methods(self) -> List[Signature]:
def methods(self) -> list[Signature]:
"""list[:class:`.signature.Signature`]: All available methods."""
self._resolve_pending_registrations()
return self._resolver.methods
Expand All @@ -199,7 +199,7 @@ def dispatch(
return self

def dispatch_multi(
self: Self, *signatures: Union[Signature, Tuple[TypeHint, ...]]
self: Self, *signatures: Union[Signature, tuple[TypeHint, ...]]
) -> Callable[[Callable], Self]:
"""Decorator to extend the function with multiple signatures at once.

Expand Down Expand Up @@ -296,8 +296,8 @@ def _resolve_pending_registrations(self) -> None:
self.clear_cache(reregister=False)

def resolve_method(
self, target: Union[Tuple[object, ...], Signature]
) -> Tuple[Callable, TypeHint]:
self, target: Union[tuple[object, ...], Signature]
) -> tuple[Callable, TypeHint]:
"""Find the method and return type for arguments.

Args:
Expand Down Expand Up @@ -336,7 +336,7 @@ def resolve_method(

def _handle_not_found_lookup_error(
self, ex: NotFoundLookupError
) -> Tuple[Callable, TypeHint]:
) -> tuple[Callable, TypeHint]:
if not self.owner:
# Not in a class. Nothing we can do.
raise ex from None
Expand Down Expand Up @@ -384,9 +384,9 @@ def __call__(self, *args, **kw_args):

def _resolve_method_with_cache(
self,
args: Union[Tuple[object, ...], Signature, None] = None,
types: Optional[Tuple[TypeHint, ...]] = None,
) -> Tuple[Callable, TypeHint]:
args: Union[tuple[object, ...], Signature, None] = None,
types: Optional[tuple[TypeHint, ...]] = None,
) -> tuple[Callable, TypeHint]:
if args is None and types is None:
raise ValueError(
"Arguments `args` and `types` cannot both be `None`. "
Expand Down Expand Up @@ -525,7 +525,7 @@ def wrapped_method(*args, **kw_args):
return wrapped_method

@property
def methods(self) -> List[Signature]:
def methods(self) -> list[Signature]:
"""list[:class:`.signature.Signature`]: All available methods."""
return self._f.methods

Expand Down
7 changes: 4 additions & 3 deletions plum/method.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import inspect
import typing
from typing import Callable, List, Optional, Set, Tuple
from collections.abc import Callable
from typing import Optional

from rich.padding import Padding
from rich.text import Text
Expand Down Expand Up @@ -96,7 +97,7 @@ def __rich_console__(self, console, options):

def repr_mismatch(
self,
mismatches: Set[int] = frozenset(),
mismatches: set[int] = frozenset(),
varargs_matched: bool = True,
) -> str:
"""Version of `__repr__` that can print which arguments are mismatched. This
Expand Down Expand Up @@ -168,7 +169,7 @@ def __rich_console__(self, console, options):
yield Padding(sum(method_repr, Text(f"[{i}] ")), (0, 4))


def extract_arg_names(f: Callable) -> Tuple[List[str], List[str], Optional[str]]:
def extract_arg_names(f: Callable) -> tuple[list[str], list[str], Optional[str]]:
"""Extract the argument names for a function.

Args:
Expand Down
2 changes: 1 addition & 1 deletion plum/overload.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import sys

if sys.version_info >= (3, 11): # pragma: specific no cover 3.7 3.8 3.9 3.10
if sys.version_info >= (3, 11): # pragma: specific no cover 3.9 3.10
from typing import get_overloads, overload
else: # pragma: specific no cover 3.11
from typing_extensions import get_overloads, overload
Expand Down
6 changes: 3 additions & 3 deletions plum/parametric.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import contextlib
from typing import Type, TypeVar, Union
from typing import TypeVar, Union

from typing_extensions import deprecated

Expand Down Expand Up @@ -472,7 +472,7 @@ def type_parameter(x):
)


def type_nonparametric(q: T) -> Type[T]:
def type_nonparametric(q: T) -> type[T]:
"""Return the non-parametric type of an object.

:mod:`plum.parametric` produces parametric subtypes of classes. This method
Expand Down Expand Up @@ -540,7 +540,7 @@ def type_nonparametric(q: T) -> Type[T]:
)


def type_unparametrized(q: T) -> Type[T]:
def type_unparametrized(q: T) -> type[T]:
"""Return the unparametrized type of an object.

:mod:`plum.parametric` produces parametric subtypes of classes. This
Expand Down
Loading