• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

patrickboateng / func-validator / 19189337758

08 Nov 2025 06:33AM UTC coverage: 97.993% (-1.5%) from 99.492%
19189337758

push

github

patrickboateng
bumped version to 1.3.0

43 of 43 branches covered (100.0%)

Branch coverage included in aggregate %.

1 of 1 new or added line in 1 file covered. (100.0%)

15 existing lines in 2 files now uncovered.

787 of 804 relevant lines covered (97.89%)

1.96 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

91.67
/func_validator/validators/collection_arg_validators.py
1
from operator import contains
2✔
2
from typing import Callable, Container, Iterable, Optional, Sized
2✔
3

4
from ._core import ErrorMsg, Number, T, ValidationError, Validator
2✔
5
from .numeric_arg_validators import (
2✔
6
    MustBeBetween,
7
    MustBeEqual,
8
    MustBeGreaterThan,
9
    MustBeGreaterThanOrEqual,
10
    MustBeLessThan,
11
    MustBeLessThanOrEqual,
12
    MustNotBeEqual,
13
)
14

15

16
def _iterable_len_validator(
2✔
17
    arg_values: Sized,
18
    arg_name: str,
19
    /,
20
    *,
21
    func: Callable,
22
):
23
    func(len(arg_values), arg_name)
2✔
24

25

26
def _iterable_values_validator(
2✔
27
    values: Iterable,
28
    arg_name: str,
29
    /,
30
    *,
31
    func: Callable,
32
):
33
    for value in values:
2✔
34
        func(value, arg_name)
2✔
35

36

37
# Membership and range validation functions
38

39

40
def _must_be_member_of(
2✔
41
    arg_value,
42
    arg_name: str,
43
    /,
44
    *,
45
    value_set: Container,
46
    err_msg: ErrorMsg,
47
):
48
    if not contains(value_set, arg_value):
2✔
49
        err_msg = err_msg.transform(
2✔
50
            arg_value=arg_value,
51
            arg_name=arg_name,
52
            value_set=repr(value_set),
53
        )
54
        raise ValidationError(err_msg)
2✔
55

56

57
class MustBeMemberOf(Validator):
2✔
58

59
    def __init__(
2✔
60
        self,
61
        value_set: Container,
62
        *,
63
        err_msg: str = "${arg_name}:${arg_value} must be in ${value_set}",
64
    ):
65
        """Validates that the value is a member of the specified set.
66

67
        :param value_set: The set of values to validate against.
68
                          `value_set` must support the `in` operator.
69
        :param err_msg: Error message.
70
        """
71
        super().__init__(err_msg=err_msg)
2✔
72
        self.value_set = value_set
2✔
73

74
    def __call__(self, arg_value: T, arg_name: str):
2✔
75
        _must_be_member_of(
2✔
76
            arg_value,
77
            arg_name,
78
            value_set=self.value_set,
79
            err_msg=self.err_msg,
80
        )
81

82

83
# Size validation functions
84

85

86
class MustBeEmpty(Validator):
2✔
87

88
    def __init__(self, *, err_msg: Optional[str] = None):
2✔
89
        """
90
        :param err_msg: Error message.
91
        """
92
        super().__init__(err_msg=err_msg)
2✔
93

94
    def __call__(self, arg_value: Sized, arg_name: str, /):
2✔
95
        """Validates that the iterable is empty."""
96
        if self.err_msg is None:
2✔
97
            fn = MustBeEqual(0)
2✔
98
        else:
UNCOV
99
            fn = MustBeEqual(0, err_msg=self.err_msg)
×
100
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
101

102

103
class MustBeNonEmpty(Validator):
2✔
104

105
    def __init__(self, *, err_msg: Optional[str] = None):
2✔
106
        """
107
        :param err_msg: Error message.
108
        """
109
        super().__init__(err_msg=err_msg)
2✔
110

