API Documentation

class filters.base.BaseFilter

Base functionality for all Filters, macros, etc.

CODE_EXCEPTION = 'exception'
apply(value: Any) T | None

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[Any] | None

Returns the parent Filter.

classmethod resolve(the_filter: BaseFilter[U] | Callable[[], BaseFilter[U]] | None, parent: BaseFilter[Any] | None = None, key: str | None = None) BaseFilter[U]

Converts a filter-compatible value into a consistent type.

set_handler(handler: BaseInvalidValueHandler) BaseFilter[T]

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: dict[str, str] = {'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.

abstract handle_invalid_value(message: str, exc_info: bool, context: MutableMapping[str, Any]) 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[str, Any]) 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[T] | None = None)

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

templates: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
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.NoOp

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

templates: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
class filters.base.Type(allowed_types: type | Tuple[type, ...], allow_subclass: bool = True)

Checks the type of the incoming 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.

CODE_WRONG_TYPE = 'wrong_type'
static get_type_name(type_: type) str

Returns the name of the specified type.

templates: dict[str, str] = {'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[Any]], 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 initializer determines the order of keys in the filtered value.

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

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: Set missing values to None and then filter as normal.

    • False: Treat missing keys as invalid values.

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

  • allow_extra_keys

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

    • True: Pass extra values through to the filtered value.

    • False: Treat extra values as invalid values and omit them from the filtered value.

    • <Iterable>: Only allow the specified extra keys.

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

Iterator version of apply().

templates: dict[str, str] = {'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[T], 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).

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: dict[str, str] = {'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[T]], default: BaseFilter[T] | None = None)

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

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: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
class filters.complex.NamedTuple(type_: Type[NamedTuple], filter_map: Mapping[str, BaseFilter[T]] | None = None)

Attempts to convert the incoming value into a namedtuple.

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: dict[str, str] = {'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.

Parameters:
  • group – The name of the entry point group that will be used to load new classes.

  • attr_name

    If set, the registry will “brand” each class with its corresponding registry key. This makes it easier to perform reverse lookups later.

    Note: if a class already defines this attribute, the registry will overwrite it!

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

Prepares the return value for get().

You may override this method in a subclass, if you want to customize the way new instances are created.

Parameters:
  • class – The requested class.

  • args – Positional keywords passed to get().

  • kwargs – Keyword arguments passed to get().

filters.extensions.GROUP_NAME = 'filters.extensions'

The key to use when declaring entry points in your library’s setup.py file.

Example:

setup(
  ...
  entry_points = {
    'filters.extensions': [
      # Declare each filter with its own entry point.
      '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.

Parameters:

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.

class filters.handlers.FilterRunner(starting_filter: BaseFilter[Any], 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 0:)

Note that FilterRunner is intended to be a “one-shot” tool; once initialised, it does not expect the data it is filtering to change.

Parameters:
  • 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.

property cleaned_data

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.

property errors: Dict[str, List[Dict[str, str]]]

Returns a dict of error messages generated by the Filter, in a format suitable for inclusion in e.g., a 400 Bad Request response payload.

E.g.:

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

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

    # etc.
}
property exc_info: List[Tuple[type, Exception, TracebackType]]

Returns tracebacks from any exceptions that were captured.

property filter_messages: Dict[str, List[FilterMessage]]

Returns the raw FilterMessages that were generated by the Filter.

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, in a format 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!

property has_exceptions: bool

Returns whether any unhandled exceptions occurred while filtering the value.

is_valid() bool

Returns whether the request payload successfully passed the Filter.

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

Invalid value handler that sends the details to a logger.

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.

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.number.Decimal(max_precision: int | Decimal | None = None, allow_tuples: bool = True)

Interprets the value as a decimal.Decimal object.

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: dict[str, str] = {'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 that Python handles really big int values transparently, so you don’t need to worry about overflow.

References

CODE_DECIMAL = 'not_int'
templates: dict[str, str] = {'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.

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: dict[str, str] = {'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.

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: dict[str, str] = {'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.Decimal = 1, rounding: str = 'ROUND_HALF_UP', result_type: type = <class 'decimal.Decimal'>)

Rounds incoming values to whole numbers or decimals.

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: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
class filters.simple.Array

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.

templates: dict[str, str] = {'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.

Parameters:

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

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

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.

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: dict[str, str] = {'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 that 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).

Check out the unit tests for more information.

Parameters:
  • timezone

    Specifies the timezone to use when the incoming value is a naive timestamp. Has no effect on timezone-aware timestamps.

    IMPORTANT: 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.

    IMPORTANT: Incoming values are still converted to UTC before stripping tzinfo!

CODE_INVALID = 'not_date'
templates: dict[str, str] = {'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.

Parameters:
  • timezone

    Specifies the timezone to use when the incoming value is a naive timestamp. Has no effect on timezone-aware timestamps.

    IMPORTANT: 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.

    IMPORTANT: Incoming values are still converted to UTC before stripping tzinfo!

CODE_INVALID = 'not_datetime'
templates: dict[str, str] = {'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: dict[str, str] = {'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: dict[str, str] = {'exception': 'An error occurred while processing this value.', 'missing': '{key} is required.'}
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: dict[str, str] = {'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.

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: dict[str, str] = {'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: dict[str, str] = {'exception': 'An error occurred while processing this value.', 'too_short': 'Value is too short (length must be > {min}).'}
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 initializer method.

Parameters:

allow_none – Whether to allow None.

CODE_EMPTY = 'empty'
templates: dict[str, str] = {'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.

Param:

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

templates: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
class filters.simple.Optional(default: Callable[[...], T] | T = 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).

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: dict[str, str] = {'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.

Param:

keys List of keys that will be picked from incoming values.

Parameters:

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: dict[str, str] = {'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.

Parameters:

allow_none – Whether to allow None.

templates: dict[str, str] = {'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: dict[str, str] = {'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.

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

  • normalize

    Whether to normalize 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: dict[str, str] = {'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 that 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: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
class filters.string.Choice(choices: Iterable[H], 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'
templates: dict[str, str] = {'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.

CODE_INVALID = 'not_ip_address'
property ip_type: str

Returns the IP address versions that this Filter accepts.

templates: dict[str, str] = {'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: ~typing.Callable = <function loads>)

Interprets the value as JSON.

CODE_INVALID = 'not_json'
templates: dict[str, str] = {'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 that an incoming string value is small enough to fit into a specified number of bytes when encoded.

Note

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

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: dict[str, str] = {'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 number of bytes, using the filter’s current configuration.

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 the incoming value is small enough to fit in a certain number of characters.

Note

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

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: dict[str, str] = {'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!

References

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 = (typing.Pattern, <class '_regex.Pattern'>)
templates: dict[str, str] = {'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.

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: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
class filters.string.Strip(leading: str = '[\\p{C}\\s]+', trailing: str = '[\\p{C}\\s]+')

Strips characters (whitespace and non-printables by default) from the end(s) of a string.

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!

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

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

templates: dict[str, str] = {'exception': 'An error occurred while processing this value.'}
class filters.string.Unicode(encoding: str = 'utf-8', normalize: bool = True)

Converts a value into a unicode string.

References:

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

  • normalize

    Whether to normalize 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: dict[str, str] = {'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.

References

CODE_INVALID = 'not_uuid'
CODE_WRONG_VERSION = 'wrong_version'
templates: dict[str, str] = {'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 error codes.

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).

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

Asserts that the FilterRunner returns the specified 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.

filter_type: BaseFilter[Any] | Callable[[], BaseFilter[Any]]
class skip_value_check

Sentinal 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 so that you can omit the expected_value parameter.