Ejemplo n.º 1
0
        def _gen(compact: bool):
            yield parser.metadata.id
            yield
            yield from self.text_block(parser.metadata.info.description)

            if (parser.metadata.external_docs is not None):
                yield " - External Documentation:"
                with self.indent():
                    yield parser.metadata.external_docs.url
                    yield from self.text_block(
                        parser.metadata.external_docs.description)

            if (parser.metadata.info.licence is not None):
                yield f" - License: {parser.metadata.info.licence.name}"
                with self.indent():
                    yield from Option(parser.metadata.info.licence.url).map(
                        '({})'.format)

            if (parser.metadata.info.contact is not None):
                yield " - Contacts:"
                with self.indent():
                    yield from Option(parser.metadata.info.contact.name).map(
                        ' - Name: {}'.format)
                    yield from Option(parser.metadata.info.contact.url).map(
                        ' - URL: {}'.format)
                    yield from Option(parser.metadata.info.contact.email).map(
                        ' - Email: {}'.format)
                yield

            yield f"Generated by Python OpenAPI Parser v{openapi_parser.__version__}"
Ejemplo n.º 2
0
class StringFilter(FilterImpl[AnyStr], Generic[AnyStr]):
    max_length: Optional[int] = None
    min_length: Optional[int] = None
    pattern: Optional[Pattern[AnyStr]] = field(
        default=None,
        metadata=config(
            decoder=lambda s: Option(s).map(re.compile).as_optional,
            encoder=lambda x: Option(x).map(lambda r: r.pattern).get_or_else(
                None)))

    def check_value(self, value: AnyStr) -> bool:
        return \
            (self.max_length is None or self.max_length >= len(value)) and \
            (self.min_length is None or self.min_length <= len(value)) and \
            (self.pattern is None or self.pattern.search(value))

    def mix_with(self, f: Filter[T]) -> Filter[T]:
        if (isinstance(f, StringFilter)):
            return StringFilter \
            (
                max_length = mix_options(self.max_length, f.max_length).map(min).as_optional,
                min_length = mix_options(self.min_length, f.min_length).map(max).as_optional,
                pattern    = mix_options(self.pattern, f.pattern).map(combine_regular_expressions).as_optional,
            )
        else:
            return super().mix_with(f)
Ejemplo n.º 3
0
        def extra_gen():
            params = method.all_parameters
            if (params):
                yield "Arguments:"
                with self.indent():
                    for p in params:
                        p_name, p_cls, p_value, _ = self.parse_attribute(
                            p.name, p.schema, is_required=p.required)
                        yield f'{p_name}' + ':' + p_cls.map(
                            ' `{}`'.format).get_or_else('') + p_value.map(
                                ', default: `{}`'.format).get_or_else('') + '.'
                        with self.indent():
                            yield from self.text_block(
                                p_value.map(lambda _: 'Optional.').get_or_else(
                                    '**REQUIRED.**') + ' ' +
                                Option(p.description).get_or_else(''))
                        yield

                    if (method.request_body is not None):
                        media_type, media_data = method.regular_request_parser
                        p_name, p_cls, p_value, _ = self.parse_attribute(
                            'data', media_data.schema, is_required=True)
                        yield f'{p_name}' + ':' + p_cls.map(
                            ' `{}`'.format).get_or_else('') + '.'
                        with self.indent():
                            yield f"**REQUIRED.** Request body" + (
                                " of '{media_type}' media-type"
                                if media_data != '*/*' else ''
                            ) + Option(media_data).flat_map(
                                lambda m: Option(m.encoding)).map(
                                    " (encoding: '{}')".format).get_or_else('')
                            if (media_data is not None
                                    and media_data.schema is not None):
                                yield from self.text_block(
                                    media_data.schema.summary, compact=True)
                                yield from self.text_block(
                                    media_data.schema.description,
                                    compact=True)
                        yield

            _, resp = method.regular_response
            if (resp is not None):
                _, media_data = resp.regular_request_parser
                if (media_data is not None and media_data.schema is not None):
                    yield "Returns:"
                    with self.indent():
                        _, r_cls, _, _ = self.parse_attribute(
                            'response', media_data.schema, is_required=True)
                        yield from self.text_block(
                            r_cls.map('`{}`. '.format).get_or_else('') +
                            Option(resp.description).get_or_else(''),
                            compact=True)
                        yield from self.text_block(media_data.schema.summary,
                                                   compact=True)
                        yield from self.text_block(
                            media_data.schema.description, compact=True)
                    yield
