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

LeanderCS / flask-inputfilter / #386

24 May 2025 12:48PM UTC coverage: 93.386% (-0.3%) from 93.644%
#386

push

coveralls-python

LeanderCS
48 | Updated IsDataclassValidator to also check against their types, including nested dataclasses, lists, and dictionaries

47 of 56 new or added lines in 4 files covered. (83.93%)

87 existing lines in 18 files now uncovered.

1878 of 2011 relevant lines covered (93.39%)

0.93 hits per line

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

76.38
/flask_inputfilter/input_filter.py
1
from __future__ import annotations
1✔
2

3
import json
1✔
4
import logging
1✔
5
from collections.abc import Callable
1✔
6
from typing import Any, Dict, List, Optional, Type, TypeVar, Union
1✔
7

8
from flask import Response, g, request
1✔
9

10
from flask_inputfilter.conditions import BaseCondition
1✔
11
from flask_inputfilter.exceptions import ValidationError
1✔
12
from flask_inputfilter.filters import BaseFilter
1✔
13
from flask_inputfilter.mixins import ExternalApiMixin, FieldMixin
1✔
14
from flask_inputfilter.models import ExternalApiConfig, FieldModel
1✔
15
from flask_inputfilter.validators import BaseValidator
1✔
16

17
T = TypeVar("T")
1✔
18

19

20
class InputFilter:
1✔
21
    """Base class for all input filters."""
22

23
    def __init__(self, methods: Optional[List[str]] = None) -> None:
1✔
24
        self.methods: List[str] = methods or [
1✔
25
            "GET",
26
            "POST",
27
            "PATCH",
28
            "PUT",
29
            "DELETE",
30
        ]
31
        self.fields: Dict[str, FieldModel] = {}
1✔
32
        self.conditions: List[BaseCondition] = []
1✔
33
        self.global_filters: List[BaseFilter] = []
1✔
34
        self.global_validators: List[BaseValidator] = []
1✔
35
        self.data: Dict[str, Any] = {}
1✔
36
        self.validated_data: Dict[str, Any] = {}
1✔
37
        self.errors: Dict[str, str] = {}
1✔
38
        self.model_class: Optional[Type[T]] = None
1✔
39

40
    def isValid(self) -> bool:
1✔
41
        """
42
        Checks if the object's state or its attributes meet certain
43
        conditions to be considered valid. This function is typically
44
        used to ensure that the current state complies with specific
45
        requirements or rules.
46

47
        Returns:
48
            bool: Returns True if the state or attributes of the object fulfill
49
                all required conditions; otherwise, returns False.
50
        """
UNCOV
51
        import warnings
×
52

UNCOV
53
        warnings.warn(
×
54
            "isValid() is deprecated, use is_valid() instead",
55
            DeprecationWarning,
56
            stacklevel=2,
57
        )
UNCOV
58
        return self.is_valid()
×
59

60
    def is_valid(self) -> bool:
1✔
61
        """
62
        Checks if the object's state or its attributes meet certain
63
        conditions to be considered valid. This function is typically
64
        used to ensure that the current state complies with specific
65
        requirements or rules.
66

67
        Returns:
68
            bool: Returns True if the state or attributes of the object fulfill
69
                all required conditions; otherwise, returns False.
70
        """
71
        try:
1✔
72
            self.validate_data()
1✔
73

74
        except ValidationError as e:
1✔
75
            self.errors = e.args[0]
1✔
76
            return False
1✔
77

78
        return True
1✔
79

80
    @classmethod
1✔
81
    def validate(
82
        cls,
83
    ) -> Callable[
84
        [Any],
85
        Callable[
86
            [tuple[Any, ...], Dict[str, Any]],
87
            Union[Response, tuple[Any, Dict[str, Any]]],
88
        ],
89
    ]:
90
        """
91
        Decorator for validating input data in routes.
92

93
        Args:
94
            cls
95

96
        Returns:
97
            Callable[
98
                [Any],
99
                Callable[
100
                    [tuple[Any, ...], Dict[str, Any]],
101
                    Union[Response, tuple[Any, Dict[str, Any]]],
102
                ],
103
            ]
104
        """
105

106
        def decorator(
1✔
107
            f: Callable,
108
        ) -> Callable[[Any, Any], Union[Response, tuple[Any, Dict[str, Any]]]]:
109
            """
110
            Decorator function to validate input data for a Flask
111
            route.
112

113
            Args:
114
                f (Callable): The Flask route function to be decorated.
115

116
            Returns:
117
                Callable[
118
                    [Any, Any],
119
                    Union[
120
                        Response,
121
                        tuple[Any, Dict[str, Any]]
122
                    ]
123
                ]: The wrapped function with input validation.
124
            """
125

126
            def wrapper(
1✔
127
                *args, **kwargs
128
            ) -> Union[Response, tuple[Any, Dict[str, Any]]]:
129
                """
130
                Wrapper function to handle input validation and error
131
                handling for the decorated route function.
132

133
                Args:
134
                    *args: Positional arguments for the route function.
135
                    **kwargs: Keyword arguments for the route function.
136

137
                Returns:
138
                    Union[Response, tuple[Any, Dict[str, Any]]]: The response
139
                        from the route function or an error response.
140
                """
