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.
Files changed (175) hide show
  1. orionis/console/base/command.py +57 -50
  2. orionis/console/base/contracts/command.py +68 -0
  3. orionis/console/dynamic/contracts/progress_bar.py +3 -3
  4. orionis/console/dynamic/progress_bar.py +8 -8
  5. orionis/console/output/console.py +8 -2
  6. orionis/console/output/contracts/console.py +1 -1
  7. orionis/container/container.py +2 -2
  8. orionis/container/context/scope.py +4 -1
  9. orionis/container/contracts/service_provider.py +2 -2
  10. orionis/container/entities/binding.py +31 -44
  11. orionis/container/enums/lifetimes.py +22 -1
  12. orionis/container/facades/facade.py +1 -2
  13. orionis/container/providers/service_provider.py +2 -2
  14. orionis/foundation/application.py +542 -248
  15. orionis/foundation/config/app/entities/app.py +107 -90
  16. orionis/foundation/config/auth/entities/auth.py +4 -33
  17. orionis/foundation/config/cache/entities/cache.py +18 -41
  18. orionis/foundation/config/cache/entities/file.py +8 -35
  19. orionis/foundation/config/cache/entities/stores.py +17 -38
  20. orionis/foundation/config/cors/entities/cors.py +41 -54
  21. orionis/foundation/config/database/entities/connections.py +40 -56
  22. orionis/foundation/config/database/entities/database.py +11 -38
  23. orionis/foundation/config/database/entities/mysql.py +48 -76
  24. orionis/foundation/config/database/entities/oracle.py +30 -57
  25. orionis/foundation/config/database/entities/pgsql.py +45 -61
  26. orionis/foundation/config/database/entities/sqlite.py +26 -53
  27. orionis/foundation/config/filesystems/entitites/aws.py +28 -49
  28. orionis/foundation/config/filesystems/entitites/disks.py +27 -47
  29. orionis/foundation/config/filesystems/entitites/filesystems.py +15 -37
  30. orionis/foundation/config/filesystems/entitites/local.py +9 -35
  31. orionis/foundation/config/filesystems/entitites/public.py +14 -41
  32. orionis/foundation/config/logging/entities/channels.py +56 -86
  33. orionis/foundation/config/logging/entities/chunked.py +9 -9
  34. orionis/foundation/config/logging/entities/daily.py +8 -8
  35. orionis/foundation/config/logging/entities/hourly.py +6 -6
  36. orionis/foundation/config/logging/entities/logging.py +12 -18
  37. orionis/foundation/config/logging/entities/monthly.py +7 -7
  38. orionis/foundation/config/logging/entities/stack.py +5 -5
  39. orionis/foundation/config/logging/entities/weekly.py +6 -6
  40. orionis/foundation/config/mail/entities/file.py +9 -36
  41. orionis/foundation/config/mail/entities/mail.py +22 -40
  42. orionis/foundation/config/mail/entities/mailers.py +29 -44
  43. orionis/foundation/config/mail/entities/smtp.py +47 -48
  44. orionis/foundation/config/queue/entities/brokers.py +19 -41
  45. orionis/foundation/config/queue/entities/database.py +24 -46
  46. orionis/foundation/config/queue/entities/queue.py +28 -40
  47. orionis/foundation/config/roots/paths.py +272 -468
  48. orionis/foundation/config/session/entities/session.py +23 -53
  49. orionis/foundation/config/startup.py +165 -135
  50. orionis/foundation/config/testing/entities/testing.py +137 -122
  51. orionis/foundation/config/testing/enums/__init__.py +6 -2
  52. orionis/foundation/config/testing/enums/drivers.py +16 -0
  53. orionis/foundation/config/testing/enums/verbosity.py +18 -0
  54. orionis/foundation/contracts/application.py +152 -362
  55. orionis/foundation/providers/console_provider.py +24 -2
  56. orionis/foundation/providers/dumper_provider.py +24 -2
  57. orionis/foundation/providers/logger_provider.py +24 -2
  58. orionis/foundation/providers/path_resolver_provider.py +25 -2
  59. orionis/foundation/providers/progress_bar_provider.py +24 -2
  60. orionis/foundation/providers/testing_provider.py +39 -0
  61. orionis/foundation/providers/workers_provider.py +24 -2
  62. orionis/metadata/framework.py +1 -1
  63. orionis/services/asynchrony/contracts/coroutines.py +13 -5
  64. orionis/services/asynchrony/coroutines.py +33 -29
  65. orionis/services/asynchrony/exceptions/exception.py +9 -1
  66. orionis/services/environment/core/dot_env.py +46 -34
  67. orionis/services/environment/enums/__init__.py +0 -0
  68. orionis/services/environment/enums/cast_type.py +42 -0
  69. orionis/services/environment/helpers/functions.py +1 -2
  70. orionis/services/environment/key/__init__.py +0 -0
  71. orionis/services/environment/key/key_generator.py +37 -0
  72. orionis/services/environment/serializer/__init__.py +0 -0
  73. orionis/services/environment/serializer/values.py +21 -0
  74. orionis/services/environment/validators/__init__.py +0 -0
  75. orionis/services/environment/validators/key_name.py +46 -0
  76. orionis/services/environment/validators/types.py +45 -0
  77. orionis/services/system/contracts/imports.py +38 -18
  78. orionis/services/system/contracts/workers.py +29 -12
  79. orionis/services/system/imports.py +65 -25
  80. orionis/services/system/runtime/imports.py +18 -9
  81. orionis/services/system/workers.py +49 -16
  82. orionis/support/entities/__init__.py +0 -0
  83. orionis/support/entities/base.py +104 -0
  84. orionis/support/facades/testing.py +15 -0
  85. orionis/support/facades/workers.py +1 -1
  86. orionis/test/cases/asynchronous.py +0 -11
  87. orionis/test/cases/synchronous.py +0 -9
  88. orionis/test/contracts/dumper.py +11 -4
  89. orionis/test/contracts/kernel.py +5 -110
  90. orionis/test/contracts/logs.py +27 -65
  91. orionis/test/contracts/printer.py +16 -128
  92. orionis/test/contracts/test_result.py +100 -0
  93. orionis/test/contracts/unit_test.py +87 -150
  94. orionis/test/core/unit_test.py +608 -554
  95. orionis/test/entities/result.py +22 -2
  96. orionis/test/enums/__init__.py +0 -2
  97. orionis/test/enums/status.py +14 -9
  98. orionis/test/exceptions/config.py +9 -1
  99. orionis/test/exceptions/failure.py +34 -11
  100. orionis/test/exceptions/persistence.py +10 -2
  101. orionis/test/exceptions/runtime.py +9 -1
  102. orionis/test/exceptions/value.py +13 -1
  103. orionis/test/kernel.py +87 -289
  104. orionis/test/output/dumper.py +83 -18
  105. orionis/test/output/printer.py +399 -156
  106. orionis/test/records/logs.py +203 -82
  107. orionis/test/validators/__init__.py +33 -0
  108. orionis/test/validators/base_path.py +45 -0
  109. orionis/test/validators/execution_mode.py +45 -0
  110. orionis/test/validators/fail_fast.py +37 -0
  111. orionis/test/validators/folder_path.py +34 -0
  112. orionis/test/validators/module_name.py +31 -0
  113. orionis/test/validators/name_pattern.py +40 -0
  114. orionis/test/validators/pattern.py +36 -0
  115. orionis/test/validators/persistent.py +42 -0
  116. orionis/test/validators/persistent_driver.py +43 -0
  117. orionis/test/validators/print_result.py +37 -0
  118. orionis/test/validators/tags.py +37 -0
  119. orionis/test/validators/throw_exception.py +39 -0
  120. orionis/test/validators/verbosity.py +37 -0
  121. orionis/test/validators/web_report.py +35 -0
  122. orionis/test/validators/workers.py +31 -0
  123. orionis/test/view/render.py +48 -54
  124. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/METADATA +1 -1
  125. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/RECORD +170 -112
  126. tests/container/__init__.py +0 -0
  127. tests/container/context/__init__.py +0 -0
  128. tests/container/context/test_manager.py +27 -0
  129. tests/container/context/test_scope.py +23 -0
  130. tests/container/entities/__init__.py +0 -0
  131. tests/container/entities/test_binding.py +133 -0
  132. tests/container/enums/__init__.py +0 -0
  133. tests/container/enums/test_lifetimes.py +63 -0
  134. tests/container/facades/__init__.py +0 -0
  135. tests/container/facades/test_facade.py +61 -0
  136. tests/container/mocks/__init__.py +0 -0
  137. tests/container/mocks/mock_complex_classes.py +482 -0
  138. tests/container/mocks/mock_simple_classes.py +32 -0
  139. tests/container/providers/__init__.py +0 -0
  140. tests/container/providers/test_providers.py +48 -0
  141. tests/container/resolver/__init__.py +0 -0
  142. tests/container/resolver/test_resolver.py +55 -0
  143. tests/container/test_container.py +254 -0
  144. tests/container/test_singleton.py +98 -0
  145. tests/container/test_thread_safety.py +217 -0
  146. tests/container/validators/__init__.py +0 -0
  147. tests/container/validators/test_implements.py +140 -0
  148. tests/container/validators/test_is_abstract_class.py +99 -0
  149. tests/container/validators/test_is_callable.py +73 -0
  150. tests/container/validators/test_is_concrete_class.py +97 -0
  151. tests/container/validators/test_is_instance.py +105 -0
  152. tests/container/validators/test_is_not_subclass.py +117 -0
  153. tests/container/validators/test_is_subclass.py +115 -0
  154. tests/container/validators/test_is_valid_alias.py +113 -0
  155. tests/container/validators/test_lifetime.py +75 -0
  156. tests/example/test_example.py +2 -2
  157. tests/foundation/config/testing/test_foundation_config_testing.py +1 -1
  158. tests/metadata/test_metadata_framework.py +89 -24
  159. tests/metadata/test_metadata_package.py +55 -10
  160. tests/services/asynchrony/test_services_asynchrony_coroutine.py +52 -7
  161. tests/services/system/test_services_system_imports.py +119 -16
  162. tests/services/system/test_services_system_workers.py +71 -30
  163. tests/testing/test_testing_result.py +117 -117
  164. tests/testing/test_testing_unit.py +209 -209
  165. orionis/foundation/config/base.py +0 -112
  166. orionis/test/arguments/parser.py +0 -187
  167. orionis/test/contracts/parser.py +0 -43
  168. orionis/test/entities/arguments.py +0 -38
  169. orionis/test/enums/execution_mode.py +0 -16
  170. /orionis/{test/arguments → console/base/contracts}/__init__.py +0 -0
  171. /orionis/foundation/config/testing/enums/{test_mode.py → mode.py} +0 -0
  172. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/WHEEL +0 -0
  173. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/licenses/LICENCE +0 -0
  174. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/top_level.txt +0 -0
  175. {orionis-0.405.0.dist-info → orionis-0.407.0.dist-info}/zip-safe +0 -0
