Nanaimo (library)

nanaimo

This module contains the common types used by Nanaimo.

exception nanaimo.AssertionError[source]

Bases: RuntimeError

Thrown by Nanaimo tests when an assertion has failed.

Note

This exception should be used only when the state of a nanaimo.fixtures.Fixture was invalid. You should use pytest tests and assertions when writing validation cases for fixture output like log files or sensor data.

class nanaimo.Arguments(inner_arguments: Any, defaults: Optional[nanaimo.config.ArgumentDefaults] = None, required_prefix: Optional[str] = None, filter_duplicates: bool = False)[source]

Bases: object

Adapter for pytest and argparse parser arguments.

Parameters:
  • inner_arguments – Either a pytest group (unpublished type returned from pytest.Parser.getgroup()) or a argparse.ArgumentParser
  • defaults (typing.Optional[ArgumentDefaults]) – Optional provider of default values for arguments.
  • required_prefix (str) – If provided add_argument() will rewrite arguments to enure they have the required prefix.
  • filter_duplicates (bool) – If true then this class will track keys provided to the add_argument() method and will not call the inner object if duplicates are detected. If false then all calls to add_argument() are always forwarded to the inner object. This filter is tracked per instance so duplicates provided to different instances are not filtered.
set_inner_arguments(inner_arguments: Any) → None[source]

Reset the inner argument object this object wraps. This method allows a single instance to filter all arguments preventing duplicates from reading the inner objects.

a = Arguments(parser, filter_duplicates=True)
a.add_argument('--foo')

# This second call will not make it to the parser
# object we set above.
a.add_argument('--foo')

# If we set another parser on the same Arguments instance...
a.inner_arguments = my_other_parser

# then the same filter will continue to apply for this new
# inner argument object.
a.add_argument('--foo')
add_argument(*args, **kwargs) → None[source]

This method invokes argparse.ArgumentParser.add_argument() but with one additional argument: enable_default_from_environ. If this is provided as True then a default value will be taken from an environment variable derived from the long form of the argument:

# Using...
long_arg = '--baud-rate'

# ...the environment variable looked for will be:
environment_var_name = 'NANAIMO_BAUD_RATE'

# If we set the environment variable...
os.environ[environment_var_name] = '115200'

a = Arguments(parser, config)

# ...and provide a default...
a.add_argument('--baud-rate',
               default=9600,
               type=int,
               enable_default_from_environ=True,
               help='Will be 9600 unless argument is provided.')

# ...the actual default value will be 115200
assert add_argument_call_args['default'] == 115200
# Using a required prefix...
a = Arguments(parser, config, required_prefix='ad')

# ...and adding an argument...
a.add_argument('--baud-rate')

# ...the actual argument added will be
actual_long_arg = '--ad-baud-rate'
class nanaimo.Namespace(parent: Optional[Any] = None, defaults: Optional[nanaimo.config.ArgumentDefaults] = None, allow_none_values: bool = True)[source]

Bases: object

Generic object that acts like argparse.Namespace but can be created using pytest plugin arguments as well.

If nanaimo.config.ArgumentDefaults are used with the Arguments and this class then a given argument’s value will be resolved in the following order:

  1. provided value
  2. config file specified by –rcfile argument.
  3. nanaimo.cfg in user directory
  4. nanaimo.cfg in system directory
  5. default from environment (if enable_default_from_environ was set for the argument)
  6. default specified for the argument.

This is accomplished by first rewriting the defaults when attributes are defined on the Arguments class and then capturing missing attributes on this class and looking up default values from configuration files.

For lookup steps involving configuration files (where configparser.ConfigParser is used internally) the lookup will search the configuration space using underscores _ as namespace separators. this search will proceed as follows:

# given
key = 'a_b_c_d'

# the following lookups will occur
config_lookups = {
    'nanaimo:a_b_c': 'd',
    'nanaimo:a_b': 'c_d',
    'nanaimo:a': 'b_c_d',
    'a_b_c': 'd',
    'a_b': 'c_d',
    'a': 'b_c_d',
    'nanaimo': 'a_b_c_d'
}

# when using an ArgumentDefaults instance
_ = argument_defaults[key]

So for a given configuration file:

[nanaimo]
a_b_c_d = 1

[a]
b_c_d = 2

the value 2 under the a group will override (i.e. mask) the value 1 under the nanaimo group.

Note

A specific example:

  • --bk-port <value> – if provided on the commandline will always override everything.
  • [bk] port = <value> – in a config file will be found next if no argument was given on the commandline.
  • NANAIMO_BK_PORT - set in the environment will be used if no configuration was provided because the nanaimo.instruments.bkprecision module defines the bk-port argument with enable_default_from_environ set.

This object has a somewhat peculiar behavior for Python. All attributes will be reported either as a found value or as None. That is, any arbitrary attribute requested from this object will be None. To differentiate between None and “not set” you must using in:

ns = nanaimo.Namespace()
assert ns.foo is None
assert 'foo' not in ns

The behavior was designed to simplify argument handling code since argparse Namespaces will have None values for all arguments even if the were not provided and had no default value.

Parameters:
  • parent (typing.Optional[typing.Any]) – A namespace-like object to inherit attributes from.
  • defaults (typing.Optional[ArgumentDefaults]) – Defaults to use if a requested attribute is not available on this object.
  • allow_none_values (bool) – If True then an attribute with a None value is considered valid otherwise any attribute that is None will cause the Namespace to search for a non-None value in the defaults.
get_as_merged_dict(key: str) → Mapping[str, Any][source]

Expect the value to be a dictionary. In this case also load the defaults into the dictionary.

Parameters:key – The key to load the dictionary from.
merge(**kwargs) → T[source]

Merges a list of keyword arguments with this namespace and returns a new, merged Namespace. This does not modify the instance that merge is called on.

