orionis 0.285.0__py3-none-any.whl → 0.287.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 (67) hide show
  1. orionis/metadata/framework.py +1 -1
  2. orionis/services/asynchrony/contracts/__init__.py +0 -0
  3. orionis/services/asynchrony/contracts/coroutines.py +24 -0
  4. orionis/services/asynchrony/coroutines.py +58 -19
  5. orionis/services/asynchrony/exceptions/coroutine_exception.py +8 -15
  6. orionis/services/environment/contracts/env.py +45 -50
  7. orionis/services/environment/dot_env.py +205 -181
  8. orionis/services/environment/env.py +68 -85
  9. orionis/services/environment/exceptions/environment_value_error.py +18 -0
  10. orionis/services/environment/exceptions/environment_value_exception.py +23 -0
  11. orionis/services/environment/type_hint.py +559 -0
  12. orionis/test/exceptions/test_config_exception.py +8 -17
  13. orionis/test/exceptions/test_failure_exception.py +27 -27
  14. orionis/test/exceptions/test_persistence_error.py +10 -20
  15. orionis/test/exceptions/test_runtime_error.py +8 -15
  16. orionis/test/exceptions/test_value_error.py +8 -15
  17. orionis/test/logs/history.py +3 -5
  18. {orionis-0.285.0.dist-info → orionis-0.287.0.dist-info}/METADATA +1 -1
  19. {orionis-0.285.0.dist-info → orionis-0.287.0.dist-info}/RECORD +66 -62
  20. tests/example/test_example.py +5 -2
  21. tests/foundation/config/app/test_app.py +13 -3
  22. tests/foundation/config/auth/test_auth.py +9 -4
  23. tests/foundation/config/cache/test_cache.py +60 -15
  24. tests/foundation/config/cache/test_cache_file.py +62 -14
  25. tests/foundation/config/cache/test_cache_stores.py +74 -14
  26. tests/foundation/config/cors/test_cors.py +102 -33
  27. tests/foundation/config/database/test_database.py +38 -14
  28. tests/foundation/config/database/test_database_connections.py +79 -5
  29. tests/foundation/config/database/test_database_mysql.py +138 -15
  30. tests/foundation/config/database/test_database_oracle.py +110 -26
  31. tests/foundation/config/database/test_database_pgsql.py +96 -26
  32. tests/foundation/config/database/test_database_sqlite.py +56 -2
  33. tests/foundation/config/exceptions/test_exceptions_integrity.py +44 -10
  34. tests/foundation/config/filesystems/test_filesystems.py +64 -14
  35. tests/foundation/config/filesystems/test_filesystems_aws.py +45 -7
  36. tests/foundation/config/filesystems/test_filesystems_disks.py +78 -8
  37. tests/foundation/config/filesystems/test_filesystems_local.py +66 -18
  38. tests/foundation/config/filesystems/test_filesystems_public.py +37 -0
  39. tests/foundation/config/logging/test_logging.py +75 -11
  40. tests/foundation/config/logging/test_logging_channels.py +79 -2
  41. tests/foundation/config/logging/test_logging_chunked.py +85 -12
  42. tests/foundation/config/logging/test_logging_daily.py +79 -12
  43. tests/foundation/config/logging/test_logging_hourly.py +68 -2
  44. tests/foundation/config/logging/test_logging_monthly.py +48 -2
  45. tests/foundation/config/logging/test_logging_stack.py +49 -14
  46. tests/foundation/config/logging/test_logging_weekly.py +92 -2
  47. tests/foundation/config/mail/test_mail.py +87 -15
  48. tests/foundation/config/mail/test_mail_file.py +40 -4
  49. tests/foundation/config/mail/test_mail_mailers.py +56 -8
  50. tests/foundation/config/mail/test_mail_smtp.py +58 -14
  51. tests/foundation/config/queue/test_queue.py +62 -9
  52. tests/foundation/config/queue/test_queue_brokers.py +27 -10
  53. tests/foundation/config/queue/test_queue_database.py +53 -15
  54. tests/foundation/config/root/test_root_paths.py +69 -2
  55. tests/foundation/config/session/test_session.py +30 -1
  56. tests/foundation/config/startup/test_config_startup.py +77 -7
  57. tests/foundation/config/testing/test_testing.py +68 -0
  58. tests/patterns/singleton/test_singleton.py +10 -1
  59. tests/services/asynchrony/test_async_io.py +4 -4
  60. tests/services/environment/test_env.py +3 -4
  61. tests/testing/test_testing_result.py +56 -19
  62. tests/testing/test_testing_unit.py +93 -24
  63. orionis/services/environment/exceptions/value_exception.py +0 -27
  64. {orionis-0.285.0.dist-info → orionis-0.287.0.dist-info}/WHEEL +0 -0
  65. {orionis-0.285.0.dist-info → orionis-0.287.0.dist-info}/licenses/LICENCE +0 -0
  66. {orionis-0.285.0.dist-info → orionis-0.287.0.dist-info}/top_level.txt +0 -0
  67. {orionis-0.285.0.dist-info → orionis-0.287.0.dist-info}/zip-safe +0 -0
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.285.0"
8
+ VERSION = "0.287.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
File without changes
@@ -0,0 +1,24 @@
1
+ from abc import ABC, abstractmethod
2
+ import asyncio
3
+ from typing import TypeVar, Union
4
+
5
+ T = TypeVar("T")
6
+
7
+ class ICoroutine(ABC):
8
+
9
+ @abstractmethod
10
+ def run(self) -> Union[T, asyncio.Future]:
11
+ """
12
+ Execute the wrapped coroutine.
13
+
14
+ Returns
15
+ -------
16
+ result : T or asyncio.Future
17
+ The result of the coroutine if run synchronously, or a Future if run in an event loop.
18
+
19
+ Notes
20
+ -----
21
+ - If called from outside an event loop, this method will run the coroutine synchronously.
22
+ - If called from within an event loop, it will schedule the coroutine and return a Future.
23
+ """
24
+ pass
@@ -1,32 +1,71 @@
1
1
  import asyncio