@@ -0,0 +1,37 @@
1
+ import os
2
+ import base64
3
+
4
+ class SecureKeyGenerator:
5
+ """
6
+ Provides static methods for generating secure random keys in base64 format.
7
+
8
+ Methods
9
+ -------
10
+ generate_key() : str
11
+ Generates a secure random key encoded in base64.
12
+ """
13
+
14
+ @staticmethod
15
+ def generate() -> str:
16
+ """
17
+ Generates a secure random key and encodes it in base64 format.
18
+
19
+ This method creates a cryptographically secure random key of 32 bytes,
20
+ encodes it using base64 encoding, and returns the result as a string
21
+ prefixed with 'base64:'.
22
+
23
+ Returns
24
+ -------
25
+ str
26
+ A string in the format 'base64:<key>', where <key> is a base64-encoded
27
+ representation of a securely generated 32-byte random key.
28
+ """
29
+
30
+ # Generate 32 bytes of cryptographically secure random data
31
+ key = os.urandom(32)
32
+
33
+ # Encode the random bytes using base64 and decode to a UTF-8 string
34
+ encoded = base64.b64encode(key).decode('utf-8')
35
+
36
+ # Return the key in the required format
37
+ return f"base64:{encoded}"
File without changes
@@ -0,0 +1,21 @@
1
+ from orionis.services.environment.enums.cast_type import EnvCastType
2
+
3
+ class SerializerValue:
4
+
5
+ def __init__(self, value):
6
+ pass
7
+
8
+ def to(self, type_hint: str | EnvCastType = None):
9
+ pass
10
+
11
+ def get(self):
12
+ pass
13
+
14
+
15
+ class SerializerFrom:
16
+
17
+ def __init__(self, key: str):
18
+ pass
19
+
20
+ def get(self):
21
+ pass
File without changes
@@ -0,0 +1,46 @@
1
+ import re
2
+ from orionis.services.environment.exceptions.value import OrionisEnvironmentValueError
3
+
4
+ class __ValidateKeyName:
5
+
6
+ # Regular expression pattern to match valid environment variable names
7
+ _pattern = re.compile(r'^[A-Z][A-Z0-9_]*$')
8
+
9
+ def __call__(self, key: object) -> str:
10
+ """
11
+ Validates that the provided environment variable name meets the required format.
12
+
13
+ Parameters
14
+ ----------
15
+ key : object
16
+ The environment variable name to validate.
17
+
18
+ Returns
19
+ -------
20
+ str
21
+ The validated environment variable name if it meets the format requirements.
22
+
23
+ Raises
24
+ ------
25
+ OrionisEnvironmentValueError
26
+ If the provided key is not a string or does not match the required format.
27
+ """
28
+
29
+ # Check if the key is a string
30
+ if not isinstance(key, str):
31
+ raise OrionisEnvironmentValueError(
32
+ f"Environment variable name must be a string, got {type(key).__name__}."
33
+ )
34
+
35
+ # Validate the key against the pattern
36
+ if not self._pattern.fullmatch(key):
37
+ raise OrionisEnvironmentValueError(
38
+ f"Invalid environment variable name '{key}'. It must start with an uppercase letter, "
39
+ "contain only uppercase letters, numbers, or underscores. Example: 'MY_ENV_VAR'."
40
+ )
41
+
42
+ # Return the validated key
43
+ return key
44
+
45
+ # Instance to be used for key name validation
46
+ ValidateKeyName = __ValidateKeyName()
@@ -0,0 +1,45 @@
1
+ import re
2
+ from typing import Any, Union
3
+ from orionis.services.environment.enums.cast_type import EnvCastType
4
+ from orionis.services.environment.exceptions.value import OrionisEnvironmentValueError
5
+
6
+ class __ValidateTypes:
7
+
8
+ def __call__(self, value: Union[str, int, float, bool, list, dict, tuple, set], type_hint: str | EnvCastType = None) -> str:
9
+
10
+ # Ensure the value is a valid type.
11
+ if not isinstance(value, (str, int, float, bool, list, dict, tuple, set)):
12
+ raise OrionisEnvironmentValueError(
13
+ f"Unsupported value type: {type(value).__name__}. Allowed types are str, int, float, bool, list, dict, tuple, set."
14
+ )
15
+
16
+ # If a type hint is provided, ensure it is valid.
17
+ if type_hint and not isinstance(type_hint, (str, EnvCastType)):
18
+ raise OrionisEnvironmentValueError(
19
+ f"Type hint must be a string or EnvCastType, got {type(type_hint).__name__}."
20
+ )
21
+
22
+ # If type_hint is provided, convert it to a string if it's an EnvCastType.
23
+ if type_hint:
24
+
25
+ # If type_hint is a string, convert it to EnvCastType if valid.
26
+ if isinstance(type_hint, str):
27
+ try:
28
+ type_hint = EnvCastType[type_hint.upper()].value
29
+ except KeyError:
30
+ raise OrionisEnvironmentValueError(
31
+ f"Invalid type hint: {type_hint}. Allowed types are {[e.value for e in EnvCastType]}"
32
+ )
33
+ elif isinstance(type_hint, EnvCastType):
34
+ type_hint = type_hint.value
35
+
36
+ # If no type hint is provided, use the type of the value.
37
+ else:
38
+ type_hint = type(value).__name__.lower()
39
+
40
+ # Return the type hint as a string.
41
+ return type_hint
42
+
43
+
44
+ # Instance to be used for key name validation
45
+ ValidateTypes = __ValidateTypes()
@@ -1,51 +1,71 @@
1
1
  from abc import ABC, abstractmethod
