edri 2025.11.1rc3__py3-none-any.whl → 2025.11.1rc4__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.
edri/api/broker.py CHANGED
@@ -21,8 +21,8 @@ from edri.dataclass.response import ResponseStatus, Response
21
21
  from edri.events.api import group, manage, client
22
22
  from edri.events.edri.router import HealthCheck, Subscribe
23
23
  from edri.utility import Storage
24
- from edri.utility.validation import StringValidation, IntegerValidation, FloatValidation, DateValidation, \
25
- TimeValidation, DateTimeValidation
24
+ from edri.utility.validation import StringValidator, IntegerValidator, FloatValidator, DateValidator, \
25
+ TimeValidator, DateTimeValidator
26
26
 
27
27
 
28
28
  class TrieNode:
@@ -391,12 +391,12 @@ class Broker(ManagerBase):
391
391
 
392
392
  def extract_parameters_response(event_cls: Type[Event]) -> tuple[dict[str, Any], dict[str, Any]]:
393
393
  VALIDATION_MAP: dict[type, tuple[str, type]] = {
394
- StringValidation: ("string", StringValidation.__bases__[0]),
395
- IntegerValidation: ("integer", IntegerValidation.__bases__[0]),
396
- FloatValidation: ("float", FloatValidation.__bases__[0]),
397
- DateValidation: ("date", DateValidation.__bases__[0]),
398
- TimeValidation: ("time", TimeValidation.__bases__[0]),
399
- DateTimeValidation: ("datetime", DateTimeValidation.__bases__[0]),
394
+ StringValidator: ("string", StringValidator.__bases__[0]),
395
+ IntegerValidator: ("integer", IntegerValidator.__bases__[0]),
396
+ FloatValidator: ("float", FloatValidator.__bases__[0]),
397
+ DateValidator: ("date", DateValidator.__bases__[0]),
398
+ TimeValidator: ("time", TimeValidator.__bases__[0]),
399
+ DateTimeValidator: ("datetime", DateTimeValidator.__bases__[0]),
400
400
  }
401
401
 
402
402
  def resolve_validation(field_type: Injection) -> tuple[str | None, dict[str, Any]]:
@@ -16,7 +16,7 @@ from edri.config.constant import ApiType
16
16
  from edri.dataclass.event import EventHandlingType, _event, Event
17
17
  from edri.dataclass.injection import Injection
18
18
  from edri.utility.function import camel2snake
19
- from edri.utility.validation import ListValidation
19
+ from edri.utility.validation import ListValidator
20
20
 
21
21
 
22
22
  @dataclass
@@ -113,7 +113,7 @@ def api(cls=None, /, *, init=True, repr=True, eq=True, order=False,
113
113
  raise TypeError(f"{field.type} cannot be used as a type for API event")
114
114
  elif isinstance(field.type, Injection):
115
115
  for validator in field.type.classes:
116
- if validator == ListValidation:
116
+ if validator == ListValidator:
117
117
  raise TypeError(
118
118
  "ListValidation must be used as ListValidation[T], "
119
119
  "e.g. ListValidation[Any] or ListValidation[inject(...)]."
@@ -72,7 +72,6 @@ class BaseHandler[T: ResponseDirective](ABC):
72
72
  def create_event(self, event_constructor: Type[Event]) -> Event:
73
73
  self.insert_default_parameters(event_constructor)
74
74
  self.check_parameters(event_constructor)
75
- # noinspection PyArgumentList
76
75
  event = event_constructor(**self.parameters)
77
76
  event._timing.stamp(self.__class__.__name__, "Created")
78
77
  return event
@@ -29,14 +29,16 @@ from edri.config.setting import MAX_BODY_SIZE, ASSETS_PATH, UPLOAD_FILES_PREFIX,
29
29
  CORS_MAX_AGE, UPLOAD_FILES_PATH
30
30
  from edri.dataclass.directive import HTTPResponseDirective, ResponseDirective
31
31
  from edri.dataclass.directive.base import InternalServerErrorResponseDirective, UnauthorizedResponseDirective
32
- from edri.dataclass.directive.http import CookieResponseDirective, AccessDeniedResponseDirective, NotFoundResponseDirective, \
33
- ConflictResponseDirective, HeaderResponseDirective, UnprocessableContentResponseDirective, BadRequestResponseDirective
32
+ from edri.dataclass.directive.http import CookieResponseDirective, AccessDeniedResponseDirective, \
33
+ NotFoundResponseDirective, \
34
+ ConflictResponseDirective, HeaderResponseDirective, UnprocessableContentResponseDirective, \
35
+ BadRequestResponseDirective, NotModifiedResponseDirective
34
36
  from edri.dataclass.event import Event
35
37
  from edri.dataclass.injection import Injection
36
38
  from edri.utility import NormalizedDefaultDict
37
39
  from edri.utility.function import camel2snake
38
40
  from edri.utility.shared_memory_pipe import SharedMemoryPipe
39
- from edri.utility.validation import StringValidation
41
+ from edri.utility.validation import StringValidator
40
42
 
41
43
 
42
44
  class EventTypesExtensionsDict(TypedDict):
@@ -194,7 +196,7 @@ class URLNode:
194
196
  raise TypeError("All classes in 'inject' must have the same base class when used as URL parameters.")
195
197
  break # Only check the first valid base class regex
196
198
 
197
- if vot is StringValidation:
199
+ if vot is StringValidator:
198
200
  regex = type_.parameters.get("regex", None)
199
201
  if regex is not None:
200
202
  regex_function = lambda name, _: rf"^(?P<{escape(name)}>{sub(r'^\^(.*)\$$', r'\1', regex.pattern)})$"
@@ -271,6 +273,9 @@ class HTTPHandler[T: HTTPResponseDirective](BaseHandler, ABC):
271
273
  },
272
274
  BadRequestResponseDirective: {
273
275
  "status": HTTPStatus.BAD_REQUEST,
276
+ },
277
+ NotModifiedResponseDirective: {
278
+ "status": HTTPStatus.NOT_MODIFIED,
274
279
  }
275
280
  }