111
    def __call__(self, arg_value: Sized, arg_name: str, /):
2✔
112
        """Validates that the iterable is not empty."""
113
        if self.err_msg is None:
2✔
114
            fn = MustNotBeEqual(0)
2✔
115
        else:
UNCOV
116
            fn = MustNotBeEqual(0, err_msg=self.err_msg)
×
117
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
118

119

120
class MustHaveLengthEqual(Validator):
2✔
121
    """Validates that the iterable has length equal to the specified
122
    value.
123
    """
124

125
    def __init__(self, value: int, *, err_msg: Optional[str] = None):
2✔
126
        """
127
        :param value: The length of the iterable.
128
        :param err_msg: Error message.
129
        """
130
        super().__init__(err_msg=err_msg)
2✔
131
        self.value = value
2✔
132

133
    def __call__(self, arg_value: Sized, arg_name: str):
2✔
134
        if self.err_msg is None:
2✔
135
            fn = MustBeEqual(self.value)
2✔
136
        else:
UNCOV
137
            fn = MustBeEqual(self.value, err_msg=self.err_msg)
×
138
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
139

140

141
class MustHaveLengthGreaterThan(Validator):
2✔
142
    """Validates that the iterable has length greater than the specified
143
    value.
144
    """
145

146
    def __init__(self, value: int, *, err_msg: Optional[str] = None):
2✔
147
        """
148
        :param value: The length of the iterable.
149
        :param err_msg: Error message.
150
        """
151
        super().__init__(err_msg=err_msg)
2✔
152
        self.value = value
2✔
153

154
    def __call__(self, arg_value: Sized, arg_name: str):
2✔
155
        if self.err_msg is None:
2✔
156
            fn = MustBeGreaterThan(self.value)
2✔
157
        else:
UNCOV
158
            fn = MustBeGreaterThan(self.value, err_msg=self.err_msg)
×
159
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
160

161

162
class MustHaveLengthGreaterThanOrEqual(Validator):
2✔
163
    """Validates that the iterable has length greater than or equal to
164
    the specified value.
165
    """
166

167
    def __init__(self, value: int, *, err_msg: Optional[str] = None):
2✔
168
        """
169
        :param value: The length of the iterable.
170
        :param err_msg: Error message
171
        """
172
        super().__init__(err_msg=err_msg)
2✔
173
        self.value = value
2✔
174

175
    def __call__(self, arg_value: Sized, arg_name: str):
2✔
176
        if self.err_msg is None:
2✔
177
            fn = MustBeGreaterThanOrEqual(self.value)
2✔
178
        else:
UNCOV
179
            fn = MustBeGreaterThanOrEqual(self.value, err_msg=self.err_msg)
×
180
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
181

182

183
class MustHaveLengthLessThan(Validator):
2✔
184
    """Validates that the iterable has length less than the specified
185
    value.
186
    """
187

188
    def __init__(self, value: int, *, err_msg: Optional[str] = None):
2✔
189
        """
190
        :param value: The length of the iterable.
191
        :param err_msg: Error message.
192
        """
193
        super().__init__(err_msg=err_msg)
2✔
194
        self.value = value
2✔
195

196
    def __call__(self, arg_value: Sized, arg_name: str):
2✔
197
        if self.err_msg is None:
2✔
198
            fn = MustBeLessThan(self.value)
2✔
199
        else:
UNCOV
200
            fn = MustBeLessThan(self.value, err_msg=self.err_msg)
×
201
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
202

203

204
class MustHaveLengthLessThanOrEqual(Validator):
2✔
205
    """Validates that the iterable has length less than or equal to
206
    the specified value.
207
    """
208

209
    def __init__(self, value: int, *, err_msg: Optional[str] = None):
2✔
210
        """
211
        :param value: The length of the iterable.
212
        :param err_msg: Error message.
213
        """
214
        super().__init__(err_msg=err_msg)
2✔
215
        self.value = value