Ejemplo n.º 4
0
    def decoder(self):
        if (self.discriminator is None):
            return None

        items = Option(self.any_of).get_or_else(list()) + Option(
            self.one_of).get_or_else(list()) + Option(self.all_of).get_or_else(
                list())
        for it in items:
            if (it.cls != dict and not isinstance(it.cls, ModelClassImpl)):
                raise InvalidAlternativeTypes(self, it.cls)

        return self.discriminator.decoder(items)
Ejemplo n.º 5
0
    def write_method_head(self,
                          method_name: str,
                          params: List[str] = None,
                          return_type: Union[Option[M],
                                             Optional[M]] = OptionNone,
                          *,
                          method_type: MethodType = MethodType.Function,
                          asynchronous: bool = False) -> Iterator[str]:
        if (params is None):
            params = list()
        if (not isinstance(return_type, Option)):
            return_type = Option.from_optional(return_type)

        if (method_type == MethodType.Function):
            pass
        elif (method_type == MethodType.RegularMethod):
            params.insert(0, 'self')
        elif (method_type == MethodType.ClassMethod):
            yield '@classmethod'
            params.insert(0, 'cls')
        elif (method_type == MethodType.StaticMethod):
            yield '@staticmethod'

        if (asynchronous):
            def_keyword = 'async def'
        else:
            def_keyword = 'def'

        yield from self.smart_constructor(
            f'{def_keyword} {method_name}',
            *params,
            suffix=return_type.map(' -> {}'.format).get_or_else('') + ':')
Ejemplo n.º 6
0
    def decoder(self, items: List[ModelSchema]) -> Optional[str]:
        mapping = Option(self.mapping).get_or_else(
            {get_class_name(it.cls): get_class_name(it.cls)
             for it in items})
        if (len(mapping) < 2):
            return None

        return f"discriminator_decoder(discriminator_key={self.property_name!r}, mappings={{ {', '.join(f'{k!r}: {v}' for k, v in mapping.items())} }})"
Ejemplo n.º 7
0
 def __post_init__(self):
     if (not Option.is_option(self.default)):
         self.default = Some(self.default)
Ejemplo n.º 8
0
def _mix_options(options: Iterable[Opt]) -> Iterator[T]:
    for op in options:
        if (not Option.is_option(op)):
            op = Option(op)
        yield from op
