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¶
-
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, msg_err=_MSG_ERR)[source]¶ Validator that ensures the given value matches one of the available choices, but allowing case insensitive values.
-
class
weaver.wps_restapi.colander_extras.
StringRange
(min=None, max=None, **kwargs)[source]¶ Validator that provides the same functionalities as
colander.Range
for a numerical string value.
-
class
weaver.wps_restapi.colander_extras.
SchemeURL
(schemes=None, msg=None, flags=re.IGNORECASE)[source]¶ String representation of an URL with extended set of allowed URI schemes.
See also
colander.url
[remote http(s)/ftp(s)]colander.file_uri
[local file://]
-
class
weaver.wps_restapi.colander_extras.
SemanticVersion
(*args, v_prefix=False, rc_suffix=True, **kwargs)[source]¶ String representation that is valid against Semantic Versioning specification.
See also
-
class
weaver.wps_restapi.colander_extras.
ExtendedBoolean
(*args, true_choices=None, false_choices=None, **kwargs)[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
(*_, allow_string=False, strict=True, **__)[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
(*_, allow_string=False, strict=True, **__)[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]¶ A type representing a Unicode string.
This type constructor accepts two arguments:
encoding
Represents the encoding which should be applied to value serialization and deserialization, for example
utf-8
. Ifencoding
is passed asNone
, theserialize
method of this type will not do any special encoding of the appstruct it is provided, nor will thedeserialize
method of this type do any special decoding of the cstruct it is provided; inputs and outputs will be assumed to be Unicode.encoding
defaults toNone
.If
encoding
isNone
:A Unicode input value to
serialize
is returned untouched.A non-Unicode input value to
serialize
is run through theunicode()
function without anencoding
parameter (unicode(value)
) and the result is returned.A Unicode input value to
deserialize
is returned untouched.A non-Unicode input value to
deserialize
is run through theunicode()
function without anencoding
parameter (unicode(value)
) and the result is returned.
If
encoding
is notNone
:A Unicode input value to
serialize
is run through theunicode
function with the encoding parameter (unicode(value, encoding)
) and the result (astr
object) is returned.A non-Unicode input value to
serialize
is converted to a Unicode using the encoding (unicode(value, encoding)
); subsequently the Unicode object is re-encoded to astr
object using the encoding and returned.A Unicode input value to
deserialize
is returned untouched.A non-Unicode input value to
deserialize
is converted to astr
object usingstr(value
). The resulting str value is converted to Unicode using the encoding (unicode(value, encoding)
) and the result is returned.
A corollary: If a string (as opposed to a unicode object) is provided as a value to either the serialize or deserialize method of this type, and the type also has an non-None
encoding
, the string must be encoded with the type’s encoding. If this is not true, ancolander.Invalid
error will result.allow_empty
Boolean, if True allows deserialization of an empty string. If False (default), empty strings will deserialize to
colander.null
The subnodes of the
colander.SchemaNode
that wraps this type are ignored.
-
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
(self, 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
(self, 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>
.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 giving an indication that any key is accepted.See also
-
_mark_variable_children
(self)[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.
-
deserialize
(self, 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.
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
(self, 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: Optional[Sequence[str]] = None, sort_after: Optional[Sequence[str]] = 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.
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
-
deserialize
(self, 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.
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.
PermissiveMappingSchema
(*args, **kwargs)[source]¶ Object schema that will allow 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.
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 ispreserved
as it was received without any validation. Other fields that are explicitly specified with sub-schema nodes will still be validated as per usual behaviour.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.
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
(self)[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
(self, 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
(self, 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
(self, 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 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.This is equivalent to OpenAPI object mapping with
additionalProperties: false
, but is more explicit in the definition of invalid or conflicting field names with explicit definitions during deserialization.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.
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
(self: OneOfKeywordSchema, schema_node) → Dict[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.
VariableObjectTypeConverter
(dispatcher)[source]¶ Object convertor with
additionalProperties
for eachproperties
marked asVariableSchemaNode
.
-
class
weaver.wps_restapi.colander_extras.
OAS3TypeConversionDispatcher
(custom_converters=None, default_converter=None)[source]¶
-
weaver.wps_restapi.colander_extras.
_make_node_instance
(schema_node_or_class: Union[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: Union[colander.SchemaNode, Type[colander.SchemaNode]], check: bool = False) → Optional[colander.SchemaType][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 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