Python snap - snap not building

Hi, I’ve done snaps before but this time I was just trying to test a python snap using hatch and nicegui on core24 and I can’t get the snap built. Most of the build process is complete but I get an error on the command. It can’t find the command I define and I’m not seeing why, since the dir is there. I get a

Detailed information: cannot pack "/root/prime": snap is unusable due to missing files: path "bin/main.py" does not exist
Failed to run snapcraft in instance

I’m using a random name for the snap (not equal to the project name), is this the cause?

Could you show us your snapcraft.yaml ?

Sure, I already changed the dir names but it didn’t work. Do I have to include a manifest file?

My yaml:

name: potencia
summary: calculate the watts your charger delivers
version: "master"
description: |
  potencia is a simple app to calculate the watts given a certain
  voltage and a certain amperage.
base: core24
confinement: strict

parts:
  potencia:
    plugin: python
    source: .
    stage-packages:
      - build-essential
      - libgl1-mesa-dev
    python-packages:
      - hatch
      - nicegui
      - pywebview
      - pyqtwebengine
      - pyqt6
      - pywebview[qt]

apps:
  potencia:
    command: potencia/src/potencia/main.py

run snapcraft with the --shell-after option, that will spawn a shell inside the build container (you can leave it with typing exit or hitting Ctrl-D), then take a look in the prime directory (this represents your final snap during build) and find where your main.py lives, the command: needs to point to the relative path underneath your prime directory where that file lives …

I.e. if your build makes it end up in prime/usr/bin/main.py your command: entry would look like:

      command: usr/bin/main.py
--shell-after

isn’t working…

my tree:

potencia
├── LICENSE.txt
├── pyproject.toml
├── README.md
├── snap
│   └── snapcraft.yaml
├── src
│   └── potencia
│       ├── __about__.py
│       ├── __init__.py
│       └── main.py
└── tests
    └── __init__.py

I also have a venv dir above this.

Well, it should, see here:

https://documentation.ubuntu.com/snapcraft/stable/how-to/debugging/debug-a-snap/#inspect-the-snap-s-contents

Yeah, that’s your source, which likely won’t look in any way like the binary snap you produce in the end …

I missed the “prime” after “snapcraft”. I searched all over and saw none of my code on the prime dir and subdirs. Possible reasons for this?

You might miss a setup.py in your source for the python plugin to do anything more than installing the python packages with pip (not sure if it uses the .toml you have there, check the documentation)…

If you just want the source copied into place you can additionally use a dump plugin to copy the files over (and either use organize: to put them into proper places like bin/ for the executables and such or set up your src/potentica dir the right way with pre-defined directories)

The documentation tells that one can use the .toml file so I was thinking I didn’t need a setup.py. I wanted to use hatch, but I don’t really know what snapcraft does when it encounters a setup.py. Does it build the package wheel and use that? Could you send me the link for the python plugin code?

Github co-pilot tells me:

What does the python plugin do with project files?

  • During the build and stage steps, the python plugin installs your Python project and its dependencies into an isolated environment (usually under $SNAPCRAFT_PART_INSTALL, which later gets merged into prime).
  • It uses pip install . (or your specified build backend via pyproject.toml) to install your project, which means:
    • Only files included in the Python package (as per your setup.py, pyproject.toml, and MANIFEST.in`) will be installed.
    • These installed files (your Python modules, data files, scripts, etc.) are placed in the correct locations in prime (e.g., lib/pythonX.Y/site-packages, bin/, etc.).
  • Raw source files (like README, tests, etc.) that are not part of the installed package are not copied to prime by default, unless you explicitly include them using the stage or prime keywords in your snapcraft.yaml.

So, actually I just found out my package is installed here: /prime/lib/python3.12/site-packages/potencia

I’m not sure if it is because I put this section on my pyproject.toml:

[tool.hatch.build.targets.sdist]
include = [
  "src/potencia/*.py",
]

but I guess maybe I also need a bin dir on the project to import main.py in a file called potencia, so that potencia also goes to bin/potencia on prime.

In order to do the script that will be put automatically in bin this is relevant: https://packaging.python.org/en/latest/specifications/entry-points/#use-for-scripts

This is the relevant part of pyproject.toml

[tool.hatch.build.targets.sdist]
include = [
  "potencia/*.py",
]

[project.scripts]
potencia = "potencia.main:run"

the snap now builds.

Now, I’m having trouble with multiprocessing :stuck_out_tongue:

by the way my snapcraft.yaml so far:

name: potencia
summary: calculate the watts your charger delivers
version: "master"
description: |
  potencia is a simple app to calculate the watts given a certain
  voltage and a certain amperage.
base: core24
confinement: strict

parts:
  potencia:
    plugin: python
    source: .
    stage-packages:
      - build-essential
      - libgl1-mesa-dev
    python-packages:
      - hatch
      - nicegui
      - pywebview
      - pyqtwebengine
      - pyqt6
      - pywebview[qt]

apps:
  potencia:
    command: bin/potencia
    plugs:
      - shared-memory
      - network

You might either need to use the shared-memory interface:

https://snapcraft.io/blog/private-shared-memory-support-for-snaps

Or you could use snapcraft-preload:

It took me a while to understand that shared-memory shouldn’t be inside app but on it’s own, like this:

...

plugs:
  shmem:
    interface: shared-memory
    private: true

apps:
...

now it’s working (it keeps running without fail) but no window is displayed. I’ve got yet to figure out why. I’m going to try including the gnome extension and see if it changes anything.

Some progress, I now get a window (with the gnome extension) but still have this issues:

It now runs ok on Gnome. It doesn’t run on Kubuntu. It says:

qt.qpa.plugin: Could not load the Qt platform plugin "xcb" in "" even though it was found.
This application failed to start because no Qt platform plugin could be initialized. Reinstalling the application may fix this problem.

Available platform plugins are: eglfs, linuxfb, minimal, minimalegl, offscreen, vnc, wayland-egl, wayland, wayland-xcomposite-egl, wayland-xcomposite-glx, webgl, xcb.

I tried the wayland plug but no sucess on Kubuntu.

My snapcraft.yaml:

name: potencia
summary: calculate the watts your charger delivers
version: "master"
description: |
  potencia is a simple app to calculate the watts given a certain
  voltage and a certain amperage.
base: core24
confinement: strict

parts:
  potencia:
    plugin: python
    source: .
    stage-packages:
      - build-essential
      - libgl1-mesa-dev
    python-packages:
      - hatch
      - nicegui
      - pywebview
      - pyqtwebengine
      - pyqt6
      - pywebview[qt]

plugs:
  shmem:
    interface: shared-memory
    private: true



apps:
  potencia:
    extensions: [gnome]
    command: bin/potencia
    plugs:
      - network
      - network-status
      - desktop
      - wayland

Um not a kde user, but how about this: