API Documentation

class filters.base.BaseFilter

Base functionality for all Filters, macros, etc.

CODE_EXCEPTION = 'exception'
apply(value)

Applies the filter to a value.

property handler: BaseInvalidValueHandler

Returns the invalid value handler for the filter.

property key: str

Returns the key associated with this filter.

property parent: BaseFilter | None

Returns the parent Filter.

classmethod resolve_filter(the_filter: BaseFilter | FilterMeta | Callable[[], BaseFilter] | None, parent: BaseFilter | None = None, key: str | None = None) FilterChain | None

Converts a filter-compatible value into a consistent type.

set_handler(handler: BaseInvalidValueHandler) BaseFilter

Cascading method for setting the filter’s invalid value handler.

sub_key(sub_key: str) str

Returns a copy of this filter’s key with an additional sub-key appended.

templates = {'exception': 'An error occurred while processing this value.'}
class filters.base.BaseInvalidValueHandler

Base functionality for classes that handle invalid values.

handle_exception(message: str, exc: Exception) Any

Handles an uncaught exception.

abstractmethod handle_invalid_value(message: str, exc_info: bool, context: MutableMapping) Any

Handles an invalid value.

Parameters:
  • message – Error message.

  • exc_info – Whether to include output from :py:func:sys.exc_info.

  • context – Additional context values for the error.

class filters.base.ExceptionHandler

Invalid value handler that raises an exception.

handle_invalid_value(message: str, exc_info: bool, context: MutableMapping) None

Handles an invalid value.

Parameters:
  • message – Error message.

  • exc_info – Whether to include output from :py:func:sys.exc_info.

  • context – Additional context values for the error.

class filters.base.FilterChain(start_filter: BaseFilter | FilterMeta | Callable[[], BaseFilter] | None = None)

Allows you to chain multiple filters together so that they are treated as a single filter.

templates = {'exception': 'An error occurred while processing this value.'}
filters.base.FilterCompatible = ForwardRef('BaseFilter') | ForwardRef('FilterMeta') | collections.abc.Callable[[], 'BaseFilter'] | None

Used in PEP-484 type hints to indicate a value that can be normalised into an instance of a BaseFilter subclass.

exception filters.base.FilterError(*args, **kwargs)

Indicates that a parsed value could not be filtered because the value was invalid.

Provides a container to include additional variables and other information to help troubleshoot errors.

class filters.base.FilterMeta(name, bases, namespace, /, **kwargs)

Metaclass for filters.

class filters.base.Type(allowed_types: type | tuple[type, ...], allow_subclass: bool = True, aliases: Mapping[type, str] | None = None)

Checks the type of a value.

Parameters:
  • allowed_types – The type (or types) that incoming values are allowed to have.

  • allow_subclass – Whether to allow subclasses when checking for type matches.

  • aliases

    Aliases to use for type names in error messages.

    This is useful for providing more context- appropriate names to end users and/or masking native Python type names.

CODE_WRONG_TYPE = 'wrong_type'
get_allowed_type_names(aliased: bool = True) str

Returns a string with all the allowed types.

get_type_name(type_: type, aliased: bool = True) str

Returns the name of the specified type.

templates = {'exception': 'An error occurred while processing this value.', 'wrong_type': '{incoming} is not valid (allowed types: {allowed}).'}
class filters.complex.FilterMapper(filter_map: Mapping[str, BaseFilter | FilterMeta | Callable[[], BaseFilter] | None], allow_missing_keys: bool | Iterable[str] = True, allow_extra_keys: bool | Iterable[str] = True)

Given a dict of filters, applies each filter to the corresponding value in incoming mappings.

The resulting value is a dict. The order of keys in the filter_map passed to the initialiser determines the order of keys in the filtered value.

Note

The order of extra keys is undefined, but they will always be last.

Initialises the FilterMapper filter.

Parameters:
  • filter_map – Maps each filter chain to the corresponding key that it will be applied to.

  • allow_missing_keys

    Determines how values with missing keys (according to filter_map) get handled:

    • True: The missing values are set to None and then filtered as normal.

    • False: Missing keys are treated as invalid values.

    • <Iterable>: Only the specified keys are allowed to be omitted.

  • allow_extra_keys

    Determines how values with extra keys (according to filter_map) get handled:

    • True: The extra values are passed through to the filtered value.

    • False: Extra values are treated as invalid values and omitted from the filtered value.

    • <Iterable>: Only the specified extra keys are allowed.

CODE_EXTRA_KEY = 'unexpected'
CODE_MISSING_KEY = 'missing'
iter(value: Mapping) Generator[tuple[str, Any], None, None]

Iterator version of apply().

templates = {'exception': 'An error occurred while processing this value.', 'missing': '{key} is required.', 'unexpected': 'Unexpected key "{actual_key}".'}
static unicodify_key(key: Any) str

Converts a key value into a unicode so that it can be represented in e.g., error message contexts.

class filters.complex.FilterRepeater(filter_chain: BaseFilter | FilterMeta | Callable[[], BaseFilter] | None, restrict_keys: Iterable | None = None)

Applies a filter to every value in an Iterable.

You can apply a FilterRepeater to a dict (or other Mapping). The filters will be applied to the Mapping’s values.

Note

The resulting value will be coerced to a list or dict (depending on the input value).

Initialises the FilterRepeater filter.

Parameters:
  • filter_chain – The filter(s) that will be applied to each item in the incoming iterables.

  • restrict_keys

    Only these keys/indexes will be allowed (any other keys/indexes encountered will be treated as invalid values).

    Important: If this is an empty container will result in EVERY key/index being rejected!

    Set to None (default) to allow any key/index.

CODE_EXTRA_KEY = 'unexpected'
iter(value: Iterable) Generator[Any, None, None]

Iterator version of apply().

mapping_result_type

alias of dict

sequence_result_type

alias of list

templates = {'exception': 'An error occurred while processing this value.', 'unexpected': 'Unexpected key "{key}".'}
static unicodify_key(key: Any) str

Converts a key value into a unicode so that it can be represented in e.g., error message contexts.

class filters.complex.FilterSwitch(getter: Callable[[Any], Hashable], cases: Mapping[Hashable, BaseFilter | FilterMeta | Callable[[], BaseFilter] | None], default: BaseFilter | FilterMeta | Callable[[], BaseFilter] | None = None)

Chooses the next filter to apply based on the output of a callable.

Initialises the FilterSwitch filter.

Parameters:
  • getter – Callable used to extract the value to match against switch cases.

  • cases – Mapping of possible values to the corresponding filters.

  • default

    Default filter to use, if none of the cases are matched.

    If null (default) then the value will be considered invalid if it doesn’t match any cases.

templates = {'exception': 'An error occurred while processing this value.'}
class filters.complex.NamedTuple(type_: type[tuple], filter_map: Mapping[str, BaseFilter | FilterMeta | Callable[[], BaseFilter] | None] | None = None)

Attempts to convert the incoming value into a namedtuple.

Initialises the NamedTuple filter.

Parameters:
  • type – The type of namedtuple into which the filter will attempt to convert incoming values.

  • filter_map

    Specifies additional filters that should be applied to each attribute in the resulting namedtuple object.

    For example:

    >>> import filters as f
    >>> from collections import namedtuple
    >>> Color = namedtuple('Color', ('r', 'g', 'b'))
    
    >>> # noinspection PyTypeChecker
    >>> filter_chain = f.NamedTuple(Color, {
    ...     'r': f.Required | f.Int | f.Min(0) | f.Max(255),
    ...     'g': f.Required | f.Int | f.Min(0) | f.Max(255),
    ...     'b': f.Required | f.Int | f.Min(0) | f.Max(255),
    ... })
    
    >>> filter_chain.apply(['64', '128', '192'])
    Color(r=64, g=128, b=192)
    

templates = {'exception': 'An error occurred while processing this value.'}
class filters.extensions.FilterExtensionRegistry(group: str = 'filters.extensions')

Creates a registry that can be used to dynamically load 3rd-party filters into the (nearly) top-level namespace.

Initialises the FilterExtensionRegistry.

Parameters:

group – The entry point group name to use. Defaults to GROUP_NAME.

static create_instance(class_: type, *args, **kwargs) Any

Returns the class itself when called with no arguments.

Overrides the default behaviour (which would instantiate the class) so that extension filters behave consistently with filters.base.FilterMeta.__or__(), which chains uninstantiated filter classes directly (e.g. filters.ext.MyFilter | OtherFilter).

Parameters:
  • class – The filter class to return or instantiate.

  • *args – Positional arguments forwarded to the class constructor.

  • **kwargs – Keyword arguments forwarded to the class constructor.

Returns:

The class itself if no arguments are provided; otherwise a new instance of the class.

filters.extensions.GROUP_NAME = 'filters.extensions'

The key to use when declaring entry points in pyproject.toml.

Example:

[project.entry-points."filters.extensions"]
Country = "filters_iso:Country"
Currency = "filters_iso:Currency"

Filters that are loaded this way are accessible from filters.ext (not imported into the global namespace because it gives IDEs a heart attack).

class filters.handlers.FilterMessage(message: str, context: MutableMapping, exc_info: str | None = None)

Provides a consistent API for messages sent to MemoryHandler.

Initialises the FilterMessage.

Parameters:
  • message – The error message.

  • context – The context mapping.

  • exc_info – Exception traceback (if applicable).

as_dict(with_debug_info: bool = False) dict

