How to call dependencies in snapcraft.yaml

Trying to create me 1st snap. It is a python app (trespass) which needs to import gpgme, numpy and pyperclip.

What is the correct way to install these dependencies?
I find no existing parts of any of them i.e. snapcraft search numpy
No matches found, try to run snapcraft update to refresh the remote parts cache.

Note. ubuntu also fails to pip install pygpgme (gpgme.h not found), but can successfully pip install numpy and pyperclip.

I can apt-get install python3-gpgme, python3-numpy and python3-pyperclip, but this seems to defeat to purpose of a snap.

My yaml file is here, which fails to build

name: trespass
version: '0.6.5'
summary: A secure command line password keeper using gpg
description: |

grade: devel
confinement: devmode

apps:
  trespass:
    command: /usr/bin/trespass

parts:
  trespass:
    plugin: python
    python-version: python3
    source: https://github.com/gps1539/trespass/archive/0.1.tar.gz
    after: [python3-gpgme, python3-numpy, python3-pyperclip]

You’re incorrectly using after. after is to say “build this part after you’ve built these other parts, which may be listed in this yaml, or might be remote parts”. What you want to do is specify build-packages which means “install these debs before building this part”.

Thanks popey

Wouldn’t using build-packages make the snap specific to Ubuntu/Debian?
Is there a way to use pip install which should be universal? My last step would then be to figure out why pip install python3-gpgme fails on Ubuntu.

No it will not make it specific to Ubuntu/Debian from a users point of view.
Have you had a chance to look at https://docs.snapcraft.io/build-snaps/python ? From there I think you want to look at requirements, but if treepass has correct install_requires in its setup.py the dependencies should be brought in from PyPI automatically.

Thanks. Would a snap that calls apt-get work on other platforms? Solus, Arch etc?
trespass pip installs correctly on arch but fails on Ubuntu as pygpgme fails with gpgme.h not found. I do not see a way to fix the gpgme.h issue without using apt-get install. In fact pip install pygpgme fails on Ubuntu directly.

BTW. I do not see an example yaml that uses pypi and it looks like the youtubedl example pulls from github and calls ffmpeg as a snap.

No, apt itself will probably not work on non-debian distros, but once you build it (which will use apt if you use build-packages) that resulting snap will run everywhere. So unless your snap actually relies on apt at runtime, you should be good.

Thanks, that makes sense.

I edited my yaml file and ran snapcraft. Alas I get an error. Is this a bug in snapcraft, in my yaml file or somewhere else?

> sudo -H snapcraft
Skipping pull trespass (already ran)
Preparing to build trespass 
Building trespass 
Collecting pip
Collecting setuptools
Collecting wheel
Installing collected packages: pip, setuptools, wheel
Successfully installed pip-9.0.1 setuptools-36.6.0 wheel-0.30.0
Staging trespass 
Priming trespass 
Traceback (most recent call last):
  File "/usr/bin/snapcraft", line 11, in <module>
    load_entry_point('snapcraft==2.34+17.10', 'console_scripts', 'snapcraft')()
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 564, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2662, in load_entry_point
    return ep.load()
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2316, in load
    return self.resolve()
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2322, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/usr/lib/python3/dist-packages/snapcraft/cli/__main__.py", line 19, in <module>
    run(prog_name='snapcraft')
  File "/usr/lib/python3/dist-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1043, in invoke
    return Command.invoke(self, ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/lib/python3/dist-packages/snapcraft/cli/__init__.py", line 110, in run
    ctx.forward(lifecyclecli.commands['snap'])
  File "/usr/lib/python3/dist-packages/click/core.py", line 553, in forward
    return self.invoke(cmd, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/snapcraft/cli/lifecycle.py", line 132, in snap
    project_options, directory=directory, output=output)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 349, in snap
    execute('prime', project_options)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 130, in execute
    _Executor(config, project_options).run(step, part_names)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 228, in run
    self._create_meta(step, part_names)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 269, in _create_meta
    self.config.snapcraft_yaml_path)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 84, in create_snap_packaging
    packaging.write_snap_yaml()
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 111, in write_snap_yaml
    snap_yaml = self._compose_snap_yaml()
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 276, in _compose_snap_yaml
    snap_yaml['apps'] = self._wrap_apps(self._config_data['apps'])
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 385, in _wrap_apps
    self._wrap_app(app, apps[app])
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 392, in _wrap_app
    app[k] = self._wrap_exe(app[k], '{}-{}'.format(k, name))
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 365, in _wrap_exe
    with open(exepath, 'rb') as exefile:
FileNotFoundError: [Errno 2] No such file or directory: '/usr/bin/trespass'
kquote

Here is my current yaml

graham@graham-VirtualBox:~/trespass-snap/snap$ cat snapcraft.yaml 

