value-object-pattern 0.1.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 (73) hide show
  1. value_object_pattern/__init__.py +10 -0
  2. value_object_pattern/decorators/__init__.py +7 -0
  3. value_object_pattern/decorators/value_object_process.py +83 -0
  4. value_object_pattern/decorators/value_object_validation.py +78 -0
  5. value_object_pattern/models/__init__.py +3 -0
  6. value_object_pattern/models/value_object.py +383 -0
  7. value_object_pattern/py.typed +0 -0
  8. value_object_pattern/usables/__init__.py +54 -0
  9. value_object_pattern/usables/dates/__init__.py +9 -0
  10. value_object_pattern/usables/dates/date/__init__.py +7 -0
  11. value_object_pattern/usables/dates/date/date_value_object.py +162 -0
  12. value_object_pattern/usables/dates/date/string_date_value_object.py +201 -0
  13. value_object_pattern/usables/dates/datetime/__init__.py +7 -0
  14. value_object_pattern/usables/dates/datetime/datetime_value_object.py +193 -0
  15. value_object_pattern/usables/dates/datetime/string_datetime_value_object.py +237 -0
  16. value_object_pattern/usables/identifiers/__init__.py +7 -0
  17. value_object_pattern/usables/identifiers/country_ids/__init__.py +3 -0
  18. value_object_pattern/usables/identifiers/country_ids/spain/__init__.py +3 -0
  19. value_object_pattern/usables/identifiers/country_ids/spain/dni_value_object.py +63 -0
  20. value_object_pattern/usables/identifiers/string_uuid_value_object.py +56 -0
  21. value_object_pattern/usables/identifiers/uuid_value_object.py +40 -0
  22. value_object_pattern/usables/internet/__init__.py +38 -0
  23. value_object_pattern/usables/internet/api_keys/__init__.py +13 -0
  24. value_object_pattern/usables/internet/api_keys/aws_access_key_id_value_object.py +40 -0
  25. value_object_pattern/usables/internet/api_keys/aws_secret_access_key_value_object.py +40 -0
  26. value_object_pattern/usables/internet/api_keys/github_personal_access_token_value_object.py +41 -0
  27. value_object_pattern/usables/internet/api_keys/openai_api_key_value_object.py +40 -0
  28. value_object_pattern/usables/internet/api_keys/resend_api_key_value_object.py +40 -0
  29. value_object_pattern/usables/internet/aws_cloud_region_value_object.py +77 -0
  30. value_object_pattern/usables/internet/domain_value_object.py +149 -0
  31. value_object_pattern/usables/internet/host_value_object.py +143 -0
  32. value_object_pattern/usables/internet/ipv4_address_value_object.py +305 -0
  33. value_object_pattern/usables/internet/ipv4_network_value_object.py +165 -0
  34. value_object_pattern/usables/internet/ipv6_address_value_object.py +288 -0
  35. value_object_pattern/usables/internet/ipv6_network_value_object.py +145 -0
  36. value_object_pattern/usables/internet/mac_address_value_object.py +390 -0
  37. value_object_pattern/usables/internet/port_value_object.py +682 -0
  38. value_object_pattern/usables/internet/uri/__init__.py +11 -0
  39. value_object_pattern/usables/internet/uri/http_https_url_value_object.py +39 -0
  40. value_object_pattern/usables/internet/uri/http_url_value_object.py +39 -0
  41. value_object_pattern/usables/internet/uri/https_url_value_object.py +39 -0
  42. value_object_pattern/usables/internet/uri/url_value_object.py +396 -0
  43. value_object_pattern/usables/primitives/__init__.py +45 -0
  44. value_object_pattern/usables/primitives/boolean/__init__.py +9 -0
  45. value_object_pattern/usables/primitives/boolean/boolean_value_object.py +36 -0
  46. value_object_pattern/usables/primitives/boolean/false_value_object.py +37 -0
  47. value_object_pattern/usables/primitives/boolean/true_value_object.py +37 -0
  48. value_object_pattern/usables/primitives/bytes/__init__.py +3 -0
  49. value_object_pattern/usables/primitives/bytes/bytes_value_object.py +36 -0
  50. value_object_pattern/usables/primitives/float/__init__.py +9 -0
  51. value_object_pattern/usables/primitives/float/float_value_object.py +36 -0
  52. value_object_pattern/usables/primitives/float/negative_float_value_object.py +37 -0
  53. value_object_pattern/usables/primitives/float/positive_float_value_object.py +37 -0
  54. value_object_pattern/usables/primitives/integer/__init__.py +13 -0
  55. value_object_pattern/usables/primitives/integer/even_integer_value_object.py +37 -0
  56. value_object_pattern/usables/primitives/integer/integer_value_object.py +36 -0
  57. value_object_pattern/usables/primitives/integer/negative_integer_value_object.py +37 -0
  58. value_object_pattern/usables/primitives/integer/odd_integer_value_object.py +37 -0
  59. value_object_pattern/usables/primitives/integer/positive_integer_value_object.py +37 -0
  60. value_object_pattern/usables/primitives/string/__init__.py +21 -0
  61. value_object_pattern/usables/primitives/string/alpha_value_object.py +37 -0
  62. value_object_pattern/usables/primitives/string/alphanumeric_value_object.py +37 -0
  63. value_object_pattern/usables/primitives/string/digit_value_object.py +37 -0
  64. value_object_pattern/usables/primitives/string/lowercase_string_value_object.py +37 -0
  65. value_object_pattern/usables/primitives/string/non_empty_string_value_object.py +37 -0
  66. value_object_pattern/usables/primitives/string/printable_string_value_object.py +37 -0
  67. value_object_pattern/usables/primitives/string/string_value_object.py +36 -0
  68. value_object_pattern/usables/primitives/string/trimmed_string_value_object.py +37 -0
  69. value_object_pattern/usables/primitives/string/uppercase_string_value_object.py +37 -0
  70. value_object_pattern-0.1.0.dist-info/METADATA +95 -0
  71. value_object_pattern-0.1.0.dist-info/RECORD +73 -0
  72. value_object_pattern-0.1.0.dist-info/WHEEL +4 -0
  73. value_object_pattern-0.1.0.dist-info/licenses/LICENSE.md +21 -0
