Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

🆙 Set minimum Python version for plum to Python 3.8 #94

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
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
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.7 or higher.
Plum requires Python 3.8 or higher.

```bash
pip install plum-dispatch
Expand Down
4 changes: 3 additions & 1 deletion docs/parametric.md
Original file line number Diff line number Diff line change
Expand Up @@ -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`
Expand Down
3 changes: 1 addition & 2 deletions plum/alias.py
Original file line number Diff line number Diff line change
Expand Up @@ -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"]

Expand Down
2 changes: 1 addition & 1 deletion plum/function.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions plum/parametric.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import warnings
from typing import Union

import beartype.door
Expand Down Expand Up @@ -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.")
Expand Down
19 changes: 5 additions & 14 deletions plum/type.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,16 @@
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

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",
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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:]:
Expand All @@ -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.
Expand Down
61 changes: 0 additions & 61 deletions plum/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
from typing import Callable, List

__all__ = [
"get_origin",
"get_args",
"TypeHint",
"repr_short",
"Missing",
Expand All @@ -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
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ classifiers = [
]
dynamic = ["version"]

requires-python = ">=3.7"
requires-python = ">=3.8"
dependencies = ["beartype"]

[project.optional-dependencies]
Expand Down Expand Up @@ -62,7 +62,7 @@ testpaths = [
# Formatting tools
[tool.black]
line-length = 88
target-version = ['py37', 'py38', 'py39']
target-version = ['py38', 'py39']
include = '\.pyi?$'
exclude = '''
/(
Expand Down
Loading