Returns a dict representation of the FilterMessage.

Parameters:

with_debug_info – Whether to include context and exception traceback in the result.

Returns:

Dict representation with code and message, and optionally context and exc_info if with_debug_info is True.

class filters.handlers.FilterRunner(starting_filter: BaseFilter | FilterMeta | Callable[[], BaseFilter] | None, incoming_data: Any = None, capture_exc_info: bool = False)

Wrapper for a filter that provides an API similar to what you would expect from a Django form – at least, when it comes to methods related to data validation :)

Initialises the FilterRunner.

Parameters:
  • starting_filter – The filter to run.

  • incoming_data – E.g., request.POST.

  • capture_exc_info

    Whether to capture sys.exc_info when handling an exception.

    This is turned off by default to reduce memory usage, but it is useful in certain cases (e.g., if you want to send exceptions to a logger).

    Regardless, you can still check self.has_exceptions to see if an exception occurred.

apply(incoming_data: Any)

Reruns the filter chain against a new value.

Parameters:

incoming_data – The new value to filter.

property cleaned_data

Returns the resulting value after applying the filter.

Returns:

The resulting value after applying the request filter.

property error_codes: dict[str, list[str]]

Returns a dict of error codes generated by the Filter.

Returns:

Dict mapping keys to lists of error codes.

property errors: dict[str, list[dict[str, str]]]

Returns a dict of error messages generated by the Filter.

The format is suitable for inclusion in e.g., a 400 Bad Request response payload.

Example:

{
    'authToken': [
        {
            'code':     'not_found',
            'message':
                'No AuthToken found matching this value.',
        },
    ],

    'data.foobar': [
        {
            'code':     'unexpected',
            'message':  'Unexpected key "foobar".',
        },
    ],

    # etc.
}
Returns:

Dict mapping keys to lists of error dicts.

property exc_info: list[tuple[type, Exception, TracebackType]]

Returns tracebacks from any exceptions that were captured.

Returns:

List of exception info tuples (type, exception, traceback).

property filter_messages: dict[str, list[FilterMessage]]

Returns the raw FilterMessages generated by the Filter.

Returns:

Dict mapping keys to lists of FilterMessage objects.

full_clean()

Applies the filter to the request data.

get_errors(with_context: bool = False) dict[str, list[dict[str, str]]]

Returns a dict of error messages generated by the Filter.

The format is suitable for inclusion in e.g., a 400 Bad Request response payload.

Parameters:

with_context

Whether to include the context object in the result (for debugging purposes).

Note: context is usually not safe to expose to clients!

Returns:

Dict mapping keys to lists of error dicts.

property has_exceptions: bool

Returns whether any unhandled exceptions occurred.

Returns:

Whether any unhandled exceptions occurred while filtering the value.

is_valid() bool

Returns whether the payload successfully passed the Filter.

Returns:

True if no filter messages were generated, False otherwise.

class filters.handlers.LogHandler(logger: Logger | LoggerAdapter, level: int = 40)

Invalid value handler that sends the details to a logger.

Initialises the LogHandler.

Parameters:
  • logger – The logger that log messages will get sent to.

  • level – Level of the logged messages.

handle_invalid_value(message: str, exc_info: bool, context: MutableMapping) None

Handles an invalid value.

Parameters:
  • message – Error message.

  • exc_info – Whether to include output from :py:func:sys.exc_info.

  • context – Additional context values for the error.

class filters.handlers.MemoryHandler(capture_exc_info: bool = False)

Invalid value handler that stores messages locally.

Initialises the MemoryHandler.

Parameters:

capture_exc_info

Whether to capture sys.exc_info when handling an exception.

This is turned off by default to reduce memory usage, but it is useful in certain cases (e.g., if you want to send exceptions to a logger that expect exc_info).

Regardless, you can still check self.has_exceptions to see if an exception occurred.

handle_exception(message: str, exc: Exception) Any

Handles an uncaught exception.

handle_invalid_value(message: str, exc_info: bool, context: MutableMapping) None

Handles an invalid value.

Parameters:
  • message – Error message.

  • exc_info – Whether to include output from :py:func:sys.exc_info.

  • context – Additional context values for the error.

class filters.macros.FilterMacroType

Base type for filter macros.

Doesn’t do anything on its own, but it is useful for identifying filter macros when paired with an issubclass check.

Important: Use issubclass, not isinstance!

Example:

@filter_macro
def MyMacro():
  return f.NoOp

# ``MyMacro`` is now a *subclass* of ``FilterMacroType``!
assert issubclass(MyMacro, FilterMacroType)

# It is *not* an *instance* of ``FilterMacroType``!
assert not isinstance(MyMacro, FilterMacroType)
templates = {'exception': 'An error occurred while processing this value.'}
filters.macros.filter_macro(func, *args, **kwargs)