276
281
 
@@ -716,6 +721,23 @@ class HTTPHandler[T: HTTPResponseDirective](BaseHandler, ABC):
716
721
  })
717
722
  except Exception as e:
718
723
  self.logger.error(e, exc_info=e)
724
+
725
+ async def response_headers(self, status: HTTPStatus, *args, **kwargs: Unpack[ResponseKW]):
726
+ headers = kwargs["headers"]
727
+ if headers is None:
728
+ headers = NormalizedDefaultDict(list)
729
+ await self.send({
730
+ 'type': 'http.response.start',
731
+ 'status': status,
732
+ 'headers': self.get_headers_binary(headers),
733
+ })
734
+
735
+ await self.send({
736
+ 'type': 'http.response.body',
737
+ 'body': b"",
738
+ 'more_body': False
739
+ })
740
+
719
741
  def get_event_constructors(self) -> tuple[dict[HTTPMethod, Type[Event]], dict[str, Any]]:
720
742
  return self.url_root.find_methods(self.scope["path"].lower())
721
743
 
edri/api/listener.py CHANGED
@@ -270,6 +270,8 @@ class Listener(Process):
270
270
  await handler.response_file(event_response, headers=headers)
271
271
  else:
272
272
  await handler.response(status, event_response, headers=headers)
273
+ elif status.is_redirection:
274
+ await handler.response_headers(status, headers=headers)
273
275
  else:
274
276
  await handler.response_error(status, event_response, headers=headers)
275
277
  self.unregister(pipe, event._api)
@@ -65,3 +65,7 @@ class UnprocessableContentResponseDirective(HTTPResponseDirective):
65
65
  @dataclass
66
66
  class BadRequestResponseDirective(HTTPResponseDirective):
67
67
  message: str | None = None
68
+
69
+ @dataclass
70
+ class NotModifiedResponseDirective(HTTPResponseDirective):
71
+ pass
@@ -3,7 +3,7 @@ from re import Pattern
3
3
  from typing import Self, Iterable, Any
4
4
 
5
5
 
6
- class StringValidation(str):
6
+ class StringValidator(str):
7
7
  """
8
8
  A string type that performs validation on initialization.
9
9
 
@@ -21,7 +21,7 @@ class StringValidation(str):
21
21
  or its length is outside the allowed bounds.
22
22
 
23
23
  Example:
24
- >>> StringValidation("hello", minimum_length=3, maximum_length=10)
24
+ >>> StringValidator("hello", minimum_length=3, maximum_length=10)
25
25
  'hello'
26
26
  """
27
27
 
@@ -49,7 +49,7 @@ class StringValidation(str):
49
49
  return (v[:max_len] + "…") if len(v) > max_len else v
50
50
 
51
51
 
52
- class IntegerValidation(int):
52
+ class IntegerValidator(int):
53
53
  """
54
54
  An integer type that performs validation on initialization.
55
55
 
@@ -65,7 +65,7 @@ class IntegerValidation(int):
65
65
  ValueError: If the value is less than `minimum` or greater than `maximum`.
66
66
 
67
67
  Example:
68
- >>> IntegerValidation(5, minimum=1, maximum=10)
68
+ >>> IntegerValidator(5, minimum=1, maximum=10)
69
69
  5
70
70
  """
71
71
 
@@ -78,7 +78,7 @@ class IntegerValidation(int):
78
78
  return value
79
79
 
80
80
 