2
2
 
3
3
  class IImports(ABC):
4
- """
5
- Interface for a utility to collect and display information about currently loaded Python modules.
6
-
7
- Methods
8
- -------
9
- collect()
10
- Collects information about user-defined Python modules currently loaded in sys.modules.
11
-
12
- display()
13
- Displays a formatted table of collected import statements.
14
-
15
- clear()
16
- Clears the collected imports list.
17
- """
18
4
 
19
5
  @abstractmethod
20
6
  def collect(self):
21
7
  """
22
- Collect information about user-defined Python modules currently loaded in sys.modules.
8
+ Collects information about user-defined Python modules currently loaded in `sys.modules`.
9
+
10
+ This method should scan the current Python runtime environment and gather details about
11
+ all user-defined modules that have been imported and are present in `sys.modules`. The
12
+ collected information may include module names, file paths, and other relevant metadata,
13
+ depending on the implementation.
23
14
 
24
15
  Returns
25
16
  -------
26
17
  IImports
27
- The current instance with updated imports information.
18
+ Returns the current instance (`self`) with its internal imports information updated
19
+ to reflect the latest state of loaded modules.
20
+
21
+ Notes
22
+ -----
23
+ This method does not modify the actual modules loaded in memory; it only updates the
24
+ internal collection maintained by the implementation. Subclasses should implement the
25
+ logic for identifying and storing relevant module information.
28
26
  """
