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
@@ -3,15 +3,37 @@ from orionis.console.output.contracts.console import IConsole
3
3
  from orionis.container.providers.service_provider import ServiceProvider
4
4
 
5
5
  class ConsoleProvider(ServiceProvider):
6
+ """
7
+ ConsoleProvider
8
+ ===============
9
+
10
+ Registers the console output service in the application container.
11
+ Provides access to various console output features, including information, warnings, errors, debug messages, tables, confirmations, and password prompts.
12
+
13
+ Methods
14
+ -------
15
+ register()
16
+ Registers the console service in the application container.
17
+ boot()
18
+ Performs post-registration initialization if needed.
19
+ """
6
20
 
7
21
  def register(self) -> None:
8
22
  """
9
- Register services into the application container.
23
+ Registers the console service in the application container.
24
+
25
+ Returns
26
+ -------
27
+ None
10
28
  """
11
29
  self.app.transient(IConsole, Console, alias="core.orionis.console")
12
30
 
13
31
  def boot(self) -> None:
14
32
  """
15
- Perform any post-registration bootstrapping or initialization.
33
+ Performs post-registration initialization if needed.
34
+
35
+ Returns
36
+ -------
37
+ None
16
38
  """
17
39
  pass
@@ -3,15 +3,37 @@ from orionis.console.dumper.contracts.dump import IDebug
3
3
  from orionis.container.providers.service_provider import ServiceProvider
4
4
 
5
5
  class DumperProvider(ServiceProvider):
6
+ """
7
+ DumperProvider
8
+ ==============
9
+
10
+ Registers the debug message service in the application container.
11
+ Provides access to debug message printing, error reporting, and other console diagnostics.
12
+
13
+ Methods
14
+ -------
15
+ register()
16
+ Registers the debug service in the application container.
17
+ boot()
18
+ Performs post-registration initialization if needed.
19
+ """
6
20
 
7
21
  def register(self) -> None:
8
22
  """
9
- Register services into the application container.
23
+ Registers the debug service in the application container.
24
+
25
+ Returns
26
+ -------
27
+ None
10
28
  """
11
29
  self.app.transient(IDebug, Debug, alias="core.orionis.dumper")
12
30
 
13
31
  def boot(self) -> None:
14
32
  """
15
- Perform any post-registration bootstrapping or initialization.
33
+ Performs post-registration initialization if needed.
34
+
35
+ Returns
36
+ -------
37
+ None
16
38
  """
17
39
  pass
@@ -3,15 +3,37 @@ from orionis.services.log.contracts.log_service import ILoggerService
3
3
  from orionis.services.log.log_service import LoggerService
4
4
 
5
5
  class LoggerProvider(ServiceProvider):
6
+ """
7
+ LoggerProvider
8
+ ==============
9
+
10
+ Registers the logging service in the application container.
11
+ Provides a `LoggerService` instance for application-wide logging.
12
+
13
+ Methods
14
+ -------
15
+ register()
16
+ Registers the logging service in the application container.
17
+ boot()
18
+ Performs post-registration initialization if needed.
19
+ """
6
20
 
7
21
  def register(self) -> None:
8
22
  """
9
- Register services into the application container.
23
+ Registers the logging service in the application container.
24
+
25
+ Returns
26
+ -------
27
+ None
10
28
  """
11
29
  self.app.instance(ILoggerService, LoggerService(self.app.config('logging')), alias="core.orionis.logger")
12
30
 
13
31
  def boot(self) -> None:
14
32
  """
15
- Perform any post-registration bootstrapping or initialization.
33
+ Performs post-registration initialization if needed.
34
+
35
+ Returns
36
+ -------
37
+ None
16
38
  """
17
39
  pass
@@ -3,15 +3,38 @@ from orionis.services.paths.contracts.resolver import IResolver
3
3
  from orionis.services.paths.resolver import Resolver
4
4
 
5
5
  class PathResolverProvider(ServiceProvider):
6
+ """
7
+ PathResolverProvider
8
+ ===================
9
+
10
+ Registers the path resolution service in the application container.
11
+ Provides compatibility with the file system for resolving paths.
12
+
13
+ Methods
14
+ -------
15
+ register()
16
+ Registers the path resolver service in the application container.
17
+ boot()
18
+ Performs post-registration initialization if needed.
19
+ """
20
+
6
21
 