141
                input_filter = cls()
1✔
142
                if request.method not in input_filter.methods:
1✔
143
                    return Response(status=405, response="Method Not Allowed")
1✔
144

145
                data = request.json if request.is_json else request.args
1✔
146

147
                try:
1✔
148
                    kwargs = kwargs or {}
1✔
149

150
                    input_filter.data = {**data, **kwargs}
1✔
151

152
                    g.validated_data = input_filter.validateData()
1✔
153

154
                except ValidationError as e:
1✔
155
                    return Response(
1✔
156
                        status=400,
157
                        response=json.dumps(e.args[0]),
158
                        mimetype="application/json",
159
                    )
160

UNCOV
161
                except Exception:
×
UNCOV
162
                    logging.getLogger(__name__).exception(
×
163
                        "An unexpected exception occurred while "
164
                        "validating input data.",
165
                    )
UNCOV
166
                    return Response(status=500)
×
167

168
                return f(*args, **kwargs)
1✔
169

170
            return wrapper
1✔
171

172
        return decorator
1✔
173

174
    def validateData(
1✔
175
        self, data: Optional[Dict[str, Any]] = None
176
    ) -> Union[Dict[str, Any], Type[T]]:
177
        """
178
        Validates input data against defined field rules, including
179
        applying filters, validators, custom logic steps, and
180
        fallback mechanisms. The validation process also ensures the
181
        required fields are handled appropriately and conditions are
182
        checked after processing.
183

184
        Args:
185
            data (Dict[str, Any]): A dictionary containing the input data to
186
                be validated where keys represent field names and values
187
                represent the corresponding data.
188

189
        Returns:
190
            Union[Dict[str, Any], Type[T]]: A dictionary containing the
191
                validated data with any modifications, default values,
192
                or processed values as per the defined validation rules.
193

194
        Raises:
195
            Any errors raised during external API calls, validation, or
196
                logical steps execution of the respective fields or conditions
197
                will propagate without explicit handling here.
198
        """
199
        import warnings
1✔
200

201
        warnings.warn(
1✔
202
            "validateData() is deprecated, use validate_data() instead",
203
            DeprecationWarning,
204
            stacklevel=2,
205
        )
206
        return self.validate_data(data)
1✔
207

208
    def validate_data(
1✔
209
        self, data: Optional[Dict[str, Any]] = None
210
    ) -> Union[Dict[str, Any], Type[T]]:
211
        """
212
        Validates input data against defined field rules, including
213
        applying filters, validators, custom logic steps, and
214
        fallback mechanisms. The validation process also ensures the
215
        required fields are handled appropriately and conditions are
216
        checked after processing.
217

218
        Args:
219
            data (Dict[str, Any]): A dictionary containing the input data to
220
                be validated where keys represent field names and values
221
                represent the corresponding data.
222

223
        Returns:
224
            Union[Dict[str, Any], Type[T]]: A dictionary containing the
225
                validated data with any modifications, default values,
226
                or processed values as per the defined validation rules.
227

228
        Raises:
229
            Any errors raised during external API calls, validation, or
230
                logical steps execution of the respective fields or conditions
231
                will propagate without explicit handling here.
232
        """
233
        data = data or self.data
1✔
234
        errors = {}
1✔
235

236
        for field_name, field_info in self.fields.items():
1✔
237
            value = data.get(field_name)
1✔
238

239
            required = field_info.required
1✔
240
            default = field_info.default
1✔
241
            fallback = field_info.fallback
1✔
242
            filters = field_info.filters + self.global_filters
1✔
243
            validators = field_info.validators + self.global_validators
1✔
244
            steps = field_info.steps
1✔
245
            external_api = field_info.external_api
1✔
246
            copy = field_info.copy
1✔
247

248
            try:
1✔
249
                if copy:
1✔
250
                    value = self.validated_data.get(copy)
1✔
251

252
                if external_api:
1✔
253
                    value = ExternalApiMixin.call_external_api(
1✔
254
                        external_api, fallback, self.validated_data
255
                    )
256

257
                value = FieldMixin.apply_filters(filters, value)
1✔
258
                value = (
1✔
259
                    FieldMixin.validate_field(validators, fallback, value)
260
                    or value
261
                )
262
                value = FieldMixin.apply_steps(steps, fallback, value) or value
1✔
263
                value = FieldMixin.check_for_required(
1✔
264
                    field_name, required, default, fallback, value
265
                )
266

267
                self.validated_data[field_name] = value
1✔
268

269
            except ValidationError as e:
1✔
270
                errors[field_name] = str(e)
1✔
271

272
        try:
1✔
273
            FieldMixin.check_conditions(self.conditions, self.validated_data)
1✔
274
        except ValidationError as e:
1✔
275
            errors["_condition"] = str(e)
1✔
276

277
        if errors:
1✔
278
            raise ValidationError(errors)
1✔
279

280
        if self.model_class is not None:
1✔
281
            return self.serialize()
1✔
282

283
        return self.validated_data
1✔
284

285
    def addCondition(self, condition: BaseCondition) -> None:
1✔
286
        """
287
        Add a condition to the input filter.
288

289
        Args:
290
            condition (BaseCondition): The condition to add.
291
        """
UNCOV
292
        import warnings
×
293

294
        warnings.warn(
×
295
            "addCondition() is deprecated, use add_condition() instead",
296
            DeprecationWarning,
297
            stacklevel=2,
298
        )
UNCOV
299
        self.add_condition(condition)
×
300

301
    def add_condition(self, condition: BaseCondition) -> None:
1✔
302
        """
303
        Add a condition to the input filter.
304

305
        Args:
306
            condition (BaseCondition): The condition to add.
307
        """
308
        self.conditions.append(condition)
1✔
309

310
    def getConditions(self) -> List[BaseCondition]:
1✔
311
        """
312
        Retrieve the list of all registered conditions.
313

314
        This function provides access to the conditions that have been
315
        registered and stored. Each condition in the returned list
316
        is represented as an instance of the BaseCondition type.
317

318
        Returns:
319
            List[BaseCondition]: A list containing all currently registered
320
                instances of BaseCondition.
321
        """
UNCOV
322
        import warnings
×
323

324
        warnings.warn(
×
325
            "getConditions() is deprecated, use get_conditions() instead",
326
            DeprecationWarning,
327
            stacklevel=2,
328
        )
UNCOV
329
        return self.get_conditions()
×
330

331
    def get_conditions(self) -> List[BaseCondition]:
1✔
332
        """
333
        Retrieve the list of all registered conditions.
334

335
        This function provides access to the conditions that have been
336
        registered and stored. Each condition in the returned list
337
        is represented as an instance of the BaseCondition type.
338

339
        Returns:
340
            List[BaseCondition]: A list containing all currently registered
341
                instances of BaseCondition.
342
        """
343
        return self.conditions
1✔
344

345
    def setData(self, data: Dict[str, Any]) -> None:
1✔
346
        """
347
        Filters and sets the provided data into the object's internal
348
        storage, ensuring that only the specified fields are
349
        considered and their values are processed through defined
350
        filters.
351

352
        Parameters:
353
            data (Dict[str, Any]):
354
                The input dictionary containing key-value pairs where keys
355
                represent field names and values represent the associated
356
                data to be filtered and stored.
357
        """
UNCOV
358
        import warnings
×
359

UNCOV
360
        warnings.warn(
×
361
            "setData() is deprecated, use set_data() instead",
362
            DeprecationWarning,
363
            stacklevel=2,
364
        )
UNCOV
365
        self.set_data(data)
×
366

367
    def set_data(self, data: Dict[str, Any]) -> None:
1✔
368
        """
369
        Filters and sets the provided data into the object's internal
370
        storage, ensuring that only the specified fields are
371
        considered and their values are processed through defined
372
        filters.
373

374
        Parameters:
375
            data (Dict[str, Any]):
376
                The input dictionary containing key-value pairs where keys
377
                represent field names and values represent the associated
378
                data to be filtered and stored.
379
        """
380
        self.data = {}
1✔
381
        for field_name, field_value in data.items():
1✔
382
            if field_name in self.fields:
1✔
383
                field_value = FieldMixin.apply_filters(
1✔
384
                    filters=self.fields[field_name].filters,
385
                    value=field_value,
386
                )
387

388
            self.data[field_name] = field_value
1✔
389

390
    def getValue(self, name: str) -> Any:
1✔
391
        """
392
        This method retrieves a value associated with the provided
393
        name. It searches for the value based on the given identifier
394
        and returns the corresponding result. If no value is found,
395
        it typically returns a default or fallback output. The method
396
        aims to provide flexibility in retrieving data without
397
        explicitly specifying the details of the underlying
398
        implementation.
399

400
        Args:
401
            name (str): A string that represents the identifier for which the
402
                 corresponding value is being retrieved. It is used to perform
403
                 the lookup.
404

405
        Returns:
406
            Any: The retrieved value associated with the given name. The
407
                 specific type of this value is dependent on the
408
                 implementation and the data being accessed.
409
        """
UNCOV
410
        import warnings
×
411

UNCOV
412
        warnings.warn(
×
413
            "getValue() is deprecated, use get_value() instead",
414
            DeprecationWarning,
415
            stacklevel=2,
416
        )
UNCOV
417
        return self.get_value(name)
×
418

419
    def get_value(self, name: str) -> Any:
1✔
420
        """
421
        This method retrieves a value associated with the provided
422
        name. It searches for the value based on the given identifier
423
        and returns the corresponding result. If no value is found,
424
        it typically returns a default or fallback output. The method
425
        aims to provide flexibility in retrieving data without
426
        explicitly specifying the details of the underlying
427
        implementation.
428

429
        Args:
430
            name (str): A string that represents the identifier for which the
431
                 corresponding value is being retrieved. It is used to perform
432
                 the lookup.
433

434
        Returns:
435
            Any: The retrieved value associated with the given name. The
436
                 specific type of this value is dependent on the
437
                 implementation and the data being accessed.
438
        """
439
        return self.validated_data.get(name)
1✔
440

441
    def getValues(self) -> Dict[str, Any]:
