aspyx 1.0.1__tar.gz → 1.1.0__tar.gz

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.

Files changed (26) hide show
  1. {aspyx-1.0.1/src/aspyx.egg-info → aspyx-1.1.0}/PKG-INFO +46 -19
  2. {aspyx-1.0.1 → aspyx-1.1.0}/README.md +45 -18
  3. {aspyx-1.0.1 → aspyx-1.1.0}/pyproject.toml +1 -1
  4. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/di/__init__.py +5 -4
  5. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/di/configuration/configuration.py +3 -3
  6. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/di/di.py +191 -67
  7. aspyx-1.1.0/src/aspyx/di/util/__init__.py +8 -0
  8. aspyx-1.1.0/src/aspyx/di/util/stringbuilder.py +31 -0
  9. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/reflection/reflection.py +11 -6
  10. {aspyx-1.0.1 → aspyx-1.1.0/src/aspyx.egg-info}/PKG-INFO +46 -19
  11. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx.egg-info/SOURCES.txt +2 -0
  12. {aspyx-1.0.1 → aspyx-1.1.0}/tests/test_aop.py +14 -12
  13. {aspyx-1.0.1 → aspyx-1.1.0}/tests/test_configuration.py +7 -5
  14. {aspyx-1.0.1 → aspyx-1.1.0}/tests/test_di.py +42 -28
  15. {aspyx-1.0.1 → aspyx-1.1.0}/tests/test_di_cycle.py +7 -5
  16. {aspyx-1.0.1 → aspyx-1.1.0}/tests/test_proxy.py +4 -1
  17. {aspyx-1.0.1 → aspyx-1.1.0}/tests/test_reflection.py +10 -14
  18. {aspyx-1.0.1 → aspyx-1.1.0}/LICENSE +0 -0
  19. {aspyx-1.0.1 → aspyx-1.1.0}/setup.cfg +0 -0
  20. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/di/aop/__init__.py +0 -0
  21. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/di/aop/aop.py +0 -0
  22. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/di/configuration/__init__.py +0 -0
  23. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/reflection/__init__.py +0 -0
  24. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx/reflection/proxy.py +0 -0
  25. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx.egg-info/dependency_links.txt +0 -0
  26. {aspyx-1.0.1 → aspyx-1.1.0}/src/aspyx.egg-info/top_level.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aspyx