Promotes a function returning a filter into its own filter type.

Example:

@filter_macro
def String():
    return Unicode | Strip | NotEmpty

# You can now use `String` anywhere you would use a regular
# Filter:
(String | Split(':')).apply('...')

You can also use filter_macro to create partials, allowing you to preset one or more initialisation arguments:

Minor = filter_macro(Max, max_value=18, inclusive=False)
Minor(inclusive=True).apply(18)
Parameters:
  • func – The function to promote to a filter type.

  • *args – Positional arguments to preset.

  • **kwargs – Keyword arguments to preset.

Returns:

A new filter type based on the function.

class filters.number.Decimal(max_precision: int | Decimal | None = None, allow_tuples: bool = True)

Interprets the value as a decimal.Decimal object.

Initialises the Decimal filter.

Parameters:
  • max_precision

    Max number of decimal places the resulting value is allowed to have. Values that are too precise will be rounded to fit.

    To avoid ambiguity, specify max_precision as a decimal.Decimal object.

    For example, to round to the nearest 1/100:

    Decimal(max_precision=decimal.Decimal('0.01'))
    

  • allow_tuples

    Whether to allow tuple-like inputs.

    Allowing tuple inputs might couple the implementation more tightly to Python’s Decimal type, so you have the option to disallow it.

CODE_INVALID = 'not_numeric'
CODE_NON_FINITE = 'not_finite'
templates = {'exception': 'An error occurred while processing this value.', 'not_finite': 'Numeric value expected.', 'not_numeric': 'Numeric value expected.'}
class filters.number.Int

Interprets the value as an int.

Strings and other compatible values will be converted, but floats will be treated as INVALID.

Note

Python handles really, really big int values transparently, so you don’t need to worry about overflow.

Reference: http://stackoverflow.com/a/538583

CODE_DECIMAL = 'not_int'
templates = {'exception': 'An error occurred while processing this value.', 'not_int': 'Integer value expected.'}
class filters.number.Max(max_value: Any, exclusive: bool = False)

Enforces a maximum value.

Note

Technically, this filter can operate on any type that supports comparison, but it tends to be used exclusively with numeric types.

Initialises the Max filter.

Parameters:
  • max_value – The max value that the Filter will accept.

  • exclusive

    Whether to exclude the max value itself as a valid value:

    • True: The incoming value must be less than the max value.

    • False (default): The incoming value must be less than or equal to the max value.

CODE_TOO_BIG = 'too_big'
templates = {'exception': 'An error occurred while processing this value.', 'too_big': 'Value is too large (must be {operator} {max}).'}
class filters.number.Min(min_value: Any, exclusive: bool = False)

Enforces a minimum value.

Note

Technically, this filter can operate on any type that supports comparison, but it tends to be used exclusively with numeric types.

Initialises the Min filter.

Parameters:
  • min_value – The min value that the Filter will accept.

  • exclusive

    Whether to exclude the min value itself as a valid value:

    • True: The incoming value must be greater than the min value.

    • False (default): The incoming value must be greater than or equal to the min value.

CODE_TOO_SMALL = 'too_small'
templates = {'exception': 'An error occurred while processing this value.', 'too_small': 'Value is too small (must be {operator} {min}).'}
class filters.number.Round(to_nearest: int | str | Decimal = 1, rounding: str = 'ROUND_HALF_UP', result_type: type = <class 'decimal.Decimal'>)

Rounds incoming values to whole numbers or decimals.

Initialises the Round filter.

Parameters:
  • to_nearest

    The value that the filter should round to.

    E.g., Round(1) rounds to the nearest whole number.

    If you want to round to a float value, it is recommended that you provide it as a string or Decimal, to avoid floating point precision errors.

  • rounding – Controls how to round values.

  • result_type – The type of result to return.

templates = {'exception': 'An error occurred while processing this value.'}
class filters.simple.Array(aliases: Mapping[type, str] | None = None)

Validates that the incoming value is a non-string sequence.

Parameters:
  • allowed_types – The type (or types) that incoming values are allowed to have.

  • allow_subclass – Whether to allow subclasses when checking for type matches.

  • aliases

    Aliases to use for type names in error messages.

    This is useful for providing more context- appropriate names to end users and/or masking native Python type names.

templates = {'exception': 'An error occurred while processing this value.', 'wrong_type': '{incoming} is not valid (allowed types: {allowed}).'}
class filters.simple.ByteArray(encoding: str = 'utf-8')

Converts an incoming value into a bytearray.

Initialises the ByteArray filter.

Parameters:

encoding – The encoding to use when decoding strings into bytes.

