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,468 +1,272 @@
1
- from dataclasses import asdict, dataclass, field, fields
2
- from pathlib import Path
3
- from typing import Dict
4
- from orionis.foundation.exceptions import OrionisIntegrityException
5
-
6
- @dataclass(frozen=True, kw_only=True)
7
- class Paths:
8
- """
9
- A frozen dataclass representing the canonical directory and file structure
10
- for a Laravel-inspired Python project.
11
-
12
- This class provides type-safe access to all standard project paths and includes
13
- validation to ensure path integrity. All paths are relative to the project root.
14
-
15
- Attributes are organized into logical groups:
16
- - Application components (controllers, models, services)
17
- - Resources (views, assets, translations)
18
- - Routing configuration
19
- - Configuration and database
20
- - Storage locations
21
- """
22
-
23
- # --- Application Paths ---
24
- console_scheduler: str = field(
25
- default='app/console/kernel.py',
26
- metadata={
27
- 'description': 'Path to the console scheduler (Kernel) file.',
28
- 'type': 'file',
29
- 'required': True
30
- }
31
- )
32
-
33
- console_commands: str = field(
34
- default='app/console/commands',
35
- metadata={
36
- 'description': 'Directory containing custom Artisan-style console commands.',
37
- 'type': 'directory',
38
- 'required': True
39
- }
40
- )
41
-
42
- http_controllers: str = field(
43
- default='app/http/controllers',
44
- metadata={
45
- 'description': 'Directory containing HTTP controller classes.',
46
- 'type': 'directory',
47
- 'required': True
48
- }
49
- )
50
-
51
- http_middleware: str = field(
52
- default='app/http/middleware',
53
- metadata={
54
- 'description': 'Directory containing HTTP middleware classes.',
55
- 'type': 'directory',
56
- 'required': True
57
- }
58
- )
59
-
60
- http_requests: str = field(
61
- default='app/http/requests',
62
- metadata={
63
- 'description': 'Directory containing HTTP form request validation classes.',
64
- 'type': 'directory',
65
- 'required': False
66
- }
67
- )
68
-
69
- models: str = field(
70
- default='app/models',
71
- metadata={
72
- 'description': 'Directory containing ORM model classes.',
73
- 'type': 'directory',
74
- 'required': True
75
- }
76
- )
77
-
78
- providers: str = field(
79
- default='app/providers',
80
- metadata={
81
- 'description': 'Directory containing service provider classes.',
82
- 'type': 'directory',
83
- 'required': True
84
- }
85
- )
86
-
87
- events: str = field(
88
- default='app/events',
89
- metadata={
90
- 'description': 'Directory containing event classes.',
91
- 'type': 'directory',
92
- 'required': False
93
- }
94
- )
95
-
96
- listeners: str = field(
97
- default='app/listeners',
98
- metadata={
99
- 'description': 'Directory containing event listener classes.',
100
- 'type': 'directory',
101
- 'required': False
102
- }
103
- )
104
-
105
- notifications: str = field(
106
- default='app/notifications',
107
- metadata={
108
- 'description': 'Directory containing notification classes.',
109
- 'type': 'directory',
110
- 'required': False
111
- }
112
- )
113
-
114
- jobs: str = field(
115
- default='app/jobs',
116
- metadata={
117
- 'description': 'Directory containing queued job classes.',
118
- 'type': 'directory',
119
- 'required': False
120
- }
121
- )
122
-
123
- policies: str = field(
124
- default='app/policies',
125
- metadata={
126
- 'description': 'Directory containing authorization policy classes.',
127
- 'type': 'directory',
128
- 'required': False
129
- }
130
- )
131
-
132
- exceptions: str = field(
133
- default='app/exceptions',
134
- metadata={
135
- 'description': 'Directory containing exception handler classes.',
136
- 'type': 'directory',
137
- 'required': True
138
- }
139
- )
140
-
141
- services: str = field(
142
- default='app/services',
143
- metadata={
144
- 'description': 'Directory containing business logic service classes.',
145
- 'type': 'directory',
146
- 'required': False
147
- }
148
- )
149
-
150
- # --- Resource Paths ---
151
- views: str = field(
152
- default='resources/views',
153
- metadata={
154
- 'description': 'Directory containing template view files.',
155
- 'type': 'directory',
156
- 'required': True
157
- }
158
- )
159
-
160
- lang: str = field(
161
- default='resources/lang',
162
- metadata={
163
- 'description': 'Directory containing internationalization files.',
164
- 'type': 'directory',
165
- 'required': False
166
- }
167
- )
168
-
169
- assets: str = field(
170
- default='resources/assets',
171
- metadata={
172
- 'description': 'Directory containing frontend assets (JS, CSS, images).',
173
- 'type': 'directory',
174
- 'required': False
175
- }
176
- )
177
-
178
- # --- Routing Paths ---
179
- routes_web: str = field(
180
- default='routes/web.py',
181
- metadata={
182
- 'description': 'Path to the web routes definition file.',
183
- 'type': 'file',
184
- 'required': True
185
- }
186
- )
187
-
188
- routes_api: str = field(
189
- default='routes/api.py',
190
- metadata={
191
- 'description': 'Path to the API routes definition file.',
192
- 'type': 'file',
193
- 'required': False
194
- }
195
- )
196
-
197
- routes_console: str = field(
198
- default='routes/console.py',
199
- metadata={
200
- 'description': 'Path to the console routes definition file.',
201
- 'type': 'file',
202
- 'required': False
203
- }
204
- )
205
-
206
- routes_channels: str = field(
207
- default='routes/channels.py',
208
- metadata={
209
- 'description': 'Path to the broadcast channels routes file.',
210
- 'type': 'file',
211
- 'required': False
212
- }
213
- )
214
-
215
- # --- Configuration & Database Paths ---
216
- config: str = field(
217
- default='config',
218
- metadata={
219
- 'description': 'Directory containing application configuration files.',
220
- 'type': 'directory',
221
- 'required': True
222
- }
223
- )
224
-
225
- migrations: str = field(
226
- default='database/migrations',
227
- metadata={
228
- 'description': 'Directory containing database migration files.',
229
- 'type': 'directory',
230
- 'required': True
231
- }
232
- )
233
-
234
- seeders: str = field(
235
- default='database/seeders',
236
- metadata={
237
- 'description': 'Directory containing database seeder files.',
238
- 'type': 'directory',
239
- 'required': False
240
- }
241
- )
242
-
243
- factories: str = field(
244
- default='database/factories',
245
- metadata={
246
- 'description': 'Directory containing model factory files.',
247
- 'type': 'directory',
248
- 'required': False
249
- }
250
- )
251
-
252
- # --- Storage Paths ---
253
- storage_logs: str = field(
254
- default='storage/logs',
255
- metadata={
256
- 'description': 'Directory containing application log files.',
257
- 'type': 'directory',
258
- 'required': True
259
- }
260
- )
261
-
262
- storage_framework: str = field(
263
- default='storage/framework',
264
- metadata={
265
- 'description': 'Directory for framework-generated files (cache, sessions, views).',
266
- 'type': 'directory',
267
- 'required': True
268
- }
269
- )
270
-
271
- storage_sessions: str = field(
272
- default='storage/framework/sessions',
273
- metadata={
274
- 'description': 'Directory containing session files.',
275
- 'type': 'directory',
276
- 'required': False
277
- }
278
- )
279
-
280
- storage_cache: str = field(
281
- default='storage/framework/cache',
282
- metadata={
283
- 'description': 'Directory containing framework cache files.',
284
- 'type': 'directory',
285
- 'required': False
286
- }
287
- )
288
-
289
- storage_views: str = field(
290
- default='storage/framework/views',
291
- metadata={
292
- 'description': 'Directory containing compiled view files.',
293
- 'type': 'directory',
294
- 'required': False
295
- }
296
- )
297
-
298
- def __post_init__(self) -> None:
299
- """
300
- Validates all path fields after initialization.
301
-
302
- Raises:
303
- OrionisIntegrityException: If any path is invalid (empty or not a string)
304
- """
305
- for field_name, field_info in self.__dataclass_fields__.items():
306
- value = getattr(self, field_name)
307
- metadata:dict = field_info.metadata
308
-
309
- if not isinstance(value, str) or not value.strip():
310
- raise OrionisIntegrityException(
311
- f"Invalid path value for '{field_name}': {value!r}. Must be non-empty string."
312
- )
313
-
314
- if metadata.get('required', False) and not value:
315
- raise OrionisIntegrityException(
316
- f"Required path '{field_name}' cannot be empty."
317
- )
318
-
319
- # --- Path Accessors ---
320
- def getConsoleScheduler(self) -> Path:
321
- """Get Path object for console scheduler file."""
322
- return Path(self.console_scheduler)
323
-
324
- def getConsoleCommands(self) -> Path:
325
- """Get Path object for console commands directory."""
326
- return Path(self.console_commands)
327
-
328
- def getHttpControllers(self) -> Path:
329
- """Get Path object for HTTP controllers directory."""
330
- return Path(self.http_controllers)
331
-
332
- def getHttpMiddleware(self) -> Path:
333
- """Get Path object for HTTP middleware directory."""
334
- return Path(self.http_middleware)
335
-
336
- def getHttpRequests(self) -> Path:
337
- """Get Path object for HTTP requests directory."""
338
- return Path(self.http_requests)
339
-
340
- def getModels(self) -> Path:
341
- """Get Path object for models directory."""
342
- return Path(self.models)
343
-
344
- def getProviders(self) -> Path:
345
- """Get Path object for service providers directory."""
346
- return Path(self.providers)
347
-
348
- def getEvents(self) -> Path:
349
- """Get Path object for events directory."""
350
- return Path(self.events)
351
-
352
- def getListeners(self) -> Path:
353
- """Get Path object for event listeners directory."""
354
- return Path(self.listeners)
355
-
356
- def getNotifications(self) -> Path:
357
- """Get Path object for notifications directory."""
358
- return Path(self.notifications)
359
-
360
- def getJobs(self) -> Path:
361
- """Get Path object for queued jobs directory."""
362
- return Path(self.jobs)
363
-
364
- def getPolicies(self) -> Path:
365
- """Get Path object for authorization policies directory."""
366
- return Path(self.policies)
367
-
368
- def getExceptions(self) -> Path:
369
- """Get Path object for exceptions directory."""
370
- return Path(self.exceptions)
371
-
372
- def getServices(self) -> Path:
373
- """Get Path object for services directory."""
374
- return Path(self.services)
375
-
376
- def getViews(self) -> Path:
377
- """Get Path object for views directory."""
378
- return Path(self.views)
379
-
380
- def getLang(self) -> Path:
381
- """Get Path object for language files directory."""
382
- return Path(self.lang)
383
-
384
- def getAssets(self) -> Path:
385
- """Get Path object for assets directory."""
386
- return Path(self.assets)
387
-
388
- def getRoutesWeb(self) -> Path:
389
- """Get Path object for web routes file."""
390
- return Path(self.routes_web)
391
-
392
- def getRoutesApi(self) -> Path:
393
- """Get Path object for API routes file."""
394
- return Path(self.routes_api)
395
-
396
- def getRoutesConsole(self) -> Path:
397
- """Get Path object for console routes file."""
398
- return Path(self.routes_console)
399
-
400
- def getRoutesChannels(self) -> Path:
401
- """Get Path object for broadcast channels routes file."""
402
- return Path(self.routes_channels)
403
-
404
- def getConfig(self) -> Path:
405
- """Get Path object for config directory."""
406
- return Path(self.config)
407
-
408
- def getMigrations(self) -> Path:
409
- """Get Path object for migrations directory."""
410
- return Path(self.migrations)
411
-
412
- def getSeeders(self) -> Path:
413
- """Get Path object for seeders directory."""
414
- return Path(self.seeders)
415
-
416
- def getFactories(self) -> Path:
417
- """Get Path object for model factories directory."""
418
- return Path(self.factories)
419
-
420
- def getStorageLogs(self) -> Path:
421
- """Get Path object for logs directory."""
422
- return Path(self.storage_logs)
423
-
424
- def getStorageFramework(self) -> Path:
425
- """Get Path object for framework storage directory."""
426
- return Path(self.storage_framework)
427
-
428
- def getStorageSessions(self) -> Path:
429
- """Get Path object for sessions storage directory."""
430
- return Path(self.storage_sessions)
431
-
432
- def getStorageCache(self) -> Path:
433
- """Get Path object for cache storage directory."""
434
- return Path(self.storage_cache)
435
-
436
- def getStorageViews(self) -> Path:
437
- """Get Path object for compiled views storage directory."""
438
- return Path(self.storage_views)
439
-
440
- def toDict(self) -> Dict[str, str]:
441
- """
442
- Returns a dictionary representation of all paths.
443
- Returns:
444
- Dict[str, str]: Dictionary mapping field names to path strings
445
- """
446
- return asdict(self)
447
-
448
- def getFields(self):
449
- """
450
- Retrieves a list of field information for the current dataclass instance.
451
-
452
- Returns:
453
- list: A list of dictionaries, each containing details about a field:
454
- - name (str): The name of the field.
455
- - type (type): The type of the field.
456
- - default: The default value of the field, if specified; otherwise, the value from metadata or None.
457
- - metadata (mapping): The metadata associated with the field.
458
- """
459
- __fields = []
460
- for field in fields(self):
461
- __metadata = dict(field.metadata) or {}
462
- __fields.append({
463
- "name": field.name,
464
- "type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
465
- "default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
466
- "metadata": __metadata
467
- })
468
- return __fields
1
+ from dataclasses import dataclass, field, fields
2
+ from pathlib import Path
3
+ from orionis.foundation.exceptions import OrionisIntegrityException
4
+ from orionis.support.entities.base import BaseEntity
5
+
6
+ @dataclass(frozen=True, kw_only=True)
7
+ class Paths(BaseEntity):
8
+
9
+ console_scheduler: str = field(
10
+ default = str((Path.cwd() / 'app' / 'console' / 'kernel.py').resolve()),
11
+ metadata = {
12
+ 'description': 'Path to the console scheduler (Kernel) file.',
13
+ 'default': str((Path.cwd() / 'app' / 'console' / 'kernel.py').resolve())
14
+ }
15
+ )
16
+
17
+ console_commands: str = field(
18
+ default = str((Path.cwd() / 'app' / 'console' / 'commands').resolve()),
19
+ metadata = {
20
+ 'description': 'Directory containing custom ArtisanStyle console commands.',
21
+ 'default': str((Path.cwd() / 'app' / 'console' / 'commands').resolve())
22
+ }
23
+ )
24
+
25
+ http_controllers: str = field(
26
+ default = str((Path.cwd() / 'app' / 'http' / 'controllers').resolve()),
27
+ metadata = {
28
+ 'description': 'Directory containing HTTP controller classes.',
29
+ 'default': str((Path.cwd() / 'app' / 'http' / 'controllers').resolve())
30
+ }
31
+ )
32
+
33
+ http_middleware: str = field(
34
+ default = str((Path.cwd() / 'app' / 'http' / 'middleware').resolve()),
35
+ metadata = {
36
+ 'description': 'Directory containing HTTP middleware classes.',
37
+ 'default': str((Path.cwd() / 'app' / 'http' / 'middleware').resolve())
38
+ }
39
+ )
40
+
41
+ http_requests: str = field(
42
+ default = str((Path.cwd() / 'app' / 'http' / 'requests').resolve()),
43
+ metadata = {
44
+ 'description': 'Directory containing HTTP form request validation classes.',
45
+ 'default': str((Path.cwd() / 'app' / 'http' / 'requests').resolve())
46
+ }
47
+ )
48
+
49
+ models: str = field(
50
+ default = str((Path.cwd() / 'app' / 'models').resolve()),
51
+ metadata = {
52
+ 'description': 'Directory containing ORM model classes.',
53
+ 'default': str((Path.cwd() / 'app' / 'models').resolve())
54
+ }
55
+ )
56
+
57
+ providers: str = field(
58
+ default = str((Path.cwd() / 'app' / 'providers').resolve()),
59
+ metadata = {
60
+ 'description': 'Directory containing service provider classes.',
61
+ 'default': str((Path.cwd() / 'app' / 'providers').resolve())
62
+ }
63
+ )
64
+
65
+ events: str = field(
66
+ default = str((Path.cwd() / 'app' / 'events').resolve()),
67
+ metadata = {
68
+ 'description': 'Directory containing event classes.',
69
+ 'default': str((Path.cwd() / 'app' / 'events').resolve())
70
+ }
71
+ )
72
+
73
+ listeners: str = field(
74
+ default = str((Path.cwd() / 'app' / 'listeners').resolve()),
75
+ metadata = {
76
+ 'description': 'Directory containing event listener classes.',
77
+ 'default': str((Path.cwd() / 'app' / 'listeners').resolve())
78
+ }
79
+ )
80
+
81
+ notifications: str = field(
82
+ default = str((Path.cwd() / 'app' / 'notifications').resolve()),
83
+ metadata = {
84
+ 'description': 'Directory containing notification classes.',
85
+ 'default': str((Path.cwd() / 'app' / 'notifications').resolve())
86
+ }
87
+ )
88
+
89
+ jobs: str = field(
90
+ default = str((Path.cwd() / 'app' / 'jobs').resolve()),
91
+ metadata = {
92
+ 'description': 'Directory containing queued job classes.',
93
+ 'default': str((Path.cwd() / 'app' / 'jobs').resolve())
94
+ }
95
+ )
96
+
97
+ policies: str = field(
98
+ default = str((Path.cwd() / 'app' / 'policies').resolve()),
99
+ metadata = {
100
+ 'description': 'Directory containing authorization policy classes.',
101
+ 'default': str((Path.cwd() / 'app' / 'policies').resolve())
102
+ }
103
+ )
104
+
105
+ exceptions: str = field(
106
+ default = str((Path.cwd() / 'app' / 'exceptions').resolve()),
107
+ metadata = {
108
+ 'description': 'Directory containing exception handler classes.',
109
+ 'default': str((Path.cwd() / 'app' / 'exceptions').resolve())
110
+ }
111
+ )
112
+
113
+ services: str = field(
114
+ default = str((Path.cwd() / 'app' / 'services').resolve()),
115
+ metadata = {
116
+ 'description': 'Directory containing business logic service classes.',
117
+ 'default': str((Path.cwd() / 'app' / 'services').resolve())
118
+ }
119
+ )
120
+
121
+ views: str = field(
122
+ default = str((Path.cwd() / 'resources' / 'views').resolve()),
123
+ metadata = {
124
+ 'description': 'Directory containing template view files.',
125
+ 'default': str((Path.cwd() / 'resources' / 'views').resolve())
126
+ }
127
+ )
128
+
129
+ lang: str = field(
130
+ default = str((Path.cwd() / 'resources' / 'lang').resolve()),
131
+ metadata = {
132
+ 'description': 'Directory containing internationalization files.',
133
+ 'default': str((Path.cwd() / 'resources' / 'lang').resolve())
134
+ }
135
+ )
136
+
137
+ assets: str = field(
138
+ default = str((Path.cwd() / 'resources' / 'assets').resolve()),
139
+ metadata = {
140
+ 'description': 'Directory containing frontend assets (JS, CSS, images).',
141
+ 'default': str((Path.cwd() / 'resources' / 'assets').resolve())
142
+ }
143
+ )
144
+
145
+ routes_web: str = field(
146
+ default = str((Path.cwd() / 'routes' / 'web.py').resolve()),
147
+ metadata = {
148
+ 'description': 'Path to the web routes definition file.',
149
+ 'default': str((Path.cwd() / 'routes' / 'web.py').resolve())
150
+ }
151
+ )
152
+
153
+ routes_api: str = field(
154
+ default = str((Path.cwd() / 'routes' / 'api.py').resolve()),
155
+ metadata = {
156
+ 'description': 'Path to the API routes definition file.',
157
+ 'default': str((Path.cwd() / 'routes' / 'api.py').resolve())
158
+ }
159
+ )
160
+
161
+ routes_console: str = field(
162
+ default = str((Path.cwd() / 'routes' / 'console.py').resolve()),
163
+ metadata = {
164
+ 'description': 'Path to the console routes definition file.',
165
+ 'default': str((Path.cwd() / 'routes' / 'console.py').resolve())
166
+ }
167
+ )
168
+
169
+ routes_channels: str = field(
170
+ default = str((Path.cwd() / 'routes' / 'channels.py').resolve()),
171
+ metadata = {
172
+ 'description': 'Path to the broadcast channels routes file.',
173
+ 'default': str((Path.cwd() / 'routes' / 'channels.py').resolve())
174
+ }
175
+ )
176
+
177
+ config: str = field(
178
+ default = str((Path.cwd() / 'config').resolve()),
179
+ metadata = {
180
+ 'description': 'Directory containing application configuration files.',
181
+ 'default': str((Path.cwd() / 'config').resolve())
182
+ }
183
+ )
184
+
185
+ migrations: str = field(
186
+ default = str((Path.cwd() / 'database' / 'migrations').resolve()),
187
+ metadata = {
188
+ 'description': 'Directory containing database migration files.',
189
+ 'default': str((Path.cwd() / 'database' / 'migrations').resolve())
190
+ }
191
+ )
192
+
193
+ seeders: str = field(
194
+ default = str((Path.cwd() / 'database' / 'seeders').resolve()),
195
+ metadata = {
196
+ 'description': 'Directory containing database seeder files.',
197
+ 'default': str((Path.cwd() / 'database' / 'seeders').resolve())
198
+ }
199
+ )
200
+
201
+ factories: str = field(
202
+ default = str((Path.cwd() / 'database' / 'factories').resolve()),
203
+ metadata = {
204
+ 'description': 'Directory containing model factory files.',
205
+ 'default': str((Path.cwd() / 'database' / 'factories').resolve())
206
+ }
207
+ )
208
+
209
+ storage_logs: str = field(
210
+ default = str((Path.cwd() / 'storage' / 'logs').resolve()),
211
+ metadata = {
212
+ 'description': 'Directory containing application log files.',
213
+ 'default': str((Path.cwd() / 'storage' / 'logs').resolve())
214
+ }
215
+ )
216
+
217
+ storage_framework: str = field(
218
+ default = str((Path.cwd() / 'storage' / 'framework').resolve()),
219
+ metadata = {
220
+ 'description': 'Directory for framework-generated files (cache, sessions, views).',
221
+ 'default': str((Path.cwd() / 'storage' / 'framework').resolve())
222
+ }
223
+ )
224
+
225
+ storage_sessions: str = field(
226
+ default = str((Path.cwd() / 'storage' / 'framework' / 'sessions').resolve()),
227
+ metadata = {
228
+ 'description': 'Directory containing session files.',
229
+ 'default': str((Path.cwd() / 'storage' / 'framework' / 'sessions').resolve())
230
+ }
231
+ )
232
+
233
+ storage_cache: str = field(
234
+ default = str((Path.cwd() / 'storage' / 'framework' / 'cache').resolve()),
235
+ metadata = {
236
+ 'description': 'Directory containing framework cache files.',
237
+ 'default': str((Path.cwd() / 'storage' / 'framework' / 'cache').resolve())
238
+ }
239
+ )
240
+
241
+ storage_views: str = field(
242
+ default = str((Path.cwd() / 'storage' / 'framework' / 'views').resolve()),
243
+ metadata = {
244
+ 'description': 'Directory containing compiled view files.',
245
+ 'default': str((Path.cwd() / 'storage' / 'framework' / 'views').resolve())
246
+ }
247
+ )
248
+
249
+ storage_testing: str = field(
250
+ default = str((Path.cwd() / 'storage' / 'framework' / 'testing').resolve()),
251
+ metadata = {
252
+ 'description': 'Directory containing compiled view files.',
253
+ 'default': str((Path.cwd() / 'storage' / 'framework' / 'testing').resolve())
254
+ }
255
+ )
256
+
257
+
258
+ def __post_init__(self) -> None:
259
+ """
260
+ Ensures all path attributes are of type str.
261
+
262
+ Raises
263
+ ------
264
+ OrionisIntegrityException
265
+ If any attribute is not a string.
266
+ """
267
+ for field_ in fields(self):
268
+ value = getattr(self, field_.name)
269
+ if not isinstance(value, str):
270
+ raise OrionisIntegrityException(
271
+ f"Invalid type for '{field_.name}': expected str, got {type(value).__name__}"
272
+ )