name: trespass
version: '0.6.5' 
summary: A secure command line password keeper using gpg 
description: |

grade: devel
confinement: devmode

apps:
  trespass:
    command: /usr/bin/trespass

parts:
  trespass:
    plugin: python
    python-version: python3
    source: https://github.com/gps1539/trespass/archive/0.1.tar.gz
    build-packages:
      - python3-gpgme
      - python3-numpy
      - python3-pyperclip

There’s two problems here. Your python setup doesn’t actually spit out a trespass binary, and once you fix that, change the command line to command: usr/bin/trespass.

Thanks popey,
you where correct that my setup.py didn’t spit out a binary. It now does
‘pip install trespass’ installs to /usr/local/bin/trespass (not sure if this is an issue)
note on arch linux it installs to /usr/bin/trespass

However snapcraft still fails for me, but hopefully I’m getting closer

> 
sudo snapcraft
Skipping pull trespass (already ran)
Skipping build trespass (already ran)
Skipping stage trespass (already ran)
Skipping prime trespass (already ran)
Traceback (most recent call last):
  File "/usr/bin/snapcraft", line 11, in <module>
    load_entry_point('snapcraft==2.34+17.10', 'console_scripts', 'snapcraft')()
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 564, in load_entry_point
    return get_distribution(dist).load_entry_point(group, name)
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2662, in load_entry_point
    return ep.load()
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2316, in load
    return self.resolve()
  File "/usr/lib/python3/dist-packages/pkg_resources/__init__.py", line 2322, in resolve
    module = __import__(self.module_name, fromlist=['__name__'], level=0)
  File "/usr/lib/python3/dist-packages/snapcraft/cli/__main__.py", line 19, in <module>
    run(prog_name='snapcraft')
  File "/usr/lib/python3/dist-packages/click/core.py", line 722, in __call__
    return self.main(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 697, in main
    rv = self.invoke(ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 1043, in invoke
    return Command.invoke(self, ctx)
  File "/usr/lib/python3/dist-packages/click/core.py", line 895, in invoke
    return ctx.invoke(self.callback, **ctx.params)
  File "/usr/lib/python3/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/click/decorators.py", line 17, in new_func
    return f(get_current_context(), *args, **kwargs)
  File "/usr/lib/python3/dist-packages/snapcraft/cli/__init__.py", line 110, in run
    ctx.forward(lifecyclecli.commands['snap'])
  File "/usr/lib/python3/dist-packages/click/core.py", line 553, in forward
    return self.invoke(cmd, **kwargs)
  File "/usr/lib/python3/dist-packages/click/core.py", line 535, in invoke
    return callback(*args, **kwargs)
  File "/usr/lib/python3/dist-packages/snapcraft/cli/lifecycle.py", line 132, in snap
    project_options, directory=directory, output=output)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 349, in snap
    execute('prime', project_options)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 130, in execute
    _Executor(config, project_options).run(step, part_names)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 228, in run
    self._create_meta(step, part_names)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/lifecycle.py", line 269, in _create_meta
    self.config.snapcraft_yaml_path)
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 84, in create_snap_packaging
    packaging.write_snap_yaml()
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 111, in write_snap_yaml
    snap_yaml = self._compose_snap_yaml()
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 276, in _compose_snap_yaml
    snap_yaml['apps'] = self._wrap_apps(self._config_data['apps'])
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 385, in _wrap_apps
    self._wrap_app(app, apps[app])
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 392, in _wrap_app
    app[k] = self._wrap_exe(app[k], '{}-{}'.format(k, name))
  File "/usr/lib/python3/dist-packages/snapcraft/internal/meta.py", line 365, in _wrap_exe
    with open(exepath, 'rb') as exefile:
FileNotFoundError: [Errno 2] No such file or directory: '/home/graham/trespass-snap/snap/prime/usr/bin/trespass'

>
cat setup.py 
from distutils.core import setup
setup(
  name = 'trespass',
  packages = ['trespass'], # this must be the same as the name above
  install_requires=[
	'numpy',
	'pygpgme',
	'pyperclip',
	'argparse',
  ],
  version = '0.6.5.5',
  description = 'A secure password keeper', 
  author = 'Graham Smith',
  author_email = 'gps1539@gmail.com',
  scripts = ['trespass/trespass'],
  license='GPL3',

  URLs removed as forum blocks posting links

  keywords = ['testing', 'logging', 'example'], # arbitrary keywords
  classifiers = [],
)

@gps1539, please when posting bits from the command line or excerpts from files (or file names) make sure to mark them as “preformatted text” in the editor; this will avoid things like README.md or setup.py being interpreted as links, which on the one hand is distracting, but more importantly triggers the spam filter. It’s been triggered by several of your replies, to the point that you had been blocked and some of your posts hidden (i’m working through them now)