CODE_BAD_ENCODING = 'bad_encoding'
templates = {'bad_encoding': 'Unable to encode this value using {encoding}.', 'exception': 'An error occurred while processing this value.'}
class filters.simple.Call(callable_: Callable[[...], Any], *extra_args, **extra_kwargs)

Runs the value through a callable.

Usually, creating a custom filter type works better, as you have more control over how invalid values are handled, you can specify custom error codes, it’s easier to write tests for, etc.

But, in a pinch, this is a handy way to quickly integrate a custom function into a filter chain.

Initialises the Call filter.

Parameters:
  • callable – The callable that will be applied to incoming values.

  • extra_args – Extra positional arguments to pass to the callable.

  • extra_kwargs – Extra keyword arguments to pass to the callable.

templates = {'exception': 'An error occurred while processing this value.'}
class filters.simple.Date(timezone: tzinfo | int | float | None = None, naive: bool = False)

Interprets the value as a UTC date.

Note

The value is first converted to a datetime with UTC timezone, which may cause the resulting date to appear to be off by +/- 1 day (does not apply if the value is already a date object).

Initialises the Datetime filter.

Parameters:
  • timezone – Specifies the timezone to use when the incoming value is a naive timestamp. Has no effect on timezone-aware timestamps. The result is always converted to UTC, regardless of the value of the timezone param! You can provide an int/float here, which is the offset from UTC in hours (e.g., 5 = UTC+5).

  • naive – If True, the filter will return naive datetime objects (sans tzinfo). This is useful e.g., for datetime values that will be stored in a database that doesn’t understand aware timestamps. Incoming values are still converted to UTC before stripping tzinfo!

CODE_INVALID = 'not_date'
templates = {'exception': 'An error occurred while processing this value.', 'not_date': 'This value does not appear to be a date.', 'not_datetime': 'This value does not appear to be a datetime.'}
class filters.simple.Datetime(timezone: tzinfo | int | float | None = None, naive: bool = False)

Interprets the value as a UTC datetime.

Initialises the Datetime filter.

Parameters:
  • timezone – Specifies the timezone to use when the incoming value is a naive timestamp. Has no effect on timezone-aware timestamps. The result is always converted to UTC, regardless of the value of the timezone param! You can provide an int/float here, which is the offset from UTC in hours (e.g., 5 = UTC+5).

  • naive – If True, the filter will return naive datetime objects (sans tzinfo). This is useful e.g., for datetime values that will be stored in a database that doesn’t understand aware timestamps. Incoming values are still converted to UTC before stripping tzinfo!

CODE_INVALID = 'not_datetime'
templates = {'exception': 'An error occurred while processing this value.', 'not_datetime': 'This value does not appear to be a datetime.'}
class filters.simple.Empty

Expects the value to be empty.

In this context, “empty” is defined as having zero length. Note that this Filter considers values that do not have length to be not empty (in particular, False and 0 are not considered empty here).

CODE_NOT_EMPTY = 'not_empty'
templates = {'exception': 'An error occurred while processing this value.', 'not_empty': 'Empty value expected.'}
class filters.simple.Item(key: Hashable | None = None)

Returns a single item from an incoming mapping or sequence.

CODE_MISSING_KEY = 'missing'
templates = {'exception': 'An error occurred while processing this value.', 'missing': '{key} is required.'}
class filters.simple.Len(exact: int | None = None, *, min: int | None = None, max: int | None = None)

Validates that a value’s length satisfies the configured constraint.

Modes (mutually exclusive):

  • Len(n) — exact length (equivalent to Length(n))

  • Len(min=n) — minimum length only (equivalent to MinLength(n))

  • Len(max=n) — maximum length only (equivalent to MaxLength(n))

  • Len(min=m, max=n) — length within a range

Parameters:
  • exact – Required length. Mutually exclusive with min and max.

  • min – Minimum allowed length.

  • max – Maximum allowed length.

Raises:

ValueError – If exact is combined with min or max, if any value is negative, or if min > max.

CODE_TOO_LONG = 'too_long'
CODE_TOO_SHORT = 'too_short'
templates = {'exception': 'An error occurred while processing this value.', 'too_long': 'Value is too long (length must be {constraint}).', 'too_short': 'Value is too short (length must be {constraint}).'}
class filters.simple.Length(length: int)

Ensures incoming values have exactly the right length.

CODE_TOO_LONG = 'too_long'
CODE_TOO_SHORT = 'too_short'
templates = {'exception': 'An error occurred while processing this value.', 'too_long': 'Value is too long (length must be exactly {expected}).', 'too_short': 'Value is too short (length must be exactly {expected}).'}
class filters.simple.MaxLength(max_length: int, truncate: bool = False)

Enforces a maximum length on the value.

Initialises the MaxLength filter.

Parameters:
  • max_length – Incoming value must have at most this many items to be valid.

  • truncate – Whether to truncate values that are too long.

