Skip to content

Commit 6e1a08e

Browse files
committed
Add language support for 3.10
- Drop 3.12 generics syntax - Drop typing.Self - Add matrix testing for 3.10-3.12 versions
1 parent 25d2fe2 commit 6e1a08e

File tree

12 files changed

+112
-59
lines changed

12 files changed

+112
-59
lines changed

.github/actions/setup-poetry/action.yml

-9
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,6 @@ description: 'Setup Poetry Project'
99
runs:
1010
using: 'composite'
1111
steps:
12-
#----------------------------------------------
13-
# set-up python
14-
#----------------------------------------------
15-
- name: Set up python
16-
id: setup-python
17-
uses: actions/setup-python@v5
18-
with:
19-
python-version: '3.12'
20-
2112
#----------------------------------------------
2213
# install & configure poetry
2314
#----------------------------------------------

.github/workflows/pipeline.yml

+13
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ jobs:
2020
steps:
2121
- name: Check out repository
2222
uses: actions/checkout@v4
23+
- name: Set up python
24+
id: setup-python
25+
uses: actions/setup-python@v5
26+
with:
27+
python-version: '3.12'
2328
- name: Setup Poetry
2429
uses: ./.github/actions/setup-poetry
2530
- name: Ruff (linting + formating)
@@ -45,9 +50,17 @@ jobs:
4550
pytest:
4651
runs-on: ubuntu-latest
4752
name: "Pytest Tests"
53+
strategy:
54+
matrix:
55+
python-version: [ "3.10", "3.11", "3.12" ]
4856
steps:
4957
- name: Check out repository
5058
uses: actions/checkout@v4
59+
- name: Set up python
60+
id: setup-python
61+
uses: actions/setup-python@v5
62+
with:
63+
python-version: ${{ matrix.python-version }}
5164
- name: Setup Poetry
5265
uses: ./.github/actions/setup-poetry
5366
- name: Run Pytest

examples/simple_service/main.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def do_stuff(self): ...
1515
# Define some providers to use for injection.
1616
ApiDomainProvider = providers.Blank()
1717
ApiTokenProvider = providers.Blank()
18-
ApiClientProvider = providers.Singleton[ApiClient](ApiClient, domain=ApiDomainProvider, token=ApiTokenProvider)
18+
ApiClientProvider = providers.Singleton(ApiClient, domain=ApiDomainProvider, token=ApiTokenProvider)
1919

2020

2121
@wiring.inject

pif/providers/existing_singleton.py

+6-1
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,16 @@
77
# Zac Scott (github.com/scottzach1)
88
#
99
# https://github.com/scottzach1/python-injector-framework
10+
from typing import TypeVar
1011

1112
from pif.providers.provider import Provider
1213

14+
__all__ = ("ExistingSingleton",)
1315

14-
class ExistingSingleton[T](Provider):
16+
T = TypeVar("T")
17+
18+
19+
class ExistingSingleton(Provider):
1520
"""
1621
Provide an existing object instance.
1722
"""

pif/providers/factory.py

+7-3
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,24 @@
99
# https://github.com/scottzach1/python-injector-framework
1010

1111
import functools
12-
from typing import Callable
12+
from typing import Callable, TypeVar
1313

1414
from pif.providers.provider import Provider
1515
from pif.providers.util import intercept_args
1616

17+
__all__ = ("Factory",)
1718

18-
class Factory[T](Provider):
19+
T = TypeVar("T")
20+
21+
22+
class Factory(Provider):
1923
"""
2024
Generate a new instance every call.
2125
"""
2226

2327
__slots__ = ("_func", "_depends")
2428

25-
def __init__(self, func: Callable[[...], T], *args, **kwargs):
29+
def __init__(self, func: Callable[..., T], *args, **kwargs):
2630
self._func = functools.partial(intercept_args(func), *args, **kwargs)
2731

2832
def _evaluate(self) -> T:

pif/providers/provider.py

+12-7
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,15 @@
1111
from __future__ import annotations
1212

1313
import abc
14-
from typing import Self
14+
from typing import Generic, TypeVar
1515

16+
__all__ = ("Provider", "Override")
1617

