diff --git a/.github/workflows/deploy-docs.yaml b/.github/workflows/deploy-docs.yaml
new file mode 100644
index 0000000..eecf6ae
--- /dev/null
+++ b/.github/workflows/deploy-docs.yaml
@@ -0,0 +1,33 @@
+name: Deploy Sphinx Documentation
+
+on:
+ push:
+ branches:
+ - main
+
+jobs:
+ deploy:
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout Repository
+ uses: actions/checkout@v3
+
+ - name: Setup Python
+ uses: actions/setup-python@v4
+ with:
+ python-version: '3.x'
+
+ - name: Install Dependencies
+ run: |
+ pip install sphinx sphinx_rtd_theme
+
+ - name: Build Documentation
+ run: |
+ sphinx-build -b html docs/ docs/_build/html
+
+ - name: Deploy to GitHub Pages
+ uses: peaceiris/actions-gh-pages@v3
+ with:
+ github_token: ${{ secrets.GITHUB_TOKEN }}
+ publish_dir: docs/_build/html
diff --git a/CHAGELOG.md b/CHAGELOG.md
deleted file mode 100644
index b63110a..0000000
--- a/CHAGELOG.md
+++ /dev/null
@@ -1,78 +0,0 @@
-# Changelog
-
-All notable changes to this project will be documented in this file.
-
-
-# [0.0.8] - 2025-01-16
-
-## Added
-
-- New functionality to define steps for a field to have more control over the
- order of the validation and filtering process.
-
-### Filter
-
-- New [`Base64ImageDownscaleFilter`](flask_inputfilter/Filter/Base64ImageDownscaleFilter.py) to reduce the size of an image.
-- New [`Base64ImageResizeFilter`](flask_inputfilter/Filter/Base64ImageResizeFilter.py) to reduce the file size of an image.
-
-### Validator
-
-- New [`IsHorizontalImageValidator`](flask_inputfilter/Validator/IsHorizontalImageValidator.py) to check if an image is horizontical.
-- New [`IsVerticalImageValidator`](flask_inputfilter/Validator/IsVerticalImageValidator.py) to check if an image is vertical.
-
-## Changed
-
-- Added UnicodeFormEnum to show possible config values for ToNormalizedUnicodeFilter.
- Old config is still supportet, but will be removed at a later version.
-
-
-# [0.0.7.1] - 2025-01-16
-
-## Changed
-
-- Updated setup.py to fix the issue with the missing subfolders.
-
-
-# [0.0.7] - 2025-01-14
-
-## Added
-
-- Workflow to run tests on all supported python versions. [Check it out](.github/workflows/test_env.yaml)
-- Added more test coverage for validators and filters.
-- Added tracking of coverage in tests. [Check it out](https://coveralls.io/github/LeanderCS/flask-inputfilter)
-- New functionality for global filters and validators in InputFilters.
-- New functionality to define custom supported methods.
-
-### Validator
-
-- New `NotInArrayValidator` to check if a value is not in a list. [Check it out](flask_inputfilter/Validator/NotInArrayValidator.py)
-- New `NotValidator` to invert the result of another validator. [Check it out](flask_inputfilter/Validator/NotValidator.py)
-
-
-# [0.0.6] - 2025-01-12
-
-## Added
-
-- New date validators and filters.
-
-## Removed
-
-- Dropped support for Python 3.6.
-
-
-# [0.0.5] - 2025-01-12
-
-## Added
-
-- New condition functionality between fields. [Check it out](flask_inputfilter/Condition/README.md)
-
-## Changed
-
-- Switched external_api config from dict to class. [Check it out](flask_inputfilter/Model/ExternalApiConfig.py)
-
-
-# [0.0.4] - 2025-01-09
-
-## Added
-
-- New external api functionality. [Check it out](EXTERNAL_API.md)
diff --git a/CREATE_OWN.md b/CREATE_OWN.md
deleted file mode 100644
index 467646a..0000000
--- a/CREATE_OWN.md
+++ /dev/null
@@ -1 +0,0 @@
-# Create own
\ No newline at end of file
diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md
deleted file mode 100644
index 89a6b02..0000000
--- a/DEVELOPMENT.md
+++ /dev/null
@@ -1,27 +0,0 @@
-# Development
-
-### Build docker image
-```bash
-docker build -t flask-inputfilter .
-```
-
-### Run docker container in interactive mode
-```bash
-docker compose up -d
-```
-
-```bash
-docker exec -it flask-inputfilter /bin/bash
-```
-
-### Run tests
-```bash
-docker exec -it flask-inputfilter pytest
-```
-
-### Run linting
-```bash
-docker exec -it flask-inputfilter sh -c "isort ."
-docker exec -it flask-inputfilter sh -c "autoflake --in-place --remove-all-unused-imports --ignore-init-module-imports --recursive ."
-docker exec -it flask-inputfilter black .
-```
diff --git a/EXTERNAL_API.md b/EXTERNAL_API.md
deleted file mode 100644
index 8e670c6..0000000
--- a/EXTERNAL_API.md
+++ /dev/null
@@ -1,118 +0,0 @@
-# External API Functionality in `InputFilter`
-
-This documentation provides a comprehensive overview of the external API functionality available in the `InputFilter` class. It covers the configuration, core methods, and examples of usage for interacting with external APIs.
-
----
-
-## 1. Overview
-
-The `InputFilter` class includes a mechanism for fetching data from external APIs during the input validation process.
-This feature allows dynamic data retrieval based on user inputs, such as validating fields or fetching related data from an external service.
-
-Important to know, the external api functionality runs after all other filters and validators have been executed.
-This means that the data fetched from the external API will not be validated or filtered.
-
----
-
-## 2. Configuration
-
-The external API functionality is configured via the `external_api` parameter in the `add` method. This parameter accepts a dictionary with the following structure:
-
-### `ExternalApiConfig` Fields
-
-| Field | Type | Description |
-|------------|--------------------------|-----------------------------------------------------------------------------|
-| `url` | `str` | The URL of the external API, with optional placeholders in `{{}}` format. |
-| `method` | `str` | The HTTP method to use (e.g., `GET`, `POST`). |
-| `params` | `Optional[Dict[str, str]]` | Query parameters for the API, with placeholders allowed. |
-| `data_key` | `Optional[str]` | Key in the JSON response to extract the required data. |
-| `api_key` | `Optional[str]` | API key for authorization, sent in the `Authorization` header. |
-
----
-
-## 3. Examples
-
-### 3.1 Basic External API Integration
-
-```python
-from flask_inputfilter.InputFilter import InputFilter
-
-class MyInputFilter(InputFilter):
- def __init__(self):
- super().__init__()
-
- self.add(
- "user_id", required=True
- )
- self.add(
- "is_active",
- required=True,
- external_api={
- "url": "https://api.example.com/users/{{user_id}}/status",
- "method": "GET",
- "data_key": "is_active",
- },
- )
-
-# Example usage
-filter_instance = MyInputFilter()
-validated_data = filter_instance.validateData({"user_id": 123})
-print(validated_data["is_active"]) # True or False based on API response
-```
-
-### 3.2 Using Query Parameters
-
-```python
-self.add(
- "is_valid",
- required=True,
- external_api={
- "url": "https://api.example.com/validate",
- "method": "GET",
- "params": {"user": "{{user_id}}", "hash": "{{hash}}"},
- "data_key": "is_valid",
- },
-)
-```
-
-This configuration sends the `user_id` and `hash` as query parameters, replacing the placeholders with validated data.
-
----
-
-### 3.3 Handling Fallback Values
-
-If the external API call fails, a fallback value can be specified:
-
-```python
-self.add(
- "user_info",
- required=True,
- fallback={"name": "unknown", "age": 0},
- external_api={
- "url": "https://api.example.com/user/{{user_id}}",
- "method": "GET",
- "data_key": "user",
- },
-)
-```
-
----
-
-## 4. Error Handling
-
-- `ValidationError` is raised when:
- - The API call returns a non-200 status code.
- - A required field is missing and no fallback/default is provided.
- - Validation of the field value fails.
-
----
-
-## 7. Best Practices
-
-- **Required Fields:** Clearly define required fields and provide fallback values where necessary.
-- **Placeholders:** Ensure placeholders in URLs and parameters match the keys in `validated_data`.
-- **Fallbacks:** Always provide fallback values for critical fields to avoid disruptions in case of API failure.
-- **Security:** Use HTTPS for API calls and secure sensitive data like API keys.
-- **Testing:** Mock external API calls during unit testing to avoid dependencies on external systems.
-
----
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..d0c3cbf
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,20 @@
+# Minimal makefile for Sphinx documentation
+#
+
+# You can set these variables from the command line, and also
+# from the environment for the first two.
+SPHINXOPTS ?=
+SPHINXBUILD ?= sphinx-build
+SOURCEDIR = source
+BUILDDIR = build
+
+# Put it first so that "make" without argument is like "make help".
+help:
+ @$(SPHINXBUILD) -M help "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
+
+.PHONY: help Makefile
+
+# Catch-all target: route all unknown targets to Sphinx using the new
+# "make mode" option. $(O) is meant as a shortcut for $(SPHINXOPTS).
+%: Makefile
+ @$(SPHINXBUILD) -M $@ "$(SOURCEDIR)" "$(BUILDDIR)" $(SPHINXOPTS) $(O)
diff --git a/README.rst b/README.rst
index 90cabd6..eac77db 100644
--- a/README.rst
+++ b/README.rst
@@ -1,10 +1,37 @@
flask-inputfilter
==================================
-The `InputFilter` class is used to validate and filter input data in Flask applications.
+The ``InputFilter`` class is used to validate and filter input data in Flask applications.
It provides a modular way to clean and ensure that incoming data meets expected format
and type requirements before being processed.
+.. raw:: html
+
+
+
+ ');">
+ Tip
+
+
+ Thank you for using flask-inputfilter!
+ If you have any questions or suggestions, please feel free to open an issue on GitHub here.
+ If you don't want to miss any updates, please star the repository.
+ This will help me to understand how many people are interested in this project.
+
+
+
+.. raw:: html
+
+
+
+ ');">
+ Hint
+
+
+ For information about the usage you can view the documentation
+
+
+
:Test Status:
.. image:: https://img.shields.io/github/actions/workflow/status/LeanderCS/flask-inputfilter/test.yaml?branch=main&style=flat-square&label=Github%20Actions
@@ -37,10 +64,10 @@ Installation
Quickstart
==========
-To use the `InputFilter` class, create a new class that inherits from it and define the
+To use the ``InputFilter`` class, create a new class that inherits from it and define the
fields you want to validate and filter.
-There are numerous filters and validators available, but you can also create your `own `_.
+There are numerous filters and validators available, but you can also create your `own `_.
Definition
----------
@@ -92,8 +119,8 @@ Definition
Usage
-----
-To use the `InputFilter` class, call the `validate` method on the class instance.
-After calling `validate`, the validated data will be available in `g.validated_data`.
+To use the ``InputFilter`` class, call the ``validate`` method on the class instance.
+After calling ``validate``, the validated data will be available in ``g.validated_data``.
If the data is invalid, a 400 response with an error message will be returned.
.. code-block:: python
@@ -112,33 +139,17 @@ If the data is invalid, a 400 response with an error message will be returned.
id = data.get('id')
zipcode = data.get('zipcode')
-Options
-=======
-
-The `add` method supports several options:
-
-- `Required`_
-- `Filter `_
-- `Validator `_
-- `Default`_
-- `Fallback`_
-- `ExternalApi `_
-
-Required
---------
-
-The `required` option specifies whether the field must be included in the input data.
-If the field is missing, a `ValidationError` will be raised with an appropriate error message.
-
-Default
--------
-The `default` option allows you to specify a default value to use if the field is not
-present in the input data.
+.. raw:: html
-Fallback
---------
+
+
+
+ Tip
+
+
+ For further instructions please view the documentary `Here
-The `fallback` option specifies a value to use if validation fails or required data
-is missing. Note that if the field is optional and absent, `fallback` will not apply;
-use `default` in such cases.
+ For ideas, suggestions or questions, please open an issue on GitHub here.
+
+
diff --git a/flask_inputfilter/Condition/ArrayLengthEqualCondition.py b/flask_inputfilter/Condition/ArrayLengthEqualCondition.py
index 90d88cc..40ce815 100644
--- a/flask_inputfilter/Condition/ArrayLengthEqualCondition.py
+++ b/flask_inputfilter/Condition/ArrayLengthEqualCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition.BaseCondition import BaseCondition
class ArrayLengthEqualCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/ArrayLongerThanCondition.py b/flask_inputfilter/Condition/ArrayLongerThanCondition.py
index de6b3e1..e4f7c2c 100644
--- a/flask_inputfilter/Condition/ArrayLongerThanCondition.py
+++ b/flask_inputfilter/Condition/ArrayLongerThanCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition.BaseCondition import BaseCondition
class ArrayLongerThanCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/CustomCondition.py b/flask_inputfilter/Condition/CustomCondition.py
index 41d6267..fa87ccc 100644
--- a/flask_inputfilter/Condition/CustomCondition.py
+++ b/flask_inputfilter/Condition/CustomCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Callable, Dict
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class CustomCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/EqualCondition.py b/flask_inputfilter/Condition/EqualCondition.py
index 82c3805..75a6944 100644
--- a/flask_inputfilter/Condition/EqualCondition.py
+++ b/flask_inputfilter/Condition/EqualCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class EqualCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/ExactlyNOfCondition.py b/flask_inputfilter/Condition/ExactlyNOfCondition.py
index c081e3e..59969e7 100644
--- a/flask_inputfilter/Condition/ExactlyNOfCondition.py
+++ b/flask_inputfilter/Condition/ExactlyNOfCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class ExactlyNOfCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/ExactlyNOfMatchesCondition.py b/flask_inputfilter/Condition/ExactlyNOfMatchesCondition.py
index b474b82..07843de 100644
--- a/flask_inputfilter/Condition/ExactlyNOfMatchesCondition.py
+++ b/flask_inputfilter/Condition/ExactlyNOfMatchesCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class ExactlyNOfMatchesCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/ExactlyOneOfCondition.py b/flask_inputfilter/Condition/ExactlyOneOfCondition.py
index bd10b55..de69d09 100644
--- a/flask_inputfilter/Condition/ExactlyOneOfCondition.py
+++ b/flask_inputfilter/Condition/ExactlyOneOfCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class ExactlyOneOfCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/ExactlyOneOfMatchesCondition.py b/flask_inputfilter/Condition/ExactlyOneOfMatchesCondition.py
index 6751602..728e63f 100644
--- a/flask_inputfilter/Condition/ExactlyOneOfMatchesCondition.py
+++ b/flask_inputfilter/Condition/ExactlyOneOfMatchesCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class ExactlyOneOfMatchesCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/IntegerBiggerThanCondition.py b/flask_inputfilter/Condition/IntegerBiggerThanCondition.py
index cc7200c..106c8a7 100644
--- a/flask_inputfilter/Condition/IntegerBiggerThanCondition.py
+++ b/flask_inputfilter/Condition/IntegerBiggerThanCondition.py
@@ -1,6 +1,6 @@
from typing import Dict
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class IntegerBiggerThanCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/NOfCondition.py b/flask_inputfilter/Condition/NOfCondition.py
index 15d15da..e7570fb 100644
--- a/flask_inputfilter/Condition/NOfCondition.py
+++ b/flask_inputfilter/Condition/NOfCondition.py
@@ -1,6 +1,6 @@
from typing import Any, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class NOfCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/NOfMatchesCondition.py b/flask_inputfilter/Condition/NOfMatchesCondition.py
index 5378e65..3e10bc4 100644
--- a/flask_inputfilter/Condition/NOfMatchesCondition.py
+++ b/flask_inputfilter/Condition/NOfMatchesCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class NOfMatchesCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/NotEqualCondition.py b/flask_inputfilter/Condition/NotEqualCondition.py
index 565f077..dab9b1c 100644
--- a/flask_inputfilter/Condition/NotEqualCondition.py
+++ b/flask_inputfilter/Condition/NotEqualCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class NotEqualCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/OneOfCondition.py b/flask_inputfilter/Condition/OneOfCondition.py
index 367109c..b6e03eb 100644
--- a/flask_inputfilter/Condition/OneOfCondition.py
+++ b/flask_inputfilter/Condition/OneOfCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class OneOfCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/OneOfMatchesCondition.py b/flask_inputfilter/Condition/OneOfMatchesCondition.py
index 45b5afb..3de5702 100644
--- a/flask_inputfilter/Condition/OneOfMatchesCondition.py
+++ b/flask_inputfilter/Condition/OneOfMatchesCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class OneOfMatchesCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/README.md b/flask_inputfilter/Condition/README.md
deleted file mode 100644
index 86911c5..0000000
--- a/flask_inputfilter/Condition/README.md
+++ /dev/null
@@ -1,59 +0,0 @@
-# Condition
-
-The `Condition` module contains the conditions that can be used to validate the input data.
-
-## Conditions
-
-The `addCondition` method is used to add a condition between fields.
-
-```python
-
-from flask_inputfilter import InputFilter
-from flask_inputfilter.Condition import OneOfCondition
-from flask_inputfilter.Filter import StringTrimFilter
-from flask_inputfilter.Validator import IsStringValidator
-
-
-class TestInputFilter(InputFilter):
- def __init__(self):
- super().__init__()
-
- self.add(
- 'username',
- filters=[StringTrimFilter()],
- validators=[IsStringValidator()]
- )
-
- self.add(
- 'name',
- filters=[StringTrimFilter()],
- validators=[IsStringValidator()]
- )
-
- self.addCondition(
- OneOfCondition(['id', 'name'])
- )
-
-```
-
-## Available conditions
-
-The following conditions are available in the `Condition` module:
-
-1. [`ArrayLengthEqualCondition`](ArrayLengthEqualCondition.py) - Validates that the length of the array is equal to the given value.
-2. [`ArrayLongerThanCondition`](ArrayLongerThanCondition.py) - Validates that the length of the array is longer than the given value.
-3. [`CustomCondition`](CustomCondition.py) - A custom condition that can be used to validate the input data.
-4. [`EqualCondition`](EqualCondition.py) - Validates that the input is equal to the given value.
-5. [`ExactlyNOfCondition`](ExactlyNOfCondition.py) - Validates that exactly `n` of the given conditions are true.
-6. [`ExactlyNOfMatchesCondition`](ExactlyNOfMatchesCondition.py) - Validates that exactly `n` of the given matches are true.
-7. [`ExactlyOneOfCondition`](ExactlyOneOfCondition.py) - Validates that exactly one of the given conditions is true.
-8. [`ExactlyOneOfMatchesCondition`](ExactlyOneOfMatchesCondition.py) - Validates that exactly one of the given matches is true.
-9. [`IntegerBiggerThanCondition`](IntegerBiggerThanCondition.py) - Validates that the integer is bigger than the given value.
-10. [`NOfCondition`](NOfCondition.py) - Validates that at least `n` of the given conditions are true.
-11. [`NOfMatchesCondition`](NOfMatchesCondition.py) - Validates that at least `n` of the given matches are true.
-12. [`NotEqualCondition`](NotEqualCondition.py) - Validates that the input is not equal to the given value.
-13. [`OneOfCondition`](OneOfCondition.py) - Validates that at least one of the given conditions is true.
-14. [`OneOfMatchesCondition`](OneOfMatchesCondition.py) - Validates that at least one of the given matches is true.
-15. [`RequiredIfCondition`](RequiredIfCondition.py) - Validates that the input is required if the given field has a specific value.
-16. [`StringLongerThanCondition`](StringLongerThanCondition.py) - Validates that the string is longer than the given value.
-17. [`TemporalOrderCondition`](TemporalOrderCondition.py) - Validates that the input is in correct temporal order.
diff --git a/flask_inputfilter/Condition/RequiredIfCondition.py b/flask_inputfilter/Condition/RequiredIfCondition.py
index c04a299..6485433 100644
--- a/flask_inputfilter/Condition/RequiredIfCondition.py
+++ b/flask_inputfilter/Condition/RequiredIfCondition.py
@@ -1,6 +1,6 @@
from typing import Any, Dict, List, Optional, Union
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class RequiredIfCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/StringLongerThanCondition.py b/flask_inputfilter/Condition/StringLongerThanCondition.py
index 026551e..321d070 100644
--- a/flask_inputfilter/Condition/StringLongerThanCondition.py
+++ b/flask_inputfilter/Condition/StringLongerThanCondition.py
@@ -1,6 +1,6 @@
from typing import Dict
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
class StringLongerThanCondition(BaseCondition):
diff --git a/flask_inputfilter/Condition/TemporalOrderCondition.py b/flask_inputfilter/Condition/TemporalOrderCondition.py
index 807ac4b..9eecfa0 100644
--- a/flask_inputfilter/Condition/TemporalOrderCondition.py
+++ b/flask_inputfilter/Condition/TemporalOrderCondition.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Dict
-from ..Exception import ValidationError
-from .BaseCondition import BaseCondition
+from flask_inputfilter.Condition import BaseCondition
+from flask_inputfilter.Exception import ValidationError
class TemporalOrderCondition(BaseCondition):
diff --git a/flask_inputfilter/Filter/ArrayExplodeFilter.py b/flask_inputfilter/Filter/ArrayExplodeFilter.py
index ad960ba..32e472f 100644
--- a/flask_inputfilter/Filter/ArrayExplodeFilter.py
+++ b/flask_inputfilter/Filter/ArrayExplodeFilter.py
@@ -1,6 +1,6 @@
from typing import Any, List, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter.BaseFilter import BaseFilter
class ArrayExplodeFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/Base64ImageDownscaleFilter.py b/flask_inputfilter/Filter/Base64ImageDownscaleFilter.py
index 08e56e9..93eb534 100644
--- a/flask_inputfilter/Filter/Base64ImageDownscaleFilter.py
+++ b/flask_inputfilter/Filter/Base64ImageDownscaleFilter.py
@@ -4,7 +4,7 @@
from PIL import Image
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter.BaseFilter import BaseFilter
class Base64ImageDownscaleFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/Base64ImageResizeFilter.py b/flask_inputfilter/Filter/Base64ImageResizeFilter.py
index c9efb2e..2969d88 100644
--- a/flask_inputfilter/Filter/Base64ImageResizeFilter.py
+++ b/flask_inputfilter/Filter/Base64ImageResizeFilter.py
@@ -4,8 +4,8 @@
from PIL import Image
-from ..Enum import ImageFormatEnum
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Enum import ImageFormatEnum
+from flask_inputfilter.Filter.BaseFilter import BaseFilter
class Base64ImageResizeFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/BlacklistFilter.py b/flask_inputfilter/Filter/BlacklistFilter.py
index cfca125..49abd20 100644
--- a/flask_inputfilter/Filter/BlacklistFilter.py
+++ b/flask_inputfilter/Filter/BlacklistFilter.py
@@ -1,6 +1,6 @@
from typing import Any, List
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class BlacklistFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/README.md b/flask_inputfilter/Filter/README.md
deleted file mode 100644
index df02528..0000000
--- a/flask_inputfilter/Filter/README.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# Filter
-
-The `Filter` module contains the filters that can be used to filter the input data.
-
-## Available filters
-
-The following filters are available in the `Filter` module:
-
-1. [`ArrayExplodeFilter`](ArrayExplodeFilter.py) - Explodes the input string into an array.
-2. [`Base64ImageDownscaleFilter`](Base64ImageDownscaleFilter.py) - Downscale the base64 image.
-3. [`Base64ImageResizeFilter`](Base64ImageResizeFilter.py) - Resize the base64 image.
-2. [`BlacklistFilter`](BlacklistFilter.py) - Filters the string based on the blacklist.
-3. [`RemoveEmojisFilter`](RemoveEmojisFilter.py) - Removes the emojis from the string.
-4. [`SlugifyFilter`](SlugifyFilter.py) - Converts the string to a slug.
-5. [`StringTrimFilter`](StringTrimFilter.py) - Trims the whitespace from the beginning and end of the string.
-6. [`ToAlphaNumericFilter`](ToAlphaNumericFilter.py) - Converts the string to an alphanumeric string.
-7. [`ToBooleanFilter`](ToBooleanFilter.py) - Converts the string to a boolean value.
-8. [`ToCamelCaseFilter`](ToCamelCaseFilter.py) - Converts the string to camel case.
-9. [`ToDateFilter`](ToDateFilter.py) - Converts a string to a date value.
-10. [`ToDateTimeFilter`](ToDateTimeFilter.py) - Converts a string to a datetime value.
-11. [`ToEnumFilter`](ToEnumFilter.py) - Converts a string or integer to an enum value.
-12. [`ToFloatFilter`](ToFloatFilter.py) - Converts a string to a float value.
-13. [`ToIntegerFilter`](ToIntegerFilter.py) - Converts a string to an integer value.
-14. [`ToIsoFilter`](ToIsoFilter.py) - Converts a string to an ISO8601 date time value.
-15. [`ToLowerFilter`](ToLowerFilter.py) - Converts a string to lowercase.
-16. [`ToNormalizedUnicodeFilter`](ToNormalizedUnicodeFilter.py) - Normalizes a unicode string.
-17. [`ToNullFilter`](ToNullFilter.py) - Converts the string to `None` if it is already `None` or `''` (empty string).
-18. [`ToPascaleCaseFilter`](ToPascaleCaseFilter.py) - Converts the string to pascal case.
-19. [`ToSnakeCaseFilter`](ToSnakeCaseFilter.py) - Converts the string to snake case.
-20. [`ToStringFilter`](ToStringFilter.py) - Converts the input to a string value.
-21. [`ToUpperFilter`](ToUpperFilter.py) - Converts the string to uppercase.
-22. [`TruncateFilter`](TruncateFilter.py) - Truncates the string to the specified length.
-23. [`WhitelistFilter`](WhitelistFilter.py) - Filters the string based on the whitelist.
-24. [`WhitespaceCollapseFilter`](WhitespaceCollapseFilter.py) - Collapses the whitespace in the string.
diff --git a/flask_inputfilter/Filter/RemoveEmojisFilter.py b/flask_inputfilter/Filter/RemoveEmojisFilter.py
index 6773405..1af6050 100644
--- a/flask_inputfilter/Filter/RemoveEmojisFilter.py
+++ b/flask_inputfilter/Filter/RemoveEmojisFilter.py
@@ -1,7 +1,7 @@
import re
from typing import Any, Optional, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
emoji_pattern = (
r"["
diff --git a/flask_inputfilter/Filter/SlugifyFilter.py b/flask_inputfilter/Filter/SlugifyFilter.py
index 1eb7ffc..a219ebe 100644
--- a/flask_inputfilter/Filter/SlugifyFilter.py
+++ b/flask_inputfilter/Filter/SlugifyFilter.py
@@ -1,7 +1,7 @@
import re
from typing import Any, Optional, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class SlugifyFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/StringTrimFilter.py b/flask_inputfilter/Filter/StringTrimFilter.py
index 0839664..28ce1e3 100644
--- a/flask_inputfilter/Filter/StringTrimFilter.py
+++ b/flask_inputfilter/Filter/StringTrimFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class StringTrimFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToAlphaNumericFilter.py b/flask_inputfilter/Filter/ToAlphaNumericFilter.py
index 6641c99..1de669e 100644
--- a/flask_inputfilter/Filter/ToAlphaNumericFilter.py
+++ b/flask_inputfilter/Filter/ToAlphaNumericFilter.py
@@ -1,7 +1,7 @@
import re
from typing import Any, Optional, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToAlphaNumericFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToBooleanFilter.py b/flask_inputfilter/Filter/ToBooleanFilter.py
index 8ed49e1..91a151d 100644
--- a/flask_inputfilter/Filter/ToBooleanFilter.py
+++ b/flask_inputfilter/Filter/ToBooleanFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Optional, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToBooleanFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToCamelCaseFilter.py b/flask_inputfilter/Filter/ToCamelCaseFilter.py
index 1e70093..a305de7 100644
--- a/flask_inputfilter/Filter/ToCamelCaseFilter.py
+++ b/flask_inputfilter/Filter/ToCamelCaseFilter.py
@@ -1,7 +1,7 @@
import re
from typing import Any, Optional, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToCamelCaseFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToDateFilter.py b/flask_inputfilter/Filter/ToDateFilter.py
index db5f35e..65b7ac3 100644
--- a/flask_inputfilter/Filter/ToDateFilter.py
+++ b/flask_inputfilter/Filter/ToDateFilter.py
@@ -1,7 +1,7 @@
from datetime import date, datetime
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToDateFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToDateTimeFilter.py b/flask_inputfilter/Filter/ToDateTimeFilter.py
index d646793..383df32 100644
--- a/flask_inputfilter/Filter/ToDateTimeFilter.py
+++ b/flask_inputfilter/Filter/ToDateTimeFilter.py
@@ -1,7 +1,7 @@
from datetime import date, datetime
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToDateTimeFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToEnumFilter.py b/flask_inputfilter/Filter/ToEnumFilter.py
index f4fc5af..a032595 100644
--- a/flask_inputfilter/Filter/ToEnumFilter.py
+++ b/flask_inputfilter/Filter/ToEnumFilter.py
@@ -1,7 +1,7 @@
from enum import Enum
from typing import Any, Type, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToEnumFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToFloatFilter.py b/flask_inputfilter/Filter/ToFloatFilter.py
index b18c221..ec6b105 100644
--- a/flask_inputfilter/Filter/ToFloatFilter.py
+++ b/flask_inputfilter/Filter/ToFloatFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToFloatFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToIntegerFilter.py b/flask_inputfilter/Filter/ToIntegerFilter.py
index 341dca1..aff33ed 100644
--- a/flask_inputfilter/Filter/ToIntegerFilter.py
+++ b/flask_inputfilter/Filter/ToIntegerFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToIntegerFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToIsoFilter.py b/flask_inputfilter/Filter/ToIsoFilter.py
index 5c17dba..2c0f138 100644
--- a/flask_inputfilter/Filter/ToIsoFilter.py
+++ b/flask_inputfilter/Filter/ToIsoFilter.py
@@ -1,7 +1,7 @@
from datetime import date, datetime
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToIsoFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToLowerFilter.py b/flask_inputfilter/Filter/ToLowerFilter.py
index 333771d..f025c37 100644
--- a/flask_inputfilter/Filter/ToLowerFilter.py
+++ b/flask_inputfilter/Filter/ToLowerFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToLowerFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToNormalizedUnicodeFilter.py b/flask_inputfilter/Filter/ToNormalizedUnicodeFilter.py
index e817c13..8870a16 100644
--- a/flask_inputfilter/Filter/ToNormalizedUnicodeFilter.py
+++ b/flask_inputfilter/Filter/ToNormalizedUnicodeFilter.py
@@ -3,8 +3,8 @@
from typing_extensions import Literal
-from ..Enum import UnicodeFormEnum
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Enum import UnicodeFormEnum
+from flask_inputfilter.Filter import BaseFilter
class ToNormalizedUnicodeFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToNullFilter.py b/flask_inputfilter/Filter/ToNullFilter.py
index f0e2345..d434a7f 100644
--- a/flask_inputfilter/Filter/ToNullFilter.py
+++ b/flask_inputfilter/Filter/ToNullFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Optional
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToNullFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToPascaleCaseFilter.py b/flask_inputfilter/Filter/ToPascaleCaseFilter.py
index 6504134..cfa71d2 100644
--- a/flask_inputfilter/Filter/ToPascaleCaseFilter.py
+++ b/flask_inputfilter/Filter/ToPascaleCaseFilter.py
@@ -1,7 +1,7 @@
import re
from typing import Any, Optional, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToPascaleCaseFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToSnakeCaseFilter.py b/flask_inputfilter/Filter/ToSnakeCaseFilter.py
index 4434df4..5fa7955 100644
--- a/flask_inputfilter/Filter/ToSnakeCaseFilter.py
+++ b/flask_inputfilter/Filter/ToSnakeCaseFilter.py
@@ -1,7 +1,7 @@
import re
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToSnakeCaseFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToStringFilter.py b/flask_inputfilter/Filter/ToStringFilter.py
index 3249cf4..e4091ca 100644
--- a/flask_inputfilter/Filter/ToStringFilter.py
+++ b/flask_inputfilter/Filter/ToStringFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToStringFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/ToUpperFilter.py b/flask_inputfilter/Filter/ToUpperFilter.py
index 5c5cefb..7e4c9ae 100644
--- a/flask_inputfilter/Filter/ToUpperFilter.py
+++ b/flask_inputfilter/Filter/ToUpperFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class ToUpperFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/TruncateFilter.py b/flask_inputfilter/Filter/TruncateFilter.py
index 731b6de..658a21e 100644
--- a/flask_inputfilter/Filter/TruncateFilter.py
+++ b/flask_inputfilter/Filter/TruncateFilter.py
@@ -1,6 +1,6 @@
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class TruncateFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/WhitelistFilter.py b/flask_inputfilter/Filter/WhitelistFilter.py
index 490e73d..a77f315 100644
--- a/flask_inputfilter/Filter/WhitelistFilter.py
+++ b/flask_inputfilter/Filter/WhitelistFilter.py
@@ -1,6 +1,6 @@
from typing import Any, List
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class WhitelistFilter(BaseFilter):
diff --git a/flask_inputfilter/Filter/WhitespaceCollapseFilter.py b/flask_inputfilter/Filter/WhitespaceCollapseFilter.py
index 02c070d..1220f71 100644
--- a/flask_inputfilter/Filter/WhitespaceCollapseFilter.py
+++ b/flask_inputfilter/Filter/WhitespaceCollapseFilter.py
@@ -1,7 +1,7 @@
import re
from typing import Any, Union
-from .BaseFilter import BaseFilter
+from flask_inputfilter.Filter import BaseFilter
class WhitespaceCollapseFilter(BaseFilter):
diff --git a/flask_inputfilter/InputFilter.py b/flask_inputfilter/InputFilter.py
index 11fb2da..9b20d80 100644
--- a/flask_inputfilter/InputFilter.py
+++ b/flask_inputfilter/InputFilter.py
@@ -4,11 +4,11 @@
import requests
from flask import Response, g, request
-from .Condition.BaseCondition import BaseCondition
-from .Exception import ValidationError
-from .Filter.BaseFilter import BaseFilter
-from .Model import ExternalApiConfig
-from .Validator.BaseValidator import BaseValidator
+from flask_inputfilter.Condition.BaseCondition import BaseCondition
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Filter import BaseFilter
+from flask_inputfilter.Model import ExternalApiConfig
+from flask_inputfilter.Validator import BaseValidator
class InputFilter:
diff --git a/flask_inputfilter/Validator/ArrayElementValidator.py b/flask_inputfilter/Validator/ArrayElementValidator.py
index e4d75be..af5a5ac 100644
--- a/flask_inputfilter/Validator/ArrayElementValidator.py
+++ b/flask_inputfilter/Validator/ArrayElementValidator.py
@@ -1,10 +1,10 @@
from typing import TYPE_CHECKING, Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator.BaseValidator import BaseValidator
if TYPE_CHECKING:
- from ..InputFilter import InputFilter
+ from flask_inputfilter import InputFilter
class ArrayElementValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/ArrayLengthValidator.py b/flask_inputfilter/Validator/ArrayLengthValidator.py
index 06fdebd..cf71d69 100644
--- a/flask_inputfilter/Validator/ArrayLengthValidator.py
+++ b/flask_inputfilter/Validator/ArrayLengthValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator.BaseValidator import BaseValidator
class ArrayLengthValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/DateAfterValidator.py b/flask_inputfilter/Validator/DateAfterValidator.py
index 18c4028..8211612 100644
--- a/flask_inputfilter/Validator/DateAfterValidator.py
+++ b/flask_inputfilter/Validator/DateAfterValidator.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Optional, Union
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class DateAfterValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/DateBeforeValidator.py b/flask_inputfilter/Validator/DateBeforeValidator.py
index 0be119d..16d7353 100644
--- a/flask_inputfilter/Validator/DateBeforeValidator.py
+++ b/flask_inputfilter/Validator/DateBeforeValidator.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Optional, Union
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class DateBeforeValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/DateRangeValidator.py b/flask_inputfilter/Validator/DateRangeValidator.py
index 2308712..553e42e 100644
--- a/flask_inputfilter/Validator/DateRangeValidator.py
+++ b/flask_inputfilter/Validator/DateRangeValidator.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Optional, Union
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class DateRangeValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/FloatPrecisionValidator.py b/flask_inputfilter/Validator/FloatPrecisionValidator.py
index 867afa5..93e2e3a 100644
--- a/flask_inputfilter/Validator/FloatPrecisionValidator.py
+++ b/flask_inputfilter/Validator/FloatPrecisionValidator.py
@@ -1,8 +1,8 @@
import re
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class FloatPrecisionValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/InArrayValidator.py b/flask_inputfilter/Validator/InArrayValidator.py
index 9f3437f..dd1a6db 100644
--- a/flask_inputfilter/Validator/InArrayValidator.py
+++ b/flask_inputfilter/Validator/InArrayValidator.py
@@ -1,7 +1,7 @@
from typing import Any, List, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class InArrayValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/InEnumValidator.py b/flask_inputfilter/Validator/InEnumValidator.py
index cd71f04..d8143bc 100644
--- a/flask_inputfilter/Validator/InEnumValidator.py
+++ b/flask_inputfilter/Validator/InEnumValidator.py
@@ -1,8 +1,8 @@
from enum import Enum
from typing import Any, Optional, Type
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class InEnumValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsArrayValidator.py b/flask_inputfilter/Validator/IsArrayValidator.py
index 47c47e6..72a3c6e 100644
--- a/flask_inputfilter/Validator/IsArrayValidator.py
+++ b/flask_inputfilter/Validator/IsArrayValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsArrayValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsBase64ImageCorrectSizeValidator.py b/flask_inputfilter/Validator/IsBase64ImageCorrectSizeValidator.py
index a95a725..1f5a43e 100644
--- a/flask_inputfilter/Validator/IsBase64ImageCorrectSizeValidator.py
+++ b/flask_inputfilter/Validator/IsBase64ImageCorrectSizeValidator.py
@@ -1,8 +1,8 @@
import base64
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsBase64ImageCorrectSizeValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsBase64ImageValidator.py b/flask_inputfilter/Validator/IsBase64ImageValidator.py
index 41cbeaf..8d13476 100644
--- a/flask_inputfilter/Validator/IsBase64ImageValidator.py
+++ b/flask_inputfilter/Validator/IsBase64ImageValidator.py
@@ -4,8 +4,8 @@
from PIL import Image
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsBase64ImageValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsBooleanValidator.py b/flask_inputfilter/Validator/IsBooleanValidator.py
index 7892ffd..e940c86 100644
--- a/flask_inputfilter/Validator/IsBooleanValidator.py
+++ b/flask_inputfilter/Validator/IsBooleanValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsBooleanValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsFloatValidator.py b/flask_inputfilter/Validator/IsFloatValidator.py
index b769536..68593ff 100644
--- a/flask_inputfilter/Validator/IsFloatValidator.py
+++ b/flask_inputfilter/Validator/IsFloatValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsFloatValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsFutureDateValidator.py b/flask_inputfilter/Validator/IsFutureDateValidator.py
index f9e5bb5..fc35013 100644
--- a/flask_inputfilter/Validator/IsFutureDateValidator.py
+++ b/flask_inputfilter/Validator/IsFutureDateValidator.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsFutureDateValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsHexadecimalValidator.py b/flask_inputfilter/Validator/IsHexadecimalValidator.py
index ff0e1bd..9f6285f 100644
--- a/flask_inputfilter/Validator/IsHexadecimalValidator.py
+++ b/flask_inputfilter/Validator/IsHexadecimalValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsHexadecimalValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsInstanceValidator.py b/flask_inputfilter/Validator/IsInstanceValidator.py
index fbf2da4..dc5c295 100644
--- a/flask_inputfilter/Validator/IsInstanceValidator.py
+++ b/flask_inputfilter/Validator/IsInstanceValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional, Type
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsInstanceValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsIntegerValidator.py b/flask_inputfilter/Validator/IsIntegerValidator.py
index 306066f..6a18a19 100644
--- a/flask_inputfilter/Validator/IsIntegerValidator.py
+++ b/flask_inputfilter/Validator/IsIntegerValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsIntegerValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsJsonValidator.py b/flask_inputfilter/Validator/IsJsonValidator.py
index 76b6cd8..09a749d 100644
--- a/flask_inputfilter/Validator/IsJsonValidator.py
+++ b/flask_inputfilter/Validator/IsJsonValidator.py
@@ -1,8 +1,8 @@
import json
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsJsonValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsPastDateValidator.py b/flask_inputfilter/Validator/IsPastDateValidator.py
index 1596857..badafa1 100644
--- a/flask_inputfilter/Validator/IsPastDateValidator.py
+++ b/flask_inputfilter/Validator/IsPastDateValidator.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsPastDateValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsStringValidator.py b/flask_inputfilter/Validator/IsStringValidator.py
index 813ae50..015268a 100644
--- a/flask_inputfilter/Validator/IsStringValidator.py
+++ b/flask_inputfilter/Validator/IsStringValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsStringValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsUUIDValidator.py b/flask_inputfilter/Validator/IsUUIDValidator.py
index 51b8396..e17ba66 100644
--- a/flask_inputfilter/Validator/IsUUIDValidator.py
+++ b/flask_inputfilter/Validator/IsUUIDValidator.py
@@ -1,8 +1,8 @@
import uuid
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsUUIDValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsWeekdayValidator.py b/flask_inputfilter/Validator/IsWeekdayValidator.py
index de57176..eff3b7a 100644
--- a/flask_inputfilter/Validator/IsWeekdayValidator.py
+++ b/flask_inputfilter/Validator/IsWeekdayValidator.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsWeekdayValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/IsWeekendValidator.py b/flask_inputfilter/Validator/IsWeekendValidator.py
index f9845e9..a284d2e 100644
--- a/flask_inputfilter/Validator/IsWeekendValidator.py
+++ b/flask_inputfilter/Validator/IsWeekendValidator.py
@@ -1,8 +1,8 @@
from datetime import date, datetime
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class IsWeekendValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/LengthValidator.py b/flask_inputfilter/Validator/LengthValidator.py
index 8fc65a6..29dfa8e 100644
--- a/flask_inputfilter/Validator/LengthValidator.py
+++ b/flask_inputfilter/Validator/LengthValidator.py
@@ -1,8 +1,8 @@
from enum import Enum
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class LengthEnum(Enum):
diff --git a/flask_inputfilter/Validator/NotInArrayValidator.py b/flask_inputfilter/Validator/NotInArrayValidator.py
index 828e936..0479336 100644
--- a/flask_inputfilter/Validator/NotInArrayValidator.py
+++ b/flask_inputfilter/Validator/NotInArrayValidator.py
@@ -1,7 +1,7 @@
from typing import Any, List, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class NotInArrayValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/NotValidator.py b/flask_inputfilter/Validator/NotValidator.py
index d63f2fe..8fccaf0 100644
--- a/flask_inputfilter/Validator/NotValidator.py
+++ b/flask_inputfilter/Validator/NotValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class NotValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/README.md b/flask_inputfilter/Validator/README.md
deleted file mode 100644
index a157455..0000000
--- a/flask_inputfilter/Validator/README.md
+++ /dev/null
@@ -1,38 +0,0 @@
-# Validator
-
-The `Validator` class is used to validate the data after the filters have been applied.
-
-## Available validators
-
-The following validators are available in the `Validator` module:
-
-1. [`ArrayElementValidator`](ArrayElementValidator.py) - Validates each element of an array with its own defined InputFilter.
-2. [`ArrayLengthValidator`](ArrayLengthValidator.py) - Validates the length of an array.
-3. [`DateAfterValidator`](DateAfterValidator.py) - Validates that the date is after a specified date.
-4. [`DateBeforeValidator`](DateBeforeValidator.py) - Validates that the date is before a specified date.
-5. [`DateRangeValidator`](DateRangeValidator.py) - Validates that the date is within a specified range.
-6. [`FloatPrecisionValidator`](FloatPrecisionValidator.py) - Validates the precision of a float.
-7. [`InArrayValidator`](InArrayValidator.py) - Validates that the value is in the given array.
-8. [`InEnumValidator`](InEnumValidator.py) - Validates that the value is in the given enum.
-9. [`IsArrayValidator`](IsArrayValidator.py) - Validates that the value is an array.
-10. [`IsBase64ImageCorrectSizeValidator`](IsBase64ImageCorrectSizeValidator.py) - Validates that the value is a base64 encoded string.
-11. [`IsBase64ImageValidator`](IsBase64ImageValidator.py) - Validates that the value is a base64 encoded string.
-12. [`IsBooleanValidator`](IsBooleanValidator.py) - Validates that the value is a boolean.
-13. [`IsFloatValidator`](IsFloatValidator.py) - Validates that the value is a float.
-14. [`IsFutureDateValidator`](IsFutureDateValidator.py) - Validates that the value is a future date.
-15. [`IsHexadecimalValidator`](IsHexadecimalValidator.py) - Validates that the value is a hexadecimal string.
-16. [`IsHorizontalImageValidator`](IsHorizontalImageValidator.py) - Validates that the value is a horizontally flipped image.
-17. [`IsInstanceValidator`](IsInstanceValidator.py) - Validates that the value is an instance of a class.
-18. [`IsIntegerValidator`](IsIntegerValidator.py) - Validates that the value is an integer.
-19. [`IsJsonValidator`](IsJsonValidator.py) - Validates that the value is a json string.
-20. [`IsPastDateValidator`](IsPastDateValidator.py) - Validates that the value is a past date.
-21. [`IsStringValidator`](IsStringValidator.py) - Validates that the value is a string.
-22. [`IsUUIDValidator`](IsUUIDValidator.py) - Validates that the value is a UUID.
-23. [`IsVerticalImageValidator`](IsVerticalImageValidator.py) - Validates that the value is a vertically flipped image.
-24. [`IsWeekdayValidator`](IsWeekdayValidator.py) - Validates that the value is a weekday.
-25. [`IsWeekendValidator`](IsWeekendValidator.py) - Validates that the value is a weekend.
-26. [`LengthValidator`](LengthValidator.py) - Validates the length of the value.
-27. [`NotInArrayValidator`](NotInArrayValidator.py) - Validates that the value is not in the given array.
-28. [`NotValidator`](NotValidator.py) - Validates that inverts the result of another validator.
-29. [`RangeValidator`](RangeValidator.py) - Validates that the value is within a specified range.
-30. [`RegexValidator`](RegexValidator.py) - Validates that the value matches a regex pattern.
diff --git a/flask_inputfilter/Validator/RangeValidator.py b/flask_inputfilter/Validator/RangeValidator.py
index 77d78cd..5916e1e 100644
--- a/flask_inputfilter/Validator/RangeValidator.py
+++ b/flask_inputfilter/Validator/RangeValidator.py
@@ -1,7 +1,7 @@
from typing import Any, Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class RangeValidator(BaseValidator):
diff --git a/flask_inputfilter/Validator/RegexValidator.py b/flask_inputfilter/Validator/RegexValidator.py
index fd9741d..a4062c1 100644
--- a/flask_inputfilter/Validator/RegexValidator.py
+++ b/flask_inputfilter/Validator/RegexValidator.py
@@ -1,8 +1,8 @@
import re
from typing import Optional
-from ..Exception import ValidationError
-from .BaseValidator import BaseValidator
+from flask_inputfilter.Exception import ValidationError
+from flask_inputfilter.Validator import BaseValidator
class RegexValidator(BaseValidator):
diff --git a/make.bat b/make.bat
new file mode 100644
index 0000000..dc1312a
--- /dev/null
+++ b/make.bat
@@ -0,0 +1,35 @@
+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+ set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=source
+set BUILDDIR=build
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+ echo.
+ echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+ echo.installed, then set the SPHINXBUILD environment variable to point
+ echo.to the full path of the 'sphinx-build' executable. Alternatively you
+ echo.may add the Sphinx directory to PATH.
+ echo.
+ echo.If you don't have Sphinx installed, grab it from
+ echo.https://www.sphinx-doc.org/
+ exit /b 1
+)
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS% %O%
+
+:end
+popd
diff --git a/source/changelog.rst b/source/changelog.rst
new file mode 100644
index 0000000..60ae212
--- /dev/null
+++ b/source/changelog.rst
@@ -0,0 +1,92 @@
+Changelog
+=========
+
+All notable changes to this project will be documented in this file.
+
+[0.0.8] - 2025-01-16
+--------------------
+
+Added
+^^^^^
+
+- New functionality to define steps for a field to have more control over the
+ order of the validation and filtering process.
+- Documentary
+
+Filter
+""""""
+
+- New `Base64ImageDownscaleFilter `_ to reduce the size of an image.
+- New `Base64ImageResizeFilter `_ to reduce the file size of an image.
+
+Validator
+"""""""""
+
+- New `IsHorizontalImageValidator `_ to check if an image is horizontal.
+- New `IsVerticalImageValidator `_ to check if an image is vertical.
+
+Changed
+^^^^^^^
+
+- Added `UnicodeFormEnum` to show possible config values for `ToNormalizedUnicodeFilter`.
+ Old config is still supported, but will be removed in a later version.
+
+[0.0.7.1] - 2025-01-16
+----------------------
+
+Changed
+^^^^^^^
+
+- Updated `setup.py` to fix the issue with the missing subfolders.
+
+[0.0.7] - 2025-01-14
+--------------------
+
+Added
+^^^^^
+
+- Workflow to run tests on all supported Python versions. [Check it out](.github/workflows/test_env.yaml)
+- Added more test coverage for validators and filters.
+- Added tracking of coverage in tests. `Check it out `_
+- New functionality for global filters and validators in `InputFilters`.
+- New functionality to define custom supported methods.
+
+Validator
+"""""""""
+
+- New `NotInArrayValidator `_ to check if a value is not in a list.
+- New `NotValidator `_ to invert the result of another validator.
+
+[0.0.6] - 2025-01-12
+--------------------
+
+Added
+^^^^^
+
+- New date validators and filters.
+
+Removed
+^^^^^^^
+
+- Dropped support for Python 3.6.
+
+[0.0.5] - 2025-01-12
+--------------------
+
+Added
+^^^^^
+
+- New condition functionality between fields. [Check it out](flask_inputfilter/Condition/README.md)
+
+Changed
+^^^^^^^
+
+- Switched `external_api` config from dict to class. [Check it out](flask_inputfilter/Model/ExternalApiConfig.py)
+
+[0.0.4] - 2025-01-09
+--------------------
+
+Added
+^^^^^
+
+- New external API functionality. [Check it out](docs/EXTERNAL_API.md)
diff --git a/source/conf.py b/source/conf.py
new file mode 100644
index 0000000..c251ae1
--- /dev/null
+++ b/source/conf.py
@@ -0,0 +1,27 @@
+# Configuration file for the Sphinx documentation builder.
+#
+# For the full list of built-in configuration values, see the documentation:
+# https://www.sphinx-doc.org/en/master/usage/configuration.html
+
+# -- Project information -----------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#project-information
+
+project = "flask-inputfilter"
+copyright = "2025, Leander Cain Slotosch"
+author = "Leander Cain Slotosch"
+release = "0.0.8"
+
+# -- General configuration ---------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#general-configuration
+
+extensions = []
+
+templates_path = []
+exclude_patterns = []
+
+
+# -- Options for HTML output -------------------------------------------------
+# https://www.sphinx-doc.org/en/master/usage/configuration.html#options-for-html-output
+
+html_theme = "alabaster"
+html_static_path = []
diff --git a/CONTRIBUTING.md b/source/contributing.rst
similarity index 65%
rename from CONTRIBUTING.md
rename to source/contributing.rst
index 6a10d35..cc099ae 100644
--- a/CONTRIBUTING.md
+++ b/source/contributing.rst
@@ -1,9 +1,9 @@
-# Contributing
+Contributing
+============
-Thank you for considering contributing to the project. To make the process as easy and as effective as possible,
-please follow the guidelines below.
-
-## Reporting Issues
+Thank you for considering contributing to the project. To make the process as easy and as effective as possible, please follow the guidelines below.
+Reporting Issues
+----------------
If you find a bug or have a feature request, please open an issue on the project's GitHub repository.
Before submitting an issue, please search the existing issues to see if your issue has already been reported.
diff --git a/source/development.rst b/source/development.rst
new file mode 100644
index 0000000..6685e93
--- /dev/null
+++ b/source/development.rst
@@ -0,0 +1,36 @@
+Development
+===========
+
+Build docker image
+-------------------
+
+.. code-block:: bash
+
+ docker build -t flask-inputfilter .
+
+Run docker container in interactive mode
+----------------------------------------
+
+.. code-block:: bash
+
+ docker compose up -d
+
+.. code-block:: bash
+
+ docker exec -it flask-inputfilter /bin/bash
+
+Run tests
+---------
+
+.. code-block:: bash
+
+ docker exec -it flask-inputfilter pytest
+
+Run linting
+-----------
+
+.. code-block:: bash
+
+ docker exec -it flask-inputfilter sh -c "isort ."
+ docker exec -it flask-inputfilter sh -c "autoflake --in-place --remove-all-unused-imports --ignore-init-module-imports --recursive ."
+ docker exec -it flask-inputfilter black .
diff --git a/source/guides/create_own.rst b/source/guides/create_own.rst
new file mode 100644
index 0000000..214616f
--- /dev/null
+++ b/source/guides/create_own.rst
@@ -0,0 +1,157 @@
+Create own
+===========
+
+Depending on what you want to build your own version from, there are different
+parameters and return values required to work properly.
+
+- `Condition`_
+- `Filter`_
+- `Validator`_
+
+Inside each ``__init__`` method you can add everything as you wish,
+due it not being called in the validation process.
+Its definition is optional.
+
+Condition
+---------
+
+First off with conditions.
+
+Their validation method is called ``check``.
+It expects a dict from the type ``Dict[str, Any]`` whereas the key (``str``) of the
+dictionary represents the name of a field and the value (``Any``) the corresponding value.
+The dict represents the entirety of all fields present in the InputFilter it is called.
+
+The return value of the method should be ``bool``, representing if the condition is ``true`` or ``false``.
+- ``true``: The condition is met and the validation can proceed
+- ``false``: The validation is **not** met and the validation raises a ``ValidationError``
+
+Example implementation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: python
+
+ from typing import Any, Dict
+
+ from flask_inputfilter.Condition import BaseCondition
+
+
+ class EqualCondition(BaseCondition):
+ """
+ Condition that checks if two fields are equal.
+ """
+
+ def __init__(self, first_field: str, second_field: str) -> None:
+ self.first_field = first_field
+ self.second_field = second_field
+
+ def check(self, data: Dict[str, Any]) -> bool:
+ return data.get(self.first_field) == data.get(self.second_field)
+
+
+Filter
+------
+
+The next type we look at is filters.
+
+Their method called in the validation process is ``apply``.
+It expects ``Any``, representing the value of the specific field, it is applied to.
+
+The return value should have the type ``Any``, representing either the successfully filtered value or
+the value from the input.
+The filter should **not** raise any ``ValidationError``, even if the value is not in the expected format
+to be filtered properly. Instead, it should just return the unfiltered value from the parameters.
+It is not a filers job to check weather a value meets the wanted format or not, that's what ``validators`` are for.
+
+Example implementation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: python
+
+ from datetime import date, datetime
+ from typing import Any, Union
+
+ from flask_inputfilter.Filter import BaseFilter
+
+
+ class ToDateTimeFilter(BaseFilter):
+ """
+ Filter that converts a value to a datetime object.
+ Supports ISO 8601 formatted strings.
+ """
+
+ def apply(self, value: Any) -> Union[datetime, Any]:
+ if isinstance(value, datetime):
+ return value
+
+ elif isinstance(value, date):
+ return datetime.combine(value, datetime.min.time())
+
+ elif isinstance(value, str):
+ try:
+ return datetime.fromisoformat(value)
+
+ except ValueError:
+ return value
+
+ else:
+ return value
+
+
+Validator
+---------
+
+The last type are the validators.
+
+This type is the most important one, as it is the one that raises ensures the value meets the wanted format.
+
+Their method called in the validation process is ``validate``.
+It expects ``Any``, representing the value of the specific field, it is applied to.
+
+The return value should be ``None`` if the value meets the wanted format, and
+it should raise a ``ValidationError`` if the validation fails.
+
+Example implementation
+~~~~~~~~~~~~~~~~~~~~~~~
+
+.. code-block:: python
+
+ from typing import Any, List, Optional
+
+ from flask_inputfilter.Exception import ValidationError
+ from flask_inputfilter.Validator import BaseValidator
+
+
+ class InArrayValidator(BaseValidator):
+ """
+ Validator that checks if a value is in a given list of allowed values.
+ """
+
+ def __init__(
+ self,
+ haystack: List[Any],
+ strict: bool = False,
+ error_message: Optional[str] = None,
+ ) -> None:
+ self.haystack = haystack
+ self.strict = strict
+ self.error_message = error_message
+
+ def validate(self, value: Any) -> None:
+ try:
+ if self.strict:
+ if value not in self.haystack or not any(
+ isinstance(value, type(item)) for item in self.haystack
+ ):
+ raise ValidationError
+
+ else:
+ if value not in self.haystack:
+ raise ValidationError
+
+ except Exception:
+ raise ValidationError(
+ self.error_message
+ or f"Value '{value}' is not in the allowed "
+ f"values '{self.haystack}'."
+ )
diff --git a/source/guides/index.rst b/source/guides/index.rst
new file mode 100644
index 0000000..0956584
--- /dev/null
+++ b/source/guides/index.rst
@@ -0,0 +1,8 @@
+Guides
+======
+
+.. toctree::
+ :maxdepth: 2
+ :glob:
+
+ create_own
diff --git a/source/index.rst b/source/index.rst
new file mode 100644
index 0000000..9f19363
--- /dev/null
+++ b/source/index.rst
@@ -0,0 +1,108 @@
+flask-inputfilter documentation
+===============================
+
+Overview
+--------
+
+.. toctree::
+ :maxdepth: 1
+
+ options/index
+ guides/index
+ changelog
+ contributing
+ development
+
+Available functions:
+--------------------
+
+- :doc:`Creating your own Conditions, Filters and Validators `
+- :doc:`Conditions `
+- :doc:`Filter `
+- :doc:`Validator `
+- :doc:`ExternalApi `
+
+Installation
+------------
+
+.. code-block:: bash
+
+ pip install flask-inputfilter
+
+Quickstart
+----------
+
+To use the `InputFilter` class, create a new class that inherits from it and define the
+fields you want to validate and filter.
+
+There are numerous filters and validators available, but you can also create your [`own`](CreateOwn.md).
+
+Definition
+^^^^^^^^^^
+
+.. code-block:: python
+
+ from flask_inputfilter import InputFilter
+ from flask_inputfilter.Condition import ExactlyOneOfCondition
+ from flask_inputfilter.Enum import RegexEnum
+ from flask_inputfilter.Filter import StringTrimFilter, ToIntegerFilter, ToNullFilter
+ from flask_inputfilter.Validator import IsIntegerValidator, IsStringValidator, RegexValidator
+
+ class UpdateZipcodeInputFilter(InputFilter):
+ def __init__(self):
+ super().__init__()
+
+ self.add(
+ 'id',
+ required=True,
+ filters=[ToIntegerFilter(), ToNullFilter()],
+ validators=[
+ IsIntegerValidator()
+ ]
+ )
+
+ self.add(
+ 'zipcode',
+ filters=[StringTrimFilter()],
+ validators=[
+ RegexValidator(
+ RegexEnum.POSTAL_CODE.value,
+ 'The zipcode is not in the correct format.'
+ )
+ ]
+ )
+
+ self.add(
+ 'city',
+ filters=[StringTrimFilter()],
+ validators=[
+ IsStringValidator()
+ ]
+ )
+
+ self.addCondition(
+ ExactlyOneOfCondition(['zipcode', 'city'])
+ )
+
+Usage
+^^^^^
+
+To use the `InputFilter` class, call the `validate` method on the class instance.
+After calling `validate`, the validated data will be available in `g.validated_data`.
+If the data is invalid, a 400 response with an error message will be returned.
+
+.. code-block:: python
+
+ from flask import Flask, g
+ from your-path import UpdateZipcodeInputFilter
+
+ app = Flask(__name__)
+
+ @app.route('/update-zipcode', methods=['POST'])
+ @UpdateZipcodeInputFilter.validate()
+ def updateZipcode():
+ data = g.validated_data
+
+ # Do something with validated data
+ id = data.get('id')
+ zipcode = data.get('zipcode')
diff --git a/source/options/condition.rst b/source/options/condition.rst
new file mode 100644
index 0000000..30bf431
--- /dev/null
+++ b/source/options/condition.rst
@@ -0,0 +1,63 @@
+Condition
+=========
+
+The `Condition` module contains the conditions that can be used to validate the input data.
+
+Conditions
+----------
+
+The `addCondition` method is used to add a condition between fields.
+
+Example
+-------
+
+.. code-block:: python
+
+ from flask_inputfilter import InputFilter
+ from flask_inputfilter.Condition import OneOfCondition
+ from flask_inputfilter.Filter import StringTrimFilter
+ from flask_inputfilter.Validator import IsStringValidator
+
+
+ class TestInputFilter(InputFilter):
+ def __init__(self):
+ super().__init__()
+
+ self.add(
+ 'username',
+ filters=[StringTrimFilter()],
+ validators=[IsStringValidator()]
+ )
+
+ self.add(
+ 'name',
+ filters=[StringTrimFilter()],
+ validators=[IsStringValidator()]
+ )
+
+ self.addCondition(
+ OneOfCondition(['id', 'name'])
+ )
+
+Available Conditions
+--------------------
+
+The following conditions are available in the `Condition` module:
+
+1. `ArrayLengthEqualCondition` - Validates that the length of the array is equal to the given value.
+2. `ArrayLongerThanCondition` - Validates that the length of the array is longer than the given value.
+3. `CustomCondition` - A custom condition that can be used to validate the input data.
+4. `EqualCondition` - Validates that the input is equal to the given value.
+5. `ExactlyNOfCondition` - Validates that exactly `n` of the given conditions are true.
+6. `ExactlyNOfMatchesCondition` - Validates that exactly `n` of the given matches are true.
+7. `ExactlyOneOfCondition` - Validates that exactly one of the given conditions is true.
+8. `ExactlyOneOfMatchesCondition` - Validates that exactly one of the given matches is true.
+9. `IntegerBiggerThanCondition` - Validates that the integer is bigger than the given value.
+10. `NOfCondition` - Validates that at least `n` of the given conditions are true.
+11. `NOfMatchesCondition` - Validates that at least `n` of the given matches are true.
+12. `NotEqualCondition` - Validates that the input is not equal to the given value.
+13. `OneOfCondition` - Validates that at least one of the given conditions is true.
+14. `OneOfMatchesCondition` - Validates that at least one of the given matches is true.
+15. `RequiredIfCondition` - Validates that the input is required if the given field has a specific value.
+16. `StringLongerThanCondition` - Validates that the string is longer than the given value.
+17. `TemporalOrderCondition` - Validates that the input is in correct temporal order.
diff --git a/source/options/external_api.rst b/source/options/external_api.rst
new file mode 100644
index 0000000..095264b
--- /dev/null
+++ b/source/options/external_api.rst
@@ -0,0 +1,127 @@
+External API
+============
+
+This documentation provides a comprehensive overview of the external API functionality available in the `InputFilter` class. It covers the configuration, core methods, and examples of usage for interacting with external APIs.
+
+Overview
+--------
+
+The `InputFilter` class includes a mechanism for fetching data from external APIs during the input validation process.
+This feature allows dynamic data retrieval based on user inputs, such as validating fields or fetching related data from an external service.
+
+.. note::
+
+ The external API functionality runs **after** all other filters and validators have been executed.
+ This means the data fetched from the external API will not be validated or filtered.
+
+Configuration
+-------------
+
+The external API functionality is configured via the ``external_api`` parameter in the ``add`` method. This parameter accepts a dictionary with the following structure:
+
+Fields of `ExternalApiConfig`
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. list-table:: External API Configuration Fields
+ :header-rows: 1
+
+ * - Field
+ - Type
+ - Description
+ * - ``url``
+ - ``str``
+ - The URL of the external API, with optional placeholders in ``{{ }}`` format.
+ * - ``method``
+ - ``str``
+ - The HTTP method to use (e.g., ``GET``, ``POST``).
+ * - ``params``
+ - ``Optional[Dict[str, str]]``
+ - Query parameters for the API, with placeholders allowed.
+ * - ``data_key``
+ - ``Optional[str]``
+ - Key in the JSON response to extract the required data.
+ * - ``api_key``
+ - ``Optional[str]``
+ - API key for authorization, sent in the ``Authorization`` header.
+
+Examples
+--------
+
+Basic External API Integration
+^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: python
+
+ from flask_inputfilter.InputFilter import InputFilter
+
+ class MyInputFilter(InputFilter):
+ def __init__(self):
+ super().__init__()
+
+ self.add(
+ "user_id", required=True
+ )
+ self.add(
+ "is_active",
+ required=True,
+ external_api={
+ "url": "https://api.example.com/users/{{user_id}}/status",
+ "method": "GET",
+ "data_key": "is_active",
+ },
+ )
+
+ # Example usage
+ filter_instance = MyInputFilter()
+ validated_data = filter_instance.validateData({"user_id": 123})
+ print(validated_data["is_active"]) # True or False based on API response
+
+Using Query Parameters
+^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: python
+
+ self.add(
+ "is_valid",
+ required=True,
+ external_api={
+ "url": "https://api.example.com/validate",
+ "method": "GET",
+ "params": {"user": "{{user_id}}", "hash": "{{hash}}"},
+ "data_key": "is_valid",
+ },
+ )
+
+This configuration sends the ``user_id`` and ``hash`` as query parameters, replacing the placeholders with validated data.
+
+Handling Fallback Values
+^^^^^^^^^^^^^^^^^^^^^^^^
+
+.. code-block:: python
+
+ self.add(
+ "user_info",
+ required=True,
+ fallback={"name": "unknown", "age": 0},
+ external_api={
+ "url": "https://api.example.com/user/{{user_id}}",
+ "method": "GET",
+ "data_key": "user",
+ },
+ )
+
+Error Handling
+--------------
+
+- **ValidationError** is raised when:
+ - The API call returns a non-200 status code.
+ - A required field is missing and no fallback/default is provided.
+ - Validation of the field value fails.
+
+Best Practices
+--------------
+
+- **Required Fields:** Clearly define required fields and provide fallback values where necessary.
+- **Placeholders:** Ensure placeholders in URLs and parameters match the keys in ``validated_data``.
+- **Fallbacks:** Always provide fallback values for critical fields to avoid disruptions in case of API failure.
+- **Security:** Use HTTPS for API calls and secure sensitive data like API keys.
diff --git a/source/options/filter.rst b/source/options/filter.rst
new file mode 100644
index 0000000..cf4d010
--- /dev/null
+++ b/source/options/filter.rst
@@ -0,0 +1,69 @@
+Filter
+======
+
+The ``Filter`` module contains the filters that can be used to filter the input data.
+
+Filters
+-------
+
+Filters can be added into the ``add`` method for a specific field or as a global filter for all fields in ``addGlobalFilter``.
+
+The global filters will be executed before the specific field filtering.
+
+Example
+-------
+
+.. code:: python
+
+ from flask_inputfilter import InputFilter
+ from flask_inputfilter.Filter import StringTrimFilter, ToLowerFilter
+
+ class TestInputFilter(InputFilter):
+ def __init__(self):
+ super().__init__()
+
+ self.add(
+ 'username',
+ required=True,
+ filters=[StringTrimFilter()]
+ )
+
+ self.add(
+ 'name',
+ required=True,
+ filters=[StringTrimFilter()]
+ )
+
+ self.addGlobalFilter(ToLowerFilter())
+
+Available Filters
+-----------------
+
+The following filters are available in the ``Filter`` module:
+
+1. `ArrayExplodeFilter <../flask_inputfilter/Filter/ArrayExplodeFilter.py>`_ - Explodes the input string into an array.
+2. `Base64ImageDownscaleFilter <../flask_inputfilter/Filter/Base64ImageDownscaleFilter.py>`_ - Downscale the base64 image.
+3. `Base64ImageResizeFilter <../flask_inputfilter/Filter/Base64ImageResizeFilter.py>`_ - Resize the base64 image.
+4. `BlacklistFilter <../flask_inputfilter/Filter/BlacklistFilter.py>`_ - Filters the string based on the blacklist.
+5. `RemoveEmojisFilter <../flask_inputfilter/Filter/RemoveEmojisFilter.py>`_ - Removes the emojis from the string.
+6. `SlugifyFilter <../flask_inputfilter/Filter/SlugifyFilter.py>`_ - Converts the string to a slug.
+7. `StringTrimFilter <../flask_inputfilter/Filter/StringTrimFilter.py>`_ - Trims the whitespace from the beginning and end of the string.
+8. `ToAlphaNumericFilter <../flask_inputfilter/Filter/ToAlphaNumericFilter.py>`_ - Converts the string to an alphanumeric string.
+9. `ToBooleanFilter <../flask_inputfilter/Filter/ToBooleanFilter.py>`_ - Converts the string to a boolean value.
+10. `ToCamelCaseFilter <../flask_inputfilter/Filter/ToCamelCaseFilter.py>`_ - Converts the string to camel case.
+11. `ToDateFilter <../flask_inputfilter/Filter/ToDateFilter.py>`_ - Converts a string to a date value.
+12. `ToDateTimeFilter <../flask_inputfilter/Filter/ToDateTimeFilter.py>`_ - Converts a string to a datetime value.
+13. `ToEnumFilter <../flask_inputfilter/Filter/ToEnumFilter.py>`_ - Converts a string or integer to an enum value.
+14. `ToFloatFilter <../flask_inputfilter/Filter/ToFloatFilter.py>`_ - Converts a string to a float value.
+15. `ToIntegerFilter <../flask_inputfilter/Filter/ToIntegerFilter.py>`_ - Converts a string to an integer value.
+16. `ToIsoFilter <../flask_inputfilter/Filter/ToIsoFilter.py>`_ - Converts a string to an ISO8601 date time value.
+17. `ToLowerFilter <../flask_inputfilter/Filter/ToLowerFilter.py>`_ - Converts a string to lowercase.
+18. `ToNormalizedUnicodeFilter <../flask_inputfilter/Filter/ToNormalizedUnicodeFilter.py>`_ - Normalizes a unicode string.
+19. `ToNullFilter <../flask_inputfilter/Filter/ToNullFilter.py>`_ - Converts the string to ``None`` if it is already ``None`` or ``''`` (empty string).
+20. `ToPascaleCaseFilter <../flask_inputfilter/Filter/ToPascaleCaseFilter.py>`_ - Converts the string to pascal case.
+21. `ToSnakeCaseFilter <../flask_inputfilter/Filter/ToSnakeCaseFilter.py>`_ - Converts the string to snake case.
+22. `ToStringFilter <../flask_inputfilter/Filter/ToStringFilter.py>`_ - Converts the input to a string value.
+23. `ToUpperFilter <../flask_inputfilter/Filter/ToUpperFilter.py>`_ - Converts the string to uppercase.
+24. `TruncateFilter <../flask_inputfilter/Filter/TruncateFilter.py>`_ - Truncates the string to the specified length.
+25. `WhitelistFilter <../flask_inputfilter/Filter/WhitelistFilter.py>`_ - Filters the string based on the whitelist.
+26. `WhitespaceCollapseFilter <../flask_inputfilter/Filter/WhitespaceCollapseFilter.py>`_ - Collapses the whitespace in the string.
diff --git a/source/options/index.rst b/source/options/index.rst
new file mode 100644
index 0000000..f96aba4
--- /dev/null
+++ b/source/options/index.rst
@@ -0,0 +1,69 @@
+Options
+=======
+
+.. toctree::
+ :maxdepth: 2
+
+ condition
+ validator
+ external_api
+ filter
+
+The `add` method supports several options:
+
+- `Required`_
+- `Filter`_
+- `Validator`_
+- `Default`_
+- `Fallback`_
+- `Steps`_
+- `ExternalApi`_
+
+Required
+--------
+
+The ``required`` option specifies whether the field must be included in the input data.
+If the field is missing, a ``ValidationError`` will be raised with an appropriate error message.
+
+Filter
+------
+
+The ``filters`` option allows you to specify one or more filters to apply to the field value.
+Filters are applied in the order they are defined.
+
+For more information view the :doc:`Filter ` documentation.
+
+Validator
+---------
+
+The ``validators`` option allows you to specify one or more validators to apply to the field value.
+Validators are applied in the order they are defined.
+
+For more information view the :doc:`Validator ` documentation.
+
+Default
+-------
+
+The ``default`` option allows you to specify a default value to use if the field is not
+present in the input data.
+
+Fallback
+--------
+
+The ``fallback`` option specifies a value to use if validation fails or required data
+is missing. Note that if the field is optional and absent, ``fallback`` will not apply;
+use ``default`` in such cases.
+
+Steps
+-----
+
+The ``steps`` option allows you to specify a list of different filters and validator to apply to the field value.
+It respects the order of the list.
+
+ExternalApi
+-----------
+
+The ``external_api`` option allows you to specify an external API to call for the field value.
+The API call is made when the field is validated, and the response is used as the field value.
+
+For more information view the :doc:`ExternalApi ` documentation.
diff --git a/source/options/validator.rst b/source/options/validator.rst
new file mode 100644
index 0000000..96887ad
--- /dev/null
+++ b/source/options/validator.rst
@@ -0,0 +1,75 @@
+Validator
+=========
+
+The `Validator` class is used to validate the data after the filters have been applied.
+
+Validators
+----------
+
+Validators can be added into the `add` method for a specific field or as a global validator for all fields in `addGlobalValidator`.
+
+The global validation will be executed before the specific field validation.
+
+Example
+-------
+
+Here is an example of how to use validators in an `InputFilter`:
+
+.. code-block:: python
+
+ from flask_inputfilter import InputFilter
+ from flask_inputfilter.Validator import IsIntegerValidator, RangeValidator
+
+
+ class UpdatePointsInputFilter(InputFilter):
+ def __init__(self):
+ super().__init__()
+
+ self.add(
+ 'id',
+ required=True
+ )
+
+ self.add(
+ 'points',
+ required=True,
+ validators=[RangeValidator(min_value=0, max_value=10)]
+ )
+
+ self.addGlobalValidator(IsIntegerValidator())
+
+Available Validators
+--------------------
+
+The following validators are available in the `Validator` module:
+
+1. :doc:`ArrayElementValidator <../flask_inputfilter/Validator/ArrayElementValidator>`
+2. :doc:`ArrayLengthValidator <../flask_inputfilter/Validator/ArrayLengthValidator>`
+3. :doc:`DateAfterValidator <../flask_inputfilter/Validator/DateAfterValidator>`
+4. :doc:`DateBeforeValidator <../flask_inputfilter/Validator/DateBeforeValidator>`
+5. :doc:`DateRangeValidator <../flask_inputfilter/Validator/DateRangeValidator>`
+6. :doc:`FloatPrecisionValidator <../flask_inputfilter/Validator/FloatPrecisionValidator>`
+7. :doc:`InArrayValidator <../flask_inputfilter/Validator/InArrayValidator>`
+8. :doc:`InEnumValidator <../flask_inputfilter/Validator/InEnumValidator>`
+9. :doc:`IsArrayValidator <../flask_inputfilter/Validator/IsArrayValidator>`
+10. :doc:`IsBase64ImageCorrectSizeValidator <../flask_inputfilter/Validator/IsBase64ImageCorrectSizeValidator>`
+11. :doc:`IsBase64ImageValidator <../flask_inputfilter/Validator/IsBase64ImageValidator>`
+12. :doc:`IsBooleanValidator <../flask_inputfilter/Validator/IsBooleanValidator>`
+13. :doc:`IsFloatValidator <../flask_inputfilter/Validator/IsFloatValidator>`
+14. :doc:`IsFutureDateValidator <../flask_inputfilter/Validator/IsFutureDateValidator>`
+15. :doc:`IsHexadecimalValidator <../flask_inputfilter/Validator/IsHexadecimalValidator>`
+16. :doc:`IsHorizontalImageValidator <../flask_inputfilter/Validator/IsHorizontalImageValidator>`
+17. :doc:`IsInstanceValidator <../flask_inputfilter/Validator/IsInstanceValidator>`
+18. :doc:`IsIntegerValidator <../flask_inputfilter/Validator/IsIntegerValidator>`
+19. :doc:`IsJsonValidator <../flask_inputfilter/Validator/IsJsonValidator>`
+20. :doc:`IsPastDateValidator <../flask_inputfilter/Validator/IsPastDateValidator>`
+21. :doc:`IsStringValidator <../flask_inputfilter/Validator/IsStringValidator>`
+22. :doc:`IsUUIDValidator <../flask_inputfilter/Validator/IsUUIDValidator>`
+23. :doc:`IsVerticalImageValidator <../flask_inputfilter/Validator/IsVerticalImageValidator>`
+24. :doc:`IsWeekdayValidator <../flask_inputfilter/Validator/IsWeekdayValidator>`
+25. :doc:`IsWeekendValidator <../flask_inputfilter/Validator/IsWeekendValidator>`
+26. :doc:`LengthValidator <../flask_inputfilter/Validator/LengthValidator>`
+27. :doc:`NotInArrayValidator <../flask_inputfilter/Validator/NotInArrayValidator>`
+28. :doc:`NotValidator <../flask_inputfilter/Validator/NotValidator>`
+29. :doc:`RangeValidator <../flask_inputfilter/Validator/RangeValidator>`
+30. :doc:`RegexValidator <../flask_inputfilter/Validator/RegexValidator>`