orionis 0.1.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/__init__.py +0 -0
- orionis/cli_manager.py +48 -0
- orionis/framework.py +45 -0
- orionis/luminate/__init__.py +0 -0
- orionis/luminate/app.py +0 -0
- orionis/luminate/bootstrap/__init__.py +0 -0
- orionis/luminate/bootstrap/parser.py +49 -0
- orionis/luminate/bootstrap/register.py +95 -0
- orionis/luminate/cache/__init__.py +0 -0
- orionis/luminate/cache/app/__init__.py +0 -0
- orionis/luminate/cache/app/config.py +96 -0
- orionis/luminate/cache/console/__init__.py +0 -0
- orionis/luminate/cache/console/commands.py +98 -0
- orionis/luminate/config/__init__.py +0 -0
- orionis/luminate/config/dataclass/__init__.py +0 -0
- orionis/luminate/config/dataclass/app.py +50 -0
- orionis/luminate/config/dataclass/auth.py +17 -0
- orionis/luminate/config/dataclass/cache.py +51 -0
- orionis/luminate/config/dataclass/cors.py +58 -0
- orionis/luminate/config/dataclass/database.py +203 -0
- orionis/luminate/config/dataclass/filesystems.py +102 -0
- orionis/luminate/config/dataclass/logging.py +107 -0
- orionis/luminate/config/dataclass/mail.py +81 -0
- orionis/luminate/config/dataclass/queue.py +63 -0
- orionis/luminate/config/dataclass/session.py +59 -0
- orionis/luminate/config/environment.py +110 -0
- orionis/luminate/config/sections.py +37 -0
- orionis/luminate/console/__init__.py +0 -0
- orionis/luminate/console/base/__init__.py +0 -0
- orionis/luminate/console/base/command.py +427 -0
- orionis/luminate/console/cache.py +132 -0
- orionis/luminate/console/command.py +40 -0
- orionis/luminate/console/command_filter.py +40 -0
- orionis/luminate/console/commands/__init__.py +0 -0
- orionis/luminate/console/commands/cache_clear.py +56 -0
- orionis/luminate/console/commands/help.py +59 -0
- orionis/luminate/console/commands/schedule_work.py +50 -0
- orionis/luminate/console/commands/tests.py +40 -0
- orionis/luminate/console/commands/version.py +39 -0
- orionis/luminate/console/exceptions/__init__.py +0 -0
- orionis/luminate/console/exceptions/cli_exception.py +125 -0
- orionis/luminate/console/kernel.py +32 -0
- orionis/luminate/console/output/__init__.py +0 -0
- orionis/luminate/console/output/console.py +426 -0
- orionis/luminate/console/output/executor.py +90 -0
- orionis/luminate/console/output/progress_bar.py +100 -0
- orionis/luminate/console/output/styles.py +95 -0
- orionis/luminate/console/parser.py +159 -0
- orionis/luminate/console/register.py +98 -0
- orionis/luminate/console/runner.py +126 -0
- orionis/luminate/console/scripts/__init__.py +0 -0
- orionis/luminate/console/scripts/management.py +94 -0
- orionis/luminate/console/tasks/__init__.py +0 -0
- orionis/luminate/console/tasks/scheduler.py +616 -0
- orionis/luminate/contracts/__init__.py +0 -0
- orionis/luminate/contracts/bootstrap/parser_interface.py +46 -0
- orionis/luminate/contracts/cache/__init__.py +0 -0
- orionis/luminate/contracts/cache/cache_commands_interface.py +69 -0
- orionis/luminate/contracts/config/__init__.py +0 -0
- orionis/luminate/contracts/config/config_interface.py +27 -0
- orionis/luminate/contracts/config/environment_interface.py +64 -0
- orionis/luminate/contracts/console/__init__.py +0 -0
- orionis/luminate/contracts/console/base_command_interface.py +448 -0
- orionis/luminate/contracts/console/cli_cache_interface.py +34 -0
- orionis/luminate/contracts/console/command_filter_interface.py +32 -0
- orionis/luminate/contracts/console/command_interface.py +36 -0
- orionis/luminate/contracts/console/console_interface.py +305 -0
- orionis/luminate/contracts/console/executor_interface.py +51 -0
- orionis/luminate/contracts/console/kernel_interface.py +32 -0
- orionis/luminate/contracts/console/management_interface.py +63 -0
- orionis/luminate/contracts/console/parser_interface.py +76 -0
- orionis/luminate/contracts/console/progress_bar_interface.py +66 -0
- orionis/luminate/contracts/console/register_interface.py +32 -0
- orionis/luminate/contracts/console/runner_interface.py +50 -0
- orionis/luminate/contracts/console/schedule_interface.py +317 -0
- orionis/luminate/contracts/console/task_manager_interface.py +37 -0
- orionis/luminate/contracts/facades/__init__.py +0 -0
- orionis/luminate/contracts/facades/env_interface.py +64 -0
- orionis/luminate/contracts/facades/log_interface.py +48 -0
- orionis/luminate/contracts/facades/paths_interface.py +141 -0
- orionis/luminate/contracts/facades/tests_interface.py +33 -0
- orionis/luminate/contracts/files/__init__.py +0 -0
- orionis/luminate/contracts/files/paths_interface.py +29 -0
- orionis/luminate/contracts/installer/__init__.py +0 -0
- orionis/luminate/contracts/installer/output_interface.py +125 -0
- orionis/luminate/contracts/installer/setup_interface.py +29 -0
- orionis/luminate/contracts/installer/upgrade_interface.py +24 -0
- orionis/luminate/contracts/log/__init__.py +0 -0
- orionis/luminate/contracts/log/logger_interface.py +33 -0
- orionis/luminate/contracts/pipelines/cli_pipeline_interface.py +84 -0
- orionis/luminate/contracts/publisher/__init__.py +0 -0
- orionis/luminate/contracts/publisher/pypi_publisher_interface.py +36 -0
- orionis/luminate/contracts/test/__init__.py +0 -0
- orionis/luminate/contracts/test/unit_test_interface.py +51 -0
- orionis/luminate/contracts/tools/__init__.py +0 -0
- orionis/luminate/contracts/tools/reflection_interface.py +343 -0
- orionis/luminate/contracts/tools/std_interface.py +56 -0
- orionis/luminate/facades/__init__.py +0 -0
- orionis/luminate/facades/environment.py +81 -0
- orionis/luminate/facades/log.py +56 -0
- orionis/luminate/facades/paths.py +268 -0
- orionis/luminate/facades/tests.py +48 -0
- orionis/luminate/files/__init__.py +0 -0
- orionis/luminate/files/paths.py +56 -0
- orionis/luminate/installer/__init__.py +0 -0
- orionis/luminate/installer/icon.ascii +11 -0
- orionis/luminate/installer/info.ascii +13 -0
- orionis/luminate/installer/output.py +188 -0
- orionis/luminate/installer/setup.py +191 -0
- orionis/luminate/installer/upgrade.py +42 -0
- orionis/luminate/log/__init__.py +0 -0
- orionis/luminate/log/logger.py +116 -0
- orionis/luminate/pipelines/__init__.py +0 -0
- orionis/luminate/pipelines/cli_pipeline.py +116 -0
- orionis/luminate/publisher/__init__.py +0 -0
- orionis/luminate/publisher/pypi.py +206 -0
- orionis/luminate/static/logos/flaskavel.png +0 -0
- orionis/luminate/test/__init__.py +0 -0
- orionis/luminate/test/exception.py +48 -0
- orionis/luminate/test/unit_test.py +108 -0
- orionis/luminate/tools/__init__.py +0 -0
- orionis/luminate/tools/reflection.py +390 -0
- orionis/luminate/tools/std.py +53 -0
- orionis-0.1.0.dist-info/LICENCE +21 -0
- orionis-0.1.0.dist-info/METADATA +27 -0
- orionis-0.1.0.dist-info/RECORD +133 -0
- orionis-0.1.0.dist-info/WHEEL +5 -0
- orionis-0.1.0.dist-info/entry_points.txt +2 -0
- orionis-0.1.0.dist-info/top_level.txt +2 -0
- tests/__init__.py +0 -0
- tests/tools/__init__.py +0 -0
- tests/tools/class_example.py +50 -0
- tests/tools/test_reflection.py +128 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
import os
|
2
|
+
import threading
|
3
|
+
from pathlib import Path
|
4
|
+
from dotenv import set_key, unset_key, dotenv_values
|
5
|
+
from orionis.luminate.contracts.config.environment_interface import IEnvironment
|
6
|
+
|
7
|
+
class Environment(IEnvironment):
|
8
|
+
"""
|
9
|
+
Singleton class to manage environment variables from a .env file.
|
10
|
+
Ensures a single instance handles environment variable access,
|
11
|
+
modification, and deletion.
|
12
|
+
"""
|
13
|
+
|
14
|
+
# Singleton instance
|
15
|
+
_instance = None
|
16
|
+
|
17
|
+
# Thread lock to control instance creation
|
18
|
+
_lock = threading.Lock()
|
19
|
+
|
20
|
+
def __new__(cls, path: str = None):
|
21
|
+
"""
|
22
|
+
Creates or returns the singleton instance.
|
23
|
+
Ensures thread-safe initialization using a lock.
|
24
|
+
|
25
|
+
Parameters
|
26
|
+
----------
|
27
|
+
path : str, optional
|
28
|
+
Path to the .env file. Defaults to None.
|
29
|
+
|
30
|
+
Returns
|
31
|
+
-------
|
32
|
+
_Environment
|
33
|
+
The singleton instance of _Environment.
|
34
|
+
"""
|
35
|
+
with cls._lock:
|
36
|
+
if cls._instance is None:
|
37
|
+
cls._instance = super().__new__(cls)
|
38
|
+
cls._instance._initialize(path)
|
39
|
+
return cls._instance
|
40
|
+
|
41
|
+
def _initialize(self, path: str = None):
|
42
|
+
"""
|
43
|
+
Initializes the instance by setting the path to the .env file.
|
44
|
+
If no path is provided, defaults to a `.env` file in the current directory.
|
45
|
+
|
46
|
+
Parameters
|
47
|
+
----------
|
48
|
+
path : str, optional
|
49
|
+
Path to the .env file. Defaults to None.
|
50
|
+
"""
|
51
|
+
self.path = Path(path) if path else Path(os.getcwd()) / ".env"
|
52
|
+
|
53
|
+
# Ensure the .env file exists
|
54
|
+
if not self.path.exists():
|
55
|
+
self.path.touch()
|
56
|
+
|
57
|
+
def get(self, key: str, default=None) -> str:
|
58
|
+
"""
|
59
|
+
Retrieves the value of an environment variable from the .env file
|
60
|
+
or from system environment variables if not found.
|
61
|
+
|
62
|
+
Parameters
|
63
|
+
----------
|
64
|
+
key : str
|
65
|
+
The key of the environment variable.
|
66
|
+
default : optional
|
67
|
+
Default value if the key does not exist. Defaults to None.
|
68
|
+
|
69
|
+
Returns
|
70
|
+
-------
|
71
|
+
str
|
72
|
+
The value of the environment variable or the default value.
|
73
|
+
"""
|
74
|
+
value = dotenv_values(self.path).get(key)
|
75
|
+
return value if value is not None else os.getenv(key, default)
|
76
|
+
|
77
|
+
def set(self, key: str, value: str) -> None:
|
78
|
+
"""
|
79
|
+
Sets the value of an environment variable in the .env file.
|
80
|
+
|
81
|
+
Parameters
|
82
|
+
----------
|
83
|
+
key : str
|
84
|
+
The key of the environment variable.
|
85
|
+
value : str
|
86
|
+
The value to set.
|
87
|
+
"""
|
88
|
+
set_key(str(self.path), key, value)
|
89
|
+
|
90
|
+
def unset(self, key: str) -> None:
|
91
|
+
"""
|
92
|
+
Removes an environment variable from the .env file.
|
93
|
+
|
94
|
+
Parameters
|
95
|
+
----------
|
96
|
+
key : str
|
97
|
+
The key of the environment variable to remove.
|
98
|
+
"""
|
99
|
+
unset_key(str(self.path), key)
|
100
|
+
|
101
|
+
def all(self) -> dict:
|
102
|
+
"""
|
103
|
+
Retrieves all environment variable values from the .env file.
|
104
|
+
|
105
|
+
Returns
|
106
|
+
-------
|
107
|
+
dict
|
108
|
+
A dictionary of all environment variables and their values.
|
109
|
+
"""
|
110
|
+
return dotenv_values(self.path)
|
@@ -0,0 +1,37 @@
|
|
1
|
+
# ------------------------------------------------------------------------------
|
2
|
+
# Authorized Configuration Sections for Bootstrapping
|
3
|
+
# ------------------------------------------------------------------------------
|
4
|
+
# This tuple defines the only allowed configuration sections that can be used
|
5
|
+
# during the application's bootstrapping process.
|
6
|
+
#
|
7
|
+
# Each section represents a core component of the framework, ensuring that only
|
8
|
+
# predefined and necessary configurations are loaded at startup. This prevents
|
9
|
+
# unauthorized modifications or unintended settings from being injected.
|
10
|
+
#
|
11
|
+
# Sections:
|
12
|
+
# - app : General application settings.
|
13
|
+
# - auth : Authentication and authorization settings.
|
14
|
+
# - cache : Configuration for caching mechanisms.
|
15
|
+
# - cors : Cross-Origin Resource Sharing (CORS) policies.
|
16
|
+
# - database : Database connection and ORM settings.
|
17
|
+
# - filesystems: File storage configurations.
|
18
|
+
# - logging : Logging and monitoring settings.
|
19
|
+
# - mail : Email sending and SMTP configurations.
|
20
|
+
# - queue : Queue system settings for background tasks.
|
21
|
+
# - session : Session management configurations.
|
22
|
+
#
|
23
|
+
# Any configuration outside these sections will be ignored or rejected.
|
24
|
+
# ------------------------------------------------------------------------------
|
25
|
+
|
26
|
+
SECTIONS = (
|
27
|
+
'app',
|
28
|
+
'auth',
|
29
|
+
'cache',
|
30
|
+
'cors',
|
31
|
+
'database',
|
32
|
+
'filesystems',
|
33
|
+
'logging',
|
34
|
+
'mail',
|
35
|
+
'queue',
|
36
|
+
'session'
|
37
|
+
)
|
File without changes
|
File without changes
|
@@ -0,0 +1,427 @@
|
|
1
|
+
from orionis.luminate.console.output.console import Console
|
2
|
+
from orionis.luminate.console.output.progress_bar import ProgressBar
|
3
|
+
from orionis.luminate.contracts.console.base_command_interface import IBaseCommand
|
4
|
+
|
5
|
+
class BaseCommand(IBaseCommand):
|
6
|
+
"""
|
7
|
+
A base class for handling common console output functionalities. This class provides methods to print messages of
|
8
|
+
various types (success, info, warning, etc.) in different styles (e.g., text, bold, colored).
|
9
|
+
|
10
|
+
This class acts as a foundation for command classes, offering utility methods to interact with the console.
|
11
|
+
"""
|
12
|
+
|
13
|
+
# Command arguments
|
14
|
+
args = {}
|
15
|
+
|
16
|
+
def success(self, message: str = '', timestamp: bool = True):
|
17
|
+
"""
|
18
|
+
Prints a success message with a green background.
|
19
|
+
|
20
|
+
Parameters
|
21
|
+
----------
|
22
|
+
message : str, optional
|
23
|
+
The message to display (default is an empty string).
|
24
|
+
timestamp : bool, optional
|
25
|
+
Whether to include a timestamp (default is True).
|
26
|
+
"""
|
27
|
+
Console.success(message, timestamp)
|
28
|
+
|
29
|
+
def textSuccess(self, message: str = ''):
|
30
|
+
"""
|
31
|
+
Prints a success message in green.
|
32
|
+
|
33
|
+
Parameters
|
34
|
+
----------
|
35
|
+
message : str, optional
|
36
|
+
The message to display (default is an empty string).
|
37
|
+
"""
|
38
|
+
Console.textSuccess(message)
|
39
|
+
|
40
|
+
def textSuccessBold(self, message: str = ''):
|
41
|
+
"""
|
42
|
+
Prints a bold success message in green.
|
43
|
+
|
44
|
+
Parameters
|
45
|
+
----------
|
46
|
+
message : str, optional
|
47
|
+
The message to display (default is an empty string).
|
48
|
+
"""
|
49
|
+
Console.textSuccessBold(message)
|
50
|
+
|
51
|
+
def info(self, message: str = '', timestamp: bool = True):
|
52
|
+
"""
|
53
|
+
Prints an informational message with a blue background.
|
54
|
+
|
55
|
+
Parameters
|
56
|
+
----------
|
57
|
+
message : str, optional
|
58
|
+
The message to display (default is an empty string).
|
59
|
+
timestamp : bool, optional
|
60
|
+
Whether to include a timestamp (default is True).
|
61
|
+
"""
|
62
|
+
Console.info(message, timestamp)
|
63
|
+
|
64
|
+
def textInfo(self, message: str = ''):
|
65
|
+
"""
|
66
|
+
Prints an informational message in blue.
|
67
|
+
|
68
|
+
Parameters
|
69
|
+
----------
|
70
|
+
message : str, optional
|
71
|
+
The message to display (default is an empty string).
|
72
|
+
"""
|
73
|
+
Console.textInfo(message)
|
74
|
+
|
75
|
+
def textInfoBold(self, message: str = ''):
|
76
|
+
"""
|
77
|
+
Prints a bold informational message in blue.
|
78
|
+
|
79
|
+
Parameters
|
80
|
+
----------
|
81
|
+
message : str, optional
|
82
|
+
The message to display (default is an empty string).
|
83
|
+
"""
|
84
|
+
Console.textInfoBold(message)
|
85
|
+
|
86
|
+
def warning(self, message: str = '', timestamp: bool = True):
|
87
|
+
"""
|
88
|
+
Prints a warning message with a yellow background.
|
89
|
+
|
90
|
+
Parameters
|
91
|
+
----------
|
92
|
+
message : str, optional
|
93
|
+
The message to display (default is an empty string).
|
94
|
+
timestamp : bool, optional
|
95
|
+
Whether to include a timestamp (default is True).
|
96
|
+
"""
|
97
|
+
Console.warning(message, timestamp)
|
98
|
+
|
99
|
+
def textWarning(self, message: str = ''):
|
100
|
+
"""
|
101
|
+
Prints a warning message in yellow.
|
102
|
+
|
103
|
+
Parameters
|
104
|
+
----------
|
105
|
+
message : str, optional
|
106
|
+
The message to display (default is an empty string).
|
107
|
+
"""
|
108
|
+
Console.textWarning(message)
|
109
|
+
|
110
|
+
def textWarningBold(self, message: str = ''):
|
111
|
+
"""
|
112
|
+
Prints a bold warning message in yellow.
|
113
|
+
|
114
|
+
Parameters
|
115
|
+
----------
|
116
|
+
message : str, optional
|
117
|
+
The message to display (default is an empty string).
|
118
|
+
"""
|
119
|
+
Console.textWarningBold(message)
|
120
|
+
|
121
|
+
def fail(self, message: str = '', timestamp: bool = True):
|
122
|
+
"""
|
123
|
+
Prints a failure message with a red background.
|
124
|
+
|
125
|
+
Parameters
|
126
|
+
----------
|
127
|
+
message : str, optional
|
128
|
+
The message to display (default is an empty string).
|
129
|
+
timestamp : bool, optional
|
130
|
+
Whether to include a timestamp (default is True).
|
131
|
+
"""
|
132
|
+
Console.fail(message, timestamp)
|
133
|
+
|
134
|
+
def error(self, message: str = '', timestamp: bool = True):
|
135
|
+
"""
|
136
|
+
Prints an error message with a red background.
|
137
|
+
|
138
|
+
Parameters
|
139
|
+
----------
|
140
|
+
message : str, optional
|
141
|
+
The message to display (default is an empty string).
|
142
|
+
timestamp : bool, optional
|
143
|
+
Whether to include a timestamp (default is True).
|
144
|
+
"""
|
145
|
+
Console.error(message, timestamp)
|
146
|
+
|
147
|
+
def textError(self, message: str = ''):
|
148
|
+
"""
|
149
|
+
Prints an error message in red.
|
150
|
+
|
151
|
+
Parameters
|
152
|
+
----------
|
153
|
+
message : str, optional
|
154
|
+
The message to display (default is an empty string).
|
155
|
+
"""
|
156
|
+
Console.textError(message)
|
157
|
+
|
158
|
+
def textErrorBold(self, message: str = ''):
|
159
|
+
"""
|
160
|
+
Prints a bold error message in red.
|
161
|
+
|
162
|
+
Parameters
|
163
|
+
----------
|
164
|
+
message : str, optional
|
165
|
+
The message to display (default is an empty string).
|
166
|
+
"""
|
167
|
+
Console.textErrorBold(message)
|
168
|
+
|
169
|
+
def textMuted(self, message: str = ''):
|
170
|
+
"""
|
171
|
+
Prints a muted (gray) message.
|
172
|
+
|
173
|
+
Parameters
|
174
|
+
----------
|
175
|
+
message : str, optional
|
176
|
+
The message to display (default is an empty string).
|
177
|
+
"""
|
178
|
+
Console.textMuted(message)
|
179
|
+
|
180
|
+
def textMutedBold(self, message: str = ''):
|
181
|
+
"""
|
182
|
+
Prints a bold muted (gray) message.
|
183
|
+
|
184
|
+
Parameters
|
185
|
+
----------
|
186
|
+
message : str, optional
|
187
|
+
The message to display (default is an empty string).
|
188
|
+
"""
|
189
|
+
Console.textMutedBold(message)
|
190
|
+
|
191
|
+
def textUnderline(self, message: str = ''):
|
192
|
+
"""
|
193
|
+
Prints an underlined message.
|
194
|
+
|
195
|
+
Parameters
|
196
|
+
----------
|
197
|
+
message : str, optional
|
198
|
+
The message to display (default is an empty string).
|
199
|
+
"""
|
200
|
+
Console.textUnderline(message)
|
201
|
+
|
202
|
+
def clear(self):
|
203
|
+
"""
|
204
|
+
Clears the console screen.
|
205
|
+
"""
|
206
|
+
Console.clear()
|
207
|
+
|
208
|
+
def clearLine(self):
|
209
|
+
"""
|
210
|
+
Clears the current console line.
|
211
|
+
"""
|
212
|
+
Console.clearLine()
|
213
|
+
|
214
|
+
def line(self, message: str = ''):
|
215
|
+
"""
|
216
|
+
Prints a line of text.
|
217
|
+
|
218
|
+
Parameters
|
219
|
+
----------
|
220
|
+
message : str, optional
|
221
|
+
The message to display (default is an empty string).
|
222
|
+
"""
|
223
|
+
Console.line(message)
|
224
|
+
|
225
|
+
def newLine(self, count: int = 1):
|
226
|
+
"""
|
227
|
+
Prints multiple new lines.
|
228
|
+
|
229
|
+
Parameters
|
230
|
+
----------
|
231
|
+
count : int, optional
|
232
|
+
The number of new lines to print (default is 1).
|
233
|
+
"""
|
234
|
+
Console.newLine(count)
|
235
|
+
|
236
|
+
def write(self, message: str = ''):
|
237
|
+
"""
|
238
|
+
Prints a message without moving to the next line.
|
239
|
+
|
240
|
+
Parameters
|
241
|
+
----------
|
242
|
+
message : str, optional
|
243
|
+
The message to display (default is an empty string).
|
244
|
+
"""
|
245
|
+
Console.write(message)
|
246
|
+
|
247
|
+
def writeLine(self, message: str = ''):
|
248
|
+
"""
|
249
|
+
Prints a message and moves to the next line.
|
250
|
+
|
251
|
+
Parameters
|
252
|
+
----------
|
253
|
+
message : str, optional
|
254
|
+
The message to display (default is an empty string).
|
255
|
+
"""
|
256
|
+
Console.writeLine(message)
|
257
|
+
|
258
|
+
def ask(self, question: str) -> str:
|
259
|
+
"""
|
260
|
+
Prompts the user for input and returns the response.
|
261
|
+
|
262
|
+
Parameters
|
263
|
+
----------
|
264
|
+
question : str
|
265
|
+
The question to ask the user.
|
266
|
+
|
267
|
+
Returns
|
268
|
+
-------
|
269
|
+
str
|
270
|
+
The user's input.
|
271
|
+
"""
|
272
|
+
return Console.ask(question)
|
273
|
+
|
274
|
+
def confirm(self, question: str, default: bool = False) -> bool:
|
275
|
+
"""
|
276
|
+
Asks a confirmation question and returns True/False based on the user's response.
|
277
|
+
|
278
|
+
Parameters
|
279
|
+
----------
|
280
|
+
question : str
|
281
|
+
The confirmation question to ask.
|
282
|
+
default : bool, optional
|
283
|
+
The default response if the user presses Enter without typing a response (default is False).
|
284
|
+
|
285
|
+
Returns
|
286
|
+
-------
|
287
|
+
bool
|
288
|
+
The user's response.
|
289
|
+
"""
|
290
|
+
return Console.ask(question, default)
|
291
|
+
|
292
|
+
def secret(self, question: str) -> str:
|
293
|
+
"""
|
294
|
+
Prompts for hidden input (e.g., password).
|
295
|
+
|
296
|
+
Parameters
|
297
|
+
----------
|
298
|
+
question : str
|
299
|
+
The prompt to ask the user.
|
300
|
+
|
301
|
+
Returns
|
302
|
+
-------
|
303
|
+
str
|
304
|
+
The user's hidden input.
|
305
|
+
"""
|
306
|
+
return Console.secret(question)
|
307
|
+
|
308
|
+
def table(self, headers: list, rows: list):
|
309
|
+
"""
|
310
|
+
Prints a formatted table in the console.
|
311
|
+
|
312
|
+
Parameters
|
313
|
+
----------
|
314
|
+
headers : list of str
|
315
|
+
The column headers for the table.
|
316
|
+
rows : list of list of str
|
317
|
+
The rows of the table.
|
318
|
+
|
319
|
+
Raises
|
320
|
+
------
|
321
|
+
ValueError
|
322
|
+
If headers or rows are empty.
|
323
|
+
"""
|
324
|
+
Console.table(headers, rows)
|
325
|
+
|
326
|
+
def anticipate(self, question: str, options: list, default=None):
|
327
|
+
"""
|
328
|
+
Provides autocomplete suggestions for user input.
|
329
|
+
|
330
|
+
Parameters
|
331
|
+
----------
|
332
|
+
question : str
|
333
|
+
The prompt for the user.
|
334
|
+
options : list of str
|
335
|
+
The list of possible options for autocomplete.
|
336
|
+
default : str, optional
|
337
|
+
The default value if no matching option is found (default is None).
|
338
|
+
|
339
|
+
Returns
|
340
|
+
-------
|
341
|
+
str
|
342
|
+
The chosen option or the default value.
|
343
|
+
"""
|
344
|
+
Console.anticipate(question, options, default)
|
345
|
+
|
346
|
+
def choice(self, question: str, choices: list, default_index: int = 0) -> str:
|
347
|
+
"""
|
348
|
+
Prompts the user to select a choice from a list.
|
349
|
+
|
350
|
+
Parameters
|
351
|
+
----------
|
352
|
+
question : str
|
353
|
+
The prompt for the user.
|
354
|
+
choices : list of str
|
355
|
+
The list of available choices.
|
356
|
+
default_index : int, optional
|
357
|
+
The index of the default choice (default is 0).
|
358
|
+
|
359
|
+
Returns
|
360
|
+
-------
|
361
|
+
str
|
362
|
+
The selected choice.
|
363
|
+
|
364
|
+
Raises
|
365
|
+
------
|
366
|
+
ValueError
|
367
|
+
If `default_index` is out of the range of choices.
|
368
|
+
"""
|
369
|
+
Console.choice(question, choices, default_index)
|
370
|
+
|
371
|
+
def createProgressBar(self, total: int = 100, width: int = 50) -> ProgressBar:
|
372
|
+
"""
|
373
|
+
Creates and returns a new progress bar.
|
374
|
+
|
375
|
+
This method initializes a `ProgressBar` object with the specified total and width.
|
376
|
+
|
377
|
+
Parameters
|
378
|
+
----------
|
379
|
+
total : int, optional
|
380
|
+
The total number of steps for the progress bar. Default is 100.
|
381
|
+
width : int, optional
|
382
|
+
The width (in characters) of the progress bar. Default is 50.
|
383
|
+
|
384
|
+
Returns
|
385
|
+
-------
|
386
|
+
ProgressBar
|
387
|
+
A new instance of the `ProgressBar` class, initialized with the specified `total` and `width`.
|
388
|
+
|
389
|
+
Notes
|
390
|
+
-----
|
391
|
+
The progress bar can be used to visually track the progress of a task.
|
392
|
+
The `total` parameter represents the number of steps to complete the task,
|
393
|
+
and the `width` parameter controls the number of characters used to represent the progress bar in the console.
|
394
|
+
"""
|
395
|
+
return ProgressBar(total=total, width=width)
|
396
|
+
|
397
|
+
def setArgs(self, args):
|
398
|
+
"""
|
399
|
+
Define the logic of setting command arguments.
|
400
|
+
|
401
|
+
Parameters
|
402
|
+
----------
|
403
|
+
args : argparse.Namespace
|
404
|
+
Contain the arguments to be set for the command.
|
405
|
+
"""
|
406
|
+
try:
|
407
|
+
# Convert arguments to a dictionary using vars(), if possible
|
408
|
+
self.args = vars(args)
|
409
|
+
except TypeError:
|
410
|
+
# Fallback to an empty dictionary if args is not compatible with vars()
|
411
|
+
self.args = {}
|
412
|
+
|
413
|
+
|
414
|
+
def handle(self, **kwargs):
|
415
|
+
"""
|
416
|
+
Abstract method to define the logic of the command.
|
417
|
+
|
418
|
+
This method must be overridden in subclasses.
|
419
|
+
|
420
|
+
Arguments:
|
421
|
+
**kwargs: Arbitrary keyword arguments.
|
422
|
+
|
423
|
+
Raises:
|
424
|
+
NotImplementedError: If the method is not implemented in a subclass. This ensures that all command classes
|
425
|
+
adhere to the expected structure.
|
426
|
+
"""
|
427
|
+
raise NotImplementedError("The 'handle' method must be implemented in the child class.")
|
@@ -0,0 +1,132 @@
|
|
1
|
+
import os
|
2
|
+
from threading import Lock
|
3
|
+
from orionis.luminate.tools.reflection import Reflection
|
4
|
+
from orionis.luminate.cache.console.commands import CacheCommands
|
5
|
+
from orionis.luminate.contracts.console.cli_cache_interface import ICLICache
|
6
|
+
|
7
|
+
class CLICache(ICLICache):
|
8
|
+
"""
|
9
|
+
Singleton class responsible for managing the loading and execution of commands within the framework.
|
10
|
+
|
11
|
+
This class ensures that commands are loaded only once and are accessible for execution. It is designed to follow
|
12
|
+
the Singleton pattern, meaning only one instance of this class will exist in the application lifecycle.
|
13
|
+
|
14
|
+
Attributes
|
15
|
+
----------
|
16
|
+
_instance : CLICache
|
17
|
+
The singleton instance of the CLICache class.
|
18
|
+
_lock : threading.Lock
|
19
|
+
A lock used to ensure thread-safety during instance creation.
|
20
|
+
_initialized : bool
|
21
|
+
A flag indicating whether the class has been initialized.
|
22
|
+
paths : list
|
23
|
+
List of directories where commands are located.
|
24
|
+
|
25
|
+
Methods
|
26
|
+
-------
|
27
|
+
__new__ :
|
28
|
+
Creates and returns the singleton instance of the CLICache class.
|
29
|
+
__init__ :
|
30
|
+
Initializes the CLICache instance, loading commands if not already initialized.
|
31
|
+
_load_commands :
|
32
|
+
Loads command modules from predefined directories and imports them dynamically.
|
33
|
+
getCommands :
|
34
|
+
Returns the instance of CacheCommands containing the command cache.
|
35
|
+
"""
|
36
|
+
|
37
|
+
_instance = None
|
38
|
+
_lock = Lock()
|
39
|
+
|
40
|
+
def __new__(cls):
|
41
|
+
"""
|
42
|
+
Ensures only one instance of the CLICache class exists (Singleton pattern).
|
43
|
+
|
44
|
+
This method is responsible for controlling the instance creation process, ensuring that no more than one
|
45
|
+
CLICache instance is created in the system, even in multi-threaded environments.
|
46
|
+
|
47
|
+
Returns
|
48
|
+
-------
|
49
|
+
CLICache
|
50
|
+
The singleton instance of the CLICache class.
|
51
|
+
"""
|
52
|
+
with cls._lock:
|
53
|
+
if cls._instance is None:
|
54
|
+
cls._instance = super(CLICache, cls).__new__(cls)
|
55
|
+
cls._instance._initialized = False
|
56
|
+
return cls._instance
|
57
|
+
|
58
|
+
def __init__(self) -> None:
|
59
|
+
"""
|
60
|
+
Initializes the CLICache instance by loading commands if not already initialized.
|
61
|
+
|
62
|
+
This method will load command modules only once, ensuring that the commands are available for execution
|
63
|
+
across the application. It should not be called directly multiple times.
|
64
|
+
|
65
|
+
Attributes
|
66
|
+
----------
|
67
|
+
paths : list
|
68
|
+
List of directories containing command files to be loaded.
|
69
|
+
"""
|
70
|
+
if self._initialized:
|
71
|
+
return
|
72
|
+
|
73
|
+
self.paths = []
|
74
|
+
self._load_commands()
|
75
|
+
self._initialized = True
|
76
|
+
|
77
|
+
def _load_commands(self):
|
78
|
+
"""
|
79
|
+
Dynamically loads command modules from predefined directories.
|
80
|
+
|
81
|
+
This method traverses the specified directories, locates Python files, and imports them as modules.
|
82
|
+
It ensures that only the main directories are iterated over, avoiding subdirectories.
|
83
|
+
|
84
|
+
Directories searched:
|
85
|
+
---------------------
|
86
|
+
- app/console/commands (relative to the base path)
|
87
|
+
- Current directory of the module (this file's directory)
|
88
|
+
"""
|
89
|
+
paths = []
|
90
|
+
|
91
|
+
# Define the base path of the application
|
92
|
+
base_path = os.getcwd()
|
93
|
+
|
94
|
+
# Define command directories to be searched
|
95
|
+
command_dirs = [
|
96
|
+
os.path.join(base_path, 'app', 'console', 'commands'),
|
97
|
+
os.path.join(os.path.dirname(__file__), 'commands')
|
98
|
+
]
|
99
|
+
|
100
|
+
# Add valid directories to paths list
|
101
|
+
for command_dir in command_dirs:
|
102
|
+
if os.path.isdir(command_dir):
|
103
|
+
paths.append(command_dir)
|
104
|
+
|
105
|
+
# Iterate over each valid directory
|
106
|
+
for path in paths:
|
107
|
+
for current_directory, _, files in os.walk(path):
|
108
|
+
# Ensure to only iterate through the top-level directories
|
109
|
+
if current_directory == path:
|
110
|
+
pre_module = current_directory.replace(base_path, '').replace(os.sep, '.').lstrip('.')
|
111
|
+
for file in files:
|
112
|
+
if file.endswith('.py'):
|
113
|
+
# Construct the module name and path
|
114
|
+
module_name = file[:-3] # Remove the '.py' extension
|
115
|
+
module_path = f"{pre_module}.{module_name}".replace('venv.Lib.site-packages.', '')
|
116
|
+
|
117
|
+
# Use Reflection to load the module dynamically
|
118
|
+
Reflection(module=module_path)
|
119
|
+
|
120
|
+
def getCommands(self):
|
121
|
+
"""
|
122
|
+
Returns the instance of the CacheCommands containing the command cache.
|
123
|
+
|
124
|
+
This method provides access to the CacheCommands instance, which holds the loaded commands cache
|
125
|
+
and makes it available for use.
|
126
|
+
|
127
|
+
Returns
|
128
|
+
-------
|
129
|
+
CacheCommands
|
130
|
+
The instance of CacheCommands that holds the cached commands.
|
131
|
+
"""
|
132
|
+
return CacheCommands()
|