CODE_TOO_LONG = 'too_long'
templates = {'exception': 'An error occurred while processing this value.', 'too_long': 'Value is too long (length must be < {max}).'}
class filters.simple.MinLength(min_length: int)

Enforces a minimum length on the value.

CODE_TOO_SHORT = 'too_short'
templates = {'exception': 'An error occurred while processing this value.', 'too_short': 'Value is too short (length must be > {min}).'}
class filters.simple.NoOp

Filter that does nothing, used when you need a placeholder Filter in a FilterChain.

templates = {'exception': 'An error occurred while processing this value.'}
class filters.simple.NotEmpty(allow_none: bool = True)

Expects the value not to be empty.

In this context, “empty” is defined as having zero length. Note that this filter considers values that do not have length to be not empty (in particular, False and 0 are not considered empty here).

By default, this filter treats None as valid, just like every other filter. However, you can configure the filter to reject None in its initialiser method.

Initialises the NotEmpty filter.

Parameters:

allow_none – Whether to allow None.

CODE_EMPTY = 'empty'
templates = {'empty': 'Non-empty value expected.', 'exception': 'An error occurred while processing this value.'}
class filters.simple.Omit(keys: Iterable)

Returns a copy of an incoming mapping or sequence, with the specified keys omitted. Any other items will be passed through.

Initialises the Omit filter.

Parameters:

keys – List of keys that will be omitted from incoming values.

templates = {'exception': 'An error occurred while processing this value.'}
class filters.simple.Optional(default: Any = None, call_default: bool | None = None)

Changes empty and null values into a default value.

In this context, “empty” is defined as having zero length.

Note

If an incoming value does not have a length, it is considered to be not empty (in particular, note that False and 0 are considered not empty in this context).

Initialises the Optional filter.

Parameters:
  • default

    The default value used to replace empty values.

    If default is callable, then when the filter encounters an empty incoming value, it will call default and use the return value as the replacement, instead of using default itself.

    For example, if default=list, then each time the filter encounters an empty value, it will create a new list to use as the replacement.

  • call_default

    Whether to call default to determine the replacement value.

    Effect:

    • None (default) - only call default if it is callable.

    • False - do not call default even if it is callable.

    • True - call default even if it is not callable (pretty sure you’d never need this, but we’re all consenting adults here).

templates = {'exception': 'An error occurred while processing this value.'}
class filters.simple.Pick(keys: Iterable, allow_missing_keys: bool | Iterable = True)

Returns a copy of an incoming mapping or sequence, with only the specified keys included.

Initialises the Pick filter.

Parameters:
  • keys – List of keys that will be picked from incoming values.

  • allow_missing_keys

    Determines how values with missing keys get handled:

    • True (default): Missing keys are ignored.

    • False: Missing keys are treated as invalid values.

    • <Iterable>: Only the specified keys are allowed to be omitted.

CODE_MISSING_KEY = 'missing'
templates = {'exception': 'An error occurred while processing this value.', 'missing': '{key} is required.'}
class filters.simple.Required

Same as NotEmpty, but with allow_none hard-wired to False.

This filter is the only exception to the “None passes by default” rule.

Initialises the NotEmpty filter.

Parameters:

allow_none – Whether to allow None.

templates = {'empty': 'This value is required.', 'exception': 'An error occurred while processing this value.'}
class filters.string.Base64Decode

Decodes an incoming value using the Base64 algo.

CODE_INVALID = 'not_base64'
templates = {'exception': 'An error occurred while processing this value.', 'not_base64': 'Base64-encoded value expected.'}
class filters.string.ByteString(encoding: str = 'utf-8', normalize: bool = False)

Converts a value into a byte string, encoded as UTF-8.

IMPORTANT: This filter returns bytes objects, not bytearrays!

Initialises the ByteString filter.

Parameters:
  • encoding – Used to decode non-unicode values.

  • normalize

    Whether to normalise the unicode value before converting back into bytes:

    • Convert to NFC form.

    • Remove non-printable characters.

    • Convert all line endings to unix-style (’n’).

    Note that normalize is False by default for ByteString, but True by default for Unicode.

templates = {'exception': 'An error occurred while processing this value.', 'wrong_encoding': 'This value cannot be decoded using {encoding}.'}
class filters.string.CaseFold

Applies case folding to an incoming string, allowing you to perform case-insensitive comparisons.

The result tends to be lowercase, but it is recommended that you NOT treat CaseFold as a Unicode-aware lowercase filter! The proper way to lowercase a string is very much locale-dependent.

Note

The built-in str.upper() and str.lower() methods tend do a pretty good job of properly changing the case of unicode strings.

References:

templates = {'exception': 'An error occurred while processing this value.'}
class filters.string.Choice(choices: Iterable[Hashable], case_sensitive: bool = True)