1✔
442
        """
443
        Retrieves a dictionary of key-value pairs from the current
444
        object. This method provides access to the internal state or
445
        configuration of the object in a dictionary format, where
446
        keys are strings and values can be of various types depending
447
        on the object's design.
448

449
        Returns:
450
            Dict[str, Any]: A dictionary containing string keys and their
451
                            corresponding values of any data type.
452
        """
UNCOV
453
        import warnings
×
454

UNCOV
455
        warnings.warn(
×
456
            "getValues() is deprecated, use get_values() instead",
457
            DeprecationWarning,
458
            stacklevel=2,
459
        )
UNCOV
460
        return self.get_values()
×
461

462
    def get_values(self) -> Dict[str, Any]:
1✔
463
        """
464
        Retrieves a dictionary of key-value pairs from the current
465
        object. This method provides access to the internal state or
466
        configuration of the object in a dictionary format, where
467
        keys are strings and values can be of various types depending
468
        on the object's design.
469

470
        Returns:
471
            Dict[str, Any]: A dictionary containing string keys and their
472
                            corresponding values of any data type.
473
        """
474
        return self.validated_data
1✔
475

476
    def getRawValue(self, name: str) -> Any:
1✔
477
        """
478
        Fetches the raw value associated with the provided key.
479

480
        This method is used to retrieve the underlying value linked to the
481
        given key without applying any transformations or validations. It
482
        directly fetches the raw stored value and is typically used in
483
        scenarios where the raw data is needed for processing or debugging
484
        purposes.
485

486
        Args:
487
            name (str): The name of the key whose raw value is to be
488
                retrieved.
489

490
        Returns:
491
            Any: The raw value associated with the provided key.
492
        """
UNCOV
493
        import warnings
×
494

UNCOV
495
        warnings.warn(
×
496
            "getRawValue() is deprecated, use get_raw_value() instead",
497
            DeprecationWarning,
498
            stacklevel=2,
499
        )
UNCOV
500
        return self.get_raw_value(name)
×
501

502
    def get_raw_value(self, name: str) -> Any:
1✔
503
        """
504
        Fetches the raw value associated with the provided key.
505

506
        This method is used to retrieve the underlying value linked to the
507
        given key without applying any transformations or validations. It
508
        directly fetches the raw stored value and is typically used in
509
        scenarios where the raw data is needed for processing or debugging
510
        purposes.
511

512
        Args:
513
            name (str): The name of the key whose raw value is to be
514
                retrieved.
515

516
        Returns:
517
            Any: The raw value associated with the provided key.
518
        """
519
        return self.data.get(name)
1✔
520

521
    def getRawValues(self) -> Dict[str, Any]:
1✔
522
        """
523
        Retrieves raw values from a given source and returns them as
524
        a dictionary.
525

526
        This method is used to fetch and return unprocessed or raw data in
527
        the form of a dictionary where the keys are strings, representing
528
        the identifiers, and the values are of any data type.
529

530
        Returns:
531
            Dict[str, Any]: A dictionary containing the raw values retrieved.
532
               The keys are strings representing the identifiers, and the
533
               values can be of any type, depending on the source
534
               being accessed.
535
        """
UNCOV
536
        import warnings
×
537

UNCOV
538
        warnings.warn(
×
539
            "getRawValues() is deprecated, use get_raw_values() instead",
540
            DeprecationWarning,
541
            stacklevel=2,
542
        )
UNCOV
543
        return self.get_raw_values()
×
544

545
    def get_raw_values(self) -> Dict[str, Any]:
1✔
546
        """
547
        Retrieves raw values from a given source and returns them as
548
        a dictionary.
549

550
        This method is used to fetch and return unprocessed or raw data in
551
        the form of a dictionary where the keys are strings, representing
552
        the identifiers, and the values are of any data type.
553

554
        Returns:
555
            Dict[str, Any]: A dictionary containing the raw values retrieved.
556
               The keys are strings representing the identifiers, and the
557
               values can be of any type, depending on the source
558
               being accessed.
559
        """
560
        if not self.fields:
1✔
561
            return {}
1✔
562

563
        return {
1✔
564
            field: self.data[field]
565
            for field in self.fields
566
            if field in self.data
567
        }
568

569
    def getUnfilteredData(self) -> Dict[str, Any]:
1✔
570
        """
571
        Fetches unfiltered data from the data source.
572

573
        This method retrieves data without any filtering, processing, or
574
        manipulations applied. It is intended to provide raw data that has
575
        not been altered since being retrieved from its source. The usage
576
        of this method should be limited to scenarios where unprocessed data
577
        is required, as it does not perform any validations or checks.
578

579
        Returns:
580
            Dict[str, Any]: The unfiltered, raw data retrieved from the
581
                 data source. The return type may vary based on the
582
                 specific implementation of the data source.
583
        """
UNCOV
584
        import warnings
×
585

UNCOV
586
        warnings.warn(
×
587
            "getUnfilteredData() is deprecated, use "
588
            "get_unfiltered_data() instead",
589
            DeprecationWarning,
590
            stacklevel=2,
591
        )
UNCOV
592
        return self.get_unfiltered_data()
×
593

594
    def get_unfiltered_data(self) -> Dict[str, Any]:
