示例#1
0
def doc():
    return Document(title='original',
                    content={
                        'nested':
                        Document(
                            content={
                                'follow':
                                Link(url='mock://example.com', action='get'),
                                'action':
                                Link(url='mock://example.com',
                                     action='post',
                                     transform='inplace',
                                     fields=['foo']),
                                'create':
                                Link(url='mock://example.com',
                                     action='post',
                                     fields=['foo']),
                                'update':
                                Link(url='mock://example.com',
                                     action='put',
                                     fields=['foo']),
                                'delete':
                                Link(url='mock://example.com', action='delete')
                            })
                    })
示例#2
0
    def get_response_object(self, response_serializer_class, description):

        fields = []
        serializer = response_serializer_class()
        nested_obj = {}

        for field in serializer.fields.values():
            # If field is a serializer, attempt to get its schema.
            if isinstance(field, serializers.Serializer):
                subfield_schema = self.get_response_object(
                    field.__class__, None)[0].get('schema')

                # If the schema exists, use it as the nested_obj
                if subfield_schema is not None:
                    nested_obj[field.field_name] = subfield_schema
                    nested_obj[
                        field.field_name]['description'] = field.help_text
                    continue

            # Otherwise, carry-on and use the field's schema.
            fallback_schema = self.fallback_schema_from_field(field)
            fields.append(
                Field(
                    name=field.field_name,
                    location='form',
                    required=field.required,
                    schema=fallback_schema
                    if fallback_schema else field_to_schema(field),
                ))

        res = _get_parameters(Link(fields=fields), None)

        if not res:
            if nested_obj:
                return {
                    'description': description,
                    'schema': {
                        'type': 'object',
                        'properties': nested_obj
                    }
                }, {}
            else:
                return {}, {}

        schema = res[0]['schema']
        schema['properties'].update(nested_obj)
        response_schema = {'description': description, 'schema': schema}

        error_status_codes = {}

        response_meta = getattr(response_serializer_class, 'Meta', None)

        for status_code, description in getattr(response_meta,
                                                'error_status_codes',
                                                {}).items():
            error_status_codes[status_code] = {'description': description}

        return response_schema, error_status_codes
示例#3
0
def test_delete(monkeypatch, http):
    def mockreturn(self, request):
        return MockResponse(b'')

    monkeypatch.setattr(requests.Session, 'send', mockreturn)

    link = Link(url='http://example.org', action='delete')
    doc = http.transition(link, decoders)
    assert doc is None
示例#4
0
def test_get(monkeypatch, http):
    def mockreturn(self, request):
        return MockResponse(b'{"_type": "document", "example": 123}')

    monkeypatch.setattr(requests.Session, 'send', mockreturn)

    link = Link(url='http://example.org', action='get')
    doc = http.transition(link, decoders)
    assert doc == {'example': 123}
示例#5
0
def test_get_with_parameters(monkeypatch, http):
    def mockreturn(self, request):
        insert = request.path_url.encode('utf-8')
        return MockResponse(b'{"_type": "document", "url": "' + insert + b'"}')

    monkeypatch.setattr(requests.Session, 'send', mockreturn)

    link = Link(url='http://example.org', action='get')
    doc = http.transition(link, decoders, params={'example': 'abc'})
    assert doc == {'url': '/?example=abc'}
示例#6
0
def test_document_equality(doc):
    assert doc == {
        'integer':
        123,
        'dict': {
            'key': 'value'
        },
        'list': [1, 2, 3],
        'link':
        Link(url='/',
             action='post',
             transform='inplace',
             fields=[
                 'optional',
                 Field('required', required=True, location='path')
             ]),
        'nested': {
            'child': Link(url='/123')
        }
    }
示例#7
0
def get_note(identifier):
    """
    Return a Document object for a single note instance.
    """
    note = notes[identifier]
    return Document(
        url='/' + identifier,
        title='Note',
        content={
            'description':
            note['description'],
            'complete':
            note['complete'],
            'edit':
            Link(action='put',
                 fields=[Field(name='description'),
                         Field(name='complete')]),
            'delete':
            Link(action='delete')
        })
示例#8
0
def test_post(monkeypatch, http):
    def mockreturn(self, request):
        codec = CoreJSONCodec()
        body = force_text(request.body)
        content = codec.encode(Document(content={'data': json.loads(body)}))
        return MockResponse(content)

    monkeypatch.setattr(requests.Session, 'send', mockreturn)

    link = Link(url='http://example.org', action='post')
    doc = http.transition(link, decoders, params={'example': 'abc'})
    assert doc == {'data': {'example': 'abc'}}
示例#9
0
def test_get_with_path_parameter(monkeypatch, http):
    def mockreturn(self, request):
        insert = request.url.encode('utf-8')
        return MockResponse(b'{"_type": "document", "example": "' + insert +
                            b'"}')

    monkeypatch.setattr(requests.Session, 'send', mockreturn)

    link = Link(url='http://example.org/{user_id}/',
                action='get',
                fields=[Field(name='user_id', location='path')])
    doc = http.transition(link, decoders, params={'user_id': 123})
    assert doc == {'example': 'http://example.org/123/'}
示例#10
0
def _get_link_from_method(method):
    spore_name, spore_method = method
    action, *keys = spore_name.split('_')
    link = Link(url=spore_method.get('path'),
                action=spore_method.get('method').lower(),
                title=spore_method.get(
                    'description',
                    spore_name.replace('_', ' ').capitalize()),
                authentication=spore_method.get('authentication', False),
                formats=spore_method.get('formats', []),
                fields=_get_fields_from_method(spore_method),
                description=spore_method.get('documentation', ''))
    return action, keys, link
示例#11
0
def get_notes():
    """
    Return the top level Document object, containing all the note instances.
    """
    return Document(
        url='/',
        title='Notes',
        content={
            'notes':
            [get_note(identifier) for identifier in reversed(notes.keys())],
            'add_note':
            Link(action='post',
                 fields=[Field(name='description', required=True)])
        })
示例#12
0
def doc():
    return Document(url='http://example.org',
                    title='Example',
                    content={
                        'integer':
                        123,
                        'dict': {
                            'key': 'value'
                        },
                        'list': [1, 2, 3],
                        'link':
                        Link(url='/',
                             action='post',
                             transform='inplace',
                             fields=[
                                 'optional',
                                 Field('required',
                                       required=True,
                                       location='path')
                             ]),
                        'nested': {
                            'child': Link(url='/123')
                        }
                    })
示例#13
0
def get_link(route: Route) -> Link:
    """
    Given a single route, return a Link instance containing all the information
    needed to expose that route in an API Schema.
    """
    path, method, view = route

    view_signature = inspect.signature(view)
    uritemplate = URITemplate(path)

    description = _get_link_description(view)

    fields = []
    for param in view_signature.parameters.values():

        if param.annotation is inspect.Signature.empty:
            annotated_type = str
        else:
            annotated_type = param.annotation

        location = None
        required = False
        param_schema = _annotated_type_to_coreschema(annotated_type)
        if param.name in uritemplate.variable_names:
            location = 'path'
            required = True
        elif (annotated_type in primitive_types) or issubclass(
                annotated_type, schema_types):
            if method in ('POST', 'PUT', 'PATCH'):
                if issubclass(annotated_type, schema.Object):
                    location = 'body'
                    required = True
                else:
                    location = 'form'
            else:
                location = 'query'

        if location is not None:
            field = Field(name=param.name,
                          location=location,
                          required=required,
                          schema=param_schema)
            fields.append(field)

    return Link(url=path,
                action=method,
                description=description,
                fields=fields)
