diff --git a/docs/source/changelog.rst b/docs/source/changelog.rst index 40d2602..5f8b4af 100644 --- a/docs/source/changelog.rst +++ b/docs/source/changelog.rst @@ -3,6 +3,15 @@ Changelog All notable changes to this project will be documented in this file. +[0.6.0] - 2025-06-30 +-------------------- + +Removed +^^^^^^^ +- Removed deprecated camel case methods and properties. +- Removed deprecated subfolders. + + [0.5.5] - 2025-06-30 -------------------- @@ -75,9 +84,11 @@ Changed - Renamed files into snake_case to follow the PEP8 standard. This requires a migration if you are importing the files directly. - e.g. ``from flask_inputfilter.filters import Base64ImageResizeFilter`` to + e.g. ``from flask_inputfilter.Filter import Base64ImageResizeFilter`` to ``from flask_inputfilter.filters.base64_image_resize_filter import Base64ImageResizeFilter``. + If you are using the components through the module, you don't need to change anything. + [0.4.3a1] - 2025-04-26 ---------------------- diff --git a/docs/source/conf.py b/docs/source/conf.py index 48b37f0..9d12b72 100644 --- a/docs/source/conf.py +++ b/docs/source/conf.py @@ -12,10 +12,25 @@ "sphinx.ext.napoleon", ] +autodoc_default_options = { + "show-inheritance": True, +} + autodoc_member_order = "bysource" autodoc_typehints = "description" autoclass_content = "both" +autodoc_type_aliases = { + "EstimatorPubLike": "EstimatorPubLike", + "SamplerPubLike": "SamplerPubLike", +} + +autosummary_generate = True +autosummary_generate_overwrite = False + +napoleon_google_docstring = True +napoleon_numpy_docstring = False + sys.path.insert(0, os.path.abspath("../..")) templates_path = [] diff --git a/flask_inputfilter/Condition/__init__.py b/flask_inputfilter/Condition/__init__.py deleted file mode 100644 index 624eddb..0000000 --- a/flask_inputfilter/Condition/__init__.py +++ /dev/null @@ -1,41 +0,0 @@ -from flask_inputfilter.conditions import ( - ArrayLengthEqualCondition, - ArrayLongerThanCondition, - BaseCondition, - CustomCondition, - EqualCondition, - ExactlyNOfCondition, - ExactlyNOfMatchesCondition, - ExactlyOneOfCondition, - ExactlyOneOfMatchesCondition, - IntegerBiggerThanCondition, - NOfCondition, - NOfMatchesCondition, - NotEqualCondition, - OneOfCondition, - OneOfMatchesCondition, - RequiredIfCondition, - StringLongerThanCondition, - TemporalOrderCondition, -) - -__all__ = [ - "ArrayLengthEqualCondition", - "ArrayLongerThanCondition", - "BaseCondition", - "CustomCondition", - "EqualCondition", - "ExactlyNOfCondition", - "ExactlyNOfMatchesCondition", - "ExactlyOneOfCondition", - "ExactlyOneOfMatchesCondition", - "IntegerBiggerThanCondition", - "NOfCondition", - "NOfMatchesCondition", - "NotEqualCondition", - "OneOfCondition", - "OneOfMatchesCondition", - "RequiredIfCondition", - "StringLongerThanCondition", - "TemporalOrderCondition", -] diff --git a/flask_inputfilter/Enum/__init__.py b/flask_inputfilter/Enum/__init__.py deleted file mode 100644 index 9af64ad..0000000 --- a/flask_inputfilter/Enum/__init__.py +++ /dev/null @@ -1,7 +0,0 @@ -from flask_inputfilter.enums import ImageFormatEnum, RegexEnum, UnicodeFormEnum - -__all__ = [ - "ImageFormatEnum", - "RegexEnum", - "UnicodeFormEnum", -] diff --git a/flask_inputfilter/Exception/__init__.py b/flask_inputfilter/Exception/__init__.py deleted file mode 100644 index d9a1937..0000000 --- a/flask_inputfilter/Exception/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -from flask_inputfilter.exceptions import ValidationError - -__all__ = [ - "ValidationError", -] diff --git a/flask_inputfilter/Filter/__init__.py b/flask_inputfilter/Filter/__init__.py deleted file mode 100644 index 0f6da5b..0000000 --- a/flask_inputfilter/Filter/__init__.py +++ /dev/null @@ -1,65 +0,0 @@ -from flask_inputfilter.filters import ( - ArrayExplodeFilter, - Base64ImageDownscaleFilter, - Base64ImageResizeFilter, - BaseFilter, - BlacklistFilter, - StringRemoveEmojisFilter, - StringSlugifyFilter, - StringTrimFilter, - ToAlphaNumericFilter, - ToBooleanFilter, - ToCamelCaseFilter, - ToDataclassFilter, - ToDateFilter, - ToDateTimeFilter, - ToDigitsFilter, - ToEnumFilter, - ToFloatFilter, - ToIntegerFilter, - ToIsoFilter, - ToLowerFilter, - ToNormalizedUnicodeFilter, - ToNullFilter, - ToPascalCaseFilter, - ToSnakeCaseFilter, - ToStringFilter, - ToTypedDictFilter, - ToUpperFilter, - TruncateFilter, - WhitelistFilter, - WhitespaceCollapseFilter, -) - -__all__ = [ - "ArrayExplodeFilter", - "Base64ImageDownscaleFilter", - "Base64ImageResizeFilter", - "BaseFilter", - "BlacklistFilter", - "StringRemoveEmojisFilter", - "StringSlugifyFilter", - "StringTrimFilter", - "ToAlphaNumericFilter", - "ToBooleanFilter", - "ToCamelCaseFilter", - "ToDataclassFilter", - "ToDateFilter", - "ToDateTimeFilter", - "ToDigitsFilter", - "ToEnumFilter", - "ToFloatFilter", - "ToIntegerFilter", - "ToIsoFilter", - "ToLowerFilter", - "ToNormalizedUnicodeFilter", - "ToNullFilter", - "ToPascalCaseFilter", - "ToSnakeCaseFilter", - "ToStringFilter", - "ToTypedDictFilter", - "ToUpperFilter", - "TruncateFilter", - "WhitelistFilter", - "WhitespaceCollapseFilter", -] diff --git a/flask_inputfilter/Model/__init__.py b/flask_inputfilter/Model/__init__.py deleted file mode 100644 index 6e20a8b..0000000 --- a/flask_inputfilter/Model/__init__.py +++ /dev/null @@ -1,6 +0,0 @@ -from flask_inputfilter.models import ExternalApiConfig, FieldModel - -__all__ = [ - "FieldModel", - "ExternalApiConfig", -] diff --git a/flask_inputfilter/Validator/__init__.py b/flask_inputfilter/Validator/__init__.py deleted file mode 100644 index 807c0d1..0000000 --- a/flask_inputfilter/Validator/__init__.py +++ /dev/null @@ -1,95 +0,0 @@ -from flask_inputfilter.validators import ( - AndValidator, - ArrayElementValidator, - ArrayLengthValidator, - BaseValidator, - CustomJsonValidator, - DateAfterValidator, - DateBeforeValidator, - DateRangeValidator, - FloatPrecisionValidator, - InArrayValidator, - InEnumValidator, - IsArrayValidator, - IsBase64ImageCorrectSizeValidator, - IsBase64ImageValidator, - IsBooleanValidator, - IsDataclassValidator, - IsDateTimeValidator, - IsDateValidator, - IsFloatValidator, - IsFutureDateValidator, - IsHexadecimalValidator, - IsHorizontalImageValidator, - IsHtmlValidator, - IsInstanceValidator, - IsIntegerValidator, - IsJsonValidator, - IsLowercaseValidator, - IsMacAddressValidator, - IsPastDateValidator, - IsPortValidator, - IsRgbColorValidator, - IsStringValidator, - IsTypedDictValidator, - IsUppercaseValidator, - IsUrlValidator, - IsUUIDValidator, - IsVerticalImageValidator, - IsWeekdayValidator, - IsWeekendValidator, - LengthValidator, - NotInArrayValidator, - NotValidator, - OrValidator, - RangeValidator, - RegexValidator, -) - -__all__ = [ - "BaseValidator", - "AndValidator", - "ArrayElementValidator", - "ArrayLengthValidator", - "CustomJsonValidator", - "DateAfterValidator", - "DateBeforeValidator", - "DateRangeValidator", - "FloatPrecisionValidator", - "InArrayValidator", - "InEnumValidator", - "IsArrayValidator", - "IsBase64ImageCorrectSizeValidator", - "IsBase64ImageValidator", - "IsBooleanValidator", - "IsDataclassValidator", - "IsDateTimeValidator", - "IsDateValidator", - "IsFloatValidator", - "IsFutureDateValidator", - "IsHexadecimalValidator", - "IsHorizontalImageValidator", - "IsHtmlValidator", - "IsInstanceValidator", - "IsIntegerValidator", - "IsJsonValidator", - "IsLowercaseValidator", - "IsMacAddressValidator", - "IsPastDateValidator", - "IsPortValidator", - "IsRgbColorValidator", - "IsStringValidator", - "IsTypedDictValidator", - "IsUppercaseValidator", - "IsUrlValidator", - "IsUUIDValidator", - "IsVerticalImageValidator", - "IsWeekdayValidator", - "IsWeekendValidator", - "LengthValidator", - "NotInArrayValidator", - "NotValidator", - "OrValidator", - "RangeValidator", - "RegexValidator", -] diff --git a/flask_inputfilter/_input_filter.pyx b/flask_inputfilter/_input_filter.pyx index 08dc072..c74057e 100644 --- a/flask_inputfilter/_input_filter.pyx +++ b/flask_inputfilter/_input_filter.pyx @@ -1,12 +1,6 @@ # cython: language=c++ -# cython: language_level=3 -# cython: binding=True -# cython: cdivision=True -# cython: boundscheck=False -# cython: initializedcheck=False import json import logging -import warnings from typing import Any, Optional, Type, TypeVar, Union from flask import Response, g, request @@ -60,14 +54,6 @@ cdef class InputFilter: self.methods.clear() [self.methods.push_back(method.encode()) for method in methods] - cpdef bint isValid(self): - warnings.warn( - "isValid() is deprecated, use is_valid() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.is_valid() - cpdef bint is_valid(self): """ Checks if the object's state or its attributes meet certain @@ -171,16 +157,6 @@ cdef class InputFilter: return decorator - cpdef object validateData( - self, data: Optional[dict[str, Any]] = None - ): - warnings.warn( - "validateData() is deprecated, use validate_data() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.validate_data(data) - cpdef object validate_data( self, data: Optional[dict[str, Any]] = None ): @@ -209,19 +185,29 @@ cdef class InputFilter: cdef dict errors = {} cdef dict validated_data = {} - cdef object default - cdef object fallback - cdef list filters - cdef list validators - cdef object external_api - cdef str copy - - cdef list global_filters = self.global_filters - cdef list global_validators = self.global_validators - cdef bint has_global_filters = bool(global_filters) - cdef bint has_global_validators = bool(global_validators) - - for field_name, field_info in self.fields.items(): + cdef: + list global_filters = self.global_filters + list global_validators = self.global_validators + bint has_global_filters = bool(global_filters) + bint has_global_validators = bool(global_validators) + + cdef: + int i = 0 + int n = len(self.fields) + list field_names = list(self.fields.keys()) + list field_infos = list(self.fields.values()) + + cdef: + object default + object fallback + list filters + list validators + object external_api + str copy + + for i in range(n): + field_name = field_names[i] + field_info = field_infos[i] try: if field_info.copy: value = validated_data.get(field_info.copy) @@ -235,27 +221,27 @@ cdef class InputFilter: value = data.get(field_name) if field_info.filters or has_global_filters: - filters = field_info.filters - if has_global_filters: - filters = filters + global_filters - value = FieldMixin.apply_filters(filters, value) + value = FieldMixin.apply_filters( + field_info.filters + global_filters + if has_global_filters + else field_info.filters, + value + ) if field_info.validators or has_global_validators: - validators = field_info.validators - if has_global_validators: - validators = validators + global_validators - result = FieldMixin.validate_field( - validators, field_info.fallback, value - ) - if result is not None: - value = result + value = FieldMixin.validate_field( + field_info.validators + global_validators + if has_global_validators + else field_info.validators, + field_info.fallback, + value + ) or value if field_info.steps: - result = FieldMixin.apply_steps( - field_info.steps, field_info.fallback, value - ) - if result is not None: - value = result + value = FieldMixin.apply_steps( + field_info.steps, + field_info.fallback, value + ) or value if value is None: if field_info.required: @@ -291,14 +277,6 @@ cdef class InputFilter: return validated_data - cpdef void addCondition(self, condition: BaseCondition): - warnings.warn( - "addCondition() is deprecated, use add_condition() instead", - DeprecationWarning, - stacklevel=2 - ) - self.add_condition(condition) - cpdef void add_condition(self, condition: BaseCondition): """ Add a condition to the input filter. @@ -308,14 +286,6 @@ cdef class InputFilter: """ self.conditions.append(condition) - cpdef list getConditions(self): - warnings.warn( - "getConditions() is deprecated, use get_conditions() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_conditions() - cpdef list get_conditions(self): """ Retrieve the list of all registered conditions. @@ -330,14 +300,6 @@ cdef class InputFilter: """ return self.conditions - cpdef void setData(self, data: dict[str, Any]): - warnings.warn( - "setData() is deprecated, use set_data() instead", - DeprecationWarning, - stacklevel=2 - ) - self.set_data(data) - cpdef void set_data(self, data: dict[str, Any]): """ Filters and sets the provided data into the object's internal @@ -351,7 +313,15 @@ cdef class InputFilter: data to be filtered and stored. """ self.data = {} - for field_name, field_value in data.items(): + cdef: + int i = 0 + int n = len(data) + list keys = list(data.keys()) + list values = list(data.values()) + + for i in range(n): + field_name = keys[i] + field_value = values[i] if field_name in self.fields: field_value = FieldMixin.apply_filters( filters=self.fields[field_name].filters + self.global_filters, @@ -360,14 +330,6 @@ cdef class InputFilter: self.data[field_name] = field_value - cpdef object getValue(self, name: str): - warnings.warn( - "getValue() is deprecated, use get_value() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_value(name) - cpdef object get_value(self, name: str): """ This method retrieves a value associated with the provided name. It @@ -389,14 +351,6 @@ cdef class InputFilter: """ return self.validated_data.get(name) - cpdef dict getValues(self): - warnings.warn( - "getValues() is deprecated, use get_values() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_values() - cpdef dict get_values(self): """ Retrieves a dictionary of key-value pairs from the current object. @@ -410,14 +364,6 @@ cdef class InputFilter: """ return self.validated_data - cpdef object getRawValue(self, name: str): - warnings.warn( - "getRawValue() is deprecated, use get_raw_value() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_raw_value(name) - cpdef object get_raw_value(self, name: str): """ Fetches the raw value associated with the provided key. @@ -437,14 +383,6 @@ cdef class InputFilter: """ return self.data.get(name) if name in self.data else None - cpdef dict getRawValues(self): - warnings.warn( - "getRawValues() is deprecated, use get_raw_values() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_raw_values() - cpdef dict get_raw_values(self): """ Retrieves raw values from a given source and returns them as a @@ -463,19 +401,17 @@ cdef class InputFilter: if not self.fields: return {} - return { - field: self.data[field] - for field in self.fields - if field in self.data - } - - cpdef dict getUnfilteredData(self): - warnings.warn( - "getUnfilteredData() is deprecated, use get_unfiltered_data() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_unfiltered_data() + cdef: + int i = 0 + int n = len(self.fields) + dict result = {} + list field_names = list(self.fields.keys()) + + for i in range(n): + field = field_names[i] + if field in self.data: + result[field] = self.data[field] + return result cpdef dict get_unfiltered_data(self): """ @@ -494,34 +430,19 @@ cdef class InputFilter: """ return self.data - cpdef void setUnfilteredData(self, data: dict[str, Any]): - warnings.warn( - "setUnfilteredData() is deprecated, use set_unfiltered_data() instead", - DeprecationWarning, - stacklevel=2 - ) - self.set_unfiltered_data(data) - cpdef void set_unfiltered_data(self, data: dict[str, Any]): """ Sets unfiltered data for the current instance. This method assigns a given dictionary of data to the instance for further processing. It updates the internal state using the provided data. - Parameters: - data (dict[str, Any]): A dictionary containing the unfiltered + **Parameters**: + + - data (dict[str, Any]): A dictionary containing the unfiltered data to be associated with the instance. """ self.data = data - cpdef bint hasUnknown(self): - warnings.warn( - "hasUnknown() is deprecated, use has_unknown() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.has_unknown() - cpdef bint has_unknown(self): """ Checks whether any values in the current data do not have @@ -539,14 +460,6 @@ cdef class InputFilter: return False - cpdef str getErrorMessage(self, field_name: str): - warnings.warn( - "getErrorMessage() is deprecated, use get_error_message() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_error_message(field_name) - cpdef str get_error_message(self, field_name: str): """ Retrieves and returns a predefined error message. @@ -567,14 +480,6 @@ cdef class InputFilter: """ return self.errors.get(field_name) - cpdef dict getErrorMessages(self): - warnings.warn( - "getErrorMessages() is deprecated, use get_error_messages() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_error_messages() - cpdef dict get_error_messages(self): """ Retrieves all error messages associated with the fields in the @@ -659,14 +564,6 @@ cdef class InputFilter: """ return field_name in self.fields - cpdef object getInput(self, field_name: str): - warnings.warn( - "getInput() is deprecated, use get_input() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_input(field_name) - cpdef object get_input(self, field_name: str): """ Represents a method to retrieve a field by its name. @@ -686,14 +583,6 @@ cdef class InputFilter: """ return self.fields.get(field_name) - cpdef dict getInputs(self): - warnings.warn( - "getInputs() is deprecated, use get_inputs() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_inputs() - cpdef dict get_inputs(self): """ Retrieve the dictionary of input fields associated with the object. @@ -785,14 +674,6 @@ cdef class InputFilter: copy=copy, ) - cpdef void addGlobalFilter(self, filter: BaseFilter): - warnings.warn( - "addGlobalFilter() is deprecated, use add_global_filter() instead", - DeprecationWarning, - stacklevel=2 - ) - self.add_global_filter(filter) - cpdef void add_global_filter(self, filter: BaseFilter): """ Add a global filter to be applied to all fields. @@ -802,14 +683,6 @@ cdef class InputFilter: """ self.global_filters.append(filter) - cpdef list getGlobalFilters(self): - warnings.warn( - "getGlobalFilters() is deprecated, use get_global_filters() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.get_global_filters() - cpdef list get_global_filters(self): """ Retrieve all global filters associated with this InputFilter instance. @@ -858,9 +731,14 @@ cdef class InputFilter: "Can only merge with another InputFilter instance." ) - for key, new_field in other.get_inputs().items(): - self.fields[key] = new_field + cdef: + int i = 0 + int n = len(other.get_inputs()) + list keys = list(other.get_inputs().keys()) + list new_fields = list(other.get_inputs().values()) + for i in range(n): + self.fields[keys[i]] = new_fields[i] self.conditions += other.conditions for filter in other.global_filters: @@ -883,14 +761,6 @@ cdef class InputFilter: else: self.global_validators.append(validator) - cpdef void setModel(self, model_class: Type[T]): - warnings.warn( - "setModel() is deprecated, use set_model() instead", - DeprecationWarning, - stacklevel=2 - ) - self.set_model(model_class) - cpdef void set_model(self, model_class: Type[T]): """ Set the model class for serialization. @@ -914,14 +784,6 @@ cdef class InputFilter: return self.model_class(**self.validated_data) - cpdef void addGlobalValidator(self, validator: BaseValidator): - warnings.warn( - "addGlobalValidator() is deprecated, use add_global_validator() instead", - DeprecationWarning, - stacklevel=2 - ) - self.add_global_validator(validator) - cpdef void add_global_validator(self, validator: BaseValidator): """ Add a global validator to be applied to all fields. @@ -931,14 +793,6 @@ cdef class InputFilter: """ self.global_validators.append(validator) - cpdef list getGlobalValidators(self): - warnings.warn( - "getGlobalValidators() is deprecated, use get_global_validators() instead", - DeprecationWarning, - stacklevel=2 - ) - return self.global_validators - cpdef list get_global_validators(self): """ Retrieve all global validators associated with this diff --git a/flask_inputfilter/conditions/custom_condition.py b/flask_inputfilter/conditions/custom_condition.py index e961811..d52d507 100644 --- a/flask_inputfilter/conditions/custom_condition.py +++ b/flask_inputfilter/conditions/custom_condition.py @@ -13,8 +13,8 @@ class CustomCondition(BaseCondition): **Parameters:** - **condition** (*Callable[[dict[str, Any]], bool]*): A function that - takes the input data and returns a boolean indicating whether the - condition is met. + takes the input data and returns a boolean indicating whether the + condition is met. **Expected Behavior:** diff --git a/flask_inputfilter/conditions/required_if_condition.py b/flask_inputfilter/conditions/required_if_condition.py index be8799d..6c91f14 100644 --- a/flask_inputfilter/conditions/required_if_condition.py +++ b/flask_inputfilter/conditions/required_if_condition.py @@ -13,9 +13,9 @@ class RequiredIfCondition(BaseCondition): - **condition_field** (*str*): The field whose value is checked. - **value** (*Optional[Union[Any, list[Any]]]*): The value(s) that - trigger the requirement. + trigger the requirement. - **required_field** (*str*): The field that becomes required if the - condition is met. + condition is met. **Expected Behavior:** diff --git a/flask_inputfilter/filters/array_element_filter.py b/flask_inputfilter/filters/array_element_filter.py index 27c1888..66c3f92 100644 --- a/flask_inputfilter/filters/array_element_filter.py +++ b/flask_inputfilter/filters/array_element_filter.py @@ -12,7 +12,7 @@ class ArrayElementFilter(BaseFilter): **Parameters:** - **element_filter** (*BaseFilter* | *list[BaseFilter]*): A filter or a - list of filters to apply to each element in the array. + list of filters to apply to each element in the array. **Expected Behavior:** @@ -49,12 +49,12 @@ def apply(self, value: Any) -> list[Any]: result = [] for element in value: - if hasattr(self.element_filter, "apply"): + if isinstance(self.element_filter, BaseFilter): result.append(self.element_filter.apply(element)) continue elif isinstance(self.element_filter, list) and all( - hasattr(v, "apply") for v in self.element_filter + isinstance(v, BaseFilter) for v in self.element_filter ): for filter_instance in self.element_filter: element = filter_instance.apply(element) diff --git a/flask_inputfilter/filters/array_explode_filter.py b/flask_inputfilter/filters/array_explode_filter.py index ab5e142..399241e 100644 --- a/flask_inputfilter/filters/array_explode_filter.py +++ b/flask_inputfilter/filters/array_explode_filter.py @@ -12,7 +12,7 @@ class ArrayExplodeFilter(BaseFilter): **Parameters:** - **delimiter** (*str*, default: ``","``): The delimiter used to split - the string. + the string. **Expected Behavior:** diff --git a/flask_inputfilter/filters/base_64_image_downscale_filter.py b/flask_inputfilter/filters/base_64_image_downscale_filter.py index d0a762b..cdf90db 100644 --- a/flask_inputfilter/filters/base_64_image_downscale_filter.py +++ b/flask_inputfilter/filters/base_64_image_downscale_filter.py @@ -17,14 +17,14 @@ class Base64ImageDownscaleFilter(BaseFilter): **Parameters:** - **size** (*Optional[int]*, default: ``1024 * 1024``): A rough pixel - count used to compute default dimensions. + count used to compute default dimensions. - **width** (*Optional[int]*, default: ``size**0.5``): The target width. - If not provided, it is calculated as ``sqrt(size)``. + If not provided, it is calculated as ``sqrt(size)``. - **height** (*Optional[int]*, default: ``size**0.5``): The target height. - If not provided, it is calculated as ``sqrt(size)``. + If not provided, it is calculated as ``sqrt(size)``. - **proportionally** (*bool*, default: ``True``): Determines if the image - should be scaled proportionally. If ``False``, the image is - forcefully resized to the specified width and height. + should be scaled proportionally. If ``False``, the image is + forcefully resized to the specified width and height. **Expected Behavior:** diff --git a/flask_inputfilter/filters/base_64_image_resize_filter.py b/flask_inputfilter/filters/base_64_image_resize_filter.py index 93b4dc3..1a72c9d 100644 --- a/flask_inputfilter/filters/base_64_image_resize_filter.py +++ b/flask_inputfilter/filters/base_64_image_resize_filter.py @@ -18,13 +18,13 @@ class Base64ImageResizeFilter(BaseFilter): **Parameters:** - **max_size** (*int*, default: ``4 * 1024 * 1024``): The maximum - allowed file size in bytes. + allowed file size in bytes. - **format** (*ImageFormatEnum*, default: ``ImageFormatEnum.JPEG``): - The output image format. + The output image format. - **preserve_icc_profile** (*bool*, default: ``False``): If set to - ``True``, the ICC profile is preserved. + ``True``, the ICC profile is preserved. - **preserve_metadata** (*bool*, default: ``False``): If set to ``True``, - image metadata is preserved. + image metadata is preserved. **Expected Behavior:** diff --git a/flask_inputfilter/filters/blacklist_filter.py b/flask_inputfilter/filters/blacklist_filter.py index f8a43d6..4324d97 100644 --- a/flask_inputfilter/filters/blacklist_filter.py +++ b/flask_inputfilter/filters/blacklist_filter.py @@ -12,12 +12,12 @@ class BlacklistFilter(BaseFilter): **Parameters:** - **blacklist** (*list[str]*): A list of substrings (for strings) or keys - (for dictionaries) that should be removed. + (for dictionaries) that should be removed. **Expected Behavior:** - For strings: Removes any occurrence of blacklisted items and trims - whitespace. + whitespace. - For lists: Filters out items present in the blacklist. - For dictionaries: Removes key-value pairs where the key is blacklisted. diff --git a/flask_inputfilter/filters/to_dataclass_filter.py b/flask_inputfilter/filters/to_dataclass_filter.py index 6f53ce2..f514857 100644 --- a/flask_inputfilter/filters/to_dataclass_filter.py +++ b/flask_inputfilter/filters/to_dataclass_filter.py @@ -12,7 +12,7 @@ class ToDataclassFilter(BaseFilter): **Parameters:** - **dataclass_type** (*Type[dict]*): The target dataclass type - that the dictionary should be converted into. + that the dictionary should be converted into. **Expected Behavior:** diff --git a/flask_inputfilter/filters/to_datetime_filter.py b/flask_inputfilter/filters/to_datetime_filter.py index 73a5e9e..9ab3eb0 100644 --- a/flask_inputfilter/filters/to_datetime_filter.py +++ b/flask_inputfilter/filters/to_datetime_filter.py @@ -16,8 +16,7 @@ class ToDateTimeFilter(BaseFilter): - If the input is a datetime, it is returned unchanged. - If the input is a date, it is combined with a minimum time value. - If the input is a string, the filter attempts to parse it as an - ISO 8601 - datetime. + ISO 8601 datetime. - If conversion fails, the original value is returned. **Example Usage:** diff --git a/flask_inputfilter/filters/to_enum_filter.py b/flask_inputfilter/filters/to_enum_filter.py index 4afd88d..9e8ff35 100644 --- a/flask_inputfilter/filters/to_enum_filter.py +++ b/flask_inputfilter/filters/to_enum_filter.py @@ -13,12 +13,12 @@ class ToEnumFilter(BaseFilter): **Parameters:** - **enum_class** (*Type[Enum]*): The enum class to which the - input should be converted. + input should be converted. **Expected Behavior:** - If the input is a string or an integer, the filter attempts to - convert it into the corresponding enum member. + convert it into the corresponding enum member. - If the input is already an enum instance, it is returned as is. - If conversion fails, the original input is returned. diff --git a/flask_inputfilter/filters/to_normalized_unicode_filter.py b/flask_inputfilter/filters/to_normalized_unicode_filter.py index dbb11f4..ee27af0 100644 --- a/flask_inputfilter/filters/to_normalized_unicode_filter.py +++ b/flask_inputfilter/filters/to_normalized_unicode_filter.py @@ -1,6 +1,7 @@ from __future__ import annotations import unicodedata +import warnings from typing import Any, Optional, Union from flask_inputfilter.enums import UnicodeFormEnum @@ -13,16 +14,13 @@ class ToNormalizedUnicodeFilter(BaseFilter): **Parameters:** - - **form** ( - *Union[UnicodeFormEnum, - Literal["NFC", "NFD", "NFKC", "NFKD"]]*, - default: ``UnicodeFormEnum.NFC`` - ): The target Unicode normalization form. + - **form** (*UnicodeFormEnum*, default: ``UnicodeFormEnum.NFC``): + The target Unicode normalization form. **Expected Behavior:** - Removes accent characters and normalizes the string based on the - specified form. + specified form. - Returns non-string inputs unchanged. **Example Usage:** @@ -45,6 +43,12 @@ def __init__( form: Optional[UnicodeFormEnum] = None, ) -> None: if form and not isinstance(form, UnicodeFormEnum): + warnings.warn( + "Directly using a sting is deprecated, use UnicodeFormEnum " + "instead", + DeprecationWarning, + stacklevel=2, + ) form = UnicodeFormEnum(form) self.form = form if form else UnicodeFormEnum.NFC diff --git a/flask_inputfilter/filters/to_pascal_case_filter.py b/flask_inputfilter/filters/to_pascal_case_filter.py index 4f3e96a..be5487b 100644 --- a/flask_inputfilter/filters/to_pascal_case_filter.py +++ b/flask_inputfilter/filters/to_pascal_case_filter.py @@ -13,7 +13,7 @@ class ToPascalCaseFilter(BaseFilter): **Expected Behavior:** - Capitalizes the first letter of each word and concatenates - them without spaces. + them without spaces. - Returns non-string inputs unchanged. **Example Usage:** diff --git a/flask_inputfilter/filters/to_snake_case_filter.py b/flask_inputfilter/filters/to_snake_case_filter.py index 73d4fd8..aa95aec 100644 --- a/flask_inputfilter/filters/to_snake_case_filter.py +++ b/flask_inputfilter/filters/to_snake_case_filter.py @@ -13,8 +13,8 @@ class ToSnakeCaseFilter(BaseFilter): **Expected Behavior:** - Inserts underscores before uppercase letters (except the first), - converts the string to lowercase, and replaces spaces or hyphens - with underscores. + converts the string to lowercase, and replaces spaces or hyphens + with underscores. - Non-string inputs are returned unchanged. **Example Usage:** diff --git a/flask_inputfilter/filters/to_typed_dict_filter.py b/flask_inputfilter/filters/to_typed_dict_filter.py index 7c83acd..4515c3c 100644 --- a/flask_inputfilter/filters/to_typed_dict_filter.py +++ b/flask_inputfilter/filters/to_typed_dict_filter.py @@ -16,7 +16,7 @@ class ToTypedDictFilter(BaseFilter): **Expected Behavior:** - If the input is a dictionary, returns an instance of the specified - TypedDict. + TypedDict. - Otherwise, returns the original value. **Example Usage:** diff --git a/flask_inputfilter/filters/whitelist_filter.py b/flask_inputfilter/filters/whitelist_filter.py index 41495a9..a118a49 100644 --- a/flask_inputfilter/filters/whitelist_filter.py +++ b/flask_inputfilter/filters/whitelist_filter.py @@ -13,15 +13,15 @@ class WhitelistFilter(BaseFilter): **Parameters:** - **whitelist** (*list[str]*, optional): A list of allowed words - or keys. If not provided, no filtering is applied. + or keys. If not provided, no filtering is applied. **Expected Behavior:** - For strings: Splits the input by whitespace and returns only - the words present in the whitelist. + the words present in the whitelist. - For lists: Returns a list of items that are in the whitelist. - For dictionaries: Returns a dictionary containing only the - whitelisted keys. + whitelisted keys. **Example Usage:** diff --git a/flask_inputfilter/filters/whitespace_collapse_filter.py b/flask_inputfilter/filters/whitespace_collapse_filter.py index dd34294..d995b66 100644 --- a/flask_inputfilter/filters/whitespace_collapse_filter.py +++ b/flask_inputfilter/filters/whitespace_collapse_filter.py @@ -13,7 +13,7 @@ class WhitespaceCollapseFilter(BaseFilter): **Expected Behavior:** - Replaces sequences of whitespace with a single space and trims - the result. + the result. - Non-string inputs are returned unchanged. **Example Usage:** diff --git a/flask_inputfilter/input_filter.py b/flask_inputfilter/input_filter.py index a37632d..fdc1d01 100644 --- a/flask_inputfilter/input_filter.py +++ b/flask_inputfilter/input_filter.py @@ -56,16 +56,6 @@ def __init__(self, methods: Optional[list[str]] = None) -> None: self.errors: dict[str, str] = {} self.model_class: Optional[Type[T]] = None - def isValid(self) -> bool: - import warnings - - warnings.warn( - "isValid() is deprecated, use is_valid() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.is_valid() - def is_valid(self) -> bool: """ Checks if the object's state or its attributes meet certain conditions @@ -168,18 +158,6 @@ def wrapper( return decorator - def validateData( - self, data: Optional[dict[str, Any]] = None - ) -> Union[dict[str, Any], Type[T]]: - import warnings - - warnings.warn( - "validateData() is deprecated, use validate_data() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.validate_data(data) - def validate_data( self, data: Optional[dict[str, Any]] = None ) -> Union[dict[str, Any], Type[T]]: @@ -227,27 +205,32 @@ def validate_data( value = data.get(field_name) if field_info.filters or has_global_filters: - filters = field_info.filters - if has_global_filters: - filters = filters + global_filters - value = FieldMixin.apply_filters(filters, value) + value = FieldMixin.apply_filters( + field_info.filters + global_filters + if has_global_filters + else field_info.filters, + value, + ) if field_info.validators or has_global_validators: - validators = field_info.validators - if has_global_validators: - validators = validators + global_validators - result = FieldMixin.validate_field( - validators, field_info.fallback, value + value = ( + FieldMixin.validate_field( + field_info.validators + global_validators + if has_global_validators + else field_info.validators, + field_info.fallback, + value, + ) + or value ) - if result is not None: - value = result if field_info.steps: - result = FieldMixin.apply_steps( - field_info.steps, field_info.fallback, value + value = ( + FieldMixin.apply_steps( + field_info.steps, field_info.fallback, value + ) + or value ) - if result is not None: - value = result if value is None: if field_info.required: @@ -283,16 +266,6 @@ def validate_data( return validated_data - def addCondition(self, condition: BaseCondition) -> None: - import warnings - - warnings.warn( - "addCondition() is deprecated, use add_condition() instead", - DeprecationWarning, - stacklevel=2, - ) - self.add_condition(condition) - def add_condition(self, condition: BaseCondition) -> None: """ Add a condition to the input filter. @@ -302,16 +275,6 @@ def add_condition(self, condition: BaseCondition) -> None: """ self.conditions.append(condition) - def getConditions(self) -> list[BaseCondition]: - import warnings - - warnings.warn( - "getConditions() is deprecated, use get_conditions() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_conditions() - def get_conditions(self) -> list[BaseCondition]: """ Retrieve the list of all registered conditions. @@ -326,16 +289,6 @@ def get_conditions(self) -> list[BaseCondition]: """ return self.conditions - def setData(self, data: dict[str, Any]) -> None: - import warnings - - warnings.warn( - "setData() is deprecated, use set_data() instead", - DeprecationWarning, - stacklevel=2, - ) - self.set_data(data) - def set_data(self, data: dict[str, Any]) -> None: """ Filters and sets the provided data into the object's internal storage, @@ -358,16 +311,6 @@ def set_data(self, data: dict[str, Any]) -> None: self.data[field_name] = field_value - def getValue(self, name: str) -> Any: - import warnings - - warnings.warn( - "getValue() is deprecated, use get_value() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_value(name) - def get_value(self, name: str) -> Any: """ This method retrieves a value associated with the provided name. It @@ -389,16 +332,6 @@ def get_value(self, name: str) -> Any: """ return self.validated_data.get(name) - def getValues(self) -> dict[str, Any]: - import warnings - - warnings.warn( - "getValues() is deprecated, use get_values() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_values() - def get_values(self) -> dict[str, Any]: """ Retrieves a dictionary of key-value pairs from the current object. This @@ -412,16 +345,6 @@ def get_values(self) -> dict[str, Any]: """ return self.validated_data - def getRawValue(self, name: str) -> Any: - import warnings - - warnings.warn( - "getRawValue() is deprecated, use get_raw_value() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_raw_value(name) - def get_raw_value(self, name: str) -> Any: """ Fetches the raw value associated with the provided key. @@ -441,16 +364,6 @@ def get_raw_value(self, name: str) -> Any: """ return self.data.get(name) - def getRawValues(self) -> dict[str, Any]: - import warnings - - warnings.warn( - "getRawValues() is deprecated, use get_raw_values() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_raw_values() - def get_raw_values(self) -> dict[str, Any]: """ Retrieves raw values from a given source and returns them as a @@ -475,17 +388,6 @@ def get_raw_values(self) -> dict[str, Any]: if field in self.data } - def getUnfilteredData(self) -> dict[str, Any]: - import warnings - - warnings.warn( - "getUnfilteredData() is deprecated, use " - "get_unfiltered_data() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_unfiltered_data() - def get_unfiltered_data(self) -> dict[str, Any]: """ Fetches unfiltered data from the data source. @@ -503,17 +405,6 @@ def get_unfiltered_data(self) -> dict[str, Any]: """ return self.data - def setUnfilteredData(self, data: dict[str, Any]) -> None: - import warnings - - warnings.warn( - "setUnfilteredData() is deprecated, use " - "set_unfiltered_data() instead", - DeprecationWarning, - stacklevel=2, - ) - self.set_unfiltered_data(data) - def set_unfiltered_data(self, data: dict[str, Any]) -> None: """ Sets unfiltered data for the current instance. This method assigns a @@ -526,16 +417,6 @@ def set_unfiltered_data(self, data: dict[str, Any]) -> None: """ self.data = data - def hasUnknown(self) -> bool: - import warnings - - warnings.warn( - "hasUnknown() is deprecated, use has_unknown() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.has_unknown() - def has_unknown(self) -> bool: """ Checks whether any values in the current data do not have corresponding @@ -552,16 +433,6 @@ def has_unknown(self) -> bool: for field_name in self.data.keys() ) - def getErrorMessage(self, field_name: str) -> Optional[str]: - import warnings - - warnings.warn( - "getErrorMessage() is deprecated, use get_error_message() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_error_message(field_name) - def get_error_message(self, field_name: str) -> Optional[str]: """ Retrieves and returns a predefined error message. @@ -582,17 +453,6 @@ def get_error_message(self, field_name: str) -> Optional[str]: """ return self.errors.get(field_name) - def getErrorMessages(self) -> dict[str, str]: - import warnings - - warnings.warn( - "getErrorMessages() is deprecated, use " - "get_error_messages() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_error_messages() - def get_error_messages(self) -> dict[str, str]: """ Retrieves all error messages associated with the fields in the input @@ -677,16 +537,6 @@ def has(self, field_name: str) -> bool: """ return field_name in self.fields - def getInput(self, field_name: str) -> Optional[FieldModel]: - import warnings - - warnings.warn( - "getInput() is deprecated, use get_input() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_input(field_name) - def get_input(self, field_name: str) -> Optional[FieldModel]: """ Represents a method to retrieve a field by its name. @@ -706,16 +556,6 @@ def get_input(self, field_name: str) -> Optional[FieldModel]: """ return self.fields.get(field_name) - def getInputs(self) -> dict[str, FieldModel]: - import warnings - - warnings.warn( - "getInputs() is deprecated, use get_inputs() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_inputs() - def get_inputs(self) -> dict[str, FieldModel]: """ Retrieve the dictionary of input fields associated with the object. @@ -807,16 +647,6 @@ def replace( copy=copy, ) - def addGlobalFilter(self, filter: BaseFilter) -> None: - import warnings - - warnings.warn( - "addGlobalFilter() is deprecated, use add_global_filter() instead", - DeprecationWarning, - stacklevel=2, - ) - self.add_global_filter(filter) - def add_global_filter(self, filter: BaseFilter) -> None: """ Add a global filter to be applied to all fields. @@ -826,17 +656,6 @@ def add_global_filter(self, filter: BaseFilter) -> None: """ self.global_filters.append(filter) - def getGlobalFilters(self) -> list[BaseFilter]: - import warnings - - warnings.warn( - "getGlobalFilters() is deprecated, use " - "get_global_filters() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_global_filters() - def get_global_filters(self) -> list[BaseFilter]: """ Retrieve all global filters associated with this InputFilter instance. @@ -880,7 +699,7 @@ def merge(self, other: "InputFilter") -> None: Args: other (InputFilter): The InputFilter instance to merge. """ - if not hasattr(other, "validate_data"): + if not isinstance(other, InputFilter): raise TypeError( "Can only merge with another InputFilter instance." ) @@ -910,16 +729,6 @@ def merge(self, other: "InputFilter") -> None: else: self.global_validators.append(validator) - def setModel(self, model_class: Type[T]) -> None: - import warnings - - warnings.warn( - "setModel() is deprecated, use set_model() instead", - DeprecationWarning, - stacklevel=2, - ) - self.set_model(model_class) - def set_model(self, model_class: Type[T]) -> None: """ Set the model class for serialization. @@ -942,17 +751,6 @@ def serialize(self) -> Union[dict[str, Any], T]: return self.model_class(**self.validated_data) - def addGlobalValidator(self, validator: BaseValidator) -> None: - import warnings - - warnings.warn( - "addGlobalValidator() is deprecated, use " - "add_global_validator() instead", - DeprecationWarning, - stacklevel=2, - ) - self.add_global_validator(validator) - def add_global_validator(self, validator: BaseValidator) -> None: """ Add a global validator to be applied to all fields. @@ -962,17 +760,6 @@ def add_global_validator(self, validator: BaseValidator) -> None: """ self.global_validators.append(validator) - def getGlobalValidators(self) -> list[BaseValidator]: - import warnings - - warnings.warn( - "getGlobalValidators() is deprecated, use " - "get_global_validators() instead", - DeprecationWarning, - stacklevel=2, - ) - return self.get_global_validators() - def get_global_validators(self) -> list[BaseValidator]: """ Retrieve all global validators associated with this InputFilter diff --git a/flask_inputfilter/input_filter.pyi b/flask_inputfilter/input_filter.pyi index 8b8bce4..d03b519 100644 --- a/flask_inputfilter/input_filter.pyi +++ b/flask_inputfilter/input_filter.pyi @@ -24,7 +24,6 @@ class InputFilter: model_class: Optional[Type[T]] def __init__(self, methods: Optional[list[str]] = ...) -> None: ... - def isValid(self) -> bool: ... def is_valid(self) -> bool: ... @classmethod def validate( @@ -36,35 +35,20 @@ class InputFilter: Union[Response, tuple[Any, dict[str, Any]]], ], ]: ... - def validateData( - self, data: Optional[dict[str, Any]] = ... - ) -> Union[dict[str, Any], Type[T]]: ... def validate_data( self, data: Optional[dict[str, Any]] = ... ) -> Union[dict[str, Any], Type[T]]: ... - def addCondition(self, condition: BaseCondition) -> None: ... def add_condition(self, condition: BaseCondition) -> None: ... - def getConditions(self) -> list[BaseCondition]: ... def get_conditions(self) -> list[BaseCondition]: ... - def setData(self, data: dict[str, Any]) -> None: ... def set_data(self, data: dict[str, Any]) -> None: ... - def getValue(self, name: str) -> Any: ... def get_value(self, name: str) -> Any: ... - def getValues(self) -> dict[str, Any]: ... def get_values(self) -> dict[str, Any]: ... - def getRawValue(self, name: str) -> Any: ... def get_raw_value(self, name: str) -> Any: ... - def getRawValues(self) -> dict[str, Any]: ... def get_raw_values(self) -> dict[str, Any]: ... - def getUnfilteredData(self) -> dict[str, Any]: ... def get_unfiltered_data(self) -> dict[str, Any]: ... - def setUnfilteredData(self, data: dict[str, Any]) -> None: ... def set_unfiltered_data(self, data: dict[str, Any]) -> None: ... - def hasUnknown(self) -> bool: ... def has_unknown(self) -> bool: ... - def getErrorMessage(self, field_name: str) -> Optional[str]: ... def get_error_message(self, field_name: str) -> Optional[str]: ... - def getErrorMessages(self) -> dict[str, str]: ... def get_error_messages(self) -> dict[str, str]: ... def add( self, @@ -79,9 +63,7 @@ class InputFilter: copy: Optional[str] = ..., ) -> None: ... def has(self, field_name: str) -> bool: ... - def getInput(self, field_name: str) -> Optional[FieldModel]: ... def get_input(self, field_name: str) -> Optional[FieldModel]: ... - def getInputs(self) -> dict[str, FieldModel]: ... def get_inputs(self) -> dict[str, FieldModel]: ... def remove(self, field_name: str) -> Optional[FieldModel]: ... def count(self) -> int: ... @@ -97,16 +79,11 @@ class InputFilter: external_api: Optional[ExternalApiConfig] = ..., copy: Optional[str] = ..., ) -> None: ... - def addGlobalFilter(self, filter: BaseFilter) -> None: ... def add_global_filter(self, filter: BaseFilter) -> None: ... - def getGlobalFilters(self) -> list[BaseFilter]: ... def get_global_filters(self) -> list[BaseFilter]: ... def clear(self) -> None: ... def merge(self, other: InputFilter) -> None: ... - def setModel(self, model_class: Type[T]) -> None: ... def set_model(self, model_class: Type[T]) -> None: ... def serialize(self) -> Union[dict[str, Any], T]: ... - def addGlobalValidator(self, validator: BaseValidator) -> None: ... def add_global_validator(self, validator: BaseValidator) -> None: ... - def getGlobalValidators(self) -> list[BaseValidator]: ... def get_global_validators(self) -> list[BaseValidator]: ... diff --git a/flask_inputfilter/mixins/_external_api_mixin.pyx b/flask_inputfilter/mixins/_external_api_mixin.pyx index e38a30c..34e8aa6 100644 --- a/flask_inputfilter/mixins/_external_api_mixin.pyx +++ b/flask_inputfilter/mixins/_external_api_mixin.pyx @@ -1,74 +1,16 @@ # cython: language=c++ -# cython: language_level=3 -# cython: binding=True -# cython: cdivision=True -# cython: boundscheck=False -# cython: initializedcheck=False import re -from typing import Any, Dict, Optional from flask_inputfilter.exceptions import ValidationError -from flask_inputfilter.models import ExternalApiConfig cdef class ExternalApiMixin: - @staticmethod - cdef str replace_placeholders( - str value, - dict validated_data - ): - """ - Replace all placeholders, marked with '{{ }}' in value - with the corresponding values from validated_data. - - Params: - value (str): The string containing placeholders to be replaced. - validated_data (dict[str, Any]): The dictionary containing - the values to replace the placeholders with. - - Returns: - str: The value with all placeholders replaced with - the corresponding values from validated_data. - """ - return re.compile(r"{{(.*?)}}").sub( - lambda match: str(validated_data.get(match.group(1))), - value, - ) - - @staticmethod - cdef dict replace_placeholders_in_params( - dict params, dict validated_data - ): - """ - Replace all placeholders in params with the corresponding - values from validated_data. - - Params: - params (dict): The params dictionary containing placeholders. - validated_data (dict[str, Any]): The dictionary containing - the values to replace the placeholders with. - - Returns: - dict: The params dictionary with all placeholders replaced - with the corresponding values from validated_data. - """ - return { - key: ExternalApiMixin.replace_placeholders(value, validated_data) - if isinstance(value, str) - else value - for key, value in params.items() - } - @staticmethod cdef object call_external_api( - object config, object fallback, dict validated_data + object config, object fallback, dict validated_data ): """ - Makes a call to an external API using provided configuration and - returns the response. - - Summary: The function constructs a request based on the given API configuration and validated data, including headers, parameters, and other request settings. It utilizes the `requests` library @@ -77,25 +19,28 @@ cdef class ExternalApiMixin: the API call. If no fallback is provided, a validation error is raised. - Parameters: - config (ExternalApiConfig): - An object containing the configuration details for the - external API call, such as URL, headers, method, and API key. - fallback (Any): - The value to be returned in case the external API call fails. - validated_data (dict[str, Any]): - The dictionary containing data used to replace placeholders - in the URL and parameters of the API request. - - Returns: - Optional[Any]: - The JSON-decoded response from the API, or the fallback - value if the call fails and a fallback is provided. - - Raises: - ValidationError - Raised if the external API call does not succeed and no - fallback value is provided. + **Parameters:** + + - **config** (*ExternalApiConfig*): + An object containing the configuration details for the + external API call, such as URL, headers, method, and API key. + - **fallback** (*Any*): + The value to be returned in case the external API call fails. + - **validated_data** (*dict[str, Any]*): + The dictionary containing data used to replace placeholders + in the URL and parameters of the API request. + + **Returns:** + + - (*Optional[Any]*): + The JSON-decoded response from the API, or the fallback + value if the call fails and a fallback is provided. + + **Raises:** + + - **ValidationError**: + Raised if the external API call does not succeed and no + fallback value is provided. """ import logging @@ -160,3 +105,54 @@ cdef class ExternalApiMixin: return fallback return result.get(data_key) if data_key else result + + @staticmethod + cdef inline str replace_placeholders( + str value, + dict validated_data + ): + """ + Replace all placeholders, marked with '{{ }}' in value + with the corresponding values from validated_data. + + **Parameters:** + + - **value** (**str**): The string containing placeholders to be replaced. + - **validated_data** (**dict[str, Any]**): The dictionary containing + the values to replace the placeholders with. + + **Returns:** + + - (*str*): The value with all placeholders replaced with + the corresponding values from validated_data. + """ + return re.compile(r"{{(.*?)}}").sub( + lambda match: str(validated_data.get(match.group(1))), + value, + ) + + @staticmethod + cdef dict replace_placeholders_in_params( + dict params, dict validated_data + ): + """ + Replace all placeholders in params with the corresponding + values from validated_data. + + **Parameters:** + + - **params** (*dict*): The params dictionary containing placeholders. + - **validated_data** (*dict[str, Any]*): The dictionary containing + the values to replace the placeholders with. + + **Returns:** + + - (*dict*): The params dictionary with all placeholders replaced + with the corresponding values from validated_data. + """ + return { + key: ExternalApiMixin.replace_placeholders(value, validated_data) + if isinstance(value, str) + else value + for key, value in params.items() + } diff --git a/flask_inputfilter/mixins/_field_mixin.pyx b/flask_inputfilter/mixins/_field_mixin.pyx index 6411973..b8f9629 100644 --- a/flask_inputfilter/mixins/_field_mixin.pyx +++ b/flask_inputfilter/mixins/_field_mixin.pyx @@ -1,4 +1,7 @@ -from typing import Any, Union +# cython: language=c++ +from typing import Union + +import cython from flask_inputfilter.conditions import BaseCondition from flask_inputfilter.exceptions import ValidationError @@ -7,25 +10,35 @@ from flask_inputfilter.validators import BaseValidator cdef class FieldMixin: + @staticmethod + @cython.exceptval(check=False) cdef object apply_filters(list filters, object value): """ Apply filters to the field value. - Args: - filters (list[BaseFilter]): A list of filters to apply to the - value. - value (Any): The value to be processed by the filters. + **Parameters:** + + - **filters** (*list[BaseFilter]*): A list of filters to apply to the + value. + - **value** (*Any*): The value to be processed by the filters. - Returns: - Any: The processed value after applying all filters. - If the value is None, None is returned. + **Returns:** + + - (*Any*): The processed value after applying all filters. + If the value is None, None is returned. """ if value is None: return None - for filter in filters: - value = filter.apply(value) + cdef: + int i + int n = len(filters) + object current_filter + + for i in range(n): + current_filter = filters[i] + value = current_filter.apply(value) return value @@ -44,32 +57,41 @@ cdef class FieldMixin: and a fallback value is provided, the fallback is returned. Otherwise, the validation error is raised. - Args: - steps (list[Union[BaseFilter, BaseValidator]]): - A list of filters and validators to be applied in order. - fallback (Any): - A fallback value to return if validation fails. - value (Any): - The initial value to be processed. - - Returns: - Any: The processed value after applying all filters and validators. - If a validation error occurs and a fallback is provided, the - fallback value is returned. - - Raises: - ValidationError: If validation fails and no fallback value is - provided. + **Parameters:** + + - **steps** (*list[Union[BaseFilter, BaseValidator]]*): + A list of filters and validators to be applied in order. + - **fallback** (*Any*): + A fallback value to return if validation fails. + - **value** (*Any*): + The initial value to be processed. + + **Returns:** + + - (*Any*): The processed value after applying all filters and + validators. If a validation error occurs and a fallback is + provided, the fallback value is returned. + + **Raises:** + + - **ValidationError:** If validation fails and no fallback value is + provided. """ if value is None: return None + cdef: + int i + int n = len(steps) + object current_step + try: - for step in steps: - if hasattr(step, 'apply'): - value = step.apply(value) - elif hasattr(step, 'validate'): - step.validate(value) + for i in range(n): + current_step = steps[i] + if isinstance(current_step, BaseFilter): + value = current_step.apply(value) + elif isinstance(current_step, BaseValidator): + current_step.validate(value) except ValidationError: if fallback is None: raise @@ -86,20 +108,28 @@ cdef class FieldMixin: condition is not met, a ValidationError is raised with an appropriate message indicating which condition failed. - Args: - conditions (list[BaseCondition]): - A list of conditions to be checked against the validated data. - validated_data (dict[str, Any]): - The validated data to check against the conditions. + **Parameters:** + + - **conditions** (*list[BaseCondition]*): + A list of conditions to be checked against the validated data. + - **validated_data** (*dict[str, Any]*): + The validated data to check against the conditions. """ - for condition in conditions: - if not condition.check(validated_data): + cdef: + int i + int n = len(conditions) + object current_condition + + for i in range(n): + current_condition = conditions[i] + if not current_condition.check(validated_data): raise ValidationError( - f"Condition '{condition.__class__.__name__}' not met." + f"Condition '{current_condition.__class__.__name__}' " + f"not met." ) @staticmethod - cdef object check_for_required( + cdef inline object check_for_required( str field_name, bint required, object default, @@ -115,18 +145,25 @@ cdef class FieldMixin: the fallback value is returned. If no of the above conditions are met, a ValidationError is raised. - Args: - field_name (str): The name of the field being processed. - required (bool): Indicates whether the field is required. - default (Any): The default value to use if the field is not provided and not required. - fallback (Any): The fallback value to use if the field is required but not provided. - value (Any): The current value of the field being processed. - - Returns: - Any: The determined value of the field after considering required, default, and fallback attributes. - - Raises: - ValidationError: If the field is required and no value or fallback is provided. + **Parameters:** + + - **field_name** (*str*): The name of the field being processed. + - **required** (*bool*): Indicates whether the field is required. + - **default** (*Any*): The default value to use if the field is not + provided and not required. + - **fallback** (*Any*): The fallback value to use if the field is + required but not provided. + - **value** (*Any*): The current value of the field being processed. + + **Returns:** + + - (*Any*): The determined value of the field after considering + required, default, and fallback attributes. + + **Raises:** + + - **ValidationError**: + If the field is required and no value or fallback is provided. """ if value is not None: return value @@ -146,23 +183,31 @@ cdef class FieldMixin: """ Validate the field value. - Args: - validators (list[BaseValidator]): A list of validators to apply - to the field value. - fallback (Any): A fallback value to return if validation fails. - value (Any): The value to be validated. - - Returns: - Any: The validated value if all validators pass. If validation - fails and a fallback is provided, the fallback value is - returned. + **Parameters:** + + - **validators** (*list[BaseValidator]*): A list of validators to + apply to the field value. + - **fallback** (*Any*): A fallback value to return if validation + fails. + - **value** (*Any*): The value to be validated. + + **Returns:** + + - (*Any*): The validated value if all validators pass. If validation + fails and a fallback is provided, the fallback value is returned. """ if value is None: return None + cdef: + int i + int n = len(validators) + object current_validator + try: - for validator in validators: - validator.validate(value) + for i in range(n): + current_validator = validators[i] + current_validator.validate(value) except ValidationError: if fallback is None: raise diff --git a/flask_inputfilter/mixins/external_api_mixin.py b/flask_inputfilter/mixins/external_api_mixin.py index c5f58c4..86824f0 100644 --- a/flask_inputfilter/mixins/external_api_mixin.py +++ b/flask_inputfilter/mixins/external_api_mixin.py @@ -8,6 +8,8 @@ class ExternalApiMixin: + __slots__ = () + @staticmethod def call_external_api( config: ExternalApiConfig, @@ -15,37 +17,35 @@ def call_external_api( validated_data: dict[str, Any], ) -> Optional[Any]: """ - Makes a call to an external API using provided configuration and - returns the response. - - Summary: - The function constructs a request based on the given API - configuration and validated data, including headers, parameters, - and other request settings. It utilizes the `requests` library - to send the API call and processes the response. If a fallback - value is supplied, it is returned in case of any failure during - the API call. If no fallback is provided, a validation error is - raised. - - Parameters: - config (ExternalApiConfig): - An object containing the configuration details for the - external API call, such as URL, headers, method, and API key. - fallback (Any): - The value to be returned in case the external API call fails. - validated_data (dict[str, Any]): - The dictionary containing data used to replace placeholders - in the URL and parameters of the API request. - - Returns: - Optional[Any]: - The JSON-decoded response from the API, or the fallback - value if the call fails and a fallback is provided. - - Raises: - ValidationError - Raised if the external API call does not succeed and no - fallback value is provided. + The function constructs a request based on the given API configuration + and validated data, including headers, parameters, and other request + settings. It utilizes the `requests` library to send the API call and + processes the response. If a fallback value is supplied, it is returned + in case of any failure during the API call. If no fallback is provided, + a validation error is raised. + + **Parameters:** + + - **config** (*ExternalApiConfig*): + An object containing the configuration details for the + external API call, such as URL, headers, method, and API key. + - **fallback** (*Any*): + The value to be returned in case the external API call fails. + - **validated_data** (*dict[str, Any]*): + The dictionary containing data used to replace placeholders + in the URL and parameters of the API request. + + **Returns:** + + - (*Optional[Any]*): + The JSON-decoded response from the API, or the fallback + value if the call fails and a fallback is provided. + + **Raises:** + + - **ValidationError**: + Raised if the external API call does not succeed and no + fallback value is provided. """ import logging @@ -121,14 +121,17 @@ def replace_placeholders( Replace all placeholders, marked with '{{ }}' in value with the corresponding values from validated_data. - Params: - value (str): The string containing placeholders to be replaced. - validated_data (dict[str, Any]): The dictionary containing - the values to replace the placeholders with. + **Parameters:** + + - **value** (**str**): The string containing placeholders to + be replaced. + - **validated_data** (**dict[str, Any]**): The dictionary containing + the values to replace the placeholders with. + + **Returns:** - Returns: - str: The value with all placeholders replaced with - the corresponding values from validated_data. + - (*str*): The value with all placeholders replaced with + the corresponding values from validated_data. """ return re.compile(r"{{(.*?)}}").sub( lambda match: str(validated_data.get(match.group(1))), @@ -143,14 +146,16 @@ def replace_placeholders_in_params( Replace all placeholders in params with the corresponding values from validated_data. - Params: - params (dict): The params dictionary containing placeholders. - validated_data (dict[str, Any]): The dictionary containing - the values to replace the placeholders with. + **Parameters:** + + - **params** (*dict*): The params dictionary containing placeholders. + - **validated_data** (*dict[str, Any]*): The dictionary containing + the values to replace the placeholders with. + + **Returns:** - Returns: - dict: The params dictionary with all placeholders replaced - with the corresponding values from validated_data. + - (*dict*): The params dictionary with all placeholders replaced + with the corresponding values from validated_data. """ return { key: ExternalApiMixin.replace_placeholders(value, validated_data) diff --git a/flask_inputfilter/mixins/field_mixin.py b/flask_inputfilter/mixins/field_mixin.py index 50fe30e..0e20150 100644 --- a/flask_inputfilter/mixins/field_mixin.py +++ b/flask_inputfilter/mixins/field_mixin.py @@ -9,19 +9,23 @@ class FieldMixin: + __slots__ = () + @staticmethod def apply_filters(filters: list[BaseFilter], value: Any) -> Any: """ Apply filters to the field value. - Args: - filters (list[BaseFilter]): A list of filters to apply to the - value. - value (Any): The value to be processed by the filters. + **Parameters:** + + - **filters** (*list[BaseFilter]*): A list of filters to apply to the + value. + - **value** (*Any*): The value to be processed by the filters. - Returns: - Any: The processed value after applying all filters. - If the value is None, None is returned. + **Returns:** + + - (*Any*): The processed value after applying all filters. + If the value is None, None is returned. """ if value is None: return None @@ -38,16 +42,18 @@ def validate_field( """ Validate the field value. - Args: - validators (list[BaseValidator]): A list of validators to apply - to the field value. - fallback (Any): A fallback value to return if validation fails. - value (Any): The value to be validated. + **Parameters:** + + - **validators** (*list[BaseValidator]*): A list of validators to + apply to the field value. + - **fallback** (*Any*): A fallback value to return if validation + fails. + - **value** (*Any*): The value to be validated. - Returns: - Any: The validated value if all validators pass. If validation - fails and a fallback is provided, the fallback value is - returned. + **Returns:** + + - (*Any*): The validated value if all validators pass. If validation + fails and a fallback is provided, the fallback value is returned. """ if value is None: return None @@ -76,31 +82,34 @@ def apply_steps( and a fallback value is provided, the fallback is returned. Otherwise, the validation error is raised. - Args: - steps (list[Union[BaseFilter, BaseValidator]]): - A list of filters and validators to be applied in order. - fallback (Any): - A fallback value to return if validation fails. - value (Any): - The initial value to be processed. - - Returns: - Any: The processed value after applying all filters and validators. - If a validation error occurs and a fallback is provided, the - fallback value is returned. - - Raises: - ValidationError: If validation fails and no fallback value is - provided. + **Parameters:** + + - **steps** (*list[Union[BaseFilter, BaseValidator]]*): + A list of filters and validators to be applied in order. + - **fallback** (*Any*): + A fallback value to return if validation fails. + - **value** (*Any*): + The initial value to be processed. + + **Returns:** + + - (*Any*): The processed value after applying all filters and + validators. If a validation error occurs and a fallback is + provided, the fallback value is returned. + + **Raises:** + + - **ValidationError:** If validation fails and no fallback value is + provided. """ if value is None: return None try: for step in steps: - if hasattr(step, "apply"): + if isinstance(step, BaseFilter): value = step.apply(value) - elif hasattr(step, "validate"): + elif isinstance(step, BaseValidator): step.validate(value) except ValidationError: if fallback is None: @@ -120,11 +129,12 @@ def check_conditions( condition is not met, a ValidationError is raised with an appropriate message indicating which condition failed. - Args: - conditions (list[BaseCondition]): - A list of conditions to be checked against the validated - validated_data (dict[str, Any]): - The validated data to check against the conditions. + **Parameters:** + + - **conditions** (*list[BaseCondition]*): + A list of conditions to be checked against the validated data. + - **validated_data** (*dict[str, Any]*): + The validated data to check against the conditions. """ for condition in conditions: if not condition.check(validated_data): @@ -149,22 +159,25 @@ def check_for_required( the fallback value is returned. If no of the above conditions are met, a ValidationError is raised. - Args: - field_name (str): The name of the field being processed. - required (bool): Indicates whether the field is required. - default (Any): The default value to use if the field is not - provided and not required. - fallback (Any): The fallback value to use if the field is required - but not provided. - value (Any): The current value of the field being processed. - - Returns: - Any: The determined value of the field after considering required, - default, and fallback attributes. - - Raises: - ValidationError: If the field is required and no value or fallback - is provided. + **Parameters:** + + - **field_name** (*str*): The name of the field being processed. + - **required** (*bool*): Indicates whether the field is required. + - **default** (*Any*): The default value to use if the field is not + provided and not required. + - **fallback** (*Any*): The fallback value to use if the field is + required but not provided. + - **value** (*Any*): The current value of the field being processed. + + **Returns:** + + - (*Any*): The determined value of the field after considering + required, default, and fallback attributes. + + **Raises:** + + - **ValidationError**: + If the field is required and no value or fallback is provided. """ if value is not None: return value diff --git a/flask_inputfilter/models/_field_model.pyx b/flask_inputfilter/models/_field_model.pyx index ee5aea8..9e5bbe8 100644 --- a/flask_inputfilter/models/_field_model.pyx +++ b/flask_inputfilter/models/_field_model.pyx @@ -1,18 +1,14 @@ # cython: language=c++ -# cython: language_level=3 -# cython: binding=True -# cython: cdivision=True -# cython: boundscheck=False -# cython: initializedcheck=False +# cython: freelist=256 from __future__ import annotations -from typing import Any, Optional, Union +import cython -from flask_inputfilter.filters import BaseFilter -from flask_inputfilter.models import ExternalApiConfig -from flask_inputfilter.validators import BaseValidator +cdef list EMPTY_LIST = [] + +@cython.final cdef class FieldModel: """ FieldModel is a dataclass that represents a field in the input data. @@ -37,20 +33,20 @@ cdef class FieldModel: def __init__( self, - required: bool = False, - default: Any = None, - fallback: Any = None, - filters: list[BaseFilter] = None, - validators: list[BaseValidator] = None, - steps: list[Union[BaseFilter, BaseValidator]] = None, - external_api: Optional[ExternalApiConfig] = None, - copy: Optional[str] = None + bint required = False, + object default = None, + object fallback = None, + list filters = None, + list validators = None, + list steps = None, + object external_api = None, + str copy = None ) -> None: self.required = required - self.default = default + self._default = default self.fallback = fallback - self.filters = filters or [] - self.validators = validators or [] - self.steps = steps or [] + self.filters = filters if filters is not None else EMPTY_LIST + self.validators = validators if validators is not None else EMPTY_LIST + self.steps = steps if steps is not None else EMPTY_LIST self.external_api = external_api self.copy = copy diff --git a/flask_inputfilter/models/external_api_config.py b/flask_inputfilter/models/external_api_config.py index 6fabb72..f7b39f6 100644 --- a/flask_inputfilter/models/external_api_config.py +++ b/flask_inputfilter/models/external_api_config.py @@ -9,12 +9,15 @@ class ExternalApiConfig: """ Configuration for an external API call. - :param url: The URL of the external API. - :param method: The HTTP method to use. - :param params: The parameters to send to the API. - :param data_key: The key in the response JSON to use - :param api_key: The API key to use. - :param headers: The headers to send to the API. + **Parameters:** + + - **url** (*str*): The URL of the external API. + - **method** (*str*): The HTTP method to use. + - **params** (*Optional[dict[str, str]]*): The parameters to send to + the API. + - **data_key** (*Optional[str]*): The key in the response JSON to use + - **api_key** (*Optional[str]*): The API key to use. + - **headers** (*Optional[dict[str, str]]*): The headers to send to the API. """ url: str diff --git a/flask_inputfilter/validators/and_validator.py b/flask_inputfilter/validators/and_validator.py index 1faf7c7..cf90352 100644 --- a/flask_inputfilter/validators/and_validator.py +++ b/flask_inputfilter/validators/and_validator.py @@ -14,9 +14,9 @@ class AndValidator(BaseValidator): **Parameters:** - **validators** (*list[BaseValidator]*): A list of validators that must - all pass. + all pass. - **error_message** (*Optional[str]*): Custom error message if any of the - validators fail. + validators fail. **Expected Behavior:** diff --git a/flask_inputfilter/validators/array_element_validator.py b/flask_inputfilter/validators/array_element_validator.py index 75d41ff..cb3f36d 100644 --- a/flask_inputfilter/validators/array_element_validator.py +++ b/flask_inputfilter/validators/array_element_validator.py @@ -19,9 +19,9 @@ class ArrayElementValidator(BaseValidator): **Parameters:** - **elementFilter** (*InputFilter* | *BaseValidator* | - *list[BaseValidator]*): An instance used to validate each element. + *list[BaseValidator]*): An instance used to validate each element. - **error_message** (*Optional[str]*): Custom error message for validation - failure. + failure. **Expected Behavior:** diff --git a/flask_inputfilter/validators/array_length_validator.py b/flask_inputfilter/validators/array_length_validator.py index 2651aae..e1069b4 100644 --- a/flask_inputfilter/validators/array_length_validator.py +++ b/flask_inputfilter/validators/array_length_validator.py @@ -13,11 +13,11 @@ class ArrayLengthValidator(BaseValidator): **Parameters:** - **min_length** (*int*, default: 0): The minimum number of - elements required. + elements required. - **max_length** (*int*, default: infinity): The maximum number - of allowed elements. + of allowed elements. - **error_message** (*Optional[str]*): Custom error message if the - length check fails. + length check fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/custom_json_validator.py b/flask_inputfilter/validators/custom_json_validator.py index 14b4fd7..ca7bcc4 100644 --- a/flask_inputfilter/validators/custom_json_validator.py +++ b/flask_inputfilter/validators/custom_json_validator.py @@ -16,11 +16,11 @@ class CustomJsonValidator(BaseValidator): **Parameters:** - **required_fields** (*list*, default: []): Fields that must exist - in the JSON. + in the JSON. - **schema** (*dict*, default: {}): A dictionary specifying expected - types for certain fields. + types for certain fields. - **error_message** (*Optional[str]*): Custom error message if validation - fails. + fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/date_after_validator.py b/flask_inputfilter/validators/date_after_validator.py index e5c876e..ce9fc12 100644 --- a/flask_inputfilter/validators/date_after_validator.py +++ b/flask_inputfilter/validators/date_after_validator.py @@ -16,9 +16,9 @@ class DateAfterValidator(BaseValidator): **Parameters:** - **reference_date** (*Union[str, date, datetime]*): The date that the - input must be later than. + input must be later than. - **error_message** (*Optional[str]*): Custom error message if the - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/date_before_validator.py b/flask_inputfilter/validators/date_before_validator.py index 8630eb0..5105941 100644 --- a/flask_inputfilter/validators/date_before_validator.py +++ b/flask_inputfilter/validators/date_before_validator.py @@ -16,9 +16,9 @@ class DateBeforeValidator(BaseValidator): **Parameters:** - **reference_date** (*Union[str, date, datetime]*): The date that the - input must be earlier than. + input must be earlier than. - **error_message** (*Optional[str]*): Custom error message if validation - fails. + fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/date_range_validator.py b/flask_inputfilter/validators/date_range_validator.py index 3dc1ccb..d78ed6d 100644 --- a/flask_inputfilter/validators/date_range_validator.py +++ b/flask_inputfilter/validators/date_range_validator.py @@ -15,11 +15,11 @@ class DateRangeValidator(BaseValidator): **Parameters:** - **min_date** (*Optional[Union[str, date, datetime]]*): The lower bound - of the date range. + of the date range. - **max_date** (*Optional[Union[str, date, datetime]]*): The upper bound - of the date range. + of the date range. - **error_message** (*Optional[str]*): Custom error message if the date - is outside the range. + is outside the range. **Expected Behavior:** diff --git a/flask_inputfilter/validators/float_precision_validator.py b/flask_inputfilter/validators/float_precision_validator.py index 808ba5e..aa2392b 100644 --- a/flask_inputfilter/validators/float_precision_validator.py +++ b/flask_inputfilter/validators/float_precision_validator.py @@ -16,9 +16,9 @@ class FloatPrecisionValidator(BaseValidator): - **precision** (*int*): The maximum total number of digits allowed. - **scale** (*int*): The maximum number of digits allowed after the - decimal point. + decimal point. - **error_message** (*Optional[str]*): Custom error message if - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/in_array_validator.py b/flask_inputfilter/validators/in_array_validator.py index 6f24558..abe72ee 100644 --- a/flask_inputfilter/validators/in_array_validator.py +++ b/flask_inputfilter/validators/in_array_validator.py @@ -15,9 +15,9 @@ class InArrayValidator(BaseValidator): - **haystack** (*list[Any]*): The list of allowed values. - **strict** (*bool*, default: False): When ``True``, also checks that - the type of the value matches the types in the allowed list. + the type of the value matches the types in the allowed list. - **error_message** (*Optional[str]*): Custom error message if - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/in_enum_validator.py b/flask_inputfilter/validators/in_enum_validator.py index 0e580e6..48e3ef2 100644 --- a/flask_inputfilter/validators/in_enum_validator.py +++ b/flask_inputfilter/validators/in_enum_validator.py @@ -1,6 +1,5 @@ from __future__ import annotations -import warnings from enum import Enum from typing import Any, Optional, Type @@ -16,7 +15,7 @@ class InEnumValidator(BaseValidator): - **enumClass** (*Type[Enum]*): The Enum to validate against. - **error_message** (*Optional[str]*): Custom error message if - validation fails. + validation fails. **Expected Behavior:** @@ -50,19 +49,7 @@ def __init__( self, enum_class: Type[Enum], error_message: Optional[str] = None, - # Deprecated parameters (for Backward Compatibility) - enumClass: Type[Enum] = None, ) -> None: - if enumClass is not None: - warnings.warn( - "Parameter 'enumClass' is deprecated, use 'enum_class' " - "instead", - DeprecationWarning, - stacklevel=2, - ) - if enum_class is None: - enum_class = enumClass - self.enum_class = enum_class self.error_message = error_message diff --git a/flask_inputfilter/validators/is_array_validator.py b/flask_inputfilter/validators/is_array_validator.py index 2a6c2b5..32e341c 100644 --- a/flask_inputfilter/validators/is_array_validator.py +++ b/flask_inputfilter/validators/is_array_validator.py @@ -13,7 +13,7 @@ class IsArrayValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_base_64_image_correct_size_validator.py b/flask_inputfilter/validators/is_base_64_image_correct_size_validator.py index f3e513f..79eb89c 100644 --- a/flask_inputfilter/validators/is_base_64_image_correct_size_validator.py +++ b/flask_inputfilter/validators/is_base_64_image_correct_size_validator.py @@ -2,7 +2,6 @@ import base64 import binascii -import warnings from typing import Any, Optional from flask_inputfilter.exceptions import ValidationError @@ -16,12 +15,12 @@ class IsBase64ImageCorrectSizeValidator(BaseValidator): **Parameters:** - - **minSize** (*int*, default: 1): The minimum allowed size - in bytes. - - **maxSize** (*int*, default: 4 * 1024 * 1024): The maximum - allowed size in bytes. + - **min_size** (*int*, default: 1): The minimum allowed size + in bytes. + - **max_size** (*int*, default: 4 * 1024 * 1024): The maximum + allowed size in bytes. - **error_message** (*Optional[str]*): Custom error message - if validation fails. + if validation fails. **Expected Behavior:** @@ -51,28 +50,7 @@ def __init__( min_size: Optional[int] = None, max_size: Optional[int] = None, error_message: Optional[str] = None, - # Deprecated parameters (for Backward Compatibility) - minSize: Optional[int] = None, - maxSize: Optional[int] = None, ) -> None: - if minSize is not None: - warnings.warn( - "Parameter 'minSize' is deprecated, use 'min_size' instead", - DeprecationWarning, - stacklevel=2, - ) - if min_size is None: - min_size = minSize - - if maxSize is not None: - warnings.warn( - "Parameter 'maxSize' is deprecated, use 'max_size' instead", - DeprecationWarning, - stacklevel=2, - ) - if max_size is None: - max_size = maxSize - self.min_size = min_size if min_size is not None else 1 self.max_size = max_size if max_size is not None else 4 * 1024 * 1024 self.error_message = error_message diff --git a/flask_inputfilter/validators/is_base_64_image_validator.py b/flask_inputfilter/validators/is_base_64_image_validator.py index d4b3301..98dbdfb 100644 --- a/flask_inputfilter/validators/is_base_64_image_validator.py +++ b/flask_inputfilter/validators/is_base_64_image_validator.py @@ -19,7 +19,7 @@ class IsBase64ImageValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_boolean_validator.py b/flask_inputfilter/validators/is_boolean_validator.py index 45193e6..9eb19ef 100644 --- a/flask_inputfilter/validators/is_boolean_validator.py +++ b/flask_inputfilter/validators/is_boolean_validator.py @@ -13,7 +13,7 @@ class IsBooleanValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - input is not a bool. + input is not a bool. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_dataclass_validator.py b/flask_inputfilter/validators/is_dataclass_validator.py index 9d4efb1..f50b844 100644 --- a/flask_inputfilter/validators/is_dataclass_validator.py +++ b/flask_inputfilter/validators/is_dataclass_validator.py @@ -43,7 +43,7 @@ class IsDataclassValidator(BaseValidator): - **dataclass_type** (*Type[dict]*): The expected dataclass type. - **error_message** (*Optional[str]*): Custom error message if - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_date_validator.py b/flask_inputfilter/validators/is_date_validator.py index 4c21f71..ff38f16 100644 --- a/flask_inputfilter/validators/is_date_validator.py +++ b/flask_inputfilter/validators/is_date_validator.py @@ -14,7 +14,7 @@ class IsDateValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a date. + value is not a date. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_datetime_validator.py b/flask_inputfilter/validators/is_datetime_validator.py index 2896c01..991002e 100644 --- a/flask_inputfilter/validators/is_datetime_validator.py +++ b/flask_inputfilter/validators/is_datetime_validator.py @@ -14,7 +14,7 @@ class IsDateTimeValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a datetime. + value is not a datetime. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_float_validator.py b/flask_inputfilter/validators/is_float_validator.py index 1b1bf0b..e866991 100644 --- a/flask_inputfilter/validators/is_float_validator.py +++ b/flask_inputfilter/validators/is_float_validator.py @@ -13,7 +13,7 @@ class IsFloatValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a float. + value is not a float. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_future_date_validator.py b/flask_inputfilter/validators/is_future_date_validator.py index 95969f4..24e0605 100644 --- a/flask_inputfilter/validators/is_future_date_validator.py +++ b/flask_inputfilter/validators/is_future_date_validator.py @@ -16,7 +16,7 @@ class IsFutureDateValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - date is not in the future. + date is not in the future. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_hexadecimal_validator.py b/flask_inputfilter/validators/is_hexadecimal_validator.py index f639c28..0322474 100644 --- a/flask_inputfilter/validators/is_hexadecimal_validator.py +++ b/flask_inputfilter/validators/is_hexadecimal_validator.py @@ -14,7 +14,7 @@ class IsHexadecimalValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a valid hexadecimal string. + value is not a valid hexadecimal string. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_horizontal_image_validator.py b/flask_inputfilter/validators/is_horizontal_image_validator.py index 059b0ac..8d635cb 100644 --- a/flask_inputfilter/validators/is_horizontal_image_validator.py +++ b/flask_inputfilter/validators/is_horizontal_image_validator.py @@ -19,7 +19,7 @@ class IsHorizontalImageValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the image - is not horizontally oriented. + is not horizontally oriented. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_html_validator.py b/flask_inputfilter/validators/is_html_validator.py index 4f7bde9..ffb93de 100644 --- a/flask_inputfilter/validators/is_html_validator.py +++ b/flask_inputfilter/validators/is_html_validator.py @@ -15,7 +15,7 @@ class IsHtmlValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the value - does not contain valid HTML. + does not contain valid HTML. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_instance_validator.py b/flask_inputfilter/validators/is_instance_validator.py index 7e78d86..12c0806 100644 --- a/flask_inputfilter/validators/is_instance_validator.py +++ b/flask_inputfilter/validators/is_instance_validator.py @@ -1,6 +1,5 @@ from __future__ import annotations -import warnings from typing import Any, Optional, Type from flask_inputfilter.exceptions import ValidationError @@ -14,9 +13,9 @@ class IsInstanceValidator(BaseValidator): **Parameters:** - **classType** (*Type[Any]*): The class against which the value is - validated. + validated. - **error_message** (*Optional[str]*): Custom error message if the - validation fails. + validation fails. **Expected Behavior:** @@ -44,18 +43,7 @@ def __init__( self, class_type: Type[Any], error_message: Optional[str] = None, - classType: Type[Any] = None, ) -> None: - if classType is not None: - warnings.warn( - "Parameter 'classType' is deprecated, use 'class_type' " - "instead", - DeprecationWarning, - stacklevel=2, - ) - if class_type is None: - class_type = classType - self.class_type = class_type self.error_message = error_message diff --git a/flask_inputfilter/validators/is_integer_validator.py b/flask_inputfilter/validators/is_integer_validator.py index 1a9c813..e0e501f 100644 --- a/flask_inputfilter/validators/is_integer_validator.py +++ b/flask_inputfilter/validators/is_integer_validator.py @@ -13,7 +13,7 @@ class IsIntegerValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if - the value is not an integer. + the value is not an integer. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_json_validator.py b/flask_inputfilter/validators/is_json_validator.py index a64bb43..f5e7b5d 100644 --- a/flask_inputfilter/validators/is_json_validator.py +++ b/flask_inputfilter/validators/is_json_validator.py @@ -14,7 +14,7 @@ class IsJsonValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if - the input is not a valid JSON string. + the input is not a valid JSON string. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_lowercase_validator.py b/flask_inputfilter/validators/is_lowercase_validator.py index cae27c3..bed3d42 100644 --- a/flask_inputfilter/validators/is_lowercase_validator.py +++ b/flask_inputfilter/validators/is_lowercase_validator.py @@ -14,7 +14,7 @@ class IsLowercaseValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not entirely lowercase. + value is not entirely lowercase. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_mac_address_validator.py b/flask_inputfilter/validators/is_mac_address_validator.py index 62e8aae..64b61ae 100644 --- a/flask_inputfilter/validators/is_mac_address_validator.py +++ b/flask_inputfilter/validators/is_mac_address_validator.py @@ -19,7 +19,7 @@ class IsMacAddressValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a valid MAC address. + value is not a valid MAC address. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_past_date_validator.py b/flask_inputfilter/validators/is_past_date_validator.py index be15360..12249fb 100644 --- a/flask_inputfilter/validators/is_past_date_validator.py +++ b/flask_inputfilter/validators/is_past_date_validator.py @@ -16,7 +16,7 @@ class IsPastDateValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the date - is not in the past. + is not in the past. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_port_validator.py b/flask_inputfilter/validators/is_port_validator.py index 5ec2555..7fb55ce 100644 --- a/flask_inputfilter/validators/is_port_validator.py +++ b/flask_inputfilter/validators/is_port_validator.py @@ -14,7 +14,7 @@ class IsPortValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the value - is not a valid port number. + is not a valid port number. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_rgb_color_validator.py b/flask_inputfilter/validators/is_rgb_color_validator.py index 4202ff7..2c2a803 100644 --- a/flask_inputfilter/validators/is_rgb_color_validator.py +++ b/flask_inputfilter/validators/is_rgb_color_validator.py @@ -18,7 +18,7 @@ class IsRgbColorValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a valid RGB color. + value is not a valid RGB color. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_string_validator.py b/flask_inputfilter/validators/is_string_validator.py index 6f65620..356f1e9 100644 --- a/flask_inputfilter/validators/is_string_validator.py +++ b/flask_inputfilter/validators/is_string_validator.py @@ -13,7 +13,7 @@ class IsStringValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a string. + value is not a string. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_typed_dict_validator.py b/flask_inputfilter/validators/is_typed_dict_validator.py index e7976e0..45a6019 100644 --- a/flask_inputfilter/validators/is_typed_dict_validator.py +++ b/flask_inputfilter/validators/is_typed_dict_validator.py @@ -14,9 +14,9 @@ class IsTypedDictValidator(BaseValidator): **Parameters:** - **typed_dict_type** (*Type[TypedDict]*): The TypedDict class that - defines the expected structure. + defines the expected structure. - **error_message** (*Optional[str]*): Custom error message if the - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_uppercase_validator.py b/flask_inputfilter/validators/is_uppercase_validator.py index 1f41d77..b2d8f42 100644 --- a/flask_inputfilter/validators/is_uppercase_validator.py +++ b/flask_inputfilter/validators/is_uppercase_validator.py @@ -14,7 +14,7 @@ class IsUppercaseValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not entirely uppercase. + value is not entirely uppercase. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_url_validator.py b/flask_inputfilter/validators/is_url_validator.py index b35db16..4302f33 100644 --- a/flask_inputfilter/validators/is_url_validator.py +++ b/flask_inputfilter/validators/is_url_validator.py @@ -15,7 +15,7 @@ class IsUrlValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - value is not a valid URL. + value is not a valid URL. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_uuid_validator.py b/flask_inputfilter/validators/is_uuid_validator.py index 5953ad0..b3792ad 100644 --- a/flask_inputfilter/validators/is_uuid_validator.py +++ b/flask_inputfilter/validators/is_uuid_validator.py @@ -14,7 +14,7 @@ class IsUUIDValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - input is not a valid UUID. + input is not a valid UUID. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_vertical_image_validator.py b/flask_inputfilter/validators/is_vertical_image_validator.py index 1a83e0a..7f261c2 100644 --- a/flask_inputfilter/validators/is_vertical_image_validator.py +++ b/flask_inputfilter/validators/is_vertical_image_validator.py @@ -20,7 +20,7 @@ class IsVerticalImageValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the image - is not vertically oriented. + is not vertically oriented. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_weekday_validator.py b/flask_inputfilter/validators/is_weekday_validator.py index d05f105..42216be 100644 --- a/flask_inputfilter/validators/is_weekday_validator.py +++ b/flask_inputfilter/validators/is_weekday_validator.py @@ -15,7 +15,7 @@ class IsWeekdayValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - date is not a weekday. + date is not a weekday. **Expected Behavior:** diff --git a/flask_inputfilter/validators/is_weekend_validator.py b/flask_inputfilter/validators/is_weekend_validator.py index 2d18c30..16cbb6b 100644 --- a/flask_inputfilter/validators/is_weekend_validator.py +++ b/flask_inputfilter/validators/is_weekend_validator.py @@ -15,7 +15,7 @@ class IsWeekendValidator(BaseValidator): **Parameters:** - **error_message** (*Optional[str]*): Custom error message if the - date is not on a weekend. + date is not on a weekend. **Expected Behavior:** diff --git a/flask_inputfilter/validators/length_validator.py b/flask_inputfilter/validators/length_validator.py index d40befe..1bd697d 100644 --- a/flask_inputfilter/validators/length_validator.py +++ b/flask_inputfilter/validators/length_validator.py @@ -24,7 +24,7 @@ class LengthValidator(BaseValidator): - **min_length** (*Optional[int]*): The minimum allowed length. - **max_length** (*Optional[int]*): The maximum allowed length. - **error_message** (*Optional[str]*): Custom error message if - the validation fails. + the validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/not_in_array_validator.py b/flask_inputfilter/validators/not_in_array_validator.py index fd8bda0..4e86a45 100644 --- a/flask_inputfilter/validators/not_in_array_validator.py +++ b/flask_inputfilter/validators/not_in_array_validator.py @@ -15,9 +15,9 @@ class NotInArrayValidator(BaseValidator): - **haystack** (*list[Any]*): A list of disallowed values. - **strict** (*bool*, default: False): If ``True``, the type of the - value is also validated against the disallowed list. + value is also validated against the disallowed list. - **error_message** (*Optional[str]*): Custom error message if the - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/not_validator.py b/flask_inputfilter/validators/not_validator.py index 0c2600a..a8d7e24 100644 --- a/flask_inputfilter/validators/not_validator.py +++ b/flask_inputfilter/validators/not_validator.py @@ -14,9 +14,9 @@ class NotValidator(BaseValidator): **Parameters:** - **validator** (*BaseValidator*): The validator whose outcome is to be - inverted. + inverted. - **error_message** (*Optional[str]*): Custom error message if the - inverted validation does not behave as expected. + inverted validation does not behave as expected. **Expected Behavior:** diff --git a/flask_inputfilter/validators/or_validator.py b/flask_inputfilter/validators/or_validator.py index 69b8edd..b2619ea 100644 --- a/flask_inputfilter/validators/or_validator.py +++ b/flask_inputfilter/validators/or_validator.py @@ -15,9 +15,9 @@ class OrValidator(BaseValidator): **Parameters:** - **validators** (*list[BaseValidator]*): A list of validators - to apply. + to apply. - **error_message** (*Optional[str]*): Custom error message if none - of the validators pass. + of the validators pass. **Expected Behavior:** diff --git a/flask_inputfilter/validators/range_validator.py b/flask_inputfilter/validators/range_validator.py index d1bdc0e..eb8d484 100644 --- a/flask_inputfilter/validators/range_validator.py +++ b/flask_inputfilter/validators/range_validator.py @@ -15,7 +15,7 @@ class RangeValidator(BaseValidator): - **min_value** (*Optional[float]*): The minimum allowed value. - **max_value** (*Optional[float]*): The maximum allowed value. - **error_message** (*Optional[str]*): Custom error message if the - validation fails. + validation fails. **Expected Behavior:** diff --git a/flask_inputfilter/validators/regex_validator.py b/flask_inputfilter/validators/regex_validator.py index 789d6f2..f4614ee 100644 --- a/flask_inputfilter/validators/regex_validator.py +++ b/flask_inputfilter/validators/regex_validator.py @@ -15,9 +15,9 @@ class RegexValidator(BaseValidator): **Parameters:** - **pattern** (*str*): The regular expression pattern the - input must match. + input must match. - **error_message** (*Optional[str]*): Custom error message if - the input does not match the pattern. + the input does not match the pattern. **Expected Behavior:** diff --git a/flask_inputfilter/validators/xor_validator.py b/flask_inputfilter/validators/xor_validator.py index 63f6b13..6f23f76 100644 --- a/flask_inputfilter/validators/xor_validator.py +++ b/flask_inputfilter/validators/xor_validator.py @@ -15,9 +15,9 @@ class XorValidator(BaseValidator): **Parameters:** - **validators** (*list[BaseValidator]*): A list of validators, - of which exactly one must pass. + of which exactly one must pass. - **error_message** (*Optional[str]*): Custom error message if the - input does not satisfy exactly one validator. + input does not satisfy exactly one validator. **Expected Behavior:** diff --git a/pyproject.toml b/pyproject.toml index d288787..a03944d 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta" [project] name = "flask_inputfilter" -version = "0.5.5" +version = "0.6.0" description = "A library to easily filter and validate input data in Flask applications" readme = "README.md" keywords = [ diff --git a/setup.py b/setup.py index eeaa948..8246eb9 100644 --- a/setup.py +++ b/setup.py @@ -24,6 +24,17 @@ for module in pyx_modules ], language_level=3, + compiler_directives={ + "binding": True, + "boundscheck": False, + "cdivision": True, + "embedsignature": True, + "infer_types": True, + "initializedcheck": False, + "linetrace": False, + "profile": False, + "wraparound": False, + }, ) options = { "build_ext": {"include_dirs": ["flask_inputfilter/include"]}, diff --git a/tests/validators/test_is_base64_image_correct_size_validator.py b/tests/validators/test_is_base64_image_correct_size_validator.py index fc8a345..fd018fd 100644 --- a/tests/validators/test_is_base64_image_correct_size_validator.py +++ b/tests/validators/test_is_base64_image_correct_size_validator.py @@ -8,7 +8,7 @@ def test_valid_base64_size(self) -> None: self.input_filter.add( "image", validators=[ - IsBase64ImageCorrectSizeValidator(minSize=10, maxSize=50) + IsBase64ImageCorrectSizeValidator(min_size=10, max_size=50) ], ) self.input_filter.validate_data( @@ -19,7 +19,7 @@ def test_invalid_base64_size(self) -> None: self.input_filter.add( "image", validators=[ - IsBase64ImageCorrectSizeValidator(minSize=10, maxSize=50) + IsBase64ImageCorrectSizeValidator(min_size=10, max_size=50) ], ) with self.assertRaises(ValidationError): @@ -30,7 +30,7 @@ def test_custom_error_message(self) -> None: "image2", validators=[ IsBase64ImageCorrectSizeValidator( - minSize=10, maxSize=5, error_message="Custom error" + min_size=10, max_size=5, error_message="Custom error" ) ], )