1✔
595
        """
596
        Fetches unfiltered data from the data source.
597

598
        This method retrieves data without any filtering, processing, or
599
        manipulations applied. It is intended to provide raw data that has
600
        not been altered since being retrieved from its source. The usage
601
        of this method should be limited to scenarios where unprocessed data
602
        is required, as it does not perform any validations or checks.
603

604
        Returns:
605
            Dict[str, Any]: The unfiltered, raw data retrieved from the
606
                 data source. The return type may vary based on the
607
                 specific implementation of the data source.
608
        """
609
        return self.data
1✔
610

611
    def setUnfilteredData(self, data: Dict[str, Any]) -> None:
1✔
612
        """
613
        Sets unfiltered data for the current instance. This method
614
        assigns a given dictionary of data to the instance for
615
        further processing. It updates the internal state using the
616
        provided data.
617

618
        Parameters:
619
            data (Dict[str, Any]): A dictionary containing the unfiltered
620
                data to be associated with the instance.
621
        """
UNCOV
622
        import warnings
×
623

UNCOV
624
        warnings.warn(
×
625
            "setUnfilteredData() is deprecated, use "
626
            "set_unfiltered_data() instead",
627
            DeprecationWarning,
628
            stacklevel=2,
629
        )
UNCOV
630
        self.set_unfiltered_data(data)
×
631

632
    def set_unfiltered_data(self, data: Dict[str, Any]) -> None:
1✔
633
        """
634
        Sets unfiltered data for the current instance. This method
635
        assigns a given dictionary of data to the instance for
636
        further processing. It updates the internal state using the
637
        provided data.
638

639
        Parameters:
640
            data (Dict[str, Any]): A dictionary containing the unfiltered
641
                data to be associated with the instance.
642
        """
643
        self.data = data
1✔
644

645
    def hasUnknown(self) -> bool:
1✔
646
        """
647
        Checks whether any values in the current data do not have
648
        corresponding configurations in the defined fields.
649

650
        Returns:
651
            bool: True if there are any unknown fields; False otherwise.
652
        """
UNCOV
653
        import warnings
×
654

UNCOV
655
        warnings.warn(
×
656
            "hasUnknown() is deprecated, use has_unknown() instead",
657
            DeprecationWarning,
658
            stacklevel=2,
659
        )
UNCOV
660
        return self.has_unknown()
×
661

662
    def has_unknown(self) -> bool:
1✔
663
        """
664
        Checks whether any values in the current data do not have
665
        corresponding configurations in the defined fields.
666

667
        Returns:
668
            bool: True if there are any unknown fields; False otherwise.
669
        """
670
        if not self.data and self.fields:
1✔
671
            return True
1✔
672

673
        return any(
1✔
674
            field_name not in self.fields.keys()
675
            for field_name in self.data.keys()
676
        )
677

678
    def getErrorMessage(self, field_name: str) -> Optional[str]:
1✔
679
        """
680
        Retrieves and returns a predefined error message.
681

682
        This method is intended to provide a consistent error message
683
        to be used across the application when an error occurs. The
684
        message is predefined and does not accept any parameters.
685
        The exact content of the error message may vary based on
686
        specific implementation, but it is designed to convey meaningful
687
        information about the nature of an error.
688

689
        Args:
690
            field_name (str): The name of the field for which the error
691
                message is being retrieved.
692

693
        Returns:
694
            Optional[str]: A string representing the predefined error message.
695
        """
UNCOV
696
        import warnings
×
697

UNCOV
698
        warnings.warn(
×
699
            "getErrorMessage() is deprecated, use get_error_message() instead",
700
            DeprecationWarning,
701
            stacklevel=2,
702
        )
UNCOV
703
        return self.get_error_message(field_name)
×
704

705
    def get_error_message(self, field_name: str) -> Optional[str]:
1✔
706
        """
707
        Retrieves and returns a predefined error message.
708

709
        This method is intended to provide a consistent error message
710
        to be used across the application when an error occurs. The
711
        message is predefined and does not accept any parameters.
712
        The exact content of the error message may vary based on
713
        specific implementation, but it is designed to convey meaningful
714
        information about the nature of an error.
715

716
        Args:
717
            field_name (str): The name of the field for which the error
718
                message is being retrieved.
719

720
        Returns:
721
            Optional[str]: A string representing the predefined error message.
722
        """
723
        return self.errors.get(field_name)
1✔
724

725
    def getErrorMessages(self) -> Dict[str, str]:
1✔
726
        """
727
        Retrieves all error messages associated with the fields in
728
        the input filter.
729

730
        This method aggregates and returns a dictionary of error messages
731
        where the keys represent field names, and the values are their
732
        respective error messages.
733

734
        Returns:
735
            Dict[str, str]: A dictionary containing field names as keys and
736
                            their corresponding error messages as values.
737
        """
UNCOV
738
        import warnings
×
739

UNCOV
740
        warnings.warn(
×
741
            "getErrorMessages() is deprecated, use "
742
            "get_error_messages() instead",
743
            DeprecationWarning,
744
            stacklevel=2,
745
        )
UNCOV
746
        return self.get_error_messages()
×
747

