Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitb831695

Browse files
authored
refactor: entrypoint.py
1 parent8792bb3 commitb831695

File tree

6 files changed

+263
-228
lines changed

6 files changed

+263
-228
lines changed

‎injection/_core/asfunction.py‎

Lines changed: 35 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
fromcollections.abcimportCallable
2-
fromfunctoolsimportwraps
1+
fromcollections.abcimportAwaitable,Callable
2+
fromfunctoolsimportupdate_wrapper
33
frominspectimportiscoroutinefunction
44
fromtypingimportAny,Protocol
55

@@ -21,33 +21,45 @@ def asfunction[**P, T](
2121
module:Module|None=None,
2222
threadsafe:bool|None=None,
2323
)->Any:
24-
module=moduleormod()
25-
2624
defdecorator(wp:AsFunctionWrappedType[P,T])->Callable[P,T]:
2725
fake_method=wp.__call__.__get__(NotImplemented,wp)
28-
factory:Caller[...,Callable[P,T]]=module.make_injected_function(
29-
wp,
30-
threadsafe=threadsafe,
31-
).__injection_metadata__
26+
factory:Caller[...,Callable[P,T]]= (
27+
(moduleormod())
28+
.make_injected_function(
29+
wp,
30+
threadsafe=threadsafe,
31+
)
32+
.__injection_metadata__
33+
)
3234

33-
wrapper:Callable[P,T]
35+
wrapper:Callable[P,T]= (
36+
_wrap_async(factory)# type: ignore[arg-type, assignment]
37+
ifiscoroutinefunction(fake_method)
38+
else_wrap_sync(factory)
39+
)
40+
wrapper=update_wrapper(wrapper,fake_method)
3441

35-
ifiscoroutinefunction(fake_method):
42+
forattributein ("__name__","__qualname__"):
43+
setattr(wrapper,attribute,getattr(wp,attribute))
3644

37-
@wraps(fake_method)
38-
asyncdefwrapper(*args:P.args,**kwargs:P.kwargs)->Any:
39-
self=awaitfactory.acall()
40-
returnawaitself(*args,**kwargs)# type: ignore[misc]
45+
returnwrapper
4146

42-
else:
47+
returndecorator(wrapped)ifwrappedelsedecorator
4348

44-
@wraps(fake_method)
45-
defwrapper(*args:P.args,**kwargs:P.kwargs)->T:
46-
self=factory.call()
47-
returnself(*args,**kwargs)
4849

49-
wrapper.__name__=wp.__name__
50-
wrapper.__qualname__=wp.__qualname__
51-
returnwrapper
50+
def_wrap_async[**P,T](
51+
factory:Caller[...,Callable[P,Awaitable[T]]],
52+
)->Callable[P,Awaitable[T]]:
53+
asyncdefwrapper(*args:P.args,**kwargs:P.kwargs)->T:
54+
self=awaitfactory.acall()
55+
returnawaitself(*args,**kwargs)
5256

53-
returndecorator(wrapped)ifwrappedelsedecorator
57+
returnwrapper
58+
59+
60+
def_wrap_sync[**P,T](factory:Caller[...,Callable[P,T]])->Callable[P,T]:
61+
defwrapper(*args:P.args,**kwargs:P.kwargs)->T:
62+
self=factory.call()
63+
returnself(*args,**kwargs)
64+
65+
returnwrapper

‎injection/entrypoint.py‎

Lines changed: 128 additions & 88 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,104 @@
11
from __future__importannotations
22

33
importasyncio
4-
fromcollections.abcimportAsyncIterator,Awaitable,Callable,Coroutine,Iterator
5-
fromcontextlibimportasynccontextmanager,contextmanager
4+
fromabcimportABC,abstractmethod
5+
fromcollections.abcimportAwaitable,Callable,Coroutine,Iterator,Sequence
6+
fromcontextlibimportcontextmanager
67
fromdataclassesimportdataclass,field
78
fromfunctoolsimportwraps
89
fromtypesimportModuleTypeasPythonModule
9-
fromtypingimportTYPE_CHECKING,Any,Concatenate,Protocol,Self,final,overload
10+
fromtypingimport (
11+
TYPE_CHECKING,
12+
Any,
13+
Concatenate,
14+
Protocol,
15+
Self,
16+
overload,
17+
runtime_checkable,
18+
)
1019

1120
frominjectionimportModule
1221
frominjection.loadersimportProfileLoader,PythonModuleLoader
1322

1423
__all__= ("AsyncEntrypoint","Entrypoint","entrypointmaker")
1524

25+
typeEntrypoint[**P,T]=EntrypointBuilder[P,Any,T]
26+
typeAsyncEntrypoint[**P,T]=Entrypoint[P,Awaitable[T]]
1627

17-
typeAsyncEntrypoint[**P,T]=Entrypoint[P,Coroutine[Any,Any,T]]
1828
typeEntrypointSetupMethod[**P,**EPP,T1,T2]=Callable[
1929
Concatenate[Entrypoint[EPP,T1],P],
2030
Entrypoint[EPP,T2],
2131
]
2232