7
22
  def register(self) -> None:
8
23
  """
9
- Register services into the application container.
24
+ Registers the path resolver service in the application container.
25
+
26
+ Returns
27
+ -------
28
+ None
10
29
  """
11
30
  self.app.transient(IResolver, Resolver, alias="core.orionis.path_resolver")
12
31
 
13
32
  def boot(self) -> None:
14
33
  """
15
- Perform any post-registration bootstrapping or initialization.
34
+ Performs post-registration initialization if needed.
35
+
36
+ Returns
37
+ -------
38
+ None
16
39
  """
17
40
  pass
@@ -3,15 +3,37 @@ from orionis.console.dynamic.progress_bar import ProgressBar
3
3
  from orionis.container.providers.service_provider import ServiceProvider
4
4
 
5
5
  class ProgressBarProvider(ServiceProvider):
6
+ """
7
+ ProgressBarProvider
8
+ ===================
9
+
10
+ Registers the dynamic progress bar service in the application container.
11
+ Provides a console progress bar for visual feedback during operations.
12
+
13
+ Methods
14
+ -------
15
+ register()
16
+ Registers the progress bar service in the application container.
17
+ boot()
18
+ Performs post-registration initialization if needed.
19
+ """
6
20
 
7
21
  def register(self) -> None:
8
22
  """
9
- Register services into the application container.
23
+ Registers the progress bar service in the application container.
24
+
25
+ Returns
26
+ -------
27
+ None
10
28
  """
11
29
  self.app.transient(IProgressBar, ProgressBar, alias="core.orionis.progress_bar")
12
30
 
13
31
  def boot(self) -> None:
14
32
  """
15
- Perform any post-registration bootstrapping or initialization.
33
+ Performs post-registration initialization if needed.
34
+
35
+ Returns
36
+ -------
37
+ None
16
38
  """
17
39
  pass
@@ -0,0 +1,39 @@
1
+ from orionis.container.providers.service_provider import ServiceProvider
2
+ from orionis.test.contracts.unit_test import IUnitTest
3
+ from orionis.test.core.unit_test import UnitTest
4
+
5
+ class TestingProvider(ServiceProvider):
6
+ """
7
+ TestingProvider
8
+ ===============
9
+
10
+ Registers the unit testing environment service in the application container.
11
+ Provides a native unit testing framework for Orionis with features beyond common frameworks.
12
+
13
+ Methods
14
+ -------
15
+ register()
16
+ Registers the unit testing service in the application container.
17
+ boot()
18
+ Performs post-registration initialization if needed.
19
+ """
20
+
21
+ def register(self) -> None:
22
+ """
23
+ Registers the unit testing service in the application container.
24
+
25
+ Returns
26
+ -------
27
+ None
28
+ """
29
+ self.app.singleton(IUnitTest, UnitTest, alias="core.orionis.testing")
30
+
31
+ def boot(self) -> None:
32
+ """
33
+ Performs post-registration initialization if needed.
34
+
35
+ Returns
36
+ -------
37
+ None
38
+ """
39
+ pass
@@ -3,15 +3,37 @@ from orionis.services.system.contracts.workers import IWorkers
3
3
  from orionis.services.system.workers import Workers
4
4
 
5
5
  class WorkersProvider(ServiceProvider):
6
+ """
7
+ WorkersProvider
8
+ ===============
9
+
10
+ Registers the worker management service in the application container.
11
+ Determines the optimal number of workers to start based on system analysis.
12
+
13
+ Methods
14
+ -------
15
+ register()
16
+ Registers the worker service in the application container.
17
+ boot()
18
+ Performs post-registration initialization if needed.
19
+ """
6
20
 
7
21
  def register(self) -> None:
8
22
  """
9
- Register services into the application container.
23
+ Registers the worker service in the application container.
24
+
25
+ Returns
26
+ -------
27
+ None
10
28
  """
11
29
  self.app.transient(IWorkers, Workers, alias="core.orionis.workers")
12
30
 