748
    def get_error_messages(self) -> Dict[str, str]:
1✔
749
        """
750
        Retrieves all error messages associated with the fields in
751
        the input filter.
752

753
        This method aggregates and returns a dictionary of error messages
754
        where the keys represent field names, and the values are their
755
        respective error messages.
756

757
        Returns:
758
            Dict[str, str]: A dictionary containing field names as keys and
759
                            their corresponding error messages as values.
760
        """
761
        return self.errors
1✔
762

763
    def add(
1✔
764
        self,
765
        name: str,
766
        required: bool = False,
767
        default: Any = None,
768
        fallback: Any = None,
769
        filters: Optional[List[BaseFilter]] = None,
770
        validators: Optional[List[BaseValidator]] = None,
771
        steps: Optional[List[Union[BaseFilter, BaseValidator]]] = None,
772
        external_api: Optional[ExternalApiConfig] = None,
773
        copy: Optional[str] = None,
774
    ) -> None:
775
        """
776
        Add the field to the input filter.
777

778
        Args:
779
            name (str): The name of the field.
780

781
            required (Optional[bool]): Whether the field is required.
782

783
            default (Optional[Any]): The default value of the field.
784

785
            fallback (Optional[Any]): The fallback value of the field, if
786
                validations fails or field None, although it is required.
787

788
            filters (Optional[List[BaseFilter]]): The filters to apply to
789
                the field value.
790

791
            validators (Optional[List[BaseValidator]]): The validators to
792
                apply to the field value.
793

794
            steps (Optional[List[Union[BaseFilter, BaseValidator]]]): Allows
795
                to apply multiple filters and validators in a specific order.
796

797
            external_api (Optional[ExternalApiConfig]): Configuration for an
798
                external API call.
799

800
            copy (Optional[str]): The name of the field to copy the value
801
                from.
802
        """
803
        if name in self.fields:
1✔
804
            raise ValueError(f"Field '{name}' already exists.")
1✔
805

806
        self.fields[name] = FieldModel(
1✔
807
            required=required,
808
            default=default,
809
            fallback=fallback,
810
            filters=filters or [],
811
            validators=validators or [],
812
            steps=steps or [],
813
            external_api=external_api,
814
            copy=copy,
815
        )
816

817
    def has(self, field_name: str) -> bool:
1✔
818
        """
819
        This method checks the existence of a specific field within
820
        the input filter values, identified by its field name. It
821
        does not return a value, serving purely as a validation or
822
        existence check mechanism.
823

824
        Args:
825
            field_name (str): The name of the field to check for existence.
826

827
        Returns:
828
            bool: True if the field exists in the input filter,
829
                otherwise False.
830
        """
831
        return field_name in self.fields
1✔
832

833
    def getInput(self, field_name: str) -> Optional[FieldModel]:
1✔
834
        """
835
        Represents a method to retrieve a field by its name.
836

837
        This method allows fetching the configuration of a specific field
838
        within the object, using its name as a string. It ensures
839
        compatibility with various field names and provides a generic
840
        return type to accommodate different data types for the fields.
841

842
        Args:
843
            field_name (str): A string representing the name of the field who
844
                        needs to be retrieved.
845

846
        Returns:
847
            Optional[FieldModel]: The field corresponding to the
848
                specified name.
849
        """
UNCOV
850
        import warnings
×
851

UNCOV
852
        warnings.warn(
×
853
            "getInput() is deprecated, use get_input() instead",
854
            DeprecationWarning,
855
            stacklevel=2,
856
        )
UNCOV
857
        return self.get_input(field_name)
×
858

859
    def get_input(self, field_name: str) -> Optional[FieldModel]:
1✔
860
        """
861
        Represents a method to retrieve a field by its name.
862

863
        This method allows fetching the configuration of a specific field
864
        within the object, using its name as a string. It ensures
865
        compatibility with various field names and provides a generic
866
        return type to accommodate different data types for the fields.
867

868
        Args:
869
            field_name (str): A string representing the name of the field who
870
                        needs to be retrieved.
871

872
        Returns:
873
            Optional[FieldModel]: The field corresponding to the
874
                specified name.
875
        """
876
        return self.fields.get(field_name)
1✔
877

878
    def getInputs(self) -> Dict[str, FieldModel]:
1✔
879
        """
880
        Retrieve the dictionary of input fields associated with the
881
        object.
882

883
        Returns:
884
            Dict[str, FieldModel]: Dictionary containing field names as
885
                keys and their corresponding FieldModel instances as values
886
        """
887
        import warnings
1✔
888

889
        warnings.warn(
1✔
890
            "getInputs() is deprecated, use get_inputs() instead",
891
            DeprecationWarning,
892
            stacklevel=2,
893
        )
894
        return self.get_inputs()
1✔
895

896
    def get_inputs(self) -> Dict[str, FieldModel]:
1✔
897
        """
898
        Retrieve the dictionary of input fields associated with the
899
        object.
900

901
        Returns:
902
            Dict[str, FieldModel]: Dictionary containing field names as
903
                keys and their corresponding FieldModel instances as values
904
        """
905
        return self.fields
1✔
906