2
- from typing import Any, Coroutine, TypeVar, Union
2
+ from inspect import iscoroutine
3
+ from typing import Any, Coroutine as TypingCoroutine, TypeVar, Union
4
+ from orionis.services.asynchrony.contracts.coroutines import ICoroutine
3
5
  from orionis.services.asynchrony.exceptions.coroutine_exception import OrionisCoroutineException
4
6
 
5
7
  T = TypeVar("T")
6
8
 
7
- def run_coroutine(coro: Coroutine[Any, Any, T]) -> Union[T, asyncio.Future]:
9
+ class Coroutine(ICoroutine):
8
10
  """
9
- Executes the given coroutine object, adapting to the current execution context.
10
- If there is an active event loop, it uses `asyncio.ensure_future` to schedule the coroutine.
11
- If there is no active event loop, it uses `asyncio.run` to run the coroutine directly.
12
- If the coroutine is already running, it returns a `Future` object that can be awaited.
11
+ Wrapper class for coroutine objects to facilitate execution in both synchronous
12
+ and asynchronous contexts.
13
13
 
14
14
  Parameters
15
15
  ----------
16
- coro : Coroutine[Any, Any, T]
17
- The coroutine object
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.
18
23
  """
19
- from inspect import iscoroutine
20
24
 
21
- if not iscoroutine(coro):
22
- raise OrionisCoroutineException("Expected a coroutine object.")
25
+ def __init__(self, func: TypingCoroutine[Any, Any, T]) -> None:
26
+ """
27
+ Initialize the Coroutine wrapper.
28
+
29
+ Parameters
30
+ ----------
31
+ func : Coroutine
32
+ The coroutine object to be wrapped.
33
+
34
+ Raises
35
+ ------
36
+ OrionisCoroutineException
37
+ If the provided object is not a coroutine.
38
+ """
39
+ if not iscoroutine(func):
40
+ raise OrionisCoroutineException(
41
+ f"Expected a coroutine object, but got {type(func).__name__}."
42
+ )
43
+ self.__func = func
44
+
45
+ def run(self) -> Union[T, asyncio.Future]:
46
+ """
47
+ Execute the wrapped coroutine.
48
+
49
+ Returns
50
+ -------
51
+ result : T or asyncio.Future
52
+ The result of the coroutine if run synchronously, or a Future if run in an event loop.
23
53
 
24
- try:
25
- loop = asyncio.get_running_loop()
26
- except RuntimeError:
27
- return asyncio.run(coro)
54
+ Notes
55
+ -----
56
+ - If called from outside an event loop, this method will run the coroutine synchronously.
57
+ - If called from within an event loop, it will schedule the coroutine and return a Future.
58
+ """
59
+ try:
60
+ # Get the current event loop
61
+ loop = asyncio.get_running_loop()
62
+ except RuntimeError:
63
+ # No running event loop, run synchronously
64
+ return asyncio.run(self.__func)
28
65
 
29
- if loop.is_running():
30
- return asyncio.ensure_future(coro)
31
- else:
32
- return loop.run_until_complete(coro)
66
+ if loop.is_running():
67
+ # Inside an event loop, schedule as a Future
68
+ return asyncio.ensure_future(self.__func)
69
+ else:
70
+ # No running loop, run synchronously
71
+ return loop.run_until_complete(self.__func)
@@ -1,26 +1,19 @@
1
1
  class OrionisCoroutineException(Exception):
2
- """
3
- Exception raised for errors related to coroutine operations in the Orionis framework.
4
- This exception is intended to signal issues encountered during asynchronous
5
- operations, providing a clear and descriptive error message to facilitate debugging.
6
- msg (str): A detailed message describing the cause of the exception.
7
- Example:
8
- raise OrionisCoroutineException("Coroutine execution failed due to timeout.")
9
- """
10
2
 
11
3
  def __init__(self, msg: str):
12
4
  """
13
- Initialize the exception with a custom error message.
14
- Args:
15
- msg (str): The error message describing the exception.
5
+ Parameters
6
+ ----------
7
+ msg : str
8
+ The error message describing the exception.
16
9
  """
17
10
  super().__init__(msg)
18
11
 
19
12
  def __str__(self) -> str:
20
13
  """
21
- Return a string representation of the exception, including the class name and the first argument.
22
-
23
- Returns:
24
- str: A formatted string with the exception class name and its first argument.
14
+ Returns
15
+ -------
16
+ str
17
+ A formatted string with the exception class name and its first argument.
25
18
  """
26
19
  return f"{self.__class__.__name__}: {self.args[0]}"
@@ -1,36 +1,47 @@
1
- from typing import Any, Dict, Optional
1
+ from typing import Any, Dict
2
2
  from abc import ABC, abstractmethod
3
3
 
4
4
  class IEnv(ABC):
5
- """Interface contract for environment management operations."""
6
5
 
7
6
  @staticmethod
8
7
  @abstractmethod
9
- def get(key: str, default: Optional[Any] = None) -> Any:
8
+ def get(key: str, default: Any = None) -> Any:
10
9
  """
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
10
+ Retrieve the value of an environment variable by key.
11
+
12
+ Parameters
13
+ ----------
14
+ key : str
15
+ The name of the environment variable to retrieve.
16
+ default : Any, optional
17
+ The value to return if the key is not found. Default is None.
18
+
19
+ Returns
20
+ -------
21
+ Any
22
+ The value of the environment variable if found, otherwise the default value.
19
23
  """
20
24
  pass
21
25
 
22
26
  @staticmethod
23
27
  @abstractmethod
24
- def set(key: str, value: str) -> bool:
28
+ def set(key: str, value: str, type: str = None) -> bool:
25
29
  """
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
30
+ Set an environment variable in the .env file.
31
+
32
+ Parameters
33
+ ----------
34
+ key : str
35
+ The name of the environment variable to set.
36
+ value : str
37
+ The value to assign to the environment variable.
38
+ type : str, optional
39
+ The type of the environment variable (e.g., 'str', 'int'). Default is None.
40
+
41
+ Returns
42
+ -------
43
+ bool
44
+ True if the variable was set successfully, False otherwise.
34
45
  """
35
46
  pass
36
47
 
@@ -38,13 +49,17 @@ class IEnv(ABC):
38
49
  @abstractmethod
39
50
  def unset(key: str) -> bool:
40
51
  """
41
- Removes an environment variable.
52
+ Remove the specified environment variable from the .env file.
42
53
 
43
- Args:
44
- key: Environment variable name
54
+ Parameters
55
+ ----------
56
+ key : str
57
+ The name of the environment variable to remove.
45
58
 
46
- Returns:
47
- True if successful, False otherwise
59
+ Returns
60
+ -------
61
+ bool
62
+ True if the variable was successfully removed, False otherwise.
48
63
  """
49
64
  pass
50
65
 
@@ -52,31 +67,11 @@ class IEnv(ABC):
52
67
  @abstractmethod
53
68
  def all() -> Dict[str, Any]:
54
69
  """
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 toJson() -> str:
65
- """
66
- Serializes environment to JSON.
67
-
68
- Returns:
69
- JSON string representation
70
- """
71
- pass
72
-
73
- @staticmethod
74
- @abstractmethod
75
- def toBase64() -> str:
76
- """
77
- Encodes environment to Base64.
70
+ Retrieve all environment variables as a dictionary.
78
71
 
79
- Returns:
80
- Base64 encoded string
72
+ Returns
73
+ -------
74
+ dict of str to Any
75
+ A dictionary containing all environment variables loaded by DotEnv.
81
76
  """
82
77
  pass