From 66072ddcd9825ab235e03d8ee2b3bb514e644335 Mon Sep 17 00:00:00 2001 From: gabrieldemarmiesse Date: Wed, 16 Aug 2023 11:32:26 +0000 Subject: [PATCH] :up: Set minimum Python version for plum to Python 3.8 --- .github/workflows/ci.yml | 2 +- README.md | 2 +- docs/parametric.md | 4 ++- plum/alias.py | 3 +- plum/function.py | 2 +- plum/parametric.py | 6 ++++ plum/type.py | 19 ++++--------- plum/util.py | 61 ---------------------------------------- pyproject.toml | 4 +-- 9 files changed, 20 insertions(+), 83 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 66fa85c8..dd405af9 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -10,7 +10,7 @@ jobs: strategy: fail-fast: false matrix: - python-version: [3.7, 3.8, 3.9, "3.10", "3.11"] + python-version: [3.8, 3.9, "3.10", "3.11"] steps: - uses: actions/checkout@v2 diff --git a/README.md b/README.md index 3909ffd4..5610430a 100644 --- a/README.md +++ b/README.md @@ -17,7 +17,7 @@ If you notice any issues with the new release, please open an issue. # Installation -Plum requires Python 3.7 or higher. +Plum requires Python 3.8 or higher. ```bash pip install plum-dispatch diff --git a/docs/parametric.md b/docs/parametric.md index 45c923bb..36034bff 100644 --- a/docs/parametric.md +++ b/docs/parametric.md @@ -268,7 +268,9 @@ def algorithm(setting: Val["slow"], x): ``` `typing.Literal` fills a very similar purpose. -You can use `Val` if `typing.Literal` is not available, e.g. on Python 3.7. +We recommend using `typing.Literal` instead. `Val` is only useful for Python +versions that do not have `typing.Literal`. Those are Python 3.7 and below, but +plum does not support those versions. ## Example: `NDArray` diff --git a/plum/alias.py b/plum/alias.py index f419d41f..5c34ad7d 100644 --- a/plum/alias.py +++ b/plum/alias.py @@ -28,8 +28,7 @@ import typing from functools import wraps - -from .util import get_args +from typing import get_args __all__ = ["activate_union_aliases", "deactivate_union_aliases", "set_union_alias"] diff --git a/plum/function.py b/plum/function.py index 68ed96f1..150d0d68 100644 --- a/plum/function.py +++ b/plum/function.py @@ -17,7 +17,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.7 3.8 3.9 3.10 +except ImportError: # pragma: specific no cover 3.8 3.9 3.10 Self = TypeVar("Self", bound="Function") SomeExceptionType = TypeVar("SomeExceptionType", bound=Exception) diff --git a/plum/parametric.py b/plum/parametric.py index 17a63116..a11d2eba 100644 --- a/plum/parametric.py +++ b/plum/parametric.py @@ -1,3 +1,4 @@ +import warnings from typing import Union import beartype.door @@ -370,6 +371,11 @@ def __init__(self, val=None): Args: val (object): The value to be moved to the type domain. """ + warnings.warn( + "plum.Val is deprecated and will be removed in a future version, " + "please use typing.Literal instead.", + stacklevel=2, + ) if type(self).concrete: if val is not None and type_parameter(self) != val: raise ValueError("The value must be equal to the type parameter.") diff --git a/plum/type.py b/plum/type.py index 347468a7..d6ea2148 100644 --- a/plum/type.py +++ b/plum/type.py @@ -2,10 +2,9 @@ import sys import typing import warnings +from typing import Literal, get_args, get_origin -from .util import get_args, get_origin - -try: # pragma: specific no cover 3.7 3.8 3.9 +try: # pragma: specific no cover 3.8 3.9 from types import UnionType except ImportError: # pragma: specific no cover 3.10 3.11 @@ -13,14 +12,6 @@ class UnionType: """Replacement for :class:`types.UnionType`.""" -try: # pragma: specific no cover 3.7 - from typing import Literal -except ImportError: # pragma: specific no cover 3.8 3.9 3.10 3.11 - - class Literal: - """A simple proxy for :class:`typing.Literal`.""" - - __all__ = [ "PromisedType", "ModuleType", @@ -130,7 +121,7 @@ def _is_hint(x): bool: `True` if `x` is a type hint and `False` otherwise. """ try: - if x.__module__ == "builtins": # pragma: specific no cover 3.7 3.8 + if x.__module__ == "builtins": # pragma: specific no cover 3.8 # Check if `x` is a subscripted built-in. We do this by checking the module # of the type of `x`. x = type(x) @@ -184,7 +175,7 @@ def resolve_type_hint(x): # hint itself. return x else: - if origin is UnionType: # pragma: specific no cover 3.7 3.8 3.9 + if origin is UnionType: # pragma: specific no cover 3.8 3.9 # The new union syntax was used. y = args[0] for arg in args[1:]: @@ -197,7 +188,7 @@ def resolve_type_hint(x): try: return origin[args] except TypeError as e: # pragma: specific no cover 3.9 3.10 3.11 - # In Python 3.7 and 3.8, the origin might be a type that cannot be + # In Python 3.8, the origin might be a type that cannot be # subscripted. As a workaround, we get the name of the type, # capitalize it, and try to get it from `typing`. So far, this # seems to have worked fine. diff --git a/plum/util.py b/plum/util.py index 4d58fc92..6f7d7261 100644 --- a/plum/util.py +++ b/plum/util.py @@ -4,8 +4,6 @@ from typing import Callable, List __all__ = [ - "get_origin", - "get_args", "TypeHint", "repr_short", "Missing", @@ -17,65 +15,6 @@ "get_context", ] -try: # pragma: specific no cover 3.7 - from typing import get_args as _get_args - from typing import get_origin as _get_origin - - # Wrap the functions, because we'll adjust their docstrings below. - - def get_args(x): - return _get_args(x) - - def get_origin(x): - return _get_origin(x) - -except ImportError: # pragma: no cover - import collections.abc - - # The functions :func:`typing.get_origin` and :func:`typing.get_args` were only - # introduced in Python 3.8, but we need them already in Python 3.7. The below is - # a copy of their source in `typing.py` from Python 3.8. Since we copied from - # the source, we also do not check for coverage. - - def get_origin(x): - if isinstance(x, typing._GenericAlias): - return x.__origin__ - if x is typing.Generic: - return typing.Generic - return None - - def get_args(x): - if isinstance(x, typing._GenericAlias) and not x._special: - args = x.__args__ - if get_origin(x) is collections.abc.Callable and args[0] is not Ellipsis: - args = (list(args[:-1]), args[-1]) - return args - return () - - -# If we were to add docstrings directly to the manual definitions of `get_origin` above, -# then the docstrings would be different depending on whether an `ImportError` happened -# or not. We don't want that. Hence, we set the docstrings below, regardless of which -# case happened. - -get_origin.__doc__ = """Get the unsubscripted version of a type hint. - -Args: - x (type hint): Type hint. - -Returns: - type hint: Unsubcripted version of `x`. -""" - -get_args.__doc__ = """Get the arguments of a subscripted type hint. - -Args: - x (type hint): Type hint. - -Returns: - tuple: Arguments of `x`. -""" - # We use this to indicate a reader that we expect a type hint. Using just `object` as a # type hint is technically correct for `int | None` for example, but does not convey the # intention to a reader. Furthermore, if later on, Python has a proper type for type diff --git a/pyproject.toml b/pyproject.toml index 20434419..f24bc57d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -17,7 +17,7 @@ classifiers = [ ] dynamic = ["version"] -requires-python = ">=3.7" +requires-python = ">=3.8" dependencies = ["beartype"] [project.optional-dependencies] @@ -62,7 +62,7 @@ testpaths = [ # Formatting tools [tool.black] line-length = 88 -target-version = ['py37', 'py38', 'py39'] +target-version = ['py38', 'py39'] include = '\.pyi?$' exclude = ''' /(