Tools for DOS Implementations

The ga4gh.dos package contains some utilities that can help you develop a compliant DOS resolver.

Dynamic /swagger.json with Chalice

If you’re using Chalice, you can expose a subset of the Data Object Service schema using ga4gh.dos.schema.from_chalice_routes():

from chalice import Chalice
app = Chalice(...)

@app.route('/swagger.json')
def swagger():
    return ga4gh.dos.schema.from_chalice_routes(app.routes)

With the above code, a GET request to /swagger.json will return a schema in the Swagger / OpenAPI 2 format that correctly lists only the endpoints that are exposed by your app.

If you have a different basePath, you can also specify that:

@app.route('/swagger.json')
def swagger():
    return ga4gh.dos.schema.from_chalice_routes(app.routes, base_path='/api')

Compliance testing

This package contains a testing suite (AbstractComplianceTest) that streamlines testing implementations of the Data Object Service for compliance with the DOS schema.

This test suite is meant to supplement, and not replace, an existing test suite. It does not:

  • test authentication
  • test health of the service(s) underpinning an implementation
  • test any endpoints not defined in the Data Object Service schema
class ga4gh.dos.test.compliance.AbstractComplianceTest(methodName='runTest')[source]

This class implements a number of compliance tests for Data Object Service implementations. It is meant to provide a single, standardized test harness to verify that a given DOS implementation acts in a manner consistent with the schema.

Using the test harness is pretty straightforward, and only requires implementing a method that can make requests to the service under test (_make_request()). As this class subclasses unittest.TestCase, all the functions exposed to a subclass of unittest.TestCase (e.g. setUpClass()) are available for use.

This test suite does not perform any authentication testing. Requests made during testing are made with the assumption that they will be properly authenticated in _make_request() or similar.

For a service built using Chalice, you would likely be able to write something similar to this:

from ga4gh.dos.test.compliance import AbstractComplianceTest
from chalice import LocalGateway, Config
from my_chalice_app import chalice_app

class TestApp(AbstractComplianceTest):
    @classmethod
    def setUpClass(cls):
        cls.lg = LocalGateway(chalice_app, Config())

    @classmethod
    def _make_request(self, meth, path, headers=None, body=None)
        headers = headers or {}
        r = self.lg.handle_request(method=meth, path='/ga4gh/dos/v1' + path,
                                   headers=headers, body=body)
        return r['body'], r['statusCode']

You would then be able to run the compliance test suite however you normally run your tests (e.g. nosetests or python -m unittest discover).

Variables:supports

a list of supported DOS operations. By default, this is the list of all DOS operations, named by the operationId key in the schema:

supports = ['GetServiceInfo', 'GetDataBundleVersions',
            'CreateDataBundle', 'ListDataBundles',
            'UpdateDataObject', 'GetDataObject', ...]

Adding / removing operations from this list will adjust which tests are run. So, doing something like:

class Test(AbstractComplianceTest):
    self.supports = ['ListDataObjects']

would skip all tests calling UpdateDataBundle, GetDataBundle, and any other endpoint that is not ListDataObjects.

classmethod _make_request(meth, path, headers=None, body=None)[source]

Method that makes requests to a DOS implementation under test given a method, path, request headers, and a request body.

The provided path is the path provided in the Data Object Service schema - this means that in your implementation of this method, you might need to prepend the provided path with your basePath, e.g. /ga4gh/dos/v1.

This method should return a tuple of the raw request content as a string and the return code of the request as an int.

Parameters:
  • meth (str) – the HTTP method to use in the request (i.e. GET, PUT, etc.)
  • path (str) – path to make a request to, sans hostname (e.g. /databundles)
  • headers (dict) – headers to include with the request
  • body (dict) – data to be included in the request body (serialized as JSON)
Return type:

tuple

Returns:

a tuple of the response body as a JSON-formatted string and the response code as an int