Hello community,
here is the log from the commit of package python-openapi-core for
openSUSE:Factory checked in at 2019-07-23 22:40:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-openapi-core (Old)
and /work/SRC/openSUSE:Factory/.python-openapi-core.new.4126 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-openapi-core"
Tue Jul 23 22:40:55 2019 rev:3 rq:717909 version:0.11.0
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-openapi-core/python-openapi-core.changes
2019-06-06 18:18:13.196670257 +0200
+++
/work/SRC/openSUSE:Factory/.python-openapi-core.new.4126/python-openapi-core.changes
2019-07-23 22:41:01.306899418 +0200
@@ -1,0 +2,11 @@
+Tue Jul 23 13:45:01 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 0.11.0:
+ * End of Python 3.4 support (#136)
+ * Add support for one-of with any type (#133)
+ * Modify FlaskOpenAPIRequest to accommodate path variables (#141)
+ * Primitive types unmarshallers (#138)
+ * attr errors hashable fix (#143)
+ * Parameters on path item object support (#144)
+
+-------------------------------------------------------------------
Old:
----
0.10.0.tar.gz
New:
----
0.11.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-openapi-core.spec ++++++
--- /var/tmp/diff_new_pack.GC3GWq/_old 2019-07-23 22:41:01.814898774 +0200
+++ /var/tmp/diff_new_pack.GC3GWq/_new 2019-07-23 22:41:01.814898774 +0200
@@ -17,9 +17,8 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
-# remove with update to > 0.5.0; atm it is not working on py2 at all
Name: python-openapi-core
-Version: 0.10.0
+Version: 0.11.0
Release: 0
Summary: Adds client-side and server-side support for the oas3
License: BSD-3-Clause
++++++ 0.10.0.tar.gz -> 0.11.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.10.0/.travis.yml
new/openapi-core-0.11.0/.travis.yml
--- old/openapi-core-0.10.0/.travis.yml 2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/.travis.yml 2019-06-18 23:42:44.000000000 +0200
@@ -3,7 +3,6 @@
matrix:
include:
- python: 2.7
- - python: 3.4
- python: 3.5
- python: 3.6
- python: 3.7
@@ -14,12 +13,12 @@
allow_failures:
- python: nightly
before_install:
-- if [[ $TRAVIS_PYTHON_VERSION == '3.2' ]]; then pip install 'coverage<4.0.0';
fi
- pip install codecov
- pip install 'py>=1.5.0'
install:
-- pip install -e .
+- pip install -r requirements.txt
- pip install -r requirements_dev.txt
+- pip install -e .
script:
- python setup.py test
after_success:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.10.0/openapi_core/__init__.py
new/openapi-core-0.11.0/openapi_core/__init__.py
--- old/openapi-core-0.10.0/openapi_core/__init__.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/__init__.py 2019-06-18
23:42:44.000000000 +0200
@@ -6,7 +6,7 @@
__author__ = 'Artur Maciag'
__email__ = '[email protected]'
-__version__ = '0.10.0'
+__version__ = '0.11.0'
__url__ = 'https://github.com/p1c2u/openapi-core'
__license__ = 'BSD 3-Clause License'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/content/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/content/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/content/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/content/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,13 +1,13 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPIContentError(OpenAPIMappingError):
pass
[email protected]
[email protected](hash=True)
class MimeTypeNotFound(OpenAPIContentError):
mimetype = attr.ib()
availableMimetypes = attr.ib()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/content/models.py
new/openapi-core-0.11.0/openapi_core/schema/content/models.py
--- old/openapi-core-0.10.0/openapi_core/schema/content/models.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/content/models.py
2019-06-18 23:42:44.000000000 +0200
@@ -18,4 +18,4 @@
if fnmatch.fnmatch(mimetype, key):
return value
- raise MimeTypeNotFound(mimetype, self.keys())
+ raise MimeTypeNotFound(mimetype, list(self.keys()))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/media_types/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/media_types/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/media_types/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/media_types/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,19 +1,21 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPIMediaTypeError(OpenAPIMappingError):
pass
[email protected]
+
[email protected](hash=True)
class InvalidMediaTypeValue(OpenAPIMediaTypeError):
original_exception = attr.ib()
def __str__(self):
return "Mimetype invalid: {0}".format(self.original_exception)
[email protected]
+
[email protected](hash=True)
class InvalidContentType(OpenAPIMediaTypeError):
mimetype = attr.ib()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/media_types/models.py
new/openapi-core-0.11.0/openapi_core/schema/media_types/models.py
--- old/openapi-core-0.10.0/openapi_core/schema/media_types/models.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/media_types/models.py
2019-06-18 23:42:44.000000000 +0200
@@ -47,6 +47,7 @@
raise InvalidMediaTypeValue(exc)
try:
- return self.schema.validate(unmarshalled,
custom_formatters=custom_formatters)
+ return self.schema.validate(
+ unmarshalled, custom_formatters=custom_formatters)
except OpenAPISchemaError as exc:
raise InvalidMediaTypeValue(exc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/operations/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/operations/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/operations/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/operations/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,13 +1,13 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPIOperationError(OpenAPIMappingError):
pass
[email protected]
[email protected](hash=True)
class InvalidOperation(OpenAPIOperationError):
path_pattern = attr.ib()
http_method = attr.ib()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/parameters/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/parameters/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/parameters/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/parameters/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,13 +1,13 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPIParameterError(OpenAPIMappingError):
pass
[email protected]
[email protected](hash=True)
class MissingParameter(OpenAPIParameterError):
name = attr.ib()
@@ -15,7 +15,7 @@
return "Missing parameter (without default value):
{0}".format(self.name)
[email protected]
[email protected](hash=True)
class MissingRequiredParameter(OpenAPIParameterError):
name = attr.ib()
@@ -23,7 +23,7 @@
return "Missing required parameter: {0}".format(self.name)
[email protected]
[email protected](hash=True)
class EmptyParameterValue(OpenAPIParameterError):
name = attr.ib()
@@ -31,7 +31,7 @@
return "Value of parameter cannot be empty: {0}".format(self.name)
[email protected]
[email protected](hash=True)
class InvalidParameterValue(OpenAPIParameterError):
name = attr.ib()
original_exception = attr.ib()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/parameters/models.py
new/openapi-core-0.11.0/openapi_core/schema/parameters/models.py
--- old/openapi-core-0.10.0/openapi_core/schema/parameters/models.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/parameters/models.py
2019-06-18 23:42:44.000000000 +0200
@@ -118,6 +118,7 @@
raise InvalidParameterValue(self.name, exc)
try:
- return self.schema.validate(unmarshalled,
custom_formatters=custom_formatters)
+ return self.schema.validate(
+ unmarshalled, custom_formatters=custom_formatters)
except OpenAPISchemaError as exc:
raise InvalidParameterValue(self.name, exc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/paths/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/paths/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/paths/exceptions.py
1970-01-01 01:00:00.000000000 +0100
+++ new/openapi-core-0.11.0/openapi_core/schema/paths/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -0,0 +1,15 @@
+import attr
+
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
+
+class OpenAPIPathError(OpenAPIMappingError):
+ pass
+
+
[email protected](hash=True)
+class InvalidPath(OpenAPIPathError):
+ path_pattern = attr.ib()
+
+ def __str__(self):
+ return "Unknown path {0}".format(self.path_pattern)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/request_bodies/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/request_bodies/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/request_bodies/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/request_bodies/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,13 +1,13 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPIRequestBodyError(OpenAPIMappingError):
pass
[email protected]
[email protected](hash=True)
class MissingRequestBody(OpenAPIRequestBodyError):
request = attr.ib()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/responses/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/responses/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/responses/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/responses/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,13 +1,13 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPIResponseError(OpenAPIMappingError):
pass
[email protected]
[email protected](hash=True)
class InvalidResponse(OpenAPIResponseError):
http_status = attr.ib()
responses = attr.ib()
@@ -16,7 +16,7 @@
return "Unknown response http status:
{0}".format(str(self.http_status))
[email protected]
[email protected](hash=True)
class MissingResponseContent(OpenAPIResponseError):
response = attr.ib()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/schemas/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/schemas/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/schemas/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/schemas/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,13 +1,13 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPISchemaError(OpenAPIMappingError):
pass
[email protected]
[email protected](hash=True)
class NoValidSchema(OpenAPISchemaError):
value = attr.ib()
@@ -15,7 +15,7 @@
return "No valid schema found for value: {0}".format(self.value)
[email protected]
[email protected](hash=True)
class UndefinedItemsSchema(OpenAPISchemaError):
type = attr.ib()
@@ -23,7 +23,7 @@
return "Null value for schema type {0}".format(self.type)
[email protected]
[email protected](hash=True)
class InvalidSchemaValue(OpenAPISchemaError):
msg = attr.ib()
value = attr.ib()
@@ -32,7 +32,8 @@
def __str__(self):
return self.msg.format(value=self.value, type=self.type)
[email protected]
+
[email protected](hash=True)
class InvalidCustomFormatSchemaValue(InvalidSchemaValue):
original_exception = attr.ib()
@@ -40,14 +41,15 @@
return self.msg.format(value=self.value, type=self.type,
exception=self.original_exception)
[email protected]
[email protected](hash=True)
class UndefinedSchemaProperty(OpenAPISchemaError):
extra_props = attr.ib()
def __str__(self):
return "Extra unexpected properties found in schema:
{0}".format(self.extra_props)
[email protected]
+
[email protected](hash=True)
class InvalidSchemaProperty(OpenAPISchemaError):
property_name = attr.ib()
original_exception = attr.ib()
@@ -55,7 +57,8 @@
def __str__(self):
return "Invalid schema property {0}: {1}".format(self.property_name,
self.original_exception)
[email protected]
+
[email protected](hash=True)
class MissingSchemaProperty(OpenAPISchemaError):
property_name = attr.ib()
@@ -63,7 +66,7 @@
return "Missing schema property: {0}".format(self.property_name)
[email protected]
[email protected](hash=True)
class NoOneOfSchema(OpenAPISchemaError):
type = attr.ib()
@@ -71,9 +74,22 @@
return "Exactly one valid schema type {0} should be valid, None
found.".format(self.type)
[email protected]
[email protected](hash=True)
class MultipleOneOfSchema(OpenAPISchemaError):
type = attr.ib()
def __str__(self):
return "Exactly one schema type {0} should be valid, more than one
found".format(self.type)
+
+
+class UnmarshallerError(OpenAPIMappingError):
+ pass
+
+
+class UnmarshallerStrictTypeError(UnmarshallerError):
+ value = attr.ib()
+ types = attr.ib()
+
+ def __str__(self):
+ return "Value {value} is not one of types {types}".format(
+ self.value, self.types)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/schemas/models.py
new/openapi-core-0.11.0/openapi_core/schema/schemas/models.py
--- old/openapi-core-0.10.0/openapi_core/schema/schemas/models.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/schemas/models.py
2019-06-18 23:42:44.000000000 +0200
@@ -2,7 +2,6 @@
import attr
import functools
import logging
-from base64 import b64decode, b64encode
from collections import defaultdict
from datetime import date, datetime
from uuid import UUID
@@ -17,6 +16,7 @@
InvalidSchemaValue, UndefinedSchemaProperty, MissingSchemaProperty,
OpenAPISchemaError, NoOneOfSchema, MultipleOneOfSchema, NoValidSchema,
UndefinedItemsSchema, InvalidCustomFormatSchemaValue,
InvalidSchemaProperty,
+ UnmarshallerStrictTypeError,
)
from openapi_core.schema.schemas.util import (
forcebool, format_date, format_datetime, format_byte, format_uuid,
@@ -156,14 +156,19 @@
return set(required)
def get_cast_mapping(self, custom_formatters=None, strict=True):
+ primitive_unmarshallers = self.get_primitive_unmarshallers(
+ custom_formatters=custom_formatters)
+
+ primitive_unmarshallers_partial = dict(
+ (t, functools.partial(u, type_format=self.format, strict=strict))
+ for t, u in primitive_unmarshallers.items()
+ )
+
pass_defaults = lambda f: functools.partial(
f, custom_formatters=custom_formatters, strict=strict)
mapping = self.DEFAULT_CAST_CALLABLE_GETTER.copy()
+ mapping.update(primitive_unmarshallers_partial)
mapping.update({
- SchemaType.STRING: pass_defaults(self._unmarshal_string),
- SchemaType.BOOLEAN: pass_defaults(self._unmarshal_boolean),
- SchemaType.INTEGER: pass_defaults(self._unmarshal_integer),
- SchemaType.NUMBER: pass_defaults(self._unmarshal_number),
SchemaType.ANY: pass_defaults(self._unmarshal_any),
SchemaType.ARRAY: pass_defaults(self._unmarshal_collection),
SchemaType.OBJECT: pass_defaults(self._unmarshal_object),
@@ -185,6 +190,10 @@
raise InvalidSchemaValue("Null value for non-nullable schema",
value, self.type)
return self.default
+ if self.enum and value not in self.enum:
+ raise InvalidSchemaValue(
+ "Value {value} not in enum choices: {type}", value, self.enum)
+
cast_mapping = self.get_cast_mapping(
custom_formatters=custom_formatters, strict=strict)
@@ -194,6 +203,9 @@
cast_callable = cast_mapping[self.type]
try:
return cast_callable(value)
+ except UnmarshallerStrictTypeError:
+ raise InvalidSchemaValue(
+ "Value {value} is not of type {type}", value, self.type)
except ValueError:
raise InvalidSchemaValue(
"Failed to cast value {value} to type {type}", value,
self.type)
@@ -208,69 +220,27 @@
if casted is None and not self.required:
return None
- if self.enum and casted not in self.enum:
- raise InvalidSchemaValue(
- "Value {value} not in enum choices: {type}", value, self.enum)
-
return casted
- def _unmarshal_string(self, value, custom_formatters=None, strict=True):
- if strict and not isinstance(value, (text_type, binary_type)):
- raise InvalidSchemaValue("Value {value} is not of type {type}",
value, self.type)
-
- try:
- schema_format = SchemaFormat(self.format)
- except ValueError:
- msg = "Unsupported format {type} unmarshalling for value {value}"
- if custom_formatters is not None:
- formatstring = custom_formatters.get(self.format)
- if formatstring is None:
- raise InvalidSchemaValue(msg, value, self.format)
- else:
- raise InvalidSchemaValue(msg, value, self.format)
- else:
- formatstring = self.STRING_FORMAT_CALLABLE_GETTER[schema_format]
-
- try:
- return formatstring.unmarshal(value)
- except ValueError as exc:
- raise InvalidCustomFormatSchemaValue(
- "Failed to format value {value} to format {type}:
{exception}", value, self.format, exc)
-
- def _unmarshal_integer(self, value, custom_formatters=None, strict=True):
- if strict and not isinstance(value, integer_types):
- raise InvalidSchemaValue("Value {value} is not of type {type}",
value, self.type)
-
- return int(value)
-
- def _unmarshal_number(self, value, custom_formatters=None, strict=True):
- if strict and not isinstance(value, (float, ) + integer_types):
- raise InvalidSchemaValue("Value {value} is not of type {type}",
value, self.type)
-
- try:
- schema_format = SchemaFormat(self.format)
- except ValueError:
- msg = "Unsupported format {type} unmarshalling for value {value}"
- if custom_formatters is not None:
- formatnumber = custom_formatters.get(self.format)
- if formatnumber is None:
- raise InvalidSchemaValue(msg, value, self.format)
- else:
- raise InvalidSchemaValue(msg, value, self.format)
- else:
- formatnumber = self.NUMBER_FORMAT_CALLABLE_GETTER[schema_format]
+ def get_primitive_unmarshallers(self, **options):
+ from openapi_core.schema.schemas.unmarshallers import (
+ StringUnmarshaller, BooleanUnmarshaller, IntegerUnmarshaller,
+ NumberUnmarshaller,
+ )
- try:
- return formatnumber.unmarshal(value)
- except ValueError as exc:
- raise InvalidCustomFormatSchemaValue(
- "Failed to format value {value} to format {type}:
{exception}", value, self.format, exc)
-
- def _unmarshal_boolean(self, value, custom_formatters=None, strict=True):
- if strict and not isinstance(value, (bool, )):
- raise InvalidSchemaValue("Value {value} is not of type {type}",
value, self.type)
+ unmarshallers_classes = {
+ SchemaType.STRING: StringUnmarshaller,
+ SchemaType.BOOLEAN: BooleanUnmarshaller,
+ SchemaType.INTEGER: IntegerUnmarshaller,
+ SchemaType.NUMBER: NumberUnmarshaller,
+ }
+
+ unmarshallers = dict(
+ (t, klass(**options))
+ for t, klass in unmarshallers_classes.items()
+ )
- return forcebool(value)
+ return unmarshallers
def _unmarshal_any(self, value, custom_formatters=None, strict=True):
types_resolve_order = [
@@ -278,13 +248,32 @@
SchemaType.INTEGER, SchemaType.NUMBER, SchemaType.STRING,
]
cast_mapping = self.get_cast_mapping()
- for schema_type in types_resolve_order:
- cast_callable = cast_mapping[schema_type]
- try:
- return cast_callable(value)
- # @todo: remove ValueError when validation separated
- except (OpenAPISchemaError, TypeError, ValueError):
- continue
+ if self.one_of:
+ result = None
+ for subschema in self.one_of:
+ try:
+ casted = subschema.cast(value, custom_formatters)
+ except (OpenAPISchemaError, TypeError, ValueError):
+ continue
+ else:
+ if result is not None:
+ raise MultipleOneOfSchema(self.type)
+ result = casted
+
+ if result is None:
+ raise NoOneOfSchema(self.type)
+
+ return result
+ else:
+ for schema_type in types_resolve_order:
+ cast_callable = cast_mapping[schema_type]
+ try:
+ return cast_callable(value)
+ except UnmarshallerStrictTypeError:
+ continue
+ # @todo: remove ValueError when validation separated
+ except (OpenAPISchemaError, TypeError, ValueError):
+ continue
raise NoValidSchema(value)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/schemas/unmarshallers.py
new/openapi-core-0.11.0/openapi_core/schema/schemas/unmarshallers.py
--- old/openapi-core-0.10.0/openapi_core/schema/schemas/unmarshallers.py
1970-01-01 01:00:00.000000000 +0100
+++ new/openapi-core-0.11.0/openapi_core/schema/schemas/unmarshallers.py
2019-06-18 23:42:44.000000000 +0200
@@ -0,0 +1,107 @@
+from six import text_type, binary_type, integer_types
+
+from openapi_core.schema.schemas.enums import SchemaFormat, SchemaType
+from openapi_core.schema.schemas.exceptions import (
+ InvalidSchemaValue, InvalidCustomFormatSchemaValue,
+ OpenAPISchemaError, MultipleOneOfSchema, NoOneOfSchema,
+ InvalidSchemaProperty,
+ UnmarshallerStrictTypeError,
+)
+from openapi_core.schema.schemas.util import (
+ forcebool, format_date, format_datetime, format_byte, format_uuid,
+ format_number,
+)
+
+
+class StrictUnmarshaller(object):
+
+ STRICT_TYPES = ()
+
+ def __call__(self, value, type_format=SchemaFormat.NONE, strict=True):
+ if self.STRICT_TYPES and strict and not isinstance(
+ value, self.STRICT_TYPES):
+ raise UnmarshallerStrictTypeError(value, self.STRICT_TYPES)
+
+ return value
+
+
+class PrimitiveTypeUnmarshaller(StrictUnmarshaller):
+
+ FORMATTERS = {
+ SchemaFormat.NONE: lambda x: x,
+ }
+
+ def __init__(self, custom_formatters=None):
+ if custom_formatters is None:
+ custom_formatters = {}
+ self.custom_formatters = custom_formatters
+
+ def __call__(self, value, type_format=SchemaFormat.NONE, strict=True):
+ value = super(PrimitiveTypeUnmarshaller, self).__call__(
+ value, type_format=type_format, strict=strict)
+
+ try:
+ schema_format = SchemaFormat(type_format)
+ except ValueError:
+ formatter = self.custom_formatters.get(type_format)
+ else:
+ formatters = self.get_formatters()
+ formatter = formatters.get(schema_format)
+
+ if formatter is None:
+ raise InvalidSchemaValue(
+ "Unsupported format {type} unmarshalling "
+ "for value {value}",
+ value, type_format)
+
+ try:
+ return formatter(value)
+ except ValueError as exc:
+ raise InvalidCustomFormatSchemaValue(
+ "Failed to format value {value} to format {type}: {exception}",
+ value, type_format, exc)
+
+ def get_formatters(self):
+ return self.FORMATTERS
+
+
+class StringUnmarshaller(PrimitiveTypeUnmarshaller):
+
+ STRICT_TYPES = (text_type, binary_type)
+ FORMATTERS = {
+ SchemaFormat.NONE: text_type,
+ SchemaFormat.PASSWORD: text_type,
+ SchemaFormat.DATE: format_date,
+ SchemaFormat.DATETIME: format_datetime,
+ SchemaFormat.BINARY: binary_type,
+ SchemaFormat.UUID: format_uuid,
+ SchemaFormat.BYTE: format_byte,
+ }
+
+
+class IntegerUnmarshaller(PrimitiveTypeUnmarshaller):
+
+ STRICT_TYPES = integer_types
+ FORMATTERS = {
+ SchemaFormat.NONE: int,
+ SchemaFormat.INT32: int,
+ SchemaFormat.INT64: int,
+ }
+
+
+class NumberUnmarshaller(PrimitiveTypeUnmarshaller):
+
+ STRICT_TYPES = (float, ) + integer_types
+ FORMATTERS = {
+ SchemaFormat.NONE: format_number,
+ SchemaFormat.FLOAT: float,
+ SchemaFormat.DOUBLE: float,
+ }
+
+
+class BooleanUnmarshaller(PrimitiveTypeUnmarshaller):
+
+ STRICT_TYPES = (bool, )
+ FORMATTERS = {
+ SchemaFormat.NONE: forcebool,
+ }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/servers/exceptions.py
new/openapi-core-0.11.0/openapi_core/schema/servers/exceptions.py
--- old/openapi-core-0.10.0/openapi_core/schema/servers/exceptions.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/servers/exceptions.py
2019-06-18 23:42:44.000000000 +0200
@@ -1,13 +1,13 @@
-from openapi_core.schema.exceptions import OpenAPIMappingError
-
import attr
+from openapi_core.schema.exceptions import OpenAPIMappingError
+
class OpenAPIServerError(OpenAPIMappingError):
pass
[email protected]
[email protected](hash=True)
class InvalidServer(OpenAPIServerError):
full_url_pattern = attr.ib()
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/schema/specs/models.py
new/openapi-core-0.11.0/openapi_core/schema/specs/models.py
--- old/openapi-core-0.10.0/openapi_core/schema/specs/models.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/schema/specs/models.py 2019-06-18
23:42:44.000000000 +0200
@@ -4,6 +4,7 @@
from openapi_core.compat import partialmethod
from openapi_core.schema.operations.exceptions import InvalidOperation
+from openapi_core.schema.paths.exceptions import InvalidPath
from openapi_core.schema.servers.exceptions import InvalidServer
@@ -19,8 +20,8 @@
self.servers = servers or []
self.components = components
- def __getitem__(self, path_name):
- return self.paths[path_name]
+ def __getitem__(self, path_pattern):
+ return self.get_path(path_pattern)
@property
def default_url(self):
@@ -36,6 +37,12 @@
def get_server_url(self, index=0):
return self.servers[index].default_url
+ def get_path(self, path_pattern):
+ try:
+ return self.paths[path_pattern]
+ except KeyError:
+ raise InvalidPath(path_pattern)
+
def get_operation(self, path_pattern, http_method):
try:
return self.paths[path_pattern].operations[http_method]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/validation/request/models.py
new/openapi-core-0.11.0/openapi_core/validation/request/models.py
--- old/openapi-core-0.10.0/openapi_core/validation/request/models.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/validation/request/models.py
2019-06-18 23:42:44.000000000 +0200
@@ -16,6 +16,16 @@
def __setitem__(self, location, value):
raise NotImplementedError
+ def __add__(self, other):
+ if not isinstance(other, self.__class__):
+ raise ValueError("Invalid type")
+
+ for location in self.valid_locations:
+ if location in other:
+ self[location].update(other[location])
+
+ return self
+
@classmethod
def validate_location(cls, location):
if location not in cls.valid_locations:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/openapi_core/validation/request/validators.py
new/openapi-core-0.11.0/openapi_core/validation/request/validators.py
--- old/openapi-core-0.10.0/openapi_core/validation/request/validators.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/validation/request/validators.py
2019-06-18 23:42:44.000000000 +0200
@@ -27,17 +27,25 @@
)
try:
+ path = self.spec[operation_pattern]
+ # don't process if operation errors
+ except OpenAPIMappingError as exc:
+ return RequestValidationResult([exc, ], None, None)
+
+ path_params, path_params_errors = self._get_parameters(request, path)
+
+ try:
operation = self.spec.get_operation(
operation_pattern, request.method)
# don't process if operation errors
except OpenAPIMappingError as exc:
return RequestValidationResult([exc, ], None, None)
- params, params_errors = self._get_parameters(request, operation)
+ op_params, op_params_errors = self._get_parameters(request, operation)
body, body_errors = self._get_body(request, operation)
- errors = params_errors + body_errors
- return RequestValidationResult(errors, body, params)
+ errors = path_params_errors + op_params_errors + body_errors
+ return RequestValidationResult(errors, body, path_params + op_params)
def _get_parameters(self, request, operation):
errors = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.10.0/openapi_core/wrappers/flask.py
new/openapi-core-0.11.0/openapi_core/wrappers/flask.py
--- old/openapi-core-0.10.0/openapi_core/wrappers/flask.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/openapi_core/wrappers/flask.py 2019-06-18
23:42:44.000000000 +0200
@@ -1,9 +1,16 @@
"""OpenAPI core wrappers module"""
+import re
+
from openapi_core.wrappers.base import BaseOpenAPIRequest, BaseOpenAPIResponse
+# http://flask.pocoo.org/docs/1.0/quickstart/#variable-rules
+PATH_PARAMETER_PATTERN = r'<(?:(?:string|int|float|path|uuid):)?(\w+)>'
+
class FlaskOpenAPIRequest(BaseOpenAPIRequest):
+ path_regex = re.compile(PATH_PARAMETER_PATTERN)
+
def __init__(self, request):
self.request = request
@@ -24,7 +31,7 @@
if self.request.url_rule is None:
return self.path
- return self.request.url_rule.rule
+ return self.path_regex.sub(r'{\1}', self.request.url_rule.rule)
@property
def parameters(self):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.10.0/setup.py
new/openapi-core-0.11.0/setup.py
--- old/openapi-core-0.10.0/setup.py 2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/setup.py 2019-06-18 23:42:44.000000000 +0200
@@ -74,7 +74,6 @@
"Topic :: Software Development :: Libraries :: Python Modules",
"Operating System :: OS Independent",
'Programming Language :: Python :: 2.7',
- 'Programming Language :: Python :: 3.4',
'Programming Language :: Python :: 3.5',
'Programming Language :: Python :: 3.6',
'Programming Language :: Python :: 3.7',
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/integration/data/v3.0/flask_wrapper.yaml
new/openapi-core-0.11.0/tests/integration/data/v3.0/flask_wrapper.yaml
--- old/openapi-core-0.10.0/tests/integration/data/v3.0/flask_wrapper.yaml
1970-01-01 01:00:00.000000000 +0100
+++ new/openapi-core-0.11.0/tests/integration/data/v3.0/flask_wrapper.yaml
2019-06-18 23:42:44.000000000 +0200
@@ -0,0 +1,19 @@
+openapi: "3.0.0"
+info:
+ title: Basic OpenAPI specification used with
test_wrappers.TestFlaskOpenAPIIValidation
+ version: "0.1"
+servers:
+ - url: 'http://localhost'
+paths:
+ '/browse/{id}/':
+ parameters:
+ - name: id
+ in: path
+ required: true
+ description: the ID of the resource to retrieve
+ schema:
+ type: integer
+ get:
+ responses:
+ default:
+ description: Return the resource.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/integration/test_minimal.py
new/openapi-core-0.11.0/tests/integration/test_minimal.py
--- old/openapi-core-0.10.0/tests/integration/test_minimal.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/integration/test_minimal.py 2019-06-18
23:42:44.000000000 +0200
@@ -1,6 +1,7 @@
import pytest
from openapi_core.schema.operations.exceptions import InvalidOperation
+from openapi_core.schema.paths.exceptions import InvalidPath
from openapi_core.shortcuts import create_spec
from openapi_core.validation.request.validators import RequestValidator
from openapi_core.wrappers.mock import MockRequest
@@ -39,7 +40,7 @@
spec_dict = factory.spec_from_file(spec_path)
spec = create_spec(spec_dict)
validator = RequestValidator(spec)
- request = MockRequest(server, "get", "/nonexistent")
+ request = MockRequest(server, "post", "/status")
result = validator.validate(request)
@@ -47,3 +48,18 @@
assert isinstance(result.errors[0], InvalidOperation)
assert result.body is None
assert result.parameters == {}
+
+ @pytest.mark.parametrize("server", servers)
+ @pytest.mark.parametrize("spec_path", spec_paths)
+ def test_invalid_path(self, factory, server, spec_path):
+ spec_dict = factory.spec_from_file(spec_path)
+ spec = create_spec(spec_dict)
+ validator = RequestValidator(spec)
+ request = MockRequest(server, "get", "/nonexistent")
+
+ result = validator.validate(request)
+
+ assert len(result.errors) == 1
+ assert isinstance(result.errors[0], InvalidPath)
+ assert result.body is None
+ assert result.parameters == {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/integration/test_petstore.py
new/openapi-core-0.11.0/tests/integration/test_petstore.py
--- old/openapi-core-0.10.0/tests/integration/test_petstore.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/integration/test_petstore.py 2019-06-18
23:42:44.000000000 +0200
@@ -1,5 +1,6 @@
import json
import pytest
+from datetime import datetime
from base64 import b64encode
from uuid import UUID
from six import iteritems, text_type
@@ -19,7 +20,7 @@
from openapi_core.schema.responses.models import Response
from openapi_core.schema.schemas.enums import SchemaType
from openapi_core.schema.schemas.exceptions import (
- NoValidSchema, InvalidSchemaProperty, InvalidSchemaValue,
+ InvalidSchemaProperty, InvalidSchemaValue,
)
from openapi_core.schema.schemas.models import Schema
from openapi_core.schema.servers.exceptions import InvalidServer
@@ -1213,7 +1214,7 @@
assert parameters == {}
assert isinstance(body, BaseModel)
- assert body.created == created
+ assert body.created == datetime(2016, 4, 16, 16, 6, 5)
assert body.name == pet_name
code = 400
@@ -1257,7 +1258,7 @@
)
parameters = request.get_parameters(spec)
- with pytest.raises(NoValidSchema):
+ with pytest.raises(InvalidMediaTypeValue):
request.get_body(spec)
assert parameters == {}
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/integration/test_validators.py
new/openapi-core-0.11.0/tests/integration/test_validators.py
--- old/openapi-core-0.10.0/tests/integration/test_validators.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/integration/test_validators.py
2019-06-18 23:42:44.000000000 +0200
@@ -9,6 +9,8 @@
from openapi_core.extensions.models.models import BaseModel
from openapi_core.schema.operations.exceptions import InvalidOperation
from openapi_core.schema.parameters.exceptions import MissingRequiredParameter
+from openapi_core.schema.parameters.exceptions import InvalidParameterValue
+from openapi_core.schema.paths.exceptions import InvalidPath
from openapi_core.schema.request_bodies.exceptions import MissingRequestBody
from openapi_core.schema.responses.exceptions import (
MissingResponseContent, InvalidResponse,
@@ -54,12 +56,22 @@
assert result.body is None
assert result.parameters == {}
- def test_invalid_operation(self, validator):
+ def test_invalid_path(self, validator):
request = MockRequest(self.host_url, 'get', '/v1')
result = validator.validate(request)
assert len(result.errors) == 1
+ assert type(result.errors[0]) == InvalidPath
+ assert result.body is None
+ assert result.parameters == {}
+
+ def test_invalid_operation(self, validator):
+ request = MockRequest(self.host_url, 'patch', '/v1/pets')
+
+ result = validator.validate(request)
+
+ assert len(result.errors) == 1
assert type(result.errors[0]) == InvalidOperation
assert result.body is None
assert result.parameters == {}
@@ -220,6 +232,80 @@
}
+class TestPathItemParamsValidator(object):
+
+ @pytest.fixture
+ def spec_dict(self, factory):
+ return {
+ "openapi": "3.0.0",
+ "info": {
+ "title": "Test path item parameter validation",
+ "version": "0.1",
+ },
+ "paths": {
+ "/resource": {
+ "parameters": [
+ {
+ "name": "resId",
+ "in": "query",
+ "required": True,
+ "schema": {
+ "type": "integer",
+ },
+ },
+ ],
+ "get": {
+ "responses": {
+ "default": {
+ "description": "Return the resource."
+ }
+ }
+ }
+ }
+ }
+ }
+
+ @pytest.fixture
+ def spec(self, spec_dict):
+ return create_spec(spec_dict)
+
+ @pytest.fixture
+ def validator(self, spec):
+ return RequestValidator(spec)
+
+ def test_request_missing_param(self, validator):
+ request = MockRequest('http://example.com', 'get', '/resource')
+ result = validator.validate(request)
+
+ assert len(result.errors) == 1
+ assert type(result.errors[0]) == MissingRequiredParameter
+ assert result.body is None
+ assert result.parameters == {}
+
+ def test_request_invalid_param(self, validator):
+ request = MockRequest(
+ 'http://example.com', 'get', '/resource',
+ args={'resId': 'invalid'},
+ )
+ result = validator.validate(request)
+
+ assert len(result.errors) == 1
+ assert type(result.errors[0]) == InvalidParameterValue
+ assert result.body is None
+ assert result.parameters == {}
+
+ def test_request_valid_param(self, validator):
+ request = MockRequest(
+ 'http://example.com', 'get', '/resource',
+ args={'resId': '10'},
+ )
+ result = validator.validate(request)
+
+ assert len(result.errors) == 0
+ assert result.body is None
+ assert result.parameters == {'query': {'resId': 10}}
+
+
class TestResponseValidator(object):
host_url = 'http://petstore.swagger.io'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/integration/test_wrappers.py
new/openapi-core-0.11.0/tests/integration/test_wrappers.py
--- old/openapi-core-0.10.0/tests/integration/test_wrappers.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/integration/test_wrappers.py 2019-06-18
23:42:44.000000000 +0200
@@ -1,54 +1,61 @@
-import pytest
-
from flask.wrappers import Request, Response
from werkzeug.datastructures import EnvironHeaders, ImmutableMultiDict
from werkzeug.routing import Map, Rule, Subdomain
from werkzeug.test import create_environ
-from openapi_core.wrappers.flask import (
- FlaskOpenAPIRequest, FlaskOpenAPIResponse,
-)
-
+import pytest
+from openapi_core.shortcuts import create_spec
+from openapi_core.validation.response.validators import ResponseValidator
+from openapi_core.validation.request.validators import RequestValidator
+from openapi_core.wrappers.flask import (FlaskOpenAPIRequest,
+ FlaskOpenAPIResponse)
+
+
[email protected]
+def environ_factory():
+ return create_environ
+
+
[email protected]
+def map():
+ return Map([
+ # Static URLs
+ Rule('/', endpoint='static/index'),
+ Rule('/about', endpoint='static/about'),
+ Rule('/help', endpoint='static/help'),
+ # Knowledge Base
+ Subdomain('kb', [
+ Rule('/', endpoint='kb/index'),
+ Rule('/browse/', endpoint='kb/browse'),
+ Rule('/browse/<int:id>/', endpoint='kb/browse'),
+ Rule('/browse/<int:id>/<int:page>', endpoint='kb/browse')
+ ])
+ ], default_subdomain='www')
-class TestFlaskOpenAPIRequest(object):
[email protected]
+def request_factory(map, environ_factory):
server_name = 'localhost'
- @pytest.fixture
- def environ_factory(self):
- return create_environ
-
- @pytest.fixture
- def map(self):
- return Map([
- # Static URLs
- Rule('/', endpoint='static/index'),
- Rule('/about', endpoint='static/about'),
- Rule('/help', endpoint='static/help'),
- # Knowledge Base
- Subdomain('kb', [
- Rule('/', endpoint='kb/index'),
- Rule('/browse/', endpoint='kb/browse'),
- Rule('/browse/<int:id>/', endpoint='kb/browse'),
- Rule('/browse/<int:id>/<int:page>', endpoint='kb/browse')
- ])
- ], default_subdomain='www')
+ def create_request(method, path, subdomain=None, query_string=None):
+ environ = environ_factory(query_string=query_string)
+ req = Request(environ)
+ urls = map.bind_to_environ(
+ environ, server_name=server_name, subdomain=subdomain)
+ req.url_rule, req.view_args = urls.match(
+ path, method, return_rule=True)
+ return req
+ return create_request
+
+
[email protected]
+def response_factory():
+ def create_response(data, status_code=200):
+ return Response(data, status=status_code)
+ return create_response
- @pytest.fixture
- def request_factory(self, map, environ_factory):
- def create_request(method, path, subdomain=None, query_string=None):
- environ = environ_factory(query_string=query_string)
- req = Request(environ)
- urls = map.bind_to_environ(
- environ, server_name=self.server_name, subdomain=subdomain)
- req.url_rule, req.view_args = urls.match(
- path, method, return_rule=True)
- return req
- return create_request
- @pytest.fixture
- def openapi_request(self, request):
- return FlaskOpenAPIRequest(request)
+class TestFlaskOpenAPIRequest(object):
def test_simple(self, request_factory, request):
request = request_factory('GET', '/', subdomain='www')
@@ -115,19 +122,13 @@
assert openapi_request.host_url == request.host_url
assert openapi_request.path == request.path
assert openapi_request.method == request.method.lower()
- assert openapi_request.path_pattern == request.url_rule.rule
+ assert openapi_request.path_pattern == '/browse/{id}/'
assert openapi_request.body == request.data
assert openapi_request.mimetype == request.mimetype
class TestFlaskOpenAPIResponse(object):
- @pytest.fixture
- def response_factory(self):
- def create_response(data, status_code=200):
- return Response(data, status=status_code)
- return create_response
-
def test_invalid_server(self, response_factory):
response = response_factory('Not Found', status_code=404)
@@ -137,3 +138,30 @@
assert openapi_response.data == response.data
assert openapi_response.status_code == response._status_code
assert openapi_response.mimetype == response.mimetype
+
+
+class TestFlaskOpenAPIValidation(object):
+
+ @pytest.fixture
+ def flask_spec(self, factory):
+ specfile = 'data/v3.0/flask_wrapper.yaml'
+ return create_spec(factory.spec_from_file(specfile))
+
+ def test_response_validator_path_pattern(self,
+ flask_spec,
+ request_factory,
+ response_factory):
+ validator = ResponseValidator(flask_spec)
+ request = request_factory('GET', '/browse/12/', subdomain='kb')
+ openapi_request = FlaskOpenAPIRequest(request)
+ response = response_factory('Some item', status_code=200)
+ openapi_response = FlaskOpenAPIResponse(response)
+ result = validator.validate(openapi_request, openapi_response)
+ assert not result.errors
+
+ def test_request_validator_path_pattern(self, flask_spec, request_factory):
+ validator = RequestValidator(flask_spec)
+ request = request_factory('GET', '/browse/12/', subdomain='kb')
+ openapi_request = FlaskOpenAPIRequest(request)
+ result = validator.validate(openapi_request)
+ assert not result.errors
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.10.0/tests/unit/schema/test_links.py
new/openapi-core-0.11.0/tests/unit/schema/test_links.py
--- old/openapi-core-0.10.0/tests/unit/schema/test_links.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/unit/schema/test_links.py 2019-06-18
23:42:44.000000000 +0200
@@ -40,5 +40,5 @@
@pytest.mark.parametrize("request_body", request_body_list)
def test_iteritems(self, link_factory, request_body, server):
link = link_factory(request_body, server)
- for par_name in link.parameters.keys():
+ for par_name in link.parameters:
assert link[par_name] == link.parameters[par_name]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/unit/schema/test_operations.py
new/openapi-core-0.11.0/tests/unit/schema/test_operations.py
--- old/openapi-core-0.10.0/tests/unit/schema/test_operations.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/unit/schema/test_operations.py
2019-06-18 23:42:44.000000000 +0200
@@ -15,7 +15,7 @@
return Operation('get', '/path', {}, parameters=parameters)
def test_iteritems(self, operation):
- for name in operation.parameters.keys():
+ for name in operation.parameters:
assert operation[name] == operation.parameters[name]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.10.0/tests/unit/schema/test_paths.py
new/openapi-core-0.11.0/tests/unit/schema/test_paths.py
--- old/openapi-core-0.10.0/tests/unit/schema/test_paths.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/unit/schema/test_paths.py 2019-06-18
23:42:44.000000000 +0200
@@ -16,6 +16,6 @@
@property
def test_iteritems(self, path):
- for http_method in path.operations.keys():
+ for http_method in path.operations:
assert path[http_method] ==\
path.operations[http_method]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/unit/schema/test_request_bodies.py
new/openapi-core-0.11.0/tests/unit/schema/test_request_bodies.py
--- old/openapi-core-0.10.0/tests/unit/schema/test_request_bodies.py
2019-05-21 14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/unit/schema/test_request_bodies.py
2019-06-18 23:42:44.000000000 +0200
@@ -16,6 +16,6 @@
@property
def test_iteritems(self, request_body):
- for mimetype in request_body.content.keys():
+ for mimetype in request_body.content:
assert request_body[mimetype] ==\
request_body.content[mimetype]
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.10.0/tests/unit/schema/test_schemas.py
new/openapi-core-0.11.0/tests/unit/schema/test_schemas.py
--- old/openapi-core-0.10.0/tests/unit/schema/test_schemas.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/unit/schema/test_schemas.py 2019-06-18
23:42:44.000000000 +0200
@@ -27,7 +27,7 @@
@property
def test_valid(self, schema):
- for name in schema.properties.keys():
+ for name in schema.properties:
assert schema[name] == schema.properties[name]
@@ -300,6 +300,33 @@
assert result == 1.2
+ def test_schema_any_one_of(self):
+ schema = Schema(one_of=[
+ Schema('string'),
+ Schema('array', items=Schema('string')),
+ ])
+ assert schema.unmarshal(['hello']) == ['hello']
+
+ def test_schema_any_one_of_mutiple(self):
+ schema = Schema(one_of=[
+ Schema('array', items=Schema('string')),
+ Schema('array', items=Schema('number')),
+ ])
+ with pytest.raises(MultipleOneOfSchema):
+ schema.unmarshal([])
+
+ def test_schema_any_one_of_no_valid(self):
+ schema = Schema(one_of=[
+ Schema('array', items=Schema('string')),
+ Schema('array', items=Schema('number')),
+ ])
+ with pytest.raises(NoOneOfSchema):
+ schema.unmarshal({})
+
+ def test_schema_any(self):
+ schema = Schema()
+ assert schema.unmarshal('string') == 'string'
+
class TestSchemaValidate(object):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.10.0/tests/unit/schema/test_specs.py
new/openapi-core-0.11.0/tests/unit/schema/test_specs.py
--- old/openapi-core-0.10.0/tests/unit/schema/test_specs.py 2019-05-21
14:21:42.000000000 +0200
+++ new/openapi-core-0.11.0/tests/unit/schema/test_specs.py 2019-06-18
23:42:44.000000000 +0200
@@ -32,7 +32,7 @@
return Spec(servers, paths)
def test_iteritems(self, spec):
- for path_name in spec.paths.keys():
+ for path_name in spec.paths:
assert spec[path_name] ==\
spec.paths[path_name]