Hello community,
here is the log from the commit of package python-openapi-core for
openSUSE:Factory checked in at 2019-09-13 14:57:54
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-openapi-core (Old)
and /work/SRC/openSUSE:Factory/.python-openapi-core.new.7948 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-openapi-core"
Fri Sep 13 14:57:54 2019 rev:4 rq:730065 version:0.11.1
Changes:
--------
--- /work/SRC/openSUSE:Factory/python-openapi-core/python-openapi-core.changes
2019-07-23 22:41:01.306899418 +0200
+++
/work/SRC/openSUSE:Factory/.python-openapi-core.new.7948/python-openapi-core.changes
2019-09-13 14:57:58.689276371 +0200
@@ -1,0 +2,7 @@
+Wed Sep 11 08:40:59 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 0.11.1:
+ * Path item parameter override (#145)
+ * Separate cast and unmarshal (#156)
+
+-------------------------------------------------------------------
Old:
----
0.11.0.tar.gz
New:
----
0.11.1.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-openapi-core.spec ++++++
--- /var/tmp/diff_new_pack.TZEABK/_old 2019-09-13 14:58:00.061276429 +0200
+++ /var/tmp/diff_new_pack.TZEABK/_new 2019-09-13 14:58:00.061276429 +0200
@@ -18,7 +18,7 @@
%{?!python_module:%define python_module() python-%{**} python3-%{**}}
Name: python-openapi-core
-Version: 0.11.0
+Version: 0.11.1
Release: 0
Summary: Adds client-side and server-side support for the oas3
License: BSD-3-Clause
++++++ 0.11.0.tar.gz -> 0.11.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/openapi-core-0.11.0/openapi_core/__init__.py
new/openapi-core-0.11.1/openapi_core/__init__.py
--- old/openapi-core-0.11.0/openapi_core/__init__.py 2019-06-18
23:42:44.000000000 +0200
+++ new/openapi-core-0.11.1/openapi_core/__init__.py 2019-09-07
14:03:58.000000000 +0200
@@ -6,7 +6,7 @@
__author__ = 'Artur Maciag'
__email__ = '[email protected]'
-__version__ = '0.11.0'
+__version__ = '0.11.1'
__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.11.0/openapi_core/schema/parameters/models.py
new/openapi-core-0.11.1/openapi_core/schema/parameters/models.py
--- old/openapi-core-0.11.0/openapi_core/schema/parameters/models.py
2019-06-18 23:42:44.000000000 +0200
+++ new/openapi-core-0.11.1/openapi_core/schema/parameters/models.py
2019-09-07 14:03:58.000000000 +0200
@@ -109,10 +109,15 @@
raise InvalidParameterValue(self.name, exc)
try:
+ casted = self.schema.cast(deserialized)
+ except OpenAPISchemaError as exc:
+ raise InvalidParameterValue(self.name, exc)
+
+ try:
unmarshalled = self.schema.unmarshal(
- deserialized,
+ casted,
custom_formatters=custom_formatters,
- strict=False,
+ strict=True,
)
except OpenAPISchemaError as exc:
raise InvalidParameterValue(self.name, exc)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.11.0/openapi_core/schema/schemas/models.py
new/openapi-core-0.11.1/openapi_core/schema/schemas/models.py
--- old/openapi-core-0.11.0/openapi_core/schema/schemas/models.py
2019-06-18 23:42:44.000000000 +0200
+++ new/openapi-core-0.11.1/openapi_core/schema/schemas/models.py
2019-09-07 14:03:58.000000000 +0200
@@ -38,7 +38,13 @@
class Schema(object):
"""Represents an OpenAPI Schema."""
- DEFAULT_CAST_CALLABLE_GETTER = {
+ TYPE_CAST_CALLABLE_GETTER = {
+ SchemaType.INTEGER: int,
+ SchemaType.NUMBER: float,
+ SchemaType.BOOLEAN: forcebool,
+ }
+
+ DEFAULT_UNMARSHAL_CALLABLE_GETTER = {
}
STRING_FORMAT_CALLABLE_GETTER = {
@@ -155,7 +161,39 @@
return set(required)
- def get_cast_mapping(self, custom_formatters=None, strict=True):
+ def are_additional_properties_allowed(self, one_of_schema=None):
+ return (
+ (self.additional_properties is not False) and
+ (one_of_schema is None or
+ one_of_schema.additional_properties is not False)
+ )
+
+ def get_cast_mapping(self):
+ mapping = self.TYPE_CAST_CALLABLE_GETTER.copy()
+ mapping.update({
+ SchemaType.ARRAY: self._cast_collection,
+ })
+
+ return defaultdict(lambda: lambda x: x, mapping)
+
+ def cast(self, value):
+ """Cast value from string to schema type"""
+ if value is None:
+ return value
+
+ cast_mapping = self.get_cast_mapping()
+
+ cast_callable = cast_mapping[self.type]
+ try:
+ return cast_callable(value)
+ except ValueError:
+ raise InvalidSchemaValue(
+ "Failed to cast value {value} to type {type}", value,
self.type)
+
+ def _cast_collection(self, value):
+ return list(map(self.items.cast, value))
+
+ def get_unmarshal_mapping(self, custom_formatters=None, strict=True):
primitive_unmarshallers = self.get_primitive_unmarshallers(
custom_formatters=custom_formatters)
@@ -166,7 +204,7 @@
pass_defaults = lambda f: functools.partial(
f, custom_formatters=custom_formatters, strict=strict)
- mapping = self.DEFAULT_CAST_CALLABLE_GETTER.copy()
+ mapping = self.DEFAULT_UNMARSHAL_CALLABLE_GETTER.copy()
mapping.update(primitive_unmarshallers_partial)
mapping.update({
SchemaType.ANY: pass_defaults(self._unmarshal_any),
@@ -176,15 +214,10 @@
return defaultdict(lambda: lambda x: x, mapping)
- def are_additional_properties_allowed(self, one_of_schema=None):
- return (
- (self.additional_properties is not False) and
- (one_of_schema is None or
- one_of_schema.additional_properties is not False)
- )
-
- def cast(self, value, custom_formatters=None, strict=True):
- """Cast value to schema type"""
+ def unmarshal(self, value, custom_formatters=None, strict=True):
+ """Unmarshal parameter from the value."""
+ if self.deprecated:
+ warnings.warn("The schema is deprecated", DeprecationWarning)
if value is None:
if not self.nullable:
raise InvalidSchemaValue("Null value for non-nullable schema",
value, self.type)
@@ -194,15 +227,15 @@
raise InvalidSchemaValue(
"Value {value} not in enum choices: {type}", value, self.enum)
- cast_mapping = self.get_cast_mapping(
+ unmarshal_mapping = self.get_unmarshal_mapping(
custom_formatters=custom_formatters, strict=strict)
if self.type is not SchemaType.STRING and value == '':
return None
- cast_callable = cast_mapping[self.type]
+ unmarshal_callable = unmarshal_mapping[self.type]
try:
- return cast_callable(value)
+ unmarshalled = unmarshal_callable(value)
except UnmarshallerStrictTypeError:
raise InvalidSchemaValue(
"Value {value} is not of type {type}", value, self.type)
@@ -210,17 +243,10 @@
raise InvalidSchemaValue(
"Failed to cast value {value} to type {type}", value,
self.type)
- def unmarshal(self, value, custom_formatters=None, strict=True):
- """Unmarshal parameter from the value."""
- if self.deprecated:
- warnings.warn("The schema is deprecated", DeprecationWarning)
-
- casted = self.cast(value, custom_formatters=custom_formatters,
strict=strict)
-
- if casted is None and not self.required:
+ if unmarshalled is None and not self.required:
return None
- return casted
+ return unmarshalled
def get_primitive_unmarshallers(self, **options):
from openapi_core.schema.schemas.unmarshallers import (
@@ -247,18 +273,18 @@
SchemaType.OBJECT, SchemaType.ARRAY, SchemaType.BOOLEAN,
SchemaType.INTEGER, SchemaType.NUMBER, SchemaType.STRING,
]
- cast_mapping = self.get_cast_mapping()
+ unmarshal_mapping = self.get_unmarshal_mapping()
if self.one_of:
result = None
for subschema in self.one_of:
try:
- casted = subschema.cast(value, custom_formatters)
+ unmarshalled = subschema.unmarshal(value,
custom_formatters)
except (OpenAPISchemaError, TypeError, ValueError):
continue
else:
if result is not None:
raise MultipleOneOfSchema(self.type)
- result = casted
+ result = unmarshalled
if result is None:
raise NoOneOfSchema(self.type)
@@ -266,9 +292,9 @@
return result
else:
for schema_type in types_resolve_order:
- cast_callable = cast_mapping[schema_type]
+ unmarshal_callable = unmarshal_mapping[schema_type]
try:
- return cast_callable(value)
+ return unmarshal_callable(value)
except UnmarshallerStrictTypeError:
continue
# @todo: remove ValueError when validation separated
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.11.0/openapi_core/validation/request/validators.py
new/openapi-core-0.11.1/openapi_core/validation/request/validators.py
--- old/openapi-core-0.11.0/openapi_core/validation/request/validators.py
2019-06-18 23:42:44.000000000 +0200
+++ new/openapi-core-0.11.1/openapi_core/validation/request/validators.py
2019-09-07 14:03:58.000000000 +0200
@@ -1,4 +1,5 @@
"""OpenAPI core validation request validators module"""
+from itertools import chain
from six import iteritems
from openapi_core.schema.exceptions import OpenAPIMappingError
@@ -28,30 +29,34 @@
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)
- op_params, op_params_errors = self._get_parameters(request, operation)
+ params, params_errors = self._get_parameters(
+ request, chain(
+ iteritems(operation.parameters),
+ iteritems(path.parameters)
+ )
+ )
+
body, body_errors = self._get_body(request, operation)
- errors = path_params_errors + op_params_errors + body_errors
- return RequestValidationResult(errors, body, path_params + op_params)
+ errors = params_errors + body_errors
+ return RequestValidationResult(errors, body, params)
- def _get_parameters(self, request, operation):
+ def _get_parameters(self, request, params):
errors = []
-
+ seen = set()
parameters = RequestParameters()
- for param_name, param in iteritems(operation.parameters):
+ for param_name, param in params:
+ if (param_name, param.location.value) in seen:
+ # skip parameter already seen
+ # e.g. overriden path item paremeter on operation
+ continue
+ seen.add((param_name, param.location.value))
try:
raw_value = param.get_value(request)
except MissingParameter:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/openapi-core-0.11.0/tests/integration/test_validators.py
new/openapi-core-0.11.1/tests/integration/test_validators.py
--- old/openapi-core-0.11.0/tests/integration/test_validators.py
2019-06-18 23:42:44.000000000 +0200
+++ new/openapi-core-0.11.1/tests/integration/test_validators.py
2019-09-07 14:03:58.000000000 +0200
@@ -235,7 +235,7 @@
class TestPathItemParamsValidator(object):
@pytest.fixture
- def spec_dict(self, factory):
+ def spec_dict(self):
return {
"openapi": "3.0.0",
"info": {
@@ -305,6 +305,50 @@
assert result.body is None
assert result.parameters == {'query': {'resId': 10}}
+ def test_request_override_param(self, spec_dict):
+ # override path parameter on operation
+ spec_dict["paths"]["/resource"]["get"]["parameters"] = [
+ {
+ # full valid parameter object required
+ "name": "resId",
+ "in": "query",
+ "required": False,
+ "schema": {
+ "type": "integer",
+ },
+ }
+ ]
+ validator = RequestValidator(create_spec(spec_dict))
+ request = MockRequest('http://example.com', 'get', '/resource')
+ result = validator.validate(request)
+
+ assert len(result.errors) == 0
+ assert result.body is None
+ assert result.parameters == {}
+
+ def test_request_override_param_uniqueness(self, spec_dict):
+ # add parameter on operation with same name as on path but
+ # different location
+ spec_dict["paths"]["/resource"]["get"]["parameters"] = [
+ {
+ # full valid parameter object required
+ "name": "resId",
+ "in": "header",
+ "required": False,
+ "schema": {
+ "type": "integer",
+ },
+ }
+ ]
+ validator = RequestValidator(create_spec(spec_dict))
+ 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 == {}
+
class TestResponseValidator(object):