Requires an incoming value to match one of a set of allowed options.

By default, the comparison is case-sensitive, but you can control this via the filter’s initialiser.

Note

This filter is technically able to work with any hashable value, not just strings.

Parameters:
  • choices – The allowed options; if an incoming value doesn’t match any of these values, it is invalid.

  • case_sensitive – Whether the comparison should be case-sensitive.

CODE_INVALID = 'not_valid_choice'
case_sensitive: bool
choice_map: dict[Hashable, Hashable]
templates = {'exception': 'An error occurred while processing this value.', 'not_valid_choice': 'Valid options are: {choices}'}
class filters.string.IpAddress(ipv4: bool = True, ipv6: bool = False)

Validates an incoming value as an IPv[46] address.

Initialises the IpAddress filter.

Parameters:
  • ipv4 – Whether to accept IPv4 addresses.

  • ipv6 – Whether to accept IPv6 addresses.

CODE_INVALID = 'not_ip_address'
property ip_type: str

Returns the IP address versions that this Filter accepts.

Returns:

String indicating accepted IP versions (e.g., “IPv4”, “IPv6”, “IPv4/IPv6”).

templates = {'exception': 'An error occurred while processing this value.', 'not_ip_address': 'This value is not a valid {ip_type} address.'}
class filters.string.JsonDecode(decoder: Callable = <function loads>)

Interprets the value as JSON.

Initialises the JsonDecode filter.

Parameters:

decoder – Callable used to decode JSON strings. Defaults to json.loads.

CODE_INVALID = 'not_json'
templates = {'exception': 'An error occurred while processing this value.', 'not_json': 'This value is not valid JSON.'}
class filters.string.MaxBytes(max_bytes: int, truncate: bool = False, prefix: str = '', suffix: str = '', encoding: str = 'utf-8')

Ensures an incoming string fits in a specified number of bytes.

Note

The resulting value is always byte string (bytes type).

Initialises the MaxBytes filter.

Parameters:
  • max_bytes – Max number of bytes to allow.

  • truncate

    How to handle values that are too long:

    • truncate is True: Return truncated string.

    • truncate is False: Treat as invalid value.

  • prefix

    Prefix to apply to truncated values.

    The prefix will count towards the number of bytes, so even with a prefix the resulting string will not exceed max_bytes in length.

    Ignored when the incoming value is short enough, or when truncate is False.

  • suffix

    Suffix to apply to truncated values.

    The suffix will count towards the number of bytes, so even with a suffix the resulting string will not exceed max_bytes in length.

    Ignored when the incoming value is short enough, or when truncate is False.

  • encoding – The character encoding to check against.

CODE_TOO_LONG = 'too_long'
templates = {'exception': 'An error occurred while processing this value.', 'too_long': 'Value is too long (must be < {max_bytes} bytes when encoded using {encoding}).'}
truncate_bytes(bytes_value: bytes) bytes

Truncates a too-long bytes value to the specified length.

Uses the filter’s current configuration to truncate the value.

Parameters:

bytes_value – The bytes value to truncate.

Returns:

Returns bytes, truncated to the correct length.

Note: Might be a bit shorter than self.max_bytes, to avoid orphaning a multibyte sequence.

class filters.string.MaxChars(max_chars: int, truncate: bool = False, prefix: str = '', suffix: str = '')

Ensures incoming value fits in a certain number of characters.

Note

The resulting value is always a unicode string (str type).

Initialises the MaxChars filter.

Parameters:
  • max_chars – Max number of characters to allow.

  • truncate

    How to handle values that are too long:

    • truncate is True: Return truncated string.

    • truncate is False: Treat as invalid value.

  • prefix

    Prefix to apply to truncated values.

    The prefix will count towards the max number of characters, so even with a prefix the resulting string will not exceed max_chars in length.

    Ignored when the incoming value is short enough, or when truncate is False.

  • suffix

    Suffix to apply to truncated values.

    The suffix will count towards the max number of characters, so even with a suffix the resulting string will not exceed max_chars in length.

    Ignored when the incoming value is short enough, or when truncate is False.

CODE_TOO_LONG = 'too_long'
templates = {'exception': 'An error occurred while processing this value.', 'too_long': 'Value is too long (must be < {max_chars} characters).'}
class filters.string.Regex(pattern: str | Pattern)

Matches a regular expression in the value.

IMPORTANT: This filter returns a LIST of all sequences in the input value that matched the regex!

IMPORTANT: This Filter uses the regex library, which behaves slightly differently than Python’s re library.

If you’ve never used regex before, try it; you’ll never want to go back!

Initialises the Regex filter.

Parameters:

pattern

String pattern, or pre-compiled regex.