示例#14
0
    def get_response_object(self, response_serializer_class, description):

        fields = []
        serializer = response_serializer_class()
        nested_obj = {}

        for field in serializer.fields.values():
            if isinstance(field, serializers.Serializer):
                nested_obj[field.field_name] = self.get_response_object(
                    field.__class__, None)[0]['schema']
                nested_obj[field.field_name]['description'] = field.help_text
                continue

            fields.append(
                Field(name=field.field_name,
                      location='form',
                      required=field.required,
                      schema=field_to_schema(field)))

        res = _get_parameters(Link(fields=fields), None)

        if not res:
            if nested_obj:
                return {
                    'description': description,
                    'schema': {
                        'type': 'object',
                        'properties': nested_obj
                    }
                }, {}
            else:
                return {}, {}

        schema = res[0]['schema']
        schema['properties'].update(nested_obj)
        response_schema = {'description': description, 'schema': schema}

        error_status_codes = {}

        response_meta = getattr(response_serializer_class, 'Meta', None)

        for status_code, description in getattr(response_meta,
                                                'error_status_codes',
                                                {}).items():
            error_status_codes[status_code] = {'description': description}

        return response_schema, error_status_codes
示例#15
0
 def test_mocking(self):
     content = {
         'test': {
             'post_data':
             Link(url='/post_data/',
                  action='post',
                  fields=[Field('data', location='body')]),
         }
     }
     schema = Document(title='test', content=content)
     mock.add(schema, ['test', 'post_data'], {"a": 1})
     client = DjangoCoreAPIClient()
     doc = client.action(schema, ['test', 'post_data'],
                         params={'data': {
                             'test': 'cat'
                         }})
     self.assertEqual(doc, {"a": 1})
示例#16
0
    def test_post_data(self):
        content = {
            'test': {
                'post_data':
                Link(url='/post_data/',
                     action='post',
                     fields=[Field('data', location='body')]),
            }
        }
        schema = Document(title='test', content=content)

        client = DjangoCoreAPIClient()
        doc = client.action(schema, ['test', 'post_data'],
                            params={'data': {
                                'test': 'cat'
                            }})
        self.assertIsNotNone(doc)
示例#17
0
 def get_link(self, path, method, base_url):
     link = super().get_link(path, method, base_url)
     fields = [
         Field('time_type',
               location='query',
               required=True,
               schema=coreschema.Enum(enum=['year', 'month'])),
         Field('time_value',
               location='query',
               required=True,
               schema=coreschema.String()),
     ]
     fields = tuple(fields)
     link = Link(url=link.url,
                 action=link.action,
                 encoding=link.encoding,
                 fields=fields,
                 description=link.description)
     document.Link()
     return link
示例#18
0
    def get_link(self, path, method, base_url):
        link = super().get_link(path, method, base_url)
        # 无法指定bill_ids数组中的元素类型,这里元素定义为int但实际为str,无法处理...
        batch_del_fields = [
            Field('bill_ids',
                  location='form',
                  required=True,
                  schema=coreschema.Array(items=coreschema.Integer(),
                                          unique_items=True))
        ]
        fields = link.fields
        if link.url == '/api/v1/bills/batch/' and method.lower() == 'delete':
            fields = tuple(batch_del_fields)

        link = Link(url=link.url,
                    action=link.action,
                    encoding=link.encoding,
                    fields=fields,
                    description=link.description)
        document.Link()
        return link
示例#19
0
def test_document_data_and_links_properties():
    doc = Document(content={'a': 1, 'b': 2, 'c': Link(), 'd': Link()})
    assert sorted(list(doc.data.keys())) == ['a', 'b']
    assert sorted(list(doc.links.keys())) == ['c', 'd']
示例#20
0
def test_object_data_and_links_properties():
    obj = Object({'a': 1, 'b': 2, 'c': Link(), 'd': Link()})
    assert sorted(list(obj.data.keys())) == ['a', 'b']
    assert sorted(list(obj.links.keys())) == ['c', 'd']
示例#21
0
from coreapi import Document, Link, Field

CONTENT_BASE_URL = '/api/v1/content/'

