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.
- value_object_pattern/__init__.py +10 -0
- value_object_pattern/decorators/__init__.py +7 -0
- value_object_pattern/decorators/value_object_process.py +83 -0
- value_object_pattern/decorators/value_object_validation.py +78 -0
- value_object_pattern/models/__init__.py +3 -0
- value_object_pattern/models/value_object.py +383 -0
- value_object_pattern/py.typed +0 -0
- value_object_pattern/usables/__init__.py +54 -0
- value_object_pattern/usables/dates/__init__.py +9 -0
- value_object_pattern/usables/dates/date/__init__.py +7 -0
- value_object_pattern/usables/dates/date/date_value_object.py +162 -0
- value_object_pattern/usables/dates/date/string_date_value_object.py +201 -0
- value_object_pattern/usables/dates/datetime/__init__.py +7 -0
- value_object_pattern/usables/dates/datetime/datetime_value_object.py +193 -0
- value_object_pattern/usables/dates/datetime/string_datetime_value_object.py +237 -0
- value_object_pattern/usables/identifiers/__init__.py +7 -0
- value_object_pattern/usables/identifiers/country_ids/__init__.py +3 -0
- value_object_pattern/usables/identifiers/country_ids/spain/__init__.py +3 -0
- value_object_pattern/usables/identifiers/country_ids/spain/dni_value_object.py +63 -0
- value_object_pattern/usables/identifiers/string_uuid_value_object.py +56 -0
- value_object_pattern/usables/identifiers/uuid_value_object.py +40 -0
- value_object_pattern/usables/internet/__init__.py +38 -0
- value_object_pattern/usables/internet/api_keys/__init__.py +13 -0
- value_object_pattern/usables/internet/api_keys/aws_access_key_id_value_object.py +40 -0
- value_object_pattern/usables/internet/api_keys/aws_secret_access_key_value_object.py +40 -0
- value_object_pattern/usables/internet/api_keys/github_personal_access_token_value_object.py +41 -0
- value_object_pattern/usables/internet/api_keys/openai_api_key_value_object.py +40 -0
- value_object_pattern/usables/internet/api_keys/resend_api_key_value_object.py +40 -0
- value_object_pattern/usables/internet/aws_cloud_region_value_object.py +77 -0
- value_object_pattern/usables/internet/domain_value_object.py +149 -0
- value_object_pattern/usables/internet/host_value_object.py +143 -0
- value_object_pattern/usables/internet/ipv4_address_value_object.py +305 -0
- value_object_pattern/usables/internet/ipv4_network_value_object.py +165 -0
- value_object_pattern/usables/internet/ipv6_address_value_object.py +288 -0
- value_object_pattern/usables/internet/ipv6_network_value_object.py +145 -0
- value_object_pattern/usables/internet/mac_address_value_object.py +390 -0
- value_object_pattern/usables/internet/port_value_object.py +682 -0
- value_object_pattern/usables/internet/uri/__init__.py +11 -0
- value_object_pattern/usables/internet/uri/http_https_url_value_object.py +39 -0
- value_object_pattern/usables/internet/uri/http_url_value_object.py +39 -0
- value_object_pattern/usables/internet/uri/https_url_value_object.py +39 -0
- value_object_pattern/usables/internet/uri/url_value_object.py +396 -0
- value_object_pattern/usables/primitives/__init__.py +45 -0
- value_object_pattern/usables/primitives/boolean/__init__.py +9 -0
- value_object_pattern/usables/primitives/boolean/boolean_value_object.py +36 -0
- value_object_pattern/usables/primitives/boolean/false_value_object.py +37 -0
- value_object_pattern/usables/primitives/boolean/true_value_object.py +37 -0
- value_object_pattern/usables/primitives/bytes/__init__.py +3 -0
- value_object_pattern/usables/primitives/bytes/bytes_value_object.py +36 -0
- value_object_pattern/usables/primitives/float/__init__.py +9 -0
- value_object_pattern/usables/primitives/float/float_value_object.py +36 -0
- value_object_pattern/usables/primitives/float/negative_float_value_object.py +37 -0
- value_object_pattern/usables/primitives/float/positive_float_value_object.py +37 -0
- value_object_pattern/usables/primitives/integer/__init__.py +13 -0
- value_object_pattern/usables/primitives/integer/even_integer_value_object.py +37 -0
- value_object_pattern/usables/primitives/integer/integer_value_object.py +36 -0
- value_object_pattern/usables/primitives/integer/negative_integer_value_object.py +37 -0
- value_object_pattern/usables/primitives/integer/odd_integer_value_object.py +37 -0
- value_object_pattern/usables/primitives/integer/positive_integer_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/__init__.py +21 -0
- value_object_pattern/usables/primitives/string/alpha_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/alphanumeric_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/digit_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/lowercase_string_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/non_empty_string_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/printable_string_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/string_value_object.py +36 -0
- value_object_pattern/usables/primitives/string/trimmed_string_value_object.py +37 -0
- value_object_pattern/usables/primitives/string/uppercase_string_value_object.py +37 -0
- value_object_pattern-0.1.0.dist-info/METADATA +95 -0
- value_object_pattern-0.1.0.dist-info/RECORD +73 -0
- value_object_pattern-0.1.0.dist-info/WHEEL +4 -0
- value_object_pattern-0.1.0.dist-info/licenses/LICENSE.md +21 -0
@@ -0,0 +1,39 @@
|
|
1
|
+
"""
|
2
|
+
HttpHttpsUrlValueObject value object.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from value_object_pattern import validation
|
6
|
+
|
7
|
+
from .url_value_object import UrlValueObject, split_url
|
8
|
+
|
9
|
+
|
10
|
+
class HttpHttpsUrlValueObject(UrlValueObject):
|
11
|
+
"""
|
12
|
+
HttpHttpsUrlValueObject value object ensures the provided value is a valid HTTP or HTTPS URL.
|
13
|
+
|
14
|
+
Example:
|
15
|
+
```python
|
16
|
+
from value_object_pattern.usables.internet import HttpHttpsUrlValueObject
|
17
|
+
|
18
|
+
url = HttpHttpsUrlValueObject(value='https://github.com/adriamontoto/value-object-pattern')
|
19
|
+
|
20
|
+
print(repr(url))
|
21
|
+
# >>> HttpHttpsUrlValueObject(value=https://github.com/adriamontoto/value-object-pattern)
|
22
|
+
```
|
23
|
+
"""
|
24
|
+
|
25
|
+
@validation(order=0)
|
26
|
+
def _validate_url_is_http_https(self, value: str) -> None:
|
27
|
+
"""
|
28
|
+
Validate url scheme is HTTP or HTTPS.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
value (str): The url value.
|
32
|
+
|
33
|
+
Raises:
|
34
|
+
ValueError: If the url scheme is not HTTP or HTTPS.
|
35
|
+
"""
|
36
|
+
scheme, *_ = split_url(value=value)
|
37
|
+
|
38
|
+
if scheme not in ('http', 'https'):
|
39
|
+
raise ValueError(f'HttpHttpsUrlValueObject value <<<{value}>>> scheme is not HTTP or HTTPS')
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""
|
2
|
+
HttpUrlValueObject value object.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from value_object_pattern import validation
|
6
|
+
|
7
|
+
from .url_value_object import UrlValueObject, split_url
|
8
|
+
|
9
|
+
|
10
|
+
class HttpUrlValueObject(UrlValueObject):
|
11
|
+
"""
|
12
|
+
HttpUrlValueObject value object ensures the provided value is a valid HTTP URL.
|
13
|
+
|
14
|
+
Example:
|
15
|
+
```python
|
16
|
+
from value_object_pattern.usables.internet import HttpUrlValueObject
|
17
|
+
|
18
|
+
url = HttpUrlValueObject(value='http://github.com/adriamontoto/value-object-pattern')
|
19
|
+
|
20
|
+
print(repr(url))
|
21
|
+
# >>> HttpUrlValueObject(value=http://github.com/adriamontoto/value-object-pattern)
|
22
|
+
```
|
23
|
+
"""
|
24
|
+
|
25
|
+
@validation(order=0)
|
26
|
+
def _validate_url_is_http(self, value: str) -> None:
|
27
|
+
"""
|
28
|
+
Validate url scheme is HTTP.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
value (str): The url value.
|
32
|
+
|
33
|
+
Raises:
|
34
|
+
ValueError: If the url scheme is not HTTP.
|
35
|
+
"""
|
36
|
+
scheme, *_ = split_url(value=value)
|
37
|
+
|
38
|
+
if scheme != 'http':
|
39
|
+
raise ValueError(f'HttpUrlValueObject value <<<{value}>>> scheme is not HTTP')
|
@@ -0,0 +1,39 @@
|
|
1
|
+
"""
|
2
|
+
HttpsUrlValueObject value object.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from value_object_pattern import validation
|
6
|
+
|
7
|
+
from .url_value_object import UrlValueObject, split_url
|
8
|
+
|
9
|
+
|
10
|
+
class HttpsUrlValueObject(UrlValueObject):
|
11
|
+
"""
|
12
|
+
HttpsUrlValueObject value object ensures the provided value is a valid HTTPS URL.
|
13
|
+
|
14
|
+
Example:
|
15
|
+
```python
|
16
|
+
from value_object_pattern.usables.internet import HttpsUrlValueObject
|
17
|
+
|
18
|
+
url = HttpsUrlValueObject(value='https://github.com/adriamontoto/value-object-pattern')
|
19
|
+
|
20
|
+
print(repr(url))
|
21
|
+
# >>> HttpsUrlValueObject(value=https://github.com/adriamontoto/value-object-pattern)
|
22
|
+
```
|
23
|
+
"""
|
24
|
+
|
25
|
+
@validation(order=0)
|
26
|
+
def _validate_url_is_https(self, value: str) -> None:
|
27
|
+
"""
|
28
|
+
Validate url scheme is HTTPS.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
value (str): The url value.
|
32
|
+
|
33
|
+
Raises:
|
34
|
+
ValueError: If the url scheme is not HTTPS.
|
35
|
+
"""
|
36
|
+
scheme, *_ = split_url(value=value)
|
37
|
+
|
38
|
+
if scheme != 'https':
|
39
|
+
raise ValueError(f'HttpsUrlValueObject value <<<{value}>>> scheme is not HTTPS')
|
@@ -0,0 +1,396 @@
|
|
1
|
+
"""
|
2
|
+
UrlValueObject value object.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from functools import lru_cache
|
6
|
+
from re import Pattern, compile as re_compile
|
7
|
+
from urllib.parse import parse_qs, urlsplit
|
8
|
+
|
9
|
+
from value_object_pattern import process, validation
|
10
|
+
from value_object_pattern.usables import NotEmptyStringValueObject, TrimmedStringValueObject
|
11
|
+
from value_object_pattern.usables.internet.host_value_object import HostValueObject
|
12
|
+
from value_object_pattern.usables.internet.port_value_object import PortValueObject
|
13
|
+
|
14
|
+
|
15
|
+
@lru_cache(maxsize=16)
|
16
|
+
def join_url(
|
17
|
+
scheme: str,
|
18
|
+
host: str,
|
19
|
+
port: int | None = None,
|
20
|
+
user_information: str | None = None,
|
21
|
+
path: str | None = None,
|
22
|
+
query: str | None = None,
|
23
|
+
fragment: str | None = None,
|
24
|
+
) -> str:
|
25
|
+
"""
|
26
|
+
Join the URL parts.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
scheme (str): The URL scheme.
|
30
|
+
host (str): The URL host.
|
31
|
+
port (int | None, optional): The URL port. Defaults to None.
|
32
|
+
user_information (str | None, optional): The URL user information. Defaults to None.
|
33
|
+
path (str | None, optional): The URL path. Defaults to None.
|
34
|
+
query (str | None, optional): The URL query. Defaults to None.
|
35
|
+
fragment (str | None, optional): The URL fragment. Defaults to None.
|
36
|
+
|
37
|
+
Returns:
|
38
|
+
str: The URL joined.
|
39
|
+
"""
|
40
|
+
netloc = host
|
41
|
+
if user_information:
|
42
|
+
netloc = f'{user_information}@{netloc}'
|
43
|
+
|
44
|
+
if port is not None:
|
45
|
+
netloc = f'{netloc}:{port}'
|
46
|
+
|
47
|
+
if path and not path.startswith('/'):
|
48
|
+
path = f'/{path}'
|
49
|
+
|
50
|
+
if query:
|
51
|
+
query = f'?{query}'
|
52
|
+
|
53
|
+
if fragment:
|
54
|
+
fragment = f'#{fragment}'
|
55
|
+
|
56
|
+
return f'{scheme}://{netloc}{path}{query}{fragment}'
|
57
|
+
|
58
|
+
|
59
|
+
@lru_cache(maxsize=16)
|
60
|
+
def split_url(value: str) -> tuple[str, str, str, str, str]:
|
61
|
+
"""
|
62
|
+
Split the URL in scheme, netloc, path, query and fragment.
|
63
|
+
|
64
|
+
Args:
|
65
|
+
value (str): The URL value.
|
66
|
+
|
67
|
+
Returns:
|
68
|
+
tuple[str, str, str, str, str]: The URL splitted in scheme, netloc, path, query and fragment.
|
69
|
+
"""
|
70
|
+
return urlsplit(url=value)
|
71
|
+
|
72
|
+
|
73
|
+
@lru_cache(maxsize=16)
|
74
|
+
def split_netloc(value: str) -> tuple[str | None, str, int | None]:
|
75
|
+
"""
|
76
|
+
Split the netloc in user_information, host and port.
|
77
|
+
|
78
|
+
Args:
|
79
|
+
value (str): The netloc value.
|
80
|
+
|
81
|
+
Returns:
|
82
|
+
tuple[str | None, str, int | None]: The netloc splitted in user_information, host and port.
|
83
|
+
"""
|
84
|
+
user_information, port = None, None
|
85
|
+
|
86
|
+
host_port = value
|
87
|
+
if '@' in value:
|
88
|
+
# prevent splitting passwords with @
|
89
|
+
user_information, host_port = value.rsplit(sep='@', maxsplit=1)
|
90
|
+
|
91
|
+
host = host_port
|
92
|
+
if ':' in host_port and host_port.count(':') == 1:
|
93
|
+
# prevent splitting IPv6 addresses
|
94
|
+
host, port_string = host_port.rsplit(sep=':', maxsplit=1)
|
95
|
+
port = int(port_string)
|
96
|
+
|
97
|
+
return user_information, host, port
|
98
|
+
|
99
|
+
|
100
|
+
class UrlValueObject(NotEmptyStringValueObject, TrimmedStringValueObject):
|
101
|
+
"""
|
102
|
+
UrlValueObject value object ensures the provided value is a valid URL.
|
103
|
+
|
104
|
+
References:
|
105
|
+
https://www.rfc-editor.org/rfc/rfc3986
|
106
|
+
|
107
|
+
Example:
|
108
|
+
```python
|
109
|
+
from value_object_pattern.usables.internet import UrlValueObject
|
110
|
+
|
111
|
+
url = UrlValueObject(value='https://github.com/adriamontoto/value-object-pattern?tab=readme-ov-file#table-of-contents')
|
112
|
+
|
113
|
+
print(repr(url))
|
114
|
+
# >>> UrlValueObject(value=https://github.com/adriamontoto/value-object-pattern?tab=readme-ov-file#table-of-contents)
|
115
|
+
```
|
116
|
+
"""
|
117
|
+
|
118
|
+
__URL_VALUE_OBJECT_SCHEME_REGEX: Pattern[str] = re_compile(pattern=r'^[a-zA-Z][a-zA-Z0-9\+\-\.]+$')
|
119
|
+
__URL_VALUE_OBJECT_USER_INFORMATION_REGEX: Pattern[str] = re_compile(pattern=r'^[a-zA-Z0-9\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=\:\@]+$') # noqa: E501 # fmt: skip
|
120
|
+
__URL_VALUE_OBJECT_PATH_REGEX: Pattern[str] = re_compile(pattern=r'^\/(?:[a-zA-Z0-9\/\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=\:\@]|%[a-fA-F0-9]{2})*$') # noqa: E501 # fmt: skip
|
121
|
+
__URL_VALUE_OBJECT_QUERY_REGEX: Pattern[str] = re_compile(pattern=r'^(?:[a-zA-Z0-9\/\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=\:\@]|%[a-fA-F0-9]{2})*$') # noqa: E501 # fmt: skip
|
122
|
+
__URL_VALUE_OBJECT_FRAGMENT_REGEX: Pattern[str] = re_compile(pattern=r'^(?:[a-zA-Z0-9\/\-\.\_\~\!\$\&\'\(\)\*\+\,\;\=\:\@]|%[a-fA-F0-9]{2})*$') # noqa: E501 # fmt: skip
|
123
|
+
|
124
|
+
@process(order=0)
|
125
|
+
def _ensure_url_is_lower(self, value: str) -> str:
|
126
|
+
"""
|
127
|
+
Ensure scheme and domain are in lower case.
|
128
|
+
|
129
|
+
Args:
|
130
|
+
value (str): The url value.
|
131
|
+
|
132
|
+
Returns:
|
133
|
+
str: The url value with scheme and domain in lower case.
|
134
|
+
"""
|
135
|
+
scheme, netloc, path, query, fragment = split_url(value=value)
|
136
|
+
user_information, host, port = split_netloc(value=netloc)
|
137
|
+
|
138
|
+
return join_url(
|
139
|
+
scheme=scheme.lower(),
|
140
|
+
user_information=user_information,
|
141
|
+
host=host.lower(),
|
142
|
+
port=port,
|
143
|
+
path=path,
|
144
|
+
query=query,
|
145
|
+
fragment=fragment,
|
146
|
+
)
|
147
|
+
|
148
|
+
@validation(order=0)
|
149
|
+
def _validate_url(self, value: str) -> None:
|
150
|
+
"""
|
151
|
+
Validate url.
|
152
|
+
|
153
|
+
Args:
|
154
|
+
value (str): The url value.
|
155
|
+
|
156
|
+
Raises:
|
157
|
+
ValueError: If value is not a valid url.
|
158
|
+
|
159
|
+
References:
|
160
|
+
https://www.rfc-editor.org/rfc/rfc3986
|
161
|
+
"""
|
162
|
+
try:
|
163
|
+
scheme, netloc, path, query, fragment = split_url(value=value)
|
164
|
+
|
165
|
+
except ValueError as error:
|
166
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> is not a valid url.') from error
|
167
|
+
|
168
|
+
if not scheme and not netloc and not path and not query and not fragment:
|
169
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> is not a valid url.')
|
170
|
+
|
171
|
+
@validation(order=1)
|
172
|
+
def _validate_url_scheme(self, value: str) -> None:
|
173
|
+
"""
|
174
|
+
Validate url scheme.
|
175
|
+
|
176
|
+
Args:
|
177
|
+
value (str): The url value.
|
178
|
+
|
179
|
+
Raises:
|
180
|
+
ValueError: If the url value has not a valid scheme.
|
181
|
+
|
182
|
+
References:
|
183
|
+
https://www.rfc-editor.org/rfc/rfc3986#section-3.1
|
184
|
+
"""
|
185
|
+
scheme, *_ = split_url(value=value)
|
186
|
+
if not self.__URL_VALUE_OBJECT_SCHEME_REGEX.match(string=scheme):
|
187
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> contains an invalid scheme <<<{scheme}>>>.')
|
188
|
+
|
189
|
+
@validation(order=2)
|
190
|
+
def _validate_url_netloc(self, value: str) -> None:
|
191
|
+
"""
|
192
|
+
Validate url netloc.
|
193
|
+
|
194
|
+
Args:
|
195
|
+
value (str): The url value.
|
196
|
+
|
197
|
+
Raises:
|
198
|
+
ValueError: If url value has not a valid netloc.
|
199
|
+
|
200
|
+
References:
|
201
|
+
https://www.rfc-editor.org/rfc/rfc3986#section-3.2.1
|
202
|
+
https://www.rfc-editor.org/rfc/rfc3986#section-3.2.2
|
203
|
+
https://www.rfc-editor.org/rfc/rfc3986#section-3.2.3
|
204
|
+
"""
|
205
|
+
_, netloc, *_ = split_url(value=value)
|
206
|
+
user_information, host, port = split_netloc(value=netloc)
|
207
|
+
|
208
|
+
if user_information is not None and not self.__URL_VALUE_OBJECT_USER_INFORMATION_REGEX.match(string=user_information): # noqa: E501 # fmt: skip
|
209
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> has not a valid user information <<<{user_information}>>>.') # noqa: E501 # fmt: skip
|
210
|
+
|
211
|
+
try:
|
212
|
+
HostValueObject(value=host)
|
213
|
+
|
214
|
+
except ValueError as error:
|
215
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> has not a valid host <<<{host}>>>.') from error
|
216
|
+
|
217
|
+
try:
|
218
|
+
if port is not None:
|
219
|
+
PortValueObject(value=port)
|
220
|
+
|
221
|
+
except ValueError as error:
|
222
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> has not a valid port <<<{port}>>>.') from error
|
223
|
+
|
224
|
+
@validation(order=3)
|
225
|
+
def _validate_url_path(self, value: str) -> None:
|
226
|
+
"""
|
227
|
+
Validate url path.
|
228
|
+
|
229
|
+
Args:
|
230
|
+
value (str): The url value.
|
231
|
+
|
232
|
+
Raises:
|
233
|
+
ValueError: If url value has not a valid path.
|
234
|
+
|
235
|
+
References:
|
236
|
+
https://www.rfc-editor.org/rfc/rfc3986#section-3.3
|
237
|
+
"""
|
238
|
+
_, _, path, *_ = split_url(value=value)
|
239
|
+
if not path:
|
240
|
+
return
|
241
|
+
|
242
|
+
if not self.__URL_VALUE_OBJECT_PATH_REGEX.match(string=path):
|
243
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> has not a valid path <<<{path}>>>.')
|
244
|
+
|
245
|
+
@validation(order=4)
|
246
|
+
def _validate_url_query(self, value: str) -> None:
|
247
|
+
"""
|
248
|
+
Validate url query.
|
249
|
+
|
250
|
+
Args:
|
251
|
+
value (str): The url value.
|
252
|
+
|
253
|
+
Raises:
|
254
|
+
ValueError: If url value has not a valid query.
|
255
|
+
|
256
|
+
References:
|
257
|
+
https://www.rfc-editor.org/rfc/rfc3986#section-3.4
|
258
|
+
"""
|
259
|
+
_, _, _, query, *_ = split_url(value=value)
|
260
|
+
if not query:
|
261
|
+
return
|
262
|
+
|
263
|
+
try:
|
264
|
+
parse_qs(qs=query)
|
265
|
+
|
266
|
+
except ValueError as error:
|
267
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> has not a valid query <<<{query}>>>.') from error
|
268
|
+
|
269
|
+
if not self.__URL_VALUE_OBJECT_QUERY_REGEX.match(string=query):
|
270
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> has not a valid query <<<{query}>>>.')
|
271
|
+
|
272
|
+
@validation(order=5)
|
273
|
+
def _validate_url_fragment(self, value: str) -> None:
|
274
|
+
"""
|
275
|
+
Validate url fragment.
|
276
|
+
|
277
|
+
Args:
|
278
|
+
value (str): The url value.
|
279
|
+
|
280
|
+
Raises:
|
281
|
+
ValueError: If url value has not a valid fragment.
|
282
|
+
|
283
|
+
References:
|
284
|
+
https://www.rfc-editor.org/rfc/rfc3986#section-3.5
|
285
|
+
"""
|
286
|
+
_, _, _, _, fragment = split_url(value=value)
|
287
|
+
if not fragment:
|
288
|
+
return
|
289
|
+
|
290
|
+
if not self.__URL_VALUE_OBJECT_FRAGMENT_REGEX.match(string=fragment):
|
291
|
+
raise ValueError(f'UrlValueObject value <<<{value}>>> has not a valid fragment <<<{fragment}>>>.')
|
292
|
+
|
293
|
+
@property
|
294
|
+
def scheme(self) -> str:
|
295
|
+
"""
|
296
|
+
Get the URL scheme.
|
297
|
+
|
298
|
+
Returns:
|
299
|
+
str: The URL scheme.
|
300
|
+
|
301
|
+
Example:
|
302
|
+
```python
|
303
|
+
from value_object_pattern.usables.internet import UrlValueObject
|
304
|
+
|
305
|
+
url = UrlValueObject(value='https://github.com/adriamontoto/value-object-pattern?tab=readme-ov-file#table-of-contents')
|
306
|
+
|
307
|
+
print(url.scheme)
|
308
|
+
# >>> https
|
309
|
+
```
|
310
|
+
"""
|
311
|
+
scheme, *_ = split_url(value=self.value)
|
312
|
+
return scheme
|
313
|
+
|
314
|
+
@property
|
315
|
+
def netloc(self) -> str:
|
316
|
+
"""
|
317
|
+
Get the URL netloc.
|
318
|
+
|
319
|
+
Returns:
|
320
|
+
str: The URL netloc.
|
321
|
+
|
322
|
+
Example:
|
323
|
+
```python
|
324
|
+
from value_object_pattern.usables.internet import UrlValueObject
|
325
|
+
|
326
|
+
url = UrlValueObject(value='https://github.com/adriamontoto/value-object-pattern?tab=readme-ov-file#table-of-contents')
|
327
|
+
|
328
|
+
print(url.netloc)
|
329
|
+
# >>> github.com
|
330
|
+
```
|
331
|
+
"""
|
332
|
+
_, netloc, *_ = split_url(value=self.value)
|
333
|
+
return netloc
|
334
|
+
|
335
|
+
@property
|
336
|
+
def path(self) -> str | None:
|
337
|
+
"""
|
338
|
+
Get the URL path.
|
339
|
+
|
340
|
+
Returns:
|
341
|
+
str | None: The URL path if exists, otherwise None.
|
342
|
+
|
343
|
+
Example:
|
344
|
+
```python
|
345
|
+
from value_object_pattern.usables.internet import UrlValueObject
|
346
|
+
|
347
|
+
url = UrlValueObject(value='https://github.com/adriamontoto/value-object-pattern?tab=readme-ov-file#table-of-contents')
|
348
|
+
|
349
|
+
print(url.path)
|
350
|
+
# >>> /adriamontoto/value-object-pattern
|
351
|
+
```
|
352
|
+
"""
|
353
|
+
_, _, path, *_ = split_url(value=self.value)
|
354
|
+
return path if path else None
|
355
|
+
|
356
|
+
@property
|
357
|
+
def query(self) -> str | None:
|
358
|
+
"""
|
359
|
+
Get the URL query.
|
360
|
+
|
361
|
+
Returns:
|
362
|
+
str | None: The URL query if exists, otherwise None.
|
363
|
+
|
364
|
+
Example:
|
365
|
+
```python
|
366
|
+
from value_object_pattern.usables.internet import UrlValueObject
|
367
|
+
|
368
|
+
url = UrlValueObject(value='https://github.com/adriamontoto/value-object-pattern?tab=readme-ov-file#table-of-contents')
|
369
|
+
|
370
|
+
print(url.query)
|
371
|
+
# >>> tab=readme-ov-file
|
372
|
+
```
|
373
|
+
"""
|
374
|
+
_, _, _, query, *_ = split_url(value=self.value)
|
375
|
+
return query if query else None
|
376
|
+
|
377
|
+
@property
|
378
|
+
def fragment(self) -> str | None:
|
379
|
+
"""
|
380
|
+
Get the URL fragment.
|
381
|
+
|
382
|
+
Returns:
|
383
|
+
str | None: The URL fragment if exists, otherwise None.
|
384
|
+
|
385
|
+
Example:
|
386
|
+
```python
|
387
|
+
from value_object_pattern.usables.internet import UrlValueObject
|
388
|
+
|
389
|
+
url = UrlValueObject(value='https://github.com/adriamontoto/value-object-pattern?tab=readme-ov-file#table-of-contents')
|
390
|
+
|
391
|
+
print(url.fragment)
|
392
|
+
# >>> table-of-contents
|
393
|
+
```
|
394
|
+
"""
|
395
|
+
_, _, _, _, fragment = split_url(value=self.value)
|
396
|
+
return fragment if fragment else None
|
@@ -0,0 +1,45 @@
|
|
1
|
+
from .boolean import BooleanValueObject, FalseValueObject, TrueValueObject
|
2
|
+
from .bytes import BytesValueObject
|
3
|
+
from .float import FloatValueObject, NegativeFloatValueObject, PositiveFloatValueObject
|
4
|
+
from .integer import (
|
5
|
+
EvenIntegerValueObject,
|
6
|
+
IntegerValueObject,
|
7
|
+
NegativeIntegerValueObject,
|
8
|
+
OddIntegerValueObject,
|
9
|
+
PositiveIntegerValueObject,
|
10
|
+
)
|
11
|
+
from .string import (
|
12
|
+
AlphaStringValueObject,
|
13
|
+
AlphanumericStringValueObject,
|
14
|
+
DigitStringValueObject,
|
15
|
+
LowercaseStringValueObject,
|
16
|
+
NotEmptyStringValueObject,
|
17
|
+
PrintableStringValueObject,
|
18
|
+
StringValueObject,
|
19
|
+
TrimmedStringValueObject,
|
20
|
+
UppercaseStringValueObject,
|
21
|
+
)
|
22
|
+
|
23
|
+
__all__ = (
|
24
|
+
'AlphaStringValueObject',
|
25
|
+
'AlphanumericStringValueObject',
|
26
|
+
'BooleanValueObject',
|
27
|
+
'BytesValueObject',
|
28
|
+
'DigitStringValueObject',
|
29
|
+
'EvenIntegerValueObject',
|
30
|
+
'FalseValueObject',
|
31
|
+
'FloatValueObject',
|
32
|
+
'IntegerValueObject',
|
33
|
+
'LowercaseStringValueObject',
|
34
|
+
'NegativeFloatValueObject',
|
35
|
+
'NegativeIntegerValueObject',
|
36
|
+
'NotEmptyStringValueObject',
|
37
|
+
'OddIntegerValueObject',
|
38
|
+
'PositiveFloatValueObject',
|
39
|
+
'PositiveIntegerValueObject',
|
40
|
+
'PrintableStringValueObject',
|
41
|
+
'StringValueObject',
|
42
|
+
'TrimmedStringValueObject',
|
43
|
+
'TrueValueObject',
|
44
|
+
'UppercaseStringValueObject',
|
45
|
+
)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
"""
|
2
|
+
BooleanValueObject value object.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from value_object_pattern.decorators import validation
|
6
|
+
from value_object_pattern.models import ValueObject
|
7
|
+
|
8
|
+
|
9
|
+
class BooleanValueObject(ValueObject[bool]):
|
10
|
+
"""
|
11
|
+
BooleanValueObject value object ensures the provided value is a boolean.
|
12
|
+
|
13
|
+
Example:
|
14
|
+
```python
|
15
|
+
from value_object_pattern.usables import BooleanValueObject
|
16
|
+
|
17
|
+
boolean = BooleanValueObject(value=True)
|
18
|
+
|
19
|
+
print(repr(boolean))
|
20
|
+
# >>> BooleanValueObject(value=True)
|
21
|
+
```
|
22
|
+
"""
|
23
|
+
|
24
|
+
@validation(order=0)
|
25
|
+
def _ensure_value_is_boolean(self, value: bool) -> None:
|
26
|
+
"""
|
27
|
+
Ensures the value object `value` is a boolean.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
value (bool): The provided value.
|
31
|
+
|
32
|
+
Raises:
|
33
|
+
TypeError: If the `value` is not a boolean.
|
34
|
+
"""
|
35
|
+
if type(value) is not bool:
|
36
|
+
raise TypeError(f'BooleanValueObject value <<<{value}>>> must be a boolean. Got <<<{type(value).__name__}>>> type.') # noqa: E501 # fmt: skip
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"""
|
2
|
+
FalseValueObject value object.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from value_object_pattern.decorators import validation
|
6
|
+
|
7
|
+
from .boolean_value_object import BooleanValueObject
|
8
|
+
|
9
|
+
|
10
|
+
class FalseValueObject(BooleanValueObject):
|
11
|
+
"""
|
12
|
+
FalseValueObject value object ensures the provided value is false.
|
13
|
+
|
14
|
+
Example:
|
15
|
+
```python
|
16
|
+
from value_object_pattern.usables import BooleanValueObject
|
17
|
+
|
18
|
+
boolean = BooleanValueObject(value=False)
|
19
|
+
|
20
|
+
print(repr(boolean))
|
21
|
+
# >>> BooleanValueObject(value=False)
|
22
|
+
```
|
23
|
+
"""
|
24
|
+
|
25
|
+
@validation(order=0)
|
26
|
+
def _ensure_value_is_false(self, value: bool) -> None:
|
27
|
+
"""
|
28
|
+
Ensures the value object `value` is false.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
value (bool): The provided value.
|
32
|
+
|
33
|
+
Raises:
|
34
|
+
ValueError: If the `value` is not false.
|
35
|
+
"""
|
36
|
+
if value:
|
37
|
+
raise ValueError(f'FalseValueObject value <<<{value}>>> must be false.')
|
@@ -0,0 +1,37 @@
|
|
1
|
+
"""
|
2
|
+
TrueValueObject value object.
|
3
|
+
"""
|
4
|
+
|
5
|
+
from value_object_pattern.decorators import validation
|
6
|
+
|
7
|
+
from .boolean_value_object import BooleanValueObject
|
8
|
+
|
9
|
+
|
10
|
+
class TrueValueObject(BooleanValueObject):
|
11
|
+
"""
|
12
|
+
TrueValueObject value object ensures the provided value is true.
|
13
|
+
|
14
|
+
Example:
|
15
|
+
```python
|
16
|
+
from value_object_pattern.usables import BooleanValueObject
|
17
|
+
|
18
|
+
boolean = BooleanValueObject(value=True)
|
19
|
+
|
20
|
+
print(repr(boolean))
|
21
|
+
# >>> BooleanValueObject(value=True)
|
22
|
+
```
|
23
|
+
"""
|
24
|
+
|
25
|
+
@validation(order=0)
|
26
|
+
def _ensure_value_is_true(self, value: bool) -> None:
|
27
|
+
"""
|
28
|
+
Ensures the value object `value` is true.
|
29
|
+
|
30
|
+
Args:
|
31
|
+
value (bool): The provided value.
|
32
|
+
|
33
|
+
Raises:
|
34
|
+
ValueError: If the `value` is not true.
|
35
|
+
"""
|
36
|
+
if not value:
|
37
|
+
raise ValueError(f'TrueValueObject value <<<{value}>>> must be true.')
|