def generate_fields(self, url, method, handler): fields = [] path_names = [ item.strip('{}').lstrip('+') for item in re.findall('{[^}]*}', url) ] parameters = inspect.signature(handler).parameters for name, param in parameters.items(): if name in path_names: schema = { param.empty: None, int: validators.Integer(), float: validators.Number(), str: validators.String() }[param.annotation] field = Field(name=name, location='path', schema=schema) fields.append(field) elif param.annotation in (param.empty, int, float, bool, str, http.QueryParam): if param.default is param.empty: kwargs = {} elif param.default is None: kwargs = {'default': None, 'allow_null': True} else: kwargs = {'default': param.default} schema = { param.empty: None, int: validators.Integer(**kwargs), float: validators.Number(**kwargs), bool: validators.Boolean(**kwargs), str: validators.String(**kwargs), http.QueryParam: validators.String(**kwargs), }[param.annotation] field = Field(name=name, location='query', schema=schema) fields.append(field) elif issubclass(param.annotation, types.Type): if method in ('GET', 'DELETE'): for name, validator in param.annotation.validator.properties.items( ): field = Field(name=name, location='query', schema=validator) fields.append(field) else: field = Field(name=name, location='body', schema=param.annotation.validator) fields.append(field) return fields
def resolve(self, parameter: inspect.Parameter, path_params: ValidatedPathParams, query_params: ValidatedQueryParams): params = path_params if (parameter.name in path_params) else query_params has_default = parameter.default is not parameter.empty allow_null = parameter.default is None param_validator = { parameter.empty: validators.Any(), str: validators.String(allow_null=allow_null), int: validators.Integer(allow_null=allow_null), float: validators.Number(allow_null=allow_null), bool: validators.Boolean(allow_null=allow_null) }[parameter.annotation] validator = validators.Object( properties=[(parameter.name, param_validator)], required=[] if has_default else [parameter.name]) try: params = validator.validate(params, allow_coerce=True) except validators.ValidationError as exc: raise exceptions.NotFound(exc.detail) return params.get(parameter.name, parameter.default)
class Product(types.Type): name = validators.String(max_length=10) rating = validators.Integer(allow_null=True, default=None, minimum=0, maximum=100) created = validators.DateTime()
import json import re from urllib.parse import urljoin, urlparse from kapi import validators from kapi.codecs import BaseCodec, JSONSchemaCodec from kapi.codecs.jsonschema import JSON_SCHEMA from kapi.compat import dict_type from kapi.document import Document, Field, Link, Section from kapi.parse import infer_json_or_yaml, parse_json, parse_yaml SCHEMA_REF = validators.Object( properties={'$ref': validators.String(pattern='^#/components/schemas/')}) REQUESTBODY_REF = validators.Object( properties={ '$ref': validators.String(pattern='^#/components/requestBodies/') }) RESPONSE_REF = validators.Object( properties={'$ref': validators.String(pattern='^#/components/responses/')}) OPEN_API = validators.Object( def_name='OpenAPI', title='OpenAPI', properties=[ ('openapi', validators.String()), ('info', validators.Ref('Info')), ('servers', validators.Array(items=validators.Ref('Server'))), ('paths', validators.Ref('Paths')), ('components', validators.Ref('Components')), ('security', validators.Array(items=validators.Ref('SecurityRequirement'))),
def load_type(typename, struct, allow_null): attrs = {'allow_null': True} if allow_null else {} if typename == 'string': if 'minLength' in struct: attrs['min_length'] = struct['minLength'] if 'maxLength' in struct: attrs['max_length'] = struct['maxLength'] if 'pattern' in struct: attrs['pattern'] = struct['pattern'] if 'format' in struct: attrs['format'] = struct['format'] return validators.String(**attrs) if typename in ['number', 'integer']: if 'minimum' in struct: attrs['minimum'] = struct['minimum'] if 'maximum' in struct: attrs['maximum'] = struct['maximum'] if 'exclusiveMinimum' in struct: attrs['exclusive_minimum'] = struct['exclusiveMinimum'] if 'exclusiveMaximum' in struct: attrs['exclusive_maximum'] = struct['exclusiveMaximum'] if 'multipleOf' in struct: attrs['multiple_of'] = struct['multipleOf'] if 'format' in struct: attrs['format'] = struct['format'] if typename == 'integer': return validators.Integer(**attrs) return validators.Number(**attrs) if typename == 'boolean': return validators.Boolean(**attrs) if typename == 'object': if 'properties' in struct: attrs['properties'] = dict_type([ (key, decode(value)) for key, value in struct['properties'].items() ]) if 'required' in struct: attrs['required'] = struct['required'] if 'minProperties' in struct: attrs['min_properties'] = struct['minProperties'] if 'maxProperties' in struct: attrs['max_properties'] = struct['maxProperties'] if 'required' in struct: attrs['required'] = struct['required'] if 'patternProperties' in struct: attrs['pattern_properties'] = dict_type([ (key, decode(value)) for key, value in struct['patternProperties'].items() ]) if 'additionalProperties' in struct: if isinstance(struct['additionalProperties'], bool): attrs['additional_properties'] = struct['additionalProperties'] else: attrs['additional_properties'] = decode( struct['additionalProperties']) return validators.Object(**attrs) if typename == 'array': if 'items' in struct: if isinstance(struct['items'], list): attrs['items'] = [decode(item) for item in struct['items']] else: attrs['items'] = decode(struct['items']) if 'additionalItems' in struct: if isinstance(struct['additionalItems'], bool): attrs['additional_items'] = struct['additionalItems'] else: attrs['additional_items'] = decode(struct['additionalItems']) if 'minItems' in struct: attrs['min_items'] = struct['minItems'] if 'maxItems' in struct: attrs['max_items'] = struct['maxItems'] if 'uniqueItems' in struct: attrs['unique_items'] = struct['uniqueItems'] return validators.Array(**attrs) assert False
import json from kapi import types, validators from kapi.codecs.base import BaseCodec from kapi.compat import dict_type from kapi.exceptions import ParseError JSON_SCHEMA = validators.Object( def_name='JSONSchema', properties=[ ('$ref', validators.String()), ('type', validators.String() | validators.Array(items=validators.String())), ('enum', validators.Array(unique_items=True, min_items=1)), ('definitions', validators.Object( additional_properties=validators.Ref('JSONSchema'))), # String ('minLength', validators.Integer(minimum=0)), ('maxLength', validators.Integer(minimum=0)), ('pattern', validators.String(format='regex')), ('format', validators.String()), # Numeric ('minimum', validators.Number()), ('maximum', validators.Number()), ('exclusiveMinimum', validators.Boolean()), ('exclusiveMaximum', validators.Boolean()), ('multipleOf', validators.Number(minimum=0.0, exclusive_minimum=True)),
class User(types.Type): name = validators.String(max_length=10) age = validators.Integer(minimum=0, allow_null=True, default=None)
import json import re from urllib.parse import urljoin, urlparse from kapi import validators from kapi.codecs import BaseCodec, JSONSchemaCodec from kapi.codecs.jsonschema import JSON_SCHEMA from kapi.compat import dict_type from kapi.document import Document, Field, Link, Section from kapi.parse import infer_json_or_yaml, parse_json, parse_yaml SCHEMA_REF = validators.Object( properties={'$ref': validators.String(pattern='^#/components/schemas/')}) RESPONSE_REF = validators.Object( properties={'$ref': validators.String(pattern='^#/components/responses/')}) SWAGGER = validators.Object( def_name='Swagger', title='Swagger', properties=[ ('swagger', validators.String()), ('info', validators.Ref('Info')), ('paths', validators.Ref('Paths')), ('host', validators.String()), ('basePath', validators.String()), ('schemes', validators.Array(items=validators.String())), ('consumes', validators.Array(items=validators.String())), ('produces', validators.Array(items=validators.String())), ('definitions', validators.Object(additional_properties=validators.Any())), ('parameters',
from kapi import validators from kapi.codecs import BaseCodec from kapi.parse import parse_yaml KAPI_CONFIG = validators.Object( properties=[ ('schema', validators.Object(properties=[ ('path', validators.String()), ('format', validators.String(enum=['openapi', 'swagger'])), ], additional_properties=False, required=['path', 'format'])), ('docs', validators.Object( properties=[ ('theme', validators.String(enum=['kapi', 'redoc', 'swaggerui'])), ], additional_properties=False, )) ], additional_properties=False, required=['schema'], ) class ConfigCodec(BaseCodec): media_type = 'application/x-yaml' format = 'kapi'
class Place(types.Type): location = Location name = validators.String(max_length=100)
class Something(types.Type): keys = validators.String()
class ReviewedProduct(Product): reviewer = validators.String(max_length=20)