13
31
  def boot(self) -> None:
14
32
  """
15
- Perform any post-registration bootstrapping or initialization.
33
+ Performs post-registration initialization if needed.
34
+
35
+ Returns
36
+ -------
37
+ None
16
38
  """
17
39
  pass
@@ -5,7 +5,7 @@
5
5
  NAME = "orionis"
6
6
 
7
7
  # Current version of the framework
8
- VERSION = "0.404.0"
8
+ VERSION = "0.406.0"
9
9
 
10
10
  # Full name of the author or maintainer of the project
11
11
  AUTHOR = "Raul Mauricio Uñate Castro"
@@ -17,5 +17,4 @@ def env(key: str, default: Any = None) -> Any:
17
17
  Any
18
18
  The value of the environment variable if it exists, otherwise the default value.
19
19
  """
20
- dotenv = DotEnv()
21
- return dotenv.get(key, default)
20
+ return DotEnv().get(key, default)
File without changes
@@ -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}"
@@ -0,0 +1,64 @@
1
+ import os
2
+ from datetime import datetime
3
+ from pathlib import Path
4
+
5
+ class FileNameLogger:
6
+
7
+ def __init__(self, path: str) -> None:
8
+ """
9
+ Initialize the FileNameLogger.
10
+
11
+ Parameters
12
+ ----------
13
+ path : str
14
+ The original file path for the log file.
15
+ """
16
+
17
+ # If the path is not a string or is empty, raise a ValueError
18
+ if not isinstance(path, str) or not path:
19
+ raise ValueError("The 'path' parameter must be a non-empty string.")
20
+
21
+ # Set the instance variable __path to the stripped path
22
+ self.__path = path.strip()
23
+
24
+ def generate(self) -> str:
25
+ """
26
+ Generate a new log file path with a timestamp prefix.
27
+
28
+ Returns
29
+ -------
30
+ str
31
+ The full path to the log file with a timestamped file name.
32
+
33
+ Notes
34
+ -----
35
+ The method ensures that the directory for the log file exists.
36
+ """
37
+
38
+ # Split the original path to extract the base name and extension
39
+ if '/' in self.__path:
40
+ parts = self.__path.split('/')
41
+ elif '\\' in self.__path:
42
+ parts = self.__path.split('\\')
43
+ else:
44
+ parts = self.__path.split(os.sep)
45
+
46
+ # Get the base name and extension
47
+ filename, ext = os.path.splitext(parts[-1])
48
+
49
+ # Create the path without the last part
50
+ path = os.path.join(*parts[:-1]) if len(parts) > 1 else ''
51
+
52
+ # Prefix the base name with a timestamp
53
+ prefix = datetime.now().strftime("%Y%m%d_%H%M%S")
54
+
55
+ # Join the path, prefix, and filename to create the full path
56
+ full_path = os.path.join(path, f"{prefix}_{filename}{ext}")
57
+
58
+ # Ensure the log directory exists
59
+ log_dir = Path(full_path).parent
60
+ if not log_dir.exists():
61
+ log_dir.mkdir(parents=True, exist_ok=True)
62
+
63
+ # Return the full path as a string
64
+ return full_path
@@ -1,52 +1,21 @@
1
- from datetime import datetime
2
1
  from logging.handlers import RotatingFileHandler
3
- from pathlib import Path
4
- import os
2
+ from orionis.services.log.handlers.filename import FileNameLogger
5
3
 
6
4
  class PrefixedSizeRotatingFileHandler(RotatingFileHandler):
7
5
 
8
- def rotation_filename(self, default_name):
6
+ def rotation_filename(self, default_name) -> str:
9
7
  """
10
- Generates a rotated log filename by prefixing the original filename with a timestamp.
11
- This method takes an original file path, extracts its directory, base name, and extension,
12
- and returns a new file path where the base name is prefixed with the current timestamp
13
- in the format 'YYYYMMDD_HHMMSS'. If the target directory does not exist, it is created.
8
+ Generate a rotated log filename by prefixing the original filename with a timestamp.
9
+
10
+ Parameters
11
+ ----------
12
+ default_name : str
14
13
  The original file path to be rotated.
