Exemple #1
0
    def action(self,
               document,
               keys,
               params=None,
               action=None,
               encoding=None,
               transform=None):
        if isinstance(keys, string_types):
            keys = [keys]

        # Validate the keys and link parameters.
        link, link_ancestors = _lookup_link(document, keys)

        if (action is not None) or (encoding is not None) or (transform
                                                              is not None):
            # Handle any explicit overrides.
            action = link.action if (action is None) else action
            encoding = link.encoding if (encoding is None) else encoding
            transform = link.transform if (transform is None) else transform
            link = Link(link.url,
                        action=action,
                        encoding=encoding,
                        transform=transform,
                        fields=link.fields)

        # Perform the action, and return a new document.
        transport = determine_transport(self.transports, link.url)
        return transport.transition(link,
                                    self.decoders,
                                    params=params,
                                    link_ancestors=link_ancestors)
Exemple #2
0
    def reload(self, document):
        url = _make_absolute(document.url)
        link = Link(url, action='get')

        # Perform the action, and return a new document.
        transport = determine_transport(link.url, transports=self.transports)
        return transport.transition(link, decoders=self.decoders)
Exemple #3
0
    def get(self, url, force_codec=False):
        link = Link(url, action='get')

        # Perform the action, and return a new document.
        transport = determine_transport(self.transports, link.url)
        return transport.transition(link,
                                    self.decoders,
                                    force_codec=force_codec)
def _primative_to_document(data, base_url=None):
    """
    Take Python primatives as returned from parsing JSON content,
    and return a Core API document.
    """
    if isinstance(data, dict) and data.get('_type') == 'document':
        # Document
        meta = _get_dict(data, '_meta')
        url = _get_string(meta, 'url')
        url = urlparse.urljoin(base_url, url)
        title = _get_string(meta, 'title')
        content = _get_content(data, base_url=url)
        return Document(url=url, title=title, content=content)

    if isinstance(data, dict) and data.get('_type') == 'error':
        # Error
        meta = _get_dict(data, '_meta')
        title = _get_string(meta, 'title')
        content = _get_content(data, base_url=base_url)
        return Error(title=title, content=content)

    elif isinstance(data, dict) and data.get('_type') == 'link':
        # Link
        url = _get_string(data, 'url')
        url = urlparse.urljoin(base_url, url)
        action = _get_string(data, 'action')
        encoding = _get_string(data, 'encoding')
        transform = _get_string(data, 'transform')
        description = _get_string(data, 'description')
        fields = _get_list(data, 'fields')
        fields = [
            Field(name=_get_string(item, 'name'),
                  required=_get_bool(item, 'required'),
                  location=_get_string(item, 'location'),
                  type=_get_string(item, 'type'),
                  description=_get_string(item, 'description'))
            for item in fields if isinstance(item, dict)
        ]
        return Link(url=url,
                    action=action,
                    encoding=encoding,
                    transform=transform,
                    description=description,
                    fields=fields)

    elif isinstance(data, dict):
        # Map
        content = _get_content(data, base_url=base_url)
        return Object(content)

    elif isinstance(data, list):
        # Array
        content = [_primative_to_document(item, base_url) for item in data]
        return Array(content)

    # String, Integer, Number, Boolean, null.
    return data
Exemple #5
0
    def action(
        self,
        document,
        keys,
        params=None,
        validate=True,
        overrides=None,
        action=None,
        encoding=None,
        transform=None,
    ):
        if (action is not None) or (encoding is not None) or (transform
                                                              is not None):
            # Fallback for v1.x overrides.
            # Will be removed at some point, most likely in a 2.1 release.
            if overrides is None:
                overrides = {}
            if action is not None:
                overrides["action"] = action
            if encoding is not None:
                overrides["encoding"] = encoding
            if transform is not None:
                overrides["transform"] = transform

        if isinstance(keys, string_types):
            keys = [keys]

        if params is None:
            params = {}

        # Validate the keys and link parameters.
        link, link_ancestors = _lookup_link(document, keys)
        if validate:
            _validate_parameters(link, params)

        if overrides:
            # Handle any explicit overrides.
            url = overrides.get("url", link.url)
            action = overrides.get("action", link.action)
            encoding = overrides.get("encoding", link.encoding)
            transform = overrides.get("transform", link.transform)
            fields = overrides.get("fields", link.fields)
            link = Link(
                url,
                action=action,
                encoding=encoding,
                transform=transform,
                fields=fields,
            )

        # Perform the action, and return a new document.
        transport = determine_transport(self.transports, link.url)
        return transport.transition(link,
                                    self.decoders,
                                    params=params,
                                    link_ancestors=link_ancestors)
def doc():
    return Document(url='http://example.org/',
                    title='Example',
                    content={
                        'integer':
                        123,
                        'dict': {
                            'key': 'value'
                        },
                        'list': [1, 2, 3],
                        'link':
                        Link(url='http://example.org/',
                             fields=[Field(name='example')]),
                        'nested': {
                            'child': Link(url='http://example.org/123')
                        },
                        '_type':
                        'needs escaping'
                    })
Exemple #7
0
def _parse_link(data, base_url=None):
    url = _get_string(data, 'href')
    url = urlparse.urljoin(base_url, url)
    if _get_bool(data, 'templated'):
        fields = [
            Field(name, location='path') for name in uritemplate.variables(url)
        ]
    else:
        fields = None
    return Link(url=url, fields=fields)
Exemple #8
0
    def get(self, url, format=None, force_codec=False):
        link = Link(url, action='get')

        decoders = self.decoders
        if format:
            decoders = [decoder for decoder in self.decoders if decoder.format == format]
            if not decoders:
                raise ValueError("No decoder available with format='%s'" % format)

        # Perform the action, and return a new document.
        transport = determine_transport(self.transports, link.url)
        return transport.transition(link, decoders, force_codec=force_codec)