17-
class Provider[T](abc.ABC):
18+
T = TypeVar("T")
19+
U = TypeVar("U")
20+
21+
22+
class Provider(abc.ABC, Generic[T]):
1823
"""
1924
Signposts something that can be injected.
2025
"""
@@ -37,13 +42,13 @@ def _evaluate(self) -> T:
3742
"""
3843
return self()
3944

40-
def override[U: Provider | None](self, provider: U) -> Override[U]:
45+
def override(self, provider: Provider[U] | None) -> Override[Provider[U] | None]:
4146
"""
4247
Override the current providers value with another provider.
4348
"""
4449
return Override(self, provider)
4550

46-
def override_existing[U](self, value: U) -> Override[Provider[T]]:
51+
def override_existing(self, value: U) -> Override[Provider[U]]:
4752
"""
4853
Override the current provider with an existing singleton.
4954
"""
@@ -52,21 +57,21 @@ def override_existing[U](self, value: U) -> Override[Provider[T]]:
5257
return self.override(ExistingSingleton(value))
5358

5459

55-
class Override[ProviderT: Provider]:
60+
class Override(Generic[T]):
5661
"""
5762
A context manager to implement overrides for providers.
5863
"""
5964

6065
__slots__ = ("_base", "_override", "_before")
6166

62-
def __init__(self, base: Provider, override: ProviderT | None = None):
67+
def __init__(self, base: Provider, override: Provider[T] | None = None):
6368
# noinspection PyProtectedMember
6469
self._before = base._override
6570
self._base = base
6671
self._override = override
6772
base._override = override
6873

69-
def __enter__(self) -> Self:
74+
def __enter__(self) -> Override[T]:
7075
yield self
7176

7277
def disable(self) -> None:

pif/providers/singleton.py

+6-3
Original file line numberDiff line numberDiff line change
@@ -9,15 +9,18 @@
99
# https://github.com/scottzach1/python-injector-framework
1010

1111
import functools
12-
from typing import Callable
12+
from typing import Callable, TypeVar
1313

1414
from pif.providers.provider import Provider
1515
from pif.providers.util import intercept_args
1616

17+
__all__ = ("Singleton",)
18+
19+
T = TypeVar("T")
1720
UNSET = object()
1821

1922

20-
class Singleton[T](Provider):
23+
class Singleton(Provider[T]):
2124
"""
2225
Provide a singleton instance.
2326
@@ -26,7 +29,7 @@ class Singleton[T](Provider):
2629

2730
__slots__ = ("_func", "_func", "_result", "_depends")
2831

29-
def __init__(self, func: Callable[[...], T], *args, **kwargs):
32+
def __init__(self, func: Callable[..., T], *args, **kwargs):
3033
self._func = functools.partial(intercept_args(func), *args, **kwargs)
3134
self._result = UNSET
3235

pif/wiring.py

+9-4
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,12 @@
1313
import inspect
1414
import itertools
1515
import types
16-
from typing import Any, Callable
16+
from typing import Any, Callable, TypeVar
1717

1818
from pif.providers.provider import Provider
1919

20+
__all__ = ("intercept", "patch_args", "inject", "is_patched", "patch_method", "unpatch_method", "wire", "unwire")
21+
2022

2123
def intercept(func):
2224
"""
@@ -62,7 +64,10 @@ def patch_args(
6264
return args, kwargs
6365

6466

65-
def inject[T: Callable](func: T) -> T:
67+
TCallable = TypeVar("TCallable", bound=Callable)
68+
69+
70+
def inject(func: TCallable) -> TCallable:
6671
"""
6772
Get a decorated copy of `func` with patched arguments.
6873
@@ -97,7 +102,7 @@ def is_patched(func: Callable | types.FunctionType) -> bool:
97102
return hasattr(func, "_patched_func")
98103

99104

100-
def patch_method[T: Callable | types.FunctionType](func: T) -> T:
105+
def patch_method(func: TCallable) -> TCallable:
101106
"""
102107
Return a "patched" version of the method provided.
103108
@@ -112,7 +117,7 @@ def patch_method[T: Callable | types.FunctionType](func: T) -> T:
112117
return func
113118

114119

115-
def unpatch_method[T: Callable | types.FunctionType](func: T) -> T:
120+
def unpatch_method(func: TCallable) -> TCallable:
116121
"""
117122
Get an "unpatched" copy of a method.
118123

poetry.lock

+29-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+1-1
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ readme = "README.md"
88
packages = [{ include = "pif" }]
99

1010
[tool.poetry.dependencies]
11-
python = "^3.12"
11+
python = "^3.10"
1212

1313
[tool.poetry.group.dev.dependencies]
1414
pytest = "^8.2.1"

0 commit comments

Comments
 (0)