3
- Version: 1.0.1
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
@@ -34,8 +34,9 @@ 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
- ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aspyx)
37
+ ![Python Versions](https://img.shields.io/badge/python-3.9%20|%203.10%20|%203.11%20|%203.12-blue)
38
38
  ![License](https://img.shields.io/github/license/coolsamson7/aspyx)
39
+ ![coverage](https://img.shields.io/badge/coverage-94%25-brightgreen)
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 reuqest scopes
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.8
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
- `singleton` will create it only once - per environment -, while `request` will recreate it on every injection request. The default is `singleton`
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
+ obejcts are created on every injection request
196
+ - `thread`
197
+ objects are cerated 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
- - `@value()`
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 lifecle methods.
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
 
@@ -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()
@@ -522,16 +532,24 @@ TypeDescriptor.for_type(<type>)
522
532
  ```
523
533
 
524
534
  it offers the methods
525
- - `get_methods(local=False)`
526
- - `get_method(name: str, local=False)`
527
- - `has_decorator(decorator) -> bool`
528
- - `get_decorator(decorator)`
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
529
543
 
530
544
  The returned method descriptors offer:
531
- - `param_types`
532
- - `return_type`
533
- - `has_decorator(decorator)`
534
- - `get_decorator(decorator)`
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
535
553
 
536
554
  The management of decorators in turn relies on another utility class `Decorators` that caches decorators.
537
555
 
@@ -548,7 +566,16 @@ def transactional():
548
566
  ```
549
567
 
550
568
 
569
+ # Version History
570
+
571
+ **1.0.1**
572
+
573
+ - some internal refactorings
574
+
575
+ **1.1.0**
551
576
 
577
+ - added `@on_running()` callback
578
+ - added `thread` scope
552
579
 
553
580
 
554
581
 
@@ -2,8 +2,9 @@
2
2
 
3
3
  ![Pylint](https://github.com/coolsamson7/aspyx/actions/workflows/pylint.yml/badge.svg)
4
4
  ![Build Status](https://github.com/coolsamson7/aspyx/actions/workflows/ci.yml/badge.svg)
5
- ![PyPI - Python Version](https://img.shields.io/pypi/pyversions/aspyx)
5
+ ![Python Versions](https://img.shields.io/badge/python-3.9%20|%203.10%20|%203.11%20|%203.12-blue)
6
6
  ![License](https://img.shields.io/github/license/coolsamson7/aspyx)
7
+ ![coverage](https://img.shields.io/badge/coverage-94%25-brightgreen)
7
8
 
8
9
  ## Table of Contents
9
10
 
@@ -24,18 +25,18 @@
24
25
  - [AOP](#aop)
25
26
  - [Configuration](#configuration)
26
27
  - [Reflection](#reflection)
28
+ - [Version History](#version-history)
27
29
 
28
30
  # Introduction
29
31
 
30
32
  Aspyx is a small python libary, that adds support for both dependency injection and aop.
31
33
 
32
34
  The following features are supported
33
- - constructor injection
34
- - method injection
35
+ - constructor and setter injection
35
36
  - post processors
36
37
  - factory classes and methods
37
38
  - support for eager construction
38
- - support for singleton and reuqest scopes
39
+ - support for singleton and request scopes
39
40
  - possibilty to add custom scopes
40
41
  - lifecycle events methods
41
42
  - bundling of injectable object sets by environment classes including recursive imports and inheritance
@@ -124,7 +125,7 @@ Let's look at the details
124
125
 
125
126
  `pip install aspyx`
126
127
 
127
- The library is tested with Python version > 3.8
128
+ The library is tested with all Python version > 3.9
128
129
 
129
130
  Ready to go...
130
131
 
@@ -153,8 +154,15 @@ The decorator accepts the keyword arguments
153
154
  - `eager : boolean`
154
155
  if `True`, the container will create the instances automatically while booting the environment. This is the default.
155
156
  - `scope: str`
156
- the name of a scope which will determine how often instances will be created.
157
- `singleton` will create it only once - per environment -, while `request` will recreate it on every injection request. The default is `singleton`
157
+ the name of a - registered - scope which will determine how often instances will be created.
158
+
159
+ The following scopes are implemented out of the box:
160
+ - `singleton`
161
+ objects are created once inside an environment and cached. This is the default.
162
+ - `request`
163
+ obejcts are created on every injection request
164
+ - `thread`
165
+ objects are cerated and cached with respect to the current thread.
158
166
 
159
167
  Other scopes - e.g. session related scopes - can be defined dynamically. Please check the corresponding chapter.
160
168
 
@@ -272,7 +280,7 @@ Different decorators are implemented, that call methods with computed values
272
280
  the method is called with all resolved parameter types ( same as the constructor call)
273
281
  - `@inject_environment`
274
282
  the method is called with the creating environment as a single parameter
275
- - `@value()`
283
+ - `@inject_value()`
276
284
  the method is called with a resolved configuration value. Check the corresponding chapter
277
285
 
278
286
  **Example**:
@@ -293,9 +301,11 @@ class Foo:
293
301
 
294
302
  ## Lifecycle methods
295
303
 
296
- It is possible to mark specific lifecle methods.
304
+ It is possible to mark specific lifecyle methods.
297
305
  - `@on_init()`
298
306
  called after the constructor and all other injections.
307
+ - `@on_running()`
308
+ called an environment has initialized all eager objects.
299
309
  - `@on_destroy()`
300
310
  called during shutdown of the environment
301
311
 
@@ -428,7 +438,7 @@ class TransactionAdvice:
428
438
 
429
439
  # Configuration
430
440
 
431
- It is possible to inject configuration values, by decorating methods with `@value(<name>)` given a configuration key.
441
+ It is possible to inject configuration values, by decorating methods with `@inject-value(<name>)` given a configuration key.
432
442
 
433
443
  ```python
434
444
  @injectable()
@@ -490,16 +500,24 @@ TypeDescriptor.for_type(<type>)
490
500
  ```
491
501
 
492
502
  it offers the methods
493
- - `get_methods(local=False)`
494
- - `get_method(name: str, local=False)`
495
- - `has_decorator(decorator) -> bool`
496
- - `get_decorator(decorator)`
503
+ - `get_methods(local=False)`
504
+ return a list of either local or overall methods
505
+ - `get_method(name: str, local=False)`
506
+ return a single either local or overall method
507
+ - `has_decorator(decorator: Callable) -> bool`
508
+ return `True`, if the class is decorated with the specified decrator
509
+ - `get_decorator(decorator) -> Optional[DecoratorDescriptor]`
510
+ return a descriptor covering the decorator. In addition to the callable, it also stores the supplied args in the `args` property
497
511
 
498
512
  The returned method descriptors offer:
499
- - `param_types`
500
- - `return_type`
501
- - `has_decorator(decorator)`
502
- - `get_decorator(decorator)`
513
+ - `param_types`
514
+ list of arg types
515
+ - `return_type`
516
+ the retur type
517
+ - `has_decorator(decorator: Callable) -> bool`
518
+ return `True`, if the method is decorated with the specified decrator
519
+ - `get_decorator(decorator: Callable) -> Optional[DecoratorDescriptor]`
520
+ return a descriptor covering the decorator. In addition to the callable, it also stores the supplied args in the `args` property
503
521
 
504
522
  The management of decorators in turn relies on another utility class `Decorators` that caches decorators.
505
523
 
@@ -516,7 +534,16 @@ def transactional():
516
534
  ```
517
535
 
518
536
 
537
+ # Version History
538
+
539
+ **1.0.1**
540
+
541
+ - some internal refactorings
542
+
543
+ **1.1.0**
519
544
 
545
+ - added `@on_running()` callback
546
+ - added `thread` scope
520
547
 
521
548
 
522
549
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "aspyx"
7
- version = "1.0.1"
7
+ version = "1.1.0"
8
8
  description = "A DI and AOP library for Python"
9
9
  authors = [{ name = "Andreas Ernst", email = "andreas.ernst7@gmail.com" }]
10
10
  readme = "README.md"
@@ -1,12 +1,12 @@
1
1
  """
2
2
  This module provides dependency injection and aop capabilities for Python applications.
3
3
  """
4
- from .di import InjectorException, CallableProcessor, LifecycleCallable, Lifecycle, Providers, Environment, ClassInstanceProvider, injectable, factory, environment, inject, create, on_init, on_destroy, inject_environment, Factory, PostProcessor
4
+ from .di import InjectorException, AbstractCallableProcessor, LifecycleCallable, Lifecycle, Providers, Environment, ClassInstanceProvider, injectable, factory, environment, inject, create, on_init, on_running, on_destroy, inject_environment, Factory, PostProcessor
5
5
 
6
6
  # import something from the subpackages, so that teh decorators are executed
7
7
 
8
- from aspyx.di.configuration import ConfigurationManager
9
- from aspyx.di.aop import before
8
+ from .configuration import ConfigurationManager
9
+ from .aop import before
10
10
 
11
11
  imports = [ConfigurationManager, before]
12
12
 
@@ -21,11 +21,12 @@ __all__ = [
21
21
  "create",
22
22
 
23
23
  "on_init",
24
+ "on_running",
24
25
  "on_destroy",
25
26
  "inject_environment",
26
27
  "Factory",
27
28
  "PostProcessor",
28
- "CallableProcessor",
29
+ "AbstractCallableProcessor",
29
30
  "LifecycleCallable",
30
31
  "InjectorException",
31
32
  "Lifecycle"
@@ -8,7 +8,7 @@ import os
8
8
  from typing import Optional, Type, TypeVar
9
9
  from dotenv import load_dotenv
10
10
 
11
- from aspyx.di import injectable, Environment, CallableProcessor, LifecycleCallable, Lifecycle
11
+ from aspyx.di import injectable, Environment, LifecycleCallable, Lifecycle
12
12
  from aspyx.di.di import order, inject
13
13
  from aspyx.reflection import Decorators, DecoratorDescriptor, TypeDescriptor
14
14
 
@@ -188,8 +188,8 @@ def value(key: str, default=None):
188
188
  @injectable()
189
189
  @order(9)
190
190
  class ConfigurationLifecycleCallable(LifecycleCallable):
191
- def __init__(self, processor: CallableProcessor, manager: ConfigurationManager):
192
- super().__init__(value, processor, Lifecycle.ON_INIT)
191
+ def __init__(self, manager: ConfigurationManager):
192
+ super().__init__(value, Lifecycle.ON_INJECT)
193
193
 
194
194
  self.manager = manager
195
195