Example:

original = Namespace()
setattr(original, 'foo', 1)

assert 1 == original.foo

merged = original.merge(foo=2, bar='hello')

assert 1 == original.foo
assert 2 == merged.foo
assert 'hello' == merged.bar
Returns:A new namespace with the contents of this object and any values provided as kwargs overwriting the values in this instance where the keys are the same.
class nanaimo.Artifacts(result_code: int = 0, parent: Optional[Any] = None, defaults: Optional[nanaimo.config.ArgumentDefaults] = None, allow_none_values: bool = True)[source]

Bases: nanaimo.Namespace

Namespace returned by nanaimo.fixtures.Fixture objects when invoked that contains the artifacts collected from the fixture’s activities.

Parameters:
  • result_code – The value to report as the status of the activity that gathered the artifacts.
  • parent (typing.Optional[typing.Any]) – A namespace-like object to inherit attributes from.
  • defaults (typing.Optional[ArgumentDefaults]) – Defaults to use if a requested attribute is not available on this object.
  • allow_none_values (bool) – If True then an attribute with a None value is considered valid otherwise any attribute that is None will cause the Artifacts to search for a non-None value in the defaults.
classmethod combine(*artifacts) → nanaimo.Artifacts[source]

Combine a series of artifacts into a single instance. This method uses Namespace.merge() but adds additional semantics including:

Note

While this method does not modify the original objects it also does not do a deep copy of artifact values.

Given two Artifacts objects with the same attribute the right-most item in the combine list will overwrite the previous values and become the only value:

setattr(first, 'foo', 1)
setattr(second, 'foo', 2)

assert Artifacts.combine(first, second).foo == 2
assert Artifacts.combine(second, first).foo == 1

The result_code of the combined value will be either 0 iff all combined Artifact objects have a result_code of 0:

first.result_code = 0
second.result_code = 0

assert Artifacts.combine(first, second).result_code == 0

or will be non-zero if any instance had a non-zero result code:

first.result_code = 0
second.result_code = 1

assert Artifacts.combine(first, second).result_code != 0
Parameters:artifacts – A list of artifacts to combine into a single Artifacts instance.
Raises:ValueError – if no artifact objects were provided or if the method was otherwise unable to create a new object from the provided ones.
result_code

0 if the artifacts were retrieved without error. Non-zero if some error occurred. The contents of this Namespace is undefined for non-zero result codes.

dump(logger: logging.Logger, log_level: int = 10) → None[source]

Dump a human readable representation of this object to the given logger. :param logger: The logger to use. :param log_level: The log level to dump the object as.

nanaimo.assert_success(artifacts: nanaimo.Artifacts) → nanaimo.Artifacts[source]

Syntactic sugar to allow more fluent handling of fixtures.Fixture.gather() artifacts. For example:

async def test_my_fixture():

    artifacts = assert_success(await fixture.gather())

    # Now we can use the artifacts. If the gather had returned
    # non-zero for the result_code an assertion error would have
    # been raised.
Parameters:artifacts (nanaimo.Artifacts) – The artifacts to assert on.
Returns:artifacts (for convenience).
Return type:nanaimo.Artifacts()
nanaimo.assert_success_if(artifacts: nanaimo.Artifacts, conditional: Callable[[nanaimo.Artifacts], bool]) → nanaimo.Artifacts[source]

Syntactic sugar to allow more fluent handling of fixtures.Fixture.gather() artifacts but with a user-supplied conditional.

