orionis 0.401.0__py3-none-any.whl → 0.403.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.
- orionis/container/providers/service_provider.py +4 -4
- orionis/foundation/application.py +4 -2
- orionis/foundation/config/base.py +112 -0
- orionis/foundation/config/logging/entities/channels.py +87 -69
- orionis/foundation/config/logging/entities/chunked.py +37 -92
- orionis/foundation/config/logging/entities/daily.py +43 -81
- orionis/foundation/config/logging/entities/hourly.py +16 -71
- orionis/foundation/config/logging/entities/logging.py +37 -38
- orionis/foundation/config/logging/entities/monthly.py +19 -75
- orionis/foundation/config/logging/entities/stack.py +13 -69
- orionis/foundation/config/logging/entities/weekly.py +19 -75
- orionis/foundation/config/logging/enums/levels.py +6 -7
- orionis/foundation/config/logging/validators/__init__.py +7 -0
- orionis/foundation/config/logging/validators/level.py +54 -0
- orionis/foundation/config/logging/validators/path.py +34 -0
- orionis/foundation/providers/console_provider.py +0 -4
- orionis/foundation/providers/dumper_provider.py +0 -4
- orionis/foundation/providers/logger_provider.py +17 -0
- orionis/foundation/providers/path_resolver_provider.py +0 -4
- orionis/foundation/providers/progress_bar_provider.py +0 -4
- orionis/foundation/providers/workers_provider.py +0 -4
- orionis/metadata/framework.py +1 -1
- orionis/services/log/contracts/__init__.py +0 -0
- orionis/services/log/contracts/log_service.py +23 -0
- orionis/services/log/exceptions/__init__.py +5 -0
- orionis/services/log/exceptions/runtime.py +19 -0
- orionis/services/log/handlers/__init__.py +0 -0
- orionis/services/log/handlers/size_rotating.py +52 -0
- orionis/services/log/handlers/timed_rotating.py +53 -0
- orionis/services/log/log_service.py +188 -143
- orionis/support/facades/logger.py +15 -0
- {orionis-0.401.0.dist-info → orionis-0.403.0.dist-info}/METADATA +1 -1
- {orionis-0.401.0.dist-info → orionis-0.403.0.dist-info}/RECORD +37 -24
- {orionis-0.401.0.dist-info → orionis-0.403.0.dist-info}/WHEEL +0 -0
- {orionis-0.401.0.dist-info → orionis-0.403.0.dist-info}/licenses/LICENCE +0 -0
- {orionis-0.401.0.dist-info → orionis-0.403.0.dist-info}/top_level.txt +0 -0
- {orionis-0.401.0.dist-info → orionis-0.403.0.dist-info}/zip-safe +0 -0
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
from orionis.container.contracts.container import IContainer
|
|
2
1
|
from orionis.container.contracts.service_provider import IServiceProvider
|
|
2
|
+
from orionis.foundation.contracts.application import IApplication
|
|
3
3
|
|
|
4
4
|
class ServiceProvider(IServiceProvider):
|
|
5
5
|
"""
|
|
@@ -11,7 +11,7 @@ class ServiceProvider(IServiceProvider):
|
|
|
11
11
|
|
|
12
12
|
Parameters
|
|
13
13
|
----------
|
|
14
|
-
app :
|
|
14
|
+
app : IApplication
|
|
15
15
|
The application container instance to which services will be registered.
|
|
16
16
|
|
|
17
17
|
Notes
|
|
@@ -20,13 +20,13 @@ class ServiceProvider(IServiceProvider):
|
|
|
20
20
|
the `register` method at minimum.
|
|
21
21
|
"""
|
|
22
22
|
|
|
23
|
-
def __init__(self, app:
|
|
23
|
+
def __init__(self, app: IApplication) -> None:
|
|
24
24
|
"""
|
|
25
25
|
Initialize the service provider with the application container.
|
|
26
26
|
|
|
27
27
|
Parameters
|
|
28
28
|
----------
|
|
29
|
-
app :
|
|
29
|
+
app : IApplication
|
|
30
30
|
The application container instance.
|
|
31
31
|
"""
|
|
32
32
|
self.app = app
|
|
@@ -18,6 +18,7 @@ from orionis.foundation.config.testing.entities.testing import Testing
|
|
|
18
18
|
from orionis.foundation.contracts.application import IApplication
|
|
19
19
|
from orionis.foundation.contracts.config import IConfig
|
|
20
20
|
from orionis.foundation.exceptions import OrionisTypeError, OrionisRuntimeError
|
|
21
|
+
from orionis.foundation.providers.logger_provider import LoggerProvider
|
|
21
22
|
|
|
22
23
|
class Application(Container, IApplication):
|
|
23
24
|
"""
|
|
@@ -116,7 +117,8 @@ class Application(Container, IApplication):
|
|
|
116
117
|
DumperProvider,
|
|
117
118
|
PathResolverProvider,
|
|
118
119
|
ProgressBarProvider,
|
|
119
|
-
WorkersProvider
|
|
120
|
+
WorkersProvider,
|
|
121
|
+
LoggerProvider
|
|
120
122
|
]
|
|
121
123
|
|
|
122
124
|
# Register each core provider
|
|
@@ -1031,7 +1033,7 @@ class Application(Container, IApplication):
|
|
|
1031
1033
|
"""
|
|
1032
1034
|
|
|
1033
1035
|
# Ensure the application is booted before accessing configuration
|
|
1034
|
-
if not self.
|
|
1036
|
+
if not self.__config:
|
|
1035
1037
|
raise RuntimeError("Application must be booted before accessing configuration. Call create() first.")
|
|
1036
1038
|
|
|
1037
1039
|
# If key is None, raise an error to prevent ambiguity
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
from dataclasses import asdict, fields
|
|
2
|
+
from dataclasses import MISSING
|
|
3
|
+
|
|
4
|
+
class BaseConfigEntity:
|
|
5
|
+
|
|
6
|
+
def toDict(self) -> dict:
|
|
7
|
+
"""
|
|
8
|
+
Converts the current instance into a dictionary representation.
|
|
9
|
+
|
|
10
|
+
Returns
|
|
11
|
+
-------
|
|
12
|
+
dict
|
|
13
|
+
Dictionary representation of the current instance.
|
|
14
|
+
"""
|
|
15
|
+
return asdict(self)
|
|
16
|
+
|
|
17
|
+
def getFields(self):
|
|
18
|
+
"""
|
|
19
|
+
Retrieves a list of field information for the current dataclass instance.
|
|
20
|
+
|
|
21
|
+
Returns
|
|
22
|
+
-------
|
|
23
|
+
list
|
|
24
|
+
A list of dictionaries, each containing details about a field:
|
|
25
|
+
- name (str): The name of the field.
|
|
26
|
+
- type (type): The type of the field.
|
|
27
|
+
- default: The default value of the field, if specified; otherwise, the value from metadata or None.
|
|
28
|
+
- metadata (mapping): The metadata associated with the field.
|
|
29
|
+
"""
|
|
30
|
+
# Dictionary to hold field information
|
|
31
|
+
__fields = []
|
|
32
|
+
|
|
33
|
+
# Iterate over the fields of the dataclass
|
|
34
|
+
# and extract relevant information
|
|
35
|
+
for field in fields(self):
|
|
36
|
+
|
|
37
|
+
# Get the field name
|
|
38
|
+
__name = field.name
|
|
39
|
+
|
|
40
|
+
# Get the field type with better handling for complex types
|
|
41
|
+
__type = getattr(field.type, '__name__', None)
|
|
42
|
+
|
|
43
|
+
# If the type is None, handle it
|
|
44
|
+
if __type is None:
|
|
45
|
+
|
|
46
|
+
# Handle generic types, unions, and other complex annotations
|
|
47
|
+
type_str = str(field.type)
|
|
48
|
+
|
|
49
|
+
# Clean up typing module references
|
|
50
|
+
type_str = type_str.replace('typing.', '')
|
|
51
|
+
|
|
52
|
+
# Handle Union types (e.g., "Channels | dict" or "Union[Channels, dict]")
|
|
53
|
+
if '|' in type_str or 'Union[' in type_str:
|
|
54
|
+
|
|
55
|
+
# Extract individual types from Union
|
|
56
|
+
if 'Union[' in type_str:
|
|
57
|
+
|
|
58
|
+
# Handle typing.Union format
|
|
59
|
+
inner = type_str.replace('Union[', '').replace(']', '')
|
|
60
|
+
types = [t.strip() for t in inner.split(',')]
|
|
61
|
+
|
|
62
|
+
else:
|
|
63
|
+
# Handle | format (Python 3.10+)
|
|
64
|
+
types = [t.strip() for t in type_str.split('|')]
|
|
65
|
+
|
|
66
|
+
# Get class names for custom types
|
|
67
|
+
clean_types = []
|
|
68
|
+
for t in types:
|
|
69
|
+
if '.' in t:
|
|
70
|
+
clean_types.append(t.split('.')[-1])
|
|
71
|
+
else:
|
|
72
|
+
clean_types.append(t)
|
|
73
|
+
|
|
74
|
+
# Join cleaned types with ' | '
|
|
75
|
+
__type = ' | '.join(clean_types)
|
|
76
|
+
|
|
77
|
+
else:
|
|
78
|
+
|
|
79
|
+
# Handle other complex types
|
|
80
|
+
if '.' in type_str:
|
|
81
|
+
__type = type_str.split('.')[-1]
|
|
82
|
+
else:
|
|
83
|
+
__type = type_str
|
|
84
|
+
|
|
85
|
+
# Extract metadata, default value, and type
|
|
86
|
+
__metadata = dict(field.metadata) or {}
|
|
87
|
+
|
|
88
|
+
# Extract the default value, if specified
|
|
89
|
+
__default = None
|
|
90
|
+
|
|
91
|
+
# Field has a direct default value
|
|
92
|
+
if field.default is not MISSING:
|
|
93
|
+
__default = field.default
|
|
94
|
+
|
|
95
|
+
# Field has a default factory (like list, dict, etc.)
|
|
96
|
+
elif field.default_factory is not MISSING:
|
|
97
|
+
__default = f"<factory: {field.default_factory.__name__}>"
|
|
98
|
+
|
|
99
|
+
# No default found, check metadata for custom default
|
|
100
|
+
else:
|
|
101
|
+
__default = __metadata.get('default', None)
|
|
102
|
+
|
|
103
|
+
# Append the field information to the list
|
|
104
|
+
__fields.append({
|
|
105
|
+
"name": __name,
|
|
106
|
+
"type": __type,
|
|
107
|
+
"default": __default,
|
|
108
|
+
"metadata": __metadata
|
|
109
|
+
})
|
|
110
|
+
|
|
111
|
+
# Return the list of field information
|
|
112
|
+
return __fields
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
from dataclasses import
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from orionis.foundation.config.base import BaseConfigEntity
|
|
2
3
|
from orionis.foundation.config.logging.entities.monthly import Monthly
|
|
3
4
|
from orionis.foundation.config.logging.entities.chunked import Chunked
|
|
4
5
|
from orionis.foundation.config.logging.entities.daily import Daily
|
|
@@ -8,56 +9,56 @@ from orionis.foundation.config.logging.entities.weekly import Weekly
|
|
|
8
9
|
from orionis.foundation.exceptions import OrionisIntegrityException
|
|
9
10
|
|
|
10
11
|
@dataclass(unsafe_hash=True, kw_only=True)
|
|
11
|
-
class Channels:
|
|
12
|
+
class Channels(BaseConfigEntity):
|
|
12
13
|
"""
|
|
13
14
|
Represents the different logging channels available.
|
|
14
15
|
"""
|
|
15
16
|
|
|
16
|
-
stack: Stack = field(
|
|
17
|
-
default_factory=Stack,
|
|
17
|
+
stack: Stack | dict = field(
|
|
18
|
+
default_factory = lambda: Stack(),
|
|
18
19
|
metadata={
|
|
19
20
|
"description": "Configuration for stack log channel.",
|
|
20
|
-
"default":
|
|
21
|
+
"default": lambda : Stack().toDict()
|
|
21
22
|
}
|
|
22
23
|
)
|
|
23
24
|
|
|
24
|
-
hourly: Hourly = field(
|
|
25
|
-
default_factory=Hourly,
|
|
25
|
+
hourly: Hourly | dict = field(
|
|
26
|
+
default_factory = lambda: Hourly(),
|
|
26
27
|
metadata={
|
|
27
28
|
"description": "Configuration for hourly log rotation.",
|
|
28
|
-
"default":
|
|
29
|
+
"default": lambda: Hourly().toDict()
|
|
29
30
|
}
|
|
30
31
|
)
|
|
31
32
|
|
|
32
|
-
daily: Daily = field(
|
|
33
|
-
default_factory=Daily,
|
|
33
|
+
daily: Daily | dict = field(
|
|
34
|
+
default_factory = lambda: Daily(),
|
|
34
35
|
metadata={
|
|
35
36
|
"description": "Configuration for daily log rotation.",
|
|
36
|
-
"default":
|
|
37
|
+
"default": lambda: Daily().toDict()
|
|
37
38
|
}
|
|
38
39
|
)
|
|
39
40
|
|
|
40
|
-
weekly: Weekly = field(
|
|
41
|
-
default_factory=Weekly,
|
|
41
|
+
weekly: Weekly | dict = field(
|
|
42
|
+
default_factory = lambda: Weekly(),
|
|
42
43
|
metadata={
|
|
43
44
|
"description": "Configuration for weekly log rotation.",
|
|
44
|
-
"default":
|
|
45
|
+
"default": lambda: Weekly().toDict()
|
|
45
46
|
}
|
|
46
47
|
)
|
|
47
48
|
|
|
48
|
-
monthly: Monthly = field(
|
|
49
|
-
default_factory=Monthly,
|
|
49
|
+
monthly: Monthly | dict= field(
|
|
50
|
+
default_factory = lambda: Monthly(),
|
|
50
51
|
metadata={
|
|
51
52
|
"description": "Configuration for monthly log rotation.",
|
|
52
|
-
"default":
|
|
53
|
+
"default": lambda: Monthly().toDict()
|
|
53
54
|
}
|
|
54
55
|
)
|
|
55
56
|
|
|
56
|
-
chunked: Chunked = field(
|
|
57
|
-
default_factory=Chunked,
|
|
57
|
+
chunked: Chunked | dict = field(
|
|
58
|
+
default_factory = lambda: Chunked(),
|
|
58
59
|
metadata={
|
|
59
60
|
"description": "Configuration for chunked log file storage.",
|
|
60
|
-
"default":
|
|
61
|
+
"default": lambda: Chunked().toDict()
|
|
61
62
|
}
|
|
62
63
|
)
|
|
63
64
|
|
|
@@ -76,62 +77,79 @@ class Channels:
|
|
|
76
77
|
"""
|
|
77
78
|
|
|
78
79
|
if not isinstance(self.stack, Stack):
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
80
|
+
if isinstance(self.stack, dict):
|
|
81
|
+
try:
|
|
82
|
+
self.stack = Stack(**self.stack)
|
|
83
|
+
except TypeError as e:
|
|
84
|
+
raise OrionisIntegrityException(
|
|
85
|
+
f"Invalid stack configuration: {e}"
|
|
86
|
+
)
|
|
87
|
+
else:
|
|
88
|
+
raise OrionisIntegrityException(
|
|
89
|
+
"The 'stack' property must be an instance of Stack or a dictionary."
|
|
90
|
+
)
|
|
82
91
|
|
|
83
92
|
if not isinstance(self.hourly, Hourly):
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
93
|
+
if isinstance(self.hourly, dict):
|
|
94
|
+
try:
|
|
95
|
+
self.hourly = Hourly(**self.hourly)
|
|
96
|
+
except TypeError as e:
|
|
97
|
+
raise OrionisIntegrityException(
|
|
98
|
+
f"Invalid hourly configuration: {e}"
|
|
99
|
+
)
|
|
100
|
+
else:
|
|
101
|
+
raise OrionisIntegrityException(
|
|
102
|
+
"The 'hourly' property must be an instance of Hourly or a dictionary."
|
|
103
|
+
)
|
|
87
104
|
|
|
88
105
|
if not isinstance(self.daily, Daily):
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
106
|
+
if isinstance(self.daily, dict):
|
|
107
|
+
try:
|
|
108
|
+
self.daily = Daily(**self.daily)
|
|
109
|
+
except TypeError as e:
|
|
110
|
+
raise OrionisIntegrityException(
|
|
111
|
+
f"Invalid daily configuration: {e}"
|
|
112
|
+
)
|
|
113
|
+
else:
|
|
114
|
+
raise OrionisIntegrityException(
|
|
115
|
+
"The 'daily' property must be an instance of Daily or a dictionary."
|
|
116
|
+
)
|
|
92
117
|
|
|
93
118
|
if not isinstance(self.weekly, Weekly):
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
119
|
+
if isinstance(self.weekly, dict):
|
|
120
|
+
try:
|
|
121
|
+
self.weekly = Weekly(**self.weekly)
|
|
122
|
+
except TypeError as e:
|
|
123
|
+
raise OrionisIntegrityException(
|
|
124
|
+
f"Invalid weekly configuration: {e}"
|
|
125
|
+
)
|
|
126
|
+
else:
|
|
127
|
+
raise OrionisIntegrityException(
|
|
128
|
+
"The 'weekly' property must be an instance of Weekly or a dictionary."
|
|
129
|
+
)
|
|
97
130
|
|
|
98
131
|
if not isinstance(self.monthly, Monthly):
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
132
|
+
if isinstance(self.monthly, dict):
|
|
133
|
+
try:
|
|
134
|
+
self.monthly = Monthly(**self.monthly)
|
|
135
|
+
except TypeError as e:
|
|
136
|
+
raise OrionisIntegrityException(
|
|
137
|
+
f"Invalid monthly configuration: {e}"
|
|
138
|
+
)
|
|
139
|
+
else:
|
|
140
|
+
raise OrionisIntegrityException(
|
|
141
|
+
"The 'monthly' property must be an instance of Monthly or a dictionary."
|
|
142
|
+
)
|
|
102
143
|
|
|
103
144
|
if not isinstance(self.chunked, Chunked):
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
return asdict(self)
|
|
116
|
-
|
|
117
|
-
def getFields(self):
|
|
118
|
-
"""
|
|
119
|
-
Retrieves a list of field information for the current dataclass instance.
|
|
120
|
-
|
|
121
|
-
Returns:
|
|
122
|
-
list: A list of dictionaries, each containing details about a field:
|
|
123
|
-
- name (str): The name of the field.
|
|
124
|
-
- type (type): The type of the field.
|
|
125
|
-
- default: The default value of the field, if specified; otherwise, the value from metadata or None.
|
|
126
|
-
- metadata (mapping): The metadata associated with the field.
|
|
127
|
-
"""
|
|
128
|
-
__fields = []
|
|
129
|
-
for field in fields(self):
|
|
130
|
-
__metadata = dict(field.metadata) or {}
|
|
131
|
-
__fields.append({
|
|
132
|
-
"name": field.name,
|
|
133
|
-
"type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
|
|
134
|
-
"default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
|
|
135
|
-
"metadata": __metadata
|
|
136
|
-
})
|
|
137
|
-
return __fields
|
|
145
|
+
if isinstance(self.chunked, dict):
|
|
146
|
+
try:
|
|
147
|
+
self.chunked = Chunked(**self.chunked)
|
|
148
|
+
except TypeError as e:
|
|
149
|
+
raise OrionisIntegrityException(
|
|
150
|
+
f"Invalid chunked configuration: {e}"
|
|
151
|
+
)
|
|
152
|
+
else:
|
|
153
|
+
raise OrionisIntegrityException(
|
|
154
|
+
"The 'chunked' property must be an instance of Chunked or a dictionary."
|
|
155
|
+
)
|
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
from dataclasses import
|
|
1
|
+
from dataclasses import dataclass, field
|
|
2
|
+
from orionis.foundation.config.base import BaseConfigEntity
|
|
3
|
+
from orionis.foundation.config.logging.validators import IsValidPath, IsValidLevel
|
|
2
4
|
from orionis.foundation.exceptions import OrionisIntegrityException
|
|
3
5
|
from orionis.foundation.config.logging.enums import Level
|
|
4
|
-
import re
|
|
5
6
|
|
|
6
7
|
@dataclass(unsafe_hash=True, kw_only=True)
|
|
7
|
-
class Chunked:
|
|
8
|
+
class Chunked(BaseConfigEntity):
|
|
8
9
|
"""
|
|
9
10
|
Configuration for chunked log file rotation.
|
|
10
11
|
|
|
@@ -25,23 +26,23 @@ class Chunked:
|
|
|
25
26
|
"""
|
|
26
27
|
|
|
27
28
|
path: str = field(
|
|
28
|
-
default='storage/log/application.log',
|
|
29
|
-
metadata={
|
|
30
|
-
"description": "
|
|
29
|
+
default = 'storage/log/application.log',
|
|
30
|
+
metadata = {
|
|
31
|
+
"description": "The file path where the log is stored.",
|
|
31
32
|
"default": "storage/log/application.log",
|
|
32
33
|
},
|
|
33
34
|
)
|
|
34
35
|
|
|
35
36
|
level: int | str | Level = field(
|
|
36
|
-
default=Level.INFO,
|
|
37
|
-
metadata={
|
|
38
|
-
"description": "
|
|
37
|
+
default = Level.INFO,
|
|
38
|
+
metadata = {
|
|
39
|
+
"description": "The logging level (e.g., DEBUG, INFO, WARNING, ERROR, CRITICAL).",
|
|
39
40
|
"default": Level.INFO,
|
|
40
41
|
},
|
|
41
42
|
)
|
|
42
43
|
|
|
43
44
|
mb_size: int = field(
|
|
44
|
-
default=10,
|
|
45
|
+
default = 10,
|
|
45
46
|
metadata={
|
|
46
47
|
"description": "Maximum size (in MB) of a log file before chunking.",
|
|
47
48
|
"default": 10,
|
|
@@ -49,7 +50,7 @@ class Chunked:
|
|
|
49
50
|
)
|
|
50
51
|
|
|
51
52
|
files: int = field(
|
|
52
|
-
default=5,
|
|
53
|
+
default = 5,
|
|
53
54
|
metadata={
|
|
54
55
|
"description": "Maximum number of log files to retain.",
|
|
55
56
|
"default": 5,
|
|
@@ -57,94 +58,38 @@ class Chunked:
|
|
|
57
58
|
)
|
|
58
59
|
|
|
59
60
|
def __post_init__(self):
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
raise OrionisIntegrityException(
|
|
63
|
-
f"Chunked log configuration error: 'path' must be a non-empty string, got {repr(self.path)}."
|
|
64
|
-
)
|
|
61
|
+
"""
|
|
62
|
+
Performs validation and normalization of configuration fields.
|
|
65
63
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
64
|
+
- path: Validates that the path is correct using the IsValidPath validator.
|
|
65
|
+
- level: Validates that the log level is correct using the IsValidLevel validator.
|
|
66
|
+
- mb_size: Checks that it is an integer between 1 and 1000 (MB).
|
|
67
|
+
- files: Checks that it is a positive integer greater than 0.
|
|
68
|
+
|
|
69
|
+
Raises
|
|
70
|
+
------
|
|
71
|
+
OrionisIntegrityException
|
|
72
|
+
If any of the configuration values are invalid.
|
|
73
|
+
"""
|
|
72
74
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
)
|
|
79
|
-
if _value not in Level.__members__:
|
|
80
|
-
raise OrionisIntegrityException(
|
|
81
|
-
f"File cache configuration error: 'level' must be one of {list(Level.__members__.keys())}, got '{self.level}'."
|
|
82
|
-
)
|
|
83
|
-
self.level = Level[_value].value
|
|
84
|
-
elif isinstance(self.level, int):
|
|
85
|
-
valid_values = [level.value for level in Level]
|
|
86
|
-
if self.level not in valid_values:
|
|
87
|
-
raise OrionisIntegrityException(
|
|
88
|
-
f"File cache configuration error: 'level' must be one of {valid_values}, got '{self.level}'."
|
|
89
|
-
)
|
|
90
|
-
elif isinstance(self.level, Level):
|
|
91
|
-
self.level = self.level.value
|
|
75
|
+
# Validate 'path' using the IsValidPath validator
|
|
76
|
+
IsValidPath(self.path)
|
|
77
|
+
|
|
78
|
+
# Validate 'level' using the IsValidLevel validator
|
|
79
|
+
IsValidLevel(self.level)
|
|
92
80
|
|
|
93
81
|
# Validate 'mb_size'
|
|
94
|
-
if isinstance(self.mb_size,
|
|
95
|
-
match = re.match(r'^(\d+)\s*(MB|KB|B)?$', self.mb_size.strip(), re.IGNORECASE)
|
|
96
|
-
if not match:
|
|
97
|
-
raise OrionisIntegrityException(
|
|
98
|
-
f"Chunked log configuration error: 'mb_size' string must be like '10MB', '500KB', or integer, got '{self.mb_size}'."
|
|
99
|
-
)
|
|
100
|
-
size, unit = match.groups()
|
|
101
|
-
size = int(size)
|
|
102
|
-
if unit is None or unit.upper() == 'MB':
|
|
103
|
-
self.mb_size = size
|
|
104
|
-
elif unit.upper() == 'KB':
|
|
105
|
-
self.mb_size = max(1, size // 1024)
|
|
106
|
-
elif unit.upper() == 'B':
|
|
107
|
-
self.mb_size = max(1, size // (1024 * 1024))
|
|
108
|
-
if not isinstance(self.mb_size, int) or self.mb_size < 1:
|
|
82
|
+
if not isinstance(self.mb_size, int):
|
|
109
83
|
raise OrionisIntegrityException(
|
|
110
|
-
f"
|
|
84
|
+
f"'mb_size' must be an integer in MB, got {type(self.mb_size).__name__}."
|
|
85
|
+
)
|
|
86
|
+
if self.mb_size < 1 or self.mb_size > 1000:
|
|
87
|
+
raise OrionisIntegrityException(
|
|
88
|
+
f"'mb_size' must be between 1 and 1000 MB, got {self.mb_size}."
|
|
111
89
|
)
|
|
112
90
|
|
|
113
91
|
# Validate 'files'
|
|
114
92
|
if not isinstance(self.files, int) or self.files < 1:
|
|
115
93
|
raise OrionisIntegrityException(
|
|
116
|
-
f"
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
def toDict(self) -> dict:
|
|
120
|
-
"""
|
|
121
|
-
Returns a dictionary representation of the Chunked configuration.
|
|
122
|
-
|
|
123
|
-
Returns
|
|
124
|
-
-------
|
|
125
|
-
dict
|
|
126
|
-
Dictionary containing all configuration fields and their values.
|
|
127
|
-
"""
|
|
128
|
-
return asdict(self)
|
|
129
|
-
|
|
130
|
-
def getFields(self):
|
|
131
|
-
"""
|
|
132
|
-
Retrieves a list of field information for the current dataclass instance.
|
|
133
|
-
|
|
134
|
-
Returns:
|
|
135
|
-
list: A list of dictionaries, each containing details about a field:
|
|
136
|
-
- name (str): The name of the field.
|
|
137
|
-
- type (type): The type of the field.
|
|
138
|
-
- default: The default value of the field, if specified; otherwise, the value from metadata or None.
|
|
139
|
-
- metadata (mapping): The metadata associated with the field.
|
|
140
|
-
"""
|
|
141
|
-
__fields = []
|
|
142
|
-
for field in fields(self):
|
|
143
|
-
__metadata = dict(field.metadata) or {}
|
|
144
|
-
__fields.append({
|
|
145
|
-
"name": field.name,
|
|
146
|
-
"type": field.type.__name__ if hasattr(field.type, '__name__') else str(field.type),
|
|
147
|
-
"default": field.default if (field.default is not None and '_MISSING_TYPE' not in str(field.default)) else __metadata.get('default', None),
|
|
148
|
-
"metadata": __metadata
|
|
149
|
-
})
|
|
150
|
-
return __fields
|
|
94
|
+
f"'files' must be a positive integer greater than 0, got {self.files} ({type(self.files).__name__})."
|
|
95
|
+
)
|