27
+
28
+ # Subclasses should implement logic to scan sys.modules and update internal imports collection.
29
29
  pass
30
30
 
31
31
  @abstractmethod
32
32
  def display(self) -> None:
33
33
  """
34
- Display a formatted table of collected import statements.
34
+ Displays a formatted table summarizing the collected import statements.
35
+
36
+ This method should present the information about the currently collected Python module imports
37
+ in a human-readable tabular format. The display may include details such as module names,
38
+ file paths, and other relevant metadata, depending on the implementation.
35
39
 
36
40
  Returns
37
41
  -------
38
42
  None
43
+ This method does not return any value. Its sole purpose is to output the collected import
44
+ information for inspection or debugging.
45
+
46
+ Notes
47
+ -----
48
+ The actual formatting and output destination (e.g., console, log, GUI) are determined by the
49
+ implementing subclass.
39
50
  """
51
+
52
+ # Subclasses should implement logic to format and output the collected imports.
40
53
  pass
41
54
 
42
55
  @abstractmethod
43
56
  def clear(self) -> None:
44
57
  """
45
- Clear the collected imports list.
58
+ Removes all entries from the collected imports list, resetting the internal state.
59
+
60
+ This method should be called when you want to discard all previously collected import
61
+ information and start fresh. It does not affect the actual Python modules loaded in memory,
62
+ only the internal collection maintained by the implementation.
46
63
 
47
64
  Returns
48
65
  -------
49
66
  None
67
+ This method does not return any value.
50
68
  """
