aspyx 1.0.1__py3-none-any.whl → 1.2.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.
- aspyx/di/__init__.py +7 -5
- aspyx/di/aop/aop.py +2 -2
- aspyx/di/configuration/__init__.py +4 -1
- aspyx/di/configuration/configuration.py +4 -54
- aspyx/di/configuration/env_configuration_source.py +55 -0
- aspyx/di/configuration/yaml_configuration_source.py +26 -0
- aspyx/di/di.py +260 -94
- aspyx/di/util/__init__.py +8 -0
- aspyx/di/util/stringbuilder.py +31 -0
- aspyx/reflection/reflection.py +40 -6
- {aspyx-1.0.1.dist-info → aspyx-1.2.0.dist-info}/METADATA +95 -27
- aspyx-1.2.0.dist-info/RECORD +18 -0
- aspyx-1.0.1.dist-info/RECORD +0 -14
- {aspyx-1.0.1.dist-info → aspyx-1.2.0.dist-info}/WHEEL +0 -0
- {aspyx-1.0.1.dist-info → aspyx-1.2.0.dist-info}/licenses/LICENSE +0 -0
- {aspyx-1.0.1.dist-info → aspyx-1.2.0.dist-info}/top_level.txt +0 -0
|
@@ -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)
|
aspyx/reflection/reflection.py
CHANGED
|
@@ -6,6 +6,7 @@ from __future__ import annotations
|
|
|
6
6
|
|
|
7
7
|
import inspect
|
|
8
8
|
from inspect import signature, getmembers
|
|
9
|
+
import threading
|
|
9
10
|
from typing import Callable, get_type_hints, Type, Dict, Optional
|
|
10
11
|
from weakref import WeakKeyDictionary
|
|
11
12
|
|
|
@@ -24,6 +25,9 @@ class DecoratorDescriptor:
|
|
|
24
25
|
return f"@{self.decorator.__name__}({','.join(self.args)})"
|
|
25
26
|
|
|
26
27
|
class Decorators:
|
|
28
|
+
"""
|
|
29
|
+
Utility class that caches decorators ( Python does not have a feature for this )
|
|
30
|
+
"""
|
|
27
31
|
@classmethod
|
|
28
32
|
def add(cls, func, decorator, *args):
|
|
29
33
|
decorators = getattr(func, '__decorators__', None)
|
|
@@ -37,9 +41,17 @@ class Decorators:
|
|
|
37
41
|
return getattr(func, '__decorators__', [])
|
|
38
42
|
|
|
39
43
|
class TypeDescriptor:
|
|
44
|
+
"""
|
|
45
|
+
This class provides a way to introspect Python classes, their methods, decorators, and type hints.
|
|
46
|
+
"""
|
|
40
47
|
# inner class
|
|
41
48
|
|
|
42
49
|
class MethodDescriptor:
|
|
50
|
+
"""
|
|
51
|
+
This class represents a method of a class, including its decorators, parameter types, and return type.
|
|
52
|
+
"""
|
|
53
|
+
# constructor
|
|
54
|
+
|
|
43
55
|
def __init__(self, cls, method: Callable):
|
|
44
56
|
self.clazz = cls
|
|
45
57
|
self.method = method
|
|
@@ -55,14 +67,16 @@ class TypeDescriptor:
|
|
|
55
67
|
|
|
56
68
|
self.return_type = type_hints.get('return', None)
|
|
57
69
|
|
|
58
|
-
|
|
70
|
+
# public
|
|
71
|
+
|
|
72
|
+
def get_decorator(self, decorator: Callable) -> Optional[DecoratorDescriptor]:
|
|
59
73
|
for dec in self.decorators:
|
|
60
74
|
if dec.decorator is decorator:
|
|
61
75
|
return dec
|
|
62
76
|
|
|
63
77
|
return None
|
|
64
78
|
|
|
65
|
-
def has_decorator(self, decorator) -> bool:
|
|
79
|
+
def has_decorator(self, decorator: Callable) -> bool:
|
|
66
80
|
for dec in self.decorators:
|
|
67
81
|
if dec.decorator is decorator:
|
|
68
82
|
return True
|
|
@@ -75,15 +89,22 @@ class TypeDescriptor:
|
|
|
75
89
|
# class properties
|
|
76
90
|
|
|
77
91
|
_cache = WeakKeyDictionary()
|
|
92
|
+
_lock = threading.RLock()
|
|
78
93
|
|
|
79
94
|
# class methods
|
|
80
95
|
|
|
81
96
|
@classmethod
|
|
82
97
|
def for_type(cls, clazz: Type) -> TypeDescriptor:
|
|
98
|
+
"""
|
|
99
|
+
Returns a TypeDescriptor for the given class, using a cache to avoid redundant introspection.
|
|
100
|
+
"""
|
|
83
101
|
descriptor = cls._cache.get(clazz)
|
|
84
102
|
if descriptor is None:
|
|
85
|
-
|
|
86
|
-
|
|
103
|
+
with cls._lock:
|
|
104
|
+
descriptor = cls._cache.get(clazz)
|
|
105
|
+
if descriptor is None:
|
|
106
|
+
descriptor = TypeDescriptor(clazz)
|
|
107
|
+
cls._cache[clazz] = descriptor
|
|
87
108
|
|
|
88
109
|
return descriptor
|
|
89
110
|
|
|
@@ -120,14 +141,19 @@ class TypeDescriptor:
|
|
|
120
141
|
|
|
121
142
|
# public
|
|
122
143
|
|
|
123
|
-
def get_decorator(self, decorator) -> Optional[DecoratorDescriptor]:
|
|
144
|
+
def get_decorator(self, decorator: Callable) -> Optional[DecoratorDescriptor]:
|
|
145
|
+
"""
|
|
146
|
+
Returns the first decorator of the given type, or None if not found.
|
|
147
|
+
"""
|
|
124
148
|
for dec in self.decorators:
|
|
125
149
|
if dec.decorator is decorator:
|
|
126
150
|
return dec
|
|
127
151
|
|
|
128
152
|
return None
|
|
129
153
|
|
|
130
|
-
def has_decorator(self, decorator) -> bool:
|
|
154
|
+
def has_decorator(self, decorator: Callable) -> bool:
|
|
155
|
+
"""
|
|
156
|
+
Checks if the class has a decorator of the given type."""
|
|
131
157
|
for dec in self.decorators:
|
|
132
158
|
if dec.decorator is decorator:
|
|
133
159
|
return True
|
|
@@ -135,12 +161,20 @@ class TypeDescriptor:
|
|
|
135
161
|
return False
|
|
136
162
|
|
|
137
163
|
def get_methods(self, local = False) -> list[TypeDescriptor.MethodDescriptor]:
|
|
164
|
+
"""
|
|
165
|
+
Returns a list of MethodDescriptor objects for the class.
|
|
166
|
+
If local is True, only returns methods defined in the class itself, otherwise includes inherited methods.
|
|
167
|
+
"""
|
|
138
168
|
if local:
|
|
139
169
|
return list(self.local_methods.values())
|
|
140
170
|
else:
|
|
141
171
|
return list(self.methods.values())
|
|
142
172
|
|
|
143
173
|
def get_method(self, name: str, local = False) -> Optional[TypeDescriptor.MethodDescriptor]:
|
|
174
|
+
"""
|
|
175
|
+
Returns a MethodDescriptor for the method with the given name.
|
|
176
|
+
If local is True, only searches for methods defined in the class itself, otherwise includes inherited methods.
|
|
177
|
+
"""
|
|
144
178
|
if local:
|
|
145
179
|
return self.local_methods.get(name, None)
|
|
146
180
|
else:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: aspyx
|
|
3
|
-
Version: 1.0
|
|
3
|
+
Version: 1.2.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
|
|
@@ -34,8 +34,9 @@ Dynamic: license-file
|
|
|
34
34
|
|
|
35
35
|

