Skip to content

Fix protobuf dependency conflict with librespot and pywidevine - #110

Open
JavaGT wants to merge 1 commit into
glomatico:mainfrom
JavaGT:fix/protobuf-conflict
Open

JavaGT wants to merge 1 commit into
glomatico:mainfrom
JavaGT:fix/protobuf-conflict

Conversation

@JavaGT

@JavaGT JavaGT commented Sep 13, 2026

Copy link
Copy Markdown

Fixes #105, fixes #103.

What

A fresh pip install 'votify[librespot]' now works out of the box: protobuf is declared as a direct dependency, the librespot extra is capped to the only release that can resolve alongside it, and the pure-Python protobuf backend is selected automatically when librespot is installed.

Why

Three overlapping problems cause the failures reported in #105 and #103:

  1. votify's bundled protobuf gencode (votify/api/proto/*_pb2.py, generated by protoc 6.33.4) requires a protobuf runtime >= 6.33, but pyproject.toml never declared protobuf — it only arrived transitively via pywidevine (protobuf>=6.33.0,<7). Environments where an older protobuf gets installed crash at startup with ImportError: cannot import name 'runtime_version' (ImportError: cannot import name 'runtime_version' from 'google.protobuf' #103).
  2. The librespot extra was unbounded (librespot>=0.0.1), but every later librespot release pins an incompatible protobuf (==4.21.0 for 0.0.2, ==3.20.1 for 0.0.3–0.0.10), which cannot resolve alongside pywidevine. That is the resolution conflict in Dependency conflict: protobuf incompatibility between librespot and pywidevine makes Votify unusable #105.
  3. Even the only resolvable combo (librespot 0.0.1 + protobuf 6.33.x, which is what uv.lock already ships) breaks at runtime: librespot 0.0.1's gencode predates protoc 3.19 and only loads under the pure-Python protobuf implementation — hence the PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python workaround in the Dependency conflict: protobuf incompatibility between librespot and pywidevine makes Votify unusable #105 comments. Since session_type defaults to librespot (votify/api/api.py), this hit the default path.

The changes

  • pyproject.toml: declare protobuf>=6.33.5 in [project].dependencies (floor matches requirements.txt; no <7 cap — protobuf's official cross-version guarantee supports gencode since 3.20.0 through runtime 8.x).
  • pyproject.toml: cap the extra at librespot>=0.0.1,<0.0.2 — the only release whose metadata is compatible, making resolution deterministic instead of dependent on pip backtracking. Worth lifting when librespot-python regenerates its protos and drops the protobuf==3.20.1 pin.
  • votify/__init__.py: os.environ.setdefault("PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION", "python"), guarded by find_spec("librespot"), so it runs before any protobuf import on the CLI path. Users without the extra keep the faster default (upb) backend; an explicitly set environment variable is respected.
  • uv.lock: regenerated with uv lock.

Verification

All in fresh venvs (Python 3.14.6 and the 3.10 floor from .python-version), re-confirmed today on 3.10:

  • pip install votify and pip install 'votify[librespot]' both resolve; pip check clean; resolves librespot 0.0.1 + protobuf 6.33.6 (matches the combo uv.lock already shipped).
  • votify --help runs in both installs.
  • With the CLI's import order, librespot 0.0.1 and votify/pywidevine protobuf messages import and construct successfully under the selected backend; without librespot installed, the upb backend stays active.
  • pip install 'votify[librespot]' 'librespot==0.0.10' fails resolution as intended; uv lock --check passes.
  • Not tested: an actual download through the librespot session (requires Spotify credentials and a .wvd device file).

Attribution

This PR was produced with AI assistance under the direction of @JavaGT:

  • Exploration, evidence verification, implementation: GLM agents (ZCode)
  • Planning: GLM agents; plan audited by the consultants below
  • Plan & implementation audit: OpenAI GPT-5.6 ("Luna") and xAI Grok 4.6,
    consulted via opencode
    Every change was cross-reviewed by the consultant models and the final diff
    verified against the described behavior. Happy to adjust or close any part
    of this — tell me what doesn't fit the project's direction.

- Declare protobuf>=6.33.5 directly in pyproject: votify's generated
  protobuf code requires a 6.33+ runtime but it was previously only
  pulled in transitively via pywidevine, so environments where an
  incompatible protobuf (e.g. 3.20.1 from newer librespot releases) got
  installed crashed with ImportError: cannot import name runtime_version

- Cap the librespot extra at 0.0.1: every later librespot release pins
  protobuf==3.20.1 (0.0.3+) or ==4.21.0 (0.0.2), which cannot resolve
  alongside pywidevine's protobuf>=6.33.0,<7.0.0 requirement

- Select the pure-Python protobuf implementation when librespot is
  installed: librespot 0.0.1 ships gencode predating protoc 3.19 that
  only loads under that backend, and votify's default session_type is
  librespot; this makes a fresh votify[librespot] install work as-is

References glomatico#105, glomatico#103

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

1 participant