Ejemplo n.º 9
0
    def load_schema(self,
                    schema_data: Dict[str, Any],
                    path: str,
                    *,
                    is_top_level: bool,
                    force_name: Optional[str] = None,
                    **kwargs) -> ModelSchema:
        if (force_name is not None and not is_top_level):
            name = force_name
        else:
            _, _, name = split_path_right(path)

        field_data = ModelSchemaImpl.from_dict(schema_data)
        field_data.property_name = name
        inheritance_data = InheritanceFilter.from_dict(schema_data)
        if (not inheritance_data.is_empty):
            inheritance_data.all_of = self._load_fields(
                inheritance_data.all_of, path + '/allOf')
            inheritance_data.any_of = self._load_fields(
                inheritance_data.any_of, path + '/anyOf')
            inheritance_data.one_of = self._load_fields(
                inheritance_data.one_of, path + '/oneOf')
            if (inheritance_data.filter_not is not None):
                # noinspection PyTypeChecker
                inheritance_data.filter_not = self.load_schema(
                    inheritance_data.filter_not, path + '/not')
            if (inheritance_data.discriminator is not None):
                if (field_data.property_type is None):
                    field_data.property_type = PropertyType.Object
                elif (field_data.property_type != PropertyType.Object):
                    # ToDo: Discriminator fields could not be used in combination with non-object properties
                    raise ValueError(
                        "Discriminator fields could not be used in combination with non-object properties"
                    )

        if (field_data.property_type is None):
            field_data.cls = Any

        elif (field_data.property_type == PropertyType.Integer):
            field_data.cls = int
            field_data.filter = NumericFilter.from_dict(schema_data)

        elif (field_data.property_type == PropertyType.Number):
            field_data.cls = float
            field_data.filter = NumericFilter.from_dict(schema_data)

        elif (field_data.property_type == PropertyType.String):
            if (DateFormatName.contains_value(field_data.property_format)):
                field_data.cls = datetime
                field_data.filter = DateFilter.from_dict(schema_data)
            else:
                if (field_data.property_format in ('byte', 'binary')):
                    field_data.cls = bytes
                else:
                    field_data.cls = str
                field_data.filter = StringFilter.from_dict(schema_data)

        elif (field_data.property_type == PropertyType.Boolean):
            field_data.cls = bool

        elif (field_data.property_type == PropertyType.Array):
            if ('items' in schema_data):
                items = self.load_schema(schema_data['items'],
                                         path + '/items',
                                         force_name=field_data.property_name +
                                         self.id_separator + 'item')
                field_data.cls = ListProxy[items.cls]
            else:
                field_data.cls = list
            field_data.filter = ArrayFilter.from_dict(schema_data)

        elif (field_data.property_type == PropertyType.Object):
            additional_properties: Union[bool,
                                         Dict[str, Any]] = schema_data.get(
                                             'additionalProperties', True)
            if ('properties' in schema_data):
                field_data.cls = self.load_class(
                    schema_data,
                    path,
                    is_top_level=is_top_level,
                    force_name=field_data.property_name)
            elif (additional_properties == False):
                raise InvalidSchemaFields(
                    path,
                    "'additionalProperties=False' is not allowed in combination with missing 'properties' for 'object' invalid_type"
                )
            elif (isinstance(additional_properties, dict)):
                cls = self.load_schema(additional_properties,
                                       path + '/additionalProperties',
                                       force_name=field_data.property_name +
                                       self.id_separator + 'item')
                field_data.cls = DictProxy[str, cls]
                field_data.filter = DictFilter.from_dict(schema_data)
            else:
                field_data.cls = dict
                field_data.filter = DictFilter.from_dict(schema_data)

        field_data.filter = EmptyFilter().mix_with(
            field_data.filter).mix_with(inheritance_data)

        if (inheritance_data.any_of is not None
                or inheritance_data.one_of is not None):
            if (inheritance_data.all_of is not None):
                raise InvalidSchemaFields(
                    path,
                    f"allOf is not allowed in combination with oneOf/anyOf")

            items = Option(inheritance_data.any_of).get_or_else(
                list()) + Option(inheritance_data.one_of).get_or_else(list())
            field_data.cls = UnionProxy[tuple(items)]
            if (inheritance_data.discriminator is not None):
                field_data.cls = field_data.cls.with_discriminator(
                    inheritance_data.discriminator)

        elif (inheritance_data.all_of is not None and field_data.cls == Any):
            field_data.cls, inh_filter = self._merge_classes(
                inheritance_data.all_of,
                path,
                is_top_level=is_top_level,
                force_name=field_data.property_name)
            inheritance_data = inheritance_data.mix_with(inh_filter)

        field_data.filter = field_data.filter.mix_with(inheritance_data)
        if ('enum' in schema_data):
            enum_data = ModelEnumDataImpl.from_dict(schema_data)
            enum_data.name = field_data.property_name
            enum_data.base_class = field_data.cls
            enum_data.path = path + '/enum'
            enum_data.pretty_path = None
            field_data.cls = enum_data

        return field_data
Ejemplo n.º 10
0
 def _name_gen(s: ModelServer) -> Option[str]:
     return Option(s.description or s.url).map(
         self.enum_entry_name_pretty).map(self.object_valid_name_filter)