|
|
36
36
|

|
|
37
|
-

|
|
38
38
|

|
|
39
|
+

|
|
39
40
|
|
|
40
41
|
## Table of Contents
|
|
41
42
|
|
|
@@ -56,18 +57,18 @@ Dynamic: license-file
|
|
|
56
57
|
- [AOP](#aop)
|
|
57
58
|
- [Configuration](#configuration)
|
|
58
59
|
- [Reflection](#reflection)
|
|
60
|
+
- [Version History](#version-history)
|
|
59
61
|
|
|
60
62
|
# Introduction
|
|
61
63
|
|
|
62
64
|
Aspyx is a small python libary, that adds support for both dependency injection and aop.
|
|
63
65
|
|
|
64
66
|
The following features are supported
|
|
65
|
-
- constructor injection
|
|
66
|
-
- method injection
|
|
67
|
+
- constructor and setter injection
|
|
67
68
|
- post processors
|
|
68
69
|
- factory classes and methods
|
|
69
70
|
- support for eager construction
|
|
70
|
-
- support for singleton and
|
|
71
|
+
- support for singleton and request scopes
|
|
71
72
|
- possibilty to add custom scopes
|
|
72
73
|
- lifecycle events methods
|
|
73
74
|
- bundling of injectable object sets by environment classes including recursive imports and inheritance
|
|
@@ -156,7 +157,7 @@ Let's look at the details
|
|
|
156
157
|
|
|
157
158
|
`pip install aspyx`
|
|
158
159
|
|
|
159
|
-
The library is tested with Python version > 3.
|
|
160
|
+
The library is tested with all Python version > 3.9
|
|
160
161
|
|
|
161
162
|
Ready to go...
|
|
162
163
|
|
|
@@ -185,8 +186,15 @@ The decorator accepts the keyword arguments
|
|
|
185
186
|
- `eager : boolean`
|
|
186
187
|
if `True`, the container will create the instances automatically while booting the environment. This is the default.
|
|
187
188
|
- `scope: str`
|
|
188
|
-
the name of a scope which will determine how often instances will be created.
|
|
189
|
-
|
|
189
|
+
the name of a - registered - scope which will determine how often instances will be created.
|
|
190
|
+
|
|
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
|
+
objects are created on every injection request
|
|
196
|
+
- `thread`
|
|
197
|
+
objects are created and cached with respect to the current thread.
|
|
190
198
|
|
|
191
199
|
Other scopes - e.g. session related scopes - can be defined dynamically. Please check the corresponding chapter.
|
|
192
200
|
|
|
@@ -304,7 +312,7 @@ Different decorators are implemented, that call methods with computed values
|
|
|
304
312
|
the method is called with all resolved parameter types ( same as the constructor call)
|
|
305
313
|
- `@inject_environment`
|
|
306
314
|
the method is called with the creating environment as a single parameter
|
|
307
|
-
- `@
|
|
315
|
+
- `@inject_value()`
|
|
308
316
|
the method is called with a resolved configuration value. Check the corresponding chapter
|
|
309
317
|
|
|
310
318
|
**Example**:
|
|
@@ -325,9 +333,11 @@ class Foo:
|
|
|
325
333
|
|
|
326
334
|
## Lifecycle methods
|
|
327
335
|
|
|
328
|
-
It is possible to mark specific
|
|
336
|
+
It is possible to mark specific lifecyle methods.
|
|
329
337
|
- `@on_init()`
|
|
330
338
|
called after the constructor and all other injections.
|
|
339
|
+
- `@on_running()`
|
|
340
|
+
called an environment has initialized all eager objects.
|
|
331
341
|
- `@on_destroy()`
|
|
332
342
|
called during shutdown of the environment
|
|
333
343
|
|
|
@@ -445,7 +455,7 @@ Both add the fluent methods:
|
|
|
445
455
|
|
|
446
456
|
The fluent methods `named`, `matches` and `of_type` can be called multiple times!
|
|
447
457
|
|
|
448
|
-
**Example**:
|
|
458
|
+
**Example**: react on both `transactional` decorators on methods or classes
|
|
449
459
|
|
|
450
460
|
```python
|
|
451
461
|
@injectable()
|
|
@@ -460,7 +470,7 @@ class TransactionAdvice:
|
|
|
460
470
|
|
|
461
471
|
# Configuration
|
|
462
472
|
|
|
463
|
-
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.
|
|
464
474
|
|
|
465
475
|
```python
|
|
466
476
|
@injectable()
|
|
@@ -468,11 +478,13 @@ class Foo:
|
|
|
468
478
|
def __init__(self):
|
|
469
479
|
pass
|
|
470
480
|
|
|
471
|
-
@
|
|
472
|
-
def
|
|
481
|
+
@inject_value("HOME")
|
|
482
|
+
def inject_home(self, os: str):
|
|
473
483
|
...
|
|
474
484
|
```
|
|
475
485
|
|
|
486
|
+
If required a coercion will be executed.
|
|
487
|
+
|
|
476
488
|
This concept relies on a central object `ConfigurationManager` that stores the overall configuration values as provided by so called configuration sources that are defined as follows.
|
|
477
489
|
|
|
478
490
|
```python
|
|
@@ -484,14 +496,24 @@ class ConfigurationSource(ABC):
|
|
|
484
496
|
|
|
485
497
|
@abstractmethod
|
|
486
498
|
def load(self) -> dict:
|
|
487
|
-
pass
|
|
488
499
|
```
|
|
489
500
|
|
|
490
501
|
The `load` method is able to return a tree-like structure by returning a `dict`.
|
|
491
502
|
|
|
492
|
-
|
|
503
|
+
Configuration variables are retrieved with the method
|
|
504
|
+
|
|
505
|
+
```python
|
|
506
|
+
def get(self, path: str, type: Type[T], default : Optional[T]=None) -> T:
|
|
507
|
+
```
|
|
508
|
+
|
|
509
|
+
- `path`
|
|
510
|
+
a '.' separated path
|
|
511
|
+
- `type`
|
|
512
|
+
the desired type
|
|
513
|
+
- `default`
|
|
514
|
+
a default, if no value is registered
|
|
493
515
|
|
|
494
|
-
|
|
516
|
+
Sources can be added dynamically by registering them.
|
|
495
517
|
|
|
496
518
|
**Example**:
|
|
497
519
|
```python
|
|
@@ -511,6 +533,31 @@ class SampleConfigurationSource(ConfigurationSource):
|
|
|
511
533
|
}
|
|
512
534
|
```
|
|
513
535
|
|
|
536
|
+
Two specific source are already implemented:
|
|
537
|
+
- `EnvConfigurationSource`
|
|
538
|
+
reads the os environment variables
|
|
539
|
+
- `YamlConfigurationSource`
|
|
540
|
+
reads a specific yaml file
|
|
541
|
+
|
|
542
|
+
Typically you create the required configuration sources in an environment class, e.g.
|
|
543
|
+
|
|
544
|
+
```python
|
|
545
|
+
@environment()
|
|
546
|
+
class SampleEnvironment:
|
|
547
|
+
# constructor
|
|
548
|
+
|
|
549
|
+
def __init__(self):
|
|
550
|
+
pass
|
|
551
|
+
|
|
552
|
+
@create()
|
|
553
|
+
def create_env_source(self) -> EnvConfigurationSource:
|
|
554
|
+
return EnvConfigurationSource()
|
|
555
|
+
|
|
556
|
+
@create()
|
|
557
|
+
def create_yaml_source(self) -> YamlConfigurationSource:
|
|
558
|
+
return YamlConfigurationSource("config.yaml")
|
|
559
|
+
```
|
|
560
|
+
|
|
514
561
|
# Reflection
|
|
515
562
|
|
|
516
563
|
As the library heavily relies on type introspection of classes and methods, a utility class `TypeDescriptor` is available that covers type information on classes.
|
|
@@ -522,16 +569,24 @@ TypeDescriptor.for_type(<type>)
|
|
|
522
569
|
```
|
|
523
570
|
|
|
524
571
|
it offers the methods
|
|
525
|
-
- `get_methods(local=False)`
|
|
526
|
-
|
|
527
|
-
- `
|
|
528
|
-
|
|
572
|
+
- `get_methods(local=False)`
|
|
573
|
+
return a list of either local or overall methods
|
|
574
|
+
- `get_method(name: str, local=False)`
|
|
575
|
+
return a single either local or overall method
|
|
576
|
+
- `has_decorator(decorator: Callable) -> bool`
|
|
577
|
+
return `True`, if the class is decorated with the specified decorator
|
|
578
|
+
- `get_decorator(decorator) -> Optional[DecoratorDescriptor]`
|
|
579
|
+
return a descriptor covering the decorator. In addition to the callable, it also stores the supplied args in the `args` property
|
|
529
580
|
|
|
530
581
|
The returned method descriptors offer:
|
|
531
|
-
- `param_types`
|
|
532
|
-
|
|
533
|
-
- `
|
|
534
|
-
|
|
582
|
+
- `param_types`
|
|
583
|
+
list of arg types
|
|
584
|
+
- `return_type`
|
|
585
|
+
the return type
|
|
586
|
+
- `has_decorator(decorator: Callable) -> bool`
|
|
587
|
+
return `True`, if the method is decorated with the specified decorator
|
|
588
|
+
- `get_decorator(decorator: Callable) -> Optional[DecoratorDescriptor]`
|
|
589
|
+
return a descriptor covering the decorator. In addition to the callable, it also stores the supplied args in the `args` property
|
|
535
590
|
|
|
536
591
|
The management of decorators in turn relies on another utility class `Decorators` that caches decorators.
|
|
537
592
|
|
|
@@ -539,16 +594,29 @@ Whenver you define a custom decorator, you will need to register it accordingly.
|
|
|
539
594
|
|
|
540
595
|
**Example**:
|
|
541
596
|
```python
|
|
542
|
-
def transactional():
|
|
597
|
+
def transactional(scope):
|
|
543
598
|
def decorator(func):
|
|
544
|
-
Decorators.add(func, transactional)
|
|
599
|
+
Decorators.add(func, transactional, scope) # also add _all_ parameters in order to cache them
|
|
545
600
|
return func
|
|
546
601
|
|
|
547
602
|
return decorator
|
|
548
603
|
```
|
|
549
604
|
|
|
550
605
|
|
|
606
|
+
# Version History
|
|
607
|
+
|
|
608
|
+
**1.0.1**
|
|
609
|
+
|
|
610
|
+
- some internal refactorings
|
|
611
|
+
|
|
612
|
+
**1.1.0**
|
|
613
|
+
|
|
614
|
+
- added `@on_running()` callback
|
|
615
|
+
- added `thread` scope
|
|
616
|
+
|
|
617
|
+
**1.2.0**
|
|
551
618
|
|
|
619
|
+
- added `YamlConfigurationSource`
|
|
552
620
|
|
|
553
621
|
|
|
554
622
|
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
aspyx/di/__init__.py,sha256=xdb2lsKh00uGMFCWYavhUEMGH15OSeAhUC-iSosqHqU,935
|
|
2
|
+
aspyx/di/di.py,sha256=evfhTznmPNRDjamthSPisMpDhGZJdNmEREUhdJ9nsTE,35571
|
|
3
|
+
aspyx/di/aop/__init__.py,sha256=nOABex49zSyMZ2w1ezwX3Q3yrOcQRSDjDtSj0DwKVbQ,233
|
|
4
|
+
aspyx/di/aop/aop.py,sha256=3GKN6sGlsZbJ7_WSxQvHZNFYouAfU4Eq6H5cBBB_e_4,14455
|
|
5
|
+
aspyx/di/configuration/__init__.py,sha256=mweJ3tZX1YJfY1d4ra-i0TWEcF3EwXBpGbHrKg1Kc6E,380
|
|
6
|
+
aspyx/di/configuration/configuration.py,sha256=KfPjrlUhhmEOUxdJiXePt5RGxKc8JczkWqlEBjpWQTg,4362
|
|
7
|
+
aspyx/di/configuration/env_configuration_source.py,sha256=Xh8g3AuQdgk89nG6GKA4iKILXaqHecD0KqMW2w91hXs,1445
|
|
8
|
+
aspyx/di/configuration/yaml_configuration_source.py,sha256=LM-5J6IRxBBbBAjDeGIFsmiT-61WuGv1sU_zXWNzhkI,549
|
|
9
|
+
aspyx/di/util/__init__.py,sha256=8H2yKkXu3nkRGeTerb8ialzKGfvzUx44XUWFUYcYuQM,125
|
|
10
|
+
aspyx/di/util/stringbuilder.py,sha256=JywkLxZfaQUUWjSB5wvqA6a6Cfs3sW1jbaZ1z4U0-CQ,540
|
|
11
|
+
aspyx/reflection/__init__.py,sha256=r2sNJrfHDpuqaIYu4fTYsoo046gpgn4VTd7bsS3mQJY,282
|
|
12
|
+
aspyx/reflection/proxy.py,sha256=zJ6Psd6zWfFABdrKOf4cULt3gibyqCRdcR6z8WKIkzE,1982
|
|
13
|
+
aspyx/reflection/reflection.py,sha256=2oYJKYysH3ULmTzbXdjGBCB1iaLbWh3IPKSnorVLshU,5719
|
|
14
|
+
aspyx-1.2.0.dist-info/licenses/LICENSE,sha256=n4jfx_MNj7cBtPhhI7MCoB_K35cj1icP9yJ4Rh4vlvY,1070
|
|
15
|
+
aspyx-1.2.0.dist-info/METADATA,sha256=wXSu9Clxg4ZZCoiRAhiZzAR1Wcqtjv4NZie4XilJNSs,19009
|
|
16
|
+
aspyx-1.2.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
17
|
+
aspyx-1.2.0.dist-info/top_level.txt,sha256=A_ZwhBY_ybIgjZlztd44eaOrWqkJAndiqjGlbJ3tR_I,6
|
|
18
|
+
aspyx-1.2.0.dist-info/RECORD,,
|
aspyx-1.0.1.dist-info/RECORD
DELETED
|
@@ -1,14 +0,0 @@
|
|
|
1
|
-
aspyx/di/__init__.py,sha256=G13Cz1MMElBKNWsrhgTEIvhmIKj5MX4uqK_Apke4w8I,897
|
|
2
|
-
aspyx/di/di.py,sha256=elT3XJokxYxPJ9mx528MAU-pmm9lIZF8_AXKGkjyhBo,31014
|
|
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=dHYoM3jC43QeDVlT6-mGDj05Sz6-Nm91LNE2TfQT1UU,5740
|
|
7
|
-
aspyx/reflection/__init__.py,sha256=r2sNJrfHDpuqaIYu4fTYsoo046gpgn4VTd7bsS3mQJY,282
|
|
8
|
-
aspyx/reflection/proxy.py,sha256=zJ6Psd6zWfFABdrKOf4cULt3gibyqCRdcR6z8WKIkzE,1982
|
|
9
|
-
aspyx/reflection/reflection.py,sha256=NkBK94kjJ7rQpPsK4mzHzX5TLSlWRM3mbNVzkwOZo4o,4379
|
|
10
|
-
aspyx-1.0.1.dist-info/licenses/LICENSE,sha256=n4jfx_MNj7cBtPhhI7MCoB_K35cj1icP9yJ4Rh4vlvY,1070
|
|
11
|
-
aspyx-1.0.1.dist-info/METADATA,sha256=69OakKuzM1UK0YTgH-y6-473YWhylxQvt8v993WsqiU,16798
|
|
12
|
-
aspyx-1.0.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
13
|
-
aspyx-1.0.1.dist-info/top_level.txt,sha256=A_ZwhBY_ybIgjZlztd44eaOrWqkJAndiqjGlbJ3tR_I,6
|
|
14
|
-
aspyx-1.0.1.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|