orionis 0.617.0__py3-none-any.whl → 0.619.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 +103 -36
- orionis/console/contracts/base_command.py +140 -75
- orionis/console/core/reactor.py +64 -49
- orionis/foundation/application.py +3 -5
- orionis/metadata/framework.py +1 -1
- orionis/test/core/unit_test.py +12 -13
- {orionis-0.617.0.dist-info → orionis-0.619.0.dist-info}/METADATA +1 -1
- {orionis-0.617.0.dist-info → orionis-0.619.0.dist-info}/RECORD +11 -11
- {orionis-0.617.0.dist-info → orionis-0.619.0.dist-info}/WHEEL +0 -0
- {orionis-0.617.0.dist-info → orionis-0.619.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.617.0.dist-info → orionis-0.619.0.dist-info}/top_level.txt +0 -0
orionis/console/base/command.py
CHANGED
|
@@ -24,34 +24,6 @@ class BaseCommand(Console, ProgressBar, IBaseCommand):
|
|
|
24
24
|
|
|
25
25
|
The class integrates with the framework's console and progress bar systems,
|
|
26
26
|
allowing commands to provide rich user feedback during execution.
|
|
27
|
-
|
|
28
|
-
Attributes
|
|
29
|
-
----------
|
|
30
|
-
timestamps : bool, default True
|
|
31
|
-
Controls whether timestamps are included in console output messages.
|
|
32
|
-
When True, all console output will be prefixed with timestamp information.
|
|
33
|
-
signature : str
|
|
34
|
-
Defines the command signature string used for command registration and
|
|
35
|
-
automatic help text generation. This should follow the framework's
|
|
36
|
-
signature format conventions.
|
|
37
|
-
description : str
|
|
38
|
-
Human-readable description of the command's purpose and functionality.
|
|
39
|
-
Used in help documentation and command listing interfaces.
|
|
40
|
-
_args : Dict[str, Any], default {}
|
|
41
|
-
Dictionary containing parsed command-line arguments and options.
|
|
42
|
-
Populated automatically by the command parser before handle() execution.
|
|
43
|
-
arguments : List[CLIArgument], default []
|
|
44
|
-
List of CLIArgument instances defining the command's accepted arguments
|
|
45
|
-
and options. Used for argument parsing and validation.
|
|
46
|
-
|
|
47
|
-
Methods
|
|
48
|
-
-------
|
|
49
|
-
handle()
|
|
50
|
-
Abstract method that must be implemented by subclasses to define the
|
|
51
|
-
main command execution logic.
|
|
52
|
-
argument(key: str)
|
|
53
|
-
Safely retrieves argument values from the parsed arguments dictionary
|
|
54
|
-
with type validation and error handling.
|
|
55
27
|
"""
|
|
56
28
|
|
|
57
29
|
# Enable timestamps in console output by default
|
|
@@ -64,12 +36,43 @@ class BaseCommand(Console, ProgressBar, IBaseCommand):
|
|
|
64
36
|
description: str
|
|
65
37
|
|
|
66
38
|
# Dictionary to store parsed command-line arguments and options
|
|
67
|
-
|
|
39
|
+
__args: Dict[str, Any] = {}
|
|
40
|
+
|
|
41
|
+
async def options(self) -> List[CLIArgument]:
|
|
42
|
+
"""
|
|
43
|
+
Defines the command-line arguments and options accepted by the command.
|
|
44
|
+
|
|
45
|
+
This asynchronous method should be overridden by subclasses to specify the list of
|
|
46
|
+
command-line arguments and options that the command supports. Each argument or option
|
|
47
|
+
should be represented as a CLIArgument object, which encapsulates details such as the
|
|
48
|
+
argument's name, type, default value, and help description.
|
|
49
|
+
|
|
50
|
+
This method enables the framework to automatically parse, validate, and document
|
|
51
|
+
the available arguments for each command, ensuring consistent user experience
|
|
52
|
+
across all commands.
|
|
53
|
+
|
|
54
|
+
Parameters
|
|
55
|
+
----------
|
|
56
|
+
None
|
|
57
|
+
|
|
58
|
+
Returns
|
|
59
|
+
-------
|
|
60
|
+
List
|
|
61
|
+
A list of CLIArgument objects, where each object describes a single
|
|
62
|
+
command-line argument or option accepted by the command. If the command
|
|
63
|
+
does not accept any arguments or options, an empty list is returned.
|
|
68
64
|
|
|
69
|
-
|
|
70
|
-
|
|
65
|
+
Notes
|
|
66
|
+
-----
|
|
67
|
+
Subclasses should override this method to declare their specific arguments.
|
|
68
|
+
The returned list is used by the framework for argument parsing and help
|
|
69
|
+
text generation.
|
|
70
|
+
"""
|
|
71
71
|
|
|
72
|
-
|
|
72
|
+
# Return an empty list by default; subclasses should override to provide arguments
|
|
73
|
+
return []
|
|
74
|
+
|
|
75
|
+
async def handle(self):
|
|
73
76
|
"""
|
|
74
77
|
Execute the main command logic.
|
|
75
78
|
|
|
@@ -99,6 +102,70 @@ class BaseCommand(Console, ProgressBar, IBaseCommand):
|
|
|
99
102
|
# Raise an error to enforce implementation in subclasses
|
|
100
103
|
raise NotImplementedError("The 'handle' method must be implemented in the subclass.")
|
|
101
104
|
|
|
105
|
+
def setArguments(self, args: Dict[str, Any]) -> None:
|
|
106
|
+
"""
|
|
107
|
+
Populate the internal arguments dictionary with parsed command-line arguments and options.
|
|
108
|
+
|
|
109
|
+
This method is intended for internal use by the command parsing mechanism to initialize
|
|
110
|
+
the internal arguments state before command execution. It assigns the provided dictionary
|
|
111
|
+
of arguments and options to the internal storage, making them accessible via the
|
|
112
|
+
`argument()` and `arguments()` methods.
|
|
113
|
+
|
|
114
|
+
Parameters
|
|
115
|
+
----------
|
|
116
|
+
args : Dict[str, Any]
|
|
117
|
+
Dictionary containing parsed command-line arguments and options, where each key
|
|
118
|
+
represents an argument name and each value is the corresponding argument value.
|
|
119
|
+
|
|
120
|
+
Returns
|
|
121
|
+
-------
|
|
122
|
+
None
|
|
123
|
+
This method does not return any value. It updates the internal state of the command
|
|
124
|
+
instance to reflect the provided arguments.
|
|
125
|
+
|
|
126
|
+
Raises
|
|
127
|
+
------
|
|
128
|
+
ValueError
|
|
129
|
+
If the provided `args` parameter is not a dictionary.
|
|
130
|
+
|
|
131
|
+
Notes
|
|
132
|
+
-----
|
|
133
|
+
This method is automatically invoked by the command framework prior to the execution
|
|
134
|
+
of the `handle()` method. It should not be called directly by command implementations.
|
|
135
|
+
"""
|
|
136
|
+
|
|
137
|
+
# Ensure the provided arguments are in dictionary form
|
|
138
|
+
if not isinstance(args, dict):
|
|
139
|
+
raise ValueError(f"Arguments must be a dictionary, got '{type(args).__name__}' instead.")
|
|
140
|
+
|
|
141
|
+
# Store the parsed arguments internally for later retrieval
|
|
142
|
+
self.__args = args
|
|
143
|
+
|
|
144
|
+
def arguments(self) -> Dict[str, Any]:
|
|
145
|
+
"""
|
|
146
|
+
Retrieve the entire dictionary of parsed command-line arguments and options.
|
|
147
|
+
|
|
148
|
+
This method provides access to all arguments and options that have been parsed
|
|
149
|
+
and stored internally for the current command execution. It is useful for
|
|
150
|
+
scenarios where bulk access to all argument values is required, such as
|
|
151
|
+
dynamic processing or debugging.
|
|
152
|
+
|
|
153
|
+
Returns
|
|
154
|
+
-------
|
|
155
|
+
Dict[str, Any]
|
|
156
|
+
A dictionary containing all parsed command-line arguments and options,
|
|
157
|
+
where each key is the argument name and each value is the corresponding
|
|
158
|
+
argument value.
|
|
159
|
+
|
|
160
|
+
Notes
|
|
161
|
+
-----
|
|
162
|
+
The returned dictionary reflects the current state of the command's arguments.
|
|
163
|
+
Modifying the returned dictionary will affect the internal state of the command.
|
|
164
|
+
"""
|
|
165
|
+
|
|
166
|
+
# Return the internal dictionary containing all parsed arguments and options
|
|
167
|
+
return self.__args
|
|
168
|
+
|
|
102
169
|
def argument(self, key: str, default: Any = None) -> Any:
|
|
103
170
|
"""
|
|
104
171
|
Retrieve the value of a specific command-line argument by key with optional default fallback.
|
|
@@ -131,7 +198,7 @@ class BaseCommand(Console, ProgressBar, IBaseCommand):
|
|
|
131
198
|
ValueError
|
|
132
199
|
If the provided key parameter is not of string type.
|
|
133
200
|
ValueError
|
|
134
|
-
If the internal
|
|
201
|
+
If the internal __args attribute is not of dictionary type, indicating
|
|
135
202
|
a corrupted or improperly initialized command state.
|
|
136
203
|
"""
|
|
137
204
|
|
|
@@ -140,8 +207,8 @@ class BaseCommand(Console, ProgressBar, IBaseCommand):
|
|
|
140
207
|
raise ValueError(f"Argument key must be a string, got '{type(key).__name__}' instead.")
|
|
141
208
|
|
|
142
209
|
# Ensure the internal args attribute is a valid dictionary
|
|
143
|
-
if not isinstance(self.
|
|
144
|
-
raise ValueError(f"Arguments must be a dictionary, got '{type(self.
|
|
210
|
+
if not isinstance(self.__args, dict):
|
|
211
|
+
raise ValueError(f"Arguments must be a dictionary, got '{type(self.__args).__name__}' instead.")
|
|
145
212
|
|
|
146
213
|
# Safely retrieve the argument value with optional default fallback
|
|
147
|
-
return self.
|
|
214
|
+
return self.__args.get(key, default)
|
|
@@ -15,51 +15,6 @@ class IBaseCommand(ABC):
|
|
|
15
15
|
ensuring all commands follow a uniform pattern for registration, execution,
|
|
16
16
|
and user interaction while maintaining flexibility for specific command logic
|
|
17
17
|
implementation.
|
|
18
|
-
|
|
19
|
-
Attributes
|
|
20
|
-
----------
|
|
21
|
-
timestamps : bool, default=True
|
|
22
|
-
Controls whether timestamps are displayed in console output. When enabled,
|
|
23
|
-
all console messages will include timestamp prefixes for better debugging
|
|
24
|
-
and logging capabilities.
|
|
25
|
-
signature : str
|
|
26
|
-
The command signature string that defines the command name and expected
|
|
27
|
-
arguments format. Used for command registration in the console system
|
|
28
|
-
and automatic help text generation. Must follow the framework's signature
|
|
29
|
-
format conventions.
|
|
30
|
-
description : str
|
|
31
|
-
Human-readable description explaining the command's purpose and functionality.
|
|
32
|
-
This text is displayed in help documentation, command listings, and usage
|
|
33
|
-
instructions to assist users in understanding the command's capabilities.
|
|
34
|
-
_args : Dict[str, Any]
|
|
35
|
-
Dictionary containing parsed command-line arguments and options passed to
|
|
36
|
-
the command during execution. Populated automatically by the command parser
|
|
37
|
-
before the handle() method is called, providing structured access to all
|
|
38
|
-
user-provided input parameters.
|
|
39
|
-
arguments : List[CLIArgument]
|
|
40
|
-
List of CLIArgument instances defining the command's accepted arguments
|
|
41
|
-
and options. Used for argument parsing, validation, and help text generation.
|
|
42
|
-
|
|
43
|
-
Methods
|
|
44
|
-
-------
|
|
45
|
-
handle() -> None
|
|
46
|
-
Abstract method that must be implemented by all concrete command subclasses.
|
|
47
|
-
Contains the main execution logic specific to each command type and handles
|
|
48
|
-
argument processing, business logic execution, and output generation.
|
|
49
|
-
|
|
50
|
-
Notes
|
|
51
|
-
-----
|
|
52
|
-
- All concrete implementations must override the handle() method
|
|
53
|
-
- Command signatures should follow framework naming conventions
|
|
54
|
-
- Use self._args dictionary to access parsed command-line arguments
|
|
55
|
-
- Implement proper error handling and validation within command logic
|
|
56
|
-
- Follow single responsibility principle for maintainable command structure
|
|
57
|
-
- Utilize framework's console output methods for consistent user experience
|
|
58
|
-
|
|
59
|
-
See Also
|
|
60
|
-
--------
|
|
61
|
-
abc.ABC : Abstract base class functionality
|
|
62
|
-
typing.Dict : Type hints for argument dictionary structure
|
|
63
18
|
"""
|
|
64
19
|
|
|
65
20
|
# Enable timestamps in console output by default
|
|
@@ -72,52 +27,162 @@ class IBaseCommand(ABC):
|
|
|
72
27
|
description: str
|
|
73
28
|
|
|
74
29
|
# Dictionary to store parsed command-line arguments and options
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
# List of CLIArgument instances defining command arguments
|
|
78
|
-
arguments: List[CLIArgument] = []
|
|
30
|
+
__args: Dict[str, Any] = {}
|
|
79
31
|
|
|
80
32
|
@abstractmethod
|
|
81
|
-
def
|
|
33
|
+
async def options(self) -> List[CLIArgument]:
|
|
82
34
|
"""
|
|
83
|
-
|
|
35
|
+
Defines the command-line arguments and options accepted by the command.
|
|
84
36
|
|
|
85
|
-
This
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
output or side effects.
|
|
37
|
+
This asynchronous method should be overridden by subclasses to specify the list of
|
|
38
|
+
command-line arguments and options that the command supports. Each argument or option
|
|
39
|
+
should be represented as a CLIArgument object, which encapsulates details such as the
|
|
40
|
+
argument's name, type, default value, and help description.
|
|
90
41
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
42
|
+
This method enables the framework to automatically parse, validate, and document
|
|
43
|
+
the available arguments for each command, ensuring consistent user experience
|
|
44
|
+
across all commands.
|
|
45
|
+
|
|
46
|
+
Parameters
|
|
47
|
+
----------
|
|
48
|
+
None
|
|
49
|
+
|
|
50
|
+
Returns
|
|
51
|
+
-------
|
|
52
|
+
List
|
|
53
|
+
A list of CLIArgument objects, where each object describes a single
|
|
54
|
+
command-line argument or option accepted by the command. If the command
|
|
55
|
+
does not accept any arguments or options, an empty list is returned.
|
|
56
|
+
|
|
57
|
+
Notes
|
|
58
|
+
-----
|
|
59
|
+
Subclasses should override this method to declare their specific arguments.
|
|
60
|
+
The returned list is used by the framework for argument parsing and help
|
|
61
|
+
text generation.
|
|
62
|
+
"""
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
@abstractmethod
|
|
66
|
+
async def handle(self):
|
|
67
|
+
"""
|
|
68
|
+
Execute the main command logic.
|
|
69
|
+
|
|
70
|
+
This abstract method defines the entry point for command execution and must be
|
|
71
|
+
implemented by all concrete command subclasses. It serves as the primary interface
|
|
72
|
+
for running the command's core functionality after argument parsing and validation.
|
|
95
73
|
|
|
96
74
|
Returns
|
|
97
75
|
-------
|
|
98
76
|
None
|
|
99
|
-
This method does not return any value. All command output
|
|
100
|
-
|
|
101
|
-
output methods, file operations, database transactions, or other
|
|
102
|
-
side effects rather than return values.
|
|
77
|
+
This method does not return any value. All command output should be handled
|
|
78
|
+
through the inherited console methods or other side effects.
|
|
103
79
|
|
|
104
80
|
Raises
|
|
105
81
|
------
|
|
106
82
|
NotImplementedError
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
83
|
+
Always raised when called on the base class, indicating that subclasses
|
|
84
|
+
must provide their own implementation of this method.
|
|
85
|
+
|
|
86
|
+
Notes
|
|
87
|
+
-----
|
|
88
|
+
Subclasses should override this method to implement their specific command
|
|
89
|
+
behavior. The method will be called after all command-line arguments have
|
|
90
|
+
been parsed and stored in the _args dictionary.
|
|
91
|
+
"""
|
|
92
|
+
pass
|
|
93
|
+
|
|
94
|
+
@abstractmethod
|
|
95
|
+
def setArguments(self, args: Dict[str, Any]) -> None:
|
|
96
|
+
"""
|
|
97
|
+
Populate the internal arguments dictionary with parsed command-line arguments and options.
|
|
98
|
+
|
|
99
|
+
This method is intended for internal use by the command parsing mechanism to initialize
|
|
100
|
+
the internal arguments state before command execution. It assigns the provided dictionary
|
|
101
|
+
of arguments and options to the internal storage, making them accessible via the
|
|
102
|
+
`argument()` and `arguments()` methods.
|
|
103
|
+
|
|
104
|
+
Parameters
|
|
105
|
+
----------
|
|
106
|
+
args : Dict[str, Any]
|
|
107
|
+
Dictionary containing parsed command-line arguments and options, where each key
|
|
108
|
+
represents an argument name and each value is the corresponding argument value.
|
|
109
|
+
|
|
110
|
+
Returns
|
|
111
|
+
-------
|
|
112
|
+
None
|
|
113
|
+
This method does not return any value. It updates the internal state of the command
|
|
114
|
+
instance to reflect the provided arguments.
|
|
115
|
+
|
|
116
|
+
Raises
|
|
117
|
+
------
|
|
118
|
+
ValueError
|
|
119
|
+
If the provided `args` parameter is not a dictionary.
|
|
110
120
|
|
|
111
121
|
Notes
|
|
112
122
|
-----
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
123
|
+
This method is automatically invoked by the command framework prior to the execution
|
|
124
|
+
of the `handle()` method. It should not be called directly by command implementations.
|
|
125
|
+
"""
|
|
126
|
+
pass
|
|
127
|
+
|
|
128
|
+
@abstractmethod
|
|
129
|
+
def arguments(self) -> Dict[str, Any]:
|
|
119
130
|
"""
|
|
131
|
+
Retrieve the entire dictionary of parsed command-line arguments and options.
|
|
120
132
|
|
|
121
|
-
|
|
122
|
-
|
|
133
|
+
This method provides access to all arguments and options that have been parsed
|
|
134
|
+
and stored internally for the current command execution. It is useful for
|
|
135
|
+
scenarios where bulk access to all argument values is required, such as
|
|
136
|
+
dynamic processing or debugging.
|
|
137
|
+
|
|
138
|
+
Returns
|
|
139
|
+
-------
|
|
140
|
+
Dict[str, Any]
|
|
141
|
+
A dictionary containing all parsed command-line arguments and options,
|
|
142
|
+
where each key is the argument name and each value is the corresponding
|
|
143
|
+
argument value.
|
|
144
|
+
|
|
145
|
+
Notes
|
|
146
|
+
-----
|
|
147
|
+
The returned dictionary reflects the current state of the command's arguments.
|
|
148
|
+
Modifying the returned dictionary will affect the internal state of the command.
|
|
149
|
+
"""
|
|
150
|
+
pass
|
|
151
|
+
|
|
152
|
+
@abstractmethod
|
|
153
|
+
def argument(self, key: str, default: Any = None) -> Any:
|
|
154
|
+
"""
|
|
155
|
+
Retrieve the value of a specific command-line argument by key with optional default fallback.
|
|
156
|
+
|
|
157
|
+
This method provides safe and validated access to command-line arguments stored in the
|
|
158
|
+
internal arguments dictionary. It performs type checking on both the key parameter and
|
|
159
|
+
the internal _args attribute to ensure data integrity before attempting retrieval.
|
|
160
|
+
|
|
161
|
+
The method follows a fail-safe approach by returning a default value when the requested
|
|
162
|
+
argument key is not found, preventing KeyError exceptions during command execution.
|
|
163
|
+
|
|
164
|
+
Parameters
|
|
165
|
+
----------
|
|
166
|
+
key : str
|
|
167
|
+
The string identifier used to locate the desired argument in the arguments
|
|
168
|
+
dictionary. Must be a non-empty string that corresponds to a valid argument name.
|
|
169
|
+
default : Any, optional
|
|
170
|
+
The fallback value to return if the specified key is not found in the arguments
|
|
171
|
+
dictionary. Defaults to None if not provided.
|
|
172
|
+
|
|
173
|
+
Returns
|
|
174
|
+
-------
|
|
175
|
+
Any
|
|
176
|
+
The value associated with the specified key if it exists in the arguments
|
|
177
|
+
dictionary. If the key is not found, returns the provided default value
|
|
178
|
+
or None if no default was specified.
|
|
179
|
+
|
|
180
|
+
Raises
|
|
181
|
+
------
|
|
182
|
+
ValueError
|
|
183
|
+
If the provided key parameter is not of string type.
|
|
184
|
+
ValueError
|
|
185
|
+
If the internal __args attribute is not of dictionary type, indicating
|
|
186
|
+
a corrupted or improperly initialized command state.
|
|
187
|
+
"""
|
|
123
188
|
pass
|
orionis/console/core/reactor.py
CHANGED
|
@@ -15,6 +15,8 @@ from orionis.console.contracts.executor import IExecutor
|
|
|
15
15
|
from orionis.console.exceptions import CLIOrionisTypeError
|
|
16
16
|
from orionis.console.request.cli_request import CLIRequest
|
|
17
17
|
from orionis.foundation.contracts.application import IApplication
|
|
18
|
+
from orionis.services.introspection.concretes.reflection import ReflectionConcrete
|
|
19
|
+
from orionis.services.introspection.instances.reflection import ReflectionInstance
|
|
18
20
|
from orionis.services.introspection.modules.reflection import ReflectionModule
|
|
19
21
|
from orionis.services.log.contracts.log_service import ILogger
|
|
20
22
|
from orionis.support.performance.contracts.counter import IPerformanceCounter
|
|
@@ -75,18 +77,6 @@ class Reactor(IReactor):
|
|
|
75
77
|
# List to hold fluent command definitions
|
|
76
78
|
self.__fluent_commands: List[ICommand] = []
|
|
77
79
|
|
|
78
|
-
# Load core commands immediately upon initialization
|
|
79
|
-
self.__loadCoreCommands()
|
|
80
|
-
self.__load__core_commands: bool = True
|
|
81
|
-
|
|
82
|
-
# Load custom user-defined commands from the project's commands directory
|
|
83
|
-
self.__loadCustomCommands()
|
|
84
|
-
self.__load__custom_commands: bool = True
|
|
85
|
-
|
|
86
|
-
# Flag to track if fluent commands have been loaded
|
|
87
|
-
self.__loadFluentCommands()
|
|
88
|
-
self.__load_fluent_commands: bool = True
|
|
89
|
-
|
|
90
80
|
def __loadCommands(self) -> None:
|
|
91
81
|
"""
|
|
92
82
|
Loads all available commands into the reactor's internal registry.
|
|
@@ -123,17 +113,17 @@ class Reactor(IReactor):
|
|
|
123
113
|
"""
|
|
124
114
|
|
|
125
115
|
# Load core commands if they have not been loaded yet
|
|
126
|
-
if not self.__load__core_commands:
|
|
116
|
+
if not hasattr(self, '_Reactor__load__core_commands') or not self.__load__core_commands:
|
|
127
117
|
self.__loadCoreCommands()
|
|
128
118
|
self.__load__core_commands = True
|
|
129
119
|
|
|
130
120
|
# Load custom user-defined commands if they have not been loaded yet
|
|
131
|
-
if not self.__load__custom_commands:
|
|
121
|
+
if not hasattr(self, '_Reactor__load__custom_commands') or not self.__load__custom_commands:
|
|
132
122
|
self.__loadCustomCommands()
|
|
133
123
|
self.__load__custom_commands = True
|
|
134
124
|
|
|
135
125
|
# Load fluent interface commands if they have not been loaded yet
|
|
136
|
-
if not self.__load_fluent_commands:
|
|
126
|
+
if not hasattr(self, '_Reactor__load_fluent_commands') or not self.__load_fluent_commands:
|
|
137
127
|
self.__loadFluentCommands()
|
|
138
128
|
self.__load_fluent_commands = True
|
|
139
129
|
|
|
@@ -317,7 +307,7 @@ class Reactor(IReactor):
|
|
|
317
307
|
for obj in core_commands:
|
|
318
308
|
|
|
319
309
|
# Get the signature attribute from the command class
|
|
320
|
-
signature =
|
|
310
|
+
signature = ReflectionConcrete(obj).getAttribute('signature')
|
|
321
311
|
|
|
322
312
|
# Skip if signature is not defined
|
|
323
313
|
if signature is None:
|
|
@@ -501,7 +491,9 @@ class Reactor(IReactor):
|
|
|
501
491
|
|
|
502
492
|
# Validate the signature against the required pattern
|
|
503
493
|
if not re.match(pattern, obj.signature):
|
|
504
|
-
raise CLIOrionisValueError(
|
|
494
|
+
raise CLIOrionisValueError(
|
|
495
|
+
f"Command class {obj.__name__} 'signature' must contain only alphanumeric characters, underscores (_) and colons (:), cannot start or end with underscore or colon, and cannot start with a number."
|
|
496
|
+
)
|
|
505
497
|
|
|
506
498
|
# Return signature
|
|
507
499
|
return obj.signature.strip()
|
|
@@ -553,8 +545,8 @@ class Reactor(IReactor):
|
|
|
553
545
|
"""
|
|
554
546
|
Validates and processes command arguments for a command class.
|
|
555
547
|
|
|
556
|
-
|
|
557
|
-
and
|
|
548
|
+
Ensures the command class provides a valid list of CLIArgument instances via its 'options' method,
|
|
549
|
+
and constructs an ArgumentParser accordingly.
|
|
558
550
|
|
|
559
551
|
Parameters
|
|
560
552
|
----------
|
|
@@ -570,43 +562,53 @@ class Reactor(IReactor):
|
|
|
570
562
|
Raises
|
|
571
563
|
------
|
|
572
564
|
CLIOrionisTypeError
|
|
573
|
-
If the '
|
|
565
|
+
If the 'options' method does not return a list or contains non-CLIArgument instances.
|
|
574
566
|
"""
|
|
575
567
|
|
|
576
|
-
#
|
|
577
|
-
|
|
578
|
-
|
|
568
|
+
# Instantiate the command and retrieve its options
|
|
569
|
+
instance = self.__app.make(obj)
|
|
570
|
+
options: List[CLIArgument] = self.__app.call(instance, 'options')
|
|
579
571
|
|
|
580
|
-
#
|
|
581
|
-
if not isinstance(
|
|
582
|
-
raise CLIOrionisTypeError(
|
|
572
|
+
# Validate that options is a list
|
|
573
|
+
if not isinstance(options, list):
|
|
574
|
+
raise CLIOrionisTypeError(
|
|
575
|
+
f"Command class {obj.__name__} 'options' must return a list."
|
|
576
|
+
)
|
|
583
577
|
|
|
584
|
-
#
|
|
585
|
-
if
|
|
578
|
+
# Return None if there are no arguments
|
|
579
|
+
if not options:
|
|
586
580
|
return None
|
|
587
581
|
|
|
588
|
-
# Validate
|
|
589
|
-
for
|
|
590
|
-
if not isinstance(
|
|
591
|
-
raise CLIOrionisTypeError(
|
|
582
|
+
# Validate all items are CLIArgument instances
|
|
583
|
+
for idx, arg in enumerate(options):
|
|
584
|
+
if not isinstance(arg, CLIArgument):
|
|
585
|
+
raise CLIOrionisTypeError(
|
|
586
|
+
f"Command class {obj.__name__} 'options' must contain only CLIArgument instances, "
|
|
587
|
+
f"found '{type(arg).__name__}' at index {idx}."
|
|
588
|
+
)
|
|
589
|
+
|
|
592
590
|
|
|
593
|
-
#
|
|
594
|
-
|
|
591
|
+
# Get the Signature attribute from the command class
|
|
592
|
+
rf_concrete = ReflectionConcrete(obj)
|
|
593
|
+
signature = rf_concrete.getAttribute('signature', '<unknown>')
|
|
594
|
+
description = rf_concrete.getAttribute('description', '')
|
|
595
595
|
|
|
596
|
-
#
|
|
596
|
+
# Build the ArgumentParser
|
|
597
597
|
arg_parser = argparse.ArgumentParser(
|
|
598
|
-
usage=f"python -B reactor {
|
|
599
|
-
description=f"Command [{
|
|
598
|
+
usage=f"python -B reactor {signature} [options]",
|
|
599
|
+
description=f"Command [{signature}] : {description}",
|
|
600
600
|
formatter_class=argparse.RawTextHelpFormatter,
|
|
601
601
|
add_help=True,
|
|
602
602
|
allow_abbrev=False,
|
|
603
603
|
exit_on_error=True,
|
|
604
|
-
prog=
|
|
604
|
+
prog=signature
|
|
605
605
|
)
|
|
606
|
-
|
|
606
|
+
|
|
607
|
+
# Add each CLIArgument to the ArgumentParser
|
|
608
|
+
for arg in options:
|
|
607
609
|
arg.addToParser(arg_parser)
|
|
608
610
|
|
|
609
|
-
# Return the
|
|
611
|
+
# Return the constructed ArgumentParser
|
|
610
612
|
return arg_parser
|
|
611
613
|
|
|
612
614
|
def __parseArgs(
|
|
@@ -646,13 +648,17 @@ class Reactor(IReactor):
|
|
|
646
648
|
|
|
647
649
|
# If the command expects arguments, parse them using its ArgumentParser
|
|
648
650
|
if command.args is not None and isinstance(command.args, argparse.ArgumentParser):
|
|
651
|
+
|
|
652
|
+
# If no args provided, use an empty list
|
|
649
653
|
if args is None:
|
|
650
654
|
args = []
|
|
655
|
+
|
|
656
|
+
# Parse the provided arguments using the command's ArgumentParser
|
|
651
657
|
try:
|
|
652
|
-
# Parse the provided arguments using the command's ArgumentParser
|
|
653
658
|
parsed_args = command.args.parse_args(args)
|
|
659
|
+
|
|
660
|
+
# Raise a CLIOrionisRuntimeError with the help message included in the exception
|
|
654
661
|
except SystemExit:
|
|
655
|
-
# Raise a CLIOrionisRuntimeError with the help message included in the exception
|
|
656
662
|
raise CLIOrionisRuntimeError(
|
|
657
663
|
f"Failed to parse arguments for command '{command.signature}'.\n"
|
|
658
664
|
f"{command.args.format_help()}\n"
|
|
@@ -662,10 +668,13 @@ class Reactor(IReactor):
|
|
|
662
668
|
# Convert the parsed arguments to a dictionary and return
|
|
663
669
|
if isinstance(parsed_args, argparse.Namespace):
|
|
664
670
|
return vars(parsed_args)
|
|
671
|
+
|
|
672
|
+
# If parsed_args is already a dictionary, return it directly
|
|
665
673
|
elif isinstance(parsed_args, dict):
|
|
666
674
|
return parsed_args
|
|
675
|
+
|
|
676
|
+
# Return an empty dictionary if no arguments were parsed
|
|
667
677
|
else:
|
|
668
|
-
# Return an empty dictionary if no arguments were parsed
|
|
669
678
|
return {}
|
|
670
679
|
|
|
671
680
|
def command(
|
|
@@ -837,13 +846,16 @@ class Reactor(IReactor):
|
|
|
837
846
|
command_instance: IBaseCommand = self.__app.make(command.obj)
|
|
838
847
|
|
|
839
848
|
# Inject parsed arguments into the command instance
|
|
840
|
-
|
|
841
|
-
|
|
849
|
+
dict_args = self.__parseArgs(command, args)
|
|
850
|
+
|
|
851
|
+
# Only set arguments if the command instance has a setArguments method
|
|
852
|
+
if ReflectionInstance(command_instance).hasMethod('setArguments'):
|
|
853
|
+
command_instance.setArguments(dict_args.copy())
|
|
842
854
|
|
|
843
855
|
# Inject a scoped CLIRequest instance into the application container for the command's context
|
|
844
856
|
self.__app.scopedInstance(ICLIRequest, CLIRequest(
|
|
845
857
|
command=signature,
|
|
846
|
-
args=
|
|
858
|
+
args=dict_args.copy()
|
|
847
859
|
))
|
|
848
860
|
|
|
849
861
|
# Execute the command's handle method and capture its output
|
|
@@ -940,13 +952,16 @@ class Reactor(IReactor):
|
|
|
940
952
|
command_instance: IBaseCommand = self.__app.make(command.obj)
|
|
941
953
|
|
|
942
954
|
# Inject parsed arguments into the command instance
|
|
943
|
-
|
|
944
|
-
|
|
955
|
+
dict_args = self.__parseArgs(command, args)
|
|
956
|
+
|
|
957
|
+
# Only set arguments if the command instance has a setArguments method
|
|
958
|
+
if ReflectionInstance(command_instance).hasMethod('setArguments'):
|
|
959
|
+
command_instance.setArguments(dict_args.copy())
|
|
945
960
|
|
|
946
961
|
# Inject a scoped CLIRequest instance into the application container for the command's context
|
|
947
962
|
self.__app.scopedInstance(ICLIRequest, CLIRequest(
|
|
948
963
|
command=signature,
|
|
949
|
-
args=
|
|
964
|
+
args=dict_args.copy()
|
|
950
965
|
))
|
|
951
966
|
|
|
952
967
|
# Execute the command's handle method asynchronously and capture its output
|
|
@@ -2118,6 +2118,7 @@ class Application(Container, IApplication):
|
|
|
2118
2118
|
duplicate initialization. The startup time is calculated and logged
|
|
2119
2119
|
for performance monitoring purposes.
|
|
2120
2120
|
"""
|
|
2121
|
+
|
|
2121
2122
|
# Check if already booted
|
|
2122
2123
|
if not self.__booted:
|
|
2123
2124
|
|
|
@@ -2125,7 +2126,7 @@ class Application(Container, IApplication):
|
|
|
2125
2126
|
self.instance(
|
|
2126
2127
|
IApplication,
|
|
2127
2128
|
self,
|
|
2128
|
-
alias=f"x-
|
|
2129
|
+
alias=f"x-orionis.foundation.contracts.application.IApplication",
|
|
2129
2130
|
enforce_decoupling=None
|
|
2130
2131
|
)
|
|
2131
2132
|
|
|
@@ -2149,11 +2150,8 @@ class Application(Container, IApplication):
|
|
|
2149
2150
|
# Calculate elapsed time in milliseconds since application start
|
|
2150
2151
|
elapsed_ms = (time.time_ns() - self.startAt) // 1_000_000
|
|
2151
2152
|
|
|
2152
|
-
# Compose the boot message
|
|
2153
|
-
boot_message = f"Orionis Framework has been successfully booted. Startup time: {elapsed_ms} ms. Started at: {self.startAt} ns"
|
|
2154
|
-
|
|
2155
2153
|
# Log message to the logger
|
|
2156
|
-
logger.info(
|
|
2154
|
+
logger.info(f"Orionis Framework has been successfully booted. Startup time: {elapsed_ms} ms. Started at: {self.startAt} ns")
|
|
2157
2155
|
|
|
2158
2156
|
# Return the application instance for method chaining
|
|
2159
2157
|
return self
|
orionis/metadata/framework.py
CHANGED
orionis/test/core/unit_test.py
CHANGED
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import inspect
|
|
2
1
|
import io
|
|
3
2
|
import json
|
|
4
3
|
import logging
|
|
@@ -118,18 +117,6 @@ class UnitTest(IUnitTest):
|
|
|
118
117
|
# Use live console output during test execution
|
|
119
118
|
self.__live_console: bool = True
|
|
120
119
|
|
|
121
|
-
# Load and set internal paths for test discovery and result storage
|
|
122
|
-
self.__loadPaths()
|
|
123
|
-
|
|
124
|
-
# Load and validate the testing configuration from the application
|
|
125
|
-
self.__loadConfig()
|
|
126
|
-
|
|
127
|
-
# Discover and import test modules based on the configuration
|
|
128
|
-
self.__loadModules()
|
|
129
|
-
|
|
130
|
-
# Discover and load all test cases from the imported modules into the suite
|
|
131
|
-
self.__loadTests()
|
|
132
|
-
|
|
133
120
|
def __loadPaths(
|
|
134
121
|
self
|
|
135
122
|
) -> None:
|
|
@@ -737,6 +724,18 @@ class UnitTest(IUnitTest):
|
|
|
737
724
|
# Record the start time in seconds
|
|
738
725
|
performance_counter.start()
|
|
739
726
|
|
|
727
|
+
# Load and set internal paths for test discovery and result storage
|
|
728
|
+
self.__loadPaths()
|
|
729
|
+
|
|
730
|
+
# Load and validate the testing configuration from the application
|
|
731
|
+
self.__loadConfig()
|
|
732
|
+
|
|
733
|
+
# Discover and import test modules based on the configuration
|
|
734
|
+
self.__loadModules()
|
|
735
|
+
|
|
736
|
+
# Discover and load all test cases from the imported modules into the suite
|
|
737
|
+
self.__loadTests()
|
|
738
|
+
|
|
740
739
|
# Length of all tests in the suite
|
|
741
740
|
total_tests = self.getTestCount()
|
|
742
741
|
|
|
@@ -4,7 +4,7 @@ orionis/console/kernel.py,sha256=NVWA20xasC8xE_fIoX5aKBy7dsrjgownQYarEOYiGKA,375
|
|
|
4
4
|
orionis/console/args/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
5
5
|
orionis/console/args/argument.py,sha256=QkdTrIYfG6CqDEMVBlQvNzRVHlBAcJOinVjq5Lz-wl8,20331
|
|
6
6
|
orionis/console/base/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
orionis/console/base/command.py,sha256=
|
|
7
|
+
orionis/console/base/command.py,sha256=tAO_EVy1aNWneNSKYYMAf9yDTfbvHAqSJnZZ6pOR4tE,9318
|
|
8
8
|
orionis/console/base/scheduler.py,sha256=IKNhpI_lPbI8H3YruD9z7eNdjuqNYceaclx_Hr5BHfY,8065
|
|
9
9
|
orionis/console/base/scheduler_event_listener.py,sha256=X2mZBAYLBCtLOH7QSrCEaLeJ5m8Hq5UtGxaWRRvWbfo,4421
|
|
10
10
|
orionis/console/commands/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -18,7 +18,7 @@ orionis/console/commands/test.py,sha256=-EmQwFwMBuby3OI9HwqMIwuJzd2CGbWbOqmwrR25
|
|
|
18
18
|
orionis/console/commands/version.py,sha256=u2f7SetqEX__ufG6c37Ga-CylT4FGvy6wgld6RPBZGc,3589
|
|
19
19
|
orionis/console/commands/workflow.py,sha256=NYOmjTSvm2o6AE4h9LSTZMFSYPQreNmEJtronyOxaYk,2451
|
|
20
20
|
orionis/console/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
|
-
orionis/console/contracts/base_command.py,sha256=
|
|
21
|
+
orionis/console/contracts/base_command.py,sha256=UlDN41Ts0ulxM-B2kgeKNr9_gNv_0LCth_pon1os-8U,7617
|
|
22
22
|
orionis/console/contracts/base_scheduler.py,sha256=RSxEW57MoMU3pXfliIrQw9WuMk95p-xHXi1yACp1qsU,7728
|
|
23
23
|
orionis/console/contracts/cli_request.py,sha256=qIV8ig8PG39LYp1acnUD8GYsNRSHncxIxGjO3B3YsUo,6755
|
|
24
24
|
orionis/console/contracts/command.py,sha256=BOfRGpLRMsRS_a58584uO-MPK1UZGkmefLbFDtbk8ME,2911
|
|
@@ -32,7 +32,7 @@ orionis/console/contracts/reactor.py,sha256=iT6ShoCutAWEeJzOf_PK7CGXi9TgrOD5tewH
|
|
|
32
32
|
orionis/console/contracts/schedule.py,sha256=N-AYUa1CJY7a4CV9L1EX_EUDtGlDJMg4y0aV9EDby1Q,16090
|
|
33
33
|
orionis/console/contracts/schedule_event_listener.py,sha256=h06qsBxuEMD3KLSyu0JXdUDHlQW19BX9lA09Qrh2QXg,3818
|
|
34
34
|
orionis/console/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
-
orionis/console/core/reactor.py,sha256=
|
|
35
|
+
orionis/console/core/reactor.py,sha256=6scyrKukt6BEcLBxIrfAKA8QYnvNTl2dXePw6IWGPUw,43831
|
|
36
36
|
orionis/console/dumper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
37
|
orionis/console/dumper/debug.py,sha256=p8uflSXeDJDrVM9mZY4JMYEus73Z6TsLnQQtgP0QUak,22427
|
|
38
38
|
orionis/console/dynamic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -103,7 +103,7 @@ orionis/failure/contracts/handler.py,sha256=AeJfkJfD3hTkOIYAtADq6GnQfq-qWgDfUc7b
|
|
|
103
103
|
orionis/failure/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
104
104
|
orionis/failure/entities/throwable.py,sha256=1zD-awcuAyEtlR-L7V7ZIfPSF4GpXkf-neL5sXul7dc,1240
|
|
105
105
|
orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
106
|
-
orionis/foundation/application.py,sha256=
|
|
106
|
+
orionis/foundation/application.py,sha256=5gIuC5CxSdXaIuya47d_fAx3VODRTdtd9yn46DkoM9M,90402
|
|
107
107
|
orionis/foundation/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
108
108
|
orionis/foundation/config/startup.py,sha256=btqvryeIf9lLNQ9fBff7bJMrfraEY8qrWi4y_5YAR0Q,9681
|
|
109
109
|
orionis/foundation/config/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -216,7 +216,7 @@ orionis/foundation/providers/scheduler_provider.py,sha256=IrPQJwvQVLRm5Qnz0Cxon4
|
|
|
216
216
|
orionis/foundation/providers/testing_provider.py,sha256=eI1p2lUlxl25b5Z487O4nmqLE31CTDb4c3Q21xFadkE,1615
|
|
217
217
|
orionis/foundation/providers/workers_provider.py,sha256=GdHENYV_yGyqmHJHn0DCyWmWId5xWjD48e6Zq2PGCWY,1674
|
|
218
218
|
orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
219
|
-
orionis/metadata/framework.py,sha256=
|
|
219
|
+
orionis/metadata/framework.py,sha256=61h0HSRONEMs2j2UbfPMMmDgNiUQj4Ja69HFKij8m5Y,4109
|
|
220
220
|
orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
|
|
221
221
|
orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
222
222
|
orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -370,7 +370,7 @@ orionis/test/contracts/render.py,sha256=wpDQzUtT0r8KFZ7zPcxWHXQ1EVNKxzA_rZ6ZKUcZ
|
|
|
370
370
|
orionis/test/contracts/test_result.py,sha256=SNXJ2UerkweYn7uCT0i0HmMGP0XBrL_9KJs-0ZvIYU4,4002
|
|
371
371
|
orionis/test/contracts/unit_test.py,sha256=EyidHoOPJItwgkBWGYY1TymbNklyn2EUXnghVvW4htc,4652
|
|
372
372
|
orionis/test/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
373
|
-
orionis/test/core/unit_test.py,sha256=
|
|
373
|
+
orionis/test/core/unit_test.py,sha256=Xe5110bWZcnHfo3LmGKfvLQobX37rjCZgRiTS08QL2I,71655
|
|
374
374
|
orionis/test/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
375
375
|
orionis/test/entities/result.py,sha256=eZ6UIqGmFW8FZ9x8PB_MZbLAc-SAuUyi4FUcMYIZzGo,4777
|
|
376
376
|
orionis/test/enums/__init__.py,sha256=M3imAgMvKFTKg55FbtVoY3zxj7QRY9AfaUWxiSZVvn4,66
|
|
@@ -403,8 +403,8 @@ orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnI
|
|
|
403
403
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
404
404
|
orionis/test/view/render.py,sha256=R55ykeRs0wDKcdTf4O1YZ8GDHTFmJ0IK6VQkbJkYUvo,5571
|
|
405
405
|
orionis/test/view/report.stub,sha256=QLqqCdRoENr3ECiritRB3DO_MOjRQvgBh5jxZ3Hs1r0,28189
|
|
406
|
-
orionis-0.
|
|
407
|
-
orionis-0.
|
|
408
|
-
orionis-0.
|
|
409
|
-
orionis-0.
|
|
410
|
-
orionis-0.
|
|
406
|
+
orionis-0.619.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
|
|
407
|
+
orionis-0.619.0.dist-info/METADATA,sha256=tCQmpJ_jyBbcIBktkP73KfZSrukZhR9WepYwza5fDfw,4801
|
|
408
|
+
orionis-0.619.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
409
|
+
orionis-0.619.0.dist-info/top_level.txt,sha256=lyXi6jArpqJ-0zzNqd_uwsH-z9TCEBVBL-pC3Ekv7hU,8
|
|
410
|
+
orionis-0.619.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|