Snapcraft Python plugin doesn't include wheel

I think I’ve found a bug in snapcraft. When building a Python project, I get this error:

Building wheels for collected packages: microk8s-puppetmaster
  Building wheel for microk8s-puppetmaster (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /root/parts/microk8s-puppetmaster/install/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-eq3z3t3b/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-eq3z3t3b/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-_x7wyv4o
       cwd: /tmp/pip-req-build-eq3z3t3b/
  Complete output (6 lines):
  usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
     or: setup.py --help [cmd1 cmd2 ...]
     or: setup.py --help-commands
     or: setup.py cmd --help
  
  error: invalid command 'bdist_wheel'
  ----------------------------------------
  ERROR: Failed building wheel for microk8s-puppetmaster

and I have to manually add

python-packages:
    - wheel

to the part. Shouldn’t this be implicit?

2 Likes

Ah, I actually had just literally seconds before seeing this post ran into a bug trying to build a core20-based python snap and gave up figuring it was a bug in the particular projects’ python setup.py, but actually adding that python-packages fixed it, so thanks for finding a workaround for my immediate bug!

but also yes this feels like a snapcraft bug to me

2 Likes

Core20 I assume?

I think this was by design (for core20 projects) to minimize the assumptions of how the developer wants to drive their build environment. @sergiusens would be able to provide the authoritative answer on that.

Out of curiosity, did the lack of wheel cause your projects to fail to build/run? Or just not take advantage of wheels and give you that ugly (non-fatal) error?

For the project I was building, yes it was based on core20, and it actually failed to build properly erroring the same way which I thought should have made the snapcraft build fail itself, but actually it completed and built something but that something was broken. See: https://github.com/tartley/cbeams/issues/2#issuecomment-702259995

Hrm, well generally speaking that’s not a fatal error. As you can see in your logs, cbeams installed fine.

FWIW I just built cbeams from your snippet (without wheel) and it ran fine. Not sure what happened in your case :thinking:

It gives a non fatal error on build, but then the snap won’t run because the expected module is not in the environment at run time.

To me, this is very undesirable. Any automated builds (e.g. LP) will look to complete but the snap will be broken.

1 Like

@joedborg That shouldn’t be the case, the library should be installed.

Can you provide a minimal reproducer?

In case I push to that in the mean time, broken state is commit 421d971250045d380e451c76236aab16725292f1

What is the traceback? It seems that boto3, a requirement of yours does require wheel (https://github.com/boto/boto3/blob/develop/requirements.txt) but does not have it in install_requires https://github.com/boto/boto3/blob/develop/setup.py#L16
Depending on the traceback, this may be the root cause of the issue

I see it with the puppetmaster part:

Building wheels for collected packages: microk8s-puppetmaster
  Building wheel for microk8s-puppetmaster (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /root/parts/microk8s-puppetmaster/install/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-hfl8powb/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-hfl8powb/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-aqxlkas4
       cwd: /tmp/pip-req-build-hfl8powb/
  Complete output (6 lines):
  usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
     or: setup.py --help [cmd1 cmd2 ...]
     or: setup.py --help-commands
     or: setup.py cmd --help
  
  error: invalid command 'bdist_wheel'
  ----------------------------------------
  ERROR: Failed building wheel for microk8s-puppetmaster

the deps seem fine:

Processing /root/parts/microk8s-puppetmaster/build
Collecting boto3
  Downloading boto3-1.15.12-py2.py3-none-any.whl (129 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 129 kB 3.6 MB/s 
Collecting ec2-metadata
  Downloading ec2_metadata-2.2.0-py3-none-any.whl (8.1 kB)
Collecting botocore<1.19.0,>=1.18.12
  Downloading botocore-1.18.12-py2.py3-none-any.whl (6.7 MB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 6.7 MB 21.5 MB/s 
Collecting jmespath<1.0.0,>=0.7.1
  Downloading jmespath-0.10.0-py2.py3-none-any.whl (24 kB)
Collecting s3transfer<0.4.0,>=0.3.0
  Downloading s3transfer-0.3.3-py2.py3-none-any.whl (69 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 69 kB 1.5 MB/s 
Collecting cached-property
  Downloading cached_property-1.5.2-py2.py3-none-any.whl (7.6 kB)
Collecting requests
  Downloading requests-2.24.0-py2.py3-none-any.whl (61 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 61 kB 213 kB/s 
Collecting python-dateutil<3.0.0,>=2.1
  Downloading python_dateutil-2.8.1-py2.py3-none-any.whl (227 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 227 kB 33.8 MB/s 
Collecting urllib3<1.26,>=1.20; python_version != "3.4"
  Downloading urllib3-1.25.10-py2.py3-none-any.whl (127 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 127 kB 39.0 MB/s 
Collecting idna<3,>=2.5
  Downloading idna-2.10-py2.py3-none-any.whl (58 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 58 kB 1.5 MB/s 
Collecting chardet<4,>=3.0.2
  Downloading chardet-3.0.4-py2.py3-none-any.whl (133 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 133 kB 43.0 MB/s 
Collecting certifi>=2017.4.17
  Downloading certifi-2020.6.20-py2.py3-none-any.whl (156 kB)
     |β–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆβ–ˆ| 156 kB 35.7 MB/s 
Collecting six>=1.5
  Downloading six-1.15.0-py2.py3-none-any.whl (10 kB)
Building wheels for collected packages: microk8s-puppetmaster
  Building wheel for microk8s-puppetmaster (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /root/parts/microk8s-puppetmaster/install/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-hfl8powb/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-hfl8powb/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-aqxlkas4
       cwd: /tmp/pip-req-build-hfl8powb/
  Complete output (6 lines):
  usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
     or: setup.py --help [cmd1 cmd2 ...]
     or: setup.py --help-commands
     or: setup.py cmd --help
  
  error: invalid command 'bdist_wheel'
  ----------------------------------------
  ERROR: Failed building wheel for microk8s-puppetmaster
  Running setup.py clean for microk8s-puppetmaster
Failed to build microk8s-puppetmaster

@joedborg, it installed fine for me. <edited, as I see the log above now :wink:> Can you try a snapcraft clean and rerun?

However, as it is a classic snap (on core20), the python3 getting invoked is from the host.

This should fix the runtime:

-    command: bin/puppetmaster
+    command: bin/python3 $SNAP/bin/puppetmaster

@sergiusens any thought on how to improve this aspect?

@sergiusens: also, this is a good example of how the python3 link is getting broke.

First run is OK. Second run (change the command or something) it gets relinked to /root/stage/bin/python3.

I still have to include wheel, even with this command (I didn’t think this would have any effect on the build).

@joedborg as you can see from my logs, the wheel fails to build, but pip still manages to install the packages correctly:

Building wheels for collected packages: microk8s-puppetmaster, boto3
  Building wheel for microk8s-puppetmaster (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /root/parts/microk8s-puppetmaster/install/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-req-build-jjs5fbdc/setup.py'"'"'; __file__='"'"'/tmp/pip-req-build-jjs5fbdc/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-09ei429s
       cwd: /tmp/pip-req-build-jjs5fbdc/
  Complete output (6 lines):
  usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
     or: setup.py --help [cmd1 cmd2 ...]
     or: setup.py --help-commands
     or: setup.py cmd --help
  
  error: invalid command 'bdist_wheel'
  ----------------------------------------
  ERROR: Failed building wheel for microk8s-puppetmaster
  Running setup.py clean for microk8s-puppetmaster
  Building wheel for boto3 (setup.py) ... error
  ERROR: Command errored out with exit status 1:
   command: /root/parts/microk8s-puppetmaster/install/bin/python3 -u -c 'import sys, setuptools, tokenize; sys.argv[0] = '"'"'/tmp/pip-install-xq5flev4/boto3/setup.py'"'"'; __file__='"'"'/tmp/pip-install-xq5flev4/boto3/setup.py'"'"';f=getattr(tokenize, '"'"'open'"'"', open)(__file__);code=f.read().replace('"'"'\r\n'"'"', '"'"'\n'"'"');f.close();exec(compile(code, __file__, '"'"'exec'"'"'))' bdist_wheel -d /tmp/pip-wheel-e84q56zw
       cwd: /tmp/pip-install-xq5flev4/boto3/
  Complete output (6 lines):
  usage: setup.py [global_opts] cmd1 [cmd1_opts] [cmd2 [cmd2_opts] ...]
     or: setup.py --help [cmd1 cmd2 ...]
     or: setup.py --help-commands
     or: setup.py cmd --help
  
  error: invalid command 'bdist_wheel'
  ----------------------------------------
  ERROR: Failed building wheel for boto3
  Running setup.py clean for boto3
Failed to build microk8s-puppetmaster boto3
Installing collected packages: jmespath, six, python-dateutil, urllib3, botocore, s3transfer, boto3, cached-property, certifi, idna, chardet, requests, ec2-metadata, microk8s-puppetmaster
    Running setup.py install for boto3 ... done
    Running setup.py install for microk8s-puppetmaster ... done
Successfully installed boto3-1.15.13 botocore-1.18.13 cached-property-1.5.2 certifi-2020.6.20 chardet-3.0.4 ec2-metadata-2.2.0 idna-2.10 jmespath-0.10.0 microk8s-puppetmaster-0.1.0 python-dateutil-2.8.1 requests-2.24.0 s3transfer-0.3.3 six-1.15.0 urllib3-1.25.10
...

Note that microk8s-puppetmaster-0.1.0 was successfully installed.

I did a fresh build of your sources with just the command updated, and it runs fine. Can you verify it does not for you?

ah yes, you’re right, needed to clean build

1 Like

@joedborg, have you noticed any problems when installing microk8s-puppetmaster on 18.04?

I ran into this issue as well, but without getting a proper solution. I tried adding python3-wheel to the build packages, but it still gives the invalid command 'bdist_wheel'

From https://snapcraft.io/docs/python-apps:

Note that your Python project should be using setuptools and you should be able to run python setup.py bdist_wheel without errors.

Making the assumption that a project should build using the bdist_wheel command but not including wheel in the build environment by default seems like an odd thing to do.

1 Like

Unfortunately that is an assumption of pip install unless using --no-binary option.

That said, I agree that it is ugly and poor default behavior for Snapcraft. I do have a PR to tackle this: https://github.com/snapcore/snapcraft/pull/3440 We haven’t nailed down the approach to take just yet, so feedback is welcome :smiley: !

1 Like