81
- class FloatValidation(float):
81
+ class FloatValidator(float):
82
82
  """
83
83
  A float type that performs validation on initialization.
84
84
 
@@ -94,7 +94,7 @@ class FloatValidation(float):
94
94
  ValueError: If the value is less than `minimum` or greater than `maximum`.
95
95
 
96
96
  Example:
97
- >>> FloatValidation(3.14, minimum=1.0, maximum=5.0)
97
+ >>> FloatValidator(3.14, minimum=1.0, maximum=5.0)
98
98
  3.14
99
99
  """
100
100
 
@@ -107,7 +107,7 @@ class FloatValidation(float):
107
107
  return value
108
108
 
109
109
 
110
- class DateValidation(date):
110
+ class DateValidator(date):
111
111
  """
112
112
  A date type that performs validation on initialization.
113
113
 
@@ -126,7 +126,7 @@ class DateValidation(date):
126
126
  ValueError: If the date is outside the allowed bounds.
127
127
 
128
128
  Example:
129
- >>> DateValidation(2024, 3, 28, minimum_date=date(2024, 1, 1))
129
+ >>> DateValidator(2024, 3, 28, minimum_date=date(2024, 1, 1))
130
130
  datetime.date(2024, 3, 28)
131
131
  """
132
132
 
@@ -144,7 +144,7 @@ class DateValidation(date):
144
144
  return value
145
145
 
146
146
 
147
- class TimeValidation(time):
147
+ class TimeValidator(time):
148
148
  """
149
149
  A time type that performs validation on initialization.
150
150
 
@@ -164,7 +164,7 @@ class TimeValidation(time):
164
164
  ValueError: If the time is outside the allowed bounds.
165
165
 
166
166
  Example:
167
- >>> TimeValidation(12, 30, maximum_time=time(20, 0))
167
+ >>> TimeValidator(12, 30, maximum_time=time(20, 0))
168
168
  datetime.time(12, 30)
169
169
  """
170
170
 
@@ -182,7 +182,7 @@ class TimeValidation(time):
182
182
  return value
183
183
 
184
184
 
185
- class DateTimeValidation(datetime):
185
+ class DateTimeValidator(datetime):
186
186
  """
187
187
  A datetime type that performs validation on initialization.
188
188
 
@@ -205,7 +205,7 @@ class DateTimeValidation(datetime):
205
205
  ValueError: If the datetime is outside the allowed bounds.
206
206
 
207
207
  Example:
208
- >>> DateTimeValidation(2024, 3, 28, 15, 45,
208
+ >>> DateTimeValidator(2024, 3, 28, 15, 45,
209
209
  ... minimum_datetime=datetime(2024, 3, 1))
210
210
  datetime.datetime(2024, 3, 28, 15, 45)
211
211
  """
@@ -224,7 +224,7 @@ class DateTimeValidation(datetime):
224
224
  return instance
225
225
 
226
226
 
227
- class ListValidation(list):
227
+ class ListValidator(list):
228
228
  """
229
229
  A list type that performs validation on initialization.
230
230
 
@@ -241,9 +241,9 @@ class ListValidation(list):
241
241
  ValueError: If the list length is outside the allowed bounds.
242
242
 
243
243
  Example:
244
- >>> ListValidation([1, 2, 3], minimum_length=2)
244
+ >>> ListValidator([1, 2, 3], minimum_length=2)
245
245
  [1, 2, 3]
246
- >>> ListValidation([1, 2, 3], maximum_length=2)
246
+ >>> ListValidator([1, 2, 3], maximum_length=2)
247
247
  ValueError: List length '3' is greater than maximum allowed '2'
248
248
  """
249
249
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: edri
3
- Version: 2025.11.1rc3
3
+ Version: 2025.11.1rc4
4
4
  Summary: Event Driven Routing Infrastructure
5
5
  Author: Marek Olšan
6
6
  Author-email: marek.olsan@gmail.com
@@ -9,20 +9,20 @@ edri/abstract/worker/worker.py,sha256=JSTItljxBiCm_ljXctzTiKwb90Yk8Cy6EzZJTchtv9
9
9
  edri/abstract/worker/worker_process.py,sha256=QiNxOuwkMds0sV2MBLyp7bjrovm5xColC7I7TNcSO4s,1957
10
10
  edri/abstract/worker/worker_thread.py,sha256=xoMPuDn-hAkWk6kFY3Xf8mxOVP__5t7-x7f-b396-8M,2176
11
11
  edri/api/__init__.py,sha256=ZDxCpHKFGajJ1RwDpV7CzxLDUaKpozJRfOCv1OPv5ZY,142
12
- edri/api/broker.py,sha256=6O-B2Io7WF9KPXJCXsCzcyxpwjieIx5vqR06cSEi1oI,37276
13
- edri/api/listener.py,sha256=QaBlrlWH8j5OsD0mFMeTd95eP2nq7J-B6FCPL9OtFac,20289
12
+ edri/api/broker.py,sha256=I3z_bKbcTDnKXk82yteGEQmuxpqHgp5KrhQaJmk3US0,37258
13
+ edri/api/listener.py,sha256=B2RgqQmCkcJOYWtTlYkyb2H7xCM233iNfsa5LG4qZZ0,20401
14
14
  edri/api/middleware.py,sha256=6_x55swthVDczT-fu_1ufY1cDsHTZ04jMx6J6xfjbsM,5483
15
15
  edri/api/dataclass/__init__.py,sha256=8Y-zcaJtzMdALnNG7M9jsCaB1qAJKM8Ld3h9MDajYjA,292
16
- edri/api/dataclass/api_event.py,sha256=vAP5JOqlrg3XBZtKd_a721dPSKa2N1NlMtebD_kpP2Q,6589
16
+ edri/api/dataclass/api_event.py,sha256=08edshexI9FxdebPIgTQMSQ4fEtGpAa3K_VYCmN1jFs,6587
17
17
  edri/api/dataclass/client.py,sha256=ctc2G4mXJR2wUSujANudT3LqxW7qxk_YkpM_TEXD0tM,216
18
18
  edri/api/dataclass/file.py,sha256=OJfJlrCTjSnzCF8yFVnxr8rGeL0l08WVMsXJx00S4qc,225
19
19
  edri/api/extensions/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  edri/api/extensions/url_extension.py,sha256=rZKumjR7J6pDTiSLIZf8IzxGgDZP7p2g0Kgs0USug_U,1971
21
21
  edri/api/extensions/url_prefix.py,sha256=kNI6g5ZlW0w-J_IMacYLco1EQvmTtMJyEkN6-SK1wC0,491
22
22
  edri/api/handlers/__init__.py,sha256=MI6OGDf1rM8jf_uCKK_JYeOGMts62CNy10BwwNlG0Tk,200
23
- edri/api/handlers/base_handler.py,sha256=wENi5nfXaz2heyypzN8ikbN0ucPGxyRMcnxCpD9_o9Q,13151
23
+ edri/api/handlers/base_handler.py,sha256=aZN95tWX7hkmJ3D401c-JPfF2azjH0t1jJy_zsjPc_4,13113
24
24
  edri/api/handlers/html_handler.py,sha256=OprcTg1IQDI7eBK-_oHqA60P1H30LA9xIQpD7iV-Neg,7464
25
- edri/api/handlers/http_handler.py,sha256=Il16LpIMjSreUXohn4c2R79Bx9mKqz7a08LfTVvPwws,35567
25
+ edri/api/handlers/http_handler.py,sha256=oTyVxbA0xgOLAyt2n4E5dRXrnfdVRpS8-GrXAe5SSeY,36219
26
26
  edri/api/handlers/rest_handler.py,sha256=GAG5lVTsRMCf9IUmYb_pokxyPcOfbnKZ2p3jxfy_-Dw,3300
27
27
  edri/api/handlers/websocket_handler.py,sha256=Dh2XannDuW0eFj5CEzf3owlGc1VTyQ8ehjpxYRrCYW8,8144
28
28
  edri/api/static_pages/documentation.j2,sha256=Fe7KLsbqp9P-pQYqG2z8rbhhGVDDFf3m6SQ2mc3PFG4,8934
@@ -41,7 +41,7 @@ edri/dataclass/response.py,sha256=VBMmVdna1IOKC5YGBXor6AayYOoiEYb9xx_RZ3bpKnw,38
41
41
  edri/dataclass/directive/__init__.py,sha256=nfvsh1BmxhACW7Q8gnwy7y3l3_cI1P0k2WP0jV5RJhI,608
42
42
  edri/dataclass/directive/base.py,sha256=2ghQpv1bGcNHYEMA0nyWGumIplXBzj9cPQ34aJ7uVr0,296
43
43
  edri/dataclass/directive/html.py,sha256=UCuwksxt_Q9b1wha1DjEygJWAyq2Hdnir5zG9lGi8as,946
44
- edri/dataclass/directive/http.py,sha256=k4ZDHZSwr4TerA6s0xeV58qpyjk2mdInTlWymBVluGI,2536
44
+ edri/dataclass/directive/http.py,sha256=6Y4LYlERcddg4UXVCFG3ry6PUwMpS1fAGL-WEM_1A3c,2616
45
45
  edri/events/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
46
46
  edri/events/api/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
47
47
  edri/events/api/client/__init__.py,sha256=6q7CJ4eLMAuz_EFIs7us-xDXudy0Z5DIHd0YCVtTeuo,170
@@ -112,7 +112,7 @@ edri/utility/queue.py,sha256=xBbeu1DT3Krdxni0YABk7gDZ5fLQL9eX-H3U-1jSqag,3628
112
112
  edri/utility/shared_memory_pipe.py,sha256=kmtd-1999s-cUVThxXVtw4N-rp_WgrHtl-h4hhEliXA,6396
113
113
  edri/utility/storage.py,sha256=AbZwtj8py0OBy3dM5C0fJ97uV88TERZO79heEmyE9Yk,3781
114
114
  edri/utility/transformation.py,sha256=4FeRNav-ifxuqgwq9ys3G5WtMzUAC3_2B3tnFhMENho,1450
115
- edri/utility/validation.py,sha256=V4EYvuDRsuVgfQTUSF-109O7tDtnNA78tsT231oeST4,9624
115
+ edri/utility/validation.py,sha256=wDQb55CBB-I-KaevucmSWlevYAGxMJ8Pok0Ya3S8cLk,9609
116
116
  edri/utility/watcher.py,sha256=9nwU-h6B_QCd02-z-2-Hvf6huro8B9yVcZAepoFtXQ4,4623
117
117
  edri/utility/manager/__init__.py,sha256=bNyqET60wyq-QFmNwk52UKRweK5lYTDH_TF2UgS6enk,73
118
118
  edri/utility/manager/scheduler.py,sha256=3wRPph-FGNrVMN3TG7SvZ_PDW8mNK7UdM3PnjI_QTH8,11624
@@ -152,11 +152,11 @@ tests/utility/test_normalized_default_dict.py,sha256=Utd4EhN6uW6m3eBxz1hhUwRCOWq
152
152
  tests/utility/test_shared_memory_pipe.py,sha256=JVzr-h8rjjlB6Uk_OnUBAlRwD2X4e74VKHBKCOE8KFM,7308
153
153
  tests/utility/test_storage.py,sha256=DD7H-xk3kTuz3x2zuJuJyHDV4eJMYy5iEsHoPAAfjuQ,1349
154
154
  tests/utility/test_transformation.py,sha256=4IJFuP3tp3Bd4vH3ohwxLb8yy4m1teK-e7UJbxJzevc,2840
155
- tests/utility/test_validation.py,sha256=OEM9hGzlFoSvZdwf5_pyH-Xg9ISxw0QJFbgMaDP8jtQ,9154
155
+ tests/utility/test_validation.py,sha256=wZcXjLrj3JheVLKnYKkkYfyC8CCpHVAw9Jn_uDnuEfk,9103
156
156
  tests/utility/manager/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
157
157
  tests/utility/manager/test_scheduler.py,sha256=sROffYvSOaWsYQxQGTy6l9Mn_qeNPRmJoXLVPKU3XNY,9153
158
158
  tests/utility/manager/test_store.py,sha256=xlo1JUsPLIhPJyQn7AXldAgWDo_O8ba2ns25TEaaGdQ,2821
159
- edri-2025.11.1rc3.dist-info/METADATA,sha256=d0LFmSlm3cYRVlw79-cj59_Pa33mweHzTS7Ox063e4Y,8346
160
- edri-2025.11.1rc3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
161
- edri-2025.11.1rc3.dist-info/top_level.txt,sha256=himES6JgPlx4Zt8aDrQEj2fxAd7IDD6MBOsiNZkzKHQ,11
162
- edri-2025.11.1rc3.dist-info/RECORD,,
159
+ edri-2025.11.1rc4.dist-info/METADATA,sha256=4aYgoa2SpOfeR-2j9x26EOZBQ9Ca62T-E6u1Es76234,8346
160
+ edri-2025.11.1rc4.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
161
+ edri-2025.11.1rc4.dist-info/top_level.txt,sha256=himES6JgPlx4Zt8aDrQEj2fxAd7IDD6MBOsiNZkzKHQ,11
162
+ edri-2025.11.1rc4.dist-info/RECORD,,
@@ -2,44 +2,44 @@ import unittest
2
2
  from datetime import date, time, datetime
3
3
  from re import compile
4
4
 
5
- from edri.utility.validation import StringValidation, IntegerValidation, FloatValidation, DateValidation, TimeValidation, DateTimeValidation
5
+ from edri.utility.validation import StringValidator, IntegerValidator, FloatValidator, DateValidator, TimeValidator, DateTimeValidator
6
6
 
7
7
 
8
8
  class TestStringValidation(unittest.TestCase):
9
9
  def test_valid_string(self):
10
- value = StringValidation('hello', minimum_length=3, maximum_length=10)
10
+ value = StringValidator('hello', minimum_length=3, maximum_length=10)
11
11
  self.assertEqual(value, 'hello')
12
12
 
13
13
  def test_too_short_string(self):
