Skip to content

Commit

Permalink
Do not alter runtime types (#120)
Browse files Browse the repository at this point in the history
Fixes #118 - Do not alter python runtime types on the fly

* Correctly create new parameterized types rather than modifying them in place.
* Have to use more than `typing.Iterable` now - hopefully this doesn't cause problems down the line, outside this package.
* Still, detect the move to `collections.abc.X` when there is a matching `typing.X`, and walk back to `typing.X`. This is needed to support earlier versions of python, and feels rather fragile!
* Fix up versions for github actions to avoid CI build depreciation warnings
  • Loading branch information
gordonwatts authored Mar 22, 2023
1 parent 2e4b59e commit 9be9f18
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 13 deletions.
10 changes: 5 additions & 5 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@ jobs:
flake8:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python 3.8
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.8
- name: Install dependencies
Expand All @@ -40,9 +40,9 @@ jobs:
python-version: [3.7, 3.8, 3.9, "3.10", 3.11]

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python ${{ matrix.python-version }}
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: ${{ matrix.python-version }}
- name: Install dependencies
Expand All @@ -55,7 +55,7 @@ jobs:
python -m pytest -r sx
- name: Report coverage with Codecov
if: github.event_name == 'push' && matrix.python-version == 3.9 && matrix.os == 'ubuntu-latest'
uses: codecov/codecov-action@v1
uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
file: ./coverage.xml
Expand Down
4 changes: 2 additions & 2 deletions .github/workflows/pypi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@ jobs:
runs-on: ubuntu-latest

steps:
- uses: actions/checkout@v2
- uses: actions/checkout@v3
- name: Set up Python
uses: actions/setup-python@v2
uses: actions/setup-python@v4
with:
python-version: 3.7
- name: Install dependencies
Expand Down
20 changes: 15 additions & 5 deletions func_adl/util_types.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import inspect
import sys
import typing
from typing import Any, Dict, Optional, Tuple, Type, TypeVar

if sys.version_info >= (3, 8):
Expand All @@ -25,9 +26,7 @@ def is_iterable(t: Type) -> bool:

def _is_iterable_direct(t: Type) -> bool:
"Is this type iterable?"
if getattr(t, "_name", None) == "Iterable":
return True
return False
return getattr(t, "_name", None) == "Iterable" or getattr(t, "__name__", None) == "Iterable"


def get_inherited(t: Type) -> Type:
Expand All @@ -54,7 +53,18 @@ def get_inherited(t: Type) -> Type:
g_args = get_args(t)
if len(g_args) > 0:
mapping = {a.__name__: v for a, v in zip(r.__parameters__, g_args)}
r.__args__ = tuple(_resolve_type(t_arg, mapping) for t_arg in get_args(r))

r_base = get_origin(r)
assert r_base is not None, "Internal error"

# Get us back to typing if this is a common interface.
# This is not needed in python 3.11 and forward, where
# collections.abc.X can are all be parameterized.
if r_base.__name__ in typing.__dict__:
r_base = typing.__dict__[r_base.__name__]

# Re-parameterize the type with the information e have from this parameterization.
r = r_base[tuple(_resolve_type(t_arg, mapping) for t_arg in get_args(r))]

return r

Expand Down Expand Up @@ -117,7 +127,7 @@ def _resolve_type(t: Type, parameters: Dict[str, Type]) -> Optional[Type]:
Returns:
None if `t` is parameterized by unknown type var's
The resolved type (a copy leaving `t` untouched) if TypeVar's are filled in
The type if no substition is required.
The type if no substitution is required.
"""
if isinstance(t, TypeVar):
if t.__name__ in parameters:
Expand Down
15 changes: 14 additions & 1 deletion tests/test_util_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -89,7 +89,7 @@ class bogus(Iterable[T]):

myc = bogus[int]

assert get_inherited(myc) == Iterable[int]
assert get_inherited(myc) == Iterable[int] # type: ignore


def test_get_inherited_two_levels():
Expand All @@ -106,6 +106,19 @@ class bogus2(bogus[Iterable[U]]):
assert get_inherited(myc) == bogus[Iterable[int]]


def test_get_inherited_generic_twice():
T = TypeVar("T")

class bogus(Iterable[T]):
pass

myc = bogus[int]
assert get_inherited(myc) == Iterable[int] # type: ignore

myd = bogus[float]
assert get_inherited(myd) == Iterable[float] # type: ignore


def test_build_type_int():
assert build_type_dict_from_type(int) == {}

Expand Down

0 comments on commit 9be9f18

Please sign in to comment.