2✔
216

217
    def __call__(self, arg_value: Sized, arg_name: str):
2✔
218
        if self.err_msg is None:
2✔
219
            fn = MustBeLessThanOrEqual(self.value)
2✔
220
        else:
UNCOV
221
            fn = MustBeLessThanOrEqual(self.value, err_msg=self.err_msg)
×
222
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
223

224

225
class MustHaveLengthBetween(Validator):
2✔
226
    """Validates that the iterable has length between the specified
227
    min_value and max_value.
228
    """
229

230
    def __init__(
2✔
231
        self,
232
        *,
233
        min_value: int,
234
        max_value: int,
235
        min_inclusive: bool = True,
236
        max_inclusive: bool = True,
237
        err_msg: Optional[str] = None,
238
    ):
239
        """
240
        :param min_value: The minimum value (inclusive or exclusive based
241
                          on min_inclusive).
242
        :param max_value: The maximum value (inclusive or exclusive based
243
                          on max_inclusive).
244
        :param min_inclusive: If True, min_value is inclusive.
245
        :param max_inclusive: If True, max_value is inclusive.
246
        :param err_msg: error message.
247
        """
248
        super().__init__(err_msg=err_msg)
2✔
249
        self.min_value = min_value
2✔
250
        self.max_value = max_value
2✔
251
        self.min_inclusive = min_inclusive
2✔
252
        self.max_inclusive = max_inclusive
2✔
253
        self.err_msg = err_msg
2✔
254

255
    def __call__(self, arg_value: Sized, arg_name: str):
2✔
256
        if self.err_msg is None:
2✔
257
            fn = MustBeBetween(
2✔
258
                min_value=self.min_value,
259
                max_value=self.max_value,
260
                min_inclusive=self.min_inclusive,
261
                max_inclusive=self.max_inclusive,
262
            )
263
        else:
UNCOV
264
            fn = MustBeBetween(
×
265
                min_value=self.min_value,
266
                max_value=self.max_value,
267
                min_inclusive=self.min_inclusive,
268
                max_inclusive=self.max_inclusive,
269
                err_msg=self.err_msg,
270
            )
271
        _iterable_len_validator(arg_value, arg_name, func=fn)
2✔
272

273

274
class MustHaveValuesGreaterThan(Validator):
2✔
275
    """Validates that all values in the iterable are greater than the
276
    specified min_value.
277
    """
278

279
    def __init__(self, min_value: Number, *, err_msg: Optional[str] = None):
2✔
280
        """
281
        :param min_value: The minimum value the values in the iterable
282
                          should be greater than.
283
        :param err_msg: Error message.
284
        """
285
        super().__init__(err_msg=err_msg)
2✔
286
        self.min_value = min_value
2✔
287

288
    def __call__(self, values: Iterable, arg_name: str):
2✔
289
        if self.err_msg is None:
2✔
290
            fn = MustBeGreaterThan(self.min_value)
2✔
291
        else:
UNCOV
292
            fn = MustBeGreaterThan(self.min_value, err_msg=self.err_msg)
×
293
        _iterable_values_validator(values, arg_name, func=fn)
2✔
294

295

296
class MustHaveValuesGreaterThanOrEqual(Validator):
2✔
297
    """Validates that all values in the iterable are greater than or
298
    equal to the specified min_value.
299
    """
300

301
    def __init__(self, min_value: Number, *, err_msg: Optional[str] = None):
2✔
302
        """
303
        :param min_value: The minimum value the values in the iterable
304
                          should be greater than or equal to.
305
        :param err_msg: Error message.
306
        """
307
        super().__init__(err_msg=err_msg)
2✔
308
        self.min_value = min_value
2✔
309

310
    def __call__(self, values: Iterable, arg_name: str):
2✔
311
        if self.err_msg is None:
2✔
312
            fn = MustBeGreaterThanOrEqual(self.min_value)