14
14
  with self.assertRaises(ValueError) as cm:
15
- StringValidation('hi', minimum_length=3)
15
+ StringValidator('hi', minimum_length=3)
16
16
  self.assertIn("too short", str(cm.exception))
17
17
 
18
18
  def test_too_long_string(self):
19
19
  with self.assertRaises(ValueError) as cm:
20
- StringValidation('this is a long string', maximum_length=10)
20
+ StringValidator('this is a long string', maximum_length=10)
21
21
  self.assertIn("too long", str(cm.exception))
22
22
 
23
23
  def test_regex_match(self):
24
24
  pattern = compile(r'^[a-z]+$')
25
- value = StringValidation('hello', regex=pattern)
25
+ value = StringValidator('hello', regex=pattern)
26
26
  self.assertEqual(value, 'hello')
27
27
 
28
28
  def test_regex_no_match(self):
29
29
  pattern = compile(r'^[a-z]+$')
30
30
  with self.assertRaises(ValueError) as cm:
31
- StringValidation('Hello123', regex=pattern)
31
+ StringValidator('Hello123', regex=pattern)
32
32
  self.assertIn("not match", str(cm.exception))
33
33
 
34
34
  def test_all_constraints_pass(self):
35
35
  pattern = compile(r'^[a-z]+$')
36
- value = StringValidation('hello', minimum_length=3, maximum_length=10, regex=pattern)
36
+ value = StringValidator('hello', minimum_length=3, maximum_length=10, regex=pattern)
37
37
  self.assertEqual(value, 'hello')
38
38
 
39
39
  def test_all_constraints_fail(self):
40
40
  pattern = compile(r'^[a-z]+$')
41
41
  with self.assertRaises(ValueError) as cm:
42
- StringValidation('Hi', minimum_length=3, maximum_length=4, regex=pattern)
42
+ StringValidator('Hi', minimum_length=3, maximum_length=4, regex=pattern)
43
43
  self.assertTrue(
44
44
  any(msg in str(cm.exception) for msg in ["not match", "too short", "too long"])
45
45
  )
@@ -48,142 +48,142 @@ class TestStringValidation(unittest.TestCase):
48
48
  class TestIntegerValidation(unittest.TestCase):
49
49
  def test_valid_integer_no_constraints(self):
50
50
  # No constraints applied should return the number as-is.
51
- value = IntegerValidation(10)
51
+ value = IntegerValidator(10)
52
52
  self.assertEqual(value, 10)
53
53
 
54
54
  def test_valid_integer_with_constraints(self):
55
55
  # Valid integer within the specified range.
56
- value = IntegerValidation(5, minimum=1, maximum=10)
56
+ value = IntegerValidator(5, minimum=1, maximum=10)
57
57
  self.assertEqual(value, 5)
58
58
 
59
59
  def test_integer_below_minimum(self):
60
60
  # Should raise a ValueError because 0 is below the minimum of 1.
61
61
  with self.assertRaises(ValueError) as cm:
62
- IntegerValidation(0, minimum=1)
62
+ IntegerValidator(0, minimum=1)
63
63
  self.assertIn("too small", str(cm.exception))
64
64
 
65
65
  def test_integer_above_maximum(self):
66
66
  # Should raise a ValueError because 11 is above the maximum of 10.
67
67
  with self.assertRaises(ValueError) as cm:
68
- IntegerValidation(11, maximum=10)
68
+ IntegerValidator(11, maximum=10)
69
69
  self.assertIn("too big", str(cm.exception))
70
70
 
71
71
 
72
72
  class TestFloatValidation(unittest.TestCase):
73
73
  def test_valid_float_no_constraints(self):
74
74
  # No constraints applied should return the float as-is.
75
- value = FloatValidation(3.14)
75
+ value = FloatValidator(3.14)
76
76
  self.assertEqual(value, 3.14)
77
77
 
78
78
  def test_valid_float_with_constraints(self):
79
79
  # Valid float within the specified range.
80
- value = FloatValidation(3.14, minimum=1.0, maximum=5.0)
80
+ value = FloatValidator(3.14, minimum=1.0, maximum=5.0)
81
81
  self.assertEqual(value, 3.14)
82
82
 
83
83
  def test_float_below_minimum(self):
84
84
  # Should raise a ValueError because 0.5 is below the minimum of 1.0.
85
85
  with self.assertRaises(ValueError) as cm:
86
- FloatValidation(0.5, minimum=1.0)
86
+ FloatValidator(0.5, minimum=1.0)
87
87
  self.assertIn("too small", str(cm.exception))
88
88
 
89
89
  def test_float_above_maximum(self):
90
90
  # Should raise a ValueError because 6.0 is above the maximum of 5.0.
91
91
  with self.assertRaises(ValueError) as cm:
