コード例 #1
0
    def __init__(self, properties=None, pattern_properties=None,
                 additional_properties=True, min_properties=None,
                 max_properties=None, required=None, allow_null=False,
                 **kwargs):
        super().__init__(**kwargs)

        properties = {} if (properties is None) else dict_type(properties)
        pattern_properties = {} if (pattern_properties is None) else dict_type(pattern_properties)
        required = list(required) if isinstance(required, (list, tuple)) else required
        required = [] if (required is None) else required

        assert all(isinstance(k, str) for k in properties.keys())
        assert all(isinstance(v, Validator) for v in properties.values())
        assert all(isinstance(k, str) for k in pattern_properties.keys())
        assert all(isinstance(v, Validator) for v in pattern_properties.values())
        assert additional_properties is None or isinstance(additional_properties, (bool, Validator))
        assert min_properties is None or isinstance(min_properties, int)
        assert max_properties is None or isinstance(max_properties, int)
        assert all(isinstance(i, str) for i in required)

        self.properties = properties
        self.pattern_properties = pattern_properties
        self.additional_properties = additional_properties
        self.min_properties = min_properties
        self.max_properties = max_properties
        self.required = required
        self.allow_null = allow_null
コード例 #2
0
    def get_content(self, swagger, base_url, schema_definitions):
        """
        Return all the links in the document, layed out by tag and operationId.
        """
        links_by_tag = dict_type()
        links = []

        for path, path_info in swagger.get('paths', {}).items():
            operations = {
                key: path_info[key]
                for key in path_info if key in METHODS
            }
            for operation, operation_info in operations.items():
                tag = lookup(operation_info, ['tags', 0])
                link = self.get_link(base_url, path, path_info, operation,
                                     operation_info, schema_definitions)
                if link is None:
                    continue

                if tag is None:
                    links.append(link)
                elif tag not in links_by_tag:
                    links_by_tag[tag] = [link]
                else:
                    links_by_tag[tag].append(link)

        sections = [
            Section(name=_simple_slugify(tag),
                    title=tag.title(),
                    content=links) for tag, links in links_by_tag.items()
        ]
        return links + sections
コード例 #3
0
    def __init__(self, title='', description='', default=NO_DEFAULT, allow_null=False, definitions=None, def_name=None):
        definitions = {} if (definitions is None) else dict_type(definitions)

        assert isinstance(title, str)
        assert isinstance(description, str)
        assert isinstance(definitions, dict)
        assert all(isinstance(k, str) for k in definitions.keys())
        assert all(isinstance(v, Validator) for v in definitions.values())

        if allow_null and default is NO_DEFAULT:
            default = None

        if default is not NO_DEFAULT:
            self.default = default

        self.title = title
        self.description = description
        self.allow_null = allow_null
        self.definitions = definitions
        self.def_name = def_name

        # We need this global counter to determine what order fields have
        # been declared in when used with `Type`.
        self._creation_counter = Validator._creation_counter
        Validator._creation_counter += 1
コード例 #4
0
    def __init__(self, routes):
        rules = []
        name_lookups = {}

        for path, name, route in self.walk_routes(routes):
            path_params = [
                item.strip("{}") for item in re.findall("{[^}]*}", path)
            ]
            args = inspect.signature(route.handler).parameters
            for path_param in path_params:
                if path_param.startswith("+"):
                    path = path.replace("{%s}" % path_param,
                                        "<path:%s>" % path_param.lstrip("+"))
                elif path_param in args and args[path_param].annotation is int:
                    path = path.replace("{%s}" % path_param,
                                        "<int:%s>" % path_param)
                elif path_param in args and args[
                        path_param].annotation is float:
                    path = path.replace("{%s}" % path_param,
                                        "<float:%s>" % path_param)
                else:
                    path = path.replace("{%s}" % path_param,
                                        "<string:%s>" % path_param)

            rule = Rule(path, methods=[route.method], endpoint=name)
            rules.append(rule)
            name_lookups[name] = route

        self.adapter = Map(rules).bind("")
        self.name_lookups = name_lookups

        # Use an MRU cache for router lookups.
        self._lookup_cache = dict_type()
        self._lookup_cache_size = 10000
コード例 #5
0
    def get_paths(self, document, schema_defs=None):
        paths = dict_type()

        for link, name, sections in document.walk_links():
            path = urlparse(link.url).path
            operation_id = link.name
            tag = sections[0].name if sections else None
            method = link.method.lower()

            if path not in paths:
                paths[path] = {}
            paths[path][method] = self.get_operation(link, operation_id, tag=tag, schema_defs=schema_defs)

        return paths
コード例 #6
0
    def encode(self, item, **options):
        defs = dict_type()
        struct = self.encode_to_data_structure(
            item, defs=defs, def_prefix="#/definitions/"
        )
        struct["definitions"] = defs
        if options.get("to_data_structure"):
            return struct

        indent = options.get("indent")
        if indent:
            kwargs = {"ensure_ascii": False, "indent": 4, "separators": (",", ": ")}
        else:
            kwargs = {"ensure_ascii": False, "indent": None, "separators": (",", ":")}
        return json.dumps(struct, **kwargs).encode("utf-8")
コード例 #7
0
    def encode(self, item, **options):
        defs = dict_type()
        struct = self.encode_to_data_structure(item,
                                               defs=defs,
                                               def_prefix='#/definitions/')
        struct['definitions'] = defs
        if options.get('to_data_structure'):
            return struct

        indent = options.get('indent')
        if indent:
            kwargs = {
                'ensure_ascii': False,
                'indent': 4,
                'separators': (',', ': ')
            }
        else:
            kwargs = {
                'ensure_ascii': False,
                'indent': None,
                'separators': (',', ':')
            }
        return json.dumps(struct, **kwargs).encode('utf-8')
コード例 #8
0
    def validate(self, value, definitions=None, allow_coerce=False):
        if value is None and self.allow_null:
            return None
        elif value is None:
            self.error('null')
        elif not isinstance(value, (dict, typing.Mapping)):
            self.error('type')

        definitions = self.get_definitions(definitions)
        validated = dict_type()

        # Ensure all property keys are strings.
        errors = {}
        if any(not isinstance(key, str) for key in value.keys()):
            self.error('invalid_key')

        # Min/Max properties
        if self.min_properties is not None:
            if len(value) < self.min_properties:
                if self.min_properties == 1:
                    self.error('empty')
                else:
                    self.error('min_properties')
        if self.max_properties is not None:
            if len(value) > self.max_properties:
                self.error('max_properties')

        # Required properties
        for key in self.required:
            if key not in value:
                errors[key] = self.error_message('required')

        # Properties
        for key, child_schema in self.properties.items():
            if key not in value:
                if child_schema.has_default():
                    validated[key] = child_schema.default
                continue
            item = value[key]
            try:
                validated[key] = child_schema.validate(
                    item,
                    definitions=definitions,
                    allow_coerce=allow_coerce
                )
            except ValidationError as exc:
                errors[key] = exc.detail

        # Pattern properties
        if self.pattern_properties:
            for key in list(value.keys()):
                for pattern, child_schema in self.pattern_properties.items():
                    if re.search(pattern, key):
                        item = value[key]
                        try:
                            validated[key] = child_schema.validate(
                                item, definitions=definitions,
                                allow_coerce=allow_coerce
                            )
                        except ValidationError as exc:
                            errors[key] = exc.detail

        # Additional properties
        remaining = [
            key for key in value.keys()
            if key not in set(validated.keys())
        ]

        if self.additional_properties is True:
            for key in remaining:
                validated[key] = value[key]
        elif self.additional_properties is False:
            for key in remaining:
                errors[key] = self.error_message('no_additional_properties')
        elif self.additional_properties is not None:
            child_schema = self.additional_properties
            for key in remaining:
                item = value[key]
                try:
                    validated[key] = child_schema.validate(
                        item,
                        definitions=definitions,
                        allow_coerce=allow_coerce
                    )
                except ValidationError as exc:
                    errors[key] = exc.detail

        if errors:
            raise ValidationError(errors)

        return validated
コード例 #9
0
    def validate(self, value, definitions=None, allow_coerce=False):
        if value is None and self.allow_null:
            return None
        elif value is None:
            self.error('null')
        elif not isinstance(value, (dict, typing.Mapping)):
            self.error('type')

        definitions = self.get_definitions(definitions)
        validated = dict_type()

        # Ensure all property keys are strings.
        errors = {}
        for key in value.keys():
            if not isinstance(key, str):
                errors[key] = [self.error_message('invalid_key')]

        # Min/Max properties
        if self.min_properties is not None:
            if len(value) < self.min_properties:
                if self.min_properties == 1:
                    self.error('empty')
                else:
                    self.error('min_properties')
        if self.max_properties is not None:
            if len(value) > self.max_properties:
                self.error('max_properties')

        # Required properties
        for key in self.required:
            if key not in value:
                errors[key] = [self.error_message('required', field_name=key)]

        # Properties
        for key, child_schema in self.properties.items():
            if key not in value:
                if child_schema.has_default():
                    validated[key] = child_schema.default
                continue
            item = value[key]
            try:
                validated[key] = child_schema.validate(
                    item,
                    definitions=definitions,
                    allow_coerce=allow_coerce
                )
            except ValidationError as exc:
                errors[key] = exc.messages

        # Pattern properties
        if self.pattern_properties:
            for key in list(value.keys()):
                for pattern, child_schema in self.pattern_properties.items():
                    if isinstance(key, str) and re.search(pattern, key):
                        item = value[key]
                        try:
                            validated[key] = child_schema.validate(
                                item, definitions=definitions,
                                allow_coerce=allow_coerce
                            )
                        except ValidationError as exc:
                            errors[key] = exc.messages

        # Additional properties
        remaining = [
            key for key in value.keys()
            if key not in set(validated.keys()) | set(errors.keys())
        ]

        if self.additional_properties is True:
            for key in remaining:
                validated[key] = value[key]
        elif self.additional_properties is False:
            for key in remaining:
                errors[key] = [self.error_message('invalid_property')]
        elif self.additional_properties is not None:
            child_schema = self.additional_properties
            for key in remaining:
                item = value[key]
                try:
                    validated[key] = child_schema.validate(
                        item,
                        definitions=definitions,
                        allow_coerce=allow_coerce
                    )
                except ValidationError as exc:
                    errors[key] = exc.messages

        if errors:
            error_messages = []
            for key, messages in errors.items():
                for message in messages:
                    index = [key] if message.index is None else [key] + message.index
                    error_message = ErrorMessage(message.text, message.code, index)
                    error_messages.append(error_message)
            raise ValidationError(error_messages)

        return validated
