Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ jobs:
set -e # Exit immediately if a command exits with a non-zero status
set -u # Exit immediately if a variable is not defined

docker run --rm flask-inputfilter-pure flake8
docker run --rm flask-inputfilter-pure ruff check

build-and-test-cython:
runs-on: ubuntu-latest
Expand Down
6 changes: 4 additions & 2 deletions MANIFEST.in
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
include docs/source/index.rst
include LICENSE
include docs/source/changelog.rst
recursive-include flask_inputfilter *.py *.pyi *.pyx *.pxd *.c *.cpp
recursive-include flask_inputfilter/include *.h
recursive-include flask_inputfilter *.py *.pyi *.pyx *.pxd *.h

recursive-exclude flask_inputfilter *.cpp

prune tests
recursive-prune __pycache__
4 changes: 2 additions & 2 deletions docs/source/conf.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import os
import sys
from pathlib import Path

project = "flask-inputfilter"
copyright = "2025, Leander Cain Slotosch"
Expand Down Expand Up @@ -31,7 +31,7 @@
napoleon_google_docstring = True
napoleon_numpy_docstring = False

sys.path.insert(0, os.path.abspath("../.."))
sys.path.insert(0, str(Path("../..").resolve()))

templates_path = []
exclude_patterns = []
Expand Down
6 changes: 3 additions & 3 deletions docs/source/guides/create_own_components.rst
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ Example implementation

from typing import Any

from flask_inputfilter.conditions import BaseCondition
from flask_inputfilter.models import BaseCondition


class EqualCondition(BaseCondition):
Expand Down Expand Up @@ -71,7 +71,7 @@ Example implementation
from datetime import date, datetime
from typing import Any

from flask_inputfilter.filters import BaseFilter
from flask_inputfilter.models import BaseFilter


class ToDateTimeFilter(BaseFilter):
Expand Down Expand Up @@ -118,7 +118,7 @@ Example implementation
from typing import Any, Optional

from flask_inputfilter.exceptions import ValidationError
from flask_inputfilter.validators import BaseValidator
from flask_inputfilter.models import BaseValidator


class InArrayValidator(BaseValidator):
Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from .product_inputfilter import ProductInputFilter
from .profile_inputfilter import ProfileInputFilter
from .user_inputfilter import UserInputFilter

__all__ = ["ProductInputFilter", "ProfileInputFilter", "UserInputFilter"]
File renamed without changes.
48 changes: 32 additions & 16 deletions flask_inputfilter/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,31 +3,47 @@

except ImportError:
import shutil
from pathlib import Path

if shutil.which("g++") is not None:
import os
_HAS_GPP = shutil.which("g++") is not None

import pyximport
if _HAS_GPP:
try:
import pyximport

THIS_DIR = os.path.dirname(__file__)
INCLUDE_DIR = os.path.join(THIS_DIR, "include")
THIS_DIR = Path(__file__).parent
INCLUDE_DIR = THIS_DIR / "include"

pyximport.install(
language_level=3,
setup_args={
"script_args": ["--quiet"],
"include_dirs": [INCLUDE_DIR],
},
reload_support=True,
)
pyximport.install(
language_level=3,
setup_args={
"script_args": ["--quiet"],
"include_dirs": [str(INCLUDE_DIR)],
},
reload_support=True,
)

from ._input_filter import InputFilter

from ._input_filter import InputFilter
except ImportError:
import logging

logging.getLogger(__name__).debug(
"Pyximport failed, falling back to pure Python implementation."
)
from .input_filter import InputFilter

else:
import logging

logging.getLogger(__name__).warning(
"Cython or g++ not available. Falling back to pure Python implementation.\n"
"Consult docs for better performance: https://leandercs.github.io/flask-inputfilter/guides/compile.html"
"Cython or g++ not available. Falling back to pure Python "
"implementation.\n"
"Consult docs for better performance: https://leandercs.github.io"
"/flask-inputfilter/guides/compile.html"
)
from .input_filter import InputFilter

__all__ = [
"InputFilter",
]
76 changes: 76 additions & 0 deletions flask_inputfilter/_input_filter.pxd
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
# cython: language=c++
from typing import Any

from flask_inputfilter.models.cimports cimport BaseCondition, BaseFilter, BaseValidator, ExternalApiConfig, FieldModel

from libcpp.vector cimport vector
from libcpp.string cimport string


cdef extern from "helper.h":
vector[string] make_default_methods()


cdef class InputFilter:
cdef readonly:
vector[string] methods
dict[str, FieldModel] fields
list[BaseCondition] conditions
list[BaseFilter] global_filters
list[BaseValidator] global_validators
dict[str, Any] data
dict[str, Any] validated_data
dict[str, str] errors
object model_class

cpdef bint is_valid(self)
cpdef object validate_data(self, dict data=*)
cpdef void add_condition(self, BaseCondition condition)
cpdef list get_conditions(self)
cpdef void set_data(self, dict data)
cpdef object get_value(self, str name)
cpdef dict get_values(self)
cpdef object get_raw_value(self, str name)
cpdef dict get_raw_values(self)
cpdef dict get_unfiltered_data(self)
cpdef void set_unfiltered_data(self, dict data)
cpdef bint has_unknown(self)
cpdef str get_error_message(self, str field_name)
cpdef dict get_error_messages(self)
cpdef void add(
self,
str name,
bint required=*,
object default=*,
object fallback=*,
list filters=*,
list validators=*,
list steps=*,
ExternalApiConfig external_api=*,
str copy=*,
) except*
cpdef bint has(self, str field_name)
cpdef FieldModel get_input(self, str field_name)
cpdef dict get_inputs(self)
cpdef object remove(self, str field_name)
cpdef int count(self)
cpdef void replace(
self,
str name,
bint required=*,
object default=*,
object fallback=*,
list[BaseFilter] filters=*,
list[BaseValidator] validators=*,
list steps=*,
ExternalApiConfig external_api=*,
str copy=*,
)
cpdef void add_global_filter(self, BaseFilter filter)
cpdef list get_global_filters(self)
cpdef void clear(self)
cpdef void merge(self, InputFilter other)
cpdef void set_model(self, object model_class)
cpdef object serialize(self)
cpdef void add_global_validator(self, BaseValidator validator)
cpdef list[BaseValidator] get_global_validators(self)
Loading