Exemple #9
0
def _get_content(data, base_url, ref):
    content = {}
    links = _get_list(data, 'links')
    properties = _get_dict(data, 'properties')

    if properties:
        for key, value in properties.items():
            if not isinstance(value, dict):
                continue
            if list(value.keys()) == ['$ref']:
                value = _dereference(value['$ref'], ref)
            sub_content = _get_content(value, base_url, ref)
            if sub_content:
                content[key] = sub_content
    if links:
        for link in get_dicts(links):
            rel = _get_string(link, 'rel')
            if rel:
                href = _get_string(link, 'href')
                method = _get_string(link, 'method')
                schema = _get_dict(link, 'schema')
                schema_type = _get_list(schema, 'type')
                schema_properties = _get_dict(schema, 'properties')
                schema_required = _get_list(schema, 'required')

                fields = []
                url = urlparse.urljoin(base_url, href)
                templated = uritemplate.variables(url)
                for item in templated:
                    orig = item
                    if item.startswith('(') and item.endswith(')'):
                        item = unquote(item.strip('(').rstrip(')'))
                    if item.startswith('#/'):
                        components = [
                            component
                            for component in item.strip('#/').split('/')
                            if component != 'definitions'
                        ]
                    item = '_'.join(components).replace('-', '_')
                    url = url.replace(orig, item)
                    fields.append(
                        Field(name=item, location='path', required=True))

                if schema_type == ['object'] and schema_properties:
                    fields += [
                        Field(name=key, required=(key in schema_required))
                        for key in schema_properties.keys()
                    ]
                if rel == 'self':
                    rel = 'read'
                content[rel] = Link(url=url, action=method, fields=fields)

    return content
Exemple #10
0
def test_link_encodings(json_codec):
    doc = Document(
        content={
            'link':
            Link(action='post',
                 transform='inplace',
                 fields=[
                     'optional',
                     Field('required', required=True, location='path')
                 ])
        })
    bytes = json_codec.encode(doc, indent=True)
    assert bytes == b"""{
Exemple #11
0
def doc():
    return Document(url='http://example.org/',
                    title='Example',
                    content={
                        'integer':
                        123,
                        'dict': {
                            'key': 'value'
                        },
                        'list': [1, 2, 3],
                        'link':
                        Link(url='http://example.org/',
                             fields=[
                                 Field(name='noschema'),
                                 Field(name='string_example', schema=String()),
                                 Field(name='enum_example',
                                       schema=Enum(['a', 'b', 'c'])),
                             ]),
                        'nested': {
                            'child': Link(url='http://example.org/123')
                        },
                        '_type':
                        'needs escaping'
                    })
Exemple #12
0
    def get(self, url, format=None, force_codec=False):
        link = Link(url, action="get")

        decoders = self.decoders
        if format:
            force_codec = True
            decoders = [
                decoder for decoder in self.decoders
                if decoder.format == format
            ]
            if not decoders:
                installed_codecs = get_installed_codecs()
                if format in installed_codecs:
                    decoders = [installed_codecs[format]]
                else:
                    raise ValueError("No decoder available with format='%s'" %
                                     format)

        # Perform the action, and return a new document.
        transport = determine_transport(self.transports, link.url)
        return transport.transition(link, decoders, force_codec=force_codec)
Exemple #13
0
def test_invalid_link_fields_ignored(json_codec):
    doc = json_codec.decode(
        b'{"_type": "document", "link": {"_type": "link", "fields": 1}}')
    assert doc == Document(content={"link": Link()})
Exemple #14
0
def _primitive_to_document(data, base_url=None):
    """
    Take Python primitives as returned from parsing JSON content,
    and return a Core API document.
    """
    if isinstance(data, dict) and data.get("_type") == "document":
        # Document
        meta = _get_dict(data, "_meta")
        url = _get_string(meta, "url")
        url = urlparse.urljoin(base_url, url)
        title = _get_string(meta, "title")
        description = _get_string(meta, "description")
        content = _get_content(data, base_url=url)
        return Document(
            url=url,
            title=title,
            description=description,
            media_type="application/coreapi+json",
            content=content,
        )

    if isinstance(data, dict) and data.get("_type") == "error":
        # Error
        meta = _get_dict(data, "_meta")
        title = _get_string(meta, "title")
        content = _get_content(data, base_url=base_url)
        return Error(title=title, content=content)

    elif isinstance(data, dict) and data.get("_type") == "link":
        # Link
        url = _get_string(data, "url")
        url = urlparse.urljoin(base_url, url)
        action = _get_string(data, "action")
        encoding = _get_string(data, "encoding")
        transform = _get_string(data, "transform")
        title = _get_string(data, "title")
        description = _get_string(data, "description")
        fields = _get_list(data, "fields")
        fields = [
            Field(
                name=_get_string(item, "name"),
                required=_get_bool(item, "required"),
                location=_get_string(item, "location"),
                schema=_get_schema(item, "schema"),
            ) for item in fields if isinstance(item, dict)
        ]
        return Link(
            url=url,
            action=action,
            encoding=encoding,
            transform=transform,
            title=title,
            description=description,
            fields=fields,
        )

    elif isinstance(data, dict):
        # Map
        content = _get_content(data, base_url=base_url)
        return Object(content)

    elif isinstance(data, list):
        # Array
        content = [_primitive_to_document(item, base_url) for item in data]
        return Array(content)

    # String, Integer, Number, Boolean, null.
    return data
Exemple #15
0
def test_invalid_link_url_ignored(json_codec):
    doc = json_codec.load(
        b'{"_type": "document", "link": {"_type": "link", "url": 1}}')
    assert doc == Document(content={"link": Link()})