907
    def remove(self, field_name: str) -> Optional[FieldModel]:
1✔
908
        """
909
        Removes the specified field from the instance or collection.
910

911
        This method is used to delete a specific field identified by
912
        its name. It ensures the designated field is removed entirely
913
        from the relevant data structure. No value is returned upon
914
        successful execution.
915

916
        Args:
917
            field_name (str): The name of the field to be removed.
918

919
        Returns:
920
            Any: The value of the removed field, if any.
921
        """
922
        return self.fields.pop(field_name, None)
1✔
923

924
    def count(self) -> int:
1✔
925
        """
926
        Counts the total number of elements in the collection.
927

928
        This method returns the total count of elements stored within the
929
        underlying data structure, providing a quick way to ascertain the
930
        size or number of entries available.
931

932
        Returns:
933
            int: The total number of elements in the collection.
934
        """
935
        return len(self.fields)
1✔
936

937
    def replace(
1✔
938
        self,
939
        name: str,
940
        required: bool = False,
941
        default: Any = None,
942
        fallback: Any = None,
943
        filters: Optional[List[BaseFilter]] = None,
944
        validators: Optional[List[BaseValidator]] = None,
945
        steps: Optional[List[Union[BaseFilter, BaseValidator]]] = None,
946
        external_api: Optional[ExternalApiConfig] = None,
947
        copy: Optional[str] = None,
948
    ) -> None:
949
        """
950
        Replaces a field in the input filter.
951

952
        Args:
953
             name (str): The name of the field.
954

955
            required (Optional[bool]): Whether the field is required.
956

957
            default (Optional[Any]): The default value of the field.
958

959
            fallback (Optional[Any]): The fallback value of the field, if
960
                validations fails or field None, although it is required.
961

962
            filters (Optional[List[BaseFilter]]): The filters to apply to
963
                the field value.
964

965
            validators (Optional[List[BaseValidator]]): The validators to
966
                apply to the field value.
967

968
            steps (Optional[List[Union[BaseFilter, BaseValidator]]]): Allows
969
                to apply multiple filters and validators in a specific order.
970

971
            external_api (Optional[ExternalApiConfig]): Configuration for an
972
                external API call.
973

974
            copy (Optional[str]): The name of the field to copy the value
975
                from.
976
        """
977
        self.fields[name] = FieldModel(
1✔
978
            required=required,
979
            default=default,
980
            fallback=fallback,
981
            filters=filters or [],
982
            validators=validators or [],
983
            steps=steps or [],
984
            external_api=external_api,
985
            copy=copy,
986
        )
987

988
    def addGlobalFilter(self, filter: BaseFilter) -> None:
1✔
989
        """
990
        Add a global filter to be applied to all fields.
991

992
        Args:
993
            filter: The filter to add.
994
        """
UNCOV
995
        import warnings
×
996

UNCOV
997
        warnings.warn(
×
998
            "addGlobalFilter() is deprecated, use add_global_filter() instead",
999
            DeprecationWarning,
1000
            stacklevel=2,
1001
        )
UNCOV
1002
        self.add_global_filter(filter)
×
1003

1004
    def add_global_filter(self, filter: BaseFilter) -> None:
1✔
1005
        """
1006
        Add a global filter to be applied to all fields.
1007

1008
        Args:
1009
            filter: The filter to add.
1010
        """
1011
        self.global_filters.append(filter)
1✔
1012

1013
    def getGlobalFilters(self) -> List[BaseFilter]:
1✔
1014
        """
1015
        Retrieve all global filters associated with this InputFilter
1016
        instance.
1017

1018
        This method returns a list of BaseFilter instances that have been
1019
        added as global filters. These filters are applied universally to
1020
        all fields during data processing.
1021

1022
        Returns:
1023
            List[BaseFilter]: A list of global filters.
1024
        """
UNCOV
1025
        import warnings
×
1026

UNCOV
1027
        warnings.warn(
×
1028
            "getGlobalFilters() is deprecated, use "
1029
            "get_global_filters() instead",
1030
            DeprecationWarning,
1031
            stacklevel=2,
1032
        )
UNCOV
1033
        return self.get_global_filters()
×
1034

1035
    def get_global_filters(self) -> List[BaseFilter]:
1✔
1036
        """
1037
        Retrieve all global filters associated with this InputFilter
1038
        instance.
1039

1040
        This method returns a list of BaseFilter instances that have been
1041
        added as global filters. These filters are applied universally to
1042
        all fields during data processing.
1043

1044
        Returns:
1045
            List[BaseFilter]: A list of global filters.
1046
        """
1047
        return self.global_filters
1✔
1048

1049
    def clear(self) -> None:
1✔
1050
        """
1051
        Resets all fields of the InputFilter instance to their
1052
        initial empty state.
1053

1054
        This method clears the internal storage of fields,
1055
        conditions, filters, validators, and data, effectively
1056
        resetting the object as if it were newly initialized.
1057
        """
1058
        self.fields.clear()
1✔
1059
        self.conditions.clear()
1✔
1060
        self.global_filters.clear()
1✔
1061
        self.global_validators.clear()
1✔
1062
        self.data.clear()
1✔
1063
        self.validated_data.clear()
