orionis 0.404.0__py3-none-any.whl → 0.406.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 (165) 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 +18 -10
  34. orionis/foundation/config/logging/entities/daily.py +17 -9
  35. orionis/foundation/config/logging/entities/hourly.py +15 -7
  36. orionis/foundation/config/logging/entities/logging.py +12 -18
  37. orionis/foundation/config/logging/entities/monthly.py +16 -8
  38. orionis/foundation/config/logging/entities/stack.py +15 -7
  39. orionis/foundation/config/logging/entities/weekly.py +15 -7
  40. orionis/foundation/config/logging/validators/path.py +6 -0
  41. orionis/foundation/config/mail/entities/file.py +9 -36
  42. orionis/foundation/config/mail/entities/mail.py +22 -40
  43. orionis/foundation/config/mail/entities/mailers.py +29 -44
  44. orionis/foundation/config/mail/entities/smtp.py +47 -48
  45. orionis/foundation/config/queue/entities/brokers.py +19 -41
  46. orionis/foundation/config/queue/entities/database.py +24 -46
  47. orionis/foundation/config/queue/entities/queue.py +28 -40
  48. orionis/foundation/config/roots/paths.py +272 -468
  49. orionis/foundation/config/session/entities/session.py +23 -53
  50. orionis/foundation/config/startup.py +165 -135
  51. orionis/foundation/config/testing/entities/testing.py +137 -122
  52. orionis/foundation/config/testing/enums/__init__.py +6 -2
  53. orionis/foundation/config/testing/enums/drivers.py +16 -0
  54. orionis/foundation/config/testing/enums/verbosity.py +18 -0
  55. orionis/foundation/contracts/application.py +152 -362
  56. orionis/foundation/providers/console_provider.py +24 -2
  57. orionis/foundation/providers/dumper_provider.py +24 -2
  58. orionis/foundation/providers/logger_provider.py +24 -2
  59. orionis/foundation/providers/path_resolver_provider.py +25 -2
  60. orionis/foundation/providers/progress_bar_provider.py +24 -2
  61. orionis/foundation/providers/testing_provider.py +39 -0
  62. orionis/foundation/providers/workers_provider.py +24 -2
  63. orionis/metadata/framework.py +1 -1
  64. orionis/services/environment/helpers/functions.py +1 -2
  65. orionis/services/environment/key/__init__.py +0 -0
  66. orionis/services/environment/key/key_generator.py +37 -0
  67. orionis/services/log/handlers/filename.py +64 -0
  68. orionis/services/log/handlers/size_rotating.py +9 -40
  69. orionis/services/log/handlers/timed_rotating.py +9 -41
  70. orionis/services/log/log_service.py +9 -52
  71. orionis/support/entities/__init__.py +0 -0
  72. orionis/support/entities/base.py +104 -0
  73. orionis/support/facades/testing.py +15 -0
  74. orionis/support/facades/workers.py +1 -1
  75. orionis/test/cases/asynchronous.py +0 -11
  76. orionis/test/cases/synchronous.py +0 -9
  77. orionis/test/contracts/dumper.py +11 -4
  78. orionis/test/contracts/kernel.py +5 -110
  79. orionis/test/contracts/logs.py +27 -65
  80. orionis/test/contracts/printer.py +16 -128
  81. orionis/test/contracts/test_result.py +100 -0
  82. orionis/test/contracts/unit_test.py +87 -150
  83. orionis/test/core/unit_test.py +608 -554
  84. orionis/test/entities/result.py +22 -2
  85. orionis/test/enums/__init__.py +0 -2
  86. orionis/test/enums/status.py +14 -9
  87. orionis/test/exceptions/config.py +9 -1
  88. orionis/test/exceptions/failure.py +34 -11
  89. orionis/test/exceptions/persistence.py +10 -2
  90. orionis/test/exceptions/runtime.py +9 -1
  91. orionis/test/exceptions/value.py +13 -1
  92. orionis/test/kernel.py +87 -289
  93. orionis/test/output/dumper.py +82 -18
  94. orionis/test/output/printer.py +399 -156
  95. orionis/test/records/logs.py +203 -82
  96. orionis/test/validators/__init__.py +33 -0
  97. orionis/test/validators/base_path.py +45 -0
  98. orionis/test/validators/execution_mode.py +45 -0
  99. orionis/test/validators/fail_fast.py +37 -0
  100. orionis/test/validators/folder_path.py +34 -0
  101. orionis/test/validators/module_name.py +31 -0
  102. orionis/test/validators/name_pattern.py +40 -0
  103. orionis/test/validators/pattern.py +36 -0
  104. orionis/test/validators/persistent.py +42 -0
  105. orionis/test/validators/persistent_driver.py +43 -0
  106. orionis/test/validators/print_result.py +37 -0
  107. orionis/test/validators/tags.py +37 -0
  108. orionis/test/validators/throw_exception.py +39 -0
  109. orionis/test/validators/verbosity.py +37 -0
  110. orionis/test/validators/web_report.py +35 -0
  111. orionis/test/validators/workers.py +31 -0
  112. orionis/test/view/render.py +48 -54
  113. {orionis-0.404.0.dist-info → orionis-0.406.0.dist-info}/METADATA +1 -1
  114. {orionis-0.404.0.dist-info → orionis-0.406.0.dist-info}/RECORD +160 -108
  115. tests/container/__init__.py +0 -0
  116. tests/container/context/__init__.py +0 -0
  117. tests/container/context/test_manager.py +27 -0
  118. tests/container/context/test_scope.py +23 -0
  119. tests/container/entities/__init__.py +0 -0
  120. tests/container/entities/test_binding.py +133 -0
  121. tests/container/enums/__init__.py +0 -0
  122. tests/container/enums/test_lifetimes.py +63 -0
  123. tests/container/facades/__init__.py +0 -0
  124. tests/container/facades/test_facade.py +61 -0
  125. tests/container/mocks/__init__.py +0 -0
  126. tests/container/mocks/mock_complex_classes.py +482 -0
  127. tests/container/mocks/mock_simple_classes.py +32 -0
  128. tests/container/providers/__init__.py +0 -0
  129. tests/container/providers/test_providers.py +48 -0
  130. tests/container/resolver/__init__.py +0 -0
  131. tests/container/resolver/test_resolver.py +55 -0
  132. tests/container/test_container.py +254 -0
  133. tests/container/test_singleton.py +98 -0
  134. tests/container/test_thread_safety.py +217 -0
  135. tests/container/validators/__init__.py +0 -0
  136. tests/container/validators/test_implements.py +140 -0
  137. tests/container/validators/test_is_abstract_class.py +99 -0
  138. tests/container/validators/test_is_callable.py +73 -0
  139. tests/container/validators/test_is_concrete_class.py +97 -0
  140. tests/container/validators/test_is_instance.py +105 -0
  141. tests/container/validators/test_is_not_subclass.py +117 -0
  142. tests/container/validators/test_is_subclass.py +115 -0
  143. tests/container/validators/test_is_valid_alias.py +113 -0
  144. tests/container/validators/test_lifetime.py +75 -0
  145. tests/foundation/config/logging/test_foundation_config_logging_chunked.py +12 -34
  146. tests/foundation/config/logging/test_foundation_config_logging_daily.py +11 -11
  147. tests/foundation/config/logging/test_foundation_config_logging_hourly.py +7 -8
  148. tests/foundation/config/logging/test_foundation_config_logging_monthly.py +7 -10
  149. tests/foundation/config/logging/test_foundation_config_logging_stack.py +6 -11
  150. tests/foundation/config/logging/test_foundation_config_logging_weekly.py +6 -5
  151. tests/foundation/config/testing/test_foundation_config_testing.py +1 -1
  152. tests/metadata/test_metadata_framework.py +18 -18
  153. tests/testing/test_testing_result.py +117 -117
  154. tests/testing/test_testing_unit.py +209 -209
  155. orionis/foundation/config/base.py +0 -112
  156. orionis/test/arguments/parser.py +0 -187
  157. orionis/test/contracts/parser.py +0 -43
  158. orionis/test/entities/arguments.py +0 -38
  159. orionis/test/enums/execution_mode.py +0 -16
  160. /orionis/{test/arguments → console/base/contracts}/__init__.py +0 -0
  161. /orionis/foundation/config/testing/enums/{test_mode.py → mode.py} +0 -0
  162. {orionis-0.404.0.dist-info → orionis-0.406.0.dist-info}/WHEEL +0 -0
  163. {orionis-0.404.0.dist-info → orionis-0.406.0.dist-info}/licenses/LICENCE +0 -0
  164. {orionis-0.404.0.dist-info → orionis-0.406.0.dist-info}/top_level.txt +0 -0
  165. {orionis-0.404.0.dist-info → orionis-0.406.0.dist-info}/zip-safe +0 -0
@@ -1,11 +1,13 @@
1
- from dataclasses import dataclass, field, asdict, fields
1
+ from dataclasses import dataclass, field
2
2
  from typing import List, Optional
3
3
  from orionis.foundation.exceptions import OrionisIntegrityException
4
+ from orionis.support.entities.base import BaseEntity
4
5
 
5
6
  @dataclass(unsafe_hash=True, kw_only=True)
6
- class Cors:
7
+ class Cors(BaseEntity):
7
8
  """
8
9
  CORS configuration compatible with Starlette CORSMiddleware.
10
+
9
11
  Attributes:
10
12
  allow_origins (List[str]): List of allowed origins. Use ["*"] to allow all origins.
11
13
  allow_origin_regex (Optional[str]): Regular expression to match allowed origins.
@@ -14,6 +16,7 @@ class Cors:
14
16
  expose_headers (List[str]): List of headers exposed to the browser.
15
17
  allow_credentials (bool): Whether to allow credentials (cookies, authorization headers, etc.).
16
18
  max_age (Optional[int]): Maximum time (in seconds) for the preflight request to be cached.
19
+
17
20
  Methods:
18
21
  __post_init__():
19
22
  Validates the types of the configuration attributes after initialization.
@@ -22,58 +25,58 @@ class Cors:
22
25
  """
23
26
 
24
27
  allow_origins: List[str] = field(
25
- default_factory=lambda: ["*"],
26
- metadata={
28
+ default_factory = lambda: ["*"],
29
+ metadata = {
27
30
  "description": "List of allowed origins. Use [\"*\"] to allow all origins.",
28
- "deafault": ["*"],
31
+ "deafault": ["*"]
29
32
  },
30
33
  )
31
34
 
32
35
  allow_origin_regex: Optional[str] = field(
33
- default=None,
34
- metadata={
36
+ default = None,
37
+ metadata = {
35
38
  "description": "Regular expression pattern to match allowed origins.",
36
- "default": None,
39
+ "default": None
37
40
  },
38
41
  )
39
42
 
40
43
  allow_methods: List[str] = field(
41
- default_factory=lambda: ["*"],
42
- metadata={
44
+ default_factory = lambda: ["*"],
45
+ metadata = {
43
46
  "description": "List of allowed HTTP methods. Use [\"*\"] to allow all methods.",
44
- "default": ["*"],
47
+ "default": ["*"]
45
48
  },
46
49
  )
47
50
 
48
51
  allow_headers: List[str] = field(
49
- default_factory=lambda: ["*"],
50
- metadata={
52
+ default_factory = lambda: ["*"],
53
+ metadata = {
51
54
  "description": "List of allowed HTTP headers. Use [\"*\"] to allow all headers.",
52
- "default": ["*"],
55
+ "default": ["*"]
53
56
  },
54
57
  )
55
58
 
56
59
  expose_headers: List[str] = field(
57
- default_factory=lambda:[],
58
- metadata={
60
+ default_factory = lambda: [],
61
+ metadata = {
59
62
  "description": "List of headers exposed to the browser.",
60
- "default": [],
63
+ "default": []
61
64
  },
62
65
  )
63
66
 
64
67
  allow_credentials: bool = field(
65
- default=False,
66
- metadata={
68
+ default = False,
69
+ metadata = {
67
70
  "description": "Whether to allow credentials (cookies, authorization headers, etc.).",
68
- "default": False,
71
+ "default": False
69
72
  },
70
73
  )
71
74
 
72
75
  max_age: Optional[int] = field(
73
- default=600,
74
- metadata={
76
+ default = 600,
77
+ metadata = {
75
78
  "description": "Maximum time (in seconds) for preflight request caching.",
76
- "default": 600,
79
+ "default": 600
77
80
  },
78
81
  )
79
82
 
@@ -91,61 +94,45 @@ class Cors:
91
94
  - allow_credentials is not a boolean.
92
95
  - max_age is not an integer or None.
93
96
  """
97
+
98
+ # Validate `allow_origins` attribute
94
99
  if not isinstance(self.allow_origins, list):
95
100
  raise OrionisIntegrityException(
96
101
  "Invalid type for 'allow_origins': expected a list of strings."
97
102
  )
103
+
104
+ # Validate `allow_origin_regex` attribute
98
105
  if self.allow_origin_regex is not None and not isinstance(self.allow_origin_regex, str):
99
106
  raise OrionisIntegrityException(
100
107
  "Invalid type for 'allow_origin_regex': expected a string or None."
101
108
  )
109
+
110
+ # Validate `allow_methods` attribute
102
111
  if not isinstance(self.allow_methods, list):
103
112
  raise OrionisIntegrityException(
104
113
  "Invalid type for 'allow_methods': expected a list of strings."
105
114
  )
115
+
116
+ # Validate `allow_headers` attribute
106
117
  if not isinstance(self.allow_headers, list):
107
118
  raise OrionisIntegrityException(
108
119
  "Invalid type for 'allow_headers': expected a list of strings."
109
120
  )
121
+
122
+ # Validate `expose_headers` attribute
110
123
  if not isinstance(self.expose_headers, list):
111
124
  raise OrionisIntegrityException(
112
125
  "Invalid type for 'expose_headers': expected a list of strings."
113
126
  )
127
+
128
+ # Validate `allow_credentials` attribute
114
129
  if not isinstance(self.allow_credentials, bool):
115
130
  raise OrionisIntegrityException(
116
131
  "Invalid type for 'allow_credentials': expected a boolean."
117
132
  )
133
+
134
+ # Validate `max_age` attribute
118
135
  if self.max_age is not None and not isinstance(self.max_age, int):
119
136
  raise OrionisIntegrityException(
120
137
  "Invalid type for 'max_age': expected an integer or None."
121
- )
122
-
123
- def toDict(self) -> dict:
124
- """
125
- Convert the object to a dictionary representation.
126
- Returns:
127
- dict: A dictionary representation of the Dataclass object.
128
- """
129
- return asdict(self)
130
-
131
- def getFields(self):
132
- """
133
- Retrieves a list of field information for the current dataclass instance.
134
-
135
- Returns:
136
- list: A list of dictionaries, each containing details about a field:
137
- - name (str): The name of the field.
138
- - type (type): The type of the field.
139
- - default: The default value of the field, if specified; otherwise, the value from metadata or None.
140
- - metadata (mapping): The metadata associated with the field.
141
- """
142
- __fields = []
143
- for field in fields(self):
144
- __metadata = dict(field.metadata) or {}
145
- __fields.append({
146
- "name": field.name,
147
- "type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
148
- "default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
149
- "metadata": __metadata
150
- })
151
- return __fields
138
+ )
@@ -1,12 +1,13 @@
1
- from dataclasses import asdict, dataclass, field, fields
1
+ from dataclasses import dataclass, field
2
2
  from orionis.foundation.config.database.entities.mysql import MySQL
3
3
  from orionis.foundation.config.database.entities.oracle import Oracle
4
4
  from orionis.foundation.config.database.entities.pgsql import PGSQL
5
5
  from orionis.foundation.config.database.entities.sqlite import SQLite
6
6
  from orionis.foundation.exceptions import OrionisIntegrityException
7
+ from orionis.support.entities.base import BaseEntity
7
8
 
8
9
  @dataclass(unsafe_hash=True, kw_only=True)
9
- class Connections:
10
+ class Connections(BaseEntity):
10
11
  """
11
12
  Data class to represent all database connections used by the application.
12
13
 
@@ -21,35 +22,35 @@ class Connections:
21
22
  oracle : Oracle
22
23
  Configuration for the Oracle database connection.
23
24
  """
24
- sqlite: SQLite = field(
25
- default_factory=SQLite,
26
- metadata={
25
+ sqlite: SQLite | dict = field(
26
+ default_factory = lambda: SQLite(),
27
+ metadata = {
27
28
  "description": "SQLite database connection configuration",
28
- "default": "SQLite()"
29
+ "default": SQLite().toDict()
29
30
  }
30
31
  )
31
32
 
32
- mysql: MySQL = field(
33
- default_factory=MySQL,
34
- metadata={
33
+ mysql: MySQL | dict = field(
34
+ default_factory = lambda: MySQL(),
35
+ metadata = {
35
36
  "description": "MySQL database connection configuration",
36
- "default": "MySQL()"
37
+ "default": MySQL().toDict()
37
38
  }
38
39
  )
39
40
 
40
- pgsql: PGSQL = field(
41
- default_factory=PGSQL,
42
- metadata={
41
+ pgsql: PGSQL | dict = field(
42
+ default_factory = lambda: PGSQL(),
43
+ metadata = {
43
44
  "description": "PostgreSQL database connection configuration",
44
- "default": "PGSQL()"
45
+ "default": PGSQL().toDict()
45
46
  }
46
47
  )
47
48
 
48
- oracle: Oracle = field(
49
- default_factory=Oracle,
50
- metadata={
49
+ oracle: Oracle | dict = field(
50
+ default_factory = lambda: Oracle(),
51
+ metadata = {
51
52
  "description": "Oracle database connection configuration",
52
- "default": "Oracle()"
53
+ "default": Oracle().toDict()
53
54
  }
54
55
  )
55
56
 
@@ -60,52 +61,35 @@ class Connections:
60
61
  Raises:
61
62
  OrionisIntegrityException: If any attribute is not an instance of its expected class.
62
63
  """
63
- if not isinstance(self.sqlite, SQLite):
64
+
65
+ # Validate `sqlite` attribute
66
+ if not isinstance(self.sqlite, (SQLite, dict)):
64
67
  raise OrionisIntegrityException(
65
- f"Invalid type for 'sqlite': expected 'Sqlite', got '{type(self.sqlite).__name__}'."
68
+ f"Invalid type for 'sqlite': expected 'SQLite' or 'dict', got '{type(self.sqlite).__name__}'."
66
69
  )
70
+ if isinstance(self.sqlite, dict):
71
+ self.sqlite = SQLite(**self.sqlite)
67
72
 
68
- if not isinstance(self.mysql, MySQL):
73
+ # Validate `mysql` attribute
74
+ if not isinstance(self.mysql, (MySQL, dict)):
69
75
  raise OrionisIntegrityException(
70
- f"Invalid type for 'mysql': expected 'Mysql', got '{type(self.mysql).__name__}'."
76
+ f"Invalid type for 'mysql': expected 'MySQL' or 'dict', got '{type(self.mysql).__name__}'."
71
77
  )
78
+ if isinstance(self.mysql, dict):
79
+ self.mysql = MySQL(**self.mysql)
72
80
 
73
- if not isinstance(self.pgsql, PGSQL):
81
+ # Validate `pgsql` attribute
82
+ if not isinstance(self.pgsql, (PGSQL, dict)):
74
83
  raise OrionisIntegrityException(
75
- f"Invalid type for 'pgsql': expected 'Pgsql', got '{type(self.pgsql).__name__}'."
84
+ f"Invalid type for 'pgsql': expected 'PGSQL' or 'dict', got '{type(self.pgsql).__name__}'."
76
85
  )
86
+ if isinstance(self.pgsql, dict):
87
+ self.pgsql = PGSQL(**self.pgsql)
77
88
 
78
- if not isinstance(self.oracle, Oracle):
89
+ # Validate `oracle` attribute
90
+ if not isinstance(self.oracle, (Oracle, dict)):
79
91
  raise OrionisIntegrityException(
80
- f"Invalid type for 'oracle': expected 'Oracle', got '{type(self.oracle).__name__}'."
92
+ f"Invalid type for 'oracle': expected 'Oracle' or 'dict', got '{type(self.oracle).__name__}'."
81
93
  )
82
-
83
- def toDict(self) -> dict:
84
- """
85
- Convert the object to a dictionary representation.
86
- Returns:
87
- dict: A dictionary representation of the Dataclass object.
88
- """
89
- return asdict(self)
90
-
91
- def getFields(self):
92
- """
93
- Retrieves a list of field information for the current dataclass instance.
94
-
95
- Returns:
96
- list: A list of dictionaries, each containing details about a field:
97
- - name (str): The name of the field.
98
- - type (type): The type of the field.
99
- - default: The default value of the field, if specified; otherwise, the value from metadata or None.
100
- - metadata (mapping): The metadata associated with the field.
101
- """
102
- __fields = []
103
- for field in fields(self):
104
- __metadata = dict(field.metadata) or {}
105
- __fields.append({
106
- "name": field.name,
107
- "type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
108
- "default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
109
- "metadata": __metadata
110
- })
111
- return __fields
94
+ if isinstance(self.oracle, dict):
95
+ self.oracle = Oracle(**self.oracle)
@@ -1,10 +1,11 @@
1
- from dataclasses import asdict, dataclass, field, fields
1
+ from dataclasses import dataclass, field, fields
2
2
  from orionis.foundation.config.database.entities.connections import Connections
3
3
  from orionis.services.environment.env import Env
4
4
  from orionis.foundation.exceptions import OrionisIntegrityException
5
+ from orionis.support.entities.base import BaseEntity
5
6
 
6
7
  @dataclass(unsafe_hash=True, kw_only=True)
7
- class Database:
8
+ class Database(BaseEntity):
8
9
  """
9
10
  Data class to represent the general database configuration.
10
11
 
@@ -16,18 +17,18 @@ class Database:
16
17
  The different database connections available to the application.
17
18
  """
18
19
  default: str = field(
19
- default_factory=lambda: Env.get("DB_CONNECTION", "sqlite"),
20
+ default = Env.get("DB_CONNECTION", "sqlite"),
20
21
  metadata={
21
22
  "description": "Default database connection name",
22
23
  "default": "sqlite"
23
24
  }
24
25
  )
25
26
 
26
- connections: Connections = field(
27
- default_factory=Connections,
27
+ connections: Connections | dict = field(
28
+ default_factory = lambda: Connections(),
28
29
  metadata={
29
30
  "description": "Database connections",
30
- "default": "Connections()"
31
+ "default": Connections().toDict()
31
32
  }
32
33
  )
33
34
 
@@ -50,35 +51,7 @@ class Database:
50
51
  raise OrionisIntegrityException(f"The 'default' attribute cannot be empty. Options are: {str(options)}")
51
52
 
52
53
  # Validate connections attribute
53
- if not self.connections or not isinstance(self.connections, Connections):
54
- raise OrionisIntegrityException("The 'connections' attribute must be of type Connections.")
55
-
56
- def toDict(self) -> dict:
57
- """
58
- Convert the object to a dictionary representation.
59
- Returns:
60
- dict: A dictionary representation of the Dataclass object.
61
- """
62
- return asdict(self)
63
-
64
- def getFields(self):
65
- """
66
- Retrieves a list of field information for the current dataclass instance.
67
-
68
- Returns:
69
- list: A list of dictionaries, each containing details about a field:
70
- - name (str): The name of the field.
71
- - type (type): The type of the field.
72
- - default: The default value of the field, if specified; otherwise, the value from metadata or None.
73
- - metadata (mapping): The metadata associated with the field.
74
- """
75
- __fields = []
76
- for field in fields(self):
77
- __metadata = dict(field.metadata) or {}
78
- __fields.append({
79
- "name": field.name,
80
- "type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
81
- "default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
82
- "metadata": __metadata
83
- })
84
- return __fields
54
+ if not self.connections or not isinstance(self.connections, (Connections, dict)):
55
+ raise OrionisIntegrityException("The 'connections' attribute must be an instance of Connections or a non-empty dictionary.")
56
+ if isinstance(self.connections, dict):
57
+ self.connections = Connections(**self.connections)
@@ -1,4 +1,4 @@
1
- from dataclasses import asdict, dataclass, field, fields
1
+ from dataclasses import dataclass, field
2
2
  from typing import Optional
3
3
  from orionis.foundation.config.database.enums import (
4
4
  MySQLCharset,
@@ -7,9 +7,10 @@ from orionis.foundation.config.database.enums import (
7
7
  )
8
8
  from orionis.foundation.exceptions import OrionisIntegrityException
9
9
  from orionis.services.environment.env import Env
10
+ from orionis.support.entities.base import BaseEntity
10
11
 
11
12
  @dataclass(unsafe_hash=True, kw_only=True)
12
- class MySQL:
13
+ class MySQL(BaseEntity):
13
14
  """
14
15
  Data class to represent the MySQL database configuration.
15
16
 
@@ -44,107 +45,106 @@ class MySQL:
44
45
  """
45
46
 
46
47
  driver: str = field(
47
- default="mysql",
48
- metadata={
48
+ default = "mysql",
49
+ metadata = {
49
50
  "description": "The database driver being used.",
50
- "default": "mysql",
51
+ "default": "mysql"
51
52
  }
52
53
  )
53
54
 
54
55
  host: str = field(
55
- default_factory=lambda: Env.get("DB_HOST", "127.0.0.1"),
56
- metadata={
56
+ default = Env.get("DB_HOST", "127.0.0.1"),
57
+ metadata = {
57
58
  "description": "The host address for the MySQL server.",
58
- "default": "127.0.0.1",
59
+ "default": "127.0.0.1"
59
60
  }
60
61
  )
61
62
 
62
63
  port: int = field(
63
- default_factory=lambda: Env.get("DB_PORT", 3306),
64
- metadata={
64
+ default = Env.get("DB_PORT", 3306),
65
+ metadata = {
65
66
  "description": "The port for connecting to the MySQL server.",
66
- "default": 3306,
67
+ "default": 3306
67
68
  }
68
69
  )
69
70
 
70
71
  database: str = field(
71
- default_factory=lambda: Env.get("DB_DATABASE", "orionis"),
72
- metadata={
72
+ default = Env.get("DB_DATABASE", "orionis"),
73
+ metadata = {
73
74
  "description": "The name of the MySQL database.",
74
- "default": "orionis",
75
+ "default": "orionis"
75
76
  }
76
77
  )
77
78
 
78
79
  username: str = field(
79
- default_factory=lambda: Env.get("DB_USERNAME", "root"),
80
- metadata={
80
+ default = Env.get("DB_USERNAME", "root"),
81
+ metadata = {
81
82
  "description": "The username for connecting to the MySQL database.",
82
- "default": "root",
83
+ "default": "root"
83
84
  }
84
85
  )
85
86
 
86
87
  password: str = field(
87
- default_factory=lambda: Env.get("DB_PASSWORD", ""),
88
- metadata={
88
+ default = Env.get("DB_PASSWORD", ""),
89
+ metadata = {
89
90
  "description": "The password for the MySQL database.",
90
- "default": "secret",
91
+ "default": ""
91
92
  }
92
93
  )
93
94
 
94
95
  unix_socket: str = field(
95
- default_factory=lambda: Env.get("DB_SOCKET", ""),
96
- metadata={
96
+ default = Env.get("DB_SOCKET", ""),
97
+ metadata = {
97
98
  "description": "The path to the Unix socket for MySQL connections (optional).",
98
- "default": "",
99
+ "default": ""
99
100
  }
100
101
  )
101
102
 
102
103
  charset: str | MySQLCharset = field(
103
- default=MySQLCharset.UTF8MB4,
104
- metadata={
104
+ default = MySQLCharset.UTF8MB4.value,
105
+ metadata = {
105
106
  "description": "The charset used for the connection.",
106
- "default": "utf8mb4",
107
+ "default": MySQLCharset.UTF8MB4.value
107
108
  }
108
109
  )
109
110
 
110
111
  collation: str | MySQLCollation = field(
111
- default=MySQLCollation.UTF8MB4_UNICODE_CI,
112
- metadata={
112
+ default = MySQLCollation.UTF8MB4_UNICODE_CI.value,
113
+ metadata = {
113
114
  "description": "The collation for the database.",
114
- "default": "utf8mb4_unicode_ci",
115
+ "default": MySQLCollation.UTF8MB4_UNICODE_CI.value
115
116
  }
116
117
  )
117
118
 
118
119
  prefix: str = field(
119
- default="",
120
- metadata={
120
+ default = "",
121
+ metadata = {
121
122
  "description": "Prefix for table names.",
122
- "default": "",
123
+ "default": ""
123
124
  }
124
125
  )
125
126
 
126
127
  prefix_indexes: bool = field(
127
- default=True,
128
- metadata={
128
+ default = True,
129
+ metadata = {
129
130
  "description": "Whether to prefix index names.",
130
- "default": True,
131
+ "default": True
131
132
  }
132
133
  )
133
134
 
134
135
  strict: bool = field(
135
- default=True,
136
- metadata={
136
+ default = True,
137
+ metadata = {
137
138
  "description": "Whether to enforce strict SQL mode.",
138
- "default": True,
139
+ "default": True
139
140
  }
140
141
  )
141
142
 
142
- engine: Optional[str | MySQLEngine] = field(
143
- default=MySQLEngine.INNODB,
144
- metadata={
143
+ engine: str | MySQLEngine = field(
144
+ default = MySQLEngine.INNODB.value,
145
+ metadata = {
145
146
  "description": "The storage engine for the MySQL database (optional).",
146
- "default": MySQLEngine.INNODB,
147
- "type": str,
147
+ "default": MySQLEngine.INNODB.value
148
148
  }
149
149
  )
150
150
 
@@ -154,6 +154,7 @@ class MySQL:
154
154
  This method performs comprehensive validation on the instance attributes to ensure
155
155
  that all required fields are present and correctly typed. It raises an
156
156
  OrionisIntegrityException with a descriptive message if any validation fails.
157
+
157
158
  Validations performed:
158
159
  - Host: Must be a non-empty string.
159
160
  - Port: Must be an integer between 1 and 65535.
@@ -167,12 +168,13 @@ class MySQL:
167
168
  - Prefix indexes: Must be a boolean.
168
169
  - Strict: Must be a boolean.
169
170
  - Engine: If provided, must be a string.
171
+
170
172
  Raises:
171
173
  OrionisIntegrityException: If any attribute fails validation.
172
174
  """
173
175
 
174
176
  # Validate driver
175
- if self.driver != 'mysql':
177
+ if self.driver not in ['mysql']:
176
178
  raise OrionisIntegrityException("Invalid driver: expected 'mysql'. Please ensure the 'driver' attribute is set to 'mysql'.")
177
179
 
178
180
  # Validate host
@@ -180,7 +182,7 @@ class MySQL:
180
182
  raise OrionisIntegrityException("Database host must be a non-empty string.")
181
183
 
182
184
  # Validate port type
183
- if not isinstance(self.port, (int)):
185
+ if not isinstance(self.port, int):
184
186
  raise OrionisIntegrityException("Database port must be an integer.")
185
187
 
186
188
  # Validate port range
@@ -261,34 +263,4 @@ class MySQL:
261
263
  else:
262
264
  self.engine = MySQLEngine[_value].value
263
265
  elif isinstance(self.engine, MySQLEngine):
264
- self.engine = self.engine.value
265
-
266
- def toDict(self) -> dict:
267
- """
268
- Convert the object to a dictionary representation.
269
- Returns:
270
- dict: A dictionary representation of the Dataclass object.
271
- """
272
- return asdict(self)
273
-
274
- def getFields(self):
275
- """
276
- Retrieves a list of field information for the current dataclass instance.
277
-
278
- Returns:
279
- list: A list of dictionaries, each containing details about a field:
280
- - name (str): The name of the field.
281
- - type (type): The type of the field.
282
- - default: The default value of the field, if specified; otherwise, the value from metadata or None.
283
- - metadata (mapping): The metadata associated with the field.
284
- """
285
- __fields = []
286
- for field in fields(self):
287
- __metadata = dict(field.metadata) or {}
288
- __fields.append({
289
- "name": field.name,
290
- "type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
291
- "default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
292
- "metadata": __metadata
293
- })
294
- return __fields
266
+ self.engine = self.engine.value