2333

34+
classRule[**P,T1,T2](ABC):
35+
__slots__= ()
36+
37+
@abstractmethod
38+
defapply(self,wrapped:Callable[P,T1])->Callable[P,T2]:
39+
raiseNotImplementedError
40+
41+
42+
@dataclass(repr=False,eq=False,frozen=True,slots=True)
43+
class_AsyncToSyncRule[**P,T](Rule[P,Awaitable[T],T]):
44+
run:Callable[[Awaitable[T]],T]
45+
46+
defapply(self,wrapped:Callable[P,Awaitable[T]])->Callable[P,T]:
47+
@wraps(wrapped)
48+
defwrapper(*args:P.args,**kwargs:P.kwargs)->T:
49+
returnself.run(wrapped(*args,**kwargs))
50+
51+
returnwrapper
52+
53+
54+
@dataclass(repr=False,eq=False,frozen=True,slots=True)
55+
class_DecorateRule[**P,T1,T2](Rule[P,T1,T2]):
56+
decorator:Callable[[Callable[P,T1]],Callable[P,T2]]
57+
58+
defapply(self,wrapped:Callable[P,T1])->Callable[P,T2]:
59+
returnself.decorator(wrapped)
60+
61+
62+
@dataclass(repr=False,eq=False,frozen=True,slots=True)
63+
class_InjectRule[**P,T](Rule[P,T,T]):
64+
module:Module
65+
66+
defapply(self,wrapped:Callable[P,T])->Callable[P,T]:
67+
returnself.module.make_injected_function(wrapped)
68+
69+
70+
@dataclass(repr=False,eq=False,frozen=True,slots=True)
71+
class_LoadModulesRule[**P,T](Rule[P,T,T]):
72+
loader:PythonModuleLoader
73+
packages:Sequence[PythonModule|str]
74+
75+
defapply(self,wrapped:Callable[P,T])->Callable[P,T]:
76+
returnself.__decorator()(wrapped)
77+
78+
@contextmanager
79+
def__decorator(self)->Iterator[None]:
80+
self.loader.load(*self.packages)
81+
yield
82+
83+
84+
@dataclass(repr=False,eq=False,frozen=True,slots=True)
85+
class_LoadProfileRule[**P,T](Rule[P,T,T]):
86+
loader:ProfileLoader
87+
profile_name:str
88+
89+
defapply(self,wrapped:Callable[P,T])->Callable[P,T]:
90+
returnself.__decorator()(wrapped)
91+
92+
@contextmanager
93+
def__decorator(self)->Iterator[None]:
94+
withself.loader.load(self.profile_name):
95+
yield
96+
97+
98+
@runtime_checkable
2499
class_EntrypointDecorator[**P,T1,T2](Protocol):
100+
__slots__= ()
101+
25102
ifTYPE_CHECKING:# pragma: no cover
26103

27104
@overload
@@ -42,18 +119,21 @@ def __call__(
42119
autocall:bool= ...,
43120
)->Callable[[Callable[P,T1]],Callable[P,T2]]: ...
44121

122+
@abstractmethod
45123
def__call__(
46124
self,
47125
wrapped:Callable[P,T1]|None= ...,
48126
/,
49127
*,
50128
autocall:bool= ...,
51-
)->Any: ...
129+
)->Any:
130+
raiseNotImplementedError
52131

53132

54133
# SMP = Setup Method Parameters
55134
# EPP = EntryPoint Parameters
56135

136+
57137
ifTYPE_CHECKING:# pragma: no cover
58138

59139
@overload
@@ -85,114 +165,74 @@ def entrypointmaker[**SMP, **EPP, T1, T2](
85165
defdecorator(
86166
wp:EntrypointSetupMethod[SMP,EPP,T1,T2],
87167
)->_EntrypointDecorator[EPP,T1,T2]:
88-
returnEntrypoint._make_decorator(wp,profile_loader)
168+
pl= (profile_loaderorProfileLoader()).init()
169+
setup_method=pl.module.make_injected_function(wp)
170+
returnsetup_method(EntrypointBuilder(pl))# type: ignore[call-arg]
89171

90172
returndecorator(wrapped)ifwrappedelsedecorator
91173

92174

93-
@final
94175
@dataclass(repr=False,eq=False,frozen=True,slots=True)
95-
classEntrypoint[**P,T]:
96-
function:Callable[P,T]
176+
classEntrypointBuilder[**P,T1,T2](_EntrypointDecorator[P,T1,T2]):
97177
profile_loader:ProfileLoader=field(default_factory=ProfileLoader)
178+
__rules:list[Rule[P,Any,Any]]=field(default_factory=list,init=False)
179+
180+
def__call__(
181+
self,
182+
wrapped:Callable[P,T1]|None=None,
183+
/,
184+
*,
185+
autocall:bool=False,
186+
)->Any:
187+
defdecorator(wp:Callable[P,T1])->Callable[P,T2]:
188+
wrapper=self._apply(wp)
189+
190+
ifautocall:
191+
wrapper()# type: ignore[call-arg]
98192

99-
def__call__(self,/,*args:P.args,**kwargs:P.kwargs)->T:
100-
returnself.function(*args,**kwargs)
193+
returnwrapper
101194

102-
@property
103-
def__module(self)->Module:
104-
returnself.profile_loader.module
195+
returndecorator(wrapped)ifwrappedelsedecorator
105196

106197
defasync_to_sync[_T](
107-
self:AsyncEntrypoint[P,_T],
198+
self:EntrypointBuilder[P,T1,Awaitable[_T]],
108199
run:Callable[[Coroutine[Any,Any,_T]],_T]=asyncio.run,
109200
/,
110-
)->Entrypoint[P,_T]:
111-
function=self.function
201+
)->EntrypointBuilder[P,T1,_T]:
202+
returnself._add_rule(_AsyncToSyncRule(run))# type: ignore[arg-type]
112203

