everysk-lib 1.10.3__cp312-cp312-win_amd64.whl → 1.11.0__cp312-cp312-win_amd64.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.
- everysk/core/_tests/mapping/__init__.py +9 -0
- everysk/core/_tests/mapping/base.py +306 -0
- everysk/core/_tests/mapping/fields.py +1154 -0
- everysk/core/datetime/datetime.py +1 -1
- everysk/core/http.py +6 -6
- everysk/core/mapping/__init__.py +29 -0
- everysk/core/mapping/base.py +214 -0
- everysk/core/mapping/fields.py +1133 -0
- everysk/core/mapping/metaclass.py +101 -0
- everysk/core/object.py +132 -124
- everysk/core/tests.py +19 -0
- everysk/sdk/engines/expression.cp312-win_amd64.pyd +0 -0
- everysk/sdk/engines/helpers.cp312-win_amd64.pyd +0 -0
- everysk/sdk/entities/script.py +0 -1
- everysk/sql/connection.py +24 -0
- {everysk_lib-1.10.3.dist-info → everysk_lib-1.11.0.dist-info}/METADATA +2 -2
- {everysk_lib-1.10.3.dist-info → everysk_lib-1.11.0.dist-info}/RECORD +21 -14
- {everysk_lib-1.10.3.dist-info → everysk_lib-1.11.0.dist-info}/.gitignore +0 -0
- {everysk_lib-1.10.3.dist-info → everysk_lib-1.11.0.dist-info}/WHEEL +0 -0
- {everysk_lib-1.10.3.dist-info → everysk_lib-1.11.0.dist-info}/licenses/LICENSE.txt +0 -0
- {everysk_lib-1.10.3.dist-info → everysk_lib-1.11.0.dist-info}/top_level.txt +0 -0
everysk/core/object.py
CHANGED
|
@@ -9,6 +9,7 @@
|
|
|
9
9
|
###############################################################################
|
|
10
10
|
from _collections_abc import dict_items, dict_keys, dict_values
|
|
11
11
|
from collections.abc import Iterator
|
|
12
|
+
from contextlib import suppress
|
|
12
13
|
from copy import copy, deepcopy
|
|
13
14
|
from inspect import isroutine
|
|
14
15
|
from types import GenericAlias, UnionType
|
|
@@ -24,7 +25,7 @@ CONFIG_ATTRIBUTE_NAME: str = '_config'
|
|
|
24
25
|
###############################################################################
|
|
25
26
|
# Private functions Implementation
|
|
26
27
|
###############################################################################
|
|
27
|
-
def __get_field_value__(obj: Any, attr: str, value: Any) -> Any:
|
|
28
|
+
def __get_field_value__(obj: Any, attr: str, value: Any) -> Any: # noqa: N807
|
|
28
29
|
"""
|
|
29
30
|
Function that get the cleaned value for a Field and validate this value.
|
|
30
31
|
|
|
@@ -40,7 +41,7 @@ def __get_field_value__(obj: Any, attr: str, value: Any) -> Any:
|
|
|
40
41
|
value = _transform_to_undefined(value)
|
|
41
42
|
|
|
42
43
|
# Get all attributes that the object has
|
|
43
|
-
attributes = getattr(obj, MetaClass._attr_name) #
|
|
44
|
+
attributes = getattr(obj, MetaClass._attr_name) # noqa: SLF001
|
|
44
45
|
try:
|
|
45
46
|
field = attributes[attr]
|
|
46
47
|
except KeyError:
|
|
@@ -82,14 +83,19 @@ def _required(attr_name: str, value: Any) -> None:
|
|
|
82
83
|
"""
|
|
83
84
|
Checks if value is required, required values can't be: None, '', [], {}.
|
|
84
85
|
|
|
86
|
+
Args:
|
|
87
|
+
attr_name (str): The name of the attribute being validated. This is used for generating error messages.
|
|
88
|
+
value (Any): The value to be validated against the required condition.
|
|
89
|
+
|
|
85
90
|
Raises:
|
|
86
91
|
RequiredError: When value is required and match with False conditions.
|
|
87
92
|
"""
|
|
88
93
|
if value in (Undefined, None, '', (), [], {}):
|
|
89
|
-
|
|
94
|
+
msg = f'The {attr_name} attribute is required.'
|
|
95
|
+
raise RequiredError(msg)
|
|
90
96
|
|
|
91
97
|
|
|
92
|
-
def _validate(attr_name: str, value: Any, attr_type: type | UnionType) -> None: #
|
|
98
|
+
def _validate(attr_name: str, value: Any, attr_type: type | UnionType) -> None: # noqa: PLR0911, PLR0912
|
|
93
99
|
"""
|
|
94
100
|
Validates that the given value is of the expected attribute type. The function supports special type checks for
|
|
95
101
|
Date and DateTime types and handles general type validation for other types. It allows the value to pass through
|
|
@@ -114,15 +120,13 @@ def _validate(attr_name: str, value: Any, attr_type: type | UnionType) -> None:
|
|
|
114
120
|
if value is None or value is Undefined:
|
|
115
121
|
return
|
|
116
122
|
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
return
|
|
123
|
+
# If we are expecting a Date we don't need to check other things
|
|
124
|
+
if attr_type == Date and Date.is_date(value):
|
|
125
|
+
return
|
|
121
126
|
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return
|
|
127
|
+
# If we are expecting a DateTime we don't need to check other things
|
|
128
|
+
if attr_type == DateTime and DateTime.is_datetime(value):
|
|
129
|
+
return
|
|
126
130
|
|
|
127
131
|
# TypeError: typing.Any cannot be used with isinstance()
|
|
128
132
|
if attr_type is Any:
|
|
@@ -131,14 +135,12 @@ def _validate(attr_name: str, value: Any, attr_type: type | UnionType) -> None:
|
|
|
131
135
|
# https://everysk.atlassian.net/browse/COD-4286
|
|
132
136
|
# If we use 'class'/callable as a annotation, the isinstance will fail
|
|
133
137
|
# because attr_type will be a string/function so we need to discard it first
|
|
134
|
-
if attr_type is callable:
|
|
135
|
-
|
|
136
|
-
return
|
|
138
|
+
if attr_type is callable and callable(value):
|
|
139
|
+
return
|
|
137
140
|
|
|
138
141
|
# If it is string, when we use classes as annotations we check if the name of the class is the same
|
|
139
|
-
if isinstance(attr_type, str):
|
|
140
|
-
|
|
141
|
-
return
|
|
142
|
+
if isinstance(attr_type, str) and type(value).__name__ == attr_type:
|
|
143
|
+
return
|
|
142
144
|
|
|
143
145
|
try:
|
|
144
146
|
# Check if value is an instance of the expected type
|
|
@@ -149,28 +151,30 @@ def _validate(attr_name: str, value: Any, attr_type: type | UnionType) -> None:
|
|
|
149
151
|
pass
|
|
150
152
|
|
|
151
153
|
## Subscriptable types like List, Dict, Tuple, etc
|
|
152
|
-
if
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
return
|
|
154
|
+
# We need to check if the value is a instance of the origin type
|
|
155
|
+
if isinstance(attr_type, GenericAlias) and isinstance(value, attr_type.__origin__):
|
|
156
|
+
# We not check the content of the list, dict, tuple, etc
|
|
157
|
+
return
|
|
157
158
|
|
|
158
159
|
if isinstance(attr_type, UnionType):
|
|
159
160
|
# Try to validate with all members of the union
|
|
160
161
|
for attr_type_ in get_args(attr_type):
|
|
161
162
|
try:
|
|
162
163
|
_validate(attr_name, value, attr_type_)
|
|
163
|
-
|
|
164
|
+
|
|
164
165
|
except FieldValueError:
|
|
165
166
|
pass
|
|
166
167
|
|
|
167
|
-
|
|
168
|
+
else:
|
|
169
|
+
return # test passed with some member
|
|
170
|
+
msg = f'Key {attr_name} must be {attr_type}.'
|
|
171
|
+
raise FieldValueError(msg)
|
|
168
172
|
|
|
169
173
|
|
|
170
174
|
###############################################################################
|
|
171
175
|
# BaseField Class Implementation
|
|
172
176
|
###############################################################################
|
|
173
|
-
class BaseField:
|
|
177
|
+
class BaseField: # noqa: PLW1641
|
|
174
178
|
"""Base class of all fields that will guarantee their type."""
|
|
175
179
|
|
|
176
180
|
## Public attributes
|
|
@@ -183,8 +187,9 @@ class BaseField:
|
|
|
183
187
|
|
|
184
188
|
def __init__(
|
|
185
189
|
self,
|
|
186
|
-
attr_type: type | UnionType = None,
|
|
190
|
+
attr_type: type | UnionType | None = None,
|
|
187
191
|
default: Any = None,
|
|
192
|
+
*,
|
|
188
193
|
readonly: bool = False,
|
|
189
194
|
required: bool = False,
|
|
190
195
|
required_lazy: bool = False,
|
|
@@ -268,7 +273,7 @@ class BaseField:
|
|
|
268
273
|
|
|
269
274
|
def get_cleaned_value(self, value: Any) -> Any:
|
|
270
275
|
"""
|
|
271
|
-
|
|
276
|
+
Function first converts the value to None if needed, then
|
|
272
277
|
checks if the `value` is a callable. If it is, the function calls
|
|
273
278
|
the `value` and stores its result by reassigning the `value` variable.
|
|
274
279
|
Finally, the function calls the `clean_value` method.
|
|
@@ -286,13 +291,11 @@ class BaseField:
|
|
|
286
291
|
value = self.get_value(value)
|
|
287
292
|
|
|
288
293
|
# Then we run the clean_value method
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
return value
|
|
294
|
+
return self.clean_value(value)
|
|
292
295
|
|
|
293
296
|
def get_value(self, value: Any) -> Any:
|
|
294
297
|
"""
|
|
295
|
-
|
|
298
|
+
Function checks if the `value` is a callable
|
|
296
299
|
By either returning the `value` or returning the
|
|
297
300
|
result of the callable function.
|
|
298
301
|
|
|
@@ -313,7 +316,7 @@ class BaseField:
|
|
|
313
316
|
|
|
314
317
|
def clean_value(self, value: Any) -> Any:
|
|
315
318
|
"""
|
|
316
|
-
|
|
319
|
+
Method is always called when we assigned a value to some attribute.
|
|
317
320
|
Must be implemented in child classes to change the behavior of a given field.
|
|
318
321
|
Below we have an example that reimplements the `clean_value()`.
|
|
319
322
|
|
|
@@ -344,7 +347,7 @@ class BaseField:
|
|
|
344
347
|
"""
|
|
345
348
|
return value
|
|
346
349
|
|
|
347
|
-
def validate(self, attr_name: str, value: Any, attr_type: type | UnionType = None) -> None:
|
|
350
|
+
def validate(self, attr_name: str, value: Any, attr_type: type | UnionType | None = None) -> None:
|
|
348
351
|
"""
|
|
349
352
|
Checks if value is required and if is of correct type.
|
|
350
353
|
This method can be reimplemented in child classes to modify
|
|
@@ -373,10 +376,10 @@ class BaseField:
|
|
|
373
376
|
if attr_type is None:
|
|
374
377
|
attr_type = self.attr_type
|
|
375
378
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
379
|
+
# This is necessary to be able to at least assign the default value to the field
|
|
380
|
+
if self.readonly and value != self.default:
|
|
381
|
+
msg = f"The field '{attr_name}' value cannot be changed."
|
|
382
|
+
raise FieldValueError(msg)
|
|
380
383
|
|
|
381
384
|
if self.required and not self.required_lazy:
|
|
382
385
|
_required(attr_name, value)
|
|
@@ -385,7 +388,7 @@ class BaseField:
|
|
|
385
388
|
|
|
386
389
|
def __getattr__(self, name: str) -> Any:
|
|
387
390
|
"""
|
|
388
|
-
|
|
391
|
+
Method is used to handle pylint errors where the method/attribute does not exist.
|
|
389
392
|
The problem is that we change the field in the MetaClass to the Field's default value,
|
|
390
393
|
so StrField does not have the str methods but the result is a string.
|
|
391
394
|
This method will only be executed if the method/attributes do not exist in the Field class.
|
|
@@ -405,7 +408,8 @@ class BaseField:
|
|
|
405
408
|
pass
|
|
406
409
|
|
|
407
410
|
# If no attribute was found we raise the error
|
|
408
|
-
|
|
411
|
+
msg = f"type object '{self.attr_type}' has no attribute '{name}'."
|
|
412
|
+
raise AttributeError(msg)
|
|
409
413
|
|
|
410
414
|
|
|
411
415
|
###############################################################################
|
|
@@ -420,14 +424,14 @@ def _silent(func: callable) -> callable:
|
|
|
420
424
|
func (callable): The function to be decorated.
|
|
421
425
|
"""
|
|
422
426
|
|
|
423
|
-
def wrapper(self, *args, **kwargs):
|
|
427
|
+
def wrapper(self, *args, **kwargs) -> Any: # noqa: ANN001
|
|
424
428
|
# pylint: disable=broad-exception-caught, protected-access
|
|
425
429
|
silent = kwargs.pop('silent', self._silent)
|
|
426
430
|
try:
|
|
427
431
|
return func(self, *args, **kwargs)
|
|
428
432
|
except Exception as error:
|
|
429
433
|
if not silent:
|
|
430
|
-
raise
|
|
434
|
+
raise
|
|
431
435
|
if self._errors is None:
|
|
432
436
|
self._errors = {}
|
|
433
437
|
self._errors['init'] = deepcopy(error)
|
|
@@ -462,40 +466,40 @@ class MetaClass(type):
|
|
|
462
466
|
kwargs = dct
|
|
463
467
|
except Exception as error: # pylint: disable=broad-exception-caught
|
|
464
468
|
if not silent:
|
|
465
|
-
raise
|
|
469
|
+
raise
|
|
466
470
|
errors['before_init'] = deepcopy(error)
|
|
467
471
|
|
|
468
472
|
## Here we create the object and initialize the silent for init must be inside the _silent function
|
|
469
473
|
obj = super().__call__(*args, **kwargs)
|
|
470
|
-
if obj._errors:
|
|
471
|
-
errors['init'] = obj._errors['init']
|
|
474
|
+
if obj._errors: # noqa: SLF001
|
|
475
|
+
errors['init'] = obj._errors['init'] # noqa: SLF001
|
|
472
476
|
|
|
473
477
|
## If the after init method is implemented we run it
|
|
474
478
|
try:
|
|
475
479
|
obj.__after_init__()
|
|
476
480
|
except Exception as error: # pylint: disable=broad-exception-caught
|
|
477
481
|
if not silent:
|
|
478
|
-
raise
|
|
482
|
+
raise
|
|
479
483
|
errors['after_init'] = deepcopy(error)
|
|
480
484
|
|
|
481
485
|
# Store the errors
|
|
482
486
|
if any(errors.values()):
|
|
483
|
-
obj._errors = errors
|
|
487
|
+
obj._errors = errors # noqa: SLF001
|
|
484
488
|
# Execute the handler for errors
|
|
485
|
-
obj._init_error_handler(kwargs, errors)
|
|
489
|
+
obj._init_error_handler(kwargs, errors) # noqa: SLF001
|
|
486
490
|
|
|
487
491
|
# Set the instance to be Frozen or not
|
|
488
492
|
try:
|
|
489
493
|
config = getattr(obj, CONFIG_ATTRIBUTE_NAME)
|
|
490
|
-
obj._is_frozen = config.frozen #
|
|
494
|
+
obj._is_frozen = config.frozen # noqa: SLF001
|
|
491
495
|
except AttributeError:
|
|
492
496
|
pass
|
|
493
497
|
|
|
494
498
|
return obj
|
|
495
499
|
|
|
496
|
-
def __new__(mcs, name: str, bases: tuple, attrs: dict) -> Self:
|
|
500
|
+
def __new__(mcs, name: str, bases: tuple, attrs: dict) -> Self: # noqa: PLR0912
|
|
497
501
|
"""
|
|
498
|
-
|
|
502
|
+
Method is executed every time a BaseObject Class is created in the Python runtime.
|
|
499
503
|
We changed this method to create the config and attributes properties and update the annotations.
|
|
500
504
|
|
|
501
505
|
Example:
|
|
@@ -538,7 +542,7 @@ class MetaClass(type):
|
|
|
538
542
|
# Creating the config property.
|
|
539
543
|
if 'Config' in attrs:
|
|
540
544
|
# If Config is in the class we just create it
|
|
541
|
-
Config = attrs.pop('Config') #
|
|
545
|
+
Config = attrs.pop('Config') # noqa: N806
|
|
542
546
|
attrs[CONFIG_ATTRIBUTE_NAME] = Config()
|
|
543
547
|
else:
|
|
544
548
|
# If Config is not in the class we get the first one from the bases
|
|
@@ -589,13 +593,13 @@ class MetaClass(type):
|
|
|
589
593
|
attributes[attr_name] = type(attr_value)
|
|
590
594
|
|
|
591
595
|
# Now we update annotations for attributes that are not annotated
|
|
592
|
-
# Ex: var = 1
|
|
596
|
+
# Ex: var = 1 # noqa: ERA001
|
|
593
597
|
if attr_name not in annotations:
|
|
594
598
|
annotations[attr_name] = type(attr_value)
|
|
595
599
|
|
|
596
600
|
# With both completed now we need to get the fields that are only annotations
|
|
597
601
|
# class MyClass:
|
|
598
|
-
# var: str
|
|
602
|
+
# var: str # noqa: ERA001
|
|
599
603
|
for key in annotations.keys() - attributes.keys():
|
|
600
604
|
attributes[key] = annotations[key]
|
|
601
605
|
# We set the default value to None to avoid break the code
|
|
@@ -618,15 +622,26 @@ class MetaClass(type):
|
|
|
618
622
|
|
|
619
623
|
return super().__new__(mcs, name, bases, attrs)
|
|
620
624
|
|
|
621
|
-
def
|
|
625
|
+
def __instancecheck__(cls, instance: object) -> bool:
|
|
626
|
+
"""
|
|
627
|
+
Method that checks if instance is a BaseMapping or BaseObject.
|
|
628
|
+
|
|
629
|
+
Args:
|
|
630
|
+
instance (object): The instance to be checked.
|
|
631
|
+
"""
|
|
632
|
+
from everysk.core.mapping import BaseMapping # noqa: PLC0415
|
|
633
|
+
|
|
634
|
+
return isinstance(instance, BaseMapping) or super().__instancecheck__(instance)
|
|
635
|
+
|
|
636
|
+
def __setattr__(cls, name: str, value: Any) -> None:
|
|
622
637
|
"""
|
|
623
638
|
Method that sets the values on fields of the class.
|
|
624
639
|
|
|
625
640
|
Args:
|
|
626
|
-
|
|
627
|
-
|
|
641
|
+
name (str): The attribute name.
|
|
642
|
+
value (Any): The value that is set.
|
|
628
643
|
"""
|
|
629
|
-
return super().__setattr__(
|
|
644
|
+
return super().__setattr__(name, __get_field_value__(cls, name, value))
|
|
630
645
|
|
|
631
646
|
|
|
632
647
|
###############################################################################
|
|
@@ -697,11 +712,10 @@ class _BaseObject(metaclass=MetaClass):
|
|
|
697
712
|
"""
|
|
698
713
|
|
|
699
714
|
def __check_frozen__(self) -> None:
|
|
700
|
-
"""
|
|
701
|
-
Method that checks if this class is a Frozen object and raises attribute error.
|
|
702
|
-
"""
|
|
715
|
+
"""Method that checks if this class is a Frozen object and raises attribute error."""
|
|
703
716
|
if self._is_frozen:
|
|
704
|
-
|
|
717
|
+
msg = f'Class {self.get_full_doted_class_path()} is frozen and cannot be modified.'
|
|
718
|
+
raise AttributeError(msg)
|
|
705
719
|
|
|
706
720
|
def __copy__(self) -> Self:
|
|
707
721
|
"""
|
|
@@ -717,10 +731,9 @@ class _BaseObject(metaclass=MetaClass):
|
|
|
717
731
|
obj.pop(CONFIG_ATTRIBUTE_NAME, None)
|
|
718
732
|
|
|
719
733
|
# We create a new obj
|
|
720
|
-
|
|
721
|
-
return obj
|
|
734
|
+
return type(self)(**obj)
|
|
722
735
|
|
|
723
|
-
def __deepcopy__(self, memo: dict = None) -> Self:
|
|
736
|
+
def __deepcopy__(self, memo: dict | None = None) -> Self:
|
|
724
737
|
"""
|
|
725
738
|
A deep copy constructs a new compound object and then, recursively,
|
|
726
739
|
inserts copies into it of the objects found in the original.
|
|
@@ -736,27 +749,24 @@ class _BaseObject(metaclass=MetaClass):
|
|
|
736
749
|
obj.pop(CONFIG_ATTRIBUTE_NAME, None)
|
|
737
750
|
|
|
738
751
|
# We create a new obj
|
|
739
|
-
|
|
740
|
-
return obj
|
|
752
|
+
return type(self)(**obj)
|
|
741
753
|
|
|
742
|
-
def __delattr__(self,
|
|
754
|
+
def __delattr__(self, name: str) -> None:
|
|
743
755
|
"""
|
|
744
|
-
Method that removes
|
|
756
|
+
Method that removes name from the object.
|
|
745
757
|
|
|
746
758
|
Args:
|
|
747
|
-
|
|
759
|
+
name (str): The name of the attribute that will be removed.
|
|
748
760
|
|
|
749
761
|
Raises:
|
|
750
762
|
AttributeError: If is frozen.
|
|
751
763
|
"""
|
|
752
764
|
self.__check_frozen__()
|
|
753
|
-
super().__delattr__(
|
|
765
|
+
super().__delattr__(name)
|
|
754
766
|
|
|
755
767
|
def __get_attributes__(self) -> dict:
|
|
756
|
-
"""
|
|
757
|
-
|
|
758
|
-
"""
|
|
759
|
-
return getattr(self, MetaClass._attr_name) # pylint: disable=protected-access
|
|
768
|
+
"""Get all attributes from this class."""
|
|
769
|
+
return getattr(self, MetaClass._attr_name) # noqa: SLF001
|
|
760
770
|
|
|
761
771
|
def __get_clean_value__(self, attr: str, value: Any) -> Any:
|
|
762
772
|
"""
|
|
@@ -769,27 +779,32 @@ class _BaseObject(metaclass=MetaClass):
|
|
|
769
779
|
|
|
770
780
|
def _init_error_handler(self, kwargs: dict, errors: dict[str, Exception]) -> None:
|
|
771
781
|
"""
|
|
772
|
-
|
|
782
|
+
Method is called at the end of the init process if the silent param is True.
|
|
773
783
|
|
|
774
784
|
Args:
|
|
785
|
+
kwargs (dict): The kwargs that were passed to the init.
|
|
775
786
|
errors (dict): A dict {'before_init': None | Exception, 'init': None | Exception, 'after_init': None | Exception}
|
|
776
|
-
"""
|
|
787
|
+
""" # noqa: E501
|
|
777
788
|
|
|
778
|
-
def __setattr__(self,
|
|
789
|
+
def __setattr__(self, name: str, value: Any) -> None:
|
|
779
790
|
"""
|
|
780
791
|
Method changed from BaseClass for check de integrity of data.
|
|
781
792
|
This method is executed on setting attributes in the object.
|
|
782
793
|
Ex: obj.attr = 1
|
|
783
794
|
|
|
795
|
+
Args:
|
|
796
|
+
name (str): The attribute name.
|
|
797
|
+
value (Any): The value that is set.
|
|
798
|
+
|
|
784
799
|
Raises:
|
|
785
800
|
AttributeError: If is frozen.
|
|
786
801
|
"""
|
|
787
802
|
self.__check_frozen__()
|
|
788
803
|
|
|
789
804
|
if getattr(self, '_need_validation', True):
|
|
790
|
-
|
|
805
|
+
value = self.__get_clean_value__(name, value)
|
|
791
806
|
|
|
792
|
-
super().__setattr__(
|
|
807
|
+
super().__setattr__(name, value)
|
|
793
808
|
|
|
794
809
|
@classmethod
|
|
795
810
|
def __set_attribute__(cls, attr_name: str, attr_type: Any, attr_value: Any) -> None:
|
|
@@ -802,8 +817,8 @@ class _BaseObject(metaclass=MetaClass):
|
|
|
802
817
|
attr_type (Any): The type for the new attribute.
|
|
803
818
|
attr_value (Any): The value for the new attribute.
|
|
804
819
|
"""
|
|
805
|
-
attributes = getattr(cls, MetaClass._attr_name, {}) #
|
|
806
|
-
annotations = getattr(cls, MetaClass._anno_name, {}) #
|
|
820
|
+
attributes = getattr(cls, MetaClass._attr_name, {}) # noqa: SLF001
|
|
821
|
+
annotations = getattr(cls, MetaClass._anno_name, {}) # noqa: SLF001
|
|
807
822
|
try:
|
|
808
823
|
# For BaseFields
|
|
809
824
|
annotations[attr_name] = attr_type.attr_type
|
|
@@ -889,7 +904,7 @@ class BaseObject(_BaseObject):
|
|
|
889
904
|
|
|
890
905
|
def __getstate__(self) -> dict:
|
|
891
906
|
"""
|
|
892
|
-
|
|
907
|
+
Method is used by Pickle module to get the correct serialized data.
|
|
893
908
|
https://docs.python.org/3.11/library/pickle.html#handling-stateful-objects
|
|
894
909
|
"""
|
|
895
910
|
# This generates a dictionary with all attributes
|
|
@@ -907,9 +922,9 @@ class BaseObject(_BaseObject):
|
|
|
907
922
|
|
|
908
923
|
return dct
|
|
909
924
|
|
|
910
|
-
def __setstate__(self, state: dict = None) -> None:
|
|
925
|
+
def __setstate__(self, state: dict | None = None) -> None:
|
|
911
926
|
"""
|
|
912
|
-
|
|
927
|
+
Method is used by Pickle module to set back the correct serialized data.
|
|
913
928
|
We need to iterate over every key and set the value to the object.
|
|
914
929
|
|
|
915
930
|
Args:
|
|
@@ -924,7 +939,7 @@ class BaseObject(_BaseObject):
|
|
|
924
939
|
# Set the original value to validate the attributes
|
|
925
940
|
self._need_validation = old_need_validation
|
|
926
941
|
|
|
927
|
-
def to_native(self, add_class_path: str | None = None, recursion: bool = False) -> Any:
|
|
942
|
+
def to_native(self, add_class_path: str | None = None, *, recursion: bool = False) -> Any:
|
|
928
943
|
"""
|
|
929
944
|
Converts the object to the specified Python type.
|
|
930
945
|
|
|
@@ -938,9 +953,9 @@ class BaseObject(_BaseObject):
|
|
|
938
953
|
"""
|
|
939
954
|
return self.to_dict(add_class_path=add_class_path, recursion=recursion)
|
|
940
955
|
|
|
941
|
-
def to_dict(self, add_class_path: bool = False, recursion: bool = False) -> dict:
|
|
956
|
+
def to_dict(self, *, add_class_path: bool = False, recursion: bool = False) -> dict:
|
|
942
957
|
"""
|
|
943
|
-
|
|
958
|
+
Method is used to convert the object to a dictionary.
|
|
944
959
|
If add_class_path is True, the full doted class path will be added to the dictionary.
|
|
945
960
|
If recursion is True, the method will call the to_dict method of the child objects.
|
|
946
961
|
|
|
@@ -966,7 +981,7 @@ class BaseObject(_BaseObject):
|
|
|
966
981
|
for key in keys:
|
|
967
982
|
value = getattr(self, key)
|
|
968
983
|
func = getattr(self, f'_process_{key}', no_op)
|
|
969
|
-
key = config.key_mapping.get(key, key)
|
|
984
|
+
key = config.key_mapping.get(key, key) # noqa: PLW2901
|
|
970
985
|
result = func(value)
|
|
971
986
|
if recursion and isinstance(result, BaseObject):
|
|
972
987
|
result = result.to_dict(add_class_path=add_class_path, recursion=recursion)
|
|
@@ -989,7 +1004,7 @@ class BaseDictConfig(BaseObjectConfig):
|
|
|
989
1004
|
###############################################################################
|
|
990
1005
|
# BaseDict Class Implementation
|
|
991
1006
|
###############################################################################
|
|
992
|
-
class BaseDict(BaseObject):
|
|
1007
|
+
class BaseDict(BaseObject): # noqa: PLW1641
|
|
993
1008
|
"""
|
|
994
1009
|
Extends BaseObject and also guarantees that BaseDict['key'] is equal to BaseDict.key
|
|
995
1010
|
|
|
@@ -1059,7 +1074,7 @@ class BaseDict(BaseObject):
|
|
|
1059
1074
|
"""
|
|
1060
1075
|
return key in self.__data__
|
|
1061
1076
|
|
|
1062
|
-
def __delattr__(self, name: str, caller: str = None) -> None:
|
|
1077
|
+
def __delattr__(self, name: str, caller: str | None = None) -> None:
|
|
1063
1078
|
"""
|
|
1064
1079
|
Removes an atribute from self.
|
|
1065
1080
|
|
|
@@ -1076,13 +1091,11 @@ class BaseDict(BaseObject):
|
|
|
1076
1091
|
# Caller not None means this method was called from __delitem__
|
|
1077
1092
|
# then we do not call the method again avoiding infinite loop
|
|
1078
1093
|
if caller is None:
|
|
1079
|
-
|
|
1094
|
+
with suppress(KeyError):
|
|
1080
1095
|
# Some times the attribute will not exists
|
|
1081
1096
|
self.__delitem__(name, caller='__delattr__')
|
|
1082
|
-
except KeyError:
|
|
1083
|
-
pass
|
|
1084
1097
|
|
|
1085
|
-
def __delitem__(self, key: Any, caller: str = None) -> None:
|
|
1098
|
+
def __delitem__(self, key: Any, caller: str | None = None) -> None:
|
|
1086
1099
|
"""
|
|
1087
1100
|
Removes an key from self.
|
|
1088
1101
|
|
|
@@ -1127,7 +1140,8 @@ class BaseDict(BaseObject):
|
|
|
1127
1140
|
except AttributeError:
|
|
1128
1141
|
pass
|
|
1129
1142
|
|
|
1130
|
-
|
|
1143
|
+
msg = f"'{self.__class__.__name__}' object has no attribute '{name}'."
|
|
1144
|
+
raise AttributeError(msg)
|
|
1131
1145
|
|
|
1132
1146
|
def __getitem__(self, key: str) -> Any:
|
|
1133
1147
|
"""
|
|
@@ -1152,9 +1166,9 @@ class BaseDict(BaseObject):
|
|
|
1152
1166
|
|
|
1153
1167
|
raise KeyError(key) # pylint: disable=raise-missing-from
|
|
1154
1168
|
|
|
1155
|
-
def __ior__(self, other: Any) ->
|
|
1169
|
+
def __ior__(self, other: Any) -> Self:
|
|
1156
1170
|
"""
|
|
1157
|
-
|
|
1171
|
+
Method performs an in-place merge of two objects using the `|=` operator.
|
|
1158
1172
|
If `other` is an instance of the same class, it merges the attributes of `other` into the `self` class.
|
|
1159
1173
|
Otherwise, it tries to merge the `other` dictionary into the `self` class.
|
|
1160
1174
|
|
|
@@ -1200,9 +1214,9 @@ class BaseDict(BaseObject):
|
|
|
1200
1214
|
"""
|
|
1201
1215
|
return not self.__eq__(other)
|
|
1202
1216
|
|
|
1203
|
-
def __or__(self, other: Any) ->
|
|
1217
|
+
def __or__(self, other: Any) -> 'BaseDict':
|
|
1204
1218
|
"""
|
|
1205
|
-
|
|
1219
|
+
Method is used to merge two objects using the `|` operator.
|
|
1206
1220
|
It merges both objects using the `self.__dict__` method if `other` is an instance of the same class.
|
|
1207
1221
|
Otherwise, if `other` is a dictionary, it merges `self.__dict__` with the `other` dictionary.
|
|
1208
1222
|
|
|
@@ -1223,17 +1237,17 @@ class BaseDict(BaseObject):
|
|
|
1223
1237
|
|
|
1224
1238
|
def __repr__(self) -> str:
|
|
1225
1239
|
"""
|
|
1226
|
-
|
|
1240
|
+
Method returns the representation of the object in a string format.
|
|
1227
1241
|
|
|
1228
1242
|
Returns:
|
|
1229
1243
|
str: The string representation of the object.
|
|
1230
1244
|
"""
|
|
1231
1245
|
return self.__data__.__repr__()
|
|
1232
1246
|
|
|
1233
|
-
def __ror__(self, other: Any) ->
|
|
1247
|
+
def __ror__(self, other: Any) -> 'BaseDict':
|
|
1234
1248
|
"""
|
|
1235
|
-
|
|
1236
|
-
It merges the current object with `other` using the `__dict__` method if `other` is an instance of the
|
|
1249
|
+
Method is used to merge two objects using the `|` operator, with the current object being on the right side.
|
|
1250
|
+
It merges the current object with `other` using the `__dict__` method if `other` is an instance of the class.
|
|
1237
1251
|
If `other` is a dictionary, it merges the `other` dictionary with `self.__dict__`.
|
|
1238
1252
|
|
|
1239
1253
|
Args:
|
|
@@ -1251,7 +1265,7 @@ class BaseDict(BaseObject):
|
|
|
1251
1265
|
# don't attempt to compare against unrelated types
|
|
1252
1266
|
return NotImplemented
|
|
1253
1267
|
|
|
1254
|
-
def __setattr__(self, name: str, value: Any, caller: str = None) -> None:
|
|
1268
|
+
def __setattr__(self, name: str, value: Any, caller: str | None = None) -> None:
|
|
1255
1269
|
"""
|
|
1256
1270
|
Method changed from BaseClass for guarantee de integrity of data attributes.
|
|
1257
1271
|
This method is executed on setting attributes in the object.
|
|
@@ -1272,7 +1286,7 @@ class BaseDict(BaseObject):
|
|
|
1272
1286
|
# For integrity guarantee writes the value to the dictionary key as well.
|
|
1273
1287
|
self.__setitem__(name, new_value, caller='__setattr__')
|
|
1274
1288
|
|
|
1275
|
-
def __setitem__(self, key: str, item: Any, caller: str = None) -> None:
|
|
1289
|
+
def __setitem__(self, key: str, item: Any, caller: str | None = None) -> None:
|
|
1276
1290
|
"""
|
|
1277
1291
|
Method changed from BaseClass for guarantee de integrity of data keys.
|
|
1278
1292
|
This method is executed on setting items in the dictionary.
|
|
@@ -1285,7 +1299,8 @@ class BaseDict(BaseObject):
|
|
|
1285
1299
|
raise KeyError("Keys can't start with '_'.")
|
|
1286
1300
|
config = getattr(self, CONFIG_ATTRIBUTE_NAME)
|
|
1287
1301
|
if key in config.keys_blacklist:
|
|
1288
|
-
|
|
1302
|
+
msg = f'The key cannot be called "{key}".'
|
|
1303
|
+
raise KeyError(msg)
|
|
1289
1304
|
|
|
1290
1305
|
# When value is associated:
|
|
1291
1306
|
# directly on the key Ex dict['key'] = value then caller will be None
|
|
@@ -1301,9 +1316,9 @@ class BaseDict(BaseObject):
|
|
|
1301
1316
|
if not isinstance(getattr(type(self), key, None), property):
|
|
1302
1317
|
self.__data__.__setitem__(key, item)
|
|
1303
1318
|
|
|
1304
|
-
def __setstate__(self, state: dict = None) -> None:
|
|
1319
|
+
def __setstate__(self, state: dict | None = None) -> None:
|
|
1305
1320
|
"""
|
|
1306
|
-
|
|
1321
|
+
Method is used by Pickle module to set back the correct serialized data.
|
|
1307
1322
|
We need to iterate over every key and set the value to the object.
|
|
1308
1323
|
|
|
1309
1324
|
Args:
|
|
@@ -1319,7 +1334,7 @@ class BaseDict(BaseObject):
|
|
|
1319
1334
|
## Public Methods
|
|
1320
1335
|
def clear(self) -> None:
|
|
1321
1336
|
"""
|
|
1322
|
-
|
|
1337
|
+
Method clears the dictionary.
|
|
1323
1338
|
|
|
1324
1339
|
Raises:
|
|
1325
1340
|
AttributeError: If is frozen.
|
|
@@ -1376,7 +1391,7 @@ class BaseDict(BaseObject):
|
|
|
1376
1391
|
|
|
1377
1392
|
def is_valid_key(self, key: str) -> bool:
|
|
1378
1393
|
"""
|
|
1379
|
-
|
|
1394
|
+
Method checks if the key is valid.
|
|
1380
1395
|
Valid keys are the ones that not starts with '_' and
|
|
1381
1396
|
are not in the config.keys_blacklist.
|
|
1382
1397
|
|
|
@@ -1390,15 +1405,11 @@ class BaseDict(BaseObject):
|
|
|
1390
1405
|
return not key.startswith('_') and key not in config.keys_blacklist
|
|
1391
1406
|
|
|
1392
1407
|
def items(self) -> dict_items:
|
|
1393
|
-
"""
|
|
1394
|
-
Return a new view of the dictionary's items ((key, value) pairs).
|
|
1395
|
-
"""
|
|
1408
|
+
"""Return a new view of the dictionary's items ((key, value) pairs)."""
|
|
1396
1409
|
return self.__data__.items()
|
|
1397
1410
|
|
|
1398
1411
|
def keys(self) -> dict_keys:
|
|
1399
|
-
"""
|
|
1400
|
-
Return a new view of the dictionary's keys.
|
|
1401
|
-
"""
|
|
1412
|
+
"""Return a new view of the dictionary's keys."""
|
|
1402
1413
|
return self.__data__.keys()
|
|
1403
1414
|
|
|
1404
1415
|
def pop(self, *args) -> Any:
|
|
@@ -1417,11 +1428,9 @@ class BaseDict(BaseObject):
|
|
|
1417
1428
|
self.__check_frozen__()
|
|
1418
1429
|
ret = self.__data__.pop(*args)
|
|
1419
1430
|
|
|
1420
|
-
|
|
1431
|
+
with suppress(AttributeError):
|
|
1421
1432
|
# Some times the attribute will not exists
|
|
1422
1433
|
self.__delattr__(args[0]) # pylint: disable=unnecessary-dunder-call
|
|
1423
|
-
except AttributeError:
|
|
1424
|
-
pass
|
|
1425
1434
|
|
|
1426
1435
|
return ret
|
|
1427
1436
|
|
|
@@ -1460,10 +1469,9 @@ class BaseDict(BaseObject):
|
|
|
1460
1469
|
if self.is_valid_key(key=key):
|
|
1461
1470
|
self[key] = value
|
|
1462
1471
|
else:
|
|
1463
|
-
|
|
1472
|
+
msg = f'The key cannot be called "{key}".'
|
|
1473
|
+
raise KeyError(msg)
|
|
1464
1474
|
|
|
1465
1475
|
def values(self) -> dict_values:
|
|
1466
|
-
"""
|
|
1467
|
-
Return a new view of the dictionary's values.
|
|
1468
|
-
"""
|
|
1476
|
+
"""Return a new view of the dictionary's values."""
|
|
1469
1477
|
return self.__data__.values()
|