15
- The new file path with a timestamp prefix added to the base name.
16
- Notes
17
- -----
18
- - The timestamp is based on the current local time.
19
- - The method ensures that the parent directory for the new file exists.
20
14
 
21
15
  Returns
22
16
  -------
23
17
  str
24
- The new filename with a timestamp prefix in the format 'YYYYMMDD_HHMMSS'.
18
+ The new file path with the base name prefixed by a timestamp in the format 'YYYYMMDD_HHMMSS'.
25
19
  """
26
- # Split the original path to extract the base name and extension
27
- if '/' in default_name:
28
- parts = default_name.split('/')
29
- elif '\\' in default_name:
30
- parts = default_name.split('\\')
31
- else:
32
- parts = default_name.split(os.sep)
33
-
34
- # Get the base name and extension
35
- filename, ext = os.path.splitext(parts[-1])
36
-
37
- # Create the path without the last part
38
- path = os.path.join(*parts[:-1]) if len(parts) > 1 else ''
39
-
40
- # Prefix the base name with a timestamp
41
- prefix = datetime.now().strftime("%Y%m%d_%H%M%S")
42
-
43
- # Join the path, prefix, and filename to create the full path
44
- full_path = os.path.join(path, f"{prefix}_{filename}{ext}")
45
-
46
- # Ensure the log directory exists
47
- log_dir = Path(full_path).parent
48
- if not log_dir.exists():
49
- log_dir.mkdir(parents=True, exist_ok=True)
50
20
 
51
- # Return the full path as a string
52
- return full_path
21
+ return FileNameLogger(default_name).generate()
@@ -1,53 +1,21 @@
1
- from datetime import datetime
2
1
  from logging.handlers import TimedRotatingFileHandler
3
- from pathlib import Path
4
- import os
2
+ from orionis.services.log.handlers.filename import FileNameLogger
5
3
 
6
4
  class PrefixedTimedRotatingFileHandler(TimedRotatingFileHandler):
7
5
 
8
- def rotation_filename(self, default_name):
6
+ def rotation_filename(self, default_name) -> str:
9
7
  """
10
- Generates a rotated log filename by prefixing the original filename with a timestamp.
11
- This method takes an original file path, extracts its directory, base name, and extension,
12
- and returns a new file path where the base name is prefixed with the current timestamp
13
- in the format 'YYYYMMDD_HHMMSS'. If the target directory does not exist, it is created.
8
+ Generate a rotated log filename by prefixing the original filename with a timestamp.
9
+
10
+ Parameters
11
+ ----------
12
+ default_name : str
14
13
  The original file path to be rotated.
15
- The new file path with a timestamp prefix added to the base name.
16
- Notes
17
- -----
18
- - The timestamp is based on the current local time.
19
- - The method ensures that the parent directory for the new file exists.
20
14
 
21
15
  Returns
22
16
  -------
23
17
  str