92
- FloatValidation(6.0, maximum=5.0)
92
+ FloatValidator(6.0, maximum=5.0)
93
93
  self.assertIn("too big", str(cm.exception))
94
94
 
95
95
 
96
96
  class TestDateValidation(unittest.TestCase):
97
97
 
98
98
  def test_valid_date_no_constraints(self):
99
- d = DateValidation(2024, 3, 28)
99
+ d = DateValidator(2024, 3, 28)
100
100
  self.assertEqual(d, date(2024, 3, 28))
101
101
 
102
102
  def test_valid_date_within_constraints(self):
103
- d = DateValidation(2024, 3, 28,
104
- minimum_date=date(2024, 1, 1),
105
- maximum_date=date(2024, 12, 31))
103
+ d = DateValidator(2024, 3, 28,
104
+ minimum_date=date(2024, 1, 1),
105
+ maximum_date=date(2024, 12, 31))
106
106
  self.assertEqual(d, date(2024, 3, 28))
107
107
 
108
108
  def test_date_equal_to_minimum(self):
109
- d = DateValidation(2024, 1, 1, minimum_date=date(2024, 1, 1))
109
+ d = DateValidator(2024, 1, 1, minimum_date=date(2024, 1, 1))
110
110
  self.assertEqual(d, date(2024, 1, 1))
111
111
 
112
112
  def test_date_equal_to_maximum(self):
113
- d = DateValidation(2024, 12, 31, maximum_date=date(2024, 12, 31))
113
+ d = DateValidator(2024, 12, 31, maximum_date=date(2024, 12, 31))
114
114
  self.assertEqual(d, date(2024, 12, 31))
115
115
 
116
116
  def test_date_below_minimum_raises(self):
117
117
  with self.assertRaises(ValueError) as context:
118
- DateValidation(2023, 12, 31, minimum_date=date(2024, 1, 1))
118
+ DateValidator(2023, 12, 31, minimum_date=date(2024, 1, 1))
119
119
  self.assertIn("earlier than minimum allowed", str(context.exception))
120
120
 
121
121
  def test_date_above_maximum_raises(self):
122
122
  with self.assertRaises(ValueError) as context:
123
- DateValidation(2025, 1, 1, maximum_date=date(2024, 12, 31))
123
+ DateValidator(2025, 1, 1, maximum_date=date(2024, 12, 31))
124
124
  self.assertIn("later than maximum allowed", str(context.exception))
125
125
 
126
126
  def test_invalid_date_raises(self):
127
127
  with self.assertRaises(ValueError):
128
- DateValidation(2024, 2, 30) # Invalid day in February
128
+ DateValidator(2024, 2, 30) # Invalid day in February
129
129
 
130
130
 
131
131
  class TestTimeValidation(unittest.TestCase):
132
132
 
133
133
  def test_valid_time_no_constraints(self):
134
- t = TimeValidation(12, 30)
134
+ t = TimeValidator(12, 30)
135
135
  self.assertEqual(t, time(12, 30))
136
136
 
137
137
  def test_valid_time_within_constraints(self):
138
- t = TimeValidation(14, 45,
139
- minimum_time=time(12, 0),
140
- maximum_time=time(20, 0))
138
+ t = TimeValidator(14, 45,
139
+ minimum_time=time(12, 0),
140
+ maximum_time=time(20, 0))
141
141
  self.assertEqual(t, time(14, 45))
142
142
 
143
143
  def test_time_equal_to_minimum(self):
144
- t = TimeValidation(8, 0, minimum_time=time(8, 0))
144
+ t = TimeValidator(8, 0, minimum_time=time(8, 0))
145
145
  self.assertEqual(t, time(8, 0))
146
146
 
147
147
  def test_time_equal_to_maximum(self):
148
- t = TimeValidation(22, 0, maximum_time=time(22, 0))
148
+ t = TimeValidator(22, 0, maximum_time=time(22, 0))
149
149
  self.assertEqual(t, time(22, 0))
150
150
 
151
151
  def test_time_below_minimum_raises(self):
152
152
  with self.assertRaises(ValueError) as context:
153
- TimeValidation(6, 59, minimum_time=time(7, 0))
153
+ TimeValidator(6, 59, minimum_time=time(7, 0))
154
154
  self.assertIn("earlier than minimum allowed", str(context.exception))
155
155
 
156
156
  def test_time_above_maximum_raises(self):
157
157
  with self.assertRaises(ValueError) as context:
158
- TimeValidation(23, 1, maximum_time=time(23, 0))
158
+ TimeValidator(23, 1, maximum_time=time(23, 0))
159
159
  self.assertIn("later than maximum allowed", str(context.exception))
160
160
 
161
161
  def test_time_with_seconds_and_microseconds(self):
