aspyx 1.5.1__py3-none-any.whl → 1.5.3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of aspyx might be problematic. Click here for more details.
- aspyx/di/aop/aop.py +57 -21
- aspyx/di/di.py +6 -7
- aspyx/di/threading/synchronized.py +3 -1
- aspyx/exception/exception_manager.py +20 -18
- aspyx/reflection/proxy.py +10 -3
- aspyx/reflection/reflection.py +8 -4
- aspyx/threading/__init__.py +2 -0
- aspyx/threading/context_local.py +48 -0
- aspyx/util/__init__.py +2 -0
- aspyx/util/logger.py +15 -0
- {aspyx-1.5.1.dist-info → aspyx-1.5.3.dist-info}/METADATA +1 -1
- {aspyx-1.5.1.dist-info → aspyx-1.5.3.dist-info}/RECORD +14 -12
- {aspyx-1.5.1.dist-info → aspyx-1.5.3.dist-info}/WHEEL +0 -0
- {aspyx-1.5.1.dist-info → aspyx-1.5.3.dist-info}/licenses/LICENSE +0 -0
aspyx/di/aop/aop.py
CHANGED
|
@@ -3,6 +3,7 @@ This module provides aspect-oriented programming (AOP) capabilities for Python a
|
|
|
3
3
|
"""
|
|
4
4
|
from __future__ import annotations
|
|
5
5
|
|
|
6
|
+
import functools
|
|
6
7
|
from abc import ABC, abstractmethod
|
|
7
8
|
import inspect
|
|
8
9
|
import re
|
|
@@ -13,7 +14,7 @@ from enum import auto, Enum
|
|
|
13
14
|
from typing import Optional, Dict, Type, Callable
|
|
14
15
|
|
|
15
16
|
from aspyx.reflection import Decorators, TypeDescriptor
|
|
16
|
-
from aspyx.di import injectable, order,
|
|
17
|
+
from aspyx.di import injectable, order, Environment, PostProcessor
|
|
17
18
|
|
|
18
19
|
class AOPException(Exception):
|
|
19
20
|
"""
|
|
@@ -64,7 +65,7 @@ class AspectTarget(ABC):
|
|
|
64
65
|
def __init__(self):
|
|
65
66
|
self._clazz = None
|
|
66
67
|
self._instance = None
|
|
67
|
-
self._async =
|
|
68
|
+
self._async : Optional[bool] = None
|
|
68
69
|
self._function = None
|
|
69
70
|
self._type = None
|
|
70
71
|
|
|
@@ -118,6 +119,16 @@ class AspectTarget(ABC):
|
|
|
118
119
|
self._async = True
|
|
119
120
|
return self
|
|
120
121
|
|
|
122
|
+
def that_are_sync(self) -> AspectTarget:
|
|
123
|
+
"""
|
|
124
|
+
matches methods that are sync
|
|
125
|
+
|
|
126
|
+
Returns:
|
|
127
|
+
AspectTarget: self
|
|
128
|
+
"""
|
|
129
|
+
self._async = False
|
|
130
|
+
return self
|
|
131
|
+
|
|
121
132
|
def of_type(self, type: Type) -> AspectTarget:
|
|
122
133
|
"""
|
|
123
134
|
matches methods belonging to a class or classes that are subclasses of the specified type
|
|
@@ -186,25 +197,25 @@ class ClassAspectTarget(AspectTarget):
|
|
|
186
197
|
#descriptor = TypeDescriptor.for_type(func)
|
|
187
198
|
# type
|
|
188
199
|
|
|
189
|
-
if
|
|
200
|
+
if self.types:
|
|
190
201
|
if next((type for type in self.types if issubclass(clazz, type)), None) is None:
|
|
191
202
|
return False
|
|
192
203
|
|
|
193
204
|
# decorators
|
|
194
205
|
|
|
195
|
-
if
|
|
206
|
+
if self.decorators:
|
|
196
207
|
if next((decorator for decorator in self.decorators if class_descriptor.has_decorator(decorator)), None) is None:
|
|
197
208
|
return False
|
|
198
209
|
|
|
199
210
|
# names
|
|
200
211
|
|
|
201
|
-
if
|
|
212
|
+
if self.names:
|
|
202
213
|
if next((name for name in self.names if name == clazz.__name__), None) is None:
|
|
203
214
|
return False
|
|
204
215
|
|
|
205
216
|
# patterns
|
|
206
217
|
|
|
207
|
-
if
|
|
218
|
+
if self.patterns:
|
|
208
219
|
if next((pattern for pattern in self.patterns if re.fullmatch(pattern, clazz.__name__) is not None), None) is None:
|
|
209
220
|
return False
|
|
210
221
|
|
|
@@ -217,10 +228,14 @@ class MethodAspectTarget(AspectTarget):
|
|
|
217
228
|
An AspectTarget matching methods
|
|
218
229
|
"""
|
|
219
230
|
|
|
220
|
-
|
|
231
|
+
__slots__ = ["belonging_to"]
|
|
221
232
|
|
|
222
|
-
|
|
233
|
+
# constructor
|
|
223
234
|
|
|
235
|
+
def __init__(self):
|
|
236
|
+
super().__init__()
|
|
237
|
+
|
|
238
|
+
self.belonging_to : list[ClassAspectTarget] = []
|
|
224
239
|
# public
|
|
225
240
|
|
|
226
241
|
def _matches_self(self, clazz : Type, func):
|
|
@@ -228,32 +243,44 @@ class MethodAspectTarget(AspectTarget):
|
|
|
228
243
|
|
|
229
244
|
method_descriptor = descriptor.get_method(func.__name__)
|
|
230
245
|
|
|
246
|
+
# classes
|
|
247
|
+
|
|
248
|
+
if self.belonging_to:
|
|
249
|
+
match = False
|
|
250
|
+
for classes in self.belonging_to:
|
|
251
|
+
if classes._matches(clazz, func):
|
|
252
|
+
match = True
|
|
253
|
+
break
|
|
254
|
+
|
|
255
|
+
if not match:
|
|
256
|
+
return False
|
|
257
|
+
|
|
231
258
|
# async
|
|
232
259
|
|
|
233
|
-
if self._async is not method_descriptor.is_async():
|
|
260
|
+
if self._async is not None and self._async is not method_descriptor.is_async():
|
|
234
261
|
return False
|
|
235
262
|
|
|
236
263
|
# type
|
|
237
264
|
|
|
238
|
-
if
|
|
265
|
+
if self.types:
|
|
239
266
|
if next((type for type in self.types if issubclass(clazz, type)), None) is None:
|
|
240
267
|
return False
|
|
241
268
|
|
|
242
269
|
# decorators
|
|
243
270
|
|
|
244
|
-
if
|
|
271
|
+
if self.decorators:
|
|
245
272
|
if next((decorator for decorator in self.decorators if method_descriptor.has_decorator(decorator)), None) is None:
|
|
246
273
|
return False
|
|
247
274
|
|
|
248
275
|
# names
|
|
249
276
|
|
|
250
|
-
if
|
|
277
|
+
if self.names:
|
|
251
278
|
if next((name for name in self.names if name == func.__name__), None) is None:
|
|
252
279
|
return False
|
|
253
280
|
|
|
254
281
|
# patterns
|
|
255
282
|
|
|
256
|
-
if
|
|
283
|
+
if self.patterns:
|
|
257
284
|
if next((pattern for pattern in self.patterns if re.fullmatch(pattern, func.__name__) is not None), None) is None:
|
|
258
285
|
return False
|
|
259
286
|
|
|
@@ -261,7 +288,14 @@ class MethodAspectTarget(AspectTarget):
|
|
|
261
288
|
|
|
262
289
|
return True
|
|
263
290
|
|
|
264
|
-
|
|
291
|
+
# fluent
|
|
292
|
+
|
|
293
|
+
def declared_by(self, classes: ClassAspectTarget) -> MethodAspectTarget:
|
|
294
|
+
self.belonging_to.append(classes)
|
|
295
|
+
|
|
296
|
+
return self
|
|
297
|
+
|
|
298
|
+
def methods() -> MethodAspectTarget:
|
|
265
299
|
"""
|
|
266
300
|
Create a new AspectTarget instance to define method aspect targets.
|
|
267
301
|
|
|
@@ -270,7 +304,7 @@ def methods() -> AspectTarget:
|
|
|
270
304
|
"""
|
|
271
305
|
return MethodAspectTarget()
|
|
272
306
|
|
|
273
|
-
def classes() ->
|
|
307
|
+
def classes() -> ClassAspectTarget:
|
|
274
308
|
"""
|
|
275
309
|
Create a new AspectTarget instance to define class aspect targets.
|
|
276
310
|
|
|
@@ -440,7 +474,7 @@ class Invocation:
|
|
|
440
474
|
"""
|
|
441
475
|
Proceed to the next aspect in the around chain up to the original method.
|
|
442
476
|
"""
|
|
443
|
-
if
|
|
477
|
+
if args or kwargs: # as soon as we have args, we replace the current ones
|
|
444
478
|
self.args = args
|
|
445
479
|
self.kwargs = kwargs
|
|
446
480
|
|
|
@@ -452,7 +486,7 @@ class Invocation:
|
|
|
452
486
|
"""
|
|
453
487
|
Proceed to the next aspect in the around chain up to the original method.
|
|
454
488
|
"""
|
|
455
|
-
if
|
|
489
|
+
if args or kwargs: # as soon as we have args, we replace the current ones
|
|
456
490
|
self.args = args
|
|
457
491
|
self.kwargs = kwargs
|
|
458
492
|
|
|
@@ -541,7 +575,7 @@ class Advices:
|
|
|
541
575
|
afters = cls.collect(clazz, member, AspectType.AFTER, environment)
|
|
542
576
|
errors = cls.collect(clazz, member, AspectType.ERROR, environment)
|
|
543
577
|
|
|
544
|
-
if
|
|
578
|
+
if befores or arounds or afters or errors:
|
|
545
579
|
return Aspects(
|
|
546
580
|
before=befores,
|
|
547
581
|
around=arounds,
|
|
@@ -563,7 +597,7 @@ def advice(cls):
|
|
|
563
597
|
Classes decorated with `@advice` are treated as advice classes.
|
|
564
598
|
They can contain methods decorated with `@before`, `@after`, `@around`, or `@error` to define aspects.
|
|
565
599
|
"""
|
|
566
|
-
Providers.register(ClassInstanceProvider(cls, True))
|
|
600
|
+
#Providers.register(ClassInstanceProvider(cls, True))
|
|
567
601
|
|
|
568
602
|
Decorators.add(cls, advice)
|
|
569
603
|
|
|
@@ -673,13 +707,15 @@ class AdviceProcessor(PostProcessor):
|
|
|
673
707
|
for member, aspects in aspect_dict.items():
|
|
674
708
|
Environment.logger.debug("add aspects for %s:%s", type(instance), member.__name__)
|
|
675
709
|
|
|
676
|
-
def wrap(jp):
|
|
710
|
+
def wrap(jp, member=member):
|
|
711
|
+
@functools.wraps(member)
|
|
677
712
|
def sync_wrapper(*args, **kwargs):
|
|
678
713
|
return Invocation(member, jp).call(*args, **kwargs)
|
|
679
714
|
|
|
680
715
|
return sync_wrapper
|
|
681
716
|
|
|
682
|
-
def wrap_async(jp):
|
|
717
|
+
def wrap_async(jp, member=member):
|
|
718
|
+
@functools.wraps(member)
|
|
683
719
|
async def async_wrapper(*args, **kwargs):
|
|
684
720
|
return await Invocation(member, jp).call_async(*args, **kwargs)
|
|
685
721
|
|
aspyx/di/di.py
CHANGED
|
@@ -552,7 +552,7 @@ class PostProcessor(LifecycleProcessor):
|
|
|
552
552
|
"""
|
|
553
553
|
__slots__ = []
|
|
554
554
|
|
|
555
|
-
|
|
555
|
+
@abstractmethod
|
|
556
556
|
def process(self, instance: object, environment: Environment):
|
|
557
557
|
pass
|
|
558
558
|
|
|
@@ -689,7 +689,7 @@ class Providers:
|
|
|
689
689
|
return True
|
|
690
690
|
|
|
691
691
|
def is_injectable(type: Type) -> bool:
|
|
692
|
-
if type
|
|
692
|
+
if type in [object, ABC]:
|
|
693
693
|
return False
|
|
694
694
|
|
|
695
695
|
if inspect.isabstract(type):
|
|
@@ -998,13 +998,13 @@ class Environment:
|
|
|
998
998
|
# inherit providers from parent
|
|
999
999
|
|
|
1000
1000
|
for provider_type, inherited_provider in self.parent.providers.items():
|
|
1001
|
+
provider = inherited_provider
|
|
1001
1002
|
if inherited_provider.get_scope() == "environment":
|
|
1002
1003
|
# replace with own environment instance provider
|
|
1003
1004
|
provider = EnvironmentInstanceProvider(self, cast(EnvironmentInstanceProvider, inherited_provider).provider)
|
|
1004
1005
|
provider.dependencies = [] # ??
|
|
1005
|
-
|
|
1006
|
-
|
|
1007
|
-
add_provider(provider_type, inherited_provider)
|
|
1006
|
+
|
|
1007
|
+
add_provider(provider_type, provider)
|
|
1008
1008
|
|
|
1009
1009
|
# inherit processors as is unless they have an environment scope
|
|
1010
1010
|
|
|
@@ -1012,8 +1012,7 @@ class Environment:
|
|
|
1012
1012
|
if self.providers[type(processor)].get_scope() != "environment":
|
|
1013
1013
|
self.lifecycle_processors.append(processor)
|
|
1014
1014
|
else:
|
|
1015
|
-
#
|
|
1016
|
-
self.lifecycle_processors.append(self.get(type(processor)))
|
|
1015
|
+
self.get(type(processor)) # will automatically be appended
|
|
1017
1016
|
else:
|
|
1018
1017
|
self.providers[SingletonScope] = SingletonScopeInstanceProvider()
|
|
1019
1018
|
self.providers[RequestScope] = RequestScopeInstanceProvider()
|
|
@@ -6,6 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
import threading
|
|
7
7
|
from weakref import WeakKeyDictionary
|
|
8
8
|
|
|
9
|
+
from aspyx.di import injectable
|
|
9
10
|
from aspyx.reflection import Decorators
|
|
10
11
|
from aspyx.di.aop import advice, around, methods, Invocation
|
|
11
12
|
|
|
@@ -20,6 +21,7 @@ def synchronized():
|
|
|
20
21
|
return decorator
|
|
21
22
|
|
|
22
23
|
@advice
|
|
24
|
+
@injectable()
|
|
23
25
|
class SynchronizeAdvice:
|
|
24
26
|
# constructor
|
|
25
27
|
|
|
@@ -38,7 +40,7 @@ class SynchronizeAdvice:
|
|
|
38
40
|
|
|
39
41
|
# around
|
|
40
42
|
|
|
41
|
-
@around(methods().decorated_with(synchronized))
|
|
43
|
+
@around(methods().decorated_with(synchronized).that_are_sync())
|
|
42
44
|
def synchronize_sync(self, invocation: Invocation):
|
|
43
45
|
with self.get_lock(invocation.args[0]):
|
|
44
46
|
return invocation.proceed()
|
|
@@ -107,6 +107,24 @@ class ExceptionManager:
|
|
|
107
107
|
|
|
108
108
|
# internal
|
|
109
109
|
|
|
110
|
+
def collect_handlers(self, instance: Any):
|
|
111
|
+
type_descriptor = TypeDescriptor.for_type(type(instance))
|
|
112
|
+
|
|
113
|
+
# analyze methods
|
|
114
|
+
|
|
115
|
+
for method in type_descriptor.get_methods():
|
|
116
|
+
if method.has_decorator(handle):
|
|
117
|
+
if len(method.param_types) == 1:
|
|
118
|
+
exception_type = method.param_types[0]
|
|
119
|
+
|
|
120
|
+
self.handler.append(Handler(
|
|
121
|
+
exception_type,
|
|
122
|
+
instance,
|
|
123
|
+
method.method,
|
|
124
|
+
))
|
|
125
|
+
else:
|
|
126
|
+
print(f"handler {method.method} expected to have one parameter")
|
|
127
|
+
|
|
110
128
|
@inject_environment()
|
|
111
129
|
def set_environment(self, environment: Environment):
|
|
112
130
|
self.environment = environment
|
|
@@ -114,23 +132,7 @@ class ExceptionManager:
|
|
|
114
132
|
@on_running()
|
|
115
133
|
def setup(self):
|
|
116
134
|
for handler_class in self.exception_handler_classes:
|
|
117
|
-
|
|
118
|
-
instance = self.environment.get(handler_class)
|
|
119
|
-
|
|
120
|
-
# analyze methods
|
|
121
|
-
|
|
122
|
-
for method in type_descriptor.get_methods():
|
|
123
|
-
if method.has_decorator(handle):
|
|
124
|
-
if len(method.param_types) == 1:
|
|
125
|
-
exception_type = method.param_types[0]
|
|
126
|
-
|
|
127
|
-
self.handler.append(Handler(
|
|
128
|
-
exception_type,
|
|
129
|
-
instance,
|
|
130
|
-
method.method,
|
|
131
|
-
))
|
|
132
|
-
else:
|
|
133
|
-
print(f"handler {method.method} expected to have one parameter")
|
|
135
|
+
self.collect_handlers(self.environment.get(handler_class))
|
|
134
136
|
|
|
135
137
|
def get_handlers(self, clazz: Type) -> Optional[Chain]:
|
|
136
138
|
chain = self.cache.get(clazz, None)
|
|
@@ -158,7 +160,7 @@ class ExceptionManager:
|
|
|
158
160
|
for i in range(0, len(chain) - 1):
|
|
159
161
|
chain[i].next = chain[i + 1]
|
|
160
162
|
|
|
161
|
-
if
|
|
163
|
+
if chain:
|
|
162
164
|
return chain[0]
|
|
163
165
|
else:
|
|
164
166
|
return None
|
aspyx/reflection/proxy.py
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
1
|
"""
|
|
2
2
|
Dynamic proxies for method interception and delegation.
|
|
3
3
|
"""
|
|
4
|
+
import functools
|
|
4
5
|
import inspect
|
|
6
|
+
from abc import ABC, abstractmethod
|
|
5
7
|
from typing import Generic, TypeVar, Type, Callable
|
|
6
8
|
|
|
7
9
|
T = TypeVar("T")
|
|
@@ -44,10 +46,12 @@ class DynamicProxy(Generic[T]):
|
|
|
44
46
|
self.args = args
|
|
45
47
|
self.kwargs = kwargs
|
|
46
48
|
|
|
47
|
-
class InvocationHandler:
|
|
49
|
+
class InvocationHandler(ABC):
|
|
50
|
+
@abstractmethod
|
|
48
51
|
def invoke(self, invocation: 'DynamicProxy.Invocation'):
|
|
49
52
|
pass
|
|
50
53
|
|
|
54
|
+
@abstractmethod
|
|
51
55
|
async def invoke_async(self, invocation: 'DynamicProxy.Invocation'):
|
|
52
56
|
return self.invoke(invocation)
|
|
53
57
|
|
|
@@ -73,13 +77,16 @@ class DynamicProxy(Generic[T]):
|
|
|
73
77
|
def __getattr__(self, name):
|
|
74
78
|
method = getattr(self.type, name)
|
|
75
79
|
|
|
76
|
-
if
|
|
80
|
+
if inspect.iscoroutinefunction(method):
|
|
81
|
+
|
|
82
|
+
@functools.wraps(method)
|
|
77
83
|
async def async_wrapper(*args, **kwargs):
|
|
78
|
-
return
|
|
84
|
+
return await self.invocation_handler.invoke_async(DynamicProxy.Invocation(self.type, method, *args, **kwargs))
|
|
79
85
|
|
|
80
86
|
return async_wrapper
|
|
81
87
|
|
|
82
88
|
else:
|
|
89
|
+
@functools.wraps(method)
|
|
83
90
|
def sync_wrapper(*args, **kwargs):
|
|
84
91
|
return self.invocation_handler.invoke(DynamicProxy.Invocation(self.type, method, *args, **kwargs))
|
|
85
92
|
|
aspyx/reflection/reflection.py
CHANGED
|
@@ -42,11 +42,15 @@ class Decorators:
|
|
|
42
42
|
decorator: the decorator
|
|
43
43
|
*args: any arguments supplied to the decorator
|
|
44
44
|
"""
|
|
45
|
-
|
|
46
|
-
if
|
|
45
|
+
current = func_or_class.__dict__.get('__decorators__')
|
|
46
|
+
if current is None:
|
|
47
47
|
setattr(func_or_class, '__decorators__', [DecoratorDescriptor(decorator, *args)])
|
|
48
48
|
else:
|
|
49
|
-
|
|
49
|
+
# Avoid mutating inherited list
|
|
50
|
+
if '__decorators__' not in func_or_class.__dict__:
|
|
51
|
+
current = list(current)
|
|
52
|
+
setattr(func_or_class, '__decorators__', current)
|
|
53
|
+
current.append(DecoratorDescriptor(decorator, *args))
|
|
50
54
|
|
|
51
55
|
@classmethod
|
|
52
56
|
def has_decorator(cls, func_or_class, callable: Callable) -> bool:
|
|
@@ -82,7 +86,7 @@ class Decorators:
|
|
|
82
86
|
if inspect.ismethod(func_or_class):
|
|
83
87
|
func_or_class = func_or_class.__func__ # unwrap bound method
|
|
84
88
|
|
|
85
|
-
#return getattr(func_or_class, '__decorators__', []) will return inherited as well
|
|
89
|
+
#return getattr(func_or_class, '__decorators__', []) #will return inherited as well
|
|
86
90
|
return func_or_class.__dict__.get('__decorators__', [])
|
|
87
91
|
|
|
88
92
|
|
aspyx/threading/__init__.py
CHANGED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import contextvars
|
|
2
|
+
from contextlib import contextmanager
|
|
3
|
+
from typing import Generic, Optional, TypeVar, Any
|
|
4
|
+
|
|
5
|
+
T = TypeVar("T")
|
|
6
|
+
|
|
7
|
+
class ContextLocal(Generic[T]):
|
|
8
|
+
"""
|
|
9
|
+
A context local value holder
|
|
10
|
+
"""
|
|
11
|
+
# constructor
|
|
12
|
+
|
|
13
|
+
def __init__(self, name: str, default: Optional[T] = None):
|
|
14
|
+
self.var = contextvars.ContextVar(name, default=default)
|
|
15
|
+
|
|
16
|
+
# public
|
|
17
|
+
|
|
18
|
+
def get(self) -> Optional[T]:
|
|
19
|
+
"""
|
|
20
|
+
return the current value or invoke the optional factory to compute one
|
|
21
|
+
|
|
22
|
+
Returns:
|
|
23
|
+
Optional[T]: the value associated with the current thread
|
|
24
|
+
"""
|
|
25
|
+
return self.var.get()
|
|
26
|
+
|
|
27
|
+
def set(self, value: Optional[T]) -> Any:
|
|
28
|
+
"""
|
|
29
|
+
set a value in the current thread
|
|
30
|
+
|
|
31
|
+
Args:
|
|
32
|
+
value: the value
|
|
33
|
+
"""
|
|
34
|
+
return self.var.set(value)
|
|
35
|
+
|
|
36
|
+
def reset(self, token) -> None:
|
|
37
|
+
"""
|
|
38
|
+
clear the value in the current thread
|
|
39
|
+
"""
|
|
40
|
+
self.var.reset(token)
|
|
41
|
+
|
|
42
|
+
@contextmanager
|
|
43
|
+
def use(self, value):
|
|
44
|
+
token = self.set(value)
|
|
45
|
+
try:
|
|
46
|
+
yield
|
|
47
|
+
finally:
|
|
48
|
+
self.reset(token)
|
aspyx/util/__init__.py
CHANGED
aspyx/util/logger.py
ADDED
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from typing import Optional, Dict
|
|
3
|
+
|
|
4
|
+
class Logger:
|
|
5
|
+
"""just syntactic sugar"""
|
|
6
|
+
|
|
7
|
+
@classmethod
|
|
8
|
+
def configure(cls,
|
|
9
|
+
default_level: int = logging.INFO,
|
|
10
|
+
format: str = "[%(asctime)s] %(levelname)s in %(filename)s:%(lineno)d - %(message)s",
|
|
11
|
+
levels: Optional[Dict[str, int]] = None):
|
|
12
|
+
logging.basicConfig(level=default_level, format=format)
|
|
13
|
+
if levels is not None:
|
|
14
|
+
for name, level in levels.items():
|
|
15
|
+
logging.getLogger(name).setLevel(level)
|
|
@@ -1,24 +1,26 @@
|
|
|
1
1
|
aspyx/__init__.py,sha256=MsSFjiLMLJZ7QhUPpVBWKiyDnCzryquRyr329NoCACI,2
|
|
2
2
|
aspyx/di/__init__.py,sha256=AGVU2VBWQyBxSssvbk_GOKrYWIYtcmSoIlupz-Oqxi4,1138
|
|
3
|
-
aspyx/di/di.py,sha256=
|
|
3
|
+
aspyx/di/di.py,sha256=V_BAV6DmFCoepPqAXhBz2GW6NwYaKokHb03HMz6A5Sw,44639
|
|
4
4
|
aspyx/di/aop/__init__.py,sha256=rn6LSpzFtUOlgaBATyhLRWBzFmZ6XoVKA9B8SgQzYEI,746
|
|
5
|
-
aspyx/di/aop/aop.py,sha256=
|
|
5
|
+
aspyx/di/aop/aop.py,sha256=RaZRmQ1Ie6jZqYm0X93hWQ89xHn8vpDSnsmRgfAV68k,19180
|
|
6
6
|
aspyx/di/configuration/__init__.py,sha256=flM9A79J2wfA5I8goQbxs4tTqYustR9tn_9s0YO2WJQ,484
|
|
7
7
|
aspyx/di/configuration/configuration.py,sha256=cXW40bPXiUZ9hUtBoZkSATT3nLrDPWsSqxtgASIBQaM,4375
|
|
8
8
|
aspyx/di/configuration/env_configuration_source.py,sha256=FXPvREzq2ZER6_GG5xdpx154TQQDxZVf7LW7cvaylAk,1446
|
|
9
9
|
aspyx/di/configuration/yaml_configuration_source.py,sha256=NDl3SeoLMNVlzHgfP-Ysvhco1tRew_zFnBL5gGy2WRk,550
|
|
10
10
|
aspyx/di/threading/__init__.py,sha256=qrWdaq7MewQ2UmZy4J0Dn6BhY-ahfiG3xsv-EHqoqSE,191
|
|
11
|
-
aspyx/di/threading/synchronized.py,sha256=
|
|
11
|
+
aspyx/di/threading/synchronized.py,sha256=6JOg5BXWrRIS5nRPH9iWR7T-kUglO4qWBQpLwhy99pI,1325
|
|
12
12
|
aspyx/exception/__init__.py,sha256=OZwv-C3ZHD0Eg1rohCQMj575WLJ7lfYuk6PZD6sh1MA,211
|
|
13
|
-
aspyx/exception/exception_manager.py,sha256=
|
|
13
|
+
aspyx/exception/exception_manager.py,sha256=CVOjdI-y4m5GiE3TvSbwLpXXoAYqEyQLMN7jQhJYRn8,5228
|
|
14
14
|
aspyx/reflection/__init__.py,sha256=r2sNJrfHDpuqaIYu4fTYsoo046gpgn4VTd7bsS3mQJY,282
|
|
15
|
-
aspyx/reflection/proxy.py,sha256=
|
|
16
|
-
aspyx/reflection/reflection.py,sha256=
|
|
17
|
-
aspyx/threading/__init__.py,sha256=
|
|
15
|
+
aspyx/reflection/proxy.py,sha256=1-pgw-TNORFXbV0gowFZqGd-bcWv1ny69bJhq8TLsKs,2761
|
|
16
|
+
aspyx/reflection/reflection.py,sha256=BcqXJcMO36Gzq71O4aBsMqPynmBhYLI8V6J7DOInPAM,9142
|
|
17
|
+
aspyx/threading/__init__.py,sha256=YWqLk-MOtSg4i3cdzRZUBR25okbbftRRxkaEdfrdMZo,207
|
|
18
|
+
aspyx/threading/context_local.py,sha256=IBjqfmuGgQSMB3EhYW9etcKEnErMQKaAVHD45s1mqOA,1111
|
|
18
19
|
aspyx/threading/thread_local.py,sha256=86dNtbA4k2B-rNUUnZgn3_pU0DAojgLrRnh8RL6zf1E,1196
|
|
19
|
-
aspyx/util/__init__.py,sha256=
|
|
20
|
+
aspyx/util/__init__.py,sha256=Uu6uZySb5v9WHS8ZooHmRXAxK_BhhKPUotv-LZyGQAI,165
|
|
21
|
+
aspyx/util/logger.py,sha256=S358l7RpBTSZtN8nivVLgX6HAp32vOQV-SDHDH0n9gc,547
|
|
20
22
|
aspyx/util/stringbuilder.py,sha256=a-0T4YEXSJFUuQ3ztKN1ZPARkh8dIGMSkNEEJHRN7dc,856
|
|
21
|
-
aspyx-1.5.
|
|
22
|
-
aspyx-1.5.
|
|
23
|
-
aspyx-1.5.
|
|
24
|
-
aspyx-1.5.
|
|
23
|
+
aspyx-1.5.3.dist-info/METADATA,sha256=hPk9M5CUZDxxvrzf0s1hTnpfw-XTJu1gPqgTzAVf6w0,26490
|
|
24
|
+
aspyx-1.5.3.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
25
|
+
aspyx-1.5.3.dist-info/licenses/LICENSE,sha256=n4jfx_MNj7cBtPhhI7MCoB_K35cj1icP9yJ4Rh4vlvY,1070
|
|
26
|
+
aspyx-1.5.3.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|