weaver.wps_restapi.colander_extras
This module offers multiple utility schema definitions to be employed with colander
and cornice_swagger
.
The colander.SchemaNode
provided here can be used in-place of colander
ones, but giving you extended behaviour according to provided keywords. You can therefore
do the following and all will be applied without modifying your code base.
# same applies for Mapping and Sequence schemas
from colander_extras import ExtendedSchemaNode as SchemaNode
from colander import SchemaNode # instead of this
The schemas support extended cornice_swagger
type converters so that you
can generate OpenAPI-3 specifications. The original package support is limited
to Swagger-2. You will also need additional in-place modifications provided
here.
Since the intended usage is to generate JSON-deserialized data structures, the
base colander.SchemaNode
have some additional patches needed to handle
JSON-native type conversion that are not directly offered by colander
- The main classes extensions are:
Multiple <ExtensionType>SchemaNode
variants are provided. You can use them
as building blocks, gaining each of their respective feature, to make specific
schema that meets your desired behaviour. The Extended
-prefixed classes
combined all available <ExtensionType>
. Note that it is preferable to use
the full Extended
-prefixed classes over individual ones as they add
complementary support of one-another features.
Warning
All node extensions assume that they are used for JSON data. Deserialization of unknown types could result in invalid result. Most of the time, Python native iterators such as tuples and generators could work and be converted to the corresponding sequence array (ie: list), but this is not guaranteed.
Warning
When defining schema nodes, DO NOT use the name
keyword otherwise
most mapping will fail validation as they cannot retrieve the same key-name
from the passed dictionary for deserialize
validation. Let the API
figure out the name of the field automatically. Instead, use the keyword
or field title
for adjusting the displayed name in the Swagger UI.
The same value will also be used to generate the $ref
reference names
of generated OpenAPI model definitions. If not explicitly provided, the
value of title
WILL default to the name of the schema node class.
Module Contents
- weaver.wps_restapi.colander_extras._make_node_instance(schema_node_or_class: colander.SchemaNode | Type[colander.SchemaNode]) colander.SchemaNode [source]
Obtains a schema node instance in case it was specified only by type reference.
This helps being more permissive of provided definitions while handling situations like presented in the example below:
class Map(OneOfMappingSchema): # uses types instead of instances like 'SubMap1([...])' and 'SubMap2([...])' _one_of = (SubMap1, SubMap2)
- weaver.wps_restapi.colander_extras._get_schema_type(schema_node: colander.SchemaNode | Type[colander.SchemaNode], check: bool = False) colander.SchemaType | None [source]
Obtains the schema-type from the provided node, supporting various initialization methods.
typ
is set by an instantiated node from specific schema (e.g.:colander.SchemaNode(colander.String())
)schema_type
can also be provided, either by type or instance if using class definition with property
- Parameters:
schema_node – item to analyse
check – only attempt to retrieve the schema type, and if failing return
None
- Returns:
found schema type
- Raises:
ConversionTypeError – if no
check
requested and schema type cannot be found (invalid schema node)
- weaver.wps_restapi.colander_extras._get_node_name(schema_node: colander.SchemaNode, schema_name: bool = False) str [source]
Obtains the name of the node with the best available value.
- Parameters:
schema_node – node for which to retrieve the name.
schema_name –
If
True
, prefer the schema definition (class) name over the instance or field name.Otherwise, return the field name, the title or as last result the class name.
- Returns:
node name
- exception weaver.wps_restapi.colander_extras.SchemaNodeTypeError[source]
Generic error indicating that the definition of a SchemaNode is invalid.
This usually means the user forgot to specify a required element for schema creation, or that a provided combination of keywords, sub-nodes and/or schema type don’t make any sense together, that they are erroneous, or that they cannot be resolved because of some kind of ambiguous definitions leading to multiple conflicting choices.
Initialize self. See help(type(self)) for accurate signature.
- exception weaver.wps_restapi.colander_extras.ConversionTypeError[source]
Conversion error due to invalid type.
Initialize self. See help(type(self)) for accurate signature.
- exception weaver.wps_restapi.colander_extras.ConversionValueError[source]
Conversion error due to invalid value.
Initialize self. See help(type(self)) for accurate signature.
- class weaver.wps_restapi.colander_extras.OneOfCaseInsensitive(choices: Iterable[str], *args: Any, **kwargs: Any)[source]
Validator that ensures the given value matches one of the available choices, but allowing case-insensitive values.
- class weaver.wps_restapi.colander_extras.StringOneOf(choices: Iterable[str], delimiter: str = ',', case_sensitive: bool = True, **kwargs: Any)[source]
Validator that ensures the given value matches one of the available choices, but defined by string delimited values.
- class weaver.wps_restapi.colander_extras.BoundedRange(min: float | int | None = None, max: float | int | None = None, exclusive_min: bool = False, exclusive_max: bool = False, **kwargs: Any)[source]
Validator of value within range with added
exclusive
bounds support.
- class weaver.wps_restapi.colander_extras.StringRange(min: float | int | str | None = None, max: float | int | str | None = None, exclusive_min: bool = False, exclusive_max: bool = False, **kwargs: Any)[source]
Validator that provides the same functionalities as
colander.Range
for a numerical string value.
- class weaver.wps_restapi.colander_extras.CommaSeparated(allow_chars: str = 'A-Za-z0-9_-', msg: str = _MSG_ERR, flags: re.RegexFlag = re.IGNORECASE)[source]
Validator that ensures the given value is a comma-separated string.
- class weaver.wps_restapi.colander_extras.SchemeURL(schemes: Iterable[str] | None = None, path_pattern: None | str | RegexPattern = None, msg: str | None = None, flags: re.RegexFlag | None = re.IGNORECASE)[source]
String representation of an URL with extended set of allowed URI schemes.
- class weaver.wps_restapi.colander_extras.SemanticVersion(*args: Any, v_prefix: bool = False, rc_suffix: bool = True, **kwargs: Any)[source]
String representation that is valid against Semantic Versioning specification.
See also
- class weaver.wps_restapi.colander_extras.ExtendedBoolean(*args: Any, true_choices: Iterable[str] | None = None, false_choices: Iterable[str] | None = None, allow_string: bool = False, **kwargs: Any)[source]
A type representing a boolean object.
The constructor accepts these keyword arguments:
false_choices
: The set of strings representing aFalse
value on deserialization.true_choices
: The set of strings representing aTrue
value on deserialization.false_val
: The value returned on serialization of a False value.true_val
: The value returned on serialization of a True value.
During deserialization, a value contained in
false_choices
, will be consideredFalse
.The behaviour for values not contained in
false_choices
depends ontrue_choices
: if it’s empty, any value is consideredTrue
; otherwise, only values contained intrue_choices
are consideredTrue
, and an Invalid exception would be raised for values outside of bothfalse_choices
andtrue_choices
.Serialization will produce
true_val
orfalse_val
based on the value.If the
colander.null
value is passed to the serialize method of this class, thecolander.null
value will be returned.The subnodes of the
colander.SchemaNode
that wraps this type are ignored.Initializes the extended boolean schema node.
When arguments
true_choices
orfalse_choices
are provided, the corresponding string values are respectively considered as valid truthy/falsy values. Otherwise (default),strict
values only of explicit typebool
will be considered valid.When values are specified
colander
converts them to string lowercase to compare against truthy/falsy values it should accept. For real OpenAPI typing validation, do NOT add other values like"1"
to avoid conflict withExtendedInteger
type for schemas that support both variants. If an OpenAPI field is expected to support truthy/falsy values, it is recommended to explicitly define its schema using aoneOf
keyword of all relevant schemas it supports, an any applicable validators for explicit values. This is the safest way to ensure the generated OpenAPI schema corresponds to expected type validation.
- class weaver.wps_restapi.colander_extras.ExtendedNumber(*_, allow_string=False, strict=True, **__)[source]
Definition of a numeric value, either explicitly or implicit with permissive
str
representation.- Behaviour in each case:
strict=True
andallow_string=False
: Value can only be explicit numeric type that matches exactly the basenum
type (default). All implicit conversion betweenfloat
,int
orstr
are disallowed.strict=True
andallow_string=True
: Value can be the explicit numeric type (int
orfloat
) or a numericstr
value representing the corresponding base numeric type. Implicit conversion betweenfloat
andint
is still disallowed.strict=False
(allow_string
doesn’t matter): Value can be anything as long as it can be converted to the expected numeric type (int
orfloat
).
- Recommended usage:
When making OpenAPI schema definitions for JSON body elements within a request or response object, default parameters
strict=True
andallow_string=False
should be used to ensure the numeric type is respected. As for other literal data Extended schema types, keyword oneOf should be used when multiple similar value types are permitted for a field in order to document in OpenAPI the specific type definitions of expected data, which is automatically converted byjson
properties of request and response classes.When defining OpenAPI query parameters,
strict=True
andallow_string=True
should be used. This ensures that documented schemas still indicate only the numeric type as expected data format, although technically thepath
of the request will contain astr
representing the number. Queries are not automatically converted by request objects, but will be converted and validated as the explicit number following deserialization when using those configuration parameters.
- class weaver.wps_restapi.colander_extras.ExtendedFloat(*_: Any, allow_string: bool = False, strict: bool = True, **__: Any)[source]
Float definition with strict typing validation by default.
This is to distinguish it from explicit definitions of
float
-like numbers or strings. By default, values such as"1"
,1.0
,True
will not be automatically converted to equivalent1.0
.
- class weaver.wps_restapi.colander_extras.ExtendedInteger(*_: Any, allow_string: bool = False, strict: bool = True, **__: Any)[source]
Integer definition with strict typing validation by default.
This is to distinguish it from explicit definitions of
integer
-like numbers or strings. By default, values such as"1"
,1.0
,True
will not be automatically converted to equivalent1
.
- class weaver.wps_restapi.colander_extras.ExtendedString(encoding=None, allow_empty=False)[source]
String with auto-conversion for known OpenAPI
format
field where no directcolander
type exist.Converts
uuid.UUID
to corresponding string when detected in the node if it definedformat="uuid"
.For
format="date"
andformat="date-time"
, consider instead usingcolander.Date
andcolander.DateTime
respectively since more advanced support and features are provided with them.
- class weaver.wps_restapi.colander_extras.NoneType[source]
Type representing an explicit JSON
null
value.
- class weaver.wps_restapi.colander_extras.XMLObject[source]
Object that provides mapping to known XML extensions for OpenAPI schema definition.
Name of the schema definition in the OpenAPI will use
prefix
and the schema class name. Prefix can be omitted from the schema definition name by setting it tocolander.drop
. The value oftitle
provided as option orSee also
- class weaver.wps_restapi.colander_extras.ExtendedSchemaBase(*args, **kwargs)[source]
Utility base node definition that initializes additional parameters at creation time of any other extended schema.
When no explicit
title
is specified by either keyword argument or field definition within container class, default it to the literal name of the class defining the schema node. This title can then be employed by other extended schema implementations to define cleaner schema references, notably in the case ofKeywordMapper
derived classes that do not necessarily have any explicit targetname
field.When the schema node is a simple field within a container schema (mapping, sequence, etc.), operation is skipped to avoid applying the generic
SchemaNode
orExtendedSchemaNode
name of the basic node class. In this case, converters already employ the targetname
of the class attribute of the container schema under which that node gets created.When the schema node is a generic
colander.String
without explicitvalidator
, but that one can be inferred from eitherpattern
orformat
OpenAPI definition, the correspondingvalidator
gets automatically generated.
- class weaver.wps_restapi.colander_extras.DropableSchemaNode(*args, **kwargs)[source]
Schema that can be dropped if the value is missing.
Drops the underlying schema node if
missing=drop
was specified and that the value representing it represents an empty value instead of raising a invalid schema error.In the case of nodes corresponding to literal schema type (i.e.: Integer, String, etc.), the empty value looked for is
None
. This is to make sure that0
or""
are preserved unless explicitly representing no-data. In the case of container schema types (i.e.: list, dict, etc.), it is simply considered empty if there are no element in it, without any more explicit verification.Original behaviour of schema classes that can have children nodes such as
colander.MappingSchema
andcolander.SequenceSchema
are to drop the sub-node only if its value is resolved ascolander.null
orcolander.drop
. This results in optional field definitions replaced byNone
in many implementations to raisecolander.Invalid
during deserialization. Inheriting this class in a schema definition will handle this situation automatically.Required schemas (without
missing=drop
, defaulting tocolander.required
) will still raise for undefined nodes.The following snippet shows the result that can be achieved using this schema class:
class SchemaA(DropableSchemaNode, MappingSchema): field = SchemaNode(String()) class SchemaB(MappingSchema): s1 = SchemaA(missing=drop) # optional s2 = SchemaA() # required SchemaB().deserialize({"s1": None, "s2": {"field": "ok"}}) # results: {'s2': {'field': 'ok'}}
- deserialize(cstruct)[source]
Deserialize the cstruct into an appstruct based on the schema, run this appstruct through the preparer, if one is present, then validate the prepared appstruct. The
cstruct
value is deserialized into anappstruct
unconditionally.If
appstruct
returned by type deserialization and preparation is the valuecolander.null
, do something special before attempting validation:If the
missing
attribute of this node has been set explicitly, return its value. No validation of this value is performed; it is simply returned.If the
missing
attribute of this node has not been set explicitly, raise acolander.Invalid
exception error.
If the appstruct is not
colander.null
and cannot be validated , acolander.Invalid
exception will be raised.If a
cstruct
argument is not explicitly provided, it defaults tocolander.null
.
- class weaver.wps_restapi.colander_extras.DefaultSchemaNode(*args, **kwargs)[source]
Schema that will return the provided default value when the corresponding value is missing or invalid.
If
default
keyword is provided duringcolander.SchemaNode
creation, overrides the returned value by this default if missing from the structure duringdeserialize()
call.Original behaviour was to drop the missing value instead of replacing by
default
. Executes all othercolander.SchemaNode
operations normally.- deserialize(cstruct)[source]
Deserialize the cstruct into an appstruct based on the schema, run this appstruct through the preparer, if one is present, then validate the prepared appstruct. The
cstruct
value is deserialized into anappstruct
unconditionally.If
appstruct
returned by type deserialization and preparation is the valuecolander.null
, do something special before attempting validation:If the
missing
attribute of this node has been set explicitly, return its value. No validation of this value is performed; it is simply returned.If the
missing
attribute of this node has not been set explicitly, raise acolander.Invalid
exception error.
If the appstruct is not
colander.null
and cannot be validated , acolander.Invalid
exception will be raised.If a
cstruct
argument is not explicitly provided, it defaults tocolander.null
.
- class weaver.wps_restapi.colander_extras.VariableSchemaNode(*args, **kwargs)[source]
Object schema that allows defining a field key as variable by name supporting deserialization validation.
This definition is useful for defining a dictionary where the key name can be any string value but contains an underlying schema that has a very specific structure to be validated, such as in the following example.
{ "<any-key-id>": { "name": "required", "value": "something" }, "<another-key-id>": { "name": "other required", "value": "same schema" } }
This is accomplished using the following definition:
class RequiredDict(ExtendedMappingSchema): name = ExtendedSchemaNode(String()) value = ExtendedSchemaNode(String()) class ContainerAnyKey(ExtendedMappingSchema): var = RequiredDict(variable="{id}")
In the above example, the
var
node name that would normally be automatically generated and used to define the dictionary key will be replaced by{id}
(any string provided byvariable
keyword). The actual attribute namevar
could be replaced by anything.Warning
Since
variable
tells the deserialization converter to try matching any valid children node schema with the provided structure regardless of key name, you should ensure that the variable child node has at least onecolander.required
field (either directly or much deeper in the structure) to ensure it has something to validate against. Otherwise, anything will be matched (ie: drop all for empty structure would be considered as valid).The above statement also applies in case you provide more than one variable schema node under a mapping where both underlying schema are different. Without any required child node to distinguish between them, the sub-structure under each variable node could end up interchanged.
Note
It is recommended to use variable names that include invalid characters for class/attribute names (e.g.:
{}
or<>
) in order to ensure that any substitution when attempting to find the schema matching the variable doesn’t result in overrides. As presented in the following example,const
could get overridden if there was a structure to parse that contained both theconst
sub-structure and another one with an arbitrary key matched against<var>
.Note
In order to avoid invalid rendering of
<>
strings (interpreted as HTML tags by Swagger-UI), it is recommended to employ{}
notation for representing variable names.class ContainerAnyKeyWithName(ExtendedMappingSchema): var = RequiredDict(variable="const") # 'const' could clash with other below const = RequiredDict(String())
Using
{const}
instead would ensure that no override occurs as it is a syntax error to write{const} = RequiredDict(String())
in the class definition, but this value can still be used to create the internal mapping to evaluate sub-schemas without name clashes. As a plus, it also helps indicating that any key is accepted.See also
- classmethod is_variable(node: colander.SchemaNode) bool [source]
If current node is the variable field definition.
- _mark_variable_children()[source]
Ensures that any immediate children schema with variable key are detected.
Verifies if a
colander.MappingSchema
(or any of its extensions) contains childrenVariableSchemaNode
schema nodes for adequatedeserialize()
result later on.If children nodes are detected as variable, this schema is marked for special processing of the children nodes so they don’t get removed from the result (in case of optional field specified by
missing=drop
) nor raisecolander.Invalid
because they are supposed to becolander.required
.Note
Because mapping schema deserialization is normally processed by validating the content of a sub-node according to its
name
, it is not possible to use the normal approach (i.e.: get dictionary value under matching key-name and validate it against the sub-schema of same name). We must verify against every variable node available in the mapping (also ignoring constants nodes with explicitly named keys), then guess a valid match and finally return it with modified name corresponding to the expectedvariable
value in the parent mapping schema. Returning this modifiedname
withvariable
makes the value/sub-schema correspondence transparent to the parent mapping when dictionary get-by-key is called during the mapping validation.Warning
Because of the above reversed-processing method, all mapping nodes must derive from
VariableSchemaNode
to ensure they pre-process potential variable candidates.
- _get_sub_variable(subnodes: Iterable[colander.SchemaNode]) List[VariableSchemaNode] [source]
- deserialize(cstruct)[source]
Deserialize the cstruct into an appstruct based on the schema, run this appstruct through the preparer, if one is present, then validate the prepared appstruct. The
cstruct
value is deserialized into anappstruct
unconditionally.If
appstruct
returned by type deserialization and preparation is the valuecolander.null
, do something special before attempting validation:If the
missing
attribute of this node has been set explicitly, return its value. No validation of this value is performed; it is simply returned.If the
missing
attribute of this node has not been set explicitly, raise acolander.Invalid
exception error.
If the appstruct is not
colander.null
and cannot be validated , acolander.Invalid
exception will be raised.If a
cstruct
argument is not explicitly provided, it defaults tocolander.null
.
- _validate_cross_variable_mapping(variable_mapping: VariableSchemaNodeMapping) None [source]
Ensure there are no matches of the same child-property across multiple variable child-schema.
In such case, the evaluated variable mapping is ambiguous, and cannot discriminate which property validates the schema. Therefore, the full mapping schema containing the variables would be invalid.
There are 2 possible situations where there could be multiple variable child-schema. Either
additionalProperties
andpatternProperties
capability is supported and employed simultaneously, or the schema class definition is invalid. It is not allowed to have 2 genericadditionalProperties
assigned simultaneously to 2 distinct child-schema. A single child-schema using a keyword mapping should be used instead to define such combinations.
- _validate_unmatched_variable_mapping(variable_mapping: VariableSchemaNodeMapping, invalid_mapping: Dict[str, colander.Invalid], constant_children_schema_names: List[str], cstruct: weaver.typedefs.JSON) None [source]
Validate if any additional properties that could not be mapped by variables are permitted in the mapping schema.
- class weaver.wps_restapi.colander_extras.SortableMappingSchema(*args, **kwargs)[source]
Adds sorting capabilities to mapping schema.
Extended schema nodes that inherit from
colander.Mapping
schema-type such that they can request ordering of resulting fields by overriding properties_sort_first
and_sort_after
within the schema definition with lists of fields names to sort.See also
- deserialize(cstruct)[source]
Deserialize the cstruct into an appstruct based on the schema, run this appstruct through the preparer, if one is present, then validate the prepared appstruct. The
cstruct
value is deserialized into anappstruct
unconditionally.If
appstruct
returned by type deserialization and preparation is the valuecolander.null
, do something special before attempting validation:If the
missing
attribute of this node has been set explicitly, return its value. No validation of this value is performed; it is simply returned.If the
missing
attribute of this node has not been set explicitly, raise acolander.Invalid
exception error.
If the appstruct is not
colander.null
and cannot be validated , acolander.Invalid
exception will be raised.If a
cstruct
argument is not explicitly provided, it defaults tocolander.null
.
- static _order_deserialize(cstruct: Dict[str, Any], sort_first: Sequence[str] | None = None, sort_after: Sequence[str] | None = None) Dict[str, Any] [source]
Enforces ordering of expected fields in deserialized result, regardless of specified children/inherited schema.
This function takes care of moving back items in a consistent order for better readability from API responses against different loaded definitions field order from remote servers, local database, pre-defined objects, etc.
This way, any field insertion order from both the input
cstruct
following deserialization operation, the internal mechanics thatcolander
(and extended OpenAPI schema definitions) employ to process this deserialization, and theresult
dictionary fields order obtained from it all don’t matter.Using this, the order of inheritance of schema children classes also doesn’t matter, removing the need to worry about placing classes in any specific order when editing and joining the already complicated structures of inherited schemas.
- Parameters:
cstruct – JSON structure to be sorted that has already been processed by a schema’s
deserialize
call.sort_first – ordered list of fields to place first in the result.
sort_after – ordered list of fields to place last in the result.
- Returns:
results formed from cstruct following order: (<fields_firsts> + <other_fields> + <fields_after>)
- class weaver.wps_restapi.colander_extras.SchemaRefMappingSchema(*args, **kwargs)[source]
Mapping schema that supports auto-insertion of JSON-schema references provided in the definition.
Schema references are resolved under two distinct contexts:
When generating the JSON schema representation of the current schema node, for OpenAPI representation, the
_schema
attribute will indicate the$id
value that identifies this schema, while the_schema_meta
will provide the$schema
property that refers to the JSON meta-schema used by default to define it.When deserializing JSON data that should be validated against the current schema node, the generated JSON data will include the
$schema
property using the_schema
attribute. In this case, the$id
is omitted as that JSON represents an instance of the schema, but not its identity.
Alternatively, the parameters
schema
andschema_meta
can be passed as keyword arguments when instantiating the schema node. The references injection in the JSON schema and data can be disabled with parametersschema_include
andschema_meta_include
, or the corresponding class attributes. Furthermore, optionsschema_include_deserialize
,schema_include_convert_type
andschema_meta_include_convert_type
can be used to control individually each schema inclusion during either the type conversion context (JSON schema) or the deserialization context (JSON data validation).- _ext_schema_options = ['_schema_meta', '_schema_meta_include', '_schema_meta_include_convert_type', '_schema',...[source]
- _schema_deserialize(cstruct: weaver.typedefs.OpenAPISchema, schema_meta: str | None, schema_id: str | None) weaver.typedefs.OpenAPISchema [source]
Applies the relevant schema references and properties depending on JSON schema/data conversion context.
- _deserialize_impl(cstruct: DataT) DataT [source]
Converts the data using validation against the JSON schema definition.
- class weaver.wps_restapi.colander_extras.ExtendedSchemaNode(*args, **kwargs)[source]
Base schema node with support of extended functionalities.
Combines all
colander.SchemaNode
extensions so thatdefault
keyword is used first to resolve a missing field value duringdeserialize()
call, and then removes the node completely if nodefault
was provided, and evaluate variables as needed.See also
- _ext_first: Iterable[Type[ExtendedNodeInterface]][source]
- _ext_after: Iterable[Type[ExtendedNodeInterface]][source]
- _deserialize_extensions(cstruct: DataT, extensions: Iterable[Type[ExtendedNodeInterface]]) DataT [source]
- deserialize(cstruct: DataT) DataT [source]
Deserialize the cstruct into an appstruct based on the schema, run this appstruct through the preparer, if one is present, then validate the prepared appstruct. The
cstruct
value is deserialized into anappstruct
unconditionally.If
appstruct
returned by type deserialization and preparation is the valuecolander.null
, do something special before attempting validation:If the
missing
attribute of this node has been set explicitly, return its value. No validation of this value is performed; it is simply returned.If the
missing
attribute of this node has not been set explicitly, raise acolander.Invalid
exception error.
If the appstruct is not
colander.null
and cannot be validated , acolander.Invalid
exception will be raised.If a
cstruct
argument is not explicitly provided, it defaults tocolander.null
.
- class weaver.wps_restapi.colander_extras.ExpandStringList(*arg, **kw)[source]
Utility that will automatically deserialize a string to its list representation using the validator delimiter.
See also
In order to use this utility, it is important to place it first in the schema node class definition.
class NewNodeSchema(ExpandStringList, ExtendedSchemaNode): schema_type = String validator = CommaSeparated()
- deserialize(cstruct: DataT) DataT [source]
Deserialize the cstruct into an appstruct based on the schema, run this appstruct through the preparer, if one is present, then validate the prepared appstruct. The
cstruct
value is deserialized into anappstruct
unconditionally.If
appstruct
returned by type deserialization and preparation is the valuecolander.null
, do something special before attempting validation:If the
missing
attribute of this node has been set explicitly, return its value. No validation of this value is performed; it is simply returned.If the
missing
attribute of this node has not been set explicitly, raise acolander.Invalid
exception error.
If the appstruct is not
colander.null
and cannot be validated , acolander.Invalid
exception will be raised.If a
cstruct
argument is not explicitly provided, it defaults tocolander.null
.
- class weaver.wps_restapi.colander_extras.DropableSequenceSchema(*args, **kwargs)[source]
Sequence schema that supports the dropable functionality.
Extends
colander.SequenceSchema
to auto-handle dropping missing entry definitions when its value is eitherNone
,colander.null
orcolander.drop
.
- class weaver.wps_restapi.colander_extras.DefaultSequenceSchema(*args, **kwargs)[source]
Sequence schema that supports the default value functionality.
Extends
colander.SequenceSchema
to auto-handle replacing the result using the provideddefault
value when the deserialization results into a sequence that should normally be dropped.
- class weaver.wps_restapi.colander_extras.ExtendedSequenceSchema(*args, **kwargs)[source]
Sequence schema that supports all applicable extended schema node functionalities.
Combines
DefaultSequenceSchema
andDefaultSequenceSchema
extensions so thatdefault
keyword is used first to resolve a missing sequence duringdeserialize()
call, and then removes the node completely if nodefault
was provided.See also
- class weaver.wps_restapi.colander_extras.DropableMappingSchema(*args, **kwargs)[source]
Mapping schema that supports the dropable functionality.
Override the default
colander.MappingSchema
to auto-handle dropping missing field definitions when the corresponding value is eitherNone
,colander.null
orcolander.drop
.
- class weaver.wps_restapi.colander_extras.DefaultMappingSchema(*args, **kwargs)[source]
Mapping schema that supports the default value functionality.
Override the default
colander.MappingSchema
to auto-handle replacing missing entries by their specifieddefault
during deserialization.
- class weaver.wps_restapi.colander_extras.VariableMappingSchema(*args, **kwargs)[source]
Mapping schema that supports the variable functionality.
Override the default
colander.MappingSchema
to auto-handle replacing missing entries by their specifiedvariable
during deserialization.
- class weaver.wps_restapi.colander_extras.ExtendedMappingSchema(*args, **kwargs)[source]
Combines multiple extensions of
colander.MappingSchema
handle their corresponding keywords.Resolution is done so that
default
keyword is used first to resolve a missing object duringdeserialize()
call, and then removes the node completely if nodefault
was provided.See also
- class weaver.wps_restapi.colander_extras.StrictMappingSchema(*args, **kwargs)[source]
Object schema that will
raise
any unknown field not represented by children schema.This is equivalent to OpenAPI object mapping with
additionalProperties: false
. This type is useful for defining a dictionary that matches exactly a specific set of values and children schema.- ..note::
When doing schema deserialization to validate it, unknown keys would normally be removed without this class (default behaviour is to
ignore
them). With this schema, content under an unknown key is fails validation.
See also
- class weaver.wps_restapi.colander_extras.EmptyMappingSchema(*args: Any, **kwargs: Any)[source]
Mapping that guarantees it is completely empty for validation during deserialization.
Any children added to this schema are removed automatically.
- class weaver.wps_restapi.colander_extras.PermissiveMappingSchema(*args: Any, **kwargs: Any)[source]
Object schema that will
preserve
any unknown field to remain present in the resulting deserialization.This type is useful for defining a dictionary where some field names are not known in advance, or when more optional keys that don’t need to all be exhaustively provided in the schema are acceptable.
- ..note::
When doing schema deserialization to validate it, unknown keys would normally be removed without this class (default behaviour is to
ignore
them). With this schema, content under an unknown key usingpreserve
are passed down without any validation. Other fields that are explicitly specified with sub-schema nodes will still be validated as per usual behaviour.
See also
Example:
class AnyKeyObject(PermissiveMappingSchema): known_key = SchemaNode(String()) AnyKeyObject().deserialize({"unknown": "kept", "known_key": "requirement"})) # result: dictionary returned as is instead of removing 'unknown' entry # 'known_key' is still validated with its string schema
Note
This class is only a shorthand definition of
unknown
keyword for convenience. Allcolander.MappingSchema
support this natively.
- class weaver.wps_restapi.colander_extras.PermissiveSequenceSchema(*args, **kwargs)[source]
Array schema that allows any item type.
This is equivalent to the any of the following JSON schema definitions.
{ "type": "array", "items": {} }
{ "type": "array", "items": true }
{ "type": "array" }
- class weaver.wps_restapi.colander_extras.KeywordMapper(*args, **kwargs)[source]
Generic keyword mapper for any sub-implementers.
Allows specifying multiple combinations of schemas variants for an underlying schema definition. Each implementer must provide the corresponding
keyword
it defines amongst OpenAPI specification keywords.- _validate_keyword_schemas()[source]
Validation of children schemas under keyword.
Validation of keyword sub-nodes to be only defined as schema objects if property
_keyword_schemas_only_object = True
(i.e.: any node that defines its schema type asMapping
).Validation of keyword sub-nodes to all have matching structure of container if
_keyword_schemas_same_struct = True
(i.e.: allcolander.Mapping
, all literal schema-types, etc.).
- abstract _deserialize_keyword(cstruct)[source]
Deserialization and validation of a keyword-based schema definition.
This method must be implemented by the specific keyword to handle invalid subnodes according to the behaviour it offers.
See also
- _deserialize_subnode(node, cstruct, index)[source]
Deserialization and validation of sub-nodes under a keyword-based schema definition.
This method must be called by keyword deserialization implementers for deserialization of every sub-node in order to apply extended behaviour operations accordingly. The original
deserialize
method ofcolander
schema nodes should not be called directly, otherwise extensions will not be handled. This method will call it after resolving any applicable extension.Note
Because sub-nodes are within a non-schema node iterable, the SchemaMeta will not have extracted the destination name for us (ie: map key to compare against). Furthermore, the destination is not directly in the KeywordMapper class, but in its parent where its instance will be dumped according to the keyword resolution. Therefore, regardless of the child, they all have the same parent destination.
See also
- deserialize(cstruct)[source]
Deserialize the cstruct into an appstruct based on the schema, run this appstruct through the preparer, if one is present, then validate the prepared appstruct. The
cstruct
value is deserialized into anappstruct
unconditionally.If
appstruct
returned by type deserialization and preparation is the valuecolander.null
, do something special before attempting validation:If the
missing
attribute of this node has been set explicitly, return its value. No validation of this value is performed; it is simply returned.If the
missing
attribute of this node has not been set explicitly, raise acolander.Invalid
exception error.
If the appstruct is not
colander.null
and cannot be validated , acolander.Invalid
exception will be raised.If a
cstruct
argument is not explicitly provided, it defaults tocolander.null
.
- class weaver.wps_restapi.colander_extras.OneOfKeywordSchema(*args, **kwargs)[source]
Allows specifying multiple supported mapping schemas variants for an underlying schema definition.
Corresponds to the
oneOf
specifier of OpenAPI specification.Example:
class Variant1(MappingSchema): [...fields of Variant1...] class Variant2(MappingSchema): [...fields of Variant2...] class RequiredByBoth(MappingSchema): [...fields required by both Variant1 and Variant2...] class OneOfWithRequiredFields(OneOfKeywordSchema, RequiredByBoth): _one_of = (Variant1, Variant2) [...alternatively, field required by all variants here...]
In the above example, the validation (ie:
deserialize
) process will succeed if only one of the_one_of
variants’ validator completely succeed, and will fail if every variant fails validation execution. The operation will also fail if more than one validation succeeds.Note
Class
OneOfWithRequiredFields
in the example is a shortcut variant to generate a specification that represents the pseudo-codeoneOf([<list-of-objects-with-same-base>])
.The real OpenAPI method to implement the above very commonly occurring situation is as presented by the following pseudo-code:
oneOf[allOf[RequiredByBoth, Variant1], allOf[RequiredByBoth, Variant2]]
This is both painful to read and is a lot of extra code to write when you actually expand it all into classes (each
oneOf/allOf
is another class). ClassOneOfKeywordSchema
will actually simplify this by automatically making theallOf
definitions for you if it detects other schema nodes thanoneOf
specified in the class bases. You can still do the fulloneOf/allOf
classes expansion manually though, it will result into the same specification.Warning
When
oneOf/allOf
automatic expansion occurs during schema generationWarning
When calling
deserialize()
, because the validation process requires exactly one of the variants to succeed to consider the whole object to evaluate as valid, it is important to insert more permissive validators later in the_one_of
iterator (orvalidator
keyword). For example, having a variant with all fields defined as optional (ie: withmissing=drop
) inserted as first item in_one_of
will make it always succeed regardless of following variants (since an empty schema with everything dropped is valid for optional-only elements). This would have as side effect of potentially failing the validation if other object are also valid depending on the received schema because the schema cannot be discriminated between many. If this occurs, it means the your schemas are too permissive.In the event that you have very similar schemas that can sometime match except one identifier (e.g.: field
type
defining the type of object), consider adding avalidator
to each sub-node with explicit values to solve the discrimination problem.As a shortcut, the OpenAPI keyword
discriminator
can be provided to try matching as a last resort.For example:
class Animal(ExtendedMappingSchema): name = ExtendedSchemaNode(String()) type = ExtendedSchemaNode(String()) # with explicit definition, this shouldn't be here ## With explicit definitions, each below 'Animal' class should be defined as follows ## type = ExtendedSchemaNode(String(), validator=colander.OneOf(['<animal>'])) class Cat(Animal): [...] # many **OPTIONAL** fields class Dog(Animal): [...] # many **OPTIONAL** fields # With the discriminator keyword, following is possible # (each schema must provide the same property name) class SomeAnimal(OneOfMappingSchema): discriminator = "type" _one_of = [ Cat(), Dog(), ] # If more specific mapping resolutions than 1-to-1 by name are needed, # an explicit dictionary can be specified instead. class SomeAnimal(OneOfMappingSchema): discriminator = { "propertyName": "type", # correspond to 'type' of 'Animal' "mapping": { "cat": Cat, "dog": Dog # map expected values to target schemas } } _one_of = [ Cat(), Dog(), ]
Note
Keyword
discriminator
supports a map of key-string to schemas-type as presented in the example, and the key must be located at the top level of the mapping. If onlydiscriminator = "<field>"
is provided, the definition will be created automatically using theexample
(which should be only the matching value) of the corresponding field of each node within the_one_of
mapping.When multiple valid schemas are matched against the input data, the error will be raised and returned with corresponding erroneous elements for each sub-schema (fully listed).
- class weaver.wps_restapi.colander_extras.AllOfKeywordSchema(*args, **kwargs)[source]
Allows specifying all the required partial mapping schemas for an underlying complete schema definition.
Corresponds to the
allOf
specifier of OpenAPI specification.Example:
class RequiredItem(ExtendedMappingSchema): item = ExtendedSchemaNode(String()) class RequiredType(ExtendedMappingSchema): type = ExtendedSchemaNode(String()) class AllRequired(AnyKeywordSchema): _all_of = [RequiredItem(), RequiredType()]
Value parsed with schema this definition will be valid only when every since one of the sub-schemas is valid. Any sub-schema raising an invalid error for any reason with make the whole schema validation fail.
- class weaver.wps_restapi.colander_extras.AnyOfKeywordSchema(*args, **kwargs)[source]
Allows specifying all mapping schemas that can be matched for an underlying schema definition.
Corresponds to the
anyOf
specifier of OpenAPI specification.Contrary to
OneOfKeywordSchema
that MUST be validated with exactly one schema, this definition will continue parsing all possibilities and apply validated sub-schemas on top of each other. Not all schemas have to be valid like in the case ofAllOfKeywordSchema
to succeed, as long as at least one of them is valid.Example:
class RequiredItem(ExtendedMappingSchema): item = ExtendedSchemaNode(String()) class RequiredType(ExtendedMappingSchema): type = ExtendedSchemaNode(String()) class RequiredFields(ExtendedMappingSchema): field_str = ExtendedSchemaNode(String()) field_int = ExtendedSchemaNode(Integer()) class AnyRequired(AnyKeywordSchema): _any_of = [RequiredItem(), RequiredType(), RequiredFields()] # following is valid because their individual parts have all required sub-fields, result is their composition AnyRequired().deserialize({"type": "test", "item": "valid"}) # result: {"type": "test", "item": "valid"} # following is also valid because even though 'item' is missing, the 'type' is present AnyRequired().deserialize({"type": "test"}) # result: {"type": "test"} # following is invalid because every one of the sub-field of individual parts are missing AnyRequired().deserialize({"type": "test"}) # following is invalid because fields of 'RequiredFields' are only partially fulfilled AnyRequired().deserialize({"field_str": "str"}) # following is valid because although fields of 'RequiredFields' are not all fulfilled, 'RequiredType' is valid AnyRequired().deserialize({"field_str": "str", "type": "str"}) # result: {"type": "test"} # following is invalid because 'RequiredFields' field 'field_int' is incorrect schema type AnyRequired().deserialize({"field_str": "str", "field_int": "str"}) # following is valid, but result omits 'type' because its schema-type is incorrect, while others are valid AnyRequired().deserialize({"field_str": "str", "field_int": 1, "items": "fields", "type": 1}) # result: {"field_str": "str", "field_int": 1, "items": "fields"}
Warning
Because valid items are applied on top of each other by merging fields during combinations, conflicting field names of any valid schema will contain only the final valid parsing during deserialization.
- class weaver.wps_restapi.colander_extras.NotKeywordSchema(*args, **kwargs)[source]
Allows specifying specific schema conditions that fails underlying schema definition validation if present.
Corresponds to the
not
specifier of OpenAPI specification.Example:
class RequiredItem(ExtendedMappingSchema): item = ExtendedSchemaNode(String()) class MappingWithType(ExtendedMappingSchema): type = ExtendedSchemaNode(String()) class MappingWithoutType(NotKeywordSchema, RequiredItem): _not = [MappingWithType()] class MappingOnlyNotType(NotKeywordSchema): _not = [MappingWithType()] # following will raise invalid error even if 'item' is valid because 'type' is also present MappingWithoutType().deserialize({"type": "invalid", "item": "valid"}) # following will return successfully with only 'item' because 'type' was not present MappingWithoutType().deserialize({"item": "valid", "value": "ignore"}) # result: {"item": "valid"} # following will return an empty mapping dropping 'item' since it only needs to ensure 'type' was not present, # but did not provide any additional fields requirement from other class inheritances MappingOnlyNotType().deserialize({"item": "valid"}) # result: {}
- class weaver.wps_restapi.colander_extras.SchemaRefConverter(dispatcher)[source]
Converter that will add OpenAPI
$schema
and$id
references if they are provided in the schema node.
- class weaver.wps_restapi.colander_extras.ExtendedTypeConverter(dispatcher)[source]
Base converter with support of Extended schema type definitions.
- class weaver.wps_restapi.colander_extras.KeywordTypeConverter(dispatcher)[source]
Generic keyword converter that builds schema with a list of sub-schemas under the keyword.
- class weaver.wps_restapi.colander_extras.OneOfKeywordTypeConverter(dispatcher)[source]
Object converter that generates the
oneOf
keyword definition.This object does a bit more work than other
KeywordTypeConverter
as it handles the shorthand definition as described inOneOfKeywordSchema
See also
- convert_type(schema_node: OneOfKeywordSchema) weaver.typedefs.OpenAPISchemaOneOf [source]
- class weaver.wps_restapi.colander_extras.AllOfKeywordTypeConverter(dispatcher)[source]
Object converter that generates the
allOf
keyword definition.
- class weaver.wps_restapi.colander_extras.AnyOfKeywordTypeConverter(dispatcher)[source]
Object converter that generates the
anyOf
keyword definition.
- class weaver.wps_restapi.colander_extras.NotKeywordTypeConverter(dispatcher)[source]
Object converter that generates the
not
keyword definition.
- class weaver.wps_restapi.colander_extras.ExtendedObjectTypeConverter(dispatcher)[source]
Object convert for mapping type with extended capabilities.
- class weaver.wps_restapi.colander_extras.VariableObjectTypeConverter(dispatcher)[source]
Object convertor with
additionalProperties
for eachproperties
marked asVariableSchemaNode
.
- class weaver.wps_restapi.colander_extras.OAS3TypeConversionDispatcher(custom_converters: Dict[colander.SchemaType, cornice_swagger.converters.schema.TypeConverter] | None = None, default_converter: cornice_swagger.converters.schema.TypeConverter | None = None)[source]
- class weaver.wps_restapi.colander_extras.OAS3ParameterConverter[source]
- class weaver.wps_restapi.colander_extras.OAS3ParameterConversionDispatcher(definition_handler)[source]
- class weaver.wps_restapi.colander_extras.OAS3DefinitionHandler(ref=0, type_converter=TypeConverter())[source]
Handles Swagger object definitions provided by cornice as colander schemas.
- Parameters:
ref – The depth that should be used by self.ref when calling self.from_schema.
- from_schema(schema_node: colander.SchemaNode, base_name: str | None = None) weaver.typedefs.OpenAPISchema [source]
Convert the schema node to an OAS schema.
If the schema node provided
schema_ref
URL and that the object is not defined, use it instead as an external reference.
- _ref_recursive(schema, depth, base_name=None)[source]
Dismantle nested swagger schemas into several definitions using JSON pointers. Note: This can be dangerous since definition titles must be unique.
- Parameters:
schema – Base swagger schema.
depth – How many levels of the swagger object schemas should be split into swagger definitions with JSON pointers. Default (0) is no split. You may use negative values to split everything.
base_name – If schema doesn’t have a name, the caller may provide it to be used as reference.
- Return type:
- Returns:
JSON pointer to the root definition schema, or the original definition if depth is zero.
- _process_items(schema: Dict[str, Any], list_type: typing_extensions.Literal[oneOf, allOf, anyOf, not], item_list: List[Dict[str, Any]], depth: int, base_name: str) Dict[str, Any] [source]
Generates recursive schema definitions with JSON ref pointers for nested keyword objects.
Contrary to the original implementation, preserves additional metadata like the object title, description, etc.
- class weaver.wps_restapi.colander_extras.OAS3ParameterHandler(definition_handler=DefinitionHandler(), ref=False, type_converter=TypeConverter(), parameter_converter=ParameterConverter(TypeConverter()))[source]
Handles swagger parameter definitions.
- Parameters:
definition_handler – Callable that handles swagger definition schemas.
ref – Specifies the ref value when calling from_xxx methods.
- class weaver.wps_restapi.colander_extras.OAS3ResponseHandler(definition_handler=DefinitionHandler(), type_converter=TypeConverter(), ref=False)[source]
Handles swagger response definitions.
- Parameters:
definition_handler – Callable that handles swagger definition schemas.
ref – Specifies the ref value when calling from_xxx methods.
- class weaver.wps_restapi.colander_extras.CorniceOpenAPI(services: Sequence[cornice.Service] | None = None, def_ref_depth: int = 0, param_ref: bool = False, resp_ref: bool = False, pyramid_registry: pyramid.registry.Registry | None = None)[source]
Handles the creation of a swagger document from a cornice application.
- Parameters:
services – List of cornice services to document. You may use cornice.service.get_services() to get it.
def_ref_depth – How depth swagger object schemas should be split into swaggger definitions with JSON pointers. Default (0) is no split. You may use negative values to split everything.
param_ref – Defines if swagger parameters should be put inline on the operation or on the parameters section and referenced by JSON pointers. Default is inline.
resp_ref – Defines if swagger responses should be put inline on the operation or on the responses section and referenced by JSON pointers. Default is inline.
pyramid_registry – Pyramid registry, should be passed if you use pyramid routes instead of service level paths.
- openapi_spec = 3[source]
OpenAPI specification version that should be used for generation. OpenAPI 3 is required to support ‘oneOf’, ‘allOf’, ‘anyOf’ and ‘not’ keywords as well as other multiple views of same method for different content-type.
- generate(title: str | None = None, version: str | None = None, base_path: str | None = None, info: weaver.typedefs.OpenAPISpecInfo | None = None, swagger: weaver.typedefs.JSON | None = None, openapi_spec: typing_extensions.Literal[2, 3] = 2, **kwargs) weaver.typedefs.OpenAPISpecification [source]
Generate an OpenAPI documentation. Keyword arguments may be used to provide additional information to build methods as such ignores.
- Parameters:
title – The name presented on the swagger document.
version – The version of the API presented on the swagger document.
base_path – The path that all requests to the API must refer to.
info – Swagger info field.
swagger – Extra fields that should be provided on the swagger documentation.
openapi_spec – The OpenAPI specification version to use for swagger documentation format.
- Return type:
- Returns:
Full OpenAPI/Swagger compliant specification for the application.