2✔
313
        else:
UNCOV
314
            fn = MustBeGreaterThanOrEqual(self.min_value, err_msg=self.err_msg)
×
315
        _iterable_values_validator(values, arg_name, func=fn)
2✔
316

317

318
class MustHaveValuesLessThan(Validator):
2✔
319
    """Validates that all values in the iterable are less than the
320
    specified max_value.
321
    """
322

323
    def __init__(self, max_value: Number, *, err_msg: Optional[str] = None):
2✔
324
        """
325
        :param max_value: The maximum value the values in the iterable
326
                          should be less than.
327
        :param err_msg: Error message.
328
        """
329
        super().__init__(err_msg=err_msg)
2✔
330
        self.max_value = max_value
2✔
331

332
    def __call__(self, values: Iterable, arg_name: str):
2✔
333
        if self.err_msg is None:
2✔
334
            fn = MustBeLessThan(self.max_value)
2✔
335
        else:
UNCOV
336
            fn = MustBeLessThan(self.max_value, err_msg=self.err_msg)
×
337
        _iterable_values_validator(values, arg_name, func=fn)
2✔
338

339

340
class MustHaveValuesLessThanOrEqual(Validator):
2✔
341
    """Validates that all values in the iterable are less than or
342
    equal to the specified max_value.
343
    """
344

345
    def __init__(self, max_value: Number, *, err_msg: Optional[str] = None):
2✔
346
        """
347
        :param max_value: The maximum value the values in the iterable
348
                          should be less than or equal to.
349
        :param err_msg: Error message.
350
        """
351
        super().__init__(err_msg=err_msg)
2✔
352
        self.max_value = max_value
2✔
353

354
    def __call__(self, values: Iterable, arg_name: str):
2✔
355
        if self.err_msg is None:
2✔
356
            fn = MustBeLessThanOrEqual(self.max_value)
2✔
357
        else:
UNCOV
358
            fn = MustBeLessThanOrEqual(self.max_value, err_msg=self.err_msg)
×
359
        _iterable_values_validator(values, arg_name, func=fn)
2✔
360

361

362
class MustHaveValuesBetween(Validator):
2✔
363
    """Validates that all values in the iterable are between the
364
    specified min_value and max_value.
365
    """
366

367
    def __init__(
2✔
368
        self,
369
        *,
370
        min_value: Number,
371
        max_value: Number,
372
        min_inclusive: bool = True,
373
        max_inclusive: bool = True,
374
        err_msg: Optional[str] = None,
375
    ):
376
        """
377
        :param min_value: The minimum value (inclusive or exclusive based
378
                          on min_inclusive).
379
        :param max_value: The maximum value (inclusive or exclusive based
380
                          on max_inclusive).
381
        :param min_inclusive: If True, min_value is inclusive.
382
        :param max_inclusive: If True, max_value is inclusive.
383
        :param err_msg: error message.
384
        """
385
        super().__init__(err_msg=err_msg)
2✔
386
        self.min_value = min_value
2✔
387
        self.max_value = max_value
2✔
388
        self.min_inclusive = min_inclusive
2✔
389
        self.max_inclusive = max_inclusive
2✔
390

391
    def __call__(self, values: Iterable, arg_name: str):
2✔
392
        if self.err_msg is None:
2✔
393
            fn = MustBeBetween(
2✔
394
                min_value=self.min_value,
395
                max_value=self.max_value,
396
                min_inclusive=self.min_inclusive,
397
                max_inclusive=self.max_inclusive,
398
            )
399
        else:
UNCOV
400
            fn = MustBeBetween(
×
401
                min_value=self.min_value,
402
                max_value=self.max_value,
403
                min_inclusive=self.min_inclusive,
404
                max_inclusive=self.max_inclusive,
405
                err_msg=self.err_msg,
406
            )
407
        _iterable_values_validator(values, arg_name, func=fn)
2✔
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc