ukBaz / python-bluezero

A simple Python interface to Bluez
MIT License
396 stars 112 forks source link

Version 0.9.0 cannot be installed via pip #414

Open erichiggins opened 2 months ago

erichiggins commented 2 months ago

Hello,

The build system for my project, which depends on bluezero, started failing back in May when version 0.9.0 was released. The issue seems related to the new dependencies that were added, which cannot be installed on Linux systems for some reason.

To resolve the issue, I've had to pin to version 0.8.0.

The following is the error log from the build, which runs on Github actions, and I was able to reproduce locally in a clean Python 3.12 virtual environment by running pip install bluezero.

Collecting PyGObject (from bluezero)
  Using cached pygobject-3.48.2.tar.gz (715 kB)
  Installing build dependencies: started
  Installing build dependencies: finished with status 'error'
  error: subprocess-exited-with-error

  × pip subprocess to install build dependencies did not run successfully.
  │ exit code: 1
  ╰─> [52 lines of output]
      Collecting meson-python>=0.12.1
        Using cached meson_python-0.16.0-py3-none-any.whl.metadata (4.1 kB)

...
 -- abbreviated --
...
            Package cairo was not found in the pkg-config search path.
            Perhaps you should add the directory containing `cairo.pc'
            to the PKG_CONFIG_PATH environment variable
            No package 'cairo' found
            Command '['pkg-config', '--print-errors', '--exists', 'cairo >= 1.15.10']' returned non-zero exit status 1.
            [end of output]

        note: This error originates from a subprocess, and is likely not a problem with pip.
        ERROR: Failed building wheel for pycairo
      Failed to build pycairo
      ERROR: ERROR: Failed to build installable wheels for some pyproject.toml based projects (pycairo)
      [end of output]

  note: This error originates from a subprocess, and is likely not a problem with pip.
error: subprocess-exited-with-error

× pip subprocess to install build dependencies did not run successfully.
│ exit code: 1
╰─> See above for output.

note: This error originates from a subprocess, and is likely not a problem with pip.
Error: Process completed with exit code 1.
ukBaz commented 2 months ago

What operating system are you using this on? And have you done any research as to what a solution might be for this? (as there is a requirement for PyGObject to be installed)

erichiggins commented 2 months ago

Both Linux systems are running Ubuntu (version 20 or 22 I believe). I have not investigated solutions (most of my time was spent fixing the broken build) -- it's not clear to me why PyGObject is required or how it's used.

ukBaz commented 2 months ago

PyGObject provides GLib and the async mainloop

erichiggins commented 2 months ago

I can try to help but I need to know more. Why is GLib needed?

ukBaz commented 2 months ago

I'm not quite sure I understand what you are looking for. I'll give some answers but please let me know if I have misunderstood what you want.

You might want to start with the instructions for how to install the package. https://pygobject.gnome.org/getting_started.html#ubuntu-logo-ubuntu-debian-logo-debian

As to why it is needed, a lot of Bluetooth functionality is asynchronous (e.g. Characteristics notifications or scanning for devices) and the BlueZ library (the official Bluetooth stack on Linux) that Bluezero builds on top of uses the GLib library. The async functionality comes from the "mainloop". More information at: https://docs.gtk.org/glib/main-loop.html

erichiggins commented 2 months ago

This helps some, thank you!

Perhaps my question should be, what does this library provide that core Python and the standard libraries do not? Async functionality is available within Python 3, for example. https://docs.python.org/3/library/asyncio.html

Looking at the diff between version 0.8.0 and 0.9.0, it doesn't appear that much has functionally changed. https://github.com/ukBaz/python-bluezero/commit/8e984b62508b2feb6b953790393b3c0630a8eb64

Was adding this dependency necessary in order to support the addition of tx-power in advertising requests?

WayneKeenan commented 2 months ago

Perhaps this might help:

apt install libcairo2-dev

or this (which depends on the above anyway)

apt install libcairo-gobject2             

FYI:

Using Python's asyncio would still require a way to call the native C API's for the GLib runtime (native async events that talk to a native main loop that get's proxied to Python, etc) that the PyGObject C Extension Module provides access to.

The architecture: https://pygobject.gnome.org/

WayneKeenan commented 2 months ago

I think explicitly adding PyGObject brings in 1 or more dependancies that would sometimes not be available in a venv, but it's been a while so please don't quote me.

ukBaz commented 2 months ago

Hi @erichiggins ,

Looking at the diff between version 0.8.0 and 0.9.0, it doesn't appear that much has functionally changed.

Ah! OK, maybe I understand the confusion a little more. The dependency wasn't added in 0.9.0 because it was new functionality in that release. It was added to (mistakenly as it turns out) add more robustness to the dependency list.

This is very much a work in progress. Made that more complex by the fact that Bluetooth relies heavily on low-level OS libraries that haven't historically been pip friendly.

Bluezero has always had the goal of helping people get started with BlueZ and then possibly getting out of the way once people knew what they were doing. As result of this, connecting the asyncio event loop and the GLib event loop was never a goal.

There are other libraries such as bleak that do make that connection. Bleak is a cross platform library so it was done to be consistent API across all platforms.

ukBaz commented 2 months ago

Hi @WayneKeenan ,

I think explicitly adding PyGObject brings in 1 or more dependancies that would sometimes not be available in a venv, but it's been a while so please don't quote me.

I believe that the PyGObject project has done some work to make things more pip friendly these days and that is why I added the dependency. However, testing on different systems and different OSes is difficult for me. I'm hoping the more eyes we can get on this the more robust this will become over time 🤞

WayneKeenan commented 2 months ago

Hi @erichiggins ,

Both Linux systems are running Ubuntu (version 20 or 22 I believe).

What CPU arch are you on?

Is it Ubuntu Server or Desktop edition?

erichiggins commented 2 months ago

Hi @erichiggins ,

Both Linux systems are running Ubuntu (version 20 or 22 I believe).

What CPU arch are you on?

Is it Ubuntu Server or Desktop edition?

For mine, Intel arch, Ubuntu Desktop (variant). Unsure what the arch/version is for the Github action runner but I can find out.

WayneKeenan commented 2 months ago

I managed to replicate the error on a fresh AWS EC2 Ubuntu 24.04 LTS instance; a long story involving not have much success running VM's on my M1 Mac and also no RPi to hand.

But, the steps below gets to the point of being able to successfully install bluezero and run the examples, although it ultimately timeouts with an DBus.Error.NoReply as bluez doesn't respond as there is no underlying BLE hardware.

The critical thing is to remove PyGObject from setup.py.

sudo apt install python3.12-venv
sudo apt  install bluez        
python3 -m venv --system-site-packages venv
. ./venv/bin/activate
wget https://github.com/ukBaz/python-bluezero/archive/refs/tags/v0.9.0.tar.gz
tar xf v0.9.0.tar.gz 
cd python-bluezero-0.9.0/
nano setup.py  #   edit line 5 to be:  required_packages = []
pip install .  
python3 examples/eddystone_scanner.py

Hope it helps from both a user and maintainer perspective.

WayneKeenan commented 2 months ago

To resolve the original error I did this:

sudo apt install libcairo-dev

However, there is a further PyGObject dependancy on python (version 2) which I could not resolve.