async def test_my_fixture():

    def fail_if_no_foo(artifacts: Artifacts) -> bool:
        return 'foo' in artifacts

    artifacts = assert_success_if(await fixture.gather(), fail_if_no_foo)

    print('artifacts have foo. It's value is {}'.format(artifacts.foo))
Parameters:
  • artifacts (nanaimo.Artifacts) – The artifacts to assert on.
  • conditiona – A method called to evaluate gathered artifacts iff Artifacts.result_code is 0. Return False to trigger an assertion, True to pass.
Returns:

artifacts (for convenience).

Return type:

nanaimo.Artifacts()

nanaimo.set_subprocess_environment(args: nanaimo.Namespace) → None[source]

Updates os.environ from values set as environ in the provided arguments.

Parameters:args – A namespace to load the environment from. The map of values in this key are added to any subsequent subprocess started but can be overridden by env arguments to subprocess constructors like subprocess.Popen

nanaimo.fixtures

Almost everything in Nanaimo is a nanaimo.fixtures.Fixture. Fixtures can be pytest fixtures, instrument abstractions, aggregates of other fixtures, or anything else that makes sense. The important thing is that any fixture can be a pytest fixture or can be awaited directly using nait (NanAimo Interactive Terminal).

class nanaimo.fixtures.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: object

Common, abstract class for pytest fixtures based on Nanaimo. Nanaimo fixtures provide a visitor pattern for arguments that are common for both pytest extra arguments and for argparse commandline arguments. This allows a Nanaimo fixture to expose a direct invocation mode for debuging with the same arguments used by the fixture as a pytest plugin. Additionally all Nanaimo fixtures provide a gather() function that takes a nanaimo.Namespace containing the provided arguments and returns a set of nanaimo.Artifacts gathered by the fixture. The contents of these artifacts are documented by each concrete fixture.

class MyFixture(nanaimo.fixtures.Fixture):
    @classmethod
    def on_visit_test_arguments(cls, arguments: nanaimo.Arguments) -> None:
        arguments.add_argument('--foo', default='bar')

    async def on_gather(self, args: nanaimo.Namespace) -> nanaimo.Artifacts:
        artifacts = nanaimo.Artifacts(-1)
        # do something and then return
        artifacts.result_code = 0
        return artifacts

MyFixture can now be used from a commandline like:

python -m nanaimo MyFixture --foo baz

or as part of a pytest:

pytest --foo=baz
Parameters:
  • manager (FixtureManager) – The fixture manager that is the scope for this fixture. There must be a 1:1 relationship between a fixture instance and a fixture manager instance.
  • args (nanaimo.Namespace) – A namespace containing the arguments for this fixture.
  • kwargs – All fixtures can be given a asyncio.AbstractEventLoop instance to use as loop and an initial value for gather_timeout_seconds as gather_timeout_seconds (float). Other keyword arguments may used by fixture specializations.
classmethod get_canonical_name() → str[source]

The name to use as a key for this nanaimo.fixtures.Fixture type. If a class defines a string fixture_name this will be used as the canonical name otherwise it will be the name of the fixture class itself.

class MyFixture(nanaimo.fixtures.Fixture):

    fixture_name = 'my_fixture'

assert 'my_fixture' == MyFixture.get_canonical_name()
classmethod get_argument_prefix() → str[source]

The name to use as a prefix for arguments. This also becomes the configuration section that the fixture’s arguments can be overridden from. If the fixture defines an argument_prefix class member this value is used otherwise the value returned from get_canonical_name() is used.

class MyFixture(nanaimo.fixtures.Fixture):

    argument_prefix = 'mf'
>>> MyFixture.get_argument_prefix()  # noqa : F821
'mf'
class MyOtherFixture(nanaimo.fixtures.Fixture):
    # this class doesn't define argument_prefix so
    # so the canonical name is used instead.
    fixture_name = 'my_outre_fixture'
>>> MyOtherFixture.get_argument_prefix()  # noqa : F821
'my-outre-fixture'
classmethod get_arg_covariant(args: nanaimo.Namespace, base_name: str, default_value: Optional[Any] = None) → Any[source]

When called by a baseclass this method will return the most specalized argument value available.

Parameters:
  • args – The arguments to search.
  • base_name – The base name. For example foo for --prefix-bar.
  • default_value – The value to use if the argument could not be found.
classmethod get_arg_covariant_or_fail(args: nanaimo.Namespace, base_name: str) → Any[source]

Calls get_arg_covariant() but raises ValueError if the result is None.

Raises:ValueError – if no value could be found for the argument.
gather_until_complete(*args, **kwargs) → nanaimo.Artifacts[source]

helper function where this:

foo.gather_until_complete()

is equivalent to this:

foo.loop.run_until_complete(foo.gather())
name

The canonical name for the Fixture.

loop

The running asyncio EventLoop in use by this Fixture. This will be the loop provided to the fixture in the constructor if that loop is still running otherwise the loop will be a running loop retrieved by asyncio.get_event_loop(). :raises RuntimeError: if no running event loop could be found.

manager

The FixtureManager that owns this nanaimo.fixtures.Fixture.

logger

A logger for this nanaimo.fixtures.Fixture instance.

fixture_arguments

The Fixture-wide arguments. Can be overridden by kwargs for each gather() invocation.

gather_timeout_seconds

The timeout in fractional seconds to wait for on_gather() to complete before raising a asyncio.TimeoutError.

classmethod visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Visit this fixture’s on_visit_test_arguments() but with the proper nanaimo.Arguments.required_prefix set.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_test_teardown(test_name: str) → None[source]

Invoked for each fixture after it was used in a test as part of the pytest _pytest.hookspec.pytest_runtest_teardown() protocol.

Parameters:test_name – The name of the test the fixture was used with.
countdown_sleep(sleep_time_seconds: float) → None[source]

Calls asyncio.sleep() for 1 second then emits an logging.Logger.info() of the time remaining until sleep_time_seconds. This is useful for long waits as an indication that the process is not deadlocked.

Parameters:sleep_time_seconds (float) – The amount of time in seconds for this coroutine to wait before exiting. For each second that passes while waiting for this amount of time the coroutine will asyncio.sleep() for 1 second.
gate_tasks(gate_co_or_f: Union[Coroutine[T_co, T_contra, V_co], _asyncio.Future], timeout_seconds: Optional[float], *gated_tasks) → Tuple[_asyncio.Future, List[_asyncio.Future]][source]

Runs a set of tasks until a gate task completes then cancels the remaining tasks.

async def gated_task():
    while True:
        await asyncio.sleep(.1)

async def gate_task():
    await asyncio.sleep(1)
    return 'gate passed'

async def example():

    any_fixture = nanaimo_bar.Fixture(manager)

    gate_future, gated_futures = await any_fixture.gate_tasks(gate_task(), None, gated_task())

    assert not gate_future.cancelled()
    assert 'gate passed' == gate_future.result()
    assert len(gated_futures) == 1
    assert gated_futures[0].cancelled()
Parameters:
Returns:

a tuple of the gate future and a set of the gated futures.

Return type:

typing.Tuple[asyncio.Future, typing.Set[asyncio.Future]]:

Raises:
gather(*args, **kwargs) → nanaimo.Artifacts[source]

Coroutine awaited to gather a new set of fixture artifacts.

Parameters:kwargs – Optional arguments to override or augment the arguments provided to the nanaimo.fixtures.Fixture constructor
Returns:A set of artifacts with the nanaimo.Artifacts.result_code set to indicate the success or failure of the fixture’s artifact gathering activies.
Raises:asyncio.TimeoutError – If gather_timeout_seconds is > 0 and on_gather() takes longer then this to complete or if on_gather itself raises a timeout error.
observe_tasks(observer_co_or_f: Union[Coroutine[T_co, T_contra, V_co], _asyncio.Future], timeout_seconds: Optional[float], *persistent_tasks) → Set[_asyncio.Future][source]

Allows running a set of tasks but returning when an observer task completes. This allows a pattern where a single task is evaluating the side-effects of other tasks as a gate to continuing the test or simply that a set of task should continue to run but a single task must complete.

Parameters:
Returns:

a list of the persistent tasks as futures.

Return type:

typing.Set[asyncio.Future]

Raises:
observe_tasks_assert_not_done(observer_co_or_f: Union[Coroutine[T_co, T_contra, V_co], _asyncio.Future], timeout_seconds: Optional[float], *persistent_tasks) → Set[_asyncio.Future][source]

Allows running a set of tasks but returning when an observer task completes. This allows a pattern where a single task is evaluating the side-effects of other tasks as a gate to continuing the test.

Parameters:
Returns:

a list of the persistent tasks as futures.

Return type:

typing.Set[asyncio.Future]

Raises:
on_gather(args: nanaimo.Namespace) → nanaimo.Artifacts[source]

Coroutine awaited by a call to gather(). The fixture should always retrieve new artifacts when invoked leaving caching to the caller.

Parameters:args (nanaimo.Namespace) – The arguments provided for the fixture instance merged with kwargs provided to the gather() method.
Returns:A set of artifacts with the nanaimo.Artifacts.result_code set to indicate the success or failure of the fixture’s artifact gathering activies.
Raises:asyncio.TimeoutError – It is valid for a fixture to raise timeout errors from this method.
class nanaimo.fixtures.SubprocessFixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.Fixture

Fixture base type that accepts a string argument cmd and executes it as a subprocess. Because some subprocess commands might result in huge amounts of data being sent to stdout and/or stderr this class does not capture this data by default. Instead, tests are encouraged to either filter the subprocess pipes or use the --logfile argument to write the output to a file in persistent storage.

Filtering is accomplished using the stdout_filter or stderr_filter property of this class. For example:

class MySubprocessFixture(nanaimo.fixtures.SubprocessFixture):
    '''
    Subprocess test fixture that simply calls "nait --version"
    '''

    @classmethod
    def on_visit_test_arguments(cls, arguments: nanaimo.Arguments) -> None:
        pass

    def on_construct_command(self, arguments: nanaimo.Namespace, inout_artifacts: nanaimo.Artifacts) -> str:
        return 'nait --version'


async def example(manager):

    subject = MySubprocessFixture(manager)

    # The accumulator does capture all stdout. Only use this if you know
    # the subprocess will produce a managable and bounded amount of output.
    filter = nanaimo.fixtures.SubprocessFixture.SubprocessMessageAccumulator()
    subject.stdout_filter = filter

    artifacts = await subject.gather()

    # In our example the subprocess produces only and exactly the Nanaimo
    # version number
    assert filter.getvalue() == nanaimo.version.__version__
Parameters:
  • stdout_filter – A logging.Filter used when gathering the subprocess.
  • stderr_filter – A logging.Filter used when gathering the subprocess.
class SubprocessMessageAccumulator(minimum_level: int = 20)[source]

Bases: logging.Filter, _io.StringIO

Helper class for working with SubprocessFixture.stdout_filter() or SubprocessFixture.stderr_filter(). This implementation will simply write all log messages (i.e. logging.LogRecord.getMessage()) to its internal buffer. Use getvalue() to get a reference to the buffer.

You can also subclass this method and override its logging.Filter.filter() method to customize your filter criteria.

Parameters:minimum_level – The minimum loglevel to accumulate messages for.
filter(record: logging.LogRecord) → bool[source]

Determine if the specified record is to be logged.

Is the specified record to be logged? Returns 0 for no, nonzero for yes. If deemed appropriate, the record may be modified in-place.

class SubprocessMessageMatcher(pattern: Any, minimum_level: int = 20)[source]

Bases: logging.Filter

Helper class for working with SubprocessFixture.stdout_filter() or SubprocessFixture.stderr_filter(). This implementation will watch every log message and store any that match the provided pattern.

This matcher does not buffer all logged messages.

Parameters:
  • pattern – A regular expression to match messages on.
  • minimum_level – The minimum loglevel to accumulate messages for.
match_count

The number of messages that matched the provided pattern.

filter(record: logging.LogRecord) → bool[source]

Determine if the specified record is to be logged.

Is the specified record to be logged? Returns 0 for no, nonzero for yes. If deemed appropriate, the record may be modified in-place.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_gather(args: nanaimo.Namespace) → nanaimo.Artifacts[source]
Artifacts
key type Notes
cmd str The command used to execute the subprocess.
logfile Optional[pathlib.Path] A file containing stdout, stderr, and test logs
stdout_filter

A filter used when logging the stdout stream with the subprocess.

stderr_filter

A filter used when logging the stderr stream with the subprocess.

on_construct_command(arguments: nanaimo.Namespace, inout_artifacts: nanaimo.Artifacts) → str[source]

Called by the subprocess fixture to ask the specialization to form a command given a set of arguments.

Parameters:
Returns:

The command to run in a subprocess shell.

class nanaimo.fixtures.FixtureManager(loop: Optional[asyncio.events.AbstractEventLoop] = None)[source]

Bases: object

A simple fixture manager and a baseclass for specalized managers.

loop

The running asyncio EventLoop in use by all Fixtures. This will be the loop provided to the fixture manager in the constructor if that loop is still running otherwise the loop will be a running loop retrieved by asyncio.get_event_loop(). :raises RuntimeError: if no running event loop could be found.

create_fixture(canonical_name: str, args: Optional[nanaimo.Namespace] = None, loop: Optional[asyncio.events.AbstractEventLoop] = None) → nanaimo.fixtures.Fixture[source]

Create a new nanaimo.fixtures.Fixture instance iff the canonical_name` is a registered plugin for this process.

Parameters:
  • canonical_name (str) – The canonical name of the fixture to instantiate.
  • args (nanaimo.Namespace) – The arguments to provide to the new instance.
  • loop (typing.Optional[asyncio.AbstractEventLoop]) – An event loop to provide the fixture instance.
Raises:

KeyError – if canonical_name was not registered with this manager.

class nanaimo.fixtures.PluggyFixtureManager[source]

Bases: object

DEPRECATED. Do not use.

nanaimo.config

Much of what Nanaimo does is to allow for intuitive, intelligent, and adaptable configuration of fixtures. This module contains internal implementations used by public types to facilitate this functionality.

class nanaimo.config.ArgumentDefaults(args: Optional[Any] = None)[source]

Bases: object

Manages default values for Nanaimo arguments. Use in conjunction with nanaimo.Arguments and nanaimo.Namespace to populate default argument values when adding arguments to pytest or argparse and to replace missing attributes with values from configuration.

When using the Nanaimo CLI or pytest plugin you don’t need to worry about this object as these modules wire up the defaults, arguments, and namespaces for you.

classmethod create_defaults_with_early_rc_config() → nanaimo.config.ArgumentDefaults[source]

A special factory method that creates a ArgumentDefaults instance pulling the value of --rcfile directly from sys.argv. This allows defaults to be pulled from a config file before argument parsing is performed.

classmethod as_dict(config_value: Union[str, List[str]]) → Mapping[str, str][source]

Where a value is set as a map this method is used to parse the resulting string into a Python dictionary:

[nanaimo]
foo =
    a = 1
    b = 2
    c = 3

Given the above configuration the value of foo can be read as a dictionary as such:

foo_dict = ArgumentDefaults.as_dict(config['foo'])

assert foo_dict['b'] == '2'

nanaimo.pytest.plugin

Nanaimo provides a collection of pytest fixtures all defined in this module.

# In my_namespace/__init__.py

class MyTestFixture(nanaimo.fixtures.Fixture):

    fixture_name = 'my_fixture_name'
    argument_prefix = 'mfn'

    @classmethod
    def on_visit_test_arguments(cls, arguments: nanaimo.Arguments) -> None:
        pass

    async def on_gather(self, args: nanaimo.Namespace) -> nanaimo.Artifacts:
        artifacts = nanaimo.Artifacts()
        # Do your on-target testing here and store results in nanaimo.Artifacts.
        return artifacts


def pytest_nanaimo_fixture_type() -> typing.Type['nanaimo.fixtures.Fixture']:
    '''
    This is required to provide the fixture to pytest as a fixture.
    '''
    return MyTestFixture

In your setup.cfg you’ll first need to register nanaimo with pytest

[options]
    pytest11 =
        pytest_nanaimo = nanaimo.pytest.plugin

then you’ll need to add your fixture’s namespace:

[options]
    pytest11 =
        pytest_nanaimo = nanaimo.pytest.plugin
        pytest_nanaimo_plugin_my_fixture = my_namspace

Note

For Nanaimo the key for your plugin in the pytest11 map is unimportant. It must be unique but nothing else about it will be visible to your tests unless you integrate more deeply with pytest. The fixture you expose from your plugin via pytest_nanaimo_fixture_type will be named for the canonical name of your Fixture (in this case, “my_fixture_name”).

You can add as many additional nanaimo plugins as you want but you can only have one Fixture in each module.

Where you don’t need your Nanaimo fixture to be redistributable you may also use standard pytest fixture creation by using the nanaimo_fixture_manager and nanaimo_arguments fixtures supplied by the core nanaimo pytest plugin. For example, assuming you have nanaimo.pytest.plugin in your setup.cfg (see above) you can do something like this in a conftest.py

@pytest.fixture
def my_fixture_name(nanaimo_fixture_manager, nanaimo_arguments) -> 'nanaimo.fixtures.Fixture':
    '''
    It is considered a best-practice to always name your pytest.fixture method the
    same as your Fixture's canonical name (i.e. fixture_name).
    '''
    return MyTestFixture(nanaimo_fixture_manager, nanaimo_arguments)
nanaimo.pytest.plugin.create_pytest_fixture(request: Any, fixture_name: str) → nanaimo.fixtures.Fixture[source]

DEPRECATED. Use the appropriate FixtureManager and its FixtureManager.create_fixture method instead.

nanaimo.pytest.plugin.nanaimo_fixture_manager(request: Any) → nanaimo.fixtures.FixtureManager[source]

Provides a default FixtureManager to a test.

def test_example(nanaimo_fixture_manager: nanaimo.Namespace) -> None:
    common_loop = nanaimo_fixture_manager.loop
Parameters:pytest_request (_pytest.fixtures.FixtureRequest) – The request object passed into the pytest fixture factory.
Returns:A new fixture manager.
Return type:nanaimo.fixtures.FixtureManager
nanaimo.pytest.plugin.nanaimo_arguments(request: Any) → nanaimo.Namespace[source]

Exposes the commandline arguments and defaults provided to a test.

def test_example(nanaimo_arguments: nanaimo.Namespace) -> None:
    an_argument = nanaimo_arguments.some_arg
Parameters:pytest_request (_pytest.fixtures.FixtureRequest) – The request object passed into the pytest fixture factory.
Returns:A namespace with the pytest commandline args added per the documented rules.
Return type:nanaimo.Namespace
nanaimo.pytest.plugin.nanaimo_log(request: Any) → logging.Logger[source]

Provides the unit tests with a logger configured for use with the Nanaimo framework.

Note

For now this is just a Python logger. Future revisions may add capabilities like the ability to log to a display or otherwise provide feedback to humans about the status of a test.

def test_example(nanaimo_log: logging.Logger) -> None:
    nanaimo_log.info('Hiya')

It’s recommended that all Nanaimo tests configure logging in a tox.ini, pytest.ini, or pyproject.toml (when this is supported). For example, the following section in tox.ini would enable cli logging for nanaimo tests:

[pytest]
log_cli = true
log_cli_level = DEBUG
log_format = %(asctime)s %(levelname)s %(name)s: %(message)s
log_date_format = %Y-%m-%d %H:%M:%S
Parameters:pytest_request (_pytest.fixtures.FixtureRequest) – The request object passed into the pytest fixture factory.
Returns:A logger for use by Nanaimo tests.
Return type:logging.Logger
nanaimo.pytest.plugin.assert_success(artifacts: nanaimo.Artifacts) → nanaimo.Artifacts[source]

Syntactic sugar to allow more fluent handling of fixtures.Fixture.gather() artifacts. For example:

from nanaimo.pytest.plugin import assert_success

async def test_my_fixture():

    artifacts = assert_success(await fixture.gather())

    # Now we can use the artifacts. If the gather had returned
    # non-zero for the result_code an assertion error would have
    # been raised.
Parameters:artifacts (nanaimo.Artifacts) – The artifacts to assert on.
Returns:artifacts (for convenience).
Return type:nanaimo.Artifacts()
nanaimo.pytest.plugin.assert_success_if(artifacts: nanaimo.Artifacts, conditional: Callable[[nanaimo.Artifacts], bool]) → nanaimo.Artifacts[source]

Syntactic sugar to allow more fluent handling of fixtures.Fixture.gather() artifacts but with a user-supplied conditional.

from nanaimo.pytest.plugin import assert_success_if

async def test_my_fixture():

    def fail_if_no_foo(artifacts: Artifacts) -> bool:
        return 'foo' in artifacts

    artifacts = assert_success_if(await fixture.gather(), fail_if_no_foo)

    print('artifacts have foo. It's value is {}'.format(artifacts.foo))
Parameters:
  • artifacts (nanaimo.Artifacts) – The artifacts to assert on.
  • conditiona – A method called to evaluate gathered artifacts iff Artifacts.result_code is 0. Return False to trigger an assertion, True to pass.
Returns:

artifacts (for convenience).

Return type:

nanaimo.Artifacts()

class nanaimo.pytest.plugin.PytestFixtureManager(pluginmanager: _pytest.config.PytestPluginManager, loop: Optional[asyncio.events.AbstractEventLoop] = None)[source]

Bases: nanaimo.fixtures.FixtureManager

FixtureManager implemented using pytest plugin APIs.

create_fixture(canonical_name: str, args: Optional[nanaimo.Namespace] = None, loop: Optional[asyncio.events.AbstractEventLoop] = None) → nanaimo.fixtures.Fixture[source]

Create a new nanaimo.fixtures.Fixture instance iff the canonical_name` is a registered plugin for this process.

Parameters:
  • canonical_name (str) – The canonical name of the fixture to instantiate.
  • args (nanaimo.Namespace) – The arguments to provide to the new instance.
  • loop (typing.Optional[asyncio.AbstractEventLoop]) – An event loop to provide the fixture instance.
Raises:

KeyError – if canonical_name was not registered with this manager.

nanaimo.pytest.plugin.is_nait_mode() → bool[source]

A special mode enabled by the ‘nait’ commandline that discards all collected tests and inserts a single test item driven by nait. This mode is used to interact with Nanaimo fixtures from a commandline.

nanaimo.pytest.plugin.pytest_addoption(parser: _pytest.config.argparsing.Parser, pluginmanager: _pytest.config.PytestPluginManager) → None[source]

See _pytest.hookspec.pytest_addoption() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_addhooks(pluginmanager)[source]

See _pytest.hookspec.pytest_addhooks() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_collection(session: _pytest.main.Session)[source]

See _pytest.hookspec.pytest_collection_modifyitems() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_sessionstart(session: _pytest.main.Session) → None[source]

See _pytest.hookspec.pytest_sessionstart() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_runtest_setup(item: _pytest.nodes.Item) → None[source]

See _pytest.hookspec.pytest_runtest_setup() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_runtest_teardown(item: _pytest.nodes.Item, nextitem: _pytest.nodes.Item) → None[source]

See _pytest.hookspec.pytest_teardown() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_sessionfinish(session: _pytest.main.Session, exitstatus: int) → None[source]

See _pytest.hookspec.pytest_sessionfinish() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_report_header(config: _pytest.config.Config, startdir) → List[str][source]

See _pytest.hookspec.pytest_sessionfinish() for documentation. Also see the “Writing Plugins” guide.

nanaimo.pytest.plugin.pytest_terminal_summary(terminalreporter: _pytest.terminal.TerminalReporter, exitstatus: int, config: _pytest.config.Config) → None[source]

See _pytest.hookspec.pytest_sessionfinish() for documentation. Also see the “Writing Plugins” guide.

nanaimo.builtin

Built-in nanaimo.fixtures.Fixture objects for common scenarios. See individual fixture documentation for use.

nanaimo.builtin.nanaimo_bar

class nanaimo.builtin.nanaimo_bar.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.Fixture

A trivial plugin. Returns an callable artifact named “eat” that logs a yummy info message when invoked.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_gather(args: nanaimo.Namespace) → nanaimo.Artifacts[source]

Create a delicious function in the artifacts to eat.

Returned Artifacts
key type Notes
eat Callable[[],None] A function that logs a message
bar_{number} str A string formed from an argument bar_number. This allows testing ordering of concurrent operations.

nanaimo.builtin.nanaimo_gather

class nanaimo.builtin.nanaimo_gather.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.Fixture

This fixture takes a list of other fixtures and runs them concurrently returning a nanaimo.Artifacts.combine() ed set of nanaimo.Artifacts.

You can use this fixture directly in your unit tests:

async def example1() -> Artifacts:

    bar_one = nanaimo_bar.Fixture(manager)
    bar_two = nanaimo_bar.Fixture(manager)
    gather_fixture = nanaimo_gather.Fixture(manager)

    return await gather_fixture.gather(
        gather_coroutine=[
            bar_one.gather(bar_number=1),
            bar_two.gather(bar_number=2)
        ]
    )

You can also use the –gather-coroutines argument to specify fixtures by name:

nait nanaimo_gather --gather-coroutine nanaimo_bar --gather-coroutine nanaimo_bar
classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_gather(args: nanaimo.Namespace) → nanaimo.Artifacts[source]

Multi-plex fixture

nanaimo.builtin.nanaimo_cmd

class nanaimo.builtin.nanaimo_cmd.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.SubprocessFixture

Fixture that accepts a string argument cmd and executes it as a subprocess.

async def list_directory() -> Artifacts:

    cmd = nanaimo_cmd.Fixture(manager)

    return await cmd.gather(
        cmd_shell = ('dir' if os.name == 'nt' else 'ls -la')
    )
classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_construct_command(arguments: nanaimo.Namespace, inout_artifacts: nanaimo.Artifacts) → str[source]

Called by the subprocess fixture to ask the specialization to form a command given a set of arguments.

Parameters:
  • arguments (nanaimo.Arguments) – The arguments passed into Fixture.on_gather().
  • inout_artifacts (nanaimo.Artifacts) – A set of artifacts the superclass is assembling This is provided to the subclass to allow it to optionally contribute artifacts.
Returns:

The command to run in a subprocess shell.

nanaimo.builtin.nanaimo_scp

class nanaimo.builtin.nanaimo_scp.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.SubprocessFixture

This fixture assumes that scp is available and functional on the system.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_construct_command(args: nanaimo.Namespace, inout_artifacts: nanaimo.Artifacts) → str[source]

Form the upload command.

nanaimo.builtin.nanaimo_ssh

class nanaimo.builtin.nanaimo_ssh.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.SubprocessFixture

This fixture assumes that ssh is available and functional on the system.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_construct_command(args: nanaimo.Namespace, inout_artifacts: nanaimo.Artifacts) → str[source]

Called by the subprocess fixture to ask the specialization to form a command given a set of arguments.

Parameters:
  • arguments (nanaimo.Arguments) – The arguments passed into Fixture.on_gather().
  • inout_artifacts (nanaimo.Artifacts) – A set of artifacts the superclass is assembling This is provided to the subclass to allow it to optionally contribute artifacts.
Returns:

The command to run in a subprocess shell.

nanaimo.builtin.nanaimo_serial_watch

class nanaimo.builtin.nanaimo_serial_watch.Fixture(manager: nanaimo.fixtures.FixtureManager, args: nanaimo.Namespace, **kwargs)[source]

Bases: nanaimo.fixtures.Fixture

Gathers a log over a serial connection until a given pattern is matched.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_gather(args: nanaimo.Namespace) → nanaimo.Artifacts[source]

Watch the logs until the pattern matches.

Returned Artifacts
key type Notes
match re.MatchObject The match if result_code is 0
matched_line str The full line matched if result_code is 0

nanaimo.connections

Connections are built-in async abstractions using standard communication protocols like UART, I2C, CAN, TCP/IP, etc. Instrument and nanaimo.fixtures.Fixture classes use connections to bind to physical hardware.

class nanaimo.connections.TimestampedLine(line_text: object)[source]

Bases: str

A line of text with an associated timestamp. This is a subclass of string so the object may be treated as a string without conversion.

timestamp_seconds

The timestamp for the line in fractional seconds. For example, this would be the time the line of text was received when this type is returned for a getter.

class nanaimo.connections.AbstractSerial[source]

Bases: object

Abstract base class for a serial communication channel.

class nanaimo.connections.AbstractAsyncSerial(loop: Optional[asyncio.events.AbstractEventLoop] = None)[source]

Bases: nanaimo.connections.AbstractSerial

Abstract base class for a serial communication channel that provides asynchronous methods.

time() → float[source]

Get the current, monotonic time, in fractional seconds, using the same clock used for receive timestamps.

get_line(timeout_seconds: Optional[float] = None) → nanaimo.connections.TimestampedLine[source]

Get a line of text.

Parameters:timeout_seconds (float) – Time in fractional seconds to wait for input.
Returns:A line of text with the time it was received at.
Return type:TimestampedLine
Raises:asyncio.TimeoutError – If a full line of text was not received within the specified timeout period.
put_line(input_line: str, timeout_seconds: Optional[float] = None) → float[source]

Put a line of text to the serial device.

Parameters:
  • input_line (str) – The line to put.
  • timeout_seconds (float) – Fractional seconds to block for if the input buffer is full. If the buffer does not become available within this time then asyncio.TimeoutError is raised. Use 0 to block forever.
Returns:

The monotonic system time that the line was put into the serial buffers at (see time()).

Raises:

asyncio.TimeoutError – If an input buffer did not become available within the specified timeout.

nanaimo.connections.uart

class nanaimo.connections.uart.ConcurrentUart(serial_port: serial.serialposix.Serial, loop: Optional[asyncio.events.AbstractEventLoop] = None, eol: str = 'rn', echo: bool = False)[source]

Bases: nanaimo.connections.AbstractAsyncSerial

Buffers serial input on another thread and provides line-oriented access to/from the tty via synchronized queues.

readline() → Optional[nanaimo.connections.TimestampedLine][source]

Get a line of text from the receive buffers.

Returns:A line of text with the time it was received at.
Return type:TimestampedLine
writeline(input_line: str, end: Optional[str] = None) → float[source]

Enqueue a line of text to be transmitted on the serial device.

Parameters:
  • input_line (str) – The line to put.
  • end (typing.Optional[str]) – Line ending (overrides the default eol()).
Returns:

The monotonic system time that the line was put into the serial buffers at (see time()).

nanaimo.instruments

This module contains control and communication objects for popular instruments useful to the type of testing Nanaimo is focused on. Where possible these async interfaces will use pure-python to communicate directly with an instrument using known protocols and well supported communication busses (e.g. ethernet, uart, or CAN), however, some instruments will require the installation of a vendor CLI for the Nanaimo automation to use.

Warning

Do not merge third-party code into the Nanaimo repo or provide Nanaimo abstractions that are incompatible with the licensing of this software.

Example block diagram of a Nanaimo instrument using a vendor CLI.

Fig. 6 Example of a Nanaimo Segger JLink instrument using the JLinkExe CLI as a Python subprocess.

Fig. 6 shows the Nanaimo jlink instrument using Segger’s JLink Commander as a subprocess to upload a firmware image to a microcontroller.

nanaimo.instruments.bkprecision

class nanaimo.instruments.bkprecision.Series1900BUart(manager: nanaimo.fixtures.FixtureManager, args: nanaimo.Namespace, **kwargs)[source]

Bases: nanaimo.fixtures.Fixture

Control of a 1900B series BK Precision power supply via UART.

classmethod mode_to_text(mode: int) → str[source]

Get a two-character textual representation for a given power supply mode.

UartFactoryType = typing.Callable[[typing.Union[str, pathlib.Path]], typing.Any]

The serial port factory type for this instrument.

classmethod default_serial_port(port: Union[str, pathlib.Path]) → Generator[nanaimo.connections.AbstractAsyncSerial, None, None][source]

Creates a serial connection to the given port using the default settings for a BK Precision Series 1900B power supply.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

is_volage_above_on_threshold(voltage: float) → bool[source]

Deprecated misspelling. See is_voltage_above_on_threshold() for correct method.

is_voltage_above_on_threshold(voltage: float) → bool[source]

Return if a given voltage is above the configured threshold for the high/on/rising voltage for this fixture.

Raises:ValueError – if no target voltage could be determined.
is_volage_below_off_threshold(voltage: float) → bool[source]

Deprecated misspelling. See is_voltage_below_off_threshold() for correct method.

is_voltage_below_off_threshold(voltage: float) → bool[source]

Return if a given voltage is below the configured threshold for the low/off/falling voltage for this fixture.

on_gather(args: nanaimo.Namespace) → nanaimo.Artifacts[source]

Send a command to the instrument and return the result. :param str command: Send one of the following commands:

Command Action Returns
‘1’ Turn on output voltage ‘OK’ or error text.
‘0’ Turn off output voltage ‘OK’ or error text
‘r’ Send a stream of <cr> characters (NA)
‘?’ Read the front panel display Display voltage, current, and status (ON or OFF)

nanaimo.instruments.saleae

TODO: See https://github.com/ppannuto/python-saleae/blob/master/saleae/saleae.py for the command strings. They don’t seem to be documented anywhere else.

class nanaimo.instruments.saleae.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.Fixture

This fixture controls a Saleae logic analyser attached to the system via USB.

Warning

Stubbed-out implementation This fixture doesn’t do anything yet either then the most naive query possible of the Saleae. This would be a great first contribution to the Nanaimo project.

classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_gather(args: nanaimo.Namespace) → nanaimo.Artifacts[source]

Coroutine awaited by a call to gather(). The fixture should always retrieve new artifacts when invoked leaving caching to the caller.

Parameters:args (nanaimo.Namespace) – The arguments provided for the fixture instance merged with kwargs provided to the gather() method.
Returns:A set of artifacts with the nanaimo.Artifacts.result_code set to indicate the success or failure of the fixture’s artifact gathering activies.
Raises:asyncio.TimeoutError – It is valid for a fixture to raise timeout errors from this method.

nanaimo.instruments.ykush

TODO: See https://www.learn.yepkit.com/reference/ykushcmd-reference-ykush/1/2 for the command strings.

class nanaimo.instruments.ykush.Fixture(manager: nanaimo.fixtures.FixtureManager, args: Optional[nanaimo.Namespace] = None, **kwargs)[source]

Bases: nanaimo.fixtures.SubprocessFixture

Fixture for controlling Yepkit USB hubs with switchable power. For example the YKUSH3 is a 3-port USB-3 hub that allows individual control of the power rails for each port.

This is a subprocess fixture that requires the ykushcmd program is available in the subprocess environment (see Yepkit’s documentation for how to build this from source). All arguments can be overridden via the fixtures gather method. The supported commands are:

command example Description
yku-all-on await nanaimo_instr_ykush.gather(yku_all_on=True) Turn on power to all ports on the YKUSH.
yku-all-off await nanaimo_instr_ykush.gather(yku_all_off=True) Turn off power to all ports on the YKUSH.
yku-command await nanaimo_instr_ykush.gather(yku_command='-l') Pass-through any command to ykushcmd.
classmethod on_visit_test_arguments(arguments: nanaimo.Arguments) → None[source]

Called by the environment before instantiating any nanaimo.fixtures.Fixture instances to register arguments supported by each type. These arguments should be portable between both argparse and pytest. The fixture is registered for this callback by returning a reference to its type from a pytest_nanaimo_fixture_type hook in your fixture’s pytest plugin module.

on_construct_command(arguments: nanaimo.Namespace, inout_artifacts: nanaimo.Artifacts) → str[source]

nanaimo.parsers

The parser module contains parsers for common reporting formats used by instruments or test frameworks. These should be broken out from instruments where appropriate to ensure reuse accross instrument families and communication busses.

nanaimo.parsers.gtest

class nanaimo.parsers.gtest.Parser(timeout_seconds: float, loop: Optional[asyncio.events.AbstractEventLoop] = None)[source]

Bases: object

Uses a given monitor to watch for google test results.