1✔
1064
        self.errors.clear()
1✔
1065

1066
    def merge(self, other: "InputFilter") -> None:
1✔
1067
        """
1068
        Merges another InputFilter instance intelligently into the
1069
        current instance.
1070

1071
        - Fields with the same name are merged recursively if possible,
1072
            otherwise overwritten.
1073
        - Conditions, are combined and duplicated.
1074
        - Global filters and validators are merged without duplicates.
1075

1076
        Args:
1077
            other (InputFilter): The InputFilter instance to merge.
1078
        """
1079
        if not isinstance(other, InputFilter):
1✔
1080
            raise TypeError(
1✔
1081
                "Can only merge with another InputFilter instance."
1082
            )
1083

1084
        for key, new_field in other.getInputs().items():
1✔
1085
            self.fields[key] = new_field
1✔
1086

1087
        self.conditions += other.conditions
1✔
1088

1089
        for filter in other.global_filters:
1✔
1090
            existing_type_map = {
1✔
1091
                type(v): i for i, v in enumerate(self.global_filters)
1092
            }
1093
            if type(filter) in existing_type_map:
1✔
1094
                self.global_filters[existing_type_map[type(filter)]] = filter
1✔
1095
            else:
1096
                self.global_filters.append(filter)
1✔
1097

1098
        for validator in other.global_validators:
1✔
1099
            existing_type_map = {
1✔
1100
                type(v): i for i, v in enumerate(self.global_validators)
1101
            }
1102
            if type(validator) in existing_type_map:
1✔
1103
                self.global_validators[
1✔
1104
                    existing_type_map[type(validator)]
1105
                ] = validator
1106
            else:
1107
                self.global_validators.append(validator)
1✔
1108

1109
    def setModel(self, model_class: Type[T]) -> None:
1✔
1110
        """
1111
        Set the model class for serialization.
1112

1113
        Args:
1114
            model_class (Type[T]): The class to use for serialization.
1115
        """
UNCOV
1116
        import warnings
×
1117

UNCOV
1118
        warnings.warn(
×
1119
            "setModel() is deprecated, use set_model() instead",
1120
            DeprecationWarning,
1121
            stacklevel=2,
1122
        )
UNCOV
1123
        self.set_model(model_class)
×
1124

1125
    def set_model(self, model_class: Type[T]) -> None:
1✔
1126
        """
1127
        Set the model class for serialization.
1128

1129
        Args:
1130
            model_class (Type[T]): The class to use for serialization.
1131
        """
1132
        self.model_class = model_class
1✔
1133

1134
    def serialize(self) -> Union[Dict[str, Any], T]:
1✔
1135
        """
1136
        Serialize the validated data. If a model class is set,
1137
        returns an instance of that class, otherwise returns the raw
1138
        validated data.
1139

1140
        Returns:
1141
            Union[Dict[str, Any], T]: The serialized data.
1142
        """
1143
        if self.model_class is None:
1✔
1144
            return self.validated_data
1✔
1145

1146
        return self.model_class(**self.validated_data)
1✔
1147

1148
    def addGlobalValidator(self, validator: BaseValidator) -> None:
1✔
1149
        """
1150
        Add a global validator to be applied to all fields.
1151

1152
        Args:
1153
            validator (BaseValidator): The validator to add.
1154
        """
UNCOV
1155
        import warnings
×
1156

UNCOV
1157
        warnings.warn(
×
1158
            "addGlobalValidator() is deprecated, use "
1159
            "add_global_validator() instead",
1160
            DeprecationWarning,
1161
            stacklevel=2,
1162
        )
UNCOV
1163
        self.add_global_validator(validator)
×
1164

1165
    def add_global_validator(self, validator: BaseValidator) -> None:
1✔
1166
        """
1167
        Add a global validator to be applied to all fields.
1168

1169
        Args:
1170
            validator (BaseValidator): The validator to add.
1171
        """
1172
        self.global_validators.append(validator)
1✔
1173

1174
    def getGlobalValidators(self) -> List[BaseValidator]:
1✔
1175
        """
1176
        Retrieve all global validators associated with this
1177
        InputFilter instance.
1178

1179
        This method returns a list of BaseValidator instances that have been
1180
        added as global validators. These validators are applied universally
1181
        to all fields during validation.
1182

1183
        Returns:
1184
            List[BaseValidator]: A list of global validators.
1185
        """
UNCOV
1186
        import warnings
×
1187

UNCOV
1188
        warnings.warn(
×
1189
            "getGlobalValidators() is deprecated, use "
1190
            "get_global_validators() instead",
1191
            DeprecationWarning,
1192
            stacklevel=2,
1193
        )
UNCOV
1194
        return self.get_global_validators()
×
1195

1196
    def get_global_validators(self) -> List[BaseValidator]:
1✔
1197
        """
1198
        Retrieve all global validators associated with this
1199
        InputFilter instance.
1200

1201
        This method returns a list of BaseValidator instances that have been
1202
        added as global validators. These validators are applied universally
1203
        to all fields during validation.
1204

1205
        Returns:
1206
            List[BaseValidator]: A list of global validators.
1207
        """
1208
        return self.global_validators
1✔
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