orionis 0.475.0__py3-none-any.whl → 0.477.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/contracts/reactor.py +74 -21
- orionis/console/core/reactor.py +213 -77
- orionis/console/enums/__init__.py +0 -0
- orionis/console/enums/command.py +43 -0
- orionis/console/enums/task.py +42 -0
- orionis/console/tasks/schedule.py +77 -8
- orionis/container/contracts/container.py +30 -1
- orionis/foundation/application.py +3 -1
- orionis/foundation/providers/performance_counter_provider.py +64 -0
- orionis/metadata/framework.py +1 -1
- orionis/support/facades/performance_counter.py +21 -0
- orionis/support/performance/__init__.py +0 -0
- orionis/support/performance/contracts/__init__.py +0 -0
- orionis/support/performance/contracts/counter.py +40 -0
- orionis/support/performance/counter.py +87 -0
- {orionis-0.475.0.dist-info → orionis-0.477.0.dist-info}/METADATA +1 -1
- {orionis-0.475.0.dist-info → orionis-0.477.0.dist-info}/RECORD +21 -12
- {orionis-0.475.0.dist-info → orionis-0.477.0.dist-info}/WHEEL +0 -0
- {orionis-0.475.0.dist-info → orionis-0.477.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.475.0.dist-info → orionis-0.477.0.dist-info}/top_level.txt +0 -0
- {orionis-0.475.0.dist-info → orionis-0.477.0.dist-info}/zip-safe +0 -0
|
@@ -1,57 +1,110 @@
|
|
|
1
1
|
from abc import ABC, abstractmethod
|
|
2
|
-
from typing import List, Optional
|
|
2
|
+
from typing import Any, List, Optional
|
|
3
3
|
|
|
4
4
|
class IReactor(ABC):
|
|
5
5
|
|
|
6
|
+
@abstractmethod
|
|
7
|
+
def info(self) -> List[dict]:
|
|
8
|
+
"""
|
|
9
|
+
Retrieves a list of all registered commands with their metadata.
|
|
10
|
+
|
|
11
|
+
This method returns a list of dictionaries, each containing information about
|
|
12
|
+
a registered command, including its signature, description, and whether it has
|
|
13
|
+
timestamps enabled. This is useful for introspection and displaying available
|
|
14
|
+
commands to the user.
|
|
15
|
+
|
|
16
|
+
Returns
|
|
17
|
+
-------
|
|
18
|
+
List[dict]
|
|
19
|
+
A list of dictionaries representing the registered commands, where each dictionary
|
|
20
|
+
contains the command's signature, description, and timestamps status.
|
|
21
|
+
"""
|
|
22
|
+
pass
|
|
23
|
+
|
|
6
24
|
@abstractmethod
|
|
7
25
|
def call(
|
|
8
26
|
self,
|
|
9
27
|
signature: str,
|
|
10
28
|
args: Optional[List[str]] = None
|
|
11
|
-
):
|
|
29
|
+
) -> Optional[Any]:
|
|
12
30
|
"""
|
|
13
|
-
Executes a command by its signature
|
|
31
|
+
Executes a registered command synchronously by its signature, optionally passing command-line arguments.
|
|
14
32
|
|
|
15
|
-
This method retrieves a
|
|
16
|
-
arguments
|
|
17
|
-
|
|
33
|
+
This method retrieves a command from the internal registry using its unique signature,
|
|
34
|
+
validates and parses any provided arguments using the command's argument parser,
|
|
35
|
+
and then executes the command's `handle` method synchronously. It manages execution timing,
|
|
36
|
+
logging, and error handling, and returns any output produced by the command.
|
|
18
37
|
|
|
19
38
|
Parameters
|
|
20
39
|
----------
|
|
21
40
|
signature : str
|
|
22
41
|
The unique signature identifier of the command to execute.
|
|
23
42
|
args : Optional[List[str]], default None
|
|
24
|
-
|
|
43
|
+
List of command-line arguments to pass to the command. If None, no arguments are provided.
|
|
25
44
|
|
|
26
45
|
Returns
|
|
27
46
|
-------
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
47
|
+
Optional[Any]
|
|
48
|
+
The output produced by the command's `handle` method if execution is successful.
|
|
49
|
+
Returns None if the command does not produce a result or if an error occurs.
|
|
31
50
|
|
|
32
51
|
Raises
|
|
33
52
|
------
|
|
34
|
-
|
|
53
|
+
CLIOrionisValueError
|
|
35
54
|
If the command with the specified signature is not found in the registry.
|
|
36
55
|
SystemExit
|
|
37
|
-
If argument parsing fails due to invalid arguments provided.
|
|
56
|
+
If argument parsing fails due to invalid arguments provided (raised by argparse).
|
|
57
|
+
Exception
|
|
58
|
+
Propagates any exception raised during command execution after logging and error output.
|
|
59
|
+
|
|
60
|
+
Notes
|
|
61
|
+
-----
|
|
62
|
+
- Logs execution start, completion, and errors with timestamps if enabled.
|
|
63
|
+
- Handles argument parsing and injects parsed arguments into the command instance.
|
|
64
|
+
- All exceptions are logged and displayed in the console.
|
|
38
65
|
"""
|
|
39
66
|
pass
|
|
40
67
|
|
|
41
68
|
@abstractmethod
|
|
42
|
-
def
|
|
69
|
+
async def callAsync(
|
|
70
|
+
self,
|
|
71
|
+
signature: str,
|
|
72
|
+
args: Optional[List[str]] = None
|
|
73
|
+
) -> Optional[Any]:
|
|
43
74
|
"""
|
|
44
|
-
|
|
75
|
+
Executes a registered command asynchronously by its signature, optionally passing command-line arguments.
|
|
45
76
|
|
|
46
|
-
This method
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
77
|
+
This method locates a command in the internal registry using its unique signature,
|
|
78
|
+
validates and parses any provided arguments using the command's argument parser,
|
|
79
|
+
and then executes the command's `handle` method asynchronously. It manages execution timing,
|
|
80
|
+
logging, and error handling, and returns any output produced by the command.
|
|
81
|
+
|
|
82
|
+
Parameters
|
|
83
|
+
----------
|
|
84
|
+
signature : str
|
|
85
|
+
The unique signature identifier of the command to execute.
|
|
86
|
+
args : Optional[List[str]], default None
|
|
87
|
+
List of command-line arguments to pass to the command. If None, no arguments are provided.
|
|
50
88
|
|
|
51
89
|
Returns
|
|
52
90
|
-------
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
91
|
+
Optional[Any]
|
|
92
|
+
The output produced by the command's `handle` method if execution is successful.
|
|
93
|
+
Returns None if the command does not produce a result or if an error occurs.
|
|
94
|
+
|
|
95
|
+
Raises
|
|
96
|
+
------
|
|
97
|
+
CLIOrionisValueError
|
|
98
|
+
If the command with the specified signature is not found in the registry.
|
|
99
|
+
SystemExit
|
|
100
|
+
If argument parsing fails due to invalid arguments provided (raised by argparse).
|
|
101
|
+
Exception
|
|
102
|
+
Propagates any exception raised during command execution after logging and error output.
|
|
103
|
+
|
|
104
|
+
Notes
|
|
105
|
+
-----
|
|
106
|
+
- Logs execution start, completion, and errors with timestamps if enabled.
|
|
107
|
+
- Handles argument parsing and injects parsed arguments into the command instance.
|
|
108
|
+
- All exceptions are logged and displayed in the console.
|
|
56
109
|
"""
|
|
57
110
|
pass
|
orionis/console/core/reactor.py
CHANGED
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import argparse
|
|
2
2
|
import os
|
|
3
3
|
import re
|
|
4
|
-
import time
|
|
5
4
|
from pathlib import Path
|
|
6
|
-
from typing import List, Optional
|
|
5
|
+
from typing import Any, List, Optional
|
|
7
6
|
from orionis.app import Orionis
|
|
8
7
|
from orionis.console.args.argument import CLIArgument
|
|
9
8
|
from orionis.console.base.command import BaseCommand
|
|
10
9
|
from orionis.console.base.contracts.command import IBaseCommand
|
|
11
10
|
from orionis.console.contracts.reactor import IReactor
|
|
11
|
+
from orionis.console.enums.command import Command
|
|
12
|
+
from orionis.console.exceptions import CLIOrionisValueError
|
|
12
13
|
from orionis.console.output.contracts.console import IConsole
|
|
13
14
|
from orionis.console.output.contracts.executor import IExecutor
|
|
14
15
|
from orionis.foundation.contracts.application import IApplication
|
|
15
16
|
from orionis.services.introspection.modules.reflection import ReflectionModule
|
|
16
17
|
from orionis.services.log.contracts.log_service import ILogger
|
|
18
|
+
from orionis.support.performance.contracts.counter import IPerformanceCounter
|
|
17
19
|
|
|
18
20
|
class Reactor(IReactor):
|
|
19
21
|
|
|
@@ -60,7 +62,7 @@ class Reactor(IReactor):
|
|
|
60
62
|
self.__root: str = str(Path.cwd())
|
|
61
63
|
|
|
62
64
|
# Initialize the internal command registry as an empty dictionary
|
|
63
|
-
self.__commands: dict = {}
|
|
65
|
+
self.__commands: dict[str, Command] = {}
|
|
64
66
|
|
|
65
67
|
# Automatically discover and load command classes from the console commands directory
|
|
66
68
|
self.__loadCommands(str(self.__app.path('console_commands')), self.__root)
|
|
@@ -77,6 +79,9 @@ class Reactor(IReactor):
|
|
|
77
79
|
# Initialize the logger service for logging command execution details
|
|
78
80
|
self.__logger: ILogger = self.__app.make('x-orionis.services.log.log_service')
|
|
79
81
|
|
|
82
|
+
# Initialize the performance counter for measuring command execution time
|
|
83
|
+
self.__performance_counter: IPerformanceCounter = self.__app.make('x-orionis.support.performance.counter')
|
|
84
|
+
|
|
80
85
|
def __loadCoreCommands(self) -> None:
|
|
81
86
|
"""
|
|
82
87
|
Loads and registers core command classes provided by the Orionis framework.
|
|
@@ -127,13 +132,13 @@ class Reactor(IReactor):
|
|
|
127
132
|
args = self.__ensureArguments(obj)
|
|
128
133
|
|
|
129
134
|
# Register the command in the internal registry with all its metadata
|
|
130
|
-
self.__commands[signature] =
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
135
|
+
self.__commands[signature] = Command(
|
|
136
|
+
obj=obj,
|
|
137
|
+
timestamps=timestamp,
|
|
138
|
+
signature=signature,
|
|
139
|
+
description=description,
|
|
140
|
+
args=args
|
|
141
|
+
)
|
|
137
142
|
|
|
138
143
|
def __loadCommands(self, commands_path: str, root_path: str) -> None:
|
|
139
144
|
"""
|
|
@@ -208,13 +213,13 @@ class Reactor(IReactor):
|
|
|
208
213
|
args = self.__ensureArguments(obj)
|
|
209
214
|
|
|
210
215
|
# Add the command to the internal registry
|
|
211
|
-
self.__commands[signature] =
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
216
|
+
self.__commands[signature] = Command(
|
|
217
|
+
obj=obj,
|
|
218
|
+
timestamps=timestamp,
|
|
219
|
+
signature=signature,
|
|
220
|
+
description=description,
|
|
221
|
+
args=args
|
|
222
|
+
)
|
|
218
223
|
|
|
219
224
|
def __ensureTimestamps(self, obj: IBaseCommand) -> bool:
|
|
220
225
|
"""
|
|
@@ -403,6 +408,61 @@ class Reactor(IReactor):
|
|
|
403
408
|
# Return the configured ArgumentParser
|
|
404
409
|
return arg_parser
|
|
405
410
|
|
|
411
|
+
def __parseArgs(
|
|
412
|
+
self,
|
|
413
|
+
command: Command,
|
|
414
|
+
args: Optional[List[str]] = None
|
|
415
|
+
) -> dict:
|
|
416
|
+
"""
|
|
417
|
+
Parses command-line arguments for a given command using its internal ArgumentParser.
|
|
418
|
+
|
|
419
|
+
This method takes a command object and an optional list of command-line arguments,
|
|
420
|
+
and parses them into a dictionary of argument names and values. If the command
|
|
421
|
+
defines an ArgumentParser (i.e., expects arguments), the arguments are parsed
|
|
422
|
+
accordingly. If no arguments are expected or provided, an empty dictionary is returned.
|
|
423
|
+
|
|
424
|
+
Parameters
|
|
425
|
+
----------
|
|
426
|
+
command : Command
|
|
427
|
+
The command object containing the argument parser and metadata.
|
|
428
|
+
args : Optional[List[str]], default None
|
|
429
|
+
A list of command-line arguments to parse. If None, an empty list is used.
|
|
430
|
+
|
|
431
|
+
Returns
|
|
432
|
+
-------
|
|
433
|
+
dict
|
|
434
|
+
A dictionary containing the parsed argument names and their corresponding values.
|
|
435
|
+
Returns an empty dictionary if no arguments are expected or provided.
|
|
436
|
+
|
|
437
|
+
Raises
|
|
438
|
+
------
|
|
439
|
+
SystemExit
|
|
440
|
+
Raised by argparse if argument parsing fails or if help is requested.
|
|
441
|
+
"""
|
|
442
|
+
|
|
443
|
+
# Initialize parsed_args to None
|
|
444
|
+
parsed_args = None
|
|
445
|
+
|
|
446
|
+
# If the command expects arguments, parse them using its ArgumentParser
|
|
447
|
+
if command.args is not None and isinstance(command.args, argparse.ArgumentParser):
|
|
448
|
+
if args is None:
|
|
449
|
+
args = []
|
|
450
|
+
try:
|
|
451
|
+
# Parse the provided arguments using the command's ArgumentParser
|
|
452
|
+
parsed_args = command.args.parse_args(args)
|
|
453
|
+
except SystemExit:
|
|
454
|
+
# Allow argparse to handle help/error messages and exit
|
|
455
|
+
raise
|
|
456
|
+
|
|
457
|
+
# Convert the parsed arguments to a dictionary and return
|
|
458
|
+
if isinstance(parsed_args, argparse.Namespace):
|
|
459
|
+
return vars(parsed_args)
|
|
460
|
+
elif isinstance(parsed_args, dict):
|
|
461
|
+
return parsed_args
|
|
462
|
+
else:
|
|
463
|
+
# Return an empty dictionary if no arguments were parsed
|
|
464
|
+
return {}
|
|
465
|
+
|
|
406
466
|
def info(self) -> List[dict]:
|
|
407
467
|
"""
|
|
408
468
|
Retrieves a list of all registered commands with their metadata.
|
|
@@ -426,8 +486,8 @@ class Reactor(IReactor):
|
|
|
426
486
|
for command in self.__commands.values():
|
|
427
487
|
|
|
428
488
|
# Extract command metadata
|
|
429
|
-
signature:str = command.
|
|
430
|
-
description:str = command.
|
|
489
|
+
signature:str = command.signature
|
|
490
|
+
description:str = command.description
|
|
431
491
|
|
|
432
492
|
# Skip internal commands (those with double underscores)
|
|
433
493
|
if signature.startswith('__') and signature.endswith('__'):
|
|
@@ -446,103 +506,179 @@ class Reactor(IReactor):
|
|
|
446
506
|
self,
|
|
447
507
|
signature: str,
|
|
448
508
|
args: Optional[List[str]] = None
|
|
449
|
-
):
|
|
509
|
+
) -> Optional[Any]:
|
|
450
510
|
"""
|
|
451
|
-
Executes a command by its signature
|
|
511
|
+
Executes a registered command synchronously by its signature, optionally passing command-line arguments.
|
|
452
512
|
|
|
453
|
-
This method retrieves a
|
|
454
|
-
arguments
|
|
455
|
-
|
|
513
|
+
This method retrieves a command from the internal registry using its unique signature,
|
|
514
|
+
validates and parses any provided arguments using the command's argument parser,
|
|
515
|
+
and then executes the command's `handle` method synchronously. It manages execution timing,
|
|
516
|
+
logging, and error handling, and returns any output produced by the command.
|
|
456
517
|
|
|
457
518
|
Parameters
|
|
458
519
|
----------
|
|
459
520
|
signature : str
|
|
460
521
|
The unique signature identifier of the command to execute.
|
|
461
522
|
args : Optional[List[str]], default None
|
|
462
|
-
|
|
523
|
+
List of command-line arguments to pass to the command. If None, no arguments are provided.
|
|
463
524
|
|
|
464
525
|
Returns
|
|
465
526
|
-------
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
527
|
+
Optional[Any]
|
|
528
|
+
The output produced by the command's `handle` method if execution is successful.
|
|
529
|
+
Returns None if the command does not produce a result or if an error occurs.
|
|
469
530
|
|
|
470
531
|
Raises
|
|
471
532
|
------
|
|
472
|
-
|
|
533
|
+
CLIOrionisValueError
|
|
473
534
|
If the command with the specified signature is not found in the registry.
|
|
474
535
|
SystemExit
|
|
475
|
-
If argument parsing fails due to invalid arguments provided.
|
|
536
|
+
If argument parsing fails due to invalid arguments provided (raised by argparse).
|
|
537
|
+
Exception
|
|
538
|
+
Propagates any exception raised during command execution after logging and error output.
|
|
539
|
+
|
|
540
|
+
Notes
|
|
541
|
+
-----
|
|
542
|
+
- Logs execution start, completion, and errors with timestamps if enabled.
|
|
543
|
+
- Handles argument parsing and injects parsed arguments into the command instance.
|
|
544
|
+
- All exceptions are logged and displayed in the console.
|
|
476
545
|
"""
|
|
477
546
|
|
|
478
|
-
# Retrieve the command from the registry
|
|
479
|
-
command:
|
|
547
|
+
# Retrieve the command from the registry by its signature
|
|
548
|
+
command: Command = self.__commands.get(signature)
|
|
480
549
|
if command is None:
|
|
481
|
-
raise
|
|
550
|
+
raise CLIOrionisValueError(f"Command '{signature}' not found.")
|
|
482
551
|
|
|
483
|
-
# Start execution timer
|
|
484
|
-
|
|
552
|
+
# Start execution timer for performance measurement
|
|
553
|
+
self.__performance_counter.start()
|
|
485
554
|
|
|
486
|
-
#
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
timestamps: bool = command.get("timestamps")
|
|
555
|
+
# Log the command execution start with RUNNING state if timestamps are enabled
|
|
556
|
+
if command.timestamps:
|
|
557
|
+
self.__executer.running(program=signature)
|
|
490
558
|
|
|
491
|
-
|
|
492
|
-
|
|
559
|
+
try:
|
|
560
|
+
# Instantiate the command class using the application container
|
|
561
|
+
command_instance: IBaseCommand = self.__app.make(command.obj)
|
|
493
562
|
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
if args is None:
|
|
497
|
-
args = []
|
|
498
|
-
try:
|
|
499
|
-
# Parse the provided arguments using the command's ArgumentParser
|
|
500
|
-
parsed_args = arg_parser.parse_args(args)
|
|
501
|
-
except SystemExit:
|
|
502
|
-
# Re-raise SystemExit to allow argparse to handle help/error messages
|
|
503
|
-
raise
|
|
563
|
+
# Inject parsed arguments into the command instance
|
|
564
|
+
command_instance._args = self.__parseArgs(command, args)
|
|
504
565
|
|
|
505
|
-
|
|
506
|
-
|
|
566
|
+
# Execute the command's handle method and capture its output
|
|
567
|
+
output = self.__app.call(command_instance, 'handle')
|
|
568
|
+
|
|
569
|
+
# Calculate elapsed time and log completion with DONE state if command.timestamps are enabled
|
|
570
|
+
elapsed_time = round(self.__performance_counter.stop(), 2)
|
|
571
|
+
if command.timestamps:
|
|
572
|
+
self.__executer.done(program=signature, time=f"{elapsed_time}s")
|
|
573
|
+
|
|
574
|
+
# Log successful execution in the logger service
|
|
575
|
+
self.__logger.info(f"Command '{signature}' executed successfully in ({elapsed_time}) seconds.")
|
|
576
|
+
|
|
577
|
+
# Return the output produced by the command, if any
|
|
578
|
+
return output
|
|
579
|
+
|
|
580
|
+
except Exception as e:
|
|
581
|
+
# Display the error message in the console (without timestamp)
|
|
582
|
+
self.__console.error(f"An error occurred while executing command '{signature}': {e}", timestamp=False)
|
|
583
|
+
|
|
584
|
+
# Log the error in the logger service
|
|
585
|
+
self.__logger.error(f"Command '{signature}' execution failed: {e}")
|
|
586
|
+
|
|
587
|
+
# Calculate elapsed time and log failure with ERROR state if command.timestamps are enabled
|
|
588
|
+
elapsed_time = round(self.__performance_counter.stop(), 2)
|
|
589
|
+
if command.timestamps:
|
|
590
|
+
self.__executer.fail(program=signature, time=f"{elapsed_time}s")
|
|
591
|
+
|
|
592
|
+
# Propagate the exception after logging
|
|
593
|
+
raise
|
|
594
|
+
|
|
595
|
+
async def callAsync(
|
|
596
|
+
self,
|
|
597
|
+
signature: str,
|
|
598
|
+
args: Optional[List[str]] = None
|
|
599
|
+
) -> Optional[Any]:
|
|
600
|
+
"""
|
|
601
|
+
Executes a registered command asynchronously by its signature, optionally passing command-line arguments.
|
|
602
|
+
|
|
603
|
+
This method locates a command in the internal registry using its unique signature,
|
|
604
|
+
validates and parses any provided arguments using the command's argument parser,
|
|
605
|
+
and then executes the command's `handle` method asynchronously. It manages execution timing,
|
|
606
|
+
logging, and error handling, and returns any output produced by the command.
|
|
607
|
+
|
|
608
|
+
Parameters
|
|
609
|
+
----------
|
|
610
|
+
signature : str
|
|
611
|
+
The unique signature identifier of the command to execute.
|
|
612
|
+
args : Optional[List[str]], default None
|
|
613
|
+
List of command-line arguments to pass to the command. If None, no arguments are provided.
|
|
614
|
+
|
|
615
|
+
Returns
|
|
616
|
+
-------
|
|
617
|
+
Optional[Any]
|
|
618
|
+
The output produced by the command's `handle` method if execution is successful.
|
|
619
|
+
Returns None if the command does not produce a result or if an error occurs.
|
|
620
|
+
|
|
621
|
+
Raises
|
|
622
|
+
------
|
|
623
|
+
CLIOrionisValueError
|
|
624
|
+
If the command with the specified signature is not found in the registry.
|
|
625
|
+
SystemExit
|
|
626
|
+
If argument parsing fails due to invalid arguments provided (raised by argparse).
|
|
627
|
+
Exception
|
|
628
|
+
Propagates any exception raised during command execution after logging and error output.
|
|
629
|
+
|
|
630
|
+
Notes
|
|
631
|
+
-----
|
|
632
|
+
- Logs execution start, completion, and errors with timestamps if enabled.
|
|
633
|
+
- Handles argument parsing and injects parsed arguments into the command instance.
|
|
634
|
+
- All exceptions are logged and displayed in the console.
|
|
635
|
+
"""
|
|
636
|
+
|
|
637
|
+
# Retrieve the command from the registry by its signature
|
|
638
|
+
command: Command = self.__commands.get(signature)
|
|
639
|
+
if command is None:
|
|
640
|
+
raise CLIOrionisValueError(f"Command '{signature}' not found.")
|
|
641
|
+
|
|
642
|
+
# Start execution timer for performance measurement
|
|
643
|
+
self.__performance_counter.start()
|
|
644
|
+
|
|
645
|
+
# Log the command execution start with RUNNING state if timestamps are enabled
|
|
646
|
+
if command.timestamps:
|
|
507
647
|
self.__executer.running(program=signature)
|
|
508
648
|
|
|
509
649
|
try:
|
|
650
|
+
# Instantiate the command class using the application container
|
|
651
|
+
command_instance: IBaseCommand = self.__app.make(command.obj)
|
|
510
652
|
|
|
511
|
-
#
|
|
512
|
-
command_instance
|
|
653
|
+
# Inject parsed arguments into the command instance
|
|
654
|
+
command_instance._args = self.__parseArgs(command, args)
|
|
513
655
|
|
|
514
|
-
#
|
|
515
|
-
|
|
516
|
-
command_instance._args = vars(parsed_args)
|
|
517
|
-
elif isinstance(parsed_args, dict):
|
|
518
|
-
command_instance._args = parsed_args
|
|
519
|
-
else:
|
|
520
|
-
command_instance._args = {}
|
|
656
|
+
# Execute the command's handle method asynchronously and capture its output
|
|
657
|
+
output = await self.__app.callAsync(command_instance, 'handle')
|
|
521
658
|
|
|
522
|
-
#
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
# Log the command execution completion with DONE state
|
|
526
|
-
elapsed_time = round(time.perf_counter() - start_time, 2)
|
|
527
|
-
if timestamps:
|
|
659
|
+
# Calculate elapsed time and log completion with DONE state if command.timestamps are enabled
|
|
660
|
+
elapsed_time = round(self.__performance_counter.stop(), 2)
|
|
661
|
+
if command.timestamps:
|
|
528
662
|
self.__executer.done(program=signature, time=f"{elapsed_time}s")
|
|
529
663
|
|
|
530
|
-
# Log the
|
|
664
|
+
# Log successful execution in the logger service
|
|
531
665
|
self.__logger.info(f"Command '{signature}' executed successfully in ({elapsed_time}) seconds.")
|
|
532
666
|
|
|
533
|
-
#
|
|
534
|
-
|
|
535
|
-
return output
|
|
667
|
+
# Return the output produced by the command, if any
|
|
668
|
+
return output
|
|
536
669
|
|
|
537
670
|
except Exception as e:
|
|
538
671
|
|
|
539
|
-
# Display the error message in the console
|
|
672
|
+
# Display the error message in the console (without timestamp)
|
|
540
673
|
self.__console.error(f"An error occurred while executing command '{signature}': {e}", timestamp=False)
|
|
541
674
|
|
|
542
675
|
# Log the error in the logger service
|
|
543
676
|
self.__logger.error(f"Command '{signature}' execution failed: {e}")
|
|
544
677
|
|
|
545
|
-
#
|
|
546
|
-
elapsed_time = round(
|
|
547
|
-
if timestamps:
|
|
548
|
-
self.__executer.fail(program=signature, time=f"{elapsed_time}s")
|
|
678
|
+
# Calculate elapsed time and log failure with ERROR state if command.timestamps are enabled
|
|
679
|
+
elapsed_time = round(self.__performance_counter.stop(), 2)
|
|
680
|
+
if command.timestamps:
|
|
681
|
+
self.__executer.fail(program=signature, time=f"{elapsed_time}s")
|
|
682
|
+
|
|
683
|
+
# Propagate the exception after logging
|
|
684
|
+
raise
|
|
File without changes
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import argparse
|
|
2
|
+
from dataclasses import dataclass
|
|
3
|
+
from typing import Type, Optional
|
|
4
|
+
from orionis.support.entities.base import BaseEntity
|
|
5
|
+
|
|
6
|
+
@dataclass(kw_only=True)
|
|
7
|
+
class Command(BaseEntity):
|
|
8
|
+
"""
|
|
9
|
+
Represents a console command and its associated metadata.
|
|
10
|
+
|
|
11
|
+
Parameters
|
|
12
|
+
----------
|
|
13
|
+
obj : Type
|
|
14
|
+
The type or class associated with the command.
|
|
15
|
+
timestamps : bool
|
|
16
|
+
Whether timestamps are enabled for this command.
|
|
17
|
+
signature : str
|
|
18
|
+
The signature string representing the command usage.
|
|
19
|
+
description : str
|
|
20
|
+
A brief description of what the command does.
|
|
21
|
+
args : Optional[argparse.ArgumentParser], optional
|
|
22
|
+
Optional argument parser for command-line arguments.
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
Command
|
|
27
|
+
An instance of the Command class containing metadata and configuration for a console command.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
# The type or class associated with the command
|
|
31
|
+
obj: Type
|
|
32
|
+
|
|
33
|
+
# Indicates if timestamps are enabled for this command
|
|
34
|
+
timestamps: bool
|
|
35
|
+
|
|
36
|
+
# The command usage signature
|
|
37
|
+
signature: str
|
|
38
|
+
|
|
39
|
+
# Description of the command's purpose
|
|
40
|
+
description: str
|
|
41
|
+
|
|
42
|
+
# Optional argument parser for command-line arguments
|
|
43
|
+
args: Optional[argparse.ArgumentParser] = None
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from dataclasses import dataclass
|
|
2
|
+
from typing import List, Optional
|
|
3
|
+
from orionis.support.entities.base import BaseEntity
|
|
4
|
+
|
|
5
|
+
@dataclass(kw_only=True)
|
|
6
|
+
class Task(BaseEntity):
|
|
7
|
+
"""
|
|
8
|
+
Represents a task entity containing metadata for execution and description.
|
|
9
|
+
|
|
10
|
+
Parameters
|
|
11
|
+
----------
|
|
12
|
+
signature : str
|
|
13
|
+
The unique identifier or signature of the task.
|
|
14
|
+
args : Optional[List[str]], optional
|
|
15
|
+
List of arguments required by the task, by default None.
|
|
16
|
+
purpose : str, optional
|
|
17
|
+
Brief description of the task's purpose, by default None.
|
|
18
|
+
trigger : str, optional
|
|
19
|
+
Event or condition that triggers the task, by default None.
|
|
20
|
+
details : str, optional
|
|
21
|
+
Additional details or information about the task, by default None.
|
|
22
|
+
|
|
23
|
+
Returns
|
|
24
|
+
-------
|
|
25
|
+
Task
|
|
26
|
+
An instance of the Task class with the specified metadata.
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
# Unique identifier for the task
|
|
30
|
+
signature: str
|
|
31
|
+
|
|
32
|
+
# List of arguments required by the task (optional)
|
|
33
|
+
args: Optional[List[str]] = None
|
|
34
|
+
|
|
35
|
+
# Brief description of the task's purpose (optional)
|
|
36
|
+
purpose: str = None
|
|
37
|
+
|
|
38
|
+
# Event or condition that triggers the task (optional)
|
|
39
|
+
trigger: str = None
|
|
40
|
+
|
|
41
|
+
# Additional details or information about the task (optional)
|
|
42
|
+
details: str = None
|
|
@@ -9,7 +9,9 @@ from apscheduler.triggers.date import DateTrigger
|
|
|
9
9
|
from apscheduler.triggers.interval import IntervalTrigger
|
|
10
10
|
from orionis.app import Orionis
|
|
11
11
|
from orionis.console.contracts.reactor import IReactor
|
|
12
|
+
from orionis.console.enums.task import Task
|
|
12
13
|
from orionis.console.exceptions import CLIOrionisRuntimeError
|
|
14
|
+
from orionis.console.exceptions.cli_orionis_value_error import CLIOrionisValueError
|
|
13
15
|
from orionis.services.log.contracts.log_service import ILogger
|
|
14
16
|
|
|
15
17
|
class Scheduler():
|
|
@@ -316,14 +318,13 @@ class Scheduler():
|
|
|
316
318
|
)
|
|
317
319
|
|
|
318
320
|
# Register the job details internally.
|
|
319
|
-
self.__jobs[self.__command] =
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
}
|
|
321
|
+
self.__jobs[self.__command] = Task(
|
|
322
|
+
signature=self.__command,
|
|
323
|
+
args=self.__args,
|
|
324
|
+
purpose=self.__purpose,
|
|
325
|
+
trigger='once_at',
|
|
326
|
+
details=f"Date: {date.strftime('%Y-%m-%d %H:%M:%S')}, Timezone: {str(date.tzinfo) if date.tzinfo else 'UTC'}"
|
|
327
|
+
)
|
|
327
328
|
|
|
328
329
|
# Add the job to the scheduler.
|
|
329
330
|
self.__scheduler.add_job(
|
|
@@ -359,6 +360,74 @@ class Scheduler():
|
|
|
359
360
|
# Wrap and raise any other exceptions as CLIOrionisRuntimeError.
|
|
360
361
|
raise CLIOrionisRuntimeError(f"Error scheduling the job: {str(e)}")
|
|
361
362
|
|
|
363
|
+
def everySeconds(
|
|
364
|
+
self,
|
|
365
|
+
seconds: int
|
|
366
|
+
) -> 'Scheduler':
|
|
367
|
+
"""
|
|
368
|
+
Schedule a command to run at regular intervals in seconds.
|
|
369
|
+
|
|
370
|
+
This method sets the interval for the currently registered command to execute
|
|
371
|
+
every specified number of seconds. The job is registered internally and added
|
|
372
|
+
to the scheduler instance.
|
|
373
|
+
|
|
374
|
+
Parameters
|
|
375
|
+
----------
|
|
376
|
+
seconds : int
|
|
377
|
+
The interval in seconds at which the command should be executed. Must be a positive integer.
|
|
378
|
+
|
|
379
|
+
Returns
|
|
380
|
+
-------
|
|
381
|
+
Scheduler
|
|
382
|
+
Returns the current instance of the Scheduler to allow method chaining.
|
|
383
|
+
|
|
384
|
+
Raises
|
|
385
|
+
------
|
|
386
|
+
ValueError
|
|
387
|
+
If the provided seconds is not a positive integer.
|
|
388
|
+
"""
|
|
389
|
+
|
|
390
|
+
try:
|
|
391
|
+
|
|
392
|
+
# Validate that the seconds parameter is a positive integer.
|
|
393
|
+
if not isinstance(seconds, int) or seconds <= 0:
|
|
394
|
+
raise CLIOrionisValueError("The interval must be a positive integer.")
|
|
395
|
+
|
|
396
|
+
# Store the interval in the jobs dictionary.
|
|
397
|
+
self.__jobs[self.__command] = Task(
|
|
398
|
+
signature=self.__command,
|
|
399
|
+
args=self.__args,
|
|
400
|
+
purpose=self.__purpose,
|
|
401
|
+
trigger='every_seconds',
|
|
402
|
+
details=f"Interval: {seconds} seconds"
|
|
403
|
+
)
|
|
404
|
+
|
|
405
|
+
# Add the job to the scheduler with an interval trigger.
|
|
406
|
+
self.__scheduler.add_job(
|
|
407
|
+
func=lambda command=self.__command, args=list(self.__args): self.__reactor.call(
|
|
408
|
+
command,
|
|
409
|
+
args
|
|
410
|
+
),
|
|
411
|
+
trigger=IntervalTrigger(
|
|
412
|
+
seconds=seconds
|
|
413
|
+
),
|
|
414
|
+
id=self.__command,
|
|
415
|
+
name=self.__command,
|
|
416
|
+
replace_existing=True
|
|
417
|
+
)
|
|
418
|
+
|
|
419
|
+
# Return self to support method chaining.
|
|
420
|
+
return self
|
|
421
|
+
|
|
422
|
+
except Exception as e:
|
|
423
|
+
|
|
424
|
+
# Reraise known CLIOrionisValueError exceptions.
|
|
425
|
+
if isinstance(e, CLIOrionisValueError):
|
|
426
|
+
raise e
|
|
427
|
+
|
|
428
|
+
# Wrap and raise any other exceptions as CLIOrionisRuntimeError.
|
|
429
|
+
raise CLIOrionisRuntimeError(f"Error scheduling the job: {str(e)}")
|
|
430
|
+
|
|
362
431
|
async def start(self) -> None:
|
|
363
432
|
"""
|
|
364
433
|
Start the AsyncIO scheduler instance and keep it running.
|
|
@@ -419,4 +419,33 @@ class IContainer(ABC):
|
|
|
419
419
|
Any
|
|
420
420
|
The result of the method call.
|
|
421
421
|
"""
|
|
422
|
-
pass
|
|
422
|
+
pass
|
|
423
|
+
|
|
424
|
+
@abstractmethod
|
|
425
|
+
async def callAsync(
|
|
426
|
+
self,
|
|
427
|
+
instance: Any,
|
|
428
|
+
method_name: str,
|
|
429
|
+
*args,
|
|
430
|
+
**kwargs
|
|
431
|
+
) -> Any:
|
|
432
|
+
"""
|
|
433
|
+
Async version of call for when you're in an async context and need to await the result.
|
|
434
|
+
|
|
435
|
+
Parameters
|
|
436
|
+
----------
|
|
437
|
+
instance : Any
|
|
438
|
+
The instance on which to call the method.
|
|
439
|
+
method_name : str
|
|
440
|
+
The name of the method to call.
|
|
441
|
+
*args : tuple
|
|
442
|
+
Positional arguments to pass to the method.
|
|
443
|
+
**kwargs : dict
|
|
444
|
+
Keyword arguments to pass to the method.
|
|
445
|
+
|
|
446
|
+
Returns
|
|
447
|
+
-------
|
|
448
|
+
Any
|
|
449
|
+
The result of the method call, properly awaited if async.
|
|
450
|
+
"""
|
|
451
|
+
pass
|
|
@@ -180,6 +180,7 @@ class Application(Container, IApplication):
|
|
|
180
180
|
from orionis.foundation.providers.inspirational_provider import InspirationalProvider
|
|
181
181
|
from orionis.foundation.providers.executor_provider import ConsoleExecuteProvider
|
|
182
182
|
from orionis.foundation.providers.reactor_provider import ReactorProvider
|
|
183
|
+
from orionis.foundation.providers.performance_counter_provider import PerformanceCounterProvider
|
|
183
184
|
|
|
184
185
|
# Core framework providers
|
|
185
186
|
core_providers = [
|
|
@@ -191,7 +192,8 @@ class Application(Container, IApplication):
|
|
|
191
192
|
TestingProvider,
|
|
192
193
|
InspirationalProvider,
|
|
193
194
|
ConsoleExecuteProvider,
|
|
194
|
-
ReactorProvider
|
|
195
|
+
ReactorProvider,
|
|
196
|
+
PerformanceCounterProvider
|
|
195
197
|
]
|
|
196
198
|
|
|
197
199
|
# Register each core provider
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
from orionis.container.providers.service_provider import ServiceProvider
|
|
2
|
+
from orionis.support.performance.contracts.counter import IPerformanceCounter
|
|
3
|
+
from orionis.support.performance.counter import PerformanceCounter
|
|
4
|
+
|
|
5
|
+
class PerformanceCounterProvider(ServiceProvider):
|
|
6
|
+
|
|
7
|
+
def register(self) -> None:
|
|
8
|
+
"""
|
|
9
|
+
Registers the performance counter service as a transient dependency in the application container.
|
|
10
|
+
|
|
11
|
+
This method binds the `IPerformanceCounter` interface contract to the `PerformanceCounter`
|
|
12
|
+
concrete implementation within the application's dependency injection container. The binding
|
|
13
|
+
is configured with a transient lifetime, ensuring that each resolution of the service yields
|
|
14
|
+
a new instance of `PerformanceCounter`. This approach is suitable for scenarios requiring
|
|
15
|
+
independent timing or measurement operations across different parts of the application.
|
|
16
|
+
|
|
17
|
+
Additionally, an alias `"x-orionis.support.performance.counter"` is assigned to this binding,
|
|
18
|
+
allowing for alternative resolution or referencing of the service.
|
|
19
|
+
|
|
20
|
+
Parameters
|
|
21
|
+
----------
|
|
22
|
+
None
|
|
23
|
+
|
|
24
|
+
Returns
|
|
25
|
+
-------
|
|
26
|
+
None
|
|
27
|
+
This method performs service registration as a side effect and does not return any value.
|
|
28
|
+
|
|
29
|
+
Notes
|
|
30
|
+
-----
|
|
31
|
+
- The transient lifetime ensures isolation between different consumers of the service.
|
|
32
|
+
- The alias facilitates flexible service resolution by name.
|
|
33
|
+
"""
|
|
34
|
+
|
|
35
|
+
# Register the IPerformanceCounter interface to the PerformanceCounter implementation
|
|
36
|
+
# with a transient lifetime and assign an alias for alternative resolution.
|
|
37
|
+
self.app.transient(IPerformanceCounter, PerformanceCounter, alias="x-orionis.support.performance.counter")
|
|
38
|
+
|
|
39
|
+
def boot(self) -> None:
|
|
40
|
+
"""
|
|
41
|
+
Performs initialization and configuration tasks for the performance counter provider during the application's bootstrapping phase.
|
|
42
|
+
|
|
43
|
+
This method is automatically invoked when the provider is loaded by the application. It is intended for setting up or registering
|
|
44
|
+
any performance counters or related resources required by the application. By default, this implementation does not perform any
|
|
45
|
+
actions, but it can be extended in subclasses to include custom initialization logic as needed.
|
|
46
|
+
|
|
47
|
+
Parameters
|
|
48
|
+
----------
|
|
49
|
+
None
|
|
50
|
+
|
|
51
|
+
Returns
|
|
52
|
+
-------
|
|
53
|
+
None
|
|
54
|
+
This method does not return any value. It executes initialization logic as a side effect.
|
|
55
|
+
|
|
56
|
+
Notes
|
|
57
|
+
-----
|
|
58
|
+
- Override this method in subclasses to implement custom bootstrapping behavior for performance counters.
|
|
59
|
+
- This method is part of the provider lifecycle and is called after service registration.
|
|
60
|
+
"""
|
|
61
|
+
|
|
62
|
+
# No initialization logic is required by default.
|
|
63
|
+
# Override this method in subclasses to perform custom setup.
|
|
64
|
+
pass
|
orionis/metadata/framework.py
CHANGED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
from orionis.container.facades.facade import Facade
|
|
2
|
+
|
|
3
|
+
class PerformanceCounter(Facade):
|
|
4
|
+
|
|
5
|
+
@classmethod
|
|
6
|
+
def getFacadeAccessor(cls):
|
|
7
|
+
"""
|
|
8
|
+
Get the registered name of the component in the service container.
|
|
9
|
+
|
|
10
|
+
This method provides the binding key that the service container uses to
|
|
11
|
+
resolve the workers service implementation. It serves as the bridge between
|
|
12
|
+
the facade and the underlying service registration.
|
|
13
|
+
|
|
14
|
+
Returns
|
|
15
|
+
-------
|
|
16
|
+
str
|
|
17
|
+
The service container binding key 'x-orionis.support.performance.counter'
|
|
18
|
+
that identifies the workers service implementation.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
return "x-orionis.support.performance.counter"
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
from abc import ABC, abstractmethod
|
|
2
|
+
|
|
3
|
+
class IPerformanceCounter(ABC):
|
|
4
|
+
"""
|
|
5
|
+
A class for measuring the elapsed time between two points in code execution.
|
|
6
|
+
|
|
7
|
+
This class provides methods to start and stop a high-resolution performance counter,
|
|
8
|
+
allowing users to measure the duration of specific code segments with precision.
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
@abstractmethod
|
|
12
|
+
def start(self) -> float:
|
|
13
|
+
"""
|
|
14
|
+
Start the performance counter.
|
|
15
|
+
|
|
16
|
+
Records the current high-resolution time as the start time using
|
|
17
|
+
`time.perf_counter()`. This marks the beginning of the interval to be measured.
|
|
18
|
+
|
|
19
|
+
Returns
|
|
20
|
+
-------
|
|
21
|
+
float
|
|
22
|
+
The timestamp (in fractional seconds) at which the counter was started.
|
|
23
|
+
"""
|
|
24
|
+
pass
|
|
25
|
+
|
|
26
|
+
@abstractmethod
|
|
27
|
+
def stop(self) -> float:
|
|
28
|
+
"""
|
|
29
|
+
Stop the performance counter and calculate the elapsed time.
|
|
30
|
+
|
|
31
|
+
Records the current high-resolution time as the end time and computes
|
|
32
|
+
the elapsed time since `start()` was called. The elapsed time is the
|
|
33
|
+
difference between the end and start timestamps.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
float
|
|
38
|
+
The elapsed time in seconds (as a float) between when `start()` and `stop()` were called.
|
|
39
|
+
"""
|
|
40
|
+
pass
|
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
import time
|
|
2
|
+
from orionis.support.performance.contracts.counter import IPerformanceCounter
|
|
3
|
+
|
|
4
|
+
class PerformanceCounter(IPerformanceCounter):
|
|
5
|
+
"""
|
|
6
|
+
A class for measuring the elapsed time between two points in code execution.
|
|
7
|
+
|
|
8
|
+
This class provides methods to start and stop a high-resolution performance counter,
|
|
9
|
+
allowing users to measure the duration of specific code segments with precision.
|
|
10
|
+
|
|
11
|
+
Attributes
|
|
12
|
+
----------
|
|
13
|
+
__start_time : float or None
|
|
14
|
+
The timestamp when the counter was started.
|
|
15
|
+
__end_time : float or None
|
|
16
|
+
The timestamp when the counter was stopped.
|
|
17
|
+
|
|
18
|
+
Methods
|
|
19
|
+
-------
|
|
20
|
+
start()
|
|
21
|
+
Starts the performance counter.
|
|
22
|
+
stop()
|
|
23
|
+
Stops the performance counter and returns the elapsed time.
|
|
24
|
+
|
|
25
|
+
Notes
|
|
26
|
+
-----
|
|
27
|
+
The counter uses `time.perf_counter()` for high-resolution timing.
|
|
28
|
+
"""
|
|
29
|
+
|
|
30
|
+
def __init__(self):
|
|
31
|
+
"""
|
|
32
|
+
Initialize a new PerformanceCounter instance.
|
|
33
|
+
|
|
34
|
+
This constructor sets the internal start and end time attributes to None,
|
|
35
|
+
preparing the counter for use. The counter can then be started and stopped
|
|
36
|
+
to measure elapsed time between two points in code execution.
|
|
37
|
+
|
|
38
|
+
Attributes
|
|
39
|
+
----------
|
|
40
|
+
__start_time : float or None
|
|
41
|
+
The timestamp when the counter is started, or None if not started.
|
|
42
|
+
__end_time : float or None
|
|
43
|
+
The timestamp when the counter is stopped, or None if not stopped.
|
|
44
|
+
"""
|
|
45
|
+
|
|
46
|
+
# Time when the counter is started; initialized to None
|
|
47
|
+
self.__start_time = None
|
|
48
|
+
|
|
49
|
+
# Time when the counter is stopped; initialized to None
|
|
50
|
+
self.__end_time = None
|
|
51
|
+
|
|
52
|
+
def start(self) -> float:
|
|
53
|
+
"""
|
|
54
|
+
Start the performance counter.
|
|
55
|
+
|
|
56
|
+
Records the current high-resolution time as the start time using
|
|
57
|
+
`time.perf_counter()`. This marks the beginning of the interval to be measured.
|
|
58
|
+
|
|
59
|
+
Returns
|
|
60
|
+
-------
|
|
61
|
+
float
|
|
62
|
+
The timestamp (in fractional seconds) at which the counter was started.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
# Record the current time as the start time
|
|
66
|
+
self.__start_time = time.perf_counter()
|
|
67
|
+
return self.__start_time
|
|
68
|
+
|
|
69
|
+
def stop(self) -> float:
|
|
70
|
+
"""
|
|
71
|
+
Stop the performance counter and calculate the elapsed time.
|
|
72
|
+
|
|
73
|
+
Records the current high-resolution time as the end time and computes
|
|
74
|
+
the elapsed time since `start()` was called. The elapsed time is the
|
|
75
|
+
difference between the end and start timestamps.
|
|
76
|
+
|
|
77
|
+
Returns
|
|
78
|
+
-------
|
|
79
|
+
float
|
|
80
|
+
The elapsed time in seconds (as a float) between when `start()` and `stop()` were called.
|
|
81
|
+
"""
|
|
82
|
+
|
|
83
|
+
# Record the current time as the end time
|
|
84
|
+
self.__end_time = time.perf_counter()
|
|
85
|
+
|
|
86
|
+
# Calculate and return the elapsed time
|
|
87
|
+
return self.__end_time - self.__start_time
|
|
@@ -19,10 +19,10 @@ orionis/console/commands/version.py,sha256=SUuNDJ40f2uq69OQUmPQXJKaa9Bm_iVRDPmBd
|
|
|
19
19
|
orionis/console/commands/workflow.py,sha256=NYOmjTSvm2o6AE4h9LSTZMFSYPQreNmEJtronyOxaYk,2451
|
|
20
20
|
orionis/console/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
21
21
|
orionis/console/contracts/kernel.py,sha256=mh4LlhEYHh3FuGZZQ0GBhD6ZLa5YQvaNj2r01IIHI5Y,826
|
|
22
|
-
orionis/console/contracts/reactor.py,sha256=
|
|
22
|
+
orionis/console/contracts/reactor.py,sha256=Xeq7Zrw6WE5MV_XOQfiQEchAFbb6-0TjLpjWOxYW--g,4554
|
|
23
23
|
orionis/console/contracts/schedule.py,sha256=A7yYPjPmRizDHOR9k4qvY3NuRPrWBmNuQs6ENGXWtBs,70
|
|
24
24
|
orionis/console/core/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
25
|
-
orionis/console/core/reactor.py,sha256=
|
|
25
|
+
orionis/console/core/reactor.py,sha256=Hd7T-jNG_tzhpJXRztjDSKCtm7-3LOh5lcQ__cIchMk,30172
|
|
26
26
|
orionis/console/dumper/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
27
27
|
orionis/console/dumper/dump.py,sha256=CATERiQ6XuIrKQsDaWcVxzTtlAJI9qLJX44fQxEX8ws,22443
|
|
28
28
|
orionis/console/dumper/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -31,6 +31,9 @@ orionis/console/dynamic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG
|
|
|
31
31
|
orionis/console/dynamic/progress_bar.py,sha256=iK1kAf9vJIgk6BbdlGvlJkGc1m7Ck4euNqQpg5aarW8,2880
|
|
32
32
|
orionis/console/dynamic/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
33
33
|
orionis/console/dynamic/contracts/progress_bar.py,sha256=NYebL2h-vg2t2H6IhJjuC37gglRkpT-MW71wbJtpLNg,1784
|
|
34
|
+
orionis/console/enums/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
|
+
orionis/console/enums/command.py,sha256=lCfVp2vnDojJN2gjdVxE_XU3mRjZZgOIxPfBVQYo9w4,1278
|
|
36
|
+
orionis/console/enums/task.py,sha256=1oRR_VKfzsojCxxywYAMhpPvZQ8kSEEdXeXvCOfAXmg,1322
|
|
34
37
|
orionis/console/exceptions/__init__.py,sha256=0qlHNuHMVZO87M-rP8lThUUyljRM1jSFNikaxSCjSbw,366
|
|
35
38
|
orionis/console/exceptions/cli_exception.py,sha256=HsZ_vSeNiJWQ0gznVFNcIdhM0Bj_vkSRVBJs0wMjEKY,1141
|
|
36
39
|
orionis/console/exceptions/cli_orionis_value_error.py,sha256=RQP0HRwxDG8hxFOT1kUoZ1Ab1CZ1KLoSIl5yqlmgG4M,1147
|
|
@@ -45,14 +48,14 @@ orionis/console/output/contracts/executor.py,sha256=7l3kwnvv6GlH9EYk0v94YE1olex_
|
|
|
45
48
|
orionis/console/output/enums/__init__.py,sha256=LAaAxg-DpArCjf_jqZ0_9s3p8899gntDYkSU_ppTdC8,66
|
|
46
49
|
orionis/console/output/enums/styles.py,sha256=6a4oQCOBOKMh2ARdeq5GlIskJ3wjiylYmh66tUKKmpQ,4053
|
|
47
50
|
orionis/console/tasks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
48
|
-
orionis/console/tasks/schedule.py,sha256=
|
|
51
|
+
orionis/console/tasks/schedule.py,sha256=DFso4ia8G3me2H1tOX366dXhucIKd-LRH8c-kfJ8fhA,21395
|
|
49
52
|
orionis/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
50
53
|
orionis/container/container.py,sha256=p7kJ-hwnDattTWCArt0ypol4bW3M334hIZ2FAQhID-w,87570
|
|
51
54
|
orionis/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
52
55
|
orionis/container/context/manager.py,sha256=I08K_jKXSKmrq18Pv33qYyMKIlAovVOwIgmfiVm-J7c,2971
|
|
53
56
|
orionis/container/context/scope.py,sha256=p_oCzR7dDz-5ZAd16ab4vfLc3gBf34CaN0f4iR9D0bQ,1155
|
|
54
57
|
orionis/container/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
55
|
-
orionis/container/contracts/container.py,sha256=
|
|
58
|
+
orionis/container/contracts/container.py,sha256=l-wVi6KMLL4I55JSHnNqykiaZSZO9ea6BDSzCKsysak,14217
|
|
56
59
|
orionis/container/contracts/service_provider.py,sha256=TJtwFoPYvw3hvBSfIEO3-httq8iszaRQh1IjCKfDyVM,1016
|
|
57
60
|
orionis/container/entities/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
58
61
|
orionis/container/entities/binding.py,sha256=sY0ioHbRcjp9TSQjfrFHxkO3vRn_VOrbHK62_QEGe1U,3717
|
|
@@ -78,7 +81,7 @@ orionis/container/validators/is_subclass.py,sha256=4sBaGLoRs8nUhuWjlP0VJqyTwVHYq
|
|
|
78
81
|
orionis/container/validators/is_valid_alias.py,sha256=4uAYcq8xov7jZbXnpKpjNkxcZtlTNnL5RRctVPMwJes,1424
|
|
79
82
|
orionis/container/validators/lifetime.py,sha256=IQ43fDNrxYHMlZH2zlYDJnlkLO_eS4U7Fs3UJgQBidI,1844
|
|
80
83
|
orionis/foundation/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
81
|
-
orionis/foundation/application.py,sha256=
|
|
84
|
+
orionis/foundation/application.py,sha256=fKKT4K_DBPEKTMZaeRfBpK_DsaWvEt_dVhA-yu1Wyfo,77173
|
|
82
85
|
orionis/foundation/config/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
83
86
|
orionis/foundation/config/startup.py,sha256=vbzduprRCNyYeR2nnMaqc1uKXw6PTzAY2jVfXNQKN8I,9691
|
|
84
87
|
orionis/foundation/config/app/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -185,12 +188,13 @@ orionis/foundation/providers/dumper_provider.py,sha256=nKHjLDClCo-KnPloh6EYVySjg
|
|
|
185
188
|
orionis/foundation/providers/executor_provider.py,sha256=kwkH8YWEXoEoP51akJXQJ0U25rhlOLxnfE0s9fALr0I,3478
|
|
186
189
|
orionis/foundation/providers/inspirational_provider.py,sha256=uq2o0uLd5p6PR99uH4cJAcc6NnU6nIOwe0ZIdzZcF4Q,3726
|
|
187
190
|
orionis/foundation/providers/logger_provider.py,sha256=rs8UpaD_vSp3qNli0u9A4eRum3q3F0KEM0V6yhcl2GU,3417
|
|
191
|
+
orionis/foundation/providers/performance_counter_provider.py,sha256=7y10Vaqx7GemGh2wCaww8XmdvFQXLXm9_E4GjpdNXcA,3010
|
|
188
192
|
orionis/foundation/providers/progress_bar_provider.py,sha256=X4Ke7mPr0MgVp6WDNaQ3bI3Z_LOS8qE-wid0MQErKms,3367
|
|
189
193
|
orionis/foundation/providers/reactor_provider.py,sha256=P0KQcp4AFKTrD6BStGfCTqhGUlpKgsrZTZZKSqyGJQg,3662
|
|
190
194
|
orionis/foundation/providers/testing_provider.py,sha256=SrJRpdvcblx9WvX7x9Y3zc7OQfiTf7la0HAJrm2ESlE,3725
|
|
191
195
|
orionis/foundation/providers/workers_provider.py,sha256=oa_2NIDH6UxZrtuGkkoo_zEoNIMGgJ46vg5CCgAm7wI,3926
|
|
192
196
|
orionis/metadata/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
193
|
-
orionis/metadata/framework.py,sha256=
|
|
197
|
+
orionis/metadata/framework.py,sha256=ejjgT2RQp5L2BLHIiUExn2vemTJaQ7Zyxa268PHB55g,4109
|
|
194
198
|
orionis/metadata/package.py,sha256=k7Yriyp5aUcR-iR8SK2ec_lf0_Cyc-C7JczgXa-I67w,16039
|
|
195
199
|
orionis/services/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
196
200
|
orionis/services/asynchrony/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -287,6 +291,7 @@ orionis/support/facades/dumper.py,sha256=qQPoMbkXExv6UaByoDCyJA-gt5SA1oQtym2Twpi
|
|
|
287
291
|
orionis/support/facades/executor.py,sha256=fRBQ447WpL2T42Ys02k_DJNqukFFk8-bbNFz4GEbRfI,931
|
|
288
292
|
orionis/support/facades/inspire.py,sha256=n7TFhxneqUtEJYQSrOdmNq9XQzhFMMsIAfdwnBWR1hA,841
|
|
289
293
|
orionis/support/facades/logger.py,sha256=Ncrd_bcggEOnWfLmvGjYTnFgO_Hop2iO9di1oWqH0Ow,824
|
|
294
|
+
orionis/support/facades/performance_counter.py,sha256=NGSYbGREfOfjsXnLcJ2J9sLVRuOLZwPjJsqYP7-6egg,733
|
|
290
295
|
orionis/support/facades/progress_bar.py,sha256=eTxfGIAfdkrXkycvdQBddn9E4MIlbCLOU7TDO2-7cgU,717
|
|
291
296
|
orionis/support/facades/reactor.py,sha256=CJwyUU-MC1LqwiHji7f7gSm2XAs8_DdhbOXmTylNt70,742
|
|
292
297
|
orionis/support/facades/testing.py,sha256=5tzFIMSe1gxLcs7dcueUnAdTJ977czd2sNK1RtUjSUM,737
|
|
@@ -300,6 +305,10 @@ orionis/support/formatter/exceptions/contracts/parser.py,sha256=onLMtggihUGPhCav
|
|
|
300
305
|
orionis/support/patterns/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
301
306
|
orionis/support/patterns/singleton/__init__.py,sha256=BIyMYL5yXpzv_F-jsSEtoKYseGlM8jdJT8hwGuXZZl8,62
|
|
302
307
|
orionis/support/patterns/singleton/meta.py,sha256=TmrE-QlkglBChD4bmMgQRGT3nli6Kf6UvDl1tiEjQ_o,3801
|
|
308
|
+
orionis/support/performance/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
309
|
+
orionis/support/performance/counter.py,sha256=eTr1VoFy1Jiqc4lmyhrYGTe2ge-Vpl1zuzYt_3nMTP8,2947
|
|
310
|
+
orionis/support/performance/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
311
|
+
orionis/support/performance/contracts/counter.py,sha256=uDBFk4YswAI4O72t2lc2H8Ck86WU4tp8p4gPXg-r3mw,1317
|
|
303
312
|
orionis/support/standard/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
304
313
|
orionis/support/standard/std.py,sha256=zwXOellgGy9LTmeAK-rCIr7CgKYg5iQijMjdwmMblFA,3800
|
|
305
314
|
orionis/support/standard/contracts/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -356,7 +365,7 @@ orionis/test/validators/web_report.py,sha256=n9BfzOZz6aEiNTypXcwuWbFRG0OdHNSmCNu
|
|
|
356
365
|
orionis/test/validators/workers.py,sha256=rWcdRexINNEmGaO7mnc1MKUxkHKxrTsVuHgbnIfJYgc,1206
|
|
357
366
|
orionis/test/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
358
367
|
orionis/test/view/render.py,sha256=f-zNhtKSg9R5Njqujbg2l2amAs2-mRVESneLIkWOZjU,4082
|
|
359
|
-
orionis-0.
|
|
368
|
+
orionis-0.477.0.dist-info/licenses/LICENCE,sha256=JhC-z_9mbpUrCfPjcl3DhDA8trNDMzb57cvRSam1avc,1463
|
|
360
369
|
tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
361
370
|
tests/container/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
362
371
|
tests/container/context/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
@@ -503,8 +512,8 @@ tests/testing/validators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZ
|
|
|
503
512
|
tests/testing/validators/test_testing_validators.py,sha256=WPo5GxTP6xE-Dw3X1vZoqOMpb6HhokjNSbgDsDRDvy4,16588
|
|
504
513
|
tests/testing/view/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
505
514
|
tests/testing/view/test_render.py,sha256=tnnMBwS0iKUIbogLvu-7Rii50G6Koddp3XT4wgdFEYM,1050
|
|
506
|
-
orionis-0.
|
|
507
|
-
orionis-0.
|
|
508
|
-
orionis-0.
|
|
509
|
-
orionis-0.
|
|
510
|
-
orionis-0.
|
|
515
|
+
orionis-0.477.0.dist-info/METADATA,sha256=kn7zCbpOB1itx7h7PtTFktTgPf1-v_fV4_WnSwerCTA,4801
|
|
516
|
+
orionis-0.477.0.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
|
|
517
|
+
orionis-0.477.0.dist-info/top_level.txt,sha256=2bdoHgyGZhOtLAXS6Om8OCTmL24dUMC_L1quMe_ETbk,14
|
|
518
|
+
orionis-0.477.0.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
519
|
+
orionis-0.477.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|