orionis 0.245.0__py3-none-any.whl → 0.247.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.
Files changed (108) hide show
  1. orionis/framework.py +1 -1
  2. orionis/luminate/config/app/__init__.py +10 -0
  3. orionis/luminate/config/app/entities/app.py +205 -0
  4. orionis/luminate/config/app/enums/ciphers.py +34 -0
  5. orionis/luminate/config/app/enums/environments.py +15 -0
  6. orionis/luminate/config/auth/__init__.py +7 -0
  7. orionis/luminate/config/auth/entities/auth.py +11 -0
  8. orionis/luminate/config/cache/__init__.py +9 -0
  9. orionis/luminate/config/cache/entities/cache.py +58 -0
  10. orionis/luminate/config/cache/entities/file.py +29 -0
  11. orionis/luminate/config/cache/entities/stores.py +35 -0
  12. orionis/luminate/config/cache/enums/drivers.py +12 -0
  13. orionis/luminate/config/contracts/config.py +27 -0
  14. orionis/luminate/config/entities/testing.py +215 -0
  15. orionis/luminate/config/exceptions/integrity_exception.py +30 -0
  16. orionis/luminate/console/dumper/dump_die.py +418 -0
  17. orionis/luminate/contracts/facades/commands/scheduler_facade.py +1 -1
  18. orionis/luminate/facades/files/path_facade.py +1 -1
  19. orionis/luminate/patterns/__init__.py +4 -0
  20. orionis/luminate/patterns/singleton/__init__.py +10 -0
  21. orionis/luminate/patterns/singleton/meta_class.py +56 -0
  22. orionis/luminate/providers/commands/reactor_commands_service_provider.py +3 -3
  23. orionis/luminate/providers/commands/scheduler_provider.py +1 -1
  24. orionis/luminate/providers/config/config_service_provider.py +1 -1
  25. orionis/luminate/providers/environment/environment__service_provider.py +2 -2
  26. orionis/luminate/providers/files/paths_provider.py +1 -1
  27. orionis/luminate/providers/log/log_service_provider.py +2 -2
  28. orionis/luminate/services/environment/__init__.py +10 -0
  29. orionis/luminate/services/environment/contracts/__init__.py +5 -0
  30. orionis/luminate/services/environment/contracts/env.py +93 -0
  31. orionis/luminate/services/environment/dot_env.py +293 -0
  32. orionis/luminate/services/environment/env.py +77 -0
  33. orionis/luminate/services/paths/__init__.py +9 -0
  34. orionis/luminate/services/paths/contracts/__init__.py +0 -0
  35. orionis/luminate/services/paths/contracts/resolver.py +67 -0
  36. orionis/luminate/services/paths/resolver.py +83 -0
  37. orionis/luminate/services/workers/__init__.py +10 -0
  38. orionis/luminate/services/workers/maximum_workers.py +36 -0
  39. orionis/luminate/services_/__init__.py +0 -0
  40. orionis/luminate/services_/commands/__init__.py +0 -0
  41. orionis/luminate/services_/config/__init__.py +0 -0
  42. orionis/luminate/services_/log/__init__.py +0 -0
  43. orionis/luminate/support/introspection/abstracts/entities/__init__.py +0 -0
  44. orionis/luminate/support/introspection/abstracts/entities/abstract_class_attributes.py +11 -0
  45. orionis/luminate/support/introspection/abstracts/reflect_abstract.py +154 -16
  46. orionis/luminate/support/introspection/instances/reflection_instance.py +2 -2
  47. orionis/luminate/test/__init__.py +11 -1
  48. orionis/luminate/test/cases/test_async.py +1 -10
  49. orionis/luminate/test/cases/test_case.py +8 -3
  50. orionis/luminate/test/cases/test_sync.py +1 -0
  51. orionis/luminate/test/core/contracts/test_suite.py +19 -31
  52. orionis/luminate/test/core/contracts/test_unit.py +103 -59
  53. orionis/luminate/test/core/test_suite.py +50 -42
  54. orionis/luminate/test/core/test_unit.py +756 -196
  55. orionis/luminate/test/entities/test_result.py +19 -18
  56. orionis/luminate/test/enums/test_mode.py +16 -0
  57. orionis/luminate/test/exceptions/test_config_exception.py +28 -0
  58. orionis/luminate/test/exceptions/test_exception.py +41 -34
  59. orionis/luminate/test/output/contracts/test_std_out.py +22 -11
  60. orionis/luminate/test/output/test_std_out.py +79 -48
  61. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/METADATA +4 -1
  62. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/RECORD +98 -61
  63. tests/config/__init__.py +0 -0
  64. tests/config/test_app.py +122 -0
  65. tests/config/test_auth.py +21 -0
  66. tests/config/test_cache.py +20 -0
  67. tests/patterns/__init__.py +0 -0
  68. tests/patterns/singleton/__init__.py +0 -0
  69. tests/patterns/singleton/test_singleton.py +18 -0
  70. tests/services/__init__.py +0 -0
  71. tests/services/environment/__init__.py +0 -0
  72. tests/services/environment/test_env.py +33 -0
  73. tests/support/inspection/fakes/fake_reflect_abstract.py +61 -5
  74. tests/support/inspection/test_reflect_abstract.py +62 -1
  75. tests/support/inspection/test_reflect_instance.py +0 -1
  76. orionis/luminate/config/app.py +0 -47
  77. orionis/luminate/config/auth.py +0 -15
  78. orionis/luminate/config/cache.py +0 -51
  79. orionis/luminate/support/environment/contracts/env.py +0 -68
  80. orionis/luminate/support/environment/env.py +0 -138
  81. orionis/luminate/support/environment/functions.py +0 -49
  82. orionis/luminate/support/environment/helper.py +0 -26
  83. orionis/luminate/support/patterns/singleton.py +0 -44
  84. tests/support/environment/test_env.py +0 -91
  85. tests/support/patterns/test_singleton.py +0 -18
  86. /orionis/luminate/{services/commands → config/app/entities}/__init__.py +0 -0
  87. /orionis/luminate/{services/config → config/app/enums}/__init__.py +0 -0
  88. /orionis/luminate/{services/log → config/auth/entities}/__init__.py +0 -0
  89. /orionis/luminate/{support/environment → config/cache/entities}/__init__.py +0 -0
  90. /orionis/luminate/{support/environment/contracts → config/cache/enums}/__init__.py +0 -0
  91. /orionis/luminate/{support/patterns → config/contracts}/__init__.py +0 -0
  92. /orionis/luminate/config/{cors.py → entities/cors.py} +0 -0
  93. /orionis/luminate/config/{database.py → entities/database.py} +0 -0
  94. /orionis/luminate/config/{filesystems.py → entities/filesystems.py} +0 -0
  95. /orionis/luminate/config/{logging.py → entities/logging.py} +0 -0
  96. /orionis/luminate/config/{mail.py → entities/mail.py} +0 -0
  97. /orionis/luminate/config/{queue.py → entities/queue.py} +0 -0
  98. /orionis/luminate/config/{session.py → entities/session.py} +0 -0
  99. {tests/support/environment → orionis/luminate/config/exceptions}/__init__.py +0 -0
  100. {tests/support/patterns → orionis/luminate/console/dumper}/__init__.py +0 -0
  101. /orionis/luminate/{services → services_}/commands/reactor_commands_service.py +0 -0
  102. /orionis/luminate/{services → services_}/commands/scheduler_service.py +0 -0
  103. /orionis/luminate/{services → services_}/config/config_service.py +0 -0
  104. /orionis/luminate/{services → services_}/log/log_service.py +0 -0
  105. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/LICENCE +0 -0
  106. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/WHEEL +0 -0
  107. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/entry_points.txt +0 -0
  108. {orionis-0.245.0.dist-info → orionis-0.247.0.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,10 @@
1
+ from orionis.luminate.patterns.singleton.meta_class import Singleton
2
+
3
+ __all__ = [
4
+ "Singleton",
5
+ ]
6
+ __author__ = "Raúl Mauricio Uñate Castro"
7
+ __description__ = (
8
+ "This module provides a singleton class to manage environment variables. "
9
+ "It allows setting, getting, and deleting environment variables."
10
+ )
@@ -0,0 +1,56 @@
1
+ import threading
2
+ import asyncio
3
+ from typing import Dict, Type, Any, TypeVar
4
+
5
+ T = TypeVar('T')
6
+
7
+ class Singleton(type):
8
+ """
9
+ Thread-safe + Async-safe singleton metaclass.
10
+ Works for both synchronous and asynchronous contexts.
11
+ """
12
+
13
+ _instances: Dict[Type[T], T] = {}
14
+ _lock = threading.Lock()
15
+ _async_lock = asyncio.Lock()
16
+
17
+ def __call__(cls: Type[T], *args: Any, **kwargs: Any) -> T:
18
+ """
19
+ Creates and returns a singleton instance of the class.
20
+
21
+ If an instance of the class does not already exist, this method acquires a lock to ensure thread safety,
22
+ creates a new instance using the provided arguments, and stores it in the class-level _instances dictionary.
23
+ Subsequent calls return the existing instance.
24
+
25
+ Args:
26
+ *args: Positional arguments to pass to the class constructor.
27
+ **kwargs: Keyword arguments to pass to the class constructor.
28
+
29
+ Returns:
30
+ T: The singleton instance of the class.
31
+ """
32
+ if cls not in cls._instances:
33
+ with cls._lock:
34
+ if cls not in cls._instances:
35
+ cls._instances[cls] = super().__call__(*args, **kwargs)
36
+ return cls._instances[cls]
37
+
38
+ async def __acall__(cls: Type[T], *args: Any, **kwargs: Any) -> T:
39
+ """
40
+ Asynchronously creates or retrieves a singleton instance of the class.
41
+
42
+ If an instance of the class does not exist, acquires an asynchronous lock to ensure thread safety,
43
+ creates the instance, and stores it. Subsequent calls return the existing instance.
44
+
45
+ Args:
46
+ *args: Positional arguments to pass to the class constructor.
47
+ **kwargs: Keyword arguments to pass to the class constructor.
48
+
49
+ Returns:
50
+ T: The singleton instance of the class.
51
+ """
52
+ if cls not in cls._instances:
53
+ async with cls._async_lock:
54
+ if cls not in cls._instances:
55
+ cls._instances[cls] = super().__call__(*args, **kwargs)
56
+ return cls._instances[cls]
@@ -2,9 +2,9 @@ from orionis.luminate.contracts.services.commands.reactor_commands_service impor
2
2
  from orionis.luminate.contracts.services.config.config_service import IConfigService
3
3
  from orionis.luminate.contracts.services.log.log_service import ILogguerService
4
4
  from orionis.luminate.providers.service_provider import ServiceProvider
5
- from orionis.luminate.services.commands.reactor_commands_service import ReactorCommandsService
6
- from orionis.luminate.services.config.config_service import ConfigService
7
- from orionis.luminate.services.log.log_service import LogguerService
5
+ from orionis.luminate.services_.commands.reactor_commands_service import ReactorCommandsService
6
+ from orionis.luminate.services_.config.config_service import ConfigService
7
+ from orionis.luminate.services_.log.log_service import LogguerService
8
8
 
9
9
  class ReactorCommandsServiceProvider(ServiceProvider):
10
10
 
@@ -1,6 +1,6 @@
1
1
  from orionis.luminate.contracts.services.commands.schedule_service import IScheduleService
2
2
  from orionis.luminate.providers.service_provider import ServiceProvider
3
- from orionis.luminate.services.commands.scheduler_service import ScheduleService
3
+ from orionis.luminate.services_.commands.scheduler_service import ScheduleService
4
4
 
5
5
  class ScheduleServiceProvider(ServiceProvider):
6
6
 
@@ -1,6 +1,6 @@
1
1
  from orionis.luminate.contracts.services.config.config_service import IConfigService
2
2
  from orionis.luminate.providers.service_provider import ServiceProvider
3
- from orionis.luminate.services.config.config_service import ConfigService
3
+ from orionis.luminate.services_.config.config_service import ConfigService
4
4
 
5
5
  class ConfigServiceProvider(ServiceProvider):
6
6
 
@@ -1,7 +1,7 @@
1
1
  from orionis.luminate.contracts.services.environment.environment_service import IEnvironmentService
2
2
  from orionis.luminate.providers.service_provider import ServiceProvider
3
- from orionis.luminate.services.environment.environment_service import EnvironmentService
4
- from orionis.luminate.services.files.path_resolver_service import PathResolverService
3
+ from orionis.luminate.services_.environment.environment_service import EnvironmentService
4
+ from orionis.luminate.services_.files.path_resolver_service import PathResolverService
5
5
 
6
6
  class EnvironmentServiceProvider(ServiceProvider):
7
7
 
@@ -1,6 +1,6 @@
1
1
  from orionis.luminate.contracts.services.files.path_resolver_service import IPathResolverService
2
2
  from orionis.luminate.providers.service_provider import ServiceProvider
3
- from orionis.luminate.services.files.path_resolver_service import PathResolverService
3
+ from orionis.luminate.services_.files.path_resolver_service import PathResolverService
4
4
 
5
5
  class PathResolverProvider(ServiceProvider):
6
6
 
@@ -1,8 +1,8 @@
1
1
  from orionis.luminate.contracts.services.config.config_service import IConfigService
2
2
  from orionis.luminate.contracts.services.log.log_service import ILogguerService
3
3
  from orionis.luminate.providers.service_provider import ServiceProvider
4
- from orionis.luminate.services.config.config_service import ConfigService
5
- from orionis.luminate.services.log.log_service import LogguerService
4
+ from orionis.luminate.services_.config.config_service import ConfigService
5
+ from orionis.luminate.services_.log.log_service import LogguerService
6
6
 
7
7
  class LogServiceProvider(ServiceProvider):
8
8
 
@@ -0,0 +1,10 @@
1
+ from orionis.luminate.services.environment.env import Env
2
+
3
+ __all__ = [
4
+ "Env",
5
+ ]
6
+ __author__ = "Raúl Mauricio Uñate Castro"
7
+ __description__ = (
8
+ "This module provides a singleton class to manage environment variables. "
9
+ "It allows setting, getting, and deleting environment variables."
10
+ )
@@ -0,0 +1,5 @@
1
+ from orionis.luminate.services.environment.dot_env import DotEnv
2
+
3
+ __all__ = [
4
+ "DotEnv",
5
+ ]
@@ -0,0 +1,93 @@
1
+ from typing import Any, Dict, Optional
2
+ from abc import ABC, abstractmethod
3
+
4
+ class IEnv(ABC):
5
+ """Interface contract for environment management operations."""
6
+
7
+ @staticmethod
8
+ @abstractmethod
9
+ def get(key: str, default: Optional[Any] = None) -> Any:
10
+ """
11
+ Retrieves an environment variable's value.
12
+
13
+ Args:
14
+ key: Environment variable name
15
+ default: Default value if key doesn't exist
16
+
17
+ Returns:
18
+ The parsed value or default if not found
19
+ """
20
+ pass
21
+
22
+ @staticmethod
23
+ @abstractmethod
24
+ def set(key: str, value: str) -> bool:
25
+ """
26
+ Sets an environment variable.
27
+
28
+ Args:
29
+ key: Environment variable name
30
+ value: Value to set
31
+
32
+ Returns:
33
+ True if successful, False otherwise
34
+ """
35
+ pass
36
+
37
+ @staticmethod
38
+ @abstractmethod
39
+ def unset(key: str) -> bool:
40
+ """
41
+ Removes an environment variable.
42
+
43
+ Args:
44
+ key: Environment variable name
45
+
46
+ Returns:
47
+ True if successful, False otherwise
48
+ """
49
+ pass
50
+
51
+ @staticmethod
52
+ @abstractmethod
53
+ def all() -> Dict[str, Any]:
54
+ """
55
+ Retrieves all environment variables.
56
+
57
+ Returns:
58
+ Dictionary of all key-value pairs
59
+ """
60
+ pass
61
+
62
+ @staticmethod
63
+ @abstractmethod
64
+ def destroy() -> bool:
65
+ """
66
+ Clears the entire environment.
67
+
68
+ Returns:
69
+ True if successful, False otherwise
70
+ """
71
+ pass
72
+
73
+ @staticmethod
74
+ @abstractmethod
75
+ def toJson() -> str:
76
+ """
77
+ Serializes environment to JSON.
78
+
79
+ Returns:
80
+ JSON string representation
81
+ """
82
+ pass
83
+
84
+ @staticmethod
85
+ @abstractmethod
86
+ def toBase64() -> str:
87
+ """
88
+ Encodes environment to Base64.
89
+
90
+ Returns:
91
+ Base64 encoded string
92
+ """
93
+ pass
@@ -0,0 +1,293 @@
1
+ import ast
2
+ import os
3
+ from pathlib import Path
4
+ from typing import Any, Optional, Union
5
+ from dotenv import dotenv_values, load_dotenv, set_key, unset_key
6
+ from orionis.luminate.patterns.singleton import Singleton
7
+
8
+ class DotEnv(metaclass=Singleton):
9
+ """
10
+ DotEnv is a singleton class for managing environment variables using a `.env` file.
11
+ This class provides methods to load, get, set, unset, and list environment variables,
12
+ with automatic serialization and deserialization of common Python data types.
13
+ It ensures that changes to the `.env` file are reflected in the current process's
14
+ environment variables and vice versa.
15
+ """
16
+
17
+ def __init__(self, path: str = None) -> None:
18
+ """
19
+ Initializes the environment service by resolving the path to the `.env` file, ensuring its existence,
20
+ and loading environment variables from it.
21
+ Args:
22
+ path (str, optional): The path to the `.env` file. If not provided, defaults to a `.env` file
23
+ in the current working directory.
24
+ Raises:
25
+ OSError: If the `.env` file cannot be created when it does not exist.
26
+ """
27
+
28
+ # Path to the `.env` file - If no path is provided, use the default path
29
+ if path:
30
+ self._resolved_path = Path(path).expanduser().resolve()
31
+ else:
32
+ self._resolved_path = Path(os.getcwd()) / ".env"
33
+
34
+ # Ensure that the `.env` file exists
35
+ if not self._resolved_path.exists():
36
+ self._resolved_path.touch()
37
+
38
+ # Load environment variables from the `.env` file
39
+ load_dotenv(self._resolved_path)
40
+
41
+ def destroy(self) -> bool:
42
+ """
43
+ Deletes the `.env` file at the resolved path.
44
+ Returns:
45
+ bool: True if the `.env` file was successfully deleted, False if the file did not exist.
46
+ """
47
+
48
+ # Deletes the `.env` file and returns True if it was successfully deleted.
49
+ if self._resolved_path.exists():
50
+ os.remove(self._resolved_path)
51
+ return True
52
+ return False
53
+
54
+ def get(self, key: str, default: Optional[Any] = None) -> Any:
55
+ """
56
+ Retrieve the value of an environment variable.
57
+ This method attempts to fetch the value of the specified environment variable `key`
58
+ from a `.env` file. If the variable is not found in the `.env` file, it falls back
59
+ to the system environment variables. If the variable is still not found, the provided
60
+ `default` value is returned.
61
+ Args:
62
+ key (str): The name of the environment variable to retrieve.
63
+ default (Optional[Any], optional): The value to return if the environment variable is not found. Defaults to None.
64
+ Returns:
65
+ Any: The value of the environment variable, parsed if found; otherwise, the `default` value.
66
+ """
67
+
68
+ # Gets the value of an environment variable from the `.env` file or from system environment variables.
69
+ value = dotenv_values(self._resolved_path).get(key)
70
+ if value is None:
71
+ value = os.getenv(key)
72
+
73
+ # If the value is not found, return the default value
74
+ return self.__parseValue(value) if value is not None else default
75
+
76
+ def set(self, key: str, value: Union[str, int, float, bool, list, dict]) -> bool:
77
+ """
78
+ Sets the value of an environment variable in both the `.env` file and the current system environment.
79
+ Args:
80
+ key (str): The name of the environment variable to set.
81
+ value (Union[str, int, float, bool, list, dict]): The value to assign to the environment variable.
82
+ The value will be serialized before being written to the `.env` file.
83
+ Notes:
84
+ - The value is serialized for storage in the `.env` file.
85
+ - The environment variable is also set in the current process's environment, making it immediately available.
86
+ """
87
+
88
+ # Serializes and sets the value of an environment variable in the `.env` file.
89
+ serialized_value = self.__serializeValue(value)
90
+
91
+ # Sets the value in the `.env` file
92
+ set_key(str(self._resolved_path), key, serialized_value)
93
+
94
+ # Also sets the value in the system environment variables
95
+ # so that it is available in the current environment.
96
+ # This is useful if you need to access the environment variable immediately
97
+ os.environ[key] = str(value)
98
+
99
+ # Return True to indicate that the operation was successful
100
+ return True
101
+
102
+ def unset(self, key: str) -> bool:
103
+ """
104
+ Removes an environment variable from both the `.env` file and the current system environment.
105
+ Args:
106
+ key (str): The name of the environment variable to remove.
107
+ This method updates the `.env` file by removing the specified key and also ensures
108
+ that the variable is no longer present in the current process's environment variables.
109
+ """
110
+
111
+ # Removes an environment variable from the `.env` file and from the system environment.
112
+ unset_key(str(self._resolved_path), key)
113
+
114
+ # Also removes the environment variable from the system
115
+ # so that it is not available in the current environment.
116
+ os.environ.pop(key, None)
117
+
118
+ # Return True to indicate that the operation was successful
119
+ return True
120
+
121
+ def all(self) -> dict:
122
+ """
123
+ Returns all environment variables from the `.env` file as a dictionary.
124
+
125
+ Reads the environment variables from the resolved `.env` file path, parses each value
126
+ using the `__parseValue` method, and returns a dictionary mapping variable names to their
127
+ parsed values.
128
+
129
+ Returns:
130
+ dict: A dictionary containing all environment variables and their parsed values.
131
+ """
132
+
133
+ # Returns all environment variables from the `.env` file as a dictionary,
134
+ # parsing the values using __parseValue.
135
+ raw_values = dotenv_values(self._resolved_path)
136
+ return {k: self.__parseValue(v) for k, v in raw_values.items()}
137
+
138
+ def toJson(self) -> str:
139
+ """
140
+ Converts the environment variables from the `.env` file into a JSON string.
141
+
142
+ This method retrieves all environment variables, parses their values using the
143
+ `__parseValue` method, and returns a JSON string representation of the resulting dictionary.
144
+
145
+ Returns:
146
+ str: A JSON string representing all environment variables and their parsed values.
147
+ """
148
+
149
+ # Converts the environment variables to a JSON string.
150
+ import json
151
+ return json.dumps(self.all(), indent=4)
152
+
153
+ def toBase64(self) -> str:
154
+ """
155
+ Converts the environment variables from the `.env` file into a Base64 encoded string.
156
+
157
+ This method retrieves all environment variables, parses their values using the
158
+ `__parseValue` method, and returns a Base64 encoded string representation of the resulting dictionary.
159
+
160
+ Returns:
161
+ str: A Base64 encoded string representing all environment variables and their parsed values.
162
+ """
163
+
164
+ # Converts the environment variables to a Base64 encoded string.
165
+ import base64
166
+ import json
167
+ return base64.b64encode(json.dumps(self.all()).encode()).decode()
168
+
169
+ def __parseValue(self, value: Any) -> Any:
170
+ """
171
+ Parses a given value and attempts to convert it into an appropriate Python data type.
172
+ The function handles the following conversions:
173
+ - Returns None for None, empty strings, or string representations of null values ('none', 'null', 'nan').
174
+ - Returns the value unchanged if it is already a primitive type (bool, int, float).
175
+ - Converts string representations of booleans ('true', 'false') to their respective boolean values.
176
+ - Converts string representations of integers and floats to their respective numeric types.
177
+ - Attempts to evaluate the string as a Python literal (e.g., lists, dicts, tuples).
178
+ - Returns the original string if no conversion is possible.
179
+ Args:
180
+ value (Any): The value to parse.
181
+ Returns:
182
+ Any: The parsed value in its appropriate Python data type, or the original string if no conversion is possible.
183
+ """
184
+
185
+ # Parses a string value into a Python data type.
186
+ if value is None:
187
+ return None
188
+
189
+ # If it is already a primitive type, return it
190
+ if isinstance(value, (bool, int, float)):
191
+ return value
192
+
193
+ value_str = str(value).strip()
194
+
195
+ # Special cases: empty or representations of None
196
+ if not value_str or value_str.lower() in {'none', 'null', 'nan'}:
197
+ return None
198
+
199
+ # Booleans
200
+ if value_str.lower() == 'true':
201
+ return True
202
+ if value_str.lower() == 'false':
203
+ return False
204
+
205
+ # Try to convert to int
206
+ try:
207
+ if value_str.isdigit() or (value_str.startswith('-') and value_str[1:].isdigit()):
208
+ return int(value_str)
209
+ except Exception:
210
+ pass
211
+
212
+ # Try to convert to float
213
+ try:
214
+ float_val = float(value_str)
215
+ # Avoid converting strings like '1e10' to float if it is not really a number
216
+ if '.' in value_str or 'e' in value_str.lower():
217
+ return float_val
218
+ except Exception:
219
+ pass
220
+
221
+ # Try to evaluate as Python literal (lists, dicts, etc.)
222
+ try:
223
+ return ast.literal_eval(value_str)
224
+ except Exception:
225
+ pass
226
+
227
+ # If all else fails, return the original string
228
+ return value_str
229
+
230
+ def __serializeValue(self, value: Any) -> str:
231
+ """
232
+ Serializes a Python value into a string suitable for storing in a `.env` file.
233
+ Supported types:
234
+ - None: serialized as the string "None"
235
+ - str: returned as-is
236
+ - bool: converted to "true" or "false"
237
+ - int, float: converted to their string representation
238
+ - list, dict: converted to their string representation using repr()
239
+ Raises:
240
+ TypeError: If the value is an instance of a custom class or an unsupported type (e.g., set, tuple).
241
+ Args:
242
+ value (Any): The value to serialize.
243
+ Returns:
244
+ str: The serialized string representation of the value.
245
+ """
246
+
247
+ # if it is None, return "None"
248
+ # This is useful to avoid problems when saving None in the .env file
249
+ if value is None:
250
+ return "None"
251
+
252
+ # If it is a string, return it as is
253
+ if isinstance(value, str):
254
+ return value
255
+
256
+ # If it is a boolean, convert it to string
257
+ if isinstance(value, bool):
258
+ return str(value).lower()
259
+
260
+ # If it is a number, convert it to string
261
+ if isinstance(value, int):
262
+ return str(value)
263
+
264
+ # If is a float, convert it to string
265
+ if isinstance(value, float):
266
+ value = str(value)
267
+ if 'e' in value or 'E' in value:
268
+ raise ValueError('scientific notation is not supported, use a string instead')
269
+ return value
270
+
271
+ # If it is a list or dictionary, convert them to string
272
+ if isinstance(value, (list, dict)):
273
+ return repr(value)
274
+
275
+ # If it is an object of a custom class, raise an error
276
+ # This is useful to avoid problems when saving class instances in the .env file
277
+ if hasattr(value, '__dict__'):
278
+ raise TypeError(f"Type {type(value).__name__} is not serializable for .env")
279
+
280
+ # If it is an unsupported data type, raise an error
281
+ # This is useful to avoid problems when saving unsupported data types in the .env file
282
+ # such as sets, tuples, etc.
283
+ if not isinstance(value, (list, dict, bool, int, float, str)):
284
+ raise TypeError(f"Type {type(value).__name__} is not serializable for .env")
285
+
286
+ # Serializes a Python data type into a string for storing in the `.env` file.
287
+ # Only allows simple serializable types and not class instances.
288
+ if isinstance(value, (list, dict, bool, int, float, str)):
289
+ # Prevent serializing instances of custom classes
290
+ if type(value).__module__ != "builtins" and not isinstance(value, str):
291
+ raise TypeError(f"Type {type(value).__name__} is not serializable for .env")
292
+ return repr(value) if not isinstance(value, str) else value
293
+ raise TypeError(f"Type {type(value).__name__} is not serializable for .env")
@@ -0,0 +1,77 @@
1
+ from orionis.luminate.services.environment.contracts.env import IEnv
2
+ from orionis.luminate.services.environment.dot_env import DotEnv
3
+ from typing import Any, Optional, Dict
4
+
5
+ def env(key: str, default: Any = None) -> Any:
6
+ """
7
+ Helper function to retrieve the value of an environment variable by key.
8
+ """
9
+ return DotEnv().get(key, default)
10
+
11
+ class Env(IEnv):
12
+ """
13
+ Env is a utility class that provides static methods for managing environment variables
14
+ using the DotEnv class. It allows getting, setting, unsetting, listing, destroying,
15
+ and serializing environment variables.
16
+ """
17
+
18
+ _dotenv_instance: Optional[DotEnv] = None
19
+
20
+ @classmethod
21
+ def _dotenv(cls) -> DotEnv:
22
+ if cls._dotenv_instance is None:
23
+ cls._dotenv_instance = DotEnv()
24
+ return cls._dotenv_instance
25
+
26
+ @staticmethod
27
+ def get(key: str, default: Any = None) -> Any:
28
+ """
29
+ Retrieve the value of an environment variable by key.
30
+ """
31
+ return Env._dotenv().get(key, default)
32
+
33
+ @staticmethod
34
+ def set(key: str, value: str) -> bool:
35
+ """
36
+ Sets the value of an environment variable.
37
+ """
38
+ return Env._dotenv().set(key, value)
39
+
40
+ @staticmethod
41
+ def unset(key: str) -> bool:
42
+ """
43
+ Removes the specified environment variable from the environment.
44
+ """
45
+ return Env._dotenv().unset(key)
46
+
47
+ @staticmethod
48
+ def all() -> Dict[str, Any]:
49
+ """
50
+ Retrieve all environment variables from the DotEnv instance.
51
+ """
52
+ return Env._dotenv().all()
53
+
54
+ @staticmethod
55
+ def destroy() -> bool:
56
+ """
57
+ Destroys the current environment by resetting the DotEnv instance.
58
+ """
59
+ if Env._dotenv_instance is not None:
60
+ result = Env._dotenv_instance.destroy()
61
+ Env._dotenv_instance = None
62
+ return result
63
+ return False
64
+
65
+ @staticmethod
66
+ def toJson() -> str:
67
+ """
68
+ Serializes the current environment variables managed by the DotEnv instance to a JSON-formatted string.
69
+ """
70
+ return Env._dotenv().toJson()
71
+
72
+ @staticmethod
73
+ def toBase64() -> str:
74
+ """
75
+ Converts the current environment variables to a Base64-encoded string.
76
+ """
77
+ return Env._dotenv().toBase64()
@@ -0,0 +1,9 @@
1
+ from orionis.luminate.services.paths.resolver import Resolver
2
+
3
+ __all__ = [
4
+ "Resolver",
5
+ ]
6
+ __author__ = "Raúl Mauricio Uñate Castro"
7
+ __description__ = (
8
+ "This module provides a Resolver class that is used to resolve paths in the Orionis Framework application. "
9
+ )
File without changes