69
+
70
+ # Subclasses should implement logic to clear their internal imports collection.
51
71
  pass
@@ -1,35 +1,52 @@
1
1
  from abc import ABC, abstractmethod
2
2
 
3
3
  class IWorkers(ABC):
4
- """
5
- Interface for calculating the optimal number of workers a machine can handle based on CPU and memory resources.
6
-
7
- Notes
8
- -----
9
- Implementations should provide logic to determine the recommended number of worker processes
10
- according to the available CPU and memory resources of the current machine.
11
- """
12
4
 
13
5
  @abstractmethod
14
6
  def setRamPerWorker(self, ram_per_worker: float) -> None:
15
7
  """
16
- Set the amount of RAM allocated per worker.
8
+ Set the amount of RAM to allocate for each worker process.
17
9
 
18
10
  Parameters
19
11
  ----------
20
12
  ram_per_worker : float
21
- Amount of RAM (in GB) allocated per worker.
13
+ The amount of RAM, in gigabytes (GB), to allocate for each worker process.
14
+
15
+ Returns
16
+ -------
17
+ None
18
+ This method does not return any value.
19
+
20
+ Notes
21
+ -----
22
+ This method should be implemented by subclasses to configure the memory usage
23
+ per worker, which may affect the total number of workers that can be spawned
24
+ based on system resources.
22
25
  """
