aspyx 1.0.0__py3-none-any.whl → 1.1.0__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.

@@ -0,0 +1,8 @@
1
+ """
2
+ This module provides utility functions.
3
+ """
4
+ from .stringbuilder import StringBuilder
5
+
6
+ __all__ = [
7
+ "StringBuilder",
8
+ ]
@@ -0,0 +1,31 @@
1
+ """
2
+ Utility class for Java lovers
3
+ """
4
+ class StringBuilder:
5
+ ___slots__ = ("_parts",)
6
+
7
+ # constructor
8
+
9
+ def __init__(self):
10
+ self._parts = []
11
+
12
+ # public
13
+
14
+ def append(self, s: str) -> "StringBuilder":
15
+ self._parts.append(str(s))
16
+
17
+ return self
18
+
19
+ def extend(self, iterable) -> "StringBuilder":
20
+ for s in iterable:
21
+ self._parts.append(str(s))
22
+
23
+ return self
24
+
25
+ def clear(self):
26
+ self._parts.clear()
27
+
28
+ # object
29
+
30
+ def __str__(self):
31
+ return ''.join(self._parts)
@@ -1,3 +1,6 @@
1
+ """
2
+ This module provides tools for dynamic proxy creation and reflection
3
+ """
1
4
  from .proxy import DynamicProxy
2
5
  from .reflection import Decorators, TypeDescriptor, DecoratorDescriptor
3
6
 
@@ -6,4 +9,4 @@ __all__ = [
6
9
  "Decorators",
7
10
  "DecoratorDescriptor",
8
11
  "TypeDescriptor"
9
- ]
12
+ ]
aspyx/reflection/proxy.py CHANGED
@@ -1,3 +1,6 @@
1
+ """
2
+ Dynamic proxies for method interception and delegation.
3
+ """
1
4
  from typing import Generic, TypeVar, Type
2
5
 
3
6
  T = TypeVar("T")
@@ -22,7 +25,7 @@ class DynamicProxy(Generic[T]):
22
25
 
23
26
  Attributes:
24
27
  type: The proxied class type.