コード例 #10
0
    def encode_to_data_structure(self, item, defs=None, def_prefix=None, is_def=False):
        if issubclass(item, types.Type):
            item = item.validator

        if defs is not None and item.def_name and not is_def:
            defs[item.def_name] = self.encode_to_data_structure(
                item, defs, def_prefix, is_def=True
            )
            return {"$ref": def_prefix + item.def_name}

        value = dict_type()
        if item.title:
            value["title"] = item.title
        if item.description:
            value["description"] = item.description
        if item.has_default():
            value["default"] = item.default
        if getattr(item, "allow_null") is True:
            value["nullable"] = True

        if isinstance(item, validators.String):
            value["type"] = "string"
            if item.max_length is not None:
                value["maxLength"] = item.max_length
            if item.min_length is not None:
                value["minLength"] = item.min_length
            if item.pattern is not None:
                value["pattern"] = item.pattern
            if item.format is not None:
                value["format"] = item.format
            return value

        elif isinstance(item, validators.NumericType):
            if isinstance(item, validators.Integer):
                value["type"] = "integer"
            else:
                value["type"] = "number"

            if item.minimum is not None:
                value["minimum"] = item.minimum
            if item.maximum is not None:
                value["maximum"] = item.maximum
            if item.exclusive_minimum:
                value["exclusiveMinimum"] = item.exclusive_minimum
            if item.exclusive_maximum:
                value["exclusiveMaximum"] = item.exclusive_maximum
            if item.multiple_of is not None:
                value["multipleOf"] = item.multiple_of
            if item.format is not None:
                value["format"] = item.format
            return value

        elif isinstance(item, validators.Boolean):
            value["type"] = "boolean"
            return value

        elif isinstance(item, validators.Object):
            value["type"] = "object"
            if item.properties:
                value["properties"] = dict_type(
                    [
                        (key, self.encode_to_data_structure(value, defs, def_prefix))
                        for key, value in item.properties.items()
                    ]
                )
            if item.required:
                value["required"] = item.required
            return value

        elif isinstance(item, validators.Array):
            value["type"] = "array"
            if item.items is not None:
                value["items"] = self.encode_to_data_structure(
                    item.items, defs, def_prefix
                )
            if item.additional_items:
                value["additionalItems"] = item.additional_items
            if item.min_items is not None:
                value["minItems"] = item.min_items
            if item.max_items is not None:
                value["maxItems"] = item.max_items
            if item.unique_items:
                value["uniqueItems"] = item.unique_items
            return value

        raise Exception("Cannot encode item %s" % item)
コード例 #11
0
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
コード例 #12
0
    def encode_to_data_structure(self,
                                 item,
                                 defs=None,
                                 def_prefix=None,
                                 is_def=False):
        if issubclass(item, types.Type):
            item = item.validator

        if defs is not None and item.def_name and not is_def:
            defs[item.def_name] = self.encode_to_data_structure(item,
                                                                defs,
                                                                def_prefix,
                                                                is_def=True)
            return {'$ref': def_prefix + item.def_name}

        value = dict_type()
        if item.title:
            value['title'] = item.title
        if item.description:
            value['description'] = item.description
        if item.has_default():
            value['default'] = item.default
        if getattr(item, 'allow_null') is True:
            value['nullable'] = True

        if isinstance(item, validators.String):
            value['type'] = 'string'
            if item.max_length is not None:
                value['maxLength'] = item.max_length
            if item.min_length is not None:
                value['minLength'] = item.min_length
            if item.pattern is not None:
                value['pattern'] = item.pattern
            if item.format is not None:
                value['format'] = item.format
            return value

        elif isinstance(item, validators.NumericType):
            if isinstance(item, validators.Integer):
                value['type'] = 'integer'
            else:
                value['type'] = 'number'

            if item.minimum is not None:
                value['minimum'] = item.minimum
            if item.maximum is not None:
                value['maximum'] = item.maximum
            if item.exclusive_minimum:
                value['exclusiveMinimum'] = item.exclusive_minimum
            if item.exclusive_maximum:
                value['exclusiveMaximum'] = item.exclusive_maximum
            if item.multiple_of is not None:
                value['multipleOf'] = item.multiple_of
            if item.format is not None:
                value['format'] = item.format
            return value

        elif isinstance(item, validators.Boolean):
            value['type'] = 'boolean'
            return value

        elif isinstance(item, validators.Object):
            value['type'] = 'object'
            if item.properties:
                value['properties'] = dict_type([
                    (key,
                     self.encode_to_data_structure(value, defs, def_prefix))
                    for key, value in item.properties.items()
                ])
            if item.required:
                value['required'] = item.required
            return value

        elif isinstance(item, validators.Array):
            value['type'] = 'array'
            if item.items is not None:
                value['items'] = self.encode_to_data_structure(
                    item.items, defs, def_prefix)
            if item.additional_items:
                value['additionalItems'] = item.additional_items
            if item.min_items is not None:
                value['minItems'] = item.min_items
            if item.max_items is not None:
                value['maxItems'] = item.max_items
            if item.unique_items:
                value['uniqueItems'] = item.unique_items
            return value

        raise Exception('Cannot encode item %s' % item)
コード例 #13
0
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