@@ -0,0 +1,10 @@
1
+ __version__ = '0.1.0'
2
+
3
+ from .decorators import process, validation
4
+ from .models import ValueObject
5
+
6
+ __all__ = (
7
+ 'ValueObject',
8
+ 'process',
9
+ 'validation',
10
+ )
@@ -0,0 +1,7 @@
1
+ from .value_object_process import process
2
+ from .value_object_validation import validation
3
+
4
+ __all__ = (
5
+ 'process',
6
+ 'validation',
7
+ )
@@ -0,0 +1,83 @@
1
+ """
2
+ Process decorator for value object pattern.
3
+ """
4
+
5
+ from functools import wraps
6
+ from typing import Any, Callable, TypeVar
7
+
8
+ T = TypeVar('T')
9
+
10
+
11
+ def process(order: int | None = None) -> Callable[[Callable[..., T]], Callable[..., T]]:
12
+ """
13
+ Decorator for process the value after the value is validated.
14
+
15
+ Args:
16
+ order (int | None, optional): The order of the process that will be executed, if None the functions will be
17
+ executed alphabetically. Defaults to None.
18
+
19
+ Raises:
20
+ TypeError: If the order is not an integer.
21
+ ValueError: If the order is not equal or greater than 0.
22
+
23
+ Returns:
24
+ Callable[[Callable[..., T]], Callable[..., T]]: Wrapper function for the process.
25
+
26
+ Example:
27
+ ```python
28
+ from value_object_pattern import ValueObject, process
29
+
30
+
31
+ class UpperStringValueObject(ValueObject[str]):
32
+ @process()
33
+ def ensure_value_is_upper(self, value: str) -> str:
34
+ return value.upper()
35
+
36
+
37
+ string = UpperStringValueObject(value='hello world')
38
+ print(string)
39
+ # >>> HELLO WORLD
40
+ ```
41
+ """
42
+
43
+ def decorator(function: Callable[..., T]) -> Callable[..., T]:
44
+ """
45
+ Decorator for process the value after the value is validated.
46
+
47
+ Args:
48
+ function (Callable[..., T]): Function to be execution after the value object is validated.
49
+
50
+ Raises:
51
+ TypeError: If the order is not an integer.
52
+ ValueError: If the order is not equal or greater than 0.
53
+
54
+ Returns:
55
+ Callable[..., T]: Wrapper function for the process.
56
+ """
57
+ if order is not None:
58
+ if type(order) is not int:
59
+ raise TypeError(f'Process order <<<{order}>>> must be an integer. Got <<<{type(order).__name__}>>> type.') # noqa: E501 # fmt: skip
60
+
61
+ if order < 0:
62
+ raise ValueError(f'Process order <<<{order}>>> must be equal or greater than 0.')
63
+
64
+ function._is_process = True # type: ignore[attr-defined]
65
+ function._order = function.__name__ if order is None else str(order) # type: ignore[attr-defined]
66
+
67
+ @wraps(wrapped=function)
68
+ def wrapper(*args: tuple[Any, ...], **kwargs: dict[str, Any]) -> T:
69
+ """
70
+ Wrapper for process.
71
+
72
+ Args:
73
+ *args (tuple[Any, ...]): The arguments for the function.
74
+ **kwargs (dict[str, Any]): The keyword arguments for the function.
75
+
76
+ Returns:
77
+ T: The return value of the function.
78
+ """
79
+ return function(*args, **kwargs)
80
+
81
+ return wrapper
82
+
83
+ return decorator
@@ -0,0 +1,78 @@
1
+ """
2
+ Validation decorator for value object pattern.
3
+ """
4
+
5
+ from functools import wraps
6
+ from typing import Any, Callable
7
+
8
+
9
+ def validation(order: int | None = None) -> Callable[[Callable[..., None]], Callable[..., None]]:
10
+ """
11
+ Decorator for validation the value before the value is created.
12
+
13
+ Args:
14
+ order (int | None, optional): The order of the validation that will be executed, if None the functions will be
15
+ executed alphabetically. Defaults to None.
16
+
17
+ Raises:
18
+ TypeError: If the order is not an integer.
19
+ ValueError: If the order is not equal or greater than 0.
20
+
21
+ Returns:
22
+ Callable[[Callable[..., None]], Callable[..., None]]: Wrapper function for the validation.
23
+
24
+ Example:
25
+ ```python
26
+ from value_object_pattern import ValueObject, validation
27
+
28
+
29
+ class IntegerValueObject(ValueObject[int]):
30
+ @validation()
31
+ def ensure_value_is_integer(self, value: int) -> None:
32
+ if type(value) is not int:
33
+ raise TypeError(f'IntegerValueObject value <<<{value}>>> must be an integer. Got <<<{type(value).__name__}>>> type.')
34
+
35
+
36
+ integer = IntegerValueObject(value='invalid')
37
+ # >>> TypeError: IntegerValueObject value <<<invalid>>> must be an integer. Got <<<str>>> type.
38
+ ```
39
+ """ # noqa: E501 # fmt: skip
40
+
41
+ def decorator(function: Callable[..., None]) -> Callable[..., None]:
42
+ """
43
+ Decorator for validation the value before the value is created.
44
+
45
+ Args:
46
+ function (Callable[..., None]): Function to be execution before the value object is created.
47
+
48
+ Raises:
49
+ TypeError: If the order is not an integer.
50
+ ValueError: If the order is not equal or greater than 0.
51
+
52
+ Returns:
53
+ Callable[..., None]: Wrapper function for the validation.
54
+ """
55
+ if order is not None:
56
+ if type(order) is not int:
57
+ raise TypeError(f'Validation order <<<{order}>>> must be an integer. Got <<<{type(order).__name__}>>> type.') # noqa: E501 # fmt: skip
58
+
59
+ if order < 0:
60
+ raise ValueError(f'Validation order <<<{order}>>> must be equal or greater than 0.')
61
+
62
+ function._is_validation = True # type: ignore[attr-defined]
63
+ function._order = function.__name__ if order is None else str(order) # type: ignore[attr-defined]
64
+
65
+ @wraps(wrapped=function)
66
+ def wrapper(*args: tuple[Any, ...], **kwargs: dict[str, Any]) -> None:
67
+ """
68
+ Wrapper for validation.
69
+
70
+ Args:
71
+ *args (tuple[Any, ...]): The arguments for the function.
72
+ **kwargs (dict[str, Any]): The keyword arguments for the function.
73
+ """
74
+ function(*args, **kwargs)
75
+
76
+ return wrapper
77
+
78
+ return decorator
@@ -0,0 +1,3 @@
1
+ from .value_object import ValueObject
2
+
3
+ __all__ = ('ValueObject',)
@@ -0,0 +1,383 @@
1
+ """
2
+ Value object generic type.
3
+ """
4
+
5
+ from abc import ABC
6
+ from collections import deque
7
+ from sys import version_info
8
+ from typing import Any, Callable, Generic, NoReturn, TypeVar
9
+
10
+ if version_info >= (3, 12):
11
+ from typing import override # pragma: no cover
12
+ else:
13
+ from typing_extensions import override # pragma: no cover
14
+
15
+ T = TypeVar('T')
16
+
17
+
18
+ class ValueObject(ABC, Generic[T]):
19
+ """
20
+ ValueObject generic type.
21
+
22
+ Example:
23
+ ```python
24
+ from value_object_pattern import ValueObject
25
+
26
+
27
+ class IntegerValueObject(ValueObject[int]):
28
+ pass
29
+
30
+
31
+ integer = IntegerValueObject(value=10)
32
+ print(repr(integer))
33
+ # >>> IntegerValueObject(value=10)
34
+ ```
35
+ """
36
+
37
+ __slots__ = ('_title', '_value')
38
+ __match_args__ = ('_title', '_value')
39
+
40
+ _value: T
41
+ _title: str
42
+
43
+ def __init__(self, *, value: T, title: str | None = None) -> None:
44
+ """
45
+ ValueObject value object constructor.
46
+
47
+ Args:
48
+ value (T): The value to store in the value object.
49
+ title (str | None, optional): The title of the value object when raising exceptions, if title is None, the
50
+ class name is used instead. Defaults to None.
51
+
52
+ Raises:
53
+ TypeError: If the title is not a string.
54
+ ValueError: If the title contains leading or trailing whitespaces.
55
+
56
+ Example:
57
+ ```python
58
+ from value_object_pattern import ValueObject
59
+
60
+
61
+ class IntegerValueObject(ValueObject[int]):
62
+ pass
63
+
64
+
65
+ integer = IntegerValueObject(value=10)
66
+ print(repr(integer))
67
+ # >>> IntegerValueObject(value=10)
68
+ ```
69
+ """
70
+ if title is None:
71
+ title = self.__class__.__name__
72
+
73
+ if type(title) is not str:
74
+ raise TypeError(f'ValueObject value <<<{title}>>> must be a string. Got <<<{type(title).__name__}>>> instead.') # noqa: E501 # fmt: skip
75
+
76
+ if title.strip() != title:
77
+ raise ValueError(f'ValueObject title <<<{title}>>> contains leading or trailing whitespaces. Only trimmed values are allowed.') # noqa: E501 # fmt: skip
78
+
79
+ object.__setattr__(self, '_title', title)
80
+
81
+ self._validate(value=value)
82
+ value = self._process(value=value)
83
+
84
+ object.__setattr__(self, '_value', value)
85
+
86
+ @override
87
+ def __repr__(self) -> str:
88
+ """
89
+ Returns a detailed string representation of the value object.
90
+
91
+ Returns:
92
+ str: A string representation of the value object in the format 'ClassName(value=value)'.
93
+
94
+ Example:
95
+ ```python
96
+ from value_object_pattern import ValueObject
97
+
98
+
99
+ class IntegerValueObject(ValueObject[int]):
100
+ pass
101
+
102
+
103
+ integer = IntegerValueObject(value=10)
104
+ print(repr(integer))
105
+ # >>> IntegerValueObject(value=10)
106
+ ```
107
+ """
108
+ return f'{self.__class__.__name__}(value={self._value!s})'
109
+
110
+ @override
111
+ def __str__(self) -> str:
112
+ """
113
+ Returns a simple string representation of the value object.
114
+
115
+ Returns:
116
+ str: The string representation of the value object value.
117
+
118
+ Example:
119
+ ```python
120
+ from value_object_pattern import ValueObject
121
+
122
+
123
+ class IntegerValueObject(ValueObject[int]):
124
+ pass
125
+
126
+
127
+ integer = IntegerValueObject(value=10)
128
+ print(integer)
129
+ # >>> 10
130
+ ```
131
+ """
132
+ return str(object=self._value)
133
+
134
+ @override
135
+ def __hash__(self) -> int:
136
+ """
137
+ Returns the hash of the value object.
138
+
139
+ Returns:
140
+ int: Hash of the value object.
141
+
142
+ Example:
143
+ ```python
144
+ from value_object_pattern import ValueObject
145
+
146
+
147
+ class IntegerValueObject(ValueObject[int]):
148
+ pass
149
+
150
+
151
+ integer = IntegerValueObject(value=10)
152
+ print(hash(integer))
153
+ # >>> 10
154
+ ```
155
+ """
156
+ return hash(self._value)
157
+
158
+ @override
159
+ def __eq__(self, other: object) -> bool:
160
+ """
161
+ Check if the value object is equal to another value object.
162
+
163
+ Args:
164
+ other (object): Object to compare.
165
+
166
+ Returns:
167
+ bool: True if both objects are equal, otherwise False.
168
+
169
+ Example:
170
+ ```python
171
+ from value_object_pattern import ValueObject
172
+
173
+
174
+ class IntegerValueObject(ValueObject[int]):
175
+ pass
176
+
177
+
178
+ integer_a = IntegerValueObject(value=10)
179
+ integer_b = IntegerValueObject(value=16)
180
+ print(integer_a == integer_b)
181
+ # >>> False
182
+ ```
183
+ """
184
+ if not isinstance(other, self.__class__):
185
+ return NotImplemented
186
+
187
+ return self._value == other.value
188
+
189
+ @override
190
+ def __setattr__(self, key: str, value: T) -> NoReturn:
191
+ """
192
+ Prevents modification or addition of attributes in the value object.
193
+
194
+ Args:
195
+ key (str): The name of the attribute.
196
+ value (T): The value to be assigned to the attribute.
197
+
198
+ Raises:
199
+ AttributeError: If there is an attempt to modify an existing attribute.
200
+ AttributeError: If there is an attempt to add a new attribute.
201
+ """
202
+ public_key = key.replace('_', '')
203
+ public_slots1 = [slot.replace('_', '') for slot in self.__slots__]
204
+
205
+ if key in self.__slots__:
206
+ raise AttributeError(f'Cannot modify attribute "{key}" of immutable instance.')
207
+
208
+ if public_key in public_slots1:
209
+ raise AttributeError(f'Cannot modify attribute "{public_key}" of immutable instance.')
210
+
211
+ raise AttributeError(f'{self.__class__.__name__} object has no attribute "{key}".')
212
+
213
+ def _process(self, value: T) -> T:
214
+ """
215
+ This method processes the value object value after validation. It ensure that the value object is stored in the
216
+ correct format, by executing all methods with the `@process` decorator.
217
+
218
+ Args:
219
+ value (T): The value object value.
220
+
221
+ Returns:
222
+ T: The processed value object value.
223
+ """
224
+ methods = self._gather_decorated_methods(instance=self, attribute_name='_is_process')
225
+ while methods:
226
+ method: Callable[..., T] = methods.popleft().__get__(self, self.__class__)
227
+ value = method(value=value)
228
+
229
+ return value
230
+
231
+ def _validate(self, value: T) -> None:
232
+ """
233
+ This method validates that the value follows the domain rules, by executing all methods with the `@validation`
234
+ decorator.
235
+
236
+ Args:
237
+ value (T): The value object value.
238
+ """
239
+ try:
240
+ methods = self._gather_decorated_methods(instance=self, attribute_name='_is_validation')
241
+ while methods:
242
+ method: Callable[..., T] = methods.popleft().__get__(self, self.__class__)
243
+ method(value=value)
244
+
245
+ except Exception as error:
246
+ classes = self._post_order_dfs_mro(cls=self.__class__, cut_off=ValueObject)
247
+ for class_name in {cls.__name__ for cls in classes}:
248
+ error.args = (str(object=error.args[0]).replace(class_name, self.title),)
249
+
250
+ raise error
251
+
252
+ def _post_order_dfs_mro(self, cls: type, visited: set[type] | None = None, cut_off: type = object) -> list[type]:
253
+ """
254
+ Computes the Post-Order Depth-First Search (DFS) Method Resolution Order (MRO) of a class.
255
+
256
+ Args:
257
+ cls (type): The class to process.
258
+ visited (set[type] | None, optional): A set of already visited classes (to prevent duplicates). Defaults
259
+ to None.
260
+ cut_off (type, optional): The class to stop the search. Defaults to object.
261
+
262
+ Returns:
263
+ list[type]: A list of classes type sorted by post-order DFS MRO.
264
+
265
+ References:
266
+ DFS: https://en.wikipedia.org/wiki/Depth-first_search
267
+ MRO: https://docs.python.org/3/howto/mro.html
268
+ """
269
+ if cls is cut_off:
270
+ return []
271
+
272
+ if visited is None:
273
+ visited = set()
274
+
275
+ result = []
276
+ for parent in cls.__bases__:
277
+ if parent not in visited and parent is not object: # pragma: no cover
278
+ result.extend(self._post_order_dfs_mro(cls=parent, visited=visited, cut_off=cut_off))
279
+
280
+ if cls not in visited: # pragma: no cover
281
+ visited.add(cls)
282
+ result.append(cls)
283
+
284
+ return result
285
+
286
+ def _gather_decorated_methods(self, instance: object, attribute_name: str) -> deque[Callable[..., Any]]:
287
+ """
288
+ Gathers decorated methods from instance.__class__ and its parent classes following the post-order DFS MRO,
289
+ returning them in a deque with the methods sorted by class hierarchy, method order, and method name.
290
+
291
+ Args:
292
+ instance (object): The object instance whose class hierarchy is inspected.
293
+ attribute_name (str): The attribute name used to identify the methods.
294
+
295
+ Returns
296
+ deque[Callable[..., Any]]: A deque of methods sorted by class hierarchy, method order, and method name.
297
+
298
+ References:
299
+ DFS: https://en.wikipedia.org/wiki/Depth-first_search
300
+ MRO: https://docs.python.org/3/howto/mro.html
301
+ """
302
+
303
+ def sort_key(item: tuple[str, str, Callable[..., Any]]) -> tuple[int, str, str]:
304
+ """
305
+ Sorts the methods by class hierarchy, method order attribute, and method name.
306
+ The only global variable used is classes_names.
307
+
308
+ Args:
309
+ item (tuple[str, str, Callable[..., Any]]): The item to sort.
310
+
311
+ Returns:
312
+ tuple[int, str, str]: A tuple with the class index, method order, and method name.
313
+ """
314
+ class_name, method_name, method = item
315
+ class_index = classes_names.get(class_name, 999)
316
+ order = getattr(method, '_order', method_name)
317
+
318
+ return int(class_index), order, method_name
319
+
320
+ classes = self._post_order_dfs_mro(cls=instance.__class__, cut_off=ValueObject)
321
+ classes_names = {cls.__name__: index for index, cls in enumerate(iterable=classes)}
322
+
323
+ classes_methods: deque[tuple[str, str, Callable[..., Any]]] = deque()
324
+ for cls in classes:
325
+ for method_name, method in cls.__dict__.items():
326
+ if not callable(method):
327
+ continue
328
+
329
+ if not getattr(method, attribute_name, False):
330
+ continue # only methods with the attribute
331
+
332
+ classes_methods.append((method.__qualname__.split('.')[0], method_name, method))
333
+
334
+ # sort by class hierarchy, method order attribute, and method name
335
+ return deque([method for _, _, method in sorted(classes_methods, key=sort_key)])
336
+
337
+ @property
338
+ def value(self) -> T:
339
+ """
340
+ Returns the value object value.
341
+
342
+ Returns:
343
+ T: The value object value.
344
+
345
+ Example:
346
+ ```python
347
+ from value_object_pattern import ValueObject
348
+
349
+
350
+ class IntegerValueObject(ValueObject[int]):
351
+ pass
352
+
353
+
354
+ integer = IntegerValueObject(value=10)
355
+ print(integer.value)
356
+ # >>> 10
357
+ ```
358
+ """
359
+ return self._value
360
+
361
+ @property
362
+ def title(self) -> str:
363
+ """
364
+ Returns the value object title.
365
+
366
+ Returns:
367
+ str: The value object title.
368
+
369
+ Example:
370
+ ```python
371
+ from value_object_pattern import ValueObject
372
+
373
+
374
+ class IntegerValueObject(ValueObject[int]):
375
+ pass
376
+
377
+
378
+ integer = IntegerValueObject(value=10)
379
+ print(integer.title)
380
+ # >>> IntegerValueObject
381
+ ```
382
+ """
383
+ return self._title
File without changes
@@ -0,0 +1,54 @@
1
+ from .primitives import (
2
+ AlphaStringValueObject,
3
+ AlphanumericStringValueObject,
4
+ BooleanValueObject,
5
+ BytesValueObject,
6
+ DigitStringValueObject,
7
+ EvenIntegerValueObject,
8
+ FalseValueObject,
9
+ FloatValueObject,
10
+ IntegerValueObject,
11
+ LowercaseStringValueObject,
12
+ NegativeFloatValueObject,
13
+ NegativeIntegerValueObject,
14
+ NotEmptyStringValueObject,
15
+ OddIntegerValueObject,
16
+ PositiveFloatValueObject,
17
+ PositiveIntegerValueObject,
18
+ PrintableStringValueObject,
19
+ StringValueObject,
20
+ TrimmedStringValueObject,
21
+ TrueValueObject,
22
+ UppercaseStringValueObject,
23
+ )
24
+
25
+ __all__ = (
26
+ 'AlphaStringValueObject',
27
+ 'AlphanumericStringValueObject',
28
+ 'BooleanValueObject',
29
+ 'BytesValueObject',
30
+ 'DigitStringValueObject',
31
+ 'EvenIntegerValueObject',
32
+ 'FalseValueObject',
33
+ 'FloatValueObject',
34
+ 'HexadecimalStringValueObject',
35
+ 'IntegerValueObject',
36
+ 'LowercaseStringValueObject',
37
+ 'LowercaseStringValueObject',
38
+ 'NegativeFloatValueObject',
39
+ 'NegativeIntegerValueObject',
40
+ 'NotEmptyStringValueObject',
41
+ 'NotEmptyStringValueObject',
42
+ 'OddIntegerValueObject',
43
+ 'PositiveFloatValueObject',
44
+ 'PositiveIntegerValueObject',
45
+ 'PrintableStringValueObject',
46
+ 'PrintableStringValueObject',
47
+ 'StringValueObject',
48
+ 'StringValueObject',
49
+ 'TrimmedStringValueObject',
50
+ 'TrimmedStringValueObject',
51
+ 'TrueValueObject',
52
+ 'UppercaseStringValueObject',
53
+ 'UppercaseStringValueObject',
54
+ )
@@ -0,0 +1,9 @@
1
+ from .date import DateValueObject, StringDateValueObject
2
+ from .datetime import DatetimeValueObject, StringDatetimeValueObject
3
+
4
+ __all__ = (
5
+ 'DateValueObject',
6
+ 'DatetimeValueObject',
7
+ 'StringDateValueObject',
8
+ 'StringDatetimeValueObject',
9
+ )
@@ -0,0 +1,7 @@
1
+ from .date_value_object import DateValueObject
2
+ from .string_date_value_object import StringDateValueObject
3
+
4
+ __all__ = (
5
+ 'DateValueObject',
6
+ 'StringDateValueObject',
7
+ )