26
+
27
+ # Implementation should assign the specified RAM per worker.
23
28
  pass
24
29
 
25
30
  @abstractmethod
26
31
  def calculate(self) -> int:
27
32
  """
28
- Compute the maximum number of workers supported by the current machine.
33
+ Compute the recommended maximum number of worker processes for the current machine.
34
+
35
+ This method should consider both CPU and memory constraints to determine the optimal
36
+ number of worker processes that can be safely spawned without overloading system resources.
29
37
 
30
38
  Returns
31
39
  -------
32
40
  int
33
- Recommended number of worker processes based on CPU and memory limits.
41
+ The maximum number of worker processes that can be supported by the current machine,
42
+ based on available CPU cores and memory limits.
43
+
44
+ Notes
45
+ -----
46
+ Subclasses should implement this method to analyze system resources and return an integer
47
+ representing the recommended number of workers. The calculation should ensure that each
48
+ worker receives sufficient resources as configured (e.g., RAM per worker).
34
49
  """
50
+
51
+ # Implementation should analyze system resources and return the recommended worker count.
35
52
  pass
@@ -2,58 +2,68 @@ from typing import List, Dict, Any
2
2
  from orionis.services.system.contracts.imports import IImports
3
3
 
4
4
  class Imports(IImports):
5
- """
6
- Utility class to collect and display information about currently loaded Python modules.
7
-
8
- This class provides methods to gather details about user-defined Python modules
9
- currently loaded in `sys.modules`, excluding standard library and virtual environment modules.
10
- It can display the collected information in a formatted table using the Rich library.
11
- """
12
5
 
13
6
  def __init__(self):
14
7
  """
15
- Initialize the Imports object.
8
+ Initialize the Imports instance.
9
+
10
+ This constructor sets up the Imports object by initializing an empty list
11
+ to store information about user-defined Python modules. The list will
12
+ contain dictionaries, each representing a module with its name, file path,
13
+ and defined symbols.
16
14
 
17
- Initializes an empty list to store module information.
15
+ Returns
16
+ -------
17
+ None
18
+ This method does not return any value.
18
19
  """
20
+
21
+ # List to hold information about imported modules
19
22
  self.imports: List[Dict[str, Any]] = []
20
23
 
21
24
  def collect(self) -> 'Imports':
22
25
  """
23
26
  Collect information about user-defined Python modules currently loaded.
24
27
 
25
- For each qualifying module, gathers:
26
- - The module's name.
27
- - The relative file path to the module from the current working directory.
28
- - A list of symbols (functions, classes, or submodules) defined in the module.
28
+ Iterates through all modules in `sys.modules` and gathers details for each qualifying module:
29
+ - Module name.
30
+ - Relative file path from the current working directory.
31
+ - List of symbols (functions, classes, or submodules) defined in the module.
29
32
 
30
- Excludes:
31
- - Modules from the standard library.
32
- - Modules from the active virtual environment (if any).
33
- - Binary extension modules (.pyd, .dll, .so).
34
- - Special modules like "__main__", "__mp_main__", and modules starting with "_distutils".
33
+ Excludes modules that:
34
+ - Are part of the standard library.
35
+ - Reside in the active virtual environment (if any).
36
+ - Are binary extension modules (e.g., `.pyd`, `.dll`, `.so`).
37
+ - Are special modules such as `"__main__"`, `"__mp_main__"`, or those starting with `"_distutils"`.
35
38
 
36
- The collected information is stored in `self.imports` as a list of dictionaries.
39
+ The collected information is stored in `self.imports` as a list of dictionaries, each containing the module's name, file path, and symbols.
37
40
 
38
41
  Returns
39
42
  -------
40
43
  Imports
41
- The current instance with updated imports information.
44
+ The current instance of `Imports` with the `imports` attribute updated to include information about the collected modules.
42
45
  """
