API Documentation
- class filters.base.BaseFilter
Base functionality for all Filters, macros, etc.
- CODE_EXCEPTION = 'exception'
- property handler: BaseInvalidValueHandler
Returns the invalid value handler for the 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.
- class filters.base.BaseInvalidValueHandler
Base functionality for classes that handle invalid values.
- class filters.base.ExceptionHandler
Invalid value handler that raises an exception.
- 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.
- 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.
- 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'
- 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'
- 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'
- 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.
- 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)
- 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).
- 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.
- property cleaned_data
Returns the resulting value after applying the request 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!
- 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_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 adecimal.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'
- 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'
- 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'
- 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'
- 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.
- 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.
- 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'
- 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.
- 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'
- 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'
- 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'
- class filters.simple.Item(key: Hashable | None = None)
Returns a single item from an incoming mapping or sequence.
- CODE_MISSING_KEY = 'missing'
- class filters.simple.Length(length: int)
Ensures incoming values have exactly the right length.
- CODE_TOO_LONG = 'too_long'
- CODE_TOO_SHORT = 'too_short'
- 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'
- class filters.simple.MinLength(min_length: int)
Enforces a minimum length on the value.
- CODE_TOO_SHORT = 'too_short'
- 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 rejectNone
in its initializer method.- Parameters:
allow_none – Whether to allow
None
.
- CODE_EMPTY = 'empty'
- 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.
- 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
and0
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 calldefault
and use the return value as the replacement, instead of usingdefault
itself.For example, if
default=list
, then each time the filter encounters an empty value, it will create a newlist
to use as the replacement.call_default –
Whether to call
default
to determine the replacement value.Effect:
None
(default) - only calldefault
if it is callable.False
- do not calldefault
even if it is callable.True
- calldefault
even if it is not callable (pretty sure you’d never need this, but we’re all consenting adults here).
- 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'
- class filters.simple.Required
Same as NotEmpty, but with
allow_none
hard-wired toFalse
.This filter is the only exception to the “
None
passes by default” rule.- Parameters:
allow_none – Whether to allow
None
.
- class filters.string.Base64Decode
Decodes an incoming value using the Base64 algo.
- CODE_INVALID = 'not_base64'
- 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
isFalse
by default forByteString
, butTrue
by default forUnicode
.
- 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()
andstr.lower()
methods tend do a pretty good job of properly changing the case of unicode strings.References
- 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'
- class filters.string.IpAddress(ipv4: bool = True, ipv6: bool = False)
Validates an incoming value as an IPv[46] address.
- CODE_INVALID = 'not_ip_address'
- class filters.string.JsonDecode(decoder: ~typing.Callable = <function loads>)
Interprets the value as JSON.
- CODE_INVALID = 'not_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'
- 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'
- 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’sre
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'>)
- 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 tolen(keys)
.
- 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’sre
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.
- 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'
- 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'
- 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 useassertFilterPasses
andassertFilterErrors
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
(usuallyNone
).
- 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 theexpected_value
parameter.