Codecs

Codecs are responsible for decoding a bytestring into a Document instance, or for encoding a Document instance into a bytestring.

A codec is associated with a media type. For example in HTTP responses, the Content-Type header is used to indicate the media type of the bytestring returned in the body of the response.

When using a Core API client, HTTP responses are decoded with an appropriate codec, based on the Content-Type of the response.

Using a codec

All the codecs provided by the coreapi library are instantiated without arguments, for example:

from coreapi import codecs

codec = codecs.CoreJSONCodec()

A codec will provide either one or both of the decode() or encode() methods.

Decoding

Signature: decode(bytestring, **options)

Given a bytestring, returns a decoded Document, Error, or raw data.

An example of decoding a document:

bytestring = open('document.corejson', 'rb').read()
document = codec.decode(bytestring)

The available options keywords depend on the codec.

Encoding

Signature: encode(document, **options)

Given a Document or Error, return an encoded representation as a bytestring.

An example of encoding a document:

bytestring = codec.encode(document)
output = open('document.corejson', 'wb')
output.write(bytestring)
output.close()

The available options keywords depend on the codec.

Attributes

The following attribute is available on codec instances:


Available codecs

CoreJSONCodec

Supports decoding or encoding the Core JSON format.

.media_type: application/coreapi+json .format: openapi

Example of decoding a Core JSON bytestring into a Document instance:

>>> from coreapi import codecs
>>> codec = codecs.CoreJSONCodec()
>>> content = b'{"_type": "document", ...}'
>>> document = codec.decode(content)
>>> print(document)
<Flight Search API 'http://api.example.com/'>
    'search': link(from, to, date)

Example of encoding a Document instance into a Core JSON bytestring:

>>> content = codec.encode(document, indent=True)
>>> print(content)
{
    "_type": "document"
}

Encoding options

indent: Set to True for an indented representation. The default is to generate a compact representation.

Decoding options

base_url: The URL from which the document was retrieved. Used to resolve any relative URLs in the document.


JSONCodec

Supports decoding JSON data.

.media_type: application/json .format: json

Example:

>>> from coreapi import codecs
>>> codec = codecs.JSONCodec()
>>> content = b'{"string": "abc", "boolean": true, "null": null}'
>>> data = codec.decode(content)
>>> print(data)
{"string": "abc", "boolean": True, "null": None}

TextCodec

Supports decoding plain-text responses.

.media_type: text/* .format: text

Example:

>>> from coreapi import codecs
>>> codec = codecs.TextCodec()
>>> data = codec.decode(b'hello, world!')
>>> print(data)
hello, world!

DownloadCodec

Supports decoding arbitrary media as a download file. Returns a temporary file that will be deleted once it goes out of scope.

.media_type: */* .format: download

Example:

>>> codec = codecs.DownloadCodec()
>>> download = codec.decode(b'abc...xyz')
>>> print(download)
<DownloadedFile '.../tmpYbxNXT.download', open 'rb'>
>>> content = download.read()
>>> print(content)
abc...xyz

The download filename will be determined by either the Content-Disposition header, or based on the request URL and the Content-Type header. Download collisions are avoided by using incrementing filenames where required. The original name used for the download file can be inspected using .basename.

>>> download = codec.decode(b'abc...xyz', content_type='image/png', base_url='http://example.com/download/')
>>> download.name
'/var/folders/2k/qjf3np5s28zf2f58963pz2k40000gn/T/download.png'
>>> download.basename
'download.png'

Instantiation

By default this codec returns a temporary file that will be deleted once it goes out of scope. If you want to return temporary files that are not deleted when they go out of scope then you can instantiate the DownloadCodec with a download_dir argument.

For example, to download files to the current working directory:

>>> import os
>>> codecs.DownloadCodec(download_dir=os.getcwd())

Decoding options

base_url: The URL from which the document was retrieved. May be used to generate an output filename if no Content-Disposition header exists.

content_type: The response Content-Type header. May be used to determine a suffix for the output filename if no Content-Disposition header exists.

content_disposition: The response Content-Disposition header. May be used to indicate the download filename.


Custom codecs

Custom codec classes may be created by inheriting from BaseCodec, setting the media_type and format properties, and implementing one or both of the decode or encode methods.

For example:

from coreapi import codecs
import yaml

class YAMLCodec(codecs.BaseCodec):
    media_type = 'application/yaml'
    format = 'yaml'

    def decode(content, **options):
        return yaml.safe_load(content)

The codec registry

Tools such as the Core API command line client require a method of discovering which codecs are installed on the system. This is enabled by using a registry system.

In order to register a custom codec, the PyPI package must contain a correctly configured entry_points option. Typically this needs to be added in a setup.py module, which is run whenever publishing a new package version.

The entry_points option must be a dictionary, containing a coreapi.codecs item listing the available codec classes. As an example, the listing for the codecs which are registered by the coreapi package itself is as follows:

setup(
    name='coreapi',
    license='BSD',
    ...
    entry_points={
        'coreapi.codecs': [
            'corejson=coreapi.codecs:CoreJSONCodec',
            'json=coreapi.codecs:JSONCodec',
            'text=coreapi.codecs:TextCodec',
            'download=coreapi.codecs:DownloadCodec',
        ]
    }
)

External packages

The following third-party packages are available.

OpenAPI

A codec for OpenAPI schemas, also known as "Swagger". Installable from PyPI as openapi-codec, and available on GitHub.

JSON Hyper-Schema

A codec for JSON Hyper-Schema. Installable from PyPI as jsonhyperschema-codec, and available on GitHub.

HAL

A codec for the HAL hypermedia format. Installable from PyPI as hal-codec, and available on GitHub.