orionis 0.413.0__py3-none-any.whl → 0.415.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 (90) hide show
  1. orionis/metadata/framework.py +1 -1
  2. orionis/support/entities/base.py +45 -26
  3. orionis/support/facades/console.py +8 -2
  4. orionis/support/facades/dumper.py +8 -2
  5. orionis/support/facades/logger.py +9 -2
  6. orionis/support/facades/path_resolver.py +9 -2
  7. orionis/support/facades/progress_bar.py +9 -2
  8. orionis/support/facades/testing.py +9 -2
  9. orionis/support/facades/workers.py +9 -2
  10. orionis/test/core/unit_test.py +26 -10
  11. orionis/test/output/dumper.py +1 -1
  12. {orionis-0.413.0.dist-info → orionis-0.415.0.dist-info}/METADATA +1 -1
  13. {orionis-0.413.0.dist-info → orionis-0.415.0.dist-info}/RECORD +88 -76
  14. orionis-0.415.0.dist-info/top_level.txt +4 -0
  15. tests/container/entities/test_binding.py +1 -1
  16. tests/container/test_thread_safety.py +0 -1
  17. tests/support/entities/__init__.py +0 -0
  18. tests/support/entities/mock_dataclass.py +34 -0
  19. tests/support/entities/test_base.py +72 -0
  20. tests/testing/cases/__init__.py +0 -0
  21. tests/testing/cases/test_testing_asynchronous.py +63 -0
  22. tests/testing/cases/test_testing_synchronous.py +59 -0
  23. tests/testing/entities/__init__.py +0 -0
  24. tests/testing/entities/test_testing_result.py +185 -0
  25. tests/testing/enums/__init__.py +0 -0
  26. tests/testing/enums/test_testing_status.py +68 -0
  27. tests/testing/output/__init__.py +0 -0
  28. tests/testing/output/test_testing_dumper.py +32 -0
  29. tests/testing/output/test_testing_printer.py +42 -0
  30. tests/testing/test_testing_unit.py +110 -209
  31. orionis-0.413.0.dist-info/top_level.txt +0 -2
  32. tests/testing/test_testing_result.py +0 -131
  33. {tests/foundation → environment}/__init__.py +0 -0
  34. {tests/services/environment → environment}/test_services_environment.py +0 -0
  35. {tests/foundation/config → foundation}/__init__.py +0 -0
  36. {tests/foundation/config/app → foundation/config}/__init__.py +0 -0
  37. {tests/foundation/config/auth → foundation/config/app}/__init__.py +0 -0
  38. {tests/foundation → foundation}/config/app/test_foundation_config_app.py +0 -0
  39. {tests/foundation/config/cache → foundation/config/auth}/__init__.py +0 -0
  40. {tests/foundation → foundation}/config/auth/test_foundation_config_auth.py +0 -0
  41. {tests/foundation/config/cors → foundation/config/cache}/__init__.py +0 -0
  42. {tests/foundation → foundation}/config/cache/test_foundation_config_cache.py +0 -0
  43. {tests/foundation → foundation}/config/cache/test_foundation_config_cache_file.py +0 -0
  44. {tests/foundation → foundation}/config/cache/test_foundation_config_cache_stores.py +0 -0
  45. {tests/foundation/config/database → foundation/config/cors}/__init__.py +0 -0
  46. {tests/foundation → foundation}/config/cors/test_foundation_config_cors.py +0 -0
  47. {tests/foundation/config/filesystems → foundation/config/database}/__init__.py +0 -0
  48. {tests/foundation → foundation}/config/database/test_foundation_config_database.py +0 -0
  49. {tests/foundation → foundation}/config/database/test_foundation_config_database_connections.py +0 -0
  50. {tests/foundation → foundation}/config/database/test_foundation_config_database_mysql.py +0 -0
  51. {tests/foundation → foundation}/config/database/test_foundation_config_database_oracle.py +0 -0
  52. {tests/foundation → foundation}/config/database/test_foundation_config_database_pgsql.py +0 -0
  53. {tests/foundation → foundation}/config/database/test_foundation_config_database_sqlite.py +0 -0
  54. {tests/foundation/config/logging → foundation/config/filesystems}/__init__.py +0 -0
  55. {tests/foundation → foundation}/config/filesystems/test_foundation_config_filesystems.py +0 -0
  56. {tests/foundation → foundation}/config/filesystems/test_foundation_config_filesystems_aws.py +0 -0
  57. {tests/foundation → foundation}/config/filesystems/test_foundation_config_filesystems_disks.py +0 -0
  58. {tests/foundation → foundation}/config/filesystems/test_foundation_config_filesystems_local.py +0 -0
  59. {tests/foundation → foundation}/config/filesystems/test_foundation_config_filesystems_public.py +0 -0
  60. {tests/foundation/config/mail → foundation/config/logging}/__init__.py +0 -0
  61. {tests/foundation → foundation}/config/logging/test_foundation_config_logging.py +0 -0
  62. {tests/foundation → foundation}/config/logging/test_foundation_config_logging_channels.py +0 -0
  63. {tests/foundation → foundation}/config/logging/test_foundation_config_logging_chunked.py +0 -0
  64. {tests/foundation → foundation}/config/logging/test_foundation_config_logging_daily.py +0 -0
  65. {tests/foundation → foundation}/config/logging/test_foundation_config_logging_hourly.py +0 -0
  66. {tests/foundation → foundation}/config/logging/test_foundation_config_logging_monthly.py +0 -0
  67. {tests/foundation → foundation}/config/logging/test_foundation_config_logging_stack.py +0 -0
  68. {tests/foundation → foundation}/config/logging/test_foundation_config_logging_weekly.py +0 -0
  69. {tests/foundation/config/queue → foundation/config/mail}/__init__.py +0 -0
  70. {tests/foundation → foundation}/config/mail/test_foundation_config_mail.py +0 -0
  71. {tests/foundation → foundation}/config/mail/test_foundation_config_mail_file.py +0 -0
  72. {tests/foundation → foundation}/config/mail/test_foundation_config_mail_mailers.py +0 -0
  73. {tests/foundation → foundation}/config/mail/test_foundation_config_mail_smtp.py +0 -0
  74. {tests/foundation/config/root → foundation/config/queue}/__init__.py +0 -0
  75. {tests/foundation → foundation}/config/queue/test_foundation_config_queue.py +0 -0
  76. {tests/foundation → foundation}/config/queue/test_foundation_config_queue_brokers.py +0 -0
  77. {tests/foundation → foundation}/config/queue/test_foundation_config_queue_database.py +0 -0
  78. {tests/foundation/config/session → foundation/config/root}/__init__.py +0 -0
  79. {tests/foundation → foundation}/config/root/test_foundation_config_root_paths.py +0 -0
  80. {tests/foundation/config/startup → foundation/config/session}/__init__.py +0 -0
  81. {tests/foundation → foundation}/config/session/test_foundation_config_session.py +0 -0
  82. {tests/foundation/config/testing → foundation/config/startup}/__init__.py +0 -0
  83. {tests/foundation → foundation}/config/startup/test_foundation_config_startup.py +0 -0
  84. {tests/foundation/exceptions → foundation/config/testing}/__init__.py +0 -0
  85. {tests/foundation → foundation}/config/testing/test_foundation_config_testing.py +0 -0
  86. {tests/services/environment → foundation/exceptions}/__init__.py +0 -0
  87. {tests/foundation → foundation}/exceptions/test_foundation_config_exceptions.py +0 -0
  88. {orionis-0.413.0.dist-info → orionis-0.415.0.dist-info}/WHEEL +0 -0
  89. {orionis-0.413.0.dist-info → orionis-0.415.0.dist-info}/licenses/LICENCE +0 -0
  90. {orionis-0.413.0.dist-info → orionis-0.415.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.413.0"
8
+ VERSION = "0.415.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -5,57 +5,77 @@ class BaseEntity:
5
5
 
6
6
  def toDict(self) -> dict:
7
7
  """
8
- Converts the current instance into a dictionary representation.
8
+ Converts the current dataclass instance into a dictionary.
9
+
10
+ Parameters
11
+ ----------
12
+ None
9
13
 
10
14
  Returns
11
15
  -------
12
16
  dict
13
- Dictionary representation of the current instance.
17
+ A dictionary containing all fields of the instance, with field names as keys and their corresponding values.
18
+
19
+ Notes
20
+ -----
21
+ This method uses `dataclasses.asdict` to recursively convert the dataclass instance and any nested dataclasses into dictionaries.
22
+ Enum values are preserved as their actual values.
14
23
  """
24
+
25
+ # Use asdict to convert the dataclass instance to a dictionary, including nested dataclasses
15
26
  return asdict(self)
16
27
 
17
28
  def getFields(self):
18
29
  """
19
- Retrieves a list of field information for the current dataclass instance.
30
+ Retrieves detailed information about each field in the current dataclass instance.
31
+
32
+ Parameters
33
+ ----------
34
+ None
20
35
 
21
36
  Returns
22
37
  -------
23
- list
24
- A list of dictionaries, each containing details about a field:
25
- - name (str): The name of the field.
26
- - type (type): The type of the field.
27
- - default: The default value of the field, if specified; otherwise, the value from metadata or None.
28
- - metadata (mapping): The metadata associated with the field.
38
+ list of dict
39
+ Each dictionary in the returned list contains:
40
+ - name (str): The name of the field.
41
+ - types (list of str): The type(s) of the field, represented as a list of type names.
42
+ - default: The default value of the field, resolved from the field definition, default factory, or metadata.
43
+ - metadata (dict): The metadata associated with the field.
44
+
45
+ Notes
46
+ -----
47
+ - Handles complex field types, including unions and generics, by representing them as lists of type names.
48
+ - Resolves default values from direct assignment, default factories, or metadata, and normalizes dataclass and Enum values.
49
+ - Metadata defaults are normalized if present and callable or dataclass/Enum types.
29
50
  """
30
- # Dictionary to hold field information
51
+
52
+ # List to hold field information dictionaries
31
53
  __fields = []
32
54
 
33
- # Iterate over the fields of the dataclass and extract relevant information
55
+ # Iterate over all fields defined in the dataclass
34
56
  for field in fields(self):
35
57
 
36
- # Get the field name
58
+ # Extract the field name
37
59
  __name = field.name
38
60
 
39
- # Get the field type with better handling for complex types
61
+ # Attempt to get the type name; handles simple types
40
62
  __type = getattr(field.type, '__name__', None)
41
63
 
42
- # If the type is None, handle it
64
+ # If type name is not available, handle complex types (e.g., Unions)
43
65
  if __type is None:
44
-
45
- # Handle Union types or other complex types
46
66
  type_lst = []
47
67
  type_str = str(field.type).split('|')
48
68
  for itype in type_str:
49
69
  type_lst.append(itype.strip())
50
70
  __type = type_lst
51
71
 
52
- # Ensure __type is a list for consistency
72
+ # Ensure __type is always a list for consistency
53
73
  __type = type_lst if isinstance(__type, list) else [__type]
54
74
 
55
- # Extract metadata, default value, and type
75
+ # Extract metadata as a dictionary
56
76
  metadata = dict(field.metadata) if field.metadata else {}
57
77
 
58
- # If metadata contains a default value, normalize it
78
+ # Normalize default value in metadata if present
59
79
  if 'default' in metadata:
60
80
  metadata_default = metadata['default']
61
81
  if callable(metadata_default):
@@ -66,13 +86,12 @@ class BaseEntity:
66
86
  metadata_default = metadata_default.value
67
87
  metadata['default'] = metadata_default
68
88
 
69
- # Add the field information to the list
70
89
  __metadata = metadata
71
90
 
72
- # Extract the default value, if specified
91
+ # Initialize default value
73
92
  __default = None
74
93
 
75
- # Field has a direct default value
94
+ # Resolve default value from field definition
76
95
  if field.default is not MISSING:
77
96
  __default = field.default() if callable(field.default) else field.default
78
97
  if is_dataclass(__default):
@@ -80,7 +99,7 @@ class BaseEntity:
80
99
  elif isinstance(__default, Enum):
81
100
  __default = __default.value
82
101
 
83
- # Field has a default factory (like list, dict, etc.)
102
+ # Resolve default value from default factory if present
84
103
  elif field.default_factory is not MISSING:
85
104
  __default = field.default_factory() if callable(field.default_factory) else field.default_factory
86
105
  if is_dataclass(__default):
@@ -88,11 +107,11 @@ class BaseEntity:
88
107
  elif isinstance(__default, Enum):
89
108
  __default = __default.value
90
109
 
91
- # No default found, check metadata for custom default
110
+ # If no default found, check metadata for custom default
92
111
  else:
93
112
  __default = __metadata.get('default', None)
94
113
 
95
- # Append the field information to the list
114
+ # Append the field information dictionary to the list
96
115
  __fields.append({
97
116
  "name": __name,
98
117
  "types": __type,
@@ -100,5 +119,5 @@ class BaseEntity:
100
119
  "metadata": __metadata
101
120
  })
102
121
 
103
- # Return the list of field information
122
+ # Return the list of field information dictionaries
104
123
  return __fields
@@ -5,11 +5,17 @@ class Console(Facade):
5
5
  @classmethod
6
6
  def getFacadeAccessor(cls) -> str:
7
7
  """
8
- Get the service container binding key for the dumper component.
8
+ Returns the service container binding key used to resolve the console component.
9
+
10
+ This method provides the unique string identifier that the service container uses
11
+ to locate and instantiate the console service. It is typically used internally
12
+ by the Facade base class to delegate calls to the underlying implementation.
9
13
 
10
14
  Returns
11
15
  -------
12
16
  str
13
- The service container binding key.
17
+ The string key `"core.orionis.console"` that identifies the console service in the container.
14
18
  """
19
+
20
+ # Return the binding key for the console service in the container
15
21
  return "core.orionis.console"
@@ -5,11 +5,17 @@ class Dumper(Facade):
5
5
  @classmethod
6
6
  def getFacadeAccessor(cls) -> str:
7
7
  """
8
- Get the service container binding key for the dumper component.
8
+ Returns the binding key used to retrieve the dumper component from the service container.
9
+
10
+ This method provides the unique string identifier that the service container uses to resolve
11
+ and return the dumper service instance. It is typically used internally by the Facade base class
12
+ to access the underlying implementation.
9
13
 
10
14
  Returns
11
15
  -------
12
16
  str
13
- The service container binding key.
17
+ The string "core.orionis.dumper", which is the service container binding key for the dumper component.
14
18
  """
19
+
20
+ # Return the service container binding key for the dumper component
15
21
  return "core.orionis.dumper"
@@ -5,11 +5,18 @@ class Log(Facade):
5
5
  @classmethod
6
6
  def getFacadeAccessor(cls) -> str:
7
7
  """
8
- Get the service container binding key for the dumper component.
8
+ Returns the binding key used to resolve the logger service from the service container.
9
+
10
+ This method provides the unique identifier required by the service container to retrieve
11
+ the logger component. It is used internally by the Facade base class to delegate calls
12
+ to the appropriate service implementation.
9
13
 
10
14
  Returns
11
15
  -------
12
16
  str
13
- The service container binding key.
17
+ The binding key for the logger service in the service container, specifically
18
+ "core.orionis.logger".
14
19
  """
20
+
21
+ # Return the service container binding key for the logger component
15
22
  return "core.orionis.logger"
@@ -5,11 +5,18 @@ class PathResolver(Facade):
5
5
  @classmethod
6
6
  def getFacadeAccessor(cls):
7
7
  """
8
- Get the service container binding key for the dumper component.
8
+ Returns the service container binding key used to resolve the path resolver component.
9
+
10
+ This method provides the unique string identifier that the service container uses
11
+ to locate and retrieve the path resolver service. It is typically used internally
12
+ by the facade mechanism to delegate calls to the appropriate underlying implementation.
9
13
 
10
14
  Returns
11
15
  -------
12
16
  str
13
- The service container binding key.
17
+ The string key "core.orionis.path_resolver" that identifies the path resolver
18
+ service in the container.
14
19
  """
20
+
21
+ # Return the binding key for the path resolver service in the container
15
22
  return "core.orionis.path_resolver"
@@ -5,11 +5,18 @@ class ProgressBar(Facade):
5
5
  @classmethod
6
6
  def getFacadeAccessor(cls):
7
7
  """
8
- Get the service container binding key for the dumper component.
8
+ Returns the binding key used to retrieve the progress bar service from the service container.
9
+
10
+ This method provides the unique string identifier that the service container uses to resolve
11
+ the progress bar component. It is typically used internally by the Facade system to access
12
+ the underlying implementation.
9
13
 
10
14
  Returns
11
15
  -------
12
16
  str
13
- The service container binding key.
17
+ The binding key for the progress bar service in the service container, specifically
18
+ "core.orionis.progress_bar".
14
19
  """
20
+
21
+ # Return the service container binding key for the progress bar component
15
22
  return "core.orionis.progress_bar"
@@ -5,11 +5,18 @@ class Test(Facade):
5
5
  @classmethod
6
6
  def getFacadeAccessor(cls) -> str:
7
7
  """
8
- Get the service container binding key for the dumper component.
8
+ Returns the service container binding key for the testing component.
9
+
10
+ This method provides the unique string identifier used by the service container
11
+ to resolve the testing component. It is typically used internally by the Facade
12
+ system to retrieve the correct implementation from the container.
9
13
 
10
14
  Returns
11
15
  -------
12
16
  str
13
- The service container binding key.
17
+ The string key "core.orionis.testing" that identifies the testing component
18
+ in the service container.
14
19
  """
20
+
21
+ # Return the binding key for the testing component in the service container
15
22
  return "core.orionis.testing"
@@ -5,11 +5,18 @@ class Workers(Facade):
5
5
  @classmethod
6
6
  def getFacadeAccessor(cls):
7
7
  """
8
- Get the service container binding key for the dumper component.
8
+ Returns the service container binding key for the workers component.
9
+
10
+ This method provides the unique string identifier used by the service container
11
+ to resolve the workers service. It is typically used internally by the Facade
12
+ mechanism to access the underlying implementation.
9
13
 
10
14
  Returns
11
15
  -------
12
16
  str
13
- The service container binding key.
17
+ The string key "core.orionis.workers" that identifies the workers service
18
+ in the service container.
14
19
  """
20
+
21
+ # Return the binding key for the workers service in the container
15
22
  return "core.orionis.workers"
@@ -1,6 +1,5 @@
1
1
  import io
2
2
  import json
3
- import os
4
3
  import re
5
4
  import time
6
5
  import traceback
@@ -316,9 +315,27 @@ class UnitTest(IUnitTest):
316
315
  tests = self.__loader.discover(
317
316
  start_dir=str(full_path),
318
317
  pattern=self.__pattern,
319
- top_level_dir=None
318
+ top_level_dir="."
320
319
  )
321
320
 
321
+ # Check for failed test imports (unittest.loader._FailedTest)
322
+ for test in self.__flattenTestSuite(tests):
323
+ if test.__class__.__name__ == "_FailedTest":
324
+ # Extract the error message from the test's traceback
325
+ error_message = ""
326
+ if hasattr(test, "_exception"):
327
+ error_message = str(test._exception)
328
+ elif hasattr(test, "_outcome") and hasattr(test._outcome, "errors"):
329
+ error_message = str(test._outcome.errors)
330
+ else:
331
+ # Try to get error from test id or str(test)
332
+ error_message = str(test)
333
+ raise OrionisTestValueError(
334
+ f"Failed to import test module: {test.id()}.\n"
335
+ f"Error details: {error_message}\n"
336
+ "Please check for import errors or missing dependencies."
337
+ )
338
+
322
339
  # If name pattern is provided, filter tests by name
323
340
  if test_name_pattern:
324
341
  tests = self.__filterTestsByName(
@@ -365,6 +382,7 @@ class UnitTest(IUnitTest):
365
382
  f"Error importing tests from path '{str(full_path)}': {str(e)}.\n"
366
383
  "Please verify that the directory and test modules are accessible and correct."
367
384
  )
385
+
368
386
  except Exception as e:
369
387
 
370
388
  # Raise a general error for unexpected issues
@@ -700,6 +718,11 @@ class UnitTest(IUnitTest):
700
718
  # Iterate through all test cases in the original (possibly nested) suite
701
719
  for test_case in self.__flattenTestSuite(self.__suite):
702
720
 
721
+ # If it's a failed test, add it as-is to the flattened suite
722
+ if test_case.__class__.__name__ == "_FailedTest":
723
+ flattened_suite.addTest(test_case)
724
+ continue
725
+
703
726
  # Get the test method name using reflection
704
727
  rf_instance = ReflectionInstance(test_case)
705
728
  method_name = rf_instance.getAttribute("_testMethodName")
@@ -730,14 +753,7 @@ class UnitTest(IUnitTest):
730
753
  continue
731
754
 
732
755
  # Attempt to extract dependency information from the test method signature
733
- try:
734
- signature = rf_instance.getMethodDependencies(method_name)
735
- except Exception as e:
736
- raise OrionisTestValueError(
737
- f"Failed to resolve test dependencies in '../{method_name}.py. "
738
- f"This may be caused by incorrect imports, missing modules, or undefined classes. "
739
- f"Please verify that all test methods and their dependencies are correctly declared and accessible."
740
- )
756
+ signature = rf_instance.getMethodDependencies(method_name)
741
757
 
742
758
  # If there are no dependencies to resolve, or unresolved dependencies exist, add as-is
743
759
  if ((not signature.resolved and not signature.unresolved) or (not signature.resolved and len(signature.unresolved) > 0)):
@@ -66,7 +66,7 @@ class TestDumper(ITestDumper):
66
66
  SyncTestCase,
67
67
  unittest.TestCase,
68
68
  unittest.IsolatedAsyncioTestCase
69
- ),
69
+ )
70
70
  )
71
71
 
72
72
  except Exception:
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: orionis
3
- Version: 0.413.0
3
+ Version: 0.415.0
4
4
  Summary: Orionis Framework – Elegant, Fast, and Powerful.
5
5
  Home-page: https://github.com/orionis-framework/framework
6
6
  Author: Raul Mauricio Uñate Castro