24
- The new filename with a timestamp prefix in the format 'YYYYMMDD_HHMMSS'.
18
+ The new file path with the base name prefixed by a timestamp in the format 'YYYYMMDD_HHMMSS'.
25
19
  """
26
20
 
27
- # Split the original path to extract the base name and extension
28
- if '/' in default_name:
29
- parts = default_name.split('/')
30
- elif '\\' in default_name:
31
- parts = default_name.split('\\')
32
- else:
33
- parts = default_name.split(os.sep)
34
-
35
- # Get the base name and extension
36
- filename, ext = os.path.splitext(parts[-1])
37
-
38
- # Create the path without the last part
39
- path = os.path.join(*parts[:-1]) if len(parts) > 1 else ''
40
-
41
- # Prefix the base name with a timestamp
42
- prefix = datetime.now().strftime("%Y%m%d_%H%M%S")
43
-
44
- # Join the path, prefix, and filename to create the full path
45
- full_path = os.path.join(path, f"{prefix}_{filename}{ext}")
46
-
47
- # Ensure the log directory exists
48
- log_dir = Path(full_path).parent
49
- if not log_dir.exists():
50
- log_dir.mkdir(parents=True, exist_ok=True)
51
-
52
- # Return the full path as a string
53
- return full_path
21
+ return FileNameLogger(default_name).generate()
@@ -2,6 +2,7 @@ from orionis.foundation.config.logging.entities.logging import Logging
2
2
  from orionis.foundation.config.logging.enums import Level
3
3
  from orionis.services.log.contracts.log_service import ILoggerService
4
4
  from orionis.services.log.exceptions import LoggerRuntimeError
5
+ from orionis.services.log.handlers.filename import FileNameLogger
5
6
  from orionis.services.log.handlers.size_rotating import PrefixedSizeRotatingFileHandler
6
7
  from orionis.services.log.handlers.timed_rotating import PrefixedTimedRotatingFileHandler
7
8
 
@@ -40,7 +41,13 @@ class LoggerService(ILoggerService):
40
41
  try:
41
42
  self.__config = Logging(**kwargs)
42
43
  except Exception as e:
43
- raise LoggerRuntimeError(f"Failed to initialize logger configuration: {e}")
44
+ raise LoggerRuntimeError(
45
+ f"Error initializing logger configuration: {e}. "
46
+ "Please check the provided parameters. "
47
+ f"Expected a Logging dataclass or a configuration dictionary. "
48
+ f"Type received: {type(config).__module__}.{type(config).__name__}. "
49
+ f"Expected: {Logging.__module__}.{Logging.__name__} or dict."
50
+ )
44
51
 
45
52
  # If config is a dictionary, convert it to Logging
46
53
  elif isinstance(config, dict):
@@ -53,56 +60,6 @@ class LoggerService(ILoggerService):
53
60
  # Initialize LoggerService
54
61
  self.__initLogger()
55
62
 
56
- def __filename(self, original_path:str) -> str:
57
- """
58
- Generates a rotated log filename by prefixing the original filename with a timestamp.
59
- This method takes an original file path, extracts its directory, base name, and extension,
60
- and returns a new file path where the base name is prefixed with the current timestamp
61
- in the format 'YYYYMMDD_HHMMSS'. If the target directory does not exist, it is created.
62
- The original file path to be rotated.
63
- The new file path with a timestamp prefix added to the base name.
64
- Notes
65
- -----
66
- - The timestamp is based on the current local time.
67
- - The method ensures that the parent directory for the new file exists.
68
-
69
- Returns
70
- -------
71
- str
72
- The new filename with a timestamp prefix in the format 'YYYYMMDD_HHMMSS'.
73
- """
74
- import os
75
- from datetime import datetime
76
- from pathlib import Path
77
-
78
- # Split the original path to extract the base name and extension
79
- if '/' in original_path:
80
- parts = original_path.split('/')
81
- elif '\\' in original_path:
82
- parts = original_path.split('\\')
83
- else:
84
- parts = original_path.split(os.sep)
85
-
86
- # Get the base name and extension
87
- filename, ext = os.path.splitext(parts[-1])
88
-
89
- # Create the path without the last part
90
- path = os.path.join(*parts[:-1]) if len(parts) > 1 else ''
91
-
92
- # Prefix the base name with a timestamp
93
- prefix = datetime.now().strftime("%Y%m%d_%H%M%S")
94
-
95
- # Join the path, prefix, and filename to create the full path
96
- full_path = os.path.join(path, f"{prefix}_{filename}{ext}")
97
-
98
- # Ensure the log directory exists
99
- log_dir = Path(full_path).parent
100
- if not log_dir.exists():
101
- log_dir.mkdir(parents=True, exist_ok=True)
102
-
103
- # Return the full path as a string
104
- return full_path
105
-
106
63
  def __initLogger(self):
107
64
  """
108
65
  Configures the logger with the specified settings.
@@ -131,7 +88,7 @@ class LoggerService(ILoggerService):
131
88
  config_channels = getattr(self.__config.channels, channel)
132
89
 
133
90
  # Get the path from the channel configuration
134
- path: str = self.__filename(getattr(config_channels, 'path'))
91
+ path: str = FileNameLogger(getattr(config_channels, 'path')).generate()
135
92
 
136
93
  # Get Level from the channel configuration, defaulting to 10 (DEBUG)
137
94
  level: Level | int = getattr(config_channels, 'level', 10)
File without changes