orionis 0.405.0__py3-none-any.whl → 0.407.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.
- orionis/console/base/command.py +57 -50
- orionis/console/base/contracts/command.py +68 -0
- orionis/console/dynamic/contracts/progress_bar.py +3 -3
- orionis/console/dynamic/progress_bar.py +8 -8
- orionis/console/output/console.py +8 -2
- orionis/console/output/contracts/console.py +1 -1
- orionis/container/container.py +2 -2
- orionis/container/context/scope.py +4 -1
- orionis/container/contracts/service_provider.py +2 -2
- orionis/container/entities/binding.py +31 -44
- orionis/container/enums/lifetimes.py +22 -1
- orionis/container/facades/facade.py +1 -2
- orionis/container/providers/service_provider.py +2 -2
- orionis/foundation/application.py +542 -248
- orionis/foundation/config/app/entities/app.py +107 -90
- orionis/foundation/config/auth/entities/auth.py +4 -33
- orionis/foundation/config/cache/entities/cache.py +18 -41
- orionis/foundation/config/cache/entities/file.py +8 -35
- orionis/foundation/config/cache/entities/stores.py +17 -38
- orionis/foundation/config/cors/entities/cors.py +41 -54
- orionis/foundation/config/database/entities/connections.py +40 -56
- orionis/foundation/config/database/entities/database.py +11 -38
- orionis/foundation/config/database/entities/mysql.py +48 -76
- orionis/foundation/config/database/entities/oracle.py +30 -57
- orionis/foundation/config/database/entities/pgsql.py +45 -61
- orionis/foundation/config/database/entities/sqlite.py +26 -53
- orionis/foundation/config/filesystems/entitites/aws.py +28 -49
- orionis/foundation/config/filesystems/entitites/disks.py +27 -47
- orionis/foundation/config/filesystems/entitites/filesystems.py +15 -37
- orionis/foundation/config/filesystems/entitites/local.py +9 -35
- orionis/foundation/config/filesystems/entitites/public.py +14 -41
- orionis/foundation/config/logging/entities/channels.py +56 -86
- orionis/foundation/config/logging/entities/chunked.py +9 -9
- orionis/foundation/config/logging/entities/daily.py +8 -8
- orionis/foundation/config/logging/entities/hourly.py +6 -6
- orionis/foundation/config/logging/entities/logging.py +12 -18
- orionis/foundation/config/logging/entities/monthly.py +7 -7
- orionis/foundation/config/logging/entities/stack.py +5 -5
- orionis/foundation/config/logging/entities/weekly.py +6 -6
- orionis/foundation/config/mail/entities/file.py +9 -36
- orionis/foundation/config/mail/entities/mail.py +22 -40
- orionis/foundation/config/mail/entities/mailers.py +29 -44
- orionis/foundation/config/mail/entities/smtp.py +47 -48
- orionis/foundation/config/queue/entities/brokers.py +19 -41
- orionis/foundation/config/queue/entities/database.py +24 -46
- orionis/foundation/config/queue/entities/queue.py +28 -40
- orionis/foundation/config/roots/paths.py +272 -468
- orionis/foundation/config/session/entities/session.py +23 -53
- orionis/foundation/config/startup.py +165 -135
- orionis/foundation/config/testing/entities/testing.py +137 -122
- orionis/foundation/config/testing/enums/__init__.py +6 -2
- orionis/foundation/config/testing/enums/drivers.py +16 -0
- orionis/foundation/config/testing/enums/verbosity.py +18 -0
- orionis/foundation/contracts/application.py +152 -362
- orionis/foundation/providers/console_provider.py +24 -2
- orionis/foundation/providers/dumper_provider.py +24 -2
- orionis/foundation/providers/logger_provider.py +24 -2
- orionis/foundation/providers/path_resolver_provider.py +25 -2
- orionis/foundation/providers/progress_bar_provider.py +24 -2
- orionis/foundation/providers/testing_provider.py +39 -0
- orionis/foundation/providers/workers_provider.py +24 -2
- orionis/metadata/framework.py +1 -1
- orionis/services/asynchrony/contracts/coroutines.py +13 -5
- orionis/services/asynchrony/coroutines.py +33 -29
- orionis/services/asynchrony/exceptions/exception.py +9 -1
- orionis/services/environment/core/dot_env.py +46 -34
- orionis/services/environment/enums/__init__.py +0 -0
- orionis/services/environment/enums/cast_type.py +42 -0
- orionis/services/environment/helpers/functions.py +1 -2
- orionis/services/environment/key/__init__.py +0 -0
- orionis/services/environment/key/key_generator.py +37 -0
- orionis/services/environment/serializer/__init__.py +0 -0
- orionis/services/environment/serializer/values.py +21 -0
- orionis/services/environment/validators/__init__.py +0 -0
- orionis/services/environment/validators/key_name.py +46 -0
- orionis/services/environment/validators/types.py +45 -0
- orionis/services/system/contracts/imports.py +38 -18
- orionis/services/system/contracts/workers.py +29 -12
- orionis/services/system/imports.py +65 -25
- orionis/services/system/runtime/imports.py +18 -9
- orionis/services/system/workers.py +49 -16
- orionis/support/entities/__init__.py +0 -0
- orionis/support/entities/base.py +104 -0
- orionis/support/facades/testing.py +15 -0
- orionis/support/facades/workers.py +1 -1
- orionis/test/cases/asynchronous.py +0 -11
- orionis/test/cases/synchronous.py +0 -9
- orionis/test/contracts/dumper.py +11 -4
- orionis/test/contracts/kernel.py +5 -110
- orionis/test/contracts/logs.py +27 -65
- orionis/test/contracts/printer.py +16 -128
- orionis/test/contracts/test_result.py +100 -0
- orionis/test/contracts/unit_test.py +87 -150
- orionis/test/core/unit_test.py +608 -554
- orionis/test/entities/result.py +22 -2
- orionis/test/enums/__init__.py +0 -2
- orionis/test/enums/status.py +14 -9
- orionis/test/exceptions/config.py +9 -1
- orionis/test/exceptions/failure.py +34 -11
- orionis/test/exceptions/persistence.py +10 -2
- orionis/test/exceptions/runtime.py +9 -1
- orionis/test/exceptions/value.py +13 -1
- orionis/test/kernel.py +87 -289
- orionis/test/output/dumper.py +83 -18
- orionis/test/output/printer.py +399 -156
- orionis/test/records/logs.py +203 -82
- orionis/test/validators/__init__.py +33 -0
- orionis/test/validators/base_path.py +45 -0
- orionis/test/validators/execution_mode.py +45 -0
- orionis/test/validators/fail_fast.py +37 -0
- orionis/test/validators/folder_path.py +34 -0
- orionis/test/validators/module_name.py +31 -0
- orionis/test/validators/name_pattern.py +40 -0
- orionis/test/validators/pattern.py +36 -0
- orionis/test/validators/persistent.py +42 -0
- orionis/test/validators/persistent_driver.py +43 -0
- orionis/test/validators/print_result.py +37 -0
- orionis/test/validators/tags.py +37 -0
- orionis/test/validators/throw_exception.py +39 -0
- orionis/test/validators/verbosity.py +37 -0
- orionis/test/validators/web_report.py +35 -0
- orionis/test/validators/workers.py +31 -0
- orionis/test/view/render.py +48 -54
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/METADATA +1 -1
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/RECORD +170 -112
- tests/container/__init__.py +0 -0
- tests/container/context/__init__.py +0 -0
- tests/container/context/test_manager.py +27 -0
- tests/container/context/test_scope.py +23 -0
- tests/container/entities/__init__.py +0 -0
- tests/container/entities/test_binding.py +133 -0
- tests/container/enums/__init__.py +0 -0
- tests/container/enums/test_lifetimes.py +63 -0
- tests/container/facades/__init__.py +0 -0
- tests/container/facades/test_facade.py +61 -0
- tests/container/mocks/__init__.py +0 -0
- tests/container/mocks/mock_complex_classes.py +482 -0
- tests/container/mocks/mock_simple_classes.py +32 -0
- tests/container/providers/__init__.py +0 -0
- tests/container/providers/test_providers.py +48 -0
- tests/container/resolver/__init__.py +0 -0
- tests/container/resolver/test_resolver.py +55 -0
- tests/container/test_container.py +254 -0
- tests/container/test_singleton.py +98 -0
- tests/container/test_thread_safety.py +217 -0
- tests/container/validators/__init__.py +0 -0
- tests/container/validators/test_implements.py +140 -0
- tests/container/validators/test_is_abstract_class.py +99 -0
- tests/container/validators/test_is_callable.py +73 -0
- tests/container/validators/test_is_concrete_class.py +97 -0
- tests/container/validators/test_is_instance.py +105 -0
- tests/container/validators/test_is_not_subclass.py +117 -0
- tests/container/validators/test_is_subclass.py +115 -0
- tests/container/validators/test_is_valid_alias.py +113 -0
- tests/container/validators/test_lifetime.py +75 -0
- tests/example/test_example.py +2 -2
- tests/foundation/config/testing/test_foundation_config_testing.py +1 -1
- tests/metadata/test_metadata_framework.py +89 -24
- tests/metadata/test_metadata_package.py +55 -10
- tests/services/asynchrony/test_services_asynchrony_coroutine.py +52 -7
- tests/services/system/test_services_system_imports.py +119 -16
- tests/services/system/test_services_system_workers.py +71 -30
- tests/testing/test_testing_result.py +117 -117
- tests/testing/test_testing_unit.py +209 -209
- orionis/foundation/config/base.py +0 -112
- orionis/test/arguments/parser.py +0 -187
- orionis/test/contracts/parser.py +0 -43
- orionis/test/entities/arguments.py +0 -38
- orionis/test/enums/execution_mode.py +0 -16
- /orionis/{test/arguments → console/base/contracts}/__init__.py +0 -0
- /orionis/foundation/config/testing/enums/{test_mode.py → mode.py} +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/WHEEL +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/top_level.txt +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/zip-safe +0 -0
orionis/console/base/command.py
CHANGED
|
@@ -1,85 +1,92 @@
|
|
|
1
|
-
import
|
|
1
|
+
from typing import Any, Dict
|
|
2
2
|
from orionis.console.dynamic.progress_bar import ProgressBar
|
|
3
3
|
from orionis.console.output.console import Console
|
|
4
|
+
from orionis.console.base.contracts.command import IBaseCommand
|
|
4
5
|
|
|
5
|
-
class BaseCommand(Console, ProgressBar):
|
|
6
|
+
class BaseCommand(Console, ProgressBar, IBaseCommand):
|
|
6
7
|
"""
|
|
7
|
-
|
|
8
|
+
Abstract base class for console commands in Orionis.
|
|
8
9
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
The class inherits from both Console and ProgressBar, providing access to:
|
|
15
|
-
- Console output methods for displaying messages, errors, and formatted text
|
|
16
|
-
- Progress bar functionality for long-running operations
|
|
17
|
-
- Argument parsing and management capabilities
|
|
10
|
+
Inherits from Console and ProgressBar, allowing commands to:
|
|
11
|
+
- Display messages, errors, and formatted text in the console.
|
|
12
|
+
- Manage progress bars for long-running tasks.
|
|
13
|
+
- Access and manipulate parsed arguments from the command line.
|
|
18
14
|
|
|
19
15
|
Attributes
|
|
20
16
|
----------
|
|
21
17
|
args : dict
|
|
22
|
-
Dictionary containing the parsed
|
|
23
|
-
This is populated by calling the `setArgs` method with either an
|
|
24
|
-
`argparse.Namespace` object or a dictionary.
|
|
18
|
+
Dictionary containing the parsed arguments for the command. Set via the setArgs method.
|
|
25
19
|
|
|
26
20
|
Methods
|
|
27
21
|
-------
|
|
28
22
|
handle()
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
23
|
+
Must be implemented by each subclass to define the main logic of the command.
|
|
24
|
+
argument(key)
|
|
25
|
+
Retrieves the value of a specific argument by key.
|
|
26
|
+
arguments()
|
|
27
|
+
Returns all parsed arguments as a dictionary.
|
|
33
28
|
"""
|
|
34
29
|
|
|
35
|
-
args = {}
|
|
30
|
+
args: Dict[str, Any] = {}
|
|
36
31
|
|
|
37
32
|
def handle(self):
|
|
38
33
|
"""
|
|
39
|
-
|
|
34
|
+
Main entry point for command execution.
|
|
40
35
|
|
|
41
|
-
This
|
|
42
|
-
|
|
43
|
-
the command should perform when invoked.
|
|
36
|
+
This method must be overridden in each subclass to define the specific logic of the command.
|
|
37
|
+
Access parsed arguments via self.args and use console and progress bar methods as needed.
|
|
44
38
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
39
|
+
Example:
|
|
40
|
+
def handle(self):
|
|
41
|
+
self.write("Processing...")
|
|
42
|
+
value = self.argument("key")
|
|
43
|
+
# custom logic
|
|
49
44
|
|
|
50
45
|
Raises
|
|
51
46
|
------
|
|
52
47
|
NotImplementedError
|
|
53
|
-
Always raised
|
|
54
|
-
implemented by concrete subclasses to define command-specific behavior.
|
|
48
|
+
Always raised in the base class. Subclasses must implement this method.
|
|
55
49
|
"""
|
|
56
|
-
raise NotImplementedError("The 'handle' method must be implemented in the
|
|
50
|
+
raise NotImplementedError("The 'handle' method must be implemented in the subclass.")
|
|
57
51
|
|
|
58
|
-
def
|
|
52
|
+
def argument(self, key: str):
|
|
59
53
|
"""
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
This method accepts command arguments in multiple formats and normalizes
|
|
63
|
-
them into a dictionary format stored in `self.args`. It provides
|
|
64
|
-
flexibility in how arguments are passed to the command while ensuring
|
|
65
|
-
consistent internal representation.
|
|
54
|
+
Retrieves the value of a specific argument by its key.
|
|
66
55
|
|
|
67
56
|
Parameters
|
|
68
57
|
----------
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
58
|
+
key : str
|
|
59
|
+
Name of the argument to retrieve.
|
|
60
|
+
|
|
61
|
+
Returns
|
|
62
|
+
-------
|
|
63
|
+
any or None
|
|
64
|
+
Value associated with the key, or None if it does not exist or arguments are not set.
|
|
73
65
|
|
|
74
66
|
Raises
|
|
75
67
|
------
|
|
76
68
|
ValueError
|
|
77
|
-
If
|
|
78
|
-
|
|
69
|
+
If the key is not a string or if arguments are not a dictionary.
|
|
70
|
+
|
|
71
|
+
Example:
|
|
72
|
+
value = self.argument("user")
|
|
73
|
+
"""
|
|
74
|
+
if not isinstance(key, str):
|
|
75
|
+
raise ValueError("Argument key must be a string.")
|
|
76
|
+
if not isinstance(self.args, dict):
|
|
77
|
+
raise ValueError("Arguments must be a dictionary.")
|
|
78
|
+
return self.args.get(key)
|
|
79
|
+
|
|
80
|
+
def arguments(self) -> dict:
|
|
81
|
+
"""
|
|
82
|
+
Returns all parsed arguments as a dictionary.
|
|
83
|
+
|
|
84
|
+
Returns
|
|
85
|
+
-------
|
|
86
|
+
dict
|
|
87
|
+
Dictionary containing all arguments received by the command. If no arguments, returns an empty dictionary.
|
|
88
|
+
|
|
89
|
+
Example:
|
|
90
|
+
args = self.arguments()
|
|
79
91
|
"""
|
|
80
|
-
if isinstance(args,
|
|
81
|
-
self.args = vars(args)
|
|
82
|
-
elif isinstance(args, dict):
|
|
83
|
-
self.args = args
|
|
84
|
-
else:
|
|
85
|
-
raise ValueError("Invalid argument type. Expected 'argparse.Namespace' or 'dict'.")
|
|
92
|
+
return dict(self.args) if isinstance(self.args, dict) else {}
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
|
|
2
|
+
from abc import ABC, abstractmethod
|
|
3
|
+
from typing import Any, Dict
|
|
4
|
+
|
|
5
|
+
class IBaseCommand(ABC):
|
|
6
|
+
"""
|
|
7
|
+
Abstract base contract for console commands in Orionis.
|
|
8
|
+
|
|
9
|
+
Inherits from ABC and defines the required interface for all console commands:
|
|
10
|
+
- Stores parsed command-line arguments.
|
|
11
|
+
- Requires implementation of main execution logic and argument accessors.
|
|
12
|
+
|
|
13
|
+
Attributes
|
|
14
|
+
----------
|
|
15
|
+
args : Dict[str, Any]
|
|
16
|
+
Dictionary containing the parsed arguments for the command. Should be set by the command parser.
|
|
17
|
+
"""
|
|
18
|
+
|
|
19
|
+
args: Dict[str, Any] = {}
|
|
20
|
+
|
|
21
|
+
@abstractmethod
|
|
22
|
+
def handle(self):
|
|
23
|
+
"""
|
|
24
|
+
Main entry point for command execution.
|
|
25
|
+
|
|
26
|
+
This method must be overridden in each subclass to define the specific logic of the command.
|
|
27
|
+
Access parsed arguments via self.args and use console/output methods as needed.
|
|
28
|
+
|
|
29
|
+
Raises
|
|
30
|
+
------
|
|
31
|
+
NotImplementedError
|
|
32
|
+
Always raised in the base class. Subclasses must implement this method.
|
|
33
|
+
"""
|
|
34
|
+
pass
|
|
35
|
+
|
|
36
|
+
@abstractmethod
|
|
37
|
+
def argument(self, key: str) -> Any:
|
|
38
|
+
"""
|
|
39
|
+
Retrieves the value of a specific argument by its key.
|
|
40
|
+
|
|
41
|
+
Parameters
|
|
42
|
+
----------
|
|
43
|
+
key : str
|
|
44
|
+
Name of the argument to retrieve.
|
|
45
|
+
|
|
46
|
+
Returns
|
|
47
|
+
-------
|
|
48
|
+
Any or None
|
|
49
|
+
Value associated with the key, or None if it does not exist or arguments are not set.
|
|
50
|
+
|
|
51
|
+
Raises
|
|
52
|
+
------
|
|
53
|
+
ValueError
|
|
54
|
+
If the key is not a string or if arguments are not a dictionary.
|
|
55
|
+
"""
|
|
56
|
+
pass
|
|
57
|
+
|
|
58
|
+
@abstractmethod
|
|
59
|
+
def arguments(self) -> Dict[str, Any]:
|
|
60
|
+
"""
|
|
61
|
+
Returns all parsed arguments as a dictionary.
|
|
62
|
+
|
|
63
|
+
Returns
|
|
64
|
+
-------
|
|
65
|
+
dict
|
|
66
|
+
Dictionary containing all arguments received by the command. If no arguments, returns an empty dictionary.
|
|
67
|
+
"""
|
|
68
|
+
pass
|
|
@@ -19,7 +19,7 @@ class IProgressBar(ABC):
|
|
|
19
19
|
"""
|
|
20
20
|
|
|
21
21
|
@abstractmethod
|
|
22
|
-
def start(self):
|
|
22
|
+
def start(self) -> None:
|
|
23
23
|
"""
|
|
24
24
|
Initializes the progress bar.
|
|
25
25
|
|
|
@@ -34,7 +34,7 @@ class IProgressBar(ABC):
|
|
|
34
34
|
pass
|
|
35
35
|
|
|
36
36
|
@abstractmethod
|
|
37
|
-
def advance(self, increment: int):
|
|
37
|
+
def advance(self, increment: int) -> None:
|
|
38
38
|
"""
|
|
39
39
|
Advances the progress bar by a given increment.
|
|
40
40
|
|
|
@@ -51,7 +51,7 @@ class IProgressBar(ABC):
|
|
|
51
51
|
pass
|
|
52
52
|
|
|
53
53
|
@abstractmethod
|
|
54
|
-
def finish(self):
|
|
54
|
+
def finish(self) -> None:
|
|
55
55
|
"""
|
|
56
56
|
Completes the progress bar.
|
|
57
57
|
|
|
@@ -34,7 +34,7 @@ class ProgressBar(IProgressBar):
|
|
|
34
34
|
Completes the progress bar and moves to a new line.
|
|
35
35
|
"""
|
|
36
36
|
|
|
37
|
-
def __init__(self, total=100, width=50):
|
|
37
|
+
def __init__(self, total=100, width=50) -> None:
|
|
38
38
|
"""
|
|
39
39
|
Constructs all the necessary attributes for the progress bar object.
|
|
40
40
|
|
|
@@ -49,7 +49,7 @@ class ProgressBar(IProgressBar):
|
|
|
49
49
|
self.bar_width = width
|
|
50
50
|
self.progress = 0
|
|
51
51
|
|
|
52
|
-
def
|
|
52
|
+
def __updateBar(self) -> None:
|
|
53
53
|
"""
|
|
54
54
|
Updates the visual representation of the progress bar.
|
|
55
55
|
|
|
@@ -64,16 +64,16 @@ class ProgressBar(IProgressBar):
|
|
|
64
64
|
sys.stdout.write("\r" + bar)
|
|
65
65
|
sys.stdout.flush()
|
|
66
66
|
|
|
67
|
-
def start(self):
|
|
67
|
+
def start(self) -> None:
|
|
68
68
|
"""
|
|
69
69
|
Initializes the progress bar to the starting state.
|
|
70
70
|
|
|
71
71
|
This method resets the progress to zero and displays the initial bar.
|
|
72
72
|
"""
|
|
73
73
|
self.progress = 0
|
|
74
|
-
self.
|
|
74
|
+
self.__updateBar()
|
|
75
75
|
|
|
76
|
-
def advance(self, increment=1):
|
|
76
|
+
def advance(self, increment=1) -> None:
|
|
77
77
|
"""
|
|
78
78
|
Advances the progress bar by a specific increment.
|
|
79
79
|
|
|
@@ -85,9 +85,9 @@ class ProgressBar(IProgressBar):
|
|
|
85
85
|
self.progress += increment
|
|
86
86
|
if self.progress > self.total:
|
|
87
87
|
self.progress = self.total
|
|
88
|
-
self.
|
|
88
|
+
self.__updateBar()
|
|
89
89
|
|
|
90
|
-
def finish(self):
|
|
90
|
+
def finish(self) -> None:
|
|
91
91
|
"""
|
|
92
92
|
Completes the progress bar.
|
|
93
93
|
|
|
@@ -95,6 +95,6 @@ class ProgressBar(IProgressBar):
|
|
|
95
95
|
and moves the cursor to a new line for cleaner output.
|
|
96
96
|
"""
|
|
97
97
|
self.progress = self.total
|
|
98
|
-
self.
|
|
98
|
+
self.__updateBar()
|
|
99
99
|
sys.stdout.write("\n")
|
|
100
100
|
sys.stdout.flush()
|
|
@@ -537,7 +537,10 @@ class Console(IConsole):
|
|
|
537
537
|
"""
|
|
538
538
|
if message:
|
|
539
539
|
self.success(message)
|
|
540
|
-
|
|
540
|
+
try:
|
|
541
|
+
sys.exit(0)
|
|
542
|
+
except SystemExit:
|
|
543
|
+
os._exit(0)
|
|
541
544
|
|
|
542
545
|
def exitError(self, message: str = None) -> None:
|
|
543
546
|
"""
|
|
@@ -550,4 +553,7 @@ class Console(IConsole):
|
|
|
550
553
|
"""
|
|
551
554
|
if message:
|
|
552
555
|
self.error(message)
|
|
553
|
-
|
|
556
|
+
try:
|
|
557
|
+
sys.exit(0)
|
|
558
|
+
except SystemExit:
|
|
559
|
+
os._exit(0)
|
orionis/container/container.py
CHANGED
|
@@ -32,8 +32,8 @@ class Container(IContainer):
|
|
|
32
32
|
"""
|
|
33
33
|
Creates and returns a singleton instance for each specific class.
|
|
34
34
|
|
|
35
|
-
This method implements a truly thread-safe singleton pattern with proper
|
|
36
|
-
inheritance support, ensuring that each class in the hierarchy has its own
|
|
35
|
+
This method implements a truly thread-safe singleton pattern with proper
|
|
36
|
+
inheritance support, ensuring that each class in the hierarchy has its own
|
|
37
37
|
singleton instance. Uses double-checked locking with proper memory barriers.
|
|
38
38
|
|
|
39
39
|
Returns
|
|
@@ -4,7 +4,10 @@ class ScopedContext:
|
|
|
4
4
|
"""
|
|
5
5
|
Holds scoped instances for the current context.
|
|
6
6
|
"""
|
|
7
|
-
_active_scope = contextvars.ContextVar(
|
|
7
|
+
_active_scope = contextvars.ContextVar(
|
|
8
|
+
"orionis_scope",
|
|
9
|
+
default=None
|
|
10
|
+
)
|
|
8
11
|
|
|
9
12
|
@classmethod
|
|
10
13
|
def getCurrentScope(cls):
|
|
@@ -3,7 +3,7 @@ from abc import ABC, abstractmethod
|
|
|
3
3
|
class IServiceProvider(ABC):
|
|
4
4
|
|
|
5
5
|
@abstractmethod
|
|
6
|
-
def register(self) -> None:
|
|
6
|
+
async def register(self) -> None:
|
|
7
7
|
"""
|
|
8
8
|
Register services into the application container.
|
|
9
9
|
|
|
@@ -19,7 +19,7 @@ class IServiceProvider(ABC):
|
|
|
19
19
|
pass
|
|
20
20
|
|
|
21
21
|
@abstractmethod
|
|
22
|
-
def boot(self) -> None:
|
|
22
|
+
async def boot(self) -> None:
|
|
23
23
|
"""
|
|
24
24
|
Perform any post-registration bootstrapping or initialization.
|
|
25
25
|
|
|
@@ -1,14 +1,15 @@
|
|
|
1
|
-
from dataclasses import
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
2
|
from orionis.container.enums.lifetimes import Lifetime
|
|
3
3
|
from orionis.container.exceptions import OrionisContainerTypeError
|
|
4
|
+
from orionis.support.entities.base import BaseEntity
|
|
4
5
|
|
|
5
6
|
@dataclass(unsafe_hash=True, kw_only=True)
|
|
6
|
-
class Binding:
|
|
7
|
+
class Binding(BaseEntity):
|
|
7
8
|
|
|
8
9
|
contract: type = field(
|
|
9
10
|
default=None,
|
|
10
11
|
metadata={
|
|
11
|
-
"description": "
|
|
12
|
+
"description": "Contract of the concrete class to inject.",
|
|
12
13
|
"default": None
|
|
13
14
|
}
|
|
14
15
|
)
|
|
@@ -16,7 +17,7 @@ class Binding:
|
|
|
16
17
|
concrete: type = field(
|
|
17
18
|
default=None,
|
|
18
19
|
metadata={
|
|
19
|
-
"description": "
|
|
20
|
+
"description": "Concrete class implementing the contract.",
|
|
20
21
|
"default": None
|
|
21
22
|
}
|
|
22
23
|
)
|
|
@@ -24,7 +25,7 @@ class Binding:
|
|
|
24
25
|
instance: object = field(
|
|
25
26
|
default=None,
|
|
26
27
|
metadata={
|
|
27
|
-
"description": "
|
|
28
|
+
"description": "Concrete instance of the class, if provided.",
|
|
28
29
|
"default": None
|
|
29
30
|
}
|
|
30
31
|
)
|
|
@@ -32,7 +33,7 @@ class Binding:
|
|
|
32
33
|
function: callable = field(
|
|
33
34
|
default=None,
|
|
34
35
|
metadata={
|
|
35
|
-
"description": "
|
|
36
|
+
"description": "Function invoked to create the instance.",
|
|
36
37
|
"default": None
|
|
37
38
|
}
|
|
38
39
|
)
|
|
@@ -40,7 +41,7 @@ class Binding:
|
|
|
40
41
|
lifetime: Lifetime = field(
|
|
41
42
|
default=Lifetime.TRANSIENT,
|
|
42
43
|
metadata={
|
|
43
|
-
"description": "
|
|
44
|
+
"description": "Lifetime of the instance.",
|
|
44
45
|
"default": Lifetime.TRANSIENT
|
|
45
46
|
}
|
|
46
47
|
)
|
|
@@ -48,7 +49,7 @@ class Binding:
|
|
|
48
49
|
enforce_decoupling: bool = field(
|
|
49
50
|
default=False,
|
|
50
51
|
metadata={
|
|
51
|
-
"description": "
|
|
52
|
+
"description": "Indicates whether to enforce decoupling between contract and concrete.",
|
|
52
53
|
"default": False
|
|
53
54
|
}
|
|
54
55
|
)
|
|
@@ -56,69 +57,55 @@ class Binding:
|
|
|
56
57
|
alias: str = field(
|
|
57
58
|
default=None,
|
|
58
59
|
metadata={
|
|
59
|
-
"description": "Alias
|
|
60
|
+
"description": "Alias for resolving the dependency from the container.",
|
|
60
61
|
"default": None
|
|
61
62
|
}
|
|
62
63
|
)
|
|
63
64
|
|
|
64
65
|
def __post_init__(self):
|
|
65
66
|
"""
|
|
66
|
-
|
|
67
|
+
Validates the types of specific instance attributes after object initialization.
|
|
68
|
+
|
|
69
|
+
This method ensures that:
|
|
70
|
+
- The 'lifetime' attribute is an instance of the `Lifetime` enum.
|
|
71
|
+
- The 'enforce_decoupling' attribute is a boolean.
|
|
72
|
+
- The 'alias' attribute is either a string or None.
|
|
73
|
+
|
|
74
|
+
If any of these conditions are not met, an `OrionisContainerTypeError` is raised to prevent improper usage.
|
|
67
75
|
|
|
68
76
|
Parameters
|
|
69
77
|
----------
|
|
70
78
|
None
|
|
71
79
|
|
|
80
|
+
Returns
|
|
81
|
+
-------
|
|
82
|
+
None
|
|
83
|
+
This method does not return any value. It raises an exception if validation fails.
|
|
84
|
+
|
|
72
85
|
Raises
|
|
73
86
|
------
|
|
74
87
|
OrionisContainerTypeError
|
|
75
|
-
If 'lifetime' is not an instance of `Lifetime
|
|
88
|
+
If 'lifetime' is not an instance of `Lifetime`.
|
|
76
89
|
OrionisContainerTypeError
|
|
77
90
|
If 'enforce_decoupling' is not of type `bool`.
|
|
78
91
|
OrionisContainerTypeError
|
|
79
92
|
If 'alias' is not of type `str` or `None`.
|
|
80
93
|
"""
|
|
81
|
-
|
|
94
|
+
|
|
95
|
+
# Validate that 'lifetime' is an instance of Lifetime enum if provided
|
|
96
|
+
if self.lifetime and not isinstance(self.lifetime, Lifetime):
|
|
82
97
|
raise OrionisContainerTypeError(
|
|
83
98
|
f"The 'lifetime' attribute must be an instance of 'Lifetime', but received type '{type(self.lifetime).__name__}'."
|
|
84
99
|
)
|
|
85
100
|
|
|
101
|
+
# Validate that 'enforce_decoupling' is a boolean
|
|
86
102
|
if not isinstance(self.enforce_decoupling, bool):
|
|
87
103
|
raise OrionisContainerTypeError(
|
|
88
104
|
f"The 'enforce_decoupling' attribute must be of type 'bool', but received type '{type(self.enforce_decoupling).__name__}'."
|
|
89
105
|
)
|
|
90
106
|
|
|
91
|
-
|
|
107
|
+
# Validate that 'alias' is either a string or None
|
|
108
|
+
if self.alias and not isinstance(self.alias, str):
|
|
92
109
|
raise OrionisContainerTypeError(
|
|
93
110
|
f"The 'alias' attribute must be of type 'str' or 'None', but received type '{type(self.alias).__name__}'."
|
|
94
|
-
)
|
|
95
|
-
|
|
96
|
-
def toDict(self) -> dict:
|
|
97
|
-
"""
|
|
98
|
-
Convert the object to a dictionary representation.
|
|
99
|
-
Returns:
|
|
100
|
-
dict: A dictionary representation of the Dataclass object.
|
|
101
|
-
"""
|
|
102
|
-
return asdict(self)
|
|
103
|
-
|
|
104
|
-
def getFields(self):
|
|
105
|
-
"""
|
|
106
|
-
Retrieves a list of field information for the current dataclass instance.
|
|
107
|
-
|
|
108
|
-
Returns:
|
|
109
|
-
list: A list of dictionaries, each containing details about a field:
|
|
110
|
-
- name (str): The name of the field.
|
|
111
|
-
- type (type): The type of the field.
|
|
112
|
-
- default: The default value of the field, if specified; otherwise, the value from metadata or None.
|
|
113
|
-
- metadata (mapping): The metadata associated with the field.
|
|
114
|
-
"""
|
|
115
|
-
__fields = []
|
|
116
|
-
for field in fields(self):
|
|
117
|
-
__metadata = dict(field.metadata) or {}
|
|
118
|
-
__fields.append({
|
|
119
|
-
"name": field.name,
|
|
120
|
-
"type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
|
|
121
|
-
"default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
|
|
122
|
-
"metadata": __metadata
|
|
123
|
-
})
|
|
124
|
-
return __fields
|
|
111
|
+
)
|
|
@@ -1,8 +1,29 @@
|
|
|
1
1
|
from enum import Enum, auto
|
|
2
2
|
|
|
3
3
|
class Lifetime(Enum):
|
|
4
|
-
"""
|
|
4
|
+
"""
|
|
5
|
+
Represents the lifecycle types used for dependency injection.
|
|
5
6
|
|
|
7
|
+
This enumeration defines how and when instances of a dependency are created and shared.
|
|
8
|
+
|
|
9
|
+
Attributes
|
|
10
|
+
----------
|
|
11
|
+
TRANSIENT : Lifetime
|
|
12
|
+
A new instance is created and provided every time the dependency is requested.
|
|
13
|
+
SINGLETON : Lifetime
|
|
14
|
+
A single shared instance is created and used throughout the entire application lifetime.
|
|
15
|
+
SCOPED : Lifetime
|
|
16
|
+
An instance is created and shared within a defined scope (such as per request or session).
|
|
17
|
+
|
|
18
|
+
Returns
|
|
19
|
+
-------
|
|
20
|
+
Lifetime
|
|
21
|
+
An enumeration member representing the selected lifecycle type.
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
# A new instance is provided every time the dependency is requested.
|
|
6
25
|
TRANSIENT = auto()
|
|
26
|
+
# A single shared instance is provided for the entire application lifetime.
|
|
7
27
|
SINGLETON = auto()
|
|
28
|
+
# An instance is provided per scope (e.g., per request or session).
|
|
8
29
|
SCOPED = auto()
|
|
@@ -31,7 +31,7 @@ class ServiceProvider(IServiceProvider):
|
|
|
31
31
|
"""
|
|
32
32
|
self.app = app
|
|
33
33
|
|
|
34
|
-
def register(self) -> None:
|
|
34
|
+
async def register(self) -> None:
|
|
35
35
|
"""
|
|
36
36
|
Register services into the application container.
|
|
37
37
|
|
|
@@ -46,7 +46,7 @@ class ServiceProvider(IServiceProvider):
|
|
|
46
46
|
"""
|
|
47
47
|
raise NotImplementedError("This method should be overridden in the subclass")
|
|
48
48
|
|
|
49
|
-
def boot(self) -> None:
|
|
49
|
+
async def boot(self) -> None:
|
|
50
50
|
"""
|
|
51
51
|
Perform any post-registration bootstrapping or initialization.
|
|
52
52
|
|