43
46
 
44
47
  import sys
45
48
  import os
46
49
  import types
47
50
 
51
+ # Clear any previously collected imports
48
52
  self.imports.clear()
53
+
54
+ # Get standard library paths to exclude standard modules
49
55
  stdlib_paths = [os.path.dirname(os.__file__)]
56
+
57
+ # Get virtual environment path if active
50
58
  venv_path = os.environ.get("VIRTUAL_ENV")
51
59
  if venv_path:
52
60
  venv_path = os.path.abspath(venv_path)
53
61
 
62
+ # Iterate over all loaded modules
54
63
  for name, module in list(sys.modules.items()):
55
- file:str = getattr(module, '__file__', None)
64
+ file: str = getattr(module, '__file__', None)
56
65
 
66
+ # Filter out unwanted modules based on path, type, and name
57
67
  if (
58
68
  file
59
69
  and not any(file.startswith(stdlib_path) for stdlib_path in stdlib_paths)
@@ -62,18 +72,25 @@ class Imports(IImports):
62
72
  and name not in ("__main__", "__mp_main__")
63
73
  and not name.startswith("_distutils")
64
74
  ):
75
+
76
+ # Get relative file path from current working directory
65
77
  rel_file = os.path.relpath(file, os.getcwd())
66
78
  symbols = []
67
79
 
80
+ # Collect symbols defined in the module (functions, classes, submodules)
68
81
  try:
69
82
  for attr in dir(module):
70
83
  value = getattr(module, attr)
71
84
  if isinstance(value, (types.FunctionType, type, types.ModuleType)):
85
+
86
+ # Ensure symbol is defined in this module
72
87
  if getattr(value, '__module__', None) == name:
73
88
  symbols.append(attr)
74
89
  except Exception:
90
+ # Ignore errors during symbol collection
75
91
  pass
76
92
 
93
+ # Only add modules that are not __init__.py and have symbols
77
94
  if not rel_file.endswith('__init__.py') and symbols:
78
95
  self.imports.append({
79
96
  "name": name,
@@ -81,32 +98,45 @@ class Imports(IImports):
81
98
  "symbols": symbols,
82
99
  })
83
100
 
101
+ # Return the current instance with updated imports
84
102
  return self
85
103
 
86
104
  def display(self) -> None:
87
105
  """
88
106
  Display a formatted table of collected import statements using the Rich library.
89
107
 
90
- If the imports have not been collected yet, it calls `self.collect()` to gather them.
91
- The table includes columns for the import name, file, and imported symbols, and is
92
- rendered inside a styled panel in the console.
108
+ This method presents a visual summary of all collected user-defined Python modules.
109
+ If the imports have not been collected yet, it automatically calls `self.collect()` to gather them.
110
+ The output is rendered as a table inside a styled panel in the console, showing each module's name,
111
+ relative file path, and its defined symbols.
112
+
113
+ Parameters
114
+ ----------
115
+ None
93
116
 
94
117
  Returns
95
118
  -------
96
119
  None
120
+ This method does not return any value. It outputs the formatted table to the console.
97
121
  """
98
122
 
123
+ # Collect imports if not already done
99
124
  if not self.imports:
100
125
  self.collect()
101
126
 
127
+ # Import Rich components for console output
102
128
  from rich.console import Console
103
129
  from rich.table import Table
104
130
  from rich.box import MINIMAL
105
131
  from rich.panel import Panel
106
132
 
133
+ # Create a console instance for output
107
134
  console = Console()
135
+
136
+ # Set table width to 75% of console width
108
137
  width = int(console.size.width * 0.75)
109
138
 
