orionis 0.405.0__py3-none-any.whl → 0.407.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- orionis/console/base/command.py +57 -50
- orionis/console/base/contracts/command.py +68 -0
- orionis/console/dynamic/contracts/progress_bar.py +3 -3
- orionis/console/dynamic/progress_bar.py +8 -8
- orionis/console/output/console.py +8 -2
- orionis/console/output/contracts/console.py +1 -1
- orionis/container/container.py +2 -2
- orionis/container/context/scope.py +4 -1
- orionis/container/contracts/service_provider.py +2 -2
- orionis/container/entities/binding.py +31 -44
- orionis/container/enums/lifetimes.py +22 -1
- orionis/container/facades/facade.py +1 -2
- orionis/container/providers/service_provider.py +2 -2
- orionis/foundation/application.py +542 -248
- orionis/foundation/config/app/entities/app.py +107 -90
- orionis/foundation/config/auth/entities/auth.py +4 -33
- orionis/foundation/config/cache/entities/cache.py +18 -41
- orionis/foundation/config/cache/entities/file.py +8 -35
- orionis/foundation/config/cache/entities/stores.py +17 -38
- orionis/foundation/config/cors/entities/cors.py +41 -54
- orionis/foundation/config/database/entities/connections.py +40 -56
- orionis/foundation/config/database/entities/database.py +11 -38
- orionis/foundation/config/database/entities/mysql.py +48 -76
- orionis/foundation/config/database/entities/oracle.py +30 -57
- orionis/foundation/config/database/entities/pgsql.py +45 -61
- orionis/foundation/config/database/entities/sqlite.py +26 -53
- orionis/foundation/config/filesystems/entitites/aws.py +28 -49
- orionis/foundation/config/filesystems/entitites/disks.py +27 -47
- orionis/foundation/config/filesystems/entitites/filesystems.py +15 -37
- orionis/foundation/config/filesystems/entitites/local.py +9 -35
- orionis/foundation/config/filesystems/entitites/public.py +14 -41
- orionis/foundation/config/logging/entities/channels.py +56 -86
- orionis/foundation/config/logging/entities/chunked.py +9 -9
- orionis/foundation/config/logging/entities/daily.py +8 -8
- orionis/foundation/config/logging/entities/hourly.py +6 -6
- orionis/foundation/config/logging/entities/logging.py +12 -18
- orionis/foundation/config/logging/entities/monthly.py +7 -7
- orionis/foundation/config/logging/entities/stack.py +5 -5
- orionis/foundation/config/logging/entities/weekly.py +6 -6
- orionis/foundation/config/mail/entities/file.py +9 -36
- orionis/foundation/config/mail/entities/mail.py +22 -40
- orionis/foundation/config/mail/entities/mailers.py +29 -44
- orionis/foundation/config/mail/entities/smtp.py +47 -48
- orionis/foundation/config/queue/entities/brokers.py +19 -41
- orionis/foundation/config/queue/entities/database.py +24 -46
- orionis/foundation/config/queue/entities/queue.py +28 -40
- orionis/foundation/config/roots/paths.py +272 -468
- orionis/foundation/config/session/entities/session.py +23 -53
- orionis/foundation/config/startup.py +165 -135
- orionis/foundation/config/testing/entities/testing.py +137 -122
- orionis/foundation/config/testing/enums/__init__.py +6 -2
- orionis/foundation/config/testing/enums/drivers.py +16 -0
- orionis/foundation/config/testing/enums/verbosity.py +18 -0
- orionis/foundation/contracts/application.py +152 -362
- orionis/foundation/providers/console_provider.py +24 -2
- orionis/foundation/providers/dumper_provider.py +24 -2
- orionis/foundation/providers/logger_provider.py +24 -2
- orionis/foundation/providers/path_resolver_provider.py +25 -2
- orionis/foundation/providers/progress_bar_provider.py +24 -2
- orionis/foundation/providers/testing_provider.py +39 -0
- orionis/foundation/providers/workers_provider.py +24 -2
- orionis/metadata/framework.py +1 -1
- orionis/services/asynchrony/contracts/coroutines.py +13 -5
- orionis/services/asynchrony/coroutines.py +33 -29
- orionis/services/asynchrony/exceptions/exception.py +9 -1
- orionis/services/environment/core/dot_env.py +46 -34
- orionis/services/environment/enums/__init__.py +0 -0
- orionis/services/environment/enums/cast_type.py +42 -0
- orionis/services/environment/helpers/functions.py +1 -2
- orionis/services/environment/key/__init__.py +0 -0
- orionis/services/environment/key/key_generator.py +37 -0
- orionis/services/environment/serializer/__init__.py +0 -0
- orionis/services/environment/serializer/values.py +21 -0
- orionis/services/environment/validators/__init__.py +0 -0
- orionis/services/environment/validators/key_name.py +46 -0
- orionis/services/environment/validators/types.py +45 -0
- orionis/services/system/contracts/imports.py +38 -18
- orionis/services/system/contracts/workers.py +29 -12
- orionis/services/system/imports.py +65 -25
- orionis/services/system/runtime/imports.py +18 -9
- orionis/services/system/workers.py +49 -16
- orionis/support/entities/__init__.py +0 -0
- orionis/support/entities/base.py +104 -0
- orionis/support/facades/testing.py +15 -0
- orionis/support/facades/workers.py +1 -1
- orionis/test/cases/asynchronous.py +0 -11
- orionis/test/cases/synchronous.py +0 -9
- orionis/test/contracts/dumper.py +11 -4
- orionis/test/contracts/kernel.py +5 -110
- orionis/test/contracts/logs.py +27 -65
- orionis/test/contracts/printer.py +16 -128
- orionis/test/contracts/test_result.py +100 -0
- orionis/test/contracts/unit_test.py +87 -150
- orionis/test/core/unit_test.py +608 -554
- orionis/test/entities/result.py +22 -2
- orionis/test/enums/__init__.py +0 -2
- orionis/test/enums/status.py +14 -9
- orionis/test/exceptions/config.py +9 -1
- orionis/test/exceptions/failure.py +34 -11
- orionis/test/exceptions/persistence.py +10 -2
- orionis/test/exceptions/runtime.py +9 -1
- orionis/test/exceptions/value.py +13 -1
- orionis/test/kernel.py +87 -289
- orionis/test/output/dumper.py +83 -18
- orionis/test/output/printer.py +399 -156
- orionis/test/records/logs.py +203 -82
- orionis/test/validators/__init__.py +33 -0
- orionis/test/validators/base_path.py +45 -0
- orionis/test/validators/execution_mode.py +45 -0
- orionis/test/validators/fail_fast.py +37 -0
- orionis/test/validators/folder_path.py +34 -0
- orionis/test/validators/module_name.py +31 -0
- orionis/test/validators/name_pattern.py +40 -0
- orionis/test/validators/pattern.py +36 -0
- orionis/test/validators/persistent.py +42 -0
- orionis/test/validators/persistent_driver.py +43 -0
- orionis/test/validators/print_result.py +37 -0
- orionis/test/validators/tags.py +37 -0
- orionis/test/validators/throw_exception.py +39 -0
- orionis/test/validators/verbosity.py +37 -0
- orionis/test/validators/web_report.py +35 -0
- orionis/test/validators/workers.py +31 -0
- orionis/test/view/render.py +48 -54
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/METADATA +1 -1
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/RECORD +170 -112
- tests/container/__init__.py +0 -0
- tests/container/context/__init__.py +0 -0
- tests/container/context/test_manager.py +27 -0
- tests/container/context/test_scope.py +23 -0
- tests/container/entities/__init__.py +0 -0
- tests/container/entities/test_binding.py +133 -0
- tests/container/enums/__init__.py +0 -0
- tests/container/enums/test_lifetimes.py +63 -0
- tests/container/facades/__init__.py +0 -0
- tests/container/facades/test_facade.py +61 -0
- tests/container/mocks/__init__.py +0 -0
- tests/container/mocks/mock_complex_classes.py +482 -0
- tests/container/mocks/mock_simple_classes.py +32 -0
- tests/container/providers/__init__.py +0 -0
- tests/container/providers/test_providers.py +48 -0
- tests/container/resolver/__init__.py +0 -0
- tests/container/resolver/test_resolver.py +55 -0
- tests/container/test_container.py +254 -0
- tests/container/test_singleton.py +98 -0
- tests/container/test_thread_safety.py +217 -0
- tests/container/validators/__init__.py +0 -0
- tests/container/validators/test_implements.py +140 -0
- tests/container/validators/test_is_abstract_class.py +99 -0
- tests/container/validators/test_is_callable.py +73 -0
- tests/container/validators/test_is_concrete_class.py +97 -0
- tests/container/validators/test_is_instance.py +105 -0
- tests/container/validators/test_is_not_subclass.py +117 -0
- tests/container/validators/test_is_subclass.py +115 -0
- tests/container/validators/test_is_valid_alias.py +113 -0
- tests/container/validators/test_lifetime.py +75 -0
- tests/example/test_example.py +2 -2
- tests/foundation/config/testing/test_foundation_config_testing.py +1 -1
- tests/metadata/test_metadata_framework.py +89 -24
- tests/metadata/test_metadata_package.py +55 -10
- tests/services/asynchrony/test_services_asynchrony_coroutine.py +52 -7
- tests/services/system/test_services_system_imports.py +119 -16
- tests/services/system/test_services_system_workers.py +71 -30
- tests/testing/test_testing_result.py +117 -117
- tests/testing/test_testing_unit.py +209 -209
- orionis/foundation/config/base.py +0 -112
- orionis/test/arguments/parser.py +0 -187
- orionis/test/contracts/parser.py +0 -43
- orionis/test/entities/arguments.py +0 -38
- orionis/test/enums/execution_mode.py +0 -16
- /orionis/{test/arguments → console/base/contracts}/__init__.py +0 -0
- /orionis/foundation/config/testing/enums/{test_mode.py → mode.py} +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/WHEEL +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/top_level.txt +0 -0
- {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/zip-safe +0 -0
|
@@ -3,15 +3,37 @@ from orionis.console.output.contracts.console import IConsole
|
|
|
3
3
|
from orionis.container.providers.service_provider import ServiceProvider
|
|
4
4
|
|
|
5
5
|
class ConsoleProvider(ServiceProvider):
|
|
6
|
+
"""
|
|
7
|
+
ConsoleProvider
|
|
8
|
+
===============
|
|
9
|
+
|
|
10
|
+
Registers the console output service in the application container.
|
|
11
|
+
Provides access to various console output features, including information, warnings, errors, debug messages, tables, confirmations, and password prompts.
|
|
12
|
+
|
|
13
|
+
Methods
|
|
14
|
+
-------
|
|
15
|
+
register()
|
|
16
|
+
Registers the console service in the application container.
|
|
17
|
+
boot()
|
|
18
|
+
Performs post-registration initialization if needed.
|
|
19
|
+
"""
|
|
6
20
|
|
|
7
21
|
def register(self) -> None:
|
|
8
22
|
"""
|
|
9
|
-
|
|
23
|
+
Registers the console service in the application container.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
10
28
|
"""
|
|
11
29
|
self.app.transient(IConsole, Console, alias="core.orionis.console")
|
|
12
30
|
|
|
13
31
|
def boot(self) -> None:
|
|
14
32
|
"""
|
|
15
|
-
|
|
33
|
+
Performs post-registration initialization if needed.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
None
|
|
16
38
|
"""
|
|
17
39
|
pass
|
|
@@ -3,15 +3,37 @@ from orionis.console.dumper.contracts.dump import IDebug
|
|
|
3
3
|
from orionis.container.providers.service_provider import ServiceProvider
|
|
4
4
|
|
|
5
5
|
class DumperProvider(ServiceProvider):
|
|
6
|
+
"""
|
|
7
|
+
DumperProvider
|
|
8
|
+
==============
|
|
9
|
+
|
|
10
|
+
Registers the debug message service in the application container.
|
|
11
|
+
Provides access to debug message printing, error reporting, and other console diagnostics.
|
|
12
|
+
|
|
13
|
+
Methods
|
|
14
|
+
-------
|
|
15
|
+
register()
|
|
16
|
+
Registers the debug service in the application container.
|
|
17
|
+
boot()
|
|
18
|
+
Performs post-registration initialization if needed.
|
|
19
|
+
"""
|
|
6
20
|
|
|
7
21
|
def register(self) -> None:
|
|
8
22
|
"""
|
|
9
|
-
|
|
23
|
+
Registers the debug service in the application container.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
10
28
|
"""
|
|
11
29
|
self.app.transient(IDebug, Debug, alias="core.orionis.dumper")
|
|
12
30
|
|
|
13
31
|
def boot(self) -> None:
|
|
14
32
|
"""
|
|
15
|
-
|
|
33
|
+
Performs post-registration initialization if needed.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
None
|
|
16
38
|
"""
|
|
17
39
|
pass
|
|
@@ -3,15 +3,37 @@ from orionis.services.log.contracts.log_service import ILoggerService
|
|
|
3
3
|
from orionis.services.log.log_service import LoggerService
|
|
4
4
|
|
|
5
5
|
class LoggerProvider(ServiceProvider):
|
|
6
|
+
"""
|
|
7
|
+
LoggerProvider
|
|
8
|
+
==============
|
|
9
|
+
|
|
10
|
+
Registers the logging service in the application container.
|
|
11
|
+
Provides a `LoggerService` instance for application-wide logging.
|
|
12
|
+
|
|
13
|
+
Methods
|
|
14
|
+
-------
|
|
15
|
+
register()
|
|
16
|
+
Registers the logging service in the application container.
|
|
17
|
+
boot()
|
|
18
|
+
Performs post-registration initialization if needed.
|
|
19
|
+
"""
|
|
6
20
|
|
|
7
21
|
def register(self) -> None:
|
|
8
22
|
"""
|
|
9
|
-
|
|
23
|
+
Registers the logging service in the application container.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
10
28
|
"""
|
|
11
29
|
self.app.instance(ILoggerService, LoggerService(self.app.config('logging')), alias="core.orionis.logger")
|
|
12
30
|
|
|
13
31
|
def boot(self) -> None:
|
|
14
32
|
"""
|
|
15
|
-
|
|
33
|
+
Performs post-registration initialization if needed.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
None
|
|
16
38
|
"""
|
|
17
39
|
pass
|
|
@@ -3,15 +3,38 @@ from orionis.services.paths.contracts.resolver import IResolver
|
|
|
3
3
|
from orionis.services.paths.resolver import Resolver
|
|
4
4
|
|
|
5
5
|
class PathResolverProvider(ServiceProvider):
|
|
6
|
+
"""
|
|
7
|
+
PathResolverProvider
|
|
8
|
+
===================
|
|
9
|
+
|
|
10
|
+
Registers the path resolution service in the application container.
|
|
11
|
+
Provides compatibility with the file system for resolving paths.
|
|
12
|
+
|
|
13
|
+
Methods
|
|
14
|
+
-------
|
|
15
|
+
register()
|
|
16
|
+
Registers the path resolver service in the application container.
|
|
17
|
+
boot()
|
|
18
|
+
Performs post-registration initialization if needed.
|
|
19
|
+
"""
|
|
20
|
+
|
|
6
21
|
|
|
7
22
|
def register(self) -> None:
|
|
8
23
|
"""
|
|
9
|
-
|
|
24
|
+
Registers the path resolver service in the application container.
|
|
25
|
+
|
|
26
|
+
Returns
|
|
27
|
+
-------
|
|
28
|
+
None
|
|
10
29
|
"""
|
|
11
30
|
self.app.transient(IResolver, Resolver, alias="core.orionis.path_resolver")
|
|
12
31
|
|
|
13
32
|
def boot(self) -> None:
|
|
14
33
|
"""
|
|
15
|
-
|
|
34
|
+
Performs post-registration initialization if needed.
|
|
35
|
+
|
|
36
|
+
Returns
|
|
37
|
+
-------
|
|
38
|
+
None
|
|
16
39
|
"""
|
|
17
40
|
pass
|
|
@@ -3,15 +3,37 @@ from orionis.console.dynamic.progress_bar import ProgressBar
|
|
|
3
3
|
from orionis.container.providers.service_provider import ServiceProvider
|
|
4
4
|
|
|
5
5
|
class ProgressBarProvider(ServiceProvider):
|
|
6
|
+
"""
|
|
7
|
+
ProgressBarProvider
|
|
8
|
+
===================
|
|
9
|
+
|
|
10
|
+
Registers the dynamic progress bar service in the application container.
|
|
11
|
+
Provides a console progress bar for visual feedback during operations.
|
|
12
|
+
|
|
13
|
+
Methods
|
|
14
|
+
-------
|
|
15
|
+
register()
|
|
16
|
+
Registers the progress bar service in the application container.
|
|
17
|
+
boot()
|
|
18
|
+
Performs post-registration initialization if needed.
|
|
19
|
+
"""
|
|
6
20
|
|
|
7
21
|
def register(self) -> None:
|
|
8
22
|
"""
|
|
9
|
-
|
|
23
|
+
Registers the progress bar service in the application container.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
10
28
|
"""
|
|
11
29
|
self.app.transient(IProgressBar, ProgressBar, alias="core.orionis.progress_bar")
|
|
12
30
|
|
|
13
31
|
def boot(self) -> None:
|
|
14
32
|
"""
|
|
15
|
-
|
|
33
|
+
Performs post-registration initialization if needed.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
None
|
|
16
38
|
"""
|
|
17
39
|
pass
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
from orionis.container.providers.service_provider import ServiceProvider
|
|
2
|
+
from orionis.test.contracts.unit_test import IUnitTest
|
|
3
|
+
from orionis.test.core.unit_test import UnitTest
|
|
4
|
+
|
|
5
|
+
class TestingProvider(ServiceProvider):
|
|
6
|
+
"""
|
|
7
|
+
TestingProvider
|
|
8
|
+
===============
|
|
9
|
+
|
|
10
|
+
Registers the unit testing environment service in the application container.
|
|
11
|
+
Provides a native unit testing framework for Orionis with features beyond common frameworks.
|
|
12
|
+
|
|
13
|
+
Methods
|
|
14
|
+
-------
|
|
15
|
+
register()
|
|
16
|
+
Registers the unit testing service in the application container.
|
|
17
|
+
boot()
|
|
18
|
+
Performs post-registration initialization if needed.
|
|
19
|
+
"""
|
|
20
|
+
|
|
21
|
+
def register(self) -> None:
|
|
22
|
+
"""
|
|
23
|
+
Registers the unit testing service in the application container.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
28
|
+
"""
|
|
29
|
+
self.app.singleton(IUnitTest, UnitTest, alias="core.orionis.testing")
|
|
30
|
+
|
|
31
|
+
def boot(self) -> None:
|
|
32
|
+
"""
|
|
33
|
+
Performs post-registration initialization if needed.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
None
|
|
38
|
+
"""
|
|
39
|
+
pass
|
|
@@ -3,15 +3,37 @@ from orionis.services.system.contracts.workers import IWorkers
|
|
|
3
3
|
from orionis.services.system.workers import Workers
|
|
4
4
|
|
|
5
5
|
class WorkersProvider(ServiceProvider):
|
|
6
|
+
"""
|
|
7
|
+
WorkersProvider
|
|
8
|
+
===============
|
|
9
|
+
|
|
10
|
+
Registers the worker management service in the application container.
|
|
11
|
+
Determines the optimal number of workers to start based on system analysis.
|
|
12
|
+
|
|
13
|
+
Methods
|
|
14
|
+
-------
|
|
15
|
+
register()
|
|
16
|
+
Registers the worker service in the application container.
|
|
17
|
+
boot()
|
|
18
|
+
Performs post-registration initialization if needed.
|
|
19
|
+
"""
|
|
6
20
|
|
|
7
21
|
def register(self) -> None:
|
|
8
22
|
"""
|
|
9
|
-
|
|
23
|
+
Registers the worker service in the application container.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
10
28
|
"""
|
|
11
29
|
self.app.transient(IWorkers, Workers, alias="core.orionis.workers")
|
|
12
30
|
|
|
13
31
|
def boot(self) -> None:
|
|
14
32
|
"""
|
|
15
|
-
|
|
33
|
+
Performs post-registration initialization if needed.
|
|
34
|
+
|
|
35
|
+
Returns
|
|
36
|
+
-------
|
|
37
|
+
None
|
|
16
38
|
"""
|
|
17
39
|
pass
|
orionis/metadata/framework.py
CHANGED
|
@@ -9,16 +9,24 @@ class ICoroutine(ABC):
|
|
|
9
9
|
@abstractmethod
|
|
10
10
|
def run(self) -> Union[T, asyncio.Future]:
|
|
11
11
|
"""
|
|
12
|
-
|
|
12
|
+
Executes the wrapped coroutine, either synchronously or asynchronously depending on the context.
|
|
13
|
+
|
|
14
|
+
Parameters
|
|
15
|
+
----------
|
|
16
|
+
None
|
|
13
17
|
|
|
14
18
|
Returns
|
|
15
19
|
-------
|
|
16
|
-
|
|
17
|
-
|
|
20
|
+
T or asyncio.Future
|
|
21
|
+
If called outside an event loop, returns the result of the coroutine execution (type T).
|
|
22
|
+
If called within an event loop, returns an asyncio.Future representing the scheduled coroutine.
|
|
18
23
|
|
|
19
24
|
Notes
|
|
20
25
|
-----
|
|
21
|
-
-
|
|
22
|
-
-
|
|
26
|
+
- When invoked outside of an event loop, the coroutine is executed synchronously and its result is returned.
|
|
27
|
+
- When invoked inside an event loop, the coroutine is scheduled for asynchronous execution and a Future is returned.
|
|
28
|
+
- The caller is responsible for awaiting the Future if asynchronous execution is used.
|
|
23
29
|
"""
|
|
30
|
+
|
|
31
|
+
# This method should be implemented by subclasses to handle coroutine execution.
|
|
24
32
|
pass
|
|
@@ -7,20 +7,6 @@ from orionis.services.introspection.objects.types import Type
|
|
|
7
7
|
T = TypeVar("T")
|
|
8
8
|
|
|
9
9
|
class Coroutine(ICoroutine):
|
|
10
|
-
"""
|
|
11
|
-
Wrapper class for coroutine objects to facilitate execution in both synchronous
|
|
12
|
-
and asynchronous contexts.
|
|
13
|
-
|
|
14
|
-
Parameters
|
|
15
|
-
----------
|
|
16
|
-
func : Coroutine
|
|
17
|
-
The coroutine object to be wrapped.
|
|
18
|
-
|
|
19
|
-
Raises
|
|
20
|
-
------
|
|
21
|
-
OrionisCoroutineException
|
|
22
|
-
If the provided object is not a coroutine.
|
|
23
|
-
"""
|
|
24
10
|
|
|
25
11
|
def __init__(self, func: TypingCoroutine[Any, Any, T]) -> None:
|
|
26
12
|
"""
|
|
@@ -29,51 +15,69 @@ class Coroutine(ICoroutine):
|
|
|
29
15
|
Parameters
|
|
30
16
|
----------
|
|
31
17
|
func : Coroutine
|
|
32
|
-
The coroutine object to be wrapped.
|
|
18
|
+
The coroutine object to be wrapped. Must be an awaitable coroutine.
|
|
33
19
|
|
|
34
20
|
Raises
|
|
35
21
|
------
|
|
36
22
|
OrionisCoroutineException
|
|
37
23
|
If the provided object is not a coroutine.
|
|
24
|
+
|
|
25
|
+
Returns
|
|
26
|
+
-------
|
|
27
|
+
None
|
|
28
|
+
This method does not return a value.
|
|
29
|
+
|
|
30
|
+
Notes
|
|
31
|
+
-----
|
|
32
|
+
This constructor validates that the provided object is a coroutine using the framework's type introspection.
|
|
33
|
+
If the validation fails, an exception is raised to prevent improper usage.
|
|
38
34
|
"""
|
|
35
|
+
# Validate that the provided object is a coroutine
|
|
39
36
|
if not Type(func).isCoroutine():
|
|
40
37
|
raise OrionisCoroutineException(
|
|
41
38
|
f"Expected a coroutine object, but got {type(func).__name__}."
|
|
42
39
|
)
|
|
43
40
|
|
|
44
|
-
# Store the coroutine
|
|
41
|
+
# Store the coroutine object for later execution
|
|
45
42
|
self.__func = func
|
|
46
43
|
|
|
47
44
|
def run(self) -> Union[T, asyncio.Future]:
|
|
48
45
|
"""
|
|
49
|
-
|
|
46
|
+
Executes the wrapped coroutine, either synchronously or asynchronously depending on the context.
|
|
47
|
+
|
|
48
|
+
Parameters
|
|
49
|
+
----------
|
|
50
|
+
None
|
|
50
51
|
|
|
51
52
|
Returns
|
|
52
53
|
-------
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
T or asyncio.Future
|
|
55
|
+
If called outside an event loop, returns the result of the coroutine after synchronous execution.
|
|
56
|
+
If called within an event loop, returns an asyncio.Future representing the scheduled coroutine.
|
|
57
|
+
|
|
58
|
+
Raises
|
|
59
|
+
------
|
|
60
|
+
RuntimeError
|
|
61
|
+
If the coroutine cannot be executed due to event loop issues.
|
|
55
62
|
|
|
56
63
|
Notes
|
|
57
64
|
-----
|
|
58
|
-
-
|
|
59
|
-
-
|
|
65
|
+
- When invoked outside an active event loop, the coroutine is executed synchronously and its result is returned.
|
|
66
|
+
- When invoked inside an active event loop, the coroutine is scheduled for asynchronous execution and a Future is returned.
|
|
67
|
+
- This method automatically detects the execution context and chooses the appropriate execution strategy.
|
|
60
68
|
"""
|
|
69
|
+
# Attempt to get the currently running event loop
|
|
61
70
|
try:
|
|
62
|
-
|
|
63
|
-
# Get the current event loop
|
|
64
71
|
loop = asyncio.get_running_loop()
|
|
65
72
|
|
|
73
|
+
# No running event loop; execute the coroutine synchronously and return its result
|
|
66
74
|
except RuntimeError:
|
|
67
|
-
|
|
68
|
-
# No running event loop, run synchronously
|
|
69
75
|
return asyncio.run(self.__func)
|
|
70
76
|
|
|
77
|
+
# If inside an active event loop, schedule the coroutine and return a Future
|
|
71
78
|
if loop.is_running():
|
|
72
|
-
|
|
73
|
-
# Inside an event loop, schedule as a Future
|
|
74
79
|
return asyncio.ensure_future(self.__func)
|
|
75
80
|
|
|
81
|
+
# If no event loop is running, execute the coroutine synchronously using the loop
|
|
76
82
|
else:
|
|
77
|
-
|
|
78
|
-
# No running loop, run synchronously
|
|
79
83
|
return loop.run_until_complete(self.__func)
|
|
@@ -2,18 +2,26 @@ class OrionisCoroutineException(Exception):
|
|
|
2
2
|
|
|
3
3
|
def __init__(self, msg: str):
|
|
4
4
|
"""
|
|
5
|
+
Initializes an OrionisCoroutineException with a descriptive error message.
|
|
6
|
+
|
|
5
7
|
Parameters
|
|
6
8
|
----------
|
|
7
9
|
msg : str
|
|
8
10
|
Descriptive error message explaining the cause of the exception.
|
|
9
11
|
"""
|
|
12
|
+
|
|
13
|
+
# Call the base Exception constructor with the provided message
|
|
10
14
|
super().__init__(msg)
|
|
11
15
|
|
|
12
16
|
def __str__(self) -> str:
|
|
13
17
|
"""
|
|
18
|
+
Returns a formatted string representation of the exception message.
|
|
19
|
+
|
|
14
20
|
Returns
|
|
15
21
|
-------
|
|
16
22
|
str
|
|
17
|
-
|
|
23
|
+
The error message provided during exception initialization.
|
|
18
24
|
"""
|
|
25
|
+
|
|
26
|
+
# Return the first argument passed to the Exception, which is the error message
|
|
19
27
|
return str(self.args[0])
|
|
@@ -5,6 +5,9 @@ import threading
|
|
|
5
5
|
from pathlib import Path
|
|
6
6
|
from typing import Any, Optional, Union
|
|
7
7
|
from dotenv import dotenv_values, load_dotenv, set_key, unset_key
|
|
8
|
+
from orionis.services.environment.enums.cast_type import EnvCastType
|
|
9
|
+
from orionis.services.environment.validators.key_name import ValidateKeyName
|
|
10
|
+
from orionis.services.environment.validators.types import ValidateTypes
|
|
8
11
|
from orionis.support.patterns.singleton import Singleton
|
|
9
12
|
from orionis.services.environment.exceptions import OrionisEnvironmentValueException, OrionisEnvironmentValueError
|
|
10
13
|
from orionis.services.environment.dynamic.types import EnvTypes
|
|
@@ -16,33 +19,56 @@ class DotEnv(metaclass=Singleton):
|
|
|
16
19
|
|
|
17
20
|
def __init__(self, path: str = None) -> None:
|
|
18
21
|
"""
|
|
19
|
-
Initialize the
|
|
20
|
-
|
|
22
|
+
Initialize the DotEnv service by resolving and preparing the `.env` file.
|
|
23
|
+
|
|
24
|
+
This method determines the path to the `.env` file, ensures its existence,
|
|
25
|
+
and loads environment variables from it into the current process environment.
|
|
21
26
|
|
|
22
27
|
Parameters
|
|
23
28
|
----------
|
|
24
29
|
path : str, optional
|
|
25
|
-
|
|
30
|
+
The path to the `.env` file. If not provided, defaults to a `.env` file
|
|
26
31
|
in the current working directory.
|
|
27
32
|
|
|
33
|
+
Returns
|
|
34
|
+
-------
|
|
35
|
+
None
|
|
36
|
+
This method does not return any value.
|
|
37
|
+
|
|
28
38
|
Raises
|
|
29
39
|
------
|
|
30
40
|
OSError
|
|
31
|
-
If the `.env` file cannot be created
|
|
41
|
+
If the `.env` file cannot be created or accessed.
|
|
42
|
+
|
|
43
|
+
Notes
|
|
44
|
+
-----
|
|
45
|
+
- If the specified `.env` file does not exist, it will be created.
|
|
46
|
+
- Environment variables from the `.env` file are loaded into the process environment.
|
|
32
47
|
"""
|
|
48
|
+
|
|
33
49
|
try:
|
|
50
|
+
|
|
51
|
+
# Use a thread-safe lock to ensure only one thread can execute this block at a time
|
|
34
52
|
with self._lock:
|
|
53
|
+
|
|
54
|
+
# Defualt Environment file path
|
|
55
|
+
self.__resolved_path = Path(os.getcwd()) / ".env"
|
|
56
|
+
|
|
57
|
+
# If a path is provided, resolve it
|
|
35
58
|
if path:
|
|
36
|
-
self.
|
|
37
|
-
|
|
38
|
-
|
|
59
|
+
self.__resolved_path = Path(path).expanduser().resolve()
|
|
60
|
+
|
|
61
|
+
# Create the .env file if it does not exist
|
|
62
|
+
if not self.__resolved_path.exists():
|
|
63
|
+
self.__resolved_path.touch()
|
|
39
64
|
|
|
40
|
-
|
|
41
|
-
|
|
65
|
+
# Load environment variables from the .env file into the process environment
|
|
66
|
+
load_dotenv(self.__resolved_path)
|
|
42
67
|
|
|
43
|
-
load_dotenv(self._resolved_path)
|
|
44
68
|
except OSError as e:
|
|
45
|
-
|
|
69
|
+
|
|
70
|
+
# Raise an error if the .env file cannot be created or accessed
|
|
71
|
+
raise OSError(f"Failed to create or access the .env file at {self.__resolved_path}: {e}")
|
|
46
72
|
|
|
47
73
|
def __parseValue(self, value: Any) -> Any:
|
|
48
74
|
"""
|
|
@@ -172,7 +198,7 @@ class DotEnv(metaclass=Singleton):
|
|
|
172
198
|
)
|
|
173
199
|
|
|
174
200
|
# Get the value from the .env file or the current environment.
|
|
175
|
-
value = dotenv_values(self.
|
|
201
|
+
value = dotenv_values(self.__resolved_path).get(key)
|
|
176
202
|
|
|
177
203
|
# If the value is not found in the .env file, check the current environment variables.
|
|
178
204
|
if value is None:
|
|
@@ -181,7 +207,7 @@ class DotEnv(metaclass=Singleton):
|
|
|
181
207
|
# Parse the value using the internal __parseValue method and return it
|
|
182
208
|
return self.__parseValue(value) if value is not None else default
|
|
183
209
|
|
|
184
|
-
def set(self, key: str, value: Union[str, int, float, bool, list, dict, tuple, set], type_hint: str = None) -> bool:
|
|
210
|
+
def set(self, key: str, value: Union[str, int, float, bool, list, dict, tuple, set], type_hint: str | EnvCastType = None) -> bool:
|
|
185
211
|
"""
|
|
186
212
|
Set an environment variable with the specified key and value.
|
|
187
213
|
|
|
@@ -203,32 +229,18 @@ class DotEnv(metaclass=Singleton):
|
|
|
203
229
|
"""
|
|
204
230
|
with self._lock:
|
|
205
231
|
|
|
206
|
-
# Ensure
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
f"The environment variable name '{key}' is not valid. It must be an uppercase string, may contain numbers and underscores, and must always start with a letter. Example of a valid name: 'MY_ENV_VAR'."
|
|
210
|
-
)
|
|
211
|
-
|
|
212
|
-
# Ensure the value is a valid type.
|
|
213
|
-
if not isinstance(value, (str, int, float, bool, list, dict, tuple, set)):
|
|
214
|
-
raise OrionisEnvironmentValueError(
|
|
215
|
-
f"Unsupported value type: {type(value).__name__}. Allowed types are str, int, float, bool, list, dict, tuple, set."
|
|
216
|
-
)
|
|
232
|
+
# Ensure name key is valid.
|
|
233
|
+
key = ValidateKeyName(key)
|
|
234
|
+
type = ValidateTypes(value, type_hint)
|
|
217
235
|
|
|
218
|
-
# Dinamically determine the type hint if not provided.
|
|
219
|
-
if isinstance(value, (int, float, bool, list, dict, tuple, set)) and not type_hint:
|
|
220
|
-
type_hint = type(value).__name__.lower()
|
|
221
236
|
|
|
222
|
-
# Validate the type hint if provided.
|
|
223
|
-
options = EnvTypes.options()
|
|
224
|
-
if type_hint and type_hint not in options:
|
|
225
|
-
raise OrionisEnvironmentValueException(f"Invalid type hint: {type_hint}. Allowed types are {str(options)}.")
|
|
226
237
|
|
|
238
|
+
|
|
227
239
|
# Serialize the value based on its type.
|
|
228
240
|
serialized_value = self.__serializeValue(value, type_hint)
|
|
229
241
|
|
|
230
242
|
# Set the environment variable in the .env file and the current process environment.
|
|
231
|
-
set_key(str(self.
|
|
243
|
+
set_key(str(self.__resolved_path), key, serialized_value)
|
|
232
244
|
os.environ[key] = str(value)
|
|
233
245
|
|
|
234
246
|
# Return True to indicate success.
|
|
@@ -249,7 +261,7 @@ class DotEnv(metaclass=Singleton):
|
|
|
249
261
|
True if the operation was successful.
|
|
250
262
|
"""
|
|
251
263
|
with self._lock:
|
|
252
|
-
unset_key(str(self.
|
|
264
|
+
unset_key(str(self.__resolved_path), key)
|
|
253
265
|
os.environ.pop(key, None)
|
|
254
266
|
return True
|
|
255
267
|
|
|
@@ -264,5 +276,5 @@ class DotEnv(metaclass=Singleton):
|
|
|
264
276
|
with values parsed using the internal __parseValue method.
|
|
265
277
|
"""
|
|
266
278
|
with self._lock:
|
|
267
|
-
raw_values = dotenv_values(self.
|
|
279
|
+
raw_values = dotenv_values(self.__resolved_path)
|
|
268
280
|
return {k: self.__parseValue(v) for k, v in raw_values.items()}
|
|
File without changes
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
from enum import Enum
|
|
2
|
+
|
|
3
|
+
class EnvCastType(Enum):
|
|
4
|
+
"""
|
|
5
|
+
Enum representing supported environment variable cast types.
|
|
6
|
+
|
|
7
|
+
Attributes
|
|
8
|
+
----------
|
|
9
|
+
PATH : EnvCastType
|
|
10
|
+
Cast to a file system path.
|
|
11
|
+
STR : EnvCastType
|
|
12
|
+
Cast to a string.
|
|
13
|
+
INT : EnvCastType
|
|
14
|
+
Cast to an integer.
|
|
15
|
+
FLOAT : EnvCastType
|
|
16
|
+
Cast to a floating-point number.
|
|
17
|
+
BOOL : EnvCastType
|
|
18
|
+
Cast to a boolean value.
|
|
19
|
+
LIST : EnvCastType
|
|
20
|
+
Cast to a list.
|
|
21
|
+
DICT : EnvCastType
|
|
22
|
+
Cast to a dictionary.
|
|
23
|
+
TUPLE : EnvCastType
|
|
24
|
+
Cast to a tuple.
|
|
25
|
+
SET : EnvCastType
|
|
26
|
+
Cast to a set.
|
|
27
|
+
|
|
28
|
+
Returns
|
|
29
|
+
-------
|
|
30
|
+
EnvCastType
|
|
31
|
+
An enumeration member representing the desired cast type.
|
|
32
|
+
"""
|
|
33
|
+
|
|
34
|
+
PATH = 'path' # Represents a file system path
|
|
35
|
+
STR = 'str' # Represents a string type
|
|
36
|
+
INT = 'int' # Represents an integer type
|
|
37
|
+
FLOAT = 'float' # Represents a floating-point type
|
|
38
|
+
BOOL = 'bool' # Represents a boolean type
|
|
39
|
+
LIST = 'list' # Represents a list type
|
|
40
|
+
DICT = 'dict' # Represents a dictionary type
|
|
41
|
+
TUPLE = 'tuple' # Represents a tuple type
|
|
42
|
+
SET = 'set' # Represents a set type
|
|
File without changes
|