SCHEMA = Document(
    title='YouTube Lab API',
    content={
        'Content Source': {
            'list_all_sources':
            Link(
                url=CONTENT_BASE_URL + 'sources/',
                action='get',
                description="""
                    List all Content sources in the database

                    Returns a list with all playlists and channels in the database
                """,
            ),
            'add_new_source':
            Link(url=CONTENT_BASE_URL + 'sources/',
                 action='post',
                 description="""
                    Add a new content source ex. playlist

                    Provide a url to the playlist or channel you want to Crawl
                """,
                 fields=[
                     Field(
                         name='url',
                         required=True,
                         location='formData',
示例#22
0
def _parse_document(data, base_url=None):
    schema_url = base_url
    base_url = _get_document_base_url(data, base_url)
    info = _get_dict(data, 'info')
    title = _get_string(info, 'title')
    paths = _get_dict(data, 'paths')
    content = {}
    for path in paths.keys():
        url = urlparse.urljoin(base_url, path.lstrip('/'))
        spec = _get_dict(paths, path)
        default_parameters = get_dicts(_get_list(spec, 'parameters'))
        for action in spec.keys():
            action = action.lower()
            if action not in ('get', 'put', 'post', 'delete', 'options',
                              'head', 'patch'):
                continue
            operation = _get_dict(spec, action)

            # Determine any fields on the link.
            fields = []
            parameters = get_dicts(_get_list(operation, 'parameters',
                                             default_parameters),
                                   dereference_using=data)
            for parameter in parameters:
                name = _get_string(parameter, 'name')
                location = _get_string(parameter, 'in')
                required = _get_bool(parameter,
                                     'required',
                                     default=(location == 'path'))
                description = _get_string(parameter, 'description')
                if location == 'body':
                    schema = _get_dict(parameter,
                                       'schema',
                                       dereference_using=data)
                    expanded = _expand_schema(schema)
                    if expanded is not None:
                        expanded_fields = [
                            Field(name=field_name,
                                  location='form',
                                  required=is_required,
                                  description=description)
                            for field_name, is_required in expanded if
                            not any([field.name == name for field in fields])
                        ]
                        fields += expanded_fields
                    else:
                        field = Field(name=name,
                                      location='body',
                                      required=True,
                                      description=description)
                        fields.append(field)
                else:
                    field = Field(name=name,
                                  location=location,
                                  required=required,
                                  description=description)
                    fields.append(field)
            link = Link(url=url, action=action, fields=fields)

            # Add the link to the document content.
            tags = get_strings(_get_list(operation, 'tags'))
            operation_id = _get_string(operation, 'operationId')
            if tags:
                for tag in tags:
                    if tag not in content:
                        content[tag] = {}
                    content[tag][operation_id] = link
            else:
                content[operation_id] = link

    return Document(url=schema_url, title=title, content=content)
示例#23
0
文件: decode.py 项目: Karim0/sport
def _parse_document(data, base_url=None):
    schema_url = base_url
    base_url = _get_document_base_url(data, base_url)
    info = _get_dict(data, 'info')
    title = _get_string(info, 'title')
    description = _get_string(info, 'description')
    consumes = get_strings(_get_list(data, 'consumes'))
    paths = _get_dict(data, 'paths')
    content = {}
    for path in paths.keys():
        url = base_url + path.lstrip('/')
        spec = _get_dict(paths, path)
        default_parameters = get_dicts(_get_list(spec, 'parameters'))
        for action in spec.keys():
            action = action.lower()
            if action not in ('get', 'put', 'post', 'delete', 'options',
                              'head', 'patch'):
                continue
            operation = _get_dict(spec, action)

            # Determine any fields on the link.
            has_body = False
            has_form = False

            fields = []
            parameters = get_dicts(_get_list(operation, 'parameters',
                                             default_parameters),
                                   dereference_using=data)
            for parameter in parameters:
                name = _get_string(parameter, 'name')
                location = _get_string(parameter, 'in')
                required = _get_bool(parameter,
                                     'required',
                                     default=(location == 'path'))
                if location == 'body':
                    has_body = True
                    schema = _get_dict(parameter,
                                       'schema',
                                       dereference_using=data)
                    expanded = _expand_schema(schema)
                    if expanded is not None:
                        # TODO: field schemas.
                        expanded_fields = [
                            Field(name=field_name,
                                  location='form',
                                  required=is_required,
                                  schema=coreschema.String(
                                      description=field_description))
                            for field_name, is_required, field_description in
                            expanded if not any(
                                [field.name == field_name for field in fields])
                        ]
                        fields += expanded_fields
                    else:
                        # TODO: field schemas.
                        field_description = _get_string(
                            parameter, 'description')
                        field = Field(name=name,
                                      location='body',
                                      required=required,
                                      schema=coreschema.String(
                                          description=field_description))
                        fields.append(field)
                else:
                    if location == 'formData':
                        has_form = True
                        location = 'form'
                    field_description = _get_string(parameter, 'description')
                    # TODO: field schemas.
                    field = Field(name=name,
                                  location=location,
                                  required=required,
                                  schema=coreschema.String(
                                      description=field_description))
                    fields.append(field)

            link_consumes = get_strings(
                _get_list(operation, 'consumes', consumes))
            encoding = ''
            if has_body:
                encoding = _select_encoding(link_consumes)
            elif has_form:
                encoding = _select_encoding(link_consumes, form=True)

            link_title = _get_string(operation, 'summary')
            link_description = _get_string(operation, 'description')
            link = Link(url=url,
                        action=action,
                        encoding=encoding,
                        fields=fields,
                        title=link_title,
                        description=link_description)

            # Add the link to the document content.
            tags = get_strings(_get_list(operation, 'tags'))
            operation_id = _get_string(operation, 'operationId')
            if tags:
                tag = tags[0]
                prefix = tag + '_'
                if operation_id.startswith(prefix):
                    operation_id = operation_id[len(prefix):]
                if tag not in content:
                    content[tag] = {}
                content[tag][operation_id] = link
            else:
                content[operation_id] = link

    return Document(url=schema_url,
                    title=title,
                    description=description,
                    content=content,
                    media_type='application/openapi+json')
示例#24
0
    Route('/static/{path}', 'GET', serve_static)
]

app = App(routes=routes)

client = TestClient(app)

expected = Schema(
    url='/schema/',
    content={
        'list_todo':
        Link(url='/todo/',
             action='GET',
             description='list_todo description',
             fields=[
                 Field(name='search',
                       location='query',
                       required=False,
                       schema=coreschema.String())
             ]),
        'add_todo':
        Link(url='/todo/',
             action='POST',
             description='add_todo description\nMultiple indented lines',
             fields=[
                 Field(name='note',
                       location='body',
                       required=True,
                       schema=coreschema.String())
             ]),
        'show_todo':
示例#25
0
def test_dotted_path_notation_with_invalid_key():
    doc = Document(content={'rows': [Document(content={'edit': Link()})]})
    keys = coerce_key_types(doc, ['dummy', '0', 'edit'])
    assert keys == ['dummy', '0', 'edit']
示例#26
0
def test_dotted_path_notation_with_invalid_array_lookup():
    doc = Document(content={'rows': [Document(content={'edit': Link()})]})
    keys = coerce_key_types(doc, ['rows', 'zero', 'edit'])
    assert keys == ['rows', 'zero', 'edit']
示例#27
0
def test_dotted_path_notation():
    doc = Document(content={'rows': [Document(content={'edit': Link()})]})
    keys = coerce_key_types(doc, ['rows', 0, 'edit'])
    assert keys == ['rows', 0, 'edit']
def test_html_link_rendering():
    doc = Document(content={'link': Link(url='/test/')})
    content = HTMLCodec().dump(doc)
    assert 'coreapi-link' in content
    assert 'href="/test/"' in content
示例#29
0
def test_link_does_not_support_property_assignment():
    link = Link()
    with pytest.raises(TypeError):
        link.integer = 456
示例#30
0
 def to_representation(self, value):
     url = super(CoreLinkField, self).to_representation(value)
     return Link(url=url, action=self.action, fields=self.fields, transition=self.transition)
示例#31
0
    'register':
    Link(url=BASE_AUTH_URL + 'users/create/',
         action='post',
         description="""
            Register a new user

            Note: You have to activate your email address, before logging in.
        """,
         fields=[
             Field(
                 name='email',
                 required=True,
                 location='formData',
             ),
             Field(
                 name='password',
                 required=True,
                 location='formData',
             ),
             Field(
                 name='first_name',
                 required=False,
                 location='formData',
             ),
             Field(
                 name='last_name',
                 required=False,
                 location='formData',
             ),
         ]),
    'activate':