113-
@wraps(function)
114-
defwrapper(*args:P.args,**kwargs:P.kwargs)->_T:
115-
returnrun(function(*args,**kwargs))
116-
117-
returnself.__recreate(wrapper)
118-
119-
defdecorate(
204+
defdecorate[_T](
120205
self,
121-
decorator:Callable[[Callable[P,T]],Callable[P,T]],
206+
decorator:Callable[[Callable[P,T2]],Callable[P,_T]],
122207
/,
123-
)->Self:
124-
returnself.__recreate(decorator(self.function))
208+
)->EntrypointBuilder[P,T1,_T]:
209+
returnself._add_rule(_DecorateRule(decorator))
125210

126211
definject(self)->Self:
127-
returnself.decorate(self.__module.make_injected_function)
212+
self._add_rule(_InjectRule(self.profile_loader.module))
213+
returnself
128214

129215
defload_modules(
130216
self,
131-
/,
132217
loader:PythonModuleLoader,
133218
*packages:PythonModule|str,
134219
)->Self:
135-
returnself.setup(lambda:loader.load(*packages))
220+
self._add_rule(_LoadModulesRule(loader,packages))
221+
returnself
136222

137223
defload_profile(self,name:str,/)->Self:
138-
@contextmanager
139-
defdecorator(loader:ProfileLoader)->Iterator[None]:
140-
withloader.load(name):
141-
yield
142-
143-
returnself.decorate(decorator(self.profile_loader))
144-
145-
defsetup(self,function:Callable[...,Any],/)->Self:
146-
@contextmanager
147-
defdecorator()->Iterator[Any]:
148-
yieldfunction()
224+
self._add_rule(_LoadProfileRule(self.profile_loader,name))
225+
returnself
149226

150-
returnself.decorate(decorator())
151-
152-
defasync_setup[_T](
153-
self:AsyncEntrypoint[P,_T],
154-
function:Callable[...,Awaitable[Any]],
155-
/,
156-
)->AsyncEntrypoint[P,_T]:
157-
@asynccontextmanager
158-
asyncdefdecorator()->AsyncIterator[Any]:
159-
yieldawaitfunction()
160-
161-
returnself.decorate(decorator())
162-
163-
def__recreate[**_P,_T](
164-
self:Entrypoint[Any,Any],
165-
function:Callable[_P,_T],
166-
/,
167-
)->Entrypoint[_P,_T]:
168-
returntype(self)(function,self.profile_loader)
169-
170-
@classmethod
171-
def_make_decorator[**_P,_T](
172-
cls,
173-
setup_method:EntrypointSetupMethod[_P,P,T,_T],
174-
/,
175-
profile_loader:ProfileLoader|None=None,
176-
)->_EntrypointDecorator[P,T,_T]:
177-
profile_loader=profile_loaderorProfileLoader()
178-
setup_method=profile_loader.module.make_injected_function(setup_method)
179-
180-
defentrypoint_decorator(
181-
wrapped:Callable[P,T]|None=None,
182-
/,
183-
*,
184-
autocall:bool=False,
185-
)->Any:
186-
defdecorator(wp:Callable[P,T])->Callable[P,_T]:
187-
profile_loader.init()
188-
self=cls(wp,profile_loader)
189-
wrapper=setup_method(self).function# type: ignore[call-arg]
190-
191-
ifautocall:
192-
wrapper()# type: ignore[call-arg]
193-
194-
returnwrapper
227+
def_add_rule[_T](
228+
self,
229+
rule:Rule[P,T2,_T],
230+
)->EntrypointBuilder[P,T1,_T]:
231+
self.__rules.append(rule)
232+
returnself# type: ignore[return-value]
195233

196-
returndecorator(wrapped)ifwrappedelsedecorator
234+
def_apply(self,function:Callable[P,T1],/)->Callable[P,T2]:
235+
forruleinself.__rules:
236+
function=rule.apply(function)
197237

198-
returnentrypoint_decorator
238+
returnfunction# type: ignore[return-value]

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp