snap-helpers - Interact with the Snap system within a Snap

Latest Version Build Status Coverage Status Documentation

A Python library to interact with snap configuration and properties from inside a snap.

It exposes a top-level snaphelpers.Snap object which provides access to:

  • snap details:

    >>> snap = snaphelpers.Snap()
    >>> snap.instance_name
    >>> snap.version
    >>> snap.revision
  • paths:

    >>> snap.paths.common
    >>> snap.paths.snap
    >>> snap.paths.user_common
    >>> snap.paths.user_data
  • snap-related environment variables:

    >>> pprint.pprint(dict(snap.environ))
    {'ARCH': 'amd64',
     'COMMON': '/var/snap/testapp/common',
     'DATA': '/var/snap/testapp/x1',
     'INSTANCE_KEY': '',
     'INSTANCE_NAME': 'testapp',
     'LIBRARY_PATH': '/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void',
     'NAME': 'testapp',
     'REEXEC': '',
     'REVISION': 'x1',
     'SNAP': '/snap/testapp/x1',
     'USER_COMMON': '/home/ack/snap/testapp/common',
     'USER_DATA': '/home/ack/snap/testapp/x1',
     'VERSION': '0+git.fdf80cd'}
    >>> snap.environ.ARCH
  • configuration options:

    >>> snap.config.set({'': 'baz', 'asdf': 3})  # this needs to be run as root
    >>> options = snap.config.get_options('foo', 'asdf')
    >>> options['foo']
    {'bar': 'baz'}
    >>> options['']
    >>> options['asdf']
    >>> options.as_dict()
    {'asdf': 3, 'foo': {'bar': 'baz'}}
  • setting snap health status, along with message and optional status code:

    >>>'foo must happen first', code='wait-foo')

    Health status (when different from okay) is visible from the snap CLI:

    $ snap info snap-helpers
    name:    snap-helpers
    summary: Test snap for snap-helpers
      status:  waiting
      message: foo must happen first
      code:    wait-foo
      checked: today at 16:23 CEST
  • content of snap metadata files such as:

    • snap/metadata.yaml

    • meta/snap.yaml

    • snap/snapcraft.yaml

    These can be accessed as follows:

    >>> snap.metadata_files.snap
    >>> pprint(dict(snap.metadata_files.snap))
    {'apps': {'ipython': {'command': 'snap/command-chain/snapcraft-runner '
                          'plugs': ['home', 'network', 'network-bind']},
              'python': {'command': 'snap/command-chain/snapcraft-runner '
                         'plugs': ['home', 'network', 'network-bind']},
              'snap-helpers': {'command': 'snap/command-chain/snapcraft-runner '
                               'plugs': ['home', 'network', 'network-bind']}},
     'architectures': ['amd64'],
     'base': 'core18',
     'confinement': 'strict',
     'description': 'Test snap for snap-helpers.\n'
                    'It provides python and ipython shells to test the '
                    '`snaphelpers` library.\n',
     'grade': 'stable',
     'name': 'snap-helpers',
     'summary': 'Test snap for snap-helpers',
     'version': '0.1.6+git6.37370cd'}

Hook helpers

The library provides helpers to reduce boilerplate when setting up hooks for the snap.

Hooks can be defined by simply registering functions to be called as hooks via entry_points in the application

    # ...
        "snaphelpers.hooks": [
            "configure = testapp:configure_hook",
            "install = testapp:install_hook",

Hook functions are called with a Snap object as argument:

def install_hook(snap: snaphelpers.Snap):
    # ...

def configure_hook(snap: snaphelpers.Snap):
    # ...

snap-helpers will take care of the hooks plumbing (i.e. creating hook files in $SNAP/snap/hooks).

Alternatively, the configuration can be done in setup.cfg:

snaphelpers.hooks =
    install = testapp:install_hook
    configure = testapp:configure_hook

Testing with the snap

The snap-helpers snap provides a way to easily test code using the library in a real snap environment with strict confinement.

It provides an IPython shell which automatically imports the snaphelpers module and provides a Snap instance for the current snap.

$ snap-helpers
Python 3.6.8 (default, Aug 20 2019, 17:12:48)
Type 'copyright', 'credits' or 'license' for more information
IPython 7.8.0 -- An enhanced Interactive Python. Type '?' for help.

Use the "snap" variable for an instance for the current snap.

In [1]: import pprint

In [2]: pprint.pprint(dict(snap.environ))
{'ARCH': 'amd64',
 'COMMON': '/var/snap/snap-helpers/common',
 'DATA': '/var/snap/snap-helpers/x1',
 'INSTANCE_NAME': 'snap-helpers',
 'LIBRARY_PATH': '/var/lib/snapd/lib/gl:/var/lib/snapd/lib/gl32:/var/lib/snapd/void',
 'NAME': 'snap-helpers',
 'REEXEC': '',
 'REVISION': 'x1',
 'SNAP': '/snap/snap-helpers/x1',
 'USER_COMMON': '/home/ack/snap/snap-helpers/common',
 'USER_DATA': '/home/ack/snap/snap-helpers/x1',
 'VERSION': '0.1.6+git1.4a0b997'}

The snap can be built and installed as follows:

$ snapcraft
$ sudo snap install --dangerous snap-helpers_*.snap


snap-helpers can be installed from PyPI.


$ pip install snap-helpers


Full documentation is available on ReadTheDocs.

Indices and tables