Skip to content

Commit e3bda43

Browse files
committed
Refactor providers into package
1 parent d57969f commit e3bda43

File tree

7 files changed

+125
-68
lines changed

7 files changed

+125
-68
lines changed

pif/providers/__init__.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
from pif.providers.blank import BlankProvider
2+
from pif.providers.existing_singleton import ExistingSingleton
3+
from pif.providers.factory import Factory
4+
from pif.providers.provider import Provider
5+
from pif.providers.singleton import Singleton

pif/providers/blank.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# _ _ _ _
2+
# ___ ___ ___ | |_| |_ ______ _ ___| |__ / |
3+
# / __|/ __/ _ \| __| __|_ / _` |/ __| '_ \| |
4+
# \__ \ (_| (_) | |_| |_ / / (_| | (__| | | | |
5+
# |___/\___\___/ \__|\__/___\__,_|\___|_| |_|_|
6+
#
7+
# Zac Scott (github.com/scottzach1)
8+
#
9+
# https://github.com/scottzach1/python-injector-framework
10+
11+
from pif import exceptions
12+
from pif.providers.provider import Provider
13+
14+
15+
class BlankProvider(Provider):
16+
"""
17+
A placeholder for a provider.
18+
"""
19+
20+
__slots__ = tuple()
21+
22+
def _evaluate(self) -> None:
23+
raise exceptions.BlankProviderException()

pif/providers/existing_singleton.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
# _ _ _ _
2+
# ___ ___ ___ | |_| |_ ______ _ ___| |__ / |
3+
# / __|/ __/ _ \| __| __|_ / _` |/ __| '_ \| |
4+
# \__ \ (_| (_) | |_| |_ / / (_| | (__| | | | |
5+
# |___/\___\___/ \__|\__/___\__,_|\___|_| |_|_|
6+
#
7+
# Zac Scott (github.com/scottzach1)
8+
#
9+
# https://github.com/scottzach1/python-injector-framework
10+
11+
from pif.providers.provider import Provider
12+
13+
14+
class ExistingSingleton[T](Provider):
15+
"""
16+
Provide an existing object instance.
17+
"""
18+
19+
__slots__ = ("t",)
20+
21+
def __init__(self, t: T):
22+
self.t = t
23+
24+
def _evaluate(self) -> T:
25+
return self.t

pif/providers/factory.py

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
# _ _ _ _
2+
# ___ ___ ___ | |_| |_ ______ _ ___| |__ / |
3+
# / __|/ __/ _ \| __| __|_ / _` |/ __| '_ \| |
4+
# \__ \ (_| (_) | |_| |_ / / (_| | (__| | | | |
5+
# |___/\___\___/ \__|\__/___\__,_|\___|_| |_|_|
6+
#
7+
# Zac Scott (github.com/scottzach1)
8+
#
9+
# https://github.com/scottzach1/python-injector-framework
10+
11+
import functools
12+
from typing import Callable
13+
14+
from pif.providers.provider import Provider
15+
16+
17+
class Factory[T](Provider):
18+
"""
19+
Generate a new instance every call.
20+
"""
21+
22+
__slots__ = ("_func", "_depends")
23+
24+
def __init__(self, func: Callable[[...], T], *args, **kwargs):
25+
self._func = functools.partial(func, *args, **kwargs)
26+
27+
def _evaluate(self) -> T:
28+
return self._func()

pif/providers.py renamed to pif/providers/provider.py

Lines changed: 3 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -11,10 +11,7 @@
1111
from __future__ import annotations
1212

1313
import abc
14-
import functools
15-
from typing import Callable, Self
16-
17-
from pif import exceptions
14+
from typing import Self
1815

1916

2017
class Provider[T](abc.ABC):
@@ -50,6 +47,8 @@ def override_existing[U](self, value: U) -> Override[Provider[T]]:
5047
"""
5148
Override the current provider with an existing singleton.
5249
"""
50+
from .existing_singleton import ExistingSingleton
51+
5352
return self.override(ExistingSingleton(value))
5453

5554

@@ -78,62 +77,3 @@ def disable(self) -> None:
7877

