Skip to content
This repository was archived by the owner on Dec 25, 2024. It is now read-only.

v2 consolidates validation #98

Merged
merged 49 commits into from
Dec 3, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
49 commits
Select commit Hold shift + click to select a range
1ffbe07
Validators made for all but 7 keywords
spacether Dec 2, 2022
0af5a91
Adds validate_required
spacether Dec 2, 2022
eb3c398
Fixes validator values and comparisons
spacether Dec 2, 2022
a795936
Adds validate_items
spacether Dec 2, 2022
876ad6d
Adds validate_properties
spacether Dec 2, 2022
4ec50bf
Adds validate_additional_properties
spacether Dec 2, 2022
a679889
Updates schemas template file
spacether Dec 2, 2022
ba663f4
Adds JsonSchemaValidator as a base class to all MetaOapg
spacether Dec 2, 2022
7d7195d
More typo and bugfixes
spacether Dec 2, 2022
f2d39d7
Embeds oneOf anyOf and allOf classes in subclesses like properties does
spacether Dec 2, 2022
00b8322
Sample regenerated with composition class wrapper fix
spacether Dec 2, 2022
beabaa0
Fixes some validate tests
spacether Dec 2, 2022
cd8bd5f
Adds validate_one_of
spacether Dec 2, 2022
73f17fa
Adds anyOf validation
spacether Dec 2, 2022
126842f
Adds validate_all_of
spacether Dec 2, 2022
535453e
Fixes validate_additional_properties
spacether Dec 2, 2022
93ca203
Speeds up Configuration property access
spacether Dec 2, 2022
e67a17f
Removes from_server info from ValidationMetadata
spacether Dec 2, 2022
1be8fb9
Ensures that configuration is present in ValidationMetadata
spacether Dec 2, 2022
898bf9a
Fixes disabled_json_schema_keywords, updates configuration
spacether Dec 2, 2022
000dc12
Fixes configuration test
spacether Dec 2, 2022
49a6b4f
Fixes tests in test_any_type_schema
spacether Dec 2, 2022
c2a2b69
Adds validate_not
spacether Dec 2, 2022
2a54947
Fixes BinarySchema one_of definition
spacether Dec 2, 2022
e0bf1ce
Fixes int checking with no format
spacether Dec 2, 2022
7312f2a
Adds path_to_type dict
spacether Dec 2, 2022
b91c3ed
Mfgs classes for unvalidated paths
spacether Dec 2, 2022
1bfdf36
Fixes generation of bool and none classes on unvalidated paths
spacether Dec 2, 2022
4788545
Fixes more tests
spacether Dec 2, 2022
befc3bf
Fixes test_dict_validate
spacether Dec 2, 2022
bfd277d
Removes unest type checking
spacether Dec 2, 2022
4a839f0
Adds validate_discriminator
spacether Dec 3, 2022
2456062
Sample regen
spacether Dec 3, 2022
4d547f0
Fixes 3 tests
spacether Dec 3, 2022
e94d0e7
Adds self handling for oneOf/anyOf/allOf validation, fixes last test
spacether Dec 3, 2022
7fa35ee
Samples regenerated
spacether Dec 3, 2022
7515add
Fixes integer validation
spacether Dec 3, 2022
59fa4ab
Removes Discriminable
spacether Dec 3, 2022
0c00553
Removes ComposedBase + BinaryBase
spacether Dec 3, 2022
977e855
Removes Int32Base/Int64Base/Float32Base/Float64Base
spacether Dec 3, 2022
3b24769
Adds int format for integers
spacether Dec 3, 2022
a4ccb8c
Removes EnumBase
spacether Dec 3, 2022
d1f2b0e
Replaces ComposedSchema with AnyTypeSchema, fixes two tests
spacether Dec 3, 2022
21b400b
Fixes two tests, handles AnyType + InheritorOfAnyType + XSchema use case
spacether Dec 3, 2022
8513adf
Adds template changes that allow nonCompliantUseDiscriminatorIfCompos…
spacether Dec 3, 2022
a96cd09
Sample regen
spacether Dec 3, 2022
1ba071e
Fixes test for nonCompliantUseDiscriminatorIfCompositionFails feature…
spacether Dec 3, 2022
932527b
Samples regenerated
spacether Dec 3, 2022
41081cb
Samples regenerate with UnsetAnyTypeSchema exclusion in cast_to_allow…
spacether Dec 3, 2022
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
Original file line number Diff line number Diff line change
Expand Up @@ -840,7 +840,12 @@ public CodegenProperty fromProperty(String name, Schema p, boolean required, boo
// fix needed for values with /n /t etc in them
String fixedName = handleSpecialCharacters(name);
CodegenProperty cp = super.fromProperty(fixedName, p, required, schemaIsFromAdditionalProperties, sourceJsonPath);

if (cp.isInteger && cp.getFormat() == null) {
// this generator treats integers as type number
// this is done so type int + float has the same base class (decimal.Decimal)
// so integer validation info must be set using formatting
cp.setFormat("int");
}
if (cp.isAnyType && cp.isNullable) {
cp.isNullable = false;
}
Expand Down Expand Up @@ -1275,6 +1280,12 @@ public CodegenModel fromModel(String name, Schema sc) {
String pattern = (String) cm.vendorExtensions.get("x-regex");
cm.setPattern(pattern);
}
if (cm.isInteger && cm.getFormat() == null) {
// this generator treats integers as type number
// this is done so type int + float has the same base class (decimal.Decimal)
// so integer validation info must be set using formatting
cm.setFormat("int");
}
if (cm.isNullable) {
cm.setIsNull(true);
cm.isNullable = false;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,46 @@
{{>partial_header}}

import copy
from http import client as http_client
import logging
{{#unless asyncio}}
import multiprocessing
{{/unless}}
import sys
import typing

import urllib3

from http import client as http_client
from {{packageName}}.exceptions import ApiValueError


JSON_SCHEMA_VALIDATION_KEYWORDS = {
'multipleOf', 'maximum', 'exclusiveMaximum',
'minimum', 'exclusiveMinimum', 'maxLength',
'minLength', 'pattern', 'maxItems', 'minItems',
'uniqueItems', 'maxProperties', 'minProperties',
JSON_SCHEMA_KEYWORD_TO_PYTHON_KEYWORD = {
'types': 'types',
'type': 'types',
'enum': 'enum_value_to_name',
'uniqueItems': 'unique_items',
'minItems': 'min_items',
'maxItems': 'max_items',
'minProperties': 'min_properties',
'maxProperties': 'max_properties',
'minLength': 'min_length',
'maxLength': 'max_length',
'minimum': 'inclusive_minimum',
'exclusiveMinimum': 'exclusive_minimum',
'maximum': 'inclusive_maximum',
'exclusiveMaximum': 'exclusive_maximum',
'multipleOf': 'multiple_of',
'pattern': 'regex',
'format': 'format',
'required': 'required',
'items': 'items',
'properties': 'properties',
'additionalProperties': 'additional_properties',
'oneOf': 'one_of',
'anyOf': 'any_of',
'allOf': 'all_of',
'not': 'not_schema',
'discriminator': 'discriminator'
}

class Configuration(object):
Expand All @@ -37,7 +61,7 @@ class Configuration(object):
The dict value is an API key prefix when generating the auth data.
:param username: Username for HTTP basic authentication
:param password: Password for HTTP basic authentication
:param disabled_client_side_validations (string): Comma-separated list of
:param disabled_json_schema_keywords (set): Set of
JSON schema validation keywords to disable JSON schema structural validation
rules. The following keywords may be specified: multipleOf, maximum,
exclusiveMaximum, minimum, exclusiveMinimum, maxLength, minLength, pattern,
Expand All @@ -46,7 +70,7 @@ class Configuration(object):
and data received from the server, independent of any validation performed by
the server side. If the input data does not satisfy the JSON schema validation
rules specified in the OpenAPI document, an exception is raised.
If disabled_client_side_validations is set, structural validation is
If disabled_json_schema_keywords is set, structural validation is
disabled. This can be useful to troubleshoot data validation problem, such as
when the OpenAPI document validation rules do not match the actual API data
received by the server.
Expand Down Expand Up @@ -162,7 +186,7 @@ conf = {{{packageName}}}.Configuration(
username=None,
password=None,
{{/if}}
disabled_client_side_validations="",
disabled_json_schema_keywords=frozenset(),
{{#if hasHttpSignatureMethods}}
signing_info=None,
{{/if}}
Expand Down Expand Up @@ -214,10 +238,8 @@ conf = {{{packageName}}}.Configuration(
"""Password for HTTP basic authentication
"""
{{/if}}
self.disabled_client_side_validations = disabled_client_side_validations
self.disabled_json_schema_keywords = disabled_json_schema_keywords
{{#if hasHttpSignatureMethods}}
if signing_info is not None:
signing_info.host = host
self.signing_info = signing_info
"""The HTTP signing configuration
"""
Expand Down Expand Up @@ -314,20 +336,39 @@ conf = {{{packageName}}}.Configuration(
result.debug = self.debug
return result

def __setattr__(self, name, value):
object.__setattr__(self, name, value)
if name == 'disabled_client_side_validations':
s = set(filter(None, value.split(',')))
for v in s:
if v not in JSON_SCHEMA_VALIDATION_KEYWORDS:
raise ApiValueError(
"Invalid keyword: '{0}''".format(v))
self._disabled_client_side_validations = s
@property
def disabled_json_schema_keywords(self) -> typing.Set[str]:
return self.__disabled_json_schema_keywords

@property
def disabled_json_schema_python_keywords(self) -> typing.Set[str]:
return self.__disabled_json_schema_python_keywords

@disabled_json_schema_keywords.setter
def disabled_json_schema_keywords(self, json_keywords: typing.Set[str]):
disabled_json_schema_keywords = set()
disabled_json_schema_python_keywords = set()
for k in json_keywords:
if k not in JSON_SCHEMA_KEYWORD_TO_PYTHON_KEYWORD:
raise ApiValueError(
"Invalid keyword: '{0}''".format(k))
disabled_json_schema_keywords.add(k)
disabled_json_schema_python_keywords.add(JSON_SCHEMA_KEYWORD_TO_PYTHON_KEYWORD[k])
self.__disabled_json_schema_keywords = disabled_json_schema_keywords
self.__disabled_json_schema_python_keywords = disabled_json_schema_python_keywords
{{#if hasHttpSignatureMethods}}
if name == "signing_info" and value is not None:

@property
def signing_info(self) -> typing.Optional['HttpSigningConfiguration']:
return self.__signing_info

@signing_info.setter
def signing_info(self, value: typing.Optional['HttpSigningConfiguration']):
if value is not None:
# Ensure the host paramater from signing info is the same as
# Configuration.host.
value.host = self.host
self.__signing_info = value
{{/if}}

@classmethod
Expand Down
Original file line number Diff line number Diff line change
@@ -1,96 +1,70 @@
{{#with composedSchemas}}
{{#if allOf}}

class all_of:
{{#each allOf}}
{{#unless refClass}}
{{> model_templates/schema }}
{{/unless}}
{{/each}}
{{#each oneOf}}
{{#unless refClass}}
{{> model_templates/schema }}
{{/unless}}
{{/each}}
{{#each anyOf}}
{{#unless refClass}}
{{> model_templates/schema }}
{{> model_templates/schema }}
{{else}}

@staticmethod
def {{#if nameInSnakeCase}}{{name}}{{else}}{{baseName}}{{/if}}() -> typing.Type['{{refClass}}']:
return {{refClass}}
{{/unless}}
{{/each}}
{{/with}}
{{#with composedSchemas}}
{{#if allOf}}

@classmethod
@functools.lru_cache()
def all_of(cls):
# we need this here to make our import statements work
# we must store _composed_schemas in here so the code is only run
# when we invoke this method. If we kept this at the class
# level we would get an error because the class level
# code would be run when this module is imported, and these composed
# classes don't exist yet because their module has not finished
# loading
return [
classes = [
{{#each allOf}}
{{#if refClass}}
{{refClass}},
{{else}}
{{#if nameInSnakeCase}}
cls.{{name}},
{{name}},
{{else}}
cls.{{baseName}},
{{baseName}},
{{/if}}
{{/if}}
{{/each}}
]
{{/if}}
{{#if oneOf}}

@classmethod
@functools.lru_cache()
def one_of(cls):
# we need this here to make our import statements work
# we must store _composed_schemas in here so the code is only run
# when we invoke this method. If we kept this at the class
# level we would get an error because the class level
# code would be run when this module is imported, and these composed
# classes don't exist yet because their module has not finished
# loading
return [
class one_of:
{{#each oneOf}}
{{#if refClass}}
{{refClass}},
{{#unless refClass}}
{{> model_templates/schema }}
{{else}}

@staticmethod
def {{#if nameInSnakeCase}}{{name}}{{else}}{{baseName}}{{/if}}() -> typing.Type['{{refClass}}']:
return {{refClass}}
{{/unless}}
{{/each}}
classes = [
{{#each oneOf}}
{{#if nameInSnakeCase}}
cls.{{name}},
{{name}},
{{else}}
cls.{{baseName}},
{{baseName}},
{{/if}}
{{/if}}
{{/each}}
]
{{/if}}
{{#if anyOf}}

@classmethod
@functools.lru_cache()
def any_of(cls):
# we need this here to make our import statements work
# we must store _composed_schemas in here so the code is only run
# when we invoke this method. If we kept this at the class
# level we would get an error because the class level
# code would be run when this module is imported, and these composed
# classes don't exist yet because their module has not finished
# loading
return [
class any_of:
{{#each anyOf}}
{{#if refClass}}
{{refClass}},
{{#unless refClass}}
{{> model_templates/schema }}
{{else}}

@staticmethod
def {{#if nameInSnakeCase}}{{name}}{{else}}{{baseName}}{{/if}}() -> typing.Type['{{refClass}}']:
return {{refClass}}
{{/unless}}
{{/each}}
classes = [
{{#each anyOf}}
{{#if nameInSnakeCase}}
cls.{{name}},
{{name}},
{{else}}
cls.{{baseName}},
{{baseName}},
{{/if}}
{{/if}}
{{/each}}
]
{{/if}}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,19 +9,4 @@ schemas.DateTimeBase,
{{/eq}}
{{#eq getFormat "number"}}
schemas.DecimalBase,
{{/eq}}
{{#eq getFormat "binary"}}
schemas.BinaryBase,
{{/eq}}
{{#eq getFormat "int32"}}
schemas.Int32Base,
{{/eq}}
{{#eq getFormat "int64"}}
schemas.Int64Base,
{{/eq}}
{{#eq getFormat "float"}}
schemas.Float32Base,
{{/eq}}
{{#eq getFormat "double"}}
schemas.Float64Base,
{{/eq}}
Original file line number Diff line number Diff line change
Expand Up @@ -5,18 +5,8 @@ class {{#if this.classname}}{{classname}}{{else}}{{#if nameInSnakeCase}}{{name}}
{{#if getFormat}}
{{> model_templates/format_base }}
{{/if}}
{{#if composedSchemas}}
schemas.ComposedSchema,
{{else}}
schemas.AnyTypeSchema,
{{/if}}
{{else}}
{{#if composedSchemas}}
schemas.ComposedBase,
{{/if}}
{{#if isEnum}}
schemas.EnumBase,
{{/if}}
{{> model_templates/xbase_schema }}
{{/if}}
):
Expand All @@ -34,6 +24,9 @@ class {{#if this.classname}}{{classname}}{{else}}{{#if nameInSnakeCase}}{{name}}


class MetaOapg:
{{#if isAnyType}}
# any type
{{/if}}
{{> model_templates/types }}
{{#if getFormat}}
format = '{{getFormat}}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,6 @@


class {{#if this.classname}}{{classname}}{{else}}{{#if nameInSnakeCase}}{{name}}{{else}}{{baseName}}{{/if}}{{/if}}(
{{#if isEnum}}
schemas.EnumBase,
{{/if}}
{{> model_templates/xbase_schema }}
):
{{#if this.classname}}
Expand All @@ -22,6 +19,9 @@ class {{#if this.classname}}{{classname}}{{else}}{{#if nameInSnakeCase}}{{name}}


class MetaOapg:
{{#if isAnyType}}
# any type
{{/if}}
{{> model_templates/types }}
{{#if getFormat}}
format = '{{getFormat}}'
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,5 @@
{{#if isAnyType}}
types = None
{{else}}
{{#unless isAnyType}}
types = {
{{/if}}
{{#if isNull}}
schemas.NoneClass,
{{/if}}
Expand All @@ -26,6 +23,5 @@ types = {
{{#if isBoolean}}
schemas.BoolClass,
{{/if}}
{{#unless isAnyType}}
}
{{/unless}}
Loading