25
- invocationHandler: The handler that processes intercepted method calls.
28
+ invocation_handler: The handler that processes intercepted method calls.
26
29
  """
27
30
  # inner class
28
31
 
@@ -40,19 +43,19 @@ class DynamicProxy(Generic[T]):
40
43
  # class methods
41
44
 
42
45
  @classmethod
43
- def create(cls, type: Type[T], invocationHandler: 'DynamicProxy.InvocationHandler') -> T:
44
- return DynamicProxy(type, invocationHandler)
46
+ def create(cls, type: Type[T], invocation_handler: 'DynamicProxy.InvocationHandler') -> T:
47
+ return DynamicProxy(type, invocation_handler)
45
48
 
46
49
  # constructor
47
50
 
48
- def __init__(self, type: Type[T], invocationHandler: 'DynamicProxy.InvocationHandler'):
51
+ def __init__(self, type: Type[T], invocation_handler: 'DynamicProxy.InvocationHandler'):
49
52
  self.type = type
50
- self.invocationHandler = invocationHandler
53
+ self.invocation_handler = invocation_handler
51
54
 
52
55
  # public
53
56
 
54
57
  def __getattr__(self, name):
55
58
  def wrapper(*args, **kwargs):
56
- return self.invocationHandler.invoke(DynamicProxy.Invocation(self.type, name, *args, **kwargs))
59
+ return self.invocation_handler.invoke(DynamicProxy.Invocation(self.type, name, *args, **kwargs))
57
60
 
58
- return wrapper
61
+ return wrapper
@@ -1,10 +1,16 @@
1
+ """
2
+ This module provides a TypeDescriptor class that allows introspection of Python classes,
3
+ including their methods, decorators, and type hints. It supports caching for performance
4
+ """
1
5
  from __future__ import annotations
2
6
 
3
7
  import inspect
4
8
  from inspect import signature, getmembers
9
+ import threading
5
10
  from typing import Callable, get_type_hints, Type, Dict, Optional
6
11
  from weakref import WeakKeyDictionary
7
12
 
13
+
8
14
  class DecoratorDescriptor:
9
15
  __slots__ = [
10
16
  "decorator",
@@ -39,25 +45,25 @@ class TypeDescriptor:
39
45
  self.clazz = cls
40
46
  self.method = method
41
47
  self.decorators: list[DecoratorDescriptor] = Decorators.get(method)
42
- self.paramTypes : list[Type] = []
48
+ self.param_types : list[Type] = []
43
49
 
44
50
  type_hints = get_type_hints(method)
45
51
  sig = signature(method)
46
52
 
47
- for name, param in sig.parameters.items():
53
+ for name, _ in sig.parameters.items():
48
54
  if name != 'self':
49
- self.paramTypes.append(type_hints.get(name, object))
55
+ self.param_types.append(type_hints.get(name, object))
50
56
 
51
- self.returnType = type_hints.get('return', None)
57
+ self.return_type = type_hints.get('return', None)
52
58
 
53
- def get_decorator(self, decorator):
59
+ def get_decorator(self, decorator: Callable) -> Optional[DecoratorDescriptor]:
54
60
  for dec in self.decorators:
55
61
  if dec.decorator is decorator:
56
62
  return dec
57
63
 
58
64
  return None
59
65
 
60
- def has_decorator(self, decorator):
66
+ def has_decorator(self, decorator: Callable) -> bool:
61
67
  for dec in self.decorators:
62
68
  if dec.decorator is decorator:
63
69
  return True
@@ -67,11 +73,10 @@ class TypeDescriptor:
67
73
  def __str__(self):
68
74
  return f"Method({self.method.__name__})"
69
75
 
70
- # class methods
71
-
72
76
  # class properties
73
77
 
74
78
  _cache = WeakKeyDictionary()
79
+ _lock = threading.RLock()
75
80
 
76
81
  # class methods
77
82
 
@@ -79,8 +84,12 @@ class TypeDescriptor:
79
84
  def for_type(cls, clazz: Type) -> TypeDescriptor:
80
85
  descriptor = cls._cache.get(clazz)
81
86
  if descriptor is None:
82
- descriptor = TypeDescriptor(clazz)
83
- cls._cache[clazz] = descriptor
87
+ with cls._lock:
88
+ descriptor = cls._cache.get(clazz)
89
+ if descriptor is None:
90
+ descriptor = TypeDescriptor(clazz)
91
+ cls._cache[clazz] = descriptor
92
+
84
93
  return descriptor
85
94
 
86
95
  # constructor
@@ -88,27 +97,25 @@ class TypeDescriptor:
88
97
  def __init__(self, cls):
89
98
  self.cls = cls
90
99
  self.decorators = Decorators.get(cls)
91
- self.methods: Dict[str, TypeDescriptor.MethodDescriptor] = dict()
92
- self.localMethods: Dict[str, TypeDescriptor.MethodDescriptor] = dict()
100
+ self.methods: Dict[str, TypeDescriptor.MethodDescriptor] = {}
101
+ self.local_methods: Dict[str, TypeDescriptor.MethodDescriptor] = {}
93
102
 
94
103
  # check superclasses
95
104
 
96
- self.superTypes = [TypeDescriptor.for_type(x) for x in cls.__bases__ if not x is object]
105
+ self.super_types = [TypeDescriptor.for_type(x) for x in cls.__bases__ if not x is object]
97
106
 
98
- for superType in self.superTypes:
99
- self.methods = self.methods | superType.methods
107
+ for super_type in self.super_types:
108
+ self.methods = self.methods | super_type.methods
100
109
 
101
110
  # methods
102
111
 
103
112
  for name, member in self._get_local_members(cls):
104
113
  method = TypeDescriptor.MethodDescriptor(cls, member)
105
- self.localMethods[name] = method
114
+ self.local_methods[name] = method
106
115
  self.methods[name] = method
107
116
 
108
117
  # internal
109
118
 
110
- #isinstance(attr, classmethod)
111
-
112
119
  def _get_local_members(self, cls):
113
120
  return [
114
121
  (name, value)
@@ -118,22 +125,28 @@ class TypeDescriptor:
118
125
 
119
126
  # public
120
127
 
121
- def get_decorator(self, decorator) -> Optional[DecoratorDescriptor]:
128
+ def get_decorator(self, decorator: Callable) -> Optional[DecoratorDescriptor]:
122
129
  for dec in self.decorators:
123
130
  if dec.decorator is decorator:
124
131
  return dec
125
132
 
126
133
  return None
127
134
 
128
- def has_decorator(self, decorator) -> bool:
135
+ def has_decorator(self, decorator: Callable) -> bool:
129
136
  for dec in self.decorators:
130
- if dec.decorator.__name__ == decorator.__name__:
137
+ if dec.decorator is decorator:
131
138
  return True
132
139
 
133
140
  return False
134
141
 
135
- def get_local_method(self, name) -> Optional[MethodDescriptor]:
136
- return self.localMethods.get(name, None)
142
+ def get_methods(self, local = False) -> list[TypeDescriptor.MethodDescriptor]:
143
+ if local:
144
+ return list(self.local_methods.values())
145
+ else:
146
+ return list(self.methods.values())
137
147
 
138
- def get_method(self, name) -> Optional[MethodDescriptor]:
139
- return self.methods.get(name, None)
148
+ def get_method(self, name: str, local = False) -> Optional[TypeDescriptor.MethodDescriptor]:
149
+ if local:
150
+ return self.local_methods.get(name, None)
151
+ else:
152
+ return self.methods.get(name, None)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aspyx
3
- Version: 1.0.0
3
+ Version: 1.1.0
4
4
  Summary: A DI and AOP library for Python
5
5
  Author-email: Andreas Ernst <andreas.ernst7@gmail.com>
6
6
  License: MIT License
@@ -25,7 +25,7 @@ License: MIT License
25
25
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
26
26
  SOFTWARE.
27
27
 
28
- Requires-Python: >=3.8
28
+ Requires-Python: >=3.9
29
29
  Description-Content-Type: text/markdown
30
30
  License-File: LICENSE
31
31
  Dynamic: license-file
@@ -34,11 +34,14 @@ Dynamic: license-file
34
34
 
35
35
  ![Pylint](https://github.com/coolsamson7/aspyx/actions/workflows/pylint.yml/badge.svg)
36
36
  ![Build Status](https://github.com/coolsamson7/aspyx/actions/workflows/ci.yml/badge.svg)
37
-
37
+ ![Python Versions](https://img.shields.io/badge/python-3.9%20|%203.10%20|%203.11%20|%203.12-blue)
38
+ ![License](https://img.shields.io/github/license/coolsamson7/aspyx)
39
+ ![coverage](https://img.shields.io/badge/coverage-94%25-brightgreen)
38
40
 
39
41
  ## Table of Contents
40
42
 
41
43
  - [Introduction](#aspyx)
44
+ - [Installation](#installation)
42
45
  - [Registration](#registration)
43
46
  - [Class](#class)
44
47
  - [Class Factory](#class-factory)
@@ -53,30 +56,32 @@ Dynamic: license-file
53
56
  - [Custom scopes](#custom-scopes)
54
57
  - [AOP](#aop)
55
58
  - [Configuration](#configuration)
59
+ - [Reflection](#reflection)
60
+ - [Version History](#version-history)
56
61
 
57
62
  # Introduction
58
63
 
59
64
  Aspyx is a small python libary, that adds support for both dependency injection and aop.
60
65
 
61
66
  The following features are supported
62
- - constructor injection
63
- - method injection
67
+ - constructor and setter injection
64
68
  - post processors
65
69
  - factory classes and methods
66
70
  - support for eager construction
67
- - support for singleton and reuqest scopes
71
+ - support for singleton and request scopes
68
72
  - possibilty to add custom scopes
69
73
  - lifecycle events methods
70
74
  - bundling of injectable object sets by environment classes including recursive imports and inheritance
71
75
  - container instances that relate to environment classes and manage the lifecylce of related objects
72
76
  - hierarchical environments
73
77
 
78
+ The library is thread-safe!
79
+
74
80
  Let's look at a simple example
75
81
 
76
82
  ```python
77
83
  from aspyx.di import injectable, on_init, on_destroy, environment, Environment
78
84
 
79
-
80
85
  @injectable()
81
86
  class Foo:
82
87
  def __init__(self):
@@ -85,13 +90,12 @@ class Foo:
85
90
  def hello(msg: str):
86
91
  print(f"hello {msg}")
87
92
 
88
-
89
93
  @injectable() # eager and singleton by default
90
94
  class Bar:
91
95
  def __init__(self, foo: Foo): # will inject the Foo dependency
92
96
  self.foo = foo
93
97
 
94
- @on_init() # a lifecycle callback called after the constructor
98
+ @on_init() # a lifecycle callback called after the constructor and all possible injections
95
99
  def init(self):
96
100
  ...
97
101
 
@@ -101,41 +105,40 @@ class Bar:
101
105
 
102
106
  @environment()
103
107
  class SampleEnvironment:
104
- # constructor
105
-
106
108
  def __init__(self):
107
109
  pass
108
110
 
109
-
110
111
  # go, forrest
111
112
 
112
- environment = SampleEnvironment(Configuration)
113
+ environment = Environment(SampleEnvironment)
113
114
 
114
115
  bar = env.get(Bar)
115
- bar.foo.hello("Andi")
116
+
117
+ bar.foo.hello("world")
116
118
  ```
117
119
 
118
- The concepts should be pretty familiar , as well as the names which are a combination of Spring and Angular names :-)
120
+ The concepts should be pretty familiar as well as the names which are a combination of Spring and Angular names :-)
119
121
 
120
122
  Let's add some aspects...
121
123
 
122
124
  ```python
125
+
123
126
  @advice
124
127
  class SampleAdvice:
125
- def __init__(self):
128
+ def __init__(self): # could inject additional stuff
126
129
  pass
127
130
 
128
131
  @before(methods().named("hello").of_type(Foo))
129
- def callBefore(self, invocation: Invocation):
132
+ def call_before(self, invocation: Invocation):
130
133
  print("before Foo.hello(...)")
131
134
 
132
135
  @error(methods().named("hello").of_type(Foo))
133
- def callError(self, invocation: Invocation):
136
+ def call_error(self, invocation: Invocation):
134
137
  print("error Foo.hello(...)")
135
138
  print(invocation.exception)
136
139
 
137
140
  @around(methods().named("hello"))
138
- def callAround(self, invocation: Invocation):
141
+ def call_around(self, invocation: Invocation):
139
142
  print("around Foo.hello()")
140
143
 
141
144
  return invocation.proceed()
@@ -150,6 +153,14 @@ The invocation parameter stores the complete context of the current execution, w
150
153
 
151
154
  Let's look at the details
152
155
 
156
+ # Installation
157
+
158
+ `pip install aspyx`
159
+
160
+ The library is tested with all Python version > 3.9
161
+
162
+ Ready to go...
163
+
153
164
  # Registration
154
165
 
155
166
  Different mechanisms are available that make classes eligible for injection
@@ -171,12 +182,21 @@ All referenced types will be injected by the environemnt.
171
182
 
172
183
  Only eligible types are allowed, of course!
173
184
 
185
+ The decorator accepts the keyword arguments
186
+ - `eager : boolean`
187
+ if `True`, the container will create the instances automatically while booting the environment. This is the default.
188
+ - `scope: str`
189
+ the name of a - registered - scope which will determine how often instances will be created.
174
190
 
175
- The decorator accepts the keyword arguments
176
- - `eager=True` if `True`, the container will create the instances automatically while booting the environment
177
- - `scope="singleton"` defines how often instances will be created. `singleton` will create it only once - per environment -, while `request` will recreate it on every injection request
191
+ The following scopes are implemented out of the box:
192
+ - `singleton`
193
+ objects are created once inside an environment and cached. This is the default.
194
+ - `request`
195
+ obejcts are created on every injection request
196
+ - `thread`
197
+ objects are cerated and cached with respect to the current thread.
178
198
 
179
- Other scopes can be defined. Please check the corresponding chapter.
199
+ Other scopes - e.g. session related scopes - can be defined dynamically. Please check the corresponding chapter.
180
200
 
181
201
  ## Class Factory
182
202
 
@@ -292,7 +312,7 @@ Different decorators are implemented, that call methods with computed values
292
312
  the method is called with all resolved parameter types ( same as the constructor call)
293
313
  - `@inject_environment`
294
314
  the method is called with the creating environment as a single parameter
295
- - `@value()`
315
+ - `@inject_value()`
296
316
  the method is called with a resolved configuration value. Check the corresponding chapter
297
317
 
298
318
  **Example**:
@@ -313,9 +333,11 @@ class Foo:
313
333
 
314
334
  ## Lifecycle methods
315
335
 
316
- It is possible to mark specific lifecle methods.
336
+ It is possible to mark specific lifecyle methods.
317
337
  - `@on_init()`
318
338
  called after the constructor and all other injections.
339
+ - `@on_running()`
340
+ called an environment has initialized all eager objects.
319
341
  - `@on_destroy()`
320
342
  called during shutdown of the environment
321
343
 
@@ -386,17 +408,17 @@ class SampleAdvice:
386
408
  pass
387
409
 
388
410
  @before(methods().named("hello").of_type(Foo))
389
- def callBefore(self, invocation: Invocation):
411
+ def call_before(self, invocation: Invocation):
390
412
  # arguments: invocation.args
391
413
  print("before Foo.hello(...)")
392
414
 
393
415
  @error(methods().named("hello").of_type(Foo))
394
- def callError(self, invocation: Invocation):
416
+ def call_error(self, invocation: Invocation):
395
417
  print("error Foo.hello(...)")
396
418
  print(invocation.exception)
397
419
 
398
420
  @around(methods().named("hello"))
399
- def callAround(self, invocation: Invocation):
421
+ def call_around(self, invocation: Invocation):
400
422
  print("around Foo.hello()")
401
423
 
402
424
  return invocation.proceed() # will leave a result in invocation.result or invocation.exception in case of an exception
@@ -417,7 +439,7 @@ All methods are expected to hava single `Invocation` parameter, that stores, the
417
439
  It is essential for `around` methods to call `proceed()` on the invocation, which will call the next around method in the chain and finally the original method.
418
440
  If the `proceed` is called with parameters, they will replace the original parameters!
419
441
 
420
- The arguments to the corresponding decorators control, how aspects are associated with which methods.
442
+ The argument list to the corresponding decorators control, how aspects are associated with which methods.
421
443
  A fluent interface is used describe the mapping.
422
444
  The parameters restrict either methods or classes and are constructed by a call to either `methods()` or `classes()`.
423
445
 
@@ -431,11 +453,24 @@ Both add the fluent methods:
431
453
  - `decorated_with(type: Type)`
432
454
  defines decorators on methods or classes
433
455
 
434
- The fluent methods `named`, `matches` and `of_type` can be called multiple timess!
456
+ The fluent methods `named`, `matches` and `of_type` can be called multiple times!
457
+
458
+ **Example**:
459
+
460
+ ```python
461
+ @injectable()
462
+ class TransactionAdvice:
463
+ def __init__(self):
464
+ pass
465
+
466
+ @around(methods().decorated_with(transactional), classes().decorated_with(transactional))
467
+ def establish_transaction(self, invocation: Invocation):
468
+ ...
469
+ ```
435
470
 
436
471
  # Configuration
437
472
 
438
- It is possible to inject configuration values, by decorating methods with `@value(<name>)` given a configuration key.
473
+ It is possible to inject configuration values, by decorating methods with `@inject-value(<name>)` given a configuration key.
439
474
 
440
475
  ```python
441
476
  @injectable()
@@ -452,10 +487,11 @@ This concept relies on a central object `ConfigurationManager` that stores the o
452
487
 
453
488
  ```python
454
489
  class ConfigurationSource(ABC):
455
- def __init__(self, manager: ConfigurationManager):
456
- manager._register(self)
490
+ def __init__(self):
457
491
  pass
458
492
 
493
+ ...
494
+
459
495
  @abstractmethod
460
496
  def load(self) -> dict:
461
497
  pass
@@ -467,14 +503,12 @@ As a default environment variables are already supported.
467
503
 
468
504
  Other sources can be added dynamically by just registering them.
469
505
 
506
+ **Example**:
470
507
  ```python
471
508
  @injectable()
472
509
  class SampleConfigurationSource(ConfigurationSource):
473
- # constructor
474
-
475
- def __init__(self, manager: ConfigurationManager):
476
- super().__init__(manager)
477
-
510
+ def __init__(self):
511
+ super().__init__()
478
512
 
479
513
  def load(self) -> dict:
480
514
  return {
@@ -487,7 +521,61 @@ class SampleConfigurationSource(ConfigurationSource):
487
521
  }
488
522
  ```
489
523
 
524
+ # Reflection
525
+
526
+ As the library heavily relies on type introspection of classes and methods, a utility class `TypeDescriptor` is available that covers type information on classes.
527
+
528
+ After beeing instatiated with
529
+
530
+ ```python
531
+ TypeDescriptor.for_type(<type>)
532
+ ```
533
+
534
+ it offers the methods
535
+ - `get_methods(local=False)`
536
+ return a list of either local or overall methods
537
+ - `get_method(name: str, local=False)`
538
+ return a single either local or overall method
539
+ - `has_decorator(decorator: Callable) -> bool`
540
+ return `True`, if the class is decorated with the specified decrator
541
+ - `get_decorator(decorator) -> Optional[DecoratorDescriptor]`
542
+ return a descriptor covering the decorator. In addition to the callable, it also stores the supplied args in the `args` property
543
+
544
+ The returned method descriptors offer:
545
+ - `param_types`
546
+ list of arg types
547
+ - `return_type`
548
+ the retur type
549
+ - `has_decorator(decorator: Callable) -> bool`
550
+ return `True`, if the method is decorated with the specified decrator
551
+ - `get_decorator(decorator: Callable) -> Optional[DecoratorDescriptor]`
552
+ return a descriptor covering the decorator. In addition to the callable, it also stores the supplied args in the `args` property
553
+
554
+ The management of decorators in turn relies on another utility class `Decorators` that caches decorators.
555
+
556
+ Whenver you define a custom decorator, you will need to register it accordingly.
557
+
558
+ **Example**:
559
+ ```python
560
+ def transactional():
561
+ def decorator(func):
562
+ Decorators.add(func, transactional)
563
+ return func
564
+
565
+ return decorator
566
+ ```
567
+
568
+
569
+ # Version History
570
+
571
+ **1.0.1**
572
+
573
+ - some internal refactorings
574
+
575
+ **1.1.0**
490
576
 
577
+ - added `@on_running()` callback
578
+ - added `thread` scope
491
579
 
492
580
 
493
581
 
@@ -0,0 +1,16 @@
1
+ aspyx/di/__init__.py,sha256=U2-4JnCmSO_IXCnN1jeig9nuWfJN__z9yRzl1WexQJk,927
2
+ aspyx/di/di.py,sha256=VVLOXhTKJer2cV0rNEOqMLyMigsNMEQ7xoc-6M7a8wU,34296
3
+ aspyx/di/aop/__init__.py,sha256=nOABex49zSyMZ2w1ezwX3Q3yrOcQRSDjDtSj0DwKVbQ,233
4
+ aspyx/di/aop/aop.py,sha256=1RUgijk8RsiXWTizfNQX1IfHF7b96kCPdUgahX_J4Io,14457
5
+ aspyx/di/configuration/__init__.py,sha256=Zw7h-OlbJD7LyJvzkgyF0EmVqra6oN_Pt0HuUdjTPTA,249
6
+ aspyx/di/configuration/configuration.py,sha256=jJJSHRG2wOIvle23Xc8CQ4WM7lp_xCL8-ENVZO603uQ,5682
7
+ aspyx/di/util/__init__.py,sha256=8H2yKkXu3nkRGeTerb8ialzKGfvzUx44XUWFUYcYuQM,125
8
+ aspyx/di/util/stringbuilder.py,sha256=JywkLxZfaQUUWjSB5wvqA6a6Cfs3sW1jbaZ1z4U0-CQ,540
9
+ aspyx/reflection/__init__.py,sha256=r2sNJrfHDpuqaIYu4fTYsoo046gpgn4VTd7bsS3mQJY,282
10
+ aspyx/reflection/proxy.py,sha256=zJ6Psd6zWfFABdrKOf4cULt3gibyqCRdcR6z8WKIkzE,1982
11
+ aspyx/reflection/reflection.py,sha256=HfPFd_FehTGmgF6NA-IJ_aHePE6GXM1ag7K3h8YIXjI,4600
12
+ aspyx-1.1.0.dist-info/licenses/LICENSE,sha256=n4jfx_MNj7cBtPhhI7MCoB_K35cj1icP9yJ4Rh4vlvY,1070
13
+ aspyx-1.1.0.dist-info/METADATA,sha256=rdeICMYyQSJmSZDJZrsdw6l5ZVrQrxvAPS_z47ObM-Y,17989
14
+ aspyx-1.1.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
15
+ aspyx-1.1.0.dist-info/top_level.txt,sha256=A_ZwhBY_ybIgjZlztd44eaOrWqkJAndiqjGlbJ3tR_I,6
16
+ aspyx-1.1.0.dist-info/RECORD,,
@@ -1,14 +0,0 @@
1
- aspyx/di/__init__.py,sha256=US6i6s94TIpk4eiRFKYm9JB0NnU9F_3RAoIoXa-OnTI,800
2
- aspyx/di/di.py,sha256=IdMNkPmMaVhRNr8heE8msGO3KYEc69pf2pjcJ8_rp4E,31169
3
- aspyx/di/aop/__init__.py,sha256=2mv6o38HHoBzF_nx8rsrvuOlUlNgYITmNRcQJVT2Bk8,213
4
- aspyx/di/aop/aop.py,sha256=stgSLSBpOd9XV_qo7KEazinq8Ul_csWbCx1w30dioWw,14647
5
- aspyx/di/configuration/__init__.py,sha256=YgUk1bHVYq1EJ9W4D_CJ9ZM-3kje-vzPNMxBdUm0Vlg,211
6
- aspyx/di/configuration/configuration.py,sha256=6EG2kf2v5pk9fTeCQUD5j6Jo5v00CFd5Nz7qXyYmxKw,5725
7
- aspyx/reflection/__init__.py,sha256=jZAjw5NDrtXENmlBsQ0u9MobcNkfEuT0Oey8IWNYh34,204
8
- aspyx/reflection/proxy.py,sha256=Re643BJAgbQjmDXO5JAvj4mu3RTpe_HF3TcFQ1euArg,1910
9
- aspyx/reflection/reflection.py,sha256=LIUu-SxA_GJ1JurbQKTrvMUrE05OOcXxXOu65zRWubw,4004
10
- aspyx-1.0.0.dist-info/licenses/LICENSE,sha256=n4jfx_MNj7cBtPhhI7MCoB_K35cj1icP9yJ4Rh4vlvY,1070
11
- aspyx-1.0.0.dist-info/METADATA,sha256=3AuH9LBUHpPfxu9BcmawTaaJIHTBWwHuFpP_gBasyh0,15227
12
- aspyx-1.0.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
13
- aspyx-1.0.0.dist-info/top_level.txt,sha256=A_ZwhBY_ybIgjZlztd44eaOrWqkJAndiqjGlbJ3tR_I,6
14
- aspyx-1.0.0.dist-info/RECORD,,
File without changes