Skip to content

Advanced Usage

Changing session configurations

It is possible to change details of how a client talks to the various servers it needs to interface with. For instance, the CAVEclient will attempt to retry specific failed requests to the server, but will only try a specific number of times, and will only wait specific amounts of time between retries. These values can be changed via the set_session_defaults method. For instance, to change the number of retries to 5, and to increase the delay between subsequent retries, you could do:

from caveclient import set_session_defaults

set_session_defaults(max_retries=5, backoff_factor=0.5)

Note that this needs to happen before initializing the client for this to work properly. Some of these parameters are also adjustable at the client level.

To view the current session defaults, you can use the get_session_defaults method:

from caveclient import get_session_defaults

client.get_session_defaults()

More information on the available parameters can be found in the API documentation.

Writing unit tests using caveclient

If you have a module that relies on caveclient and you want to write unit tests for it, you can use the caveclient.testing module to help you create an initialized, mocked client with user-specified options. This helps deal with the complex conversation that caveclient has with various services when initializing itself so that you get the appropriate functionality. The function CAVEclientMock offers a number of options for how to build a client, including server versions for various services, available API versions, and more. Importantly, the module provides sensible defaults but also allows you to override them as needed. Note that using testing requires the responses to be installed, which is not a dependency of caveclient.

The CAVEclientMock function requires you to specify which services you expect to call on in order to ensure that your code is working as expected. For example, to create a pytest fixture that would utilize the chunkedgraph module, but otherwise use default nonsense test values, you could include this in your conftest.py:

import pytest
from caveclient.tools.testing import CAVEclientMock

@pytest.fixture()
def test_client():
    return CAVEclientMock(
        chunkedgraph=True,
    )

Then, in your test module, you can use the test_client fixture to get a client. Note that after mocked initialization, the client will attempt normal network requests and thus you should mock the responses. If you only care to get a specific value back from a given function, you can use pytest-mock to mock the response to a given function call. For example, if you have a function do_something_with_roots that takes a caveclient that uses the get_roots function, you could mock the get_roots function so that it return a specific value:

from pytest_mock import mocker
from conftest import test_client
from my_module import do_something_with_roots

def test_get_roots(mocker, test_client):
    mocker.patch.object(test_client.chunkedgraph, 'get_roots', return_value=[1, 2, 3])
    test_data = # Something appropriate
    test_output = do_something_with_roots(test_client, test_data)
    assert test_output == # The expected answer

Note that if you your own datastack info_file that has a different local_server address than the default value (TEST_LOCAL_SERVER variable, which defaults to https://local.cave.com) you will also need to specify a local_server with the same value as in the local_server field of your info file.

Specifying conditions

While sensible defaults are provided, you can also specify things like server versions to make sure your code works with the versions of the services you expect. For example, let's make a richer mock client that specifies the server versions for the chunkedgraph, materailization, and l2cache services:

@pytest.fixture()
def version_specified_client():
    return CAVEclientMock(
        chunkedgraph=True,
        chunkedgraph_server_version='3.0.1',
        materialization=True,
        materialization_server_version='2.0.0',
        l2cache=True,
    )

Note that some services like l2cache do not currently use a server version to offer different functionality, and this value is not exposed for them currently. See the API documentation for more information.

You can also override default values like server_address or datastack_name:

@pytest.fixture()
def server_specified_client():
    return CAVEclientMock(
        datastack_name='my_datastack',
        server_address='http://my.server.com',
        chunkedgraph=True,
        materialization=True,
    )

If you want to get access to the various default values of server version, datastack name, datastack info file, and api versions, you can use functions get_server_versions, get_server_information, default_info, get_api_versions respectively. Each of these functions will return a dictionary of the values that can be used as a kwargs input into CAVEclientMock. If you specify your own override values, it will take precedence over the default value and you can just use the dictionary in your tests. See the caveclient tests for an example of how to use these functions.