162
- t = TimeValidation(10, 15, 30, 500000)
162
+ t = TimeValidator(10, 15, 30, 500000)
163
163
  self.assertEqual(t, time(10, 15, 30, 500000))
164
164
 
165
165
  def test_time_with_timezone(self):
166
166
  tz = time(0, 0).tzinfo # no tzinfo set, just testing the arg
167
- t = TimeValidation(10, 0, 0, 0, tz)
167
+ t = TimeValidator(10, 0, 0, 0, tz)
168
168
  self.assertEqual(t, time(10, 0))
169
169
 
170
170
  def test_invalid_hour_raises(self):
171
171
  with self.assertRaises(ValueError):
172
- TimeValidation(25, 0) # hour out of range
172
+ TimeValidator(25, 0) # hour out of range
173
173
 
174
174
  def test_invalid_minute_raises(self):
175
175
  with self.assertRaises(ValueError):
176
- TimeValidation(12, 60) # minute out of range
176
+ TimeValidator(12, 60) # minute out of range
177
177
 
178
178
 
179
179
  class TestDateTimeValidation(unittest.TestCase):
180
180
 
181
181
  def test_valid_datetime_no_constraints(self):
182
- dt = DateTimeValidation(2024, 3, 28, 15, 30)
182
+ dt = DateTimeValidator(2024, 3, 28, 15, 30)
183
183
  self.assertEqual(dt, datetime(2024, 3, 28, 15, 30))
184
184
 
185
185
  def test_valid_datetime_within_constraints(self):
186
- dt = DateTimeValidation(
186
+ dt = DateTimeValidator(
187
187
  2024, 3, 28, 12, 0,
188
188
  minimum_datetime=datetime(2024, 3, 1, 0, 0),
189
189
  maximum_datetime=datetime(2024, 12, 31, 23, 59)
@@ -191,14 +191,14 @@ class TestDateTimeValidation(unittest.TestCase):
191
191
  self.assertEqual(dt, datetime(2024, 3, 28, 12, 0))
192
192
 
193
193
  def test_datetime_equal_to_minimum(self):
194
- dt = DateTimeValidation(
194
+ dt = DateTimeValidator(
195
195
  2024, 3, 1, 0, 0,
196
196
  minimum_datetime=datetime(2024, 3, 1, 0, 0)
197
197
  )
198
198
  self.assertEqual(dt, datetime(2024, 3, 1, 0, 0))
199
199
 
200
200
  def test_datetime_equal_to_maximum(self):
201
- dt = DateTimeValidation(
201
+ dt = DateTimeValidator(
202
202
  2024, 12, 31, 23, 59,
203
203
  maximum_datetime=datetime(2024, 12, 31, 23, 59)
204
204
  )
@@ -206,7 +206,7 @@ class TestDateTimeValidation(unittest.TestCase):
206
206
 
207
207
  def test_datetime_below_minimum_raises(self):
208
208
  with self.assertRaises(ValueError) as context:
209
- DateTimeValidation(
209
+ DateTimeValidator(
210
210
  2024, 2, 29, 23, 59,
211
211
  minimum_datetime=datetime(2024, 3, 1)
212
212
  )
@@ -214,21 +214,21 @@ class TestDateTimeValidation(unittest.TestCase):
214
214
 
215
215
  def test_datetime_above_maximum_raises(self):
216
216
  with self.assertRaises(ValueError) as context:
217
- DateTimeValidation(
217
+ DateTimeValidator(
218
218
  2025, 1, 1, 0, 0,
219
219
  maximum_datetime=datetime(2024, 12, 31, 23, 59)
220
220
  )
221
221
  self.assertIn("later than maximum allowed", str(context.exception))
222
222
 
223
223
  def test_datetime_with_seconds_and_microseconds(self):
224
- dt = DateTimeValidation(2024, 3, 28, 12, 45, 30, 999999)
224
+ dt = DateTimeValidator(2024, 3, 28, 12, 45, 30, 999999)
225
225
  self.assertEqual(dt, datetime(2024, 3, 28, 12, 45, 30, 999999))
226
226
 
227
227
  def test_invalid_datetime_raises(self):
228
228
  with self.assertRaises(ValueError):
229
- DateTimeValidation(2024, 2, 30, 12, 0) # Invalid date
229
+ DateTimeValidator(2024, 2, 30, 12, 0) # Invalid date
230
230
 
231
231
  def test_timezone_argument_is_applied(self):
232
232
  tz = datetime.now().astimezone().tzinfo
233
- dt = DateTimeValidation(2024, 3, 28, 10, 0, 0, 0, tz)
233
+ dt = DateTimeValidator(2024, 3, 28, 10, 0, 0, 0, tz)
234
234
  self.assertEqual(dt.tzinfo, tz)