7978
def __exit__(self, exc_type, exc_val, exc_tb):
8079
self.disable()
81-
82-
83-
class BlankProvider(Provider):
84-
"""
85-
A placeholder for a provider.
86-
"""
87-
88-
__slots__ = tuple()
89-
90-
def _evaluate(self) -> None:
91-
raise exceptions.BlankProviderException()
92-
93-
94-
class ExistingSingleton[T](Provider):
95-
"""
96-
Provide an existing object instance.
97-
"""
98-
99-
__slots__ = ("t",)
100-
101-
def __init__(self, t: T):
102-
self.t = t
103-
104-
def _evaluate(self) -> T:
105-
return self.t
106-
107-
108-
UNSET = object()
109-
110-
111-
class Singleton[T](Provider):
112-
"""
113-
Provide a singleton instance.
114-
"""
115-
116-
__slots__ = ("_func", "_func", "_result", "_depends")
117-
118-
def __init__(self, func: Callable[[...], T], *args, **kwargs):
119-
self._func = functools.partial(func, *args, **kwargs)
120-
self._result = UNSET
121-
122-
def _evaluate(self) -> T:
123-
if self._result is UNSET:
124-
self._result = self._func()
125-
return self._result
126-
127-
128-
class Factory[T](Provider):
129-
"""
130-
Generate a new instance every call.
131-
"""
132-
133-
__slots__ = ("_func", "_depends")
134-
135-
def __init__(self, func: Callable[[...], T], *args, **kwargs):
136-
self._func = functools.partial(func, *args, **kwargs)
137-
138-
def _evaluate(self) -> T:
139-
return self._func()

pif/providers/singleton.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
# _ _ _ _
2+
# ___ ___ ___ | |_| |_ ______ _ ___| |__ / |
3+
# / __|/ __/ _ \| __| __|_ / _` |/ __| '_ \| |
4+
# \__ \ (_| (_) | |_| |_ / / (_| | (__| | | | |
5+
# |___/\___\___/ \__|\__/___\__,_|\___|_| |_|_|
6+
#
7+
# Zac Scott (github.com/scottzach1)
8+
#
9+
# https://github.com/scottzach1/python-injector-framework
10+
11+
import functools
12+
from typing import Callable
13+
14+
from pif.providers.provider import Provider
15+
16+
UNSET = object()
17+
18+
19+
class Singleton[T](Provider):
20+
"""
21+
Provide a singleton instance.
22+
"""
23+
24+
__slots__ = ("_func", "_func", "_result", "_depends")
25+
26+
def __init__(self, func: Callable[[...], T], *args, **kwargs):
27+
self._func = functools.partial(func, *args, **kwargs)
28+
self._result = UNSET
29+
30+
def _evaluate(self) -> T:
31+
if self._result is UNSET:
32+
self._result = self._func()
33+
return self._result

pif/wiring.py

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
import types
1616
from typing import Any, Callable
1717

18-
from pif import providers
18+
from pif.providers.provider import Provider
1919

2020

2121
def patch_args(
@@ -32,7 +32,7 @@ def patch_args(
3232
:return: injected args and kwargs to pass to func.
3333
"""
3434
for i, (name, value) in enumerate(signature.parameters.items()):
35-
if isinstance(value.default, providers.Provider) and i >= len(args):
35+
if isinstance(value.default, Provider) and i >= len(args):
3636
if value.kind == inspect.Parameter.POSITIONAL_ONLY:
3737
args = (
3838
*args,
@@ -54,9 +54,12 @@ def inject[T: Callable](func: T) -> T:
5454
:param func: to decorate.
5555
:return: the decorated function.
5656
"""
57-
signature = inspect.signature(func)
57+
try:
58+
signature = inspect.signature(func)
59+
except ValueError:
60+
return func # We cannot derive signature from provided callable.
5861

59-
if not any(p for p in signature.parameters.values() if isinstance(p.default, providers.Provider)):
62+
if not any(p for p in signature.parameters.values() if isinstance(p.default, Provider)):
6063
return func
6164

6265
@functools.wraps(func)
@@ -88,7 +91,7 @@ def patch_method[T: Callable | types.FunctionType](func: T) -> T:
8891
:param func: to patch default values.
8992
:return: a "patched" version of the method provided.
9093
"""
91-
if any(1 for param in inspect.signature(func).parameters.values() if isinstance(param.default, providers.Provider)):
94+
if any(1 for param in inspect.signature(func).parameters.values() if isinstance(param.default, Provider)):
9295
return inject(func)
9396

9497
return func

0 commit comments

Comments
 (0)