IMPORTANT: If you specify your own compiled regex, be sure to add the UNICODE flag for Unicode support!

CODE_INVALID = 'malformed'
pattern_types = (<class 're.Pattern'>, <class '_regex.Pattern'>)
templates = {'exception': 'An error occurred while processing this value.', 'malformed': 'Value does not match regular expression {pattern}.'}
class filters.string.Split(pattern: str | Pattern, keys: Sequence[str] | None = None)

Splits an incoming string into parts.

The result is either a list or a dict, depending on whether you specify keys to map to the result.

Initialises the Split filter.

Parameters:
  • pattern

    Regex used to split incoming string values.

    IMPORTANT: If you specify your own compiled regex, be sure to add the UNICODE flag for Unicode support!

  • keys

    If set, the resulting list will be converted into a dict, using the specified keys.

    Important: If keys is set, the split value’s length must be less than or equal to len(keys).

templates = {'exception': 'An error occurred while processing this value.'}
class filters.string.Strip(leading: str = '[\\p{C}\\s]+', trailing: str = '[\\p{C}\\s]+')

Strips characters from the end(s) of a string.

Strips whitespace and non-printables by default.

IMPORTANT: This Filter uses the regex library, which behaves slightly differently than Python’s re library.

If you’ve never used regex before, try it; you’ll never want to go back!

Initialises the Strip filter.

Parameters:
  • leading – Regex to match at the start of the string.

  • trailing – Regex to match at the end of the string.

templates = {'exception': 'An error occurred while processing this value.'}
class filters.string.TomlDecode

Interprets the value as TOML.

CODE_INVALID = 'not_toml'
templates = {'exception': 'An error occurred while processing this value.', 'not_toml': 'This value is not valid TOML.'}
class filters.string.Unicode(encoding: str = 'utf-8', normalize: bool = True)

Converts a value into a unicode string.

Note

By default, additional normalisation is applied to the resulting value. See the initialiser docstring for more info.

References:

Initialises the Unicode filter.

Parameters:
  • encoding – Used to decode non-unicode values.

  • normalize

    Whether to normalise the resulting value:

    • Convert to NFC form.

    • Remove non-printable characters.

    • Convert all line endings to unix-style (’n’).

CODE_DECODE_ERROR = 'wrong_encoding'
templates = {'exception': 'An error occurred while processing this value.', 'wrong_encoding': 'This value cannot be decoded using {encoding}.'}
class filters.string.Uuid(version: int | None = None)

Interprets an incoming value as a UUID.

Initialises the Uuid filter.

Parameters:

version – If specified, requires the resulting UUID to match the specified version.

CODE_INVALID = 'not_uuid'
CODE_WRONG_VERSION = 'wrong_version'
templates = {'exception': 'An error occurred while processing this value.', 'not_uuid': 'This value is not a well-formed UUID.', 'wrong_version': 'v{incoming} UUID not allowed (expected v{expected}).'}
class filters.test.BaseFilterTestCase(methodName='runTest')

Base functionality for request filter unit tests.

Prevents typos from causing invalid test passes/failures by abstracting the Filter type out of filtering ops; just set filter_type at the top of your test case, and then use assertFilterPasses and assertFilterErrors to check use cases.

Create an instance of the class that will use the named test method when executed. Raises a ValueError if the instance does not have a method with the specified name.

assertFilterErrors(runner: Any, expected_codes: Mapping[str, Sequence[str]] | Sequence[str], expected_value: Any = None) FilterRunner

Asserts that the FilterRunner generates the specified errors.

Parameters:
  • runner – Usually a FilterRunner instance, but you can pass in the test value itself if you want (it will automatically be run through _filter).

  • expected_codes – Expected error codes.

  • expected_value – Expected value for runner.cleaned_data (usually None).

Returns:

The FilterRunner instance for further assertions.

assertFilterPasses(runner: Any, expected_value: Any = <class 'filters.test.BaseFilterTestCase.unmodified'>) FilterRunner

Asserts that the FilterRunner returns the value without errors.

Parameters:
  • runner – Usually a FilterRunner instance, but you can pass in the test value itself if you want (it will automatically be run through _filter).

  • expected_value

    The expected value for runner.cleaned_data.

    If omitted, the assertion will check that the incoming value is returned unmodified.

Returns:

The FilterRunner instance for further assertions.

filter_type: Callable[[...], BaseFilter] = None
class skip_value_check

Sentinel value to skip checking the filtered value.

Sentinel value; used by assertFilterPasses to skip checking the filtered value. This is useful for tests where a simple equality check is not practical.

Note

If you use skip_value_check, you should add extra assertions to your test to make sure the filtered value conforms to expectations.

class unmodified

Used by assertFilterPasses to omit expected_value parameter.

Used by assertFilterPasses so that you can omit the expected_value parameter.