139
+ # Create a table with minimal box style and custom formatting
110
140
  table = Table(
111
141
  box=MINIMAL,
112
142
  show_header=True,
@@ -117,14 +147,17 @@ class Imports(IImports):
117
147
  collapse_padding=True,
118
148
  )
119
149
 
150
+ # Add columns for module name, file path, and symbols
120
151
  table.add_column("Name", style="cyan", no_wrap=True)
121
152
  table.add_column("File", style="white")
122
153
  table.add_column("Symbols", style="magenta")
123
154
 
155
+ # Populate the table with sorted import data
124
156
  for imp in sorted(self.imports, key=lambda x: x["name"].lower()):
125
157
  symbols_str = ", ".join(imp["symbols"])
126
158
  table.add_row(imp["name"], imp["file"], symbols_str)
127
159
 
160
+ # Render the table inside a styled panel in the console
128
161
  console.print(Panel(
129
162
  table,
130
163
  title="[bold blue]🔎 Loaded Python Modules (Orionis Imports Trace)[/bold blue]",
@@ -134,10 +167,17 @@ class Imports(IImports):
134
167
 
135
168
  def clear(self) -> None:
136
169
  """
137
- Clear the collected imports list.
170
+ Remove all entries from the collected imports list.
171
+
172
+ This method resets the `imports` attribute by removing all currently stored
173
+ module information. It is useful for discarding previously collected data
174
+ before performing a new collection or when a fresh state is required.
138
175
 
139
176
  Returns
140
177
  -------
141
178
  None
179
+ This method does not return any value. The `imports` list is emptied in place.
142
180
  """
181
+
182
+ # Remove all items from the imports list to reset its state
143
183
  self.imports.clear()
@@ -25,6 +25,7 @@ Notes
25
25
  - Thread safety is provided via a threading.Lock.
26
26
 
27
27
  """
28
+
28
29
  import builtins
29
30
  from collections import defaultdict
30
31
  from threading import Lock
@@ -40,40 +41,48 @@ _import_lock = Lock()
40
41
 
41
42
  def custom_import(name, globals=None, locals=None, fromlist=(), level=0):
42
43
  """
43
- Custom import function that tracks imports of 'orionis' modules.
44
+ Tracks and logs imports of modules whose names start with 'orionis'.
45
+
46
+ This function overrides Python's built-in import mechanism to monitor
47
+ how many times modules from the 'orionis' package are imported. It
48
+ increments an internal counter for each such import and prints a log
49
+ message with the module name, import count, and fromlist. Thread safety
50
+ is ensured using a lock.
44
51
 
45
52
  Parameters
46
53
  ----------
47
54
  name : str
48
55
  The name of the module to import.
49
56
  globals : dict, optional
50
- The global namespace.
57
+ The global namespace in which the import is performed.
51
58
  locals : dict, optional
52
- The local namespace.
59
+ The local namespace in which the import is performed.
53
60
  fromlist : tuple, optional
54
61
  Names to import from the module.
55
62
  level : int, optional
56
- Relative import level.
63
+ Relative import level (0 for absolute, >0 for relative).
57
64
 
58
65
  Returns
59
66
  -------
60
- module
61
- The imported module.
67
+ module : ModuleType
68
+ The imported module object as returned by the original import function.
62
69
  """
63
- # Check if the module name starts with 'orionis'
70
+ # Only track imports for modules starting with 'orionis'
64
71
  if str(name).startswith("orionis"):
65
72
  with _import_lock:
73
+
74
+ # Increment the import count for this module
66
75
  _import_count[name] += 1
67
76
  count = _import_count[name]
68
77
 
69
- # Print the import details
78
+ # Print import details to the console
70
79
  print(
71
80
  f"\033[1;37mModule\033[0m: \033[90m{name}\033[0m | "
72
81
  f"\033[1;37mImported\033[0m: \033[90m{count}\033[0m | "
73
82
  f"\033[1;37mFromList\033[0m: \033[90m{fromlist}\033[0m"
74
83
  )
75
84
 
76
- # Call the original import function
85
+ # Delegate the actual import to the original __import__ function
77
86
  return _original_import(name, globals, locals, fromlist, level)
78
87
 
79
88
  # Override the built-in __import__ function