Po spustení brew upgrade na mojom Mac M3 OfflineIMAP náhle prestal fungovať s touto chybou:

OfflineIMAP 8.0.1
  Licensed under the GNU GPL v2 or any later version (with an OpenSSL exception)
imaplib2 v3.06, Python v3.14.0, OpenSSL 3.6.0 1 Oct 2025
Account sync Peter:
 *** Processing account Peter
 Establishing connection to imap.mailbox.org:993 (PeterRemote)
 ERROR: While attempting to sync account 'Peter'
  No module named 'keyring'
 *** Finished account 'Peter' in 0:00
ERROR: Exceptions occurred during the run!
ERROR: While attempting to sync account 'Peter'
  ModuleNotFoundError: No module named 'keyring'

Pre kontext, OfflineIMAP fungoval perfektne dlhú dobu. Nikdy som nepotreboval žiadny modul keyring — jednoducho by sa ma opýtal na heslo, keď bolo potrebné. Aktualizácia cez brew pravdepodobne aktualizovala buď OfflineIMAP alebo Python 3.14, čím rozlámala túto závislosť.

Pochopenie príčiny problému #

Problém nastáva, pretože:

  1. Homebrew aktualizoval OfflineIMAP alebo Python na novšiu verziu
  2. Nová verzia má implicitnú závislosť na Python module keyring
  3. Formula OfflineIMAP v Homebrew nedeklaruje keyring ako závislosť
  4. Modul chýba v Python prostredí, ktoré OfflineIMAP používa

Keď som skontroloval, ktorý Python OfflineIMAP používa:

which offlineimap
head -1 (which offlineimap)

Ukázalo to na /opt/homebrew/opt/[email protected] — Homebrew-spravovanú inštaláciu Pythonu.

Systémová inštalácia #

Existujú dva spôsoby, ako nainštalovať chýbajúci modul keyring — prvý je systémový:

/opt/homebrew/opt/[email protected]/bin/pip3 install keyring --break-system-packages

Tým sa keyring nainštaluje priamo do site-packages adresára Pythonu 3.14 od Homebrew na /opt/homebrew/lib/python3.14/site-packages/.

Collecting keyring
  Downloading keyring-25.7.0-py3-none-any.whl.metadata (21 kB)
Collecting jaraco.classes (from keyring)
  Downloading jaraco.classes-3.4.0-py3-none-any.whl.metadata (2.9 kB)
...
Successfully installed jaraco.classes-3.4.0 jaraco.context-6.0.1 jaraco.functools-4.1.0 keyring-25.7.0 more-itertools-10.5.0

Druhá možnosť je inštalácia pre používateľa pridaním prepínača --user:

/opt/homebrew/opt/[email protected]/bin/pip3 install keyring --break-system-packages --user

Tým sa keyring nainštaluje do lokálneho adresára Python balíkov používateľa na ~/.local/lib/python3.14/site-packages/.

Pre jednopouúžívateľské Mac systémy (najčastejší prípad) je Možnosť 1 jednoduchšia a priamočiarejšia. Pre viacpouúžívateľské systémy alebo ak chcete, aby balíky prežili aktualizácie Pythonu, je lepšia Možnosť 2.

Pochopenie --break-system-packages #

Príznak --break-system-packages je požadovaný kvôli PEP 668, ktorý zabraňuje pip-u modifikovať systémom spravované inštalácie Pythonu. Moderné distribúcie Pythonu (vrátane tých od Homebrew) sú označené ako „externe spravované”, aby sa predišlo konfliktom medzi pip a správcom systémových balíkov.

Hoci názov príznaku znie nebezpečne, na macOS s Homebrew je relatívne bezpečný, pretože:

  • Python od Homebrew je izolovaný od systémového Pythonu macOS (/usr/bin/python3)
  • Poškodenie Pythonu od Homebrew neovplyvní systémové nástroje macOS
  • Vždy sa dá zotaviť pomocou brew reinstall [email protected]

Overenie #

Po inštalácii keyring OfflineIMAP funguje perfektne:

offlineimap

Chyba je preč a synchronizácia e-mailov prebieha normálne.

Prečo sa to stalo #

Pri pohľade na formulu OfflineIMAP v Homebrew, modul keyring nie je uvedený ako závislosť zdroja:

resource "distro" do
  url "https://files.pythonhosted.org/packages/.../distro-1.9.0.tar.gz"
  sha256 "2fa77c6fd8940f116ee1d6b94a2f90b13b5ea8d019b98bc8bafdcabcdd9bdbed"
end

resource "imaplib2" do
  # ...
end

resource "rfc6555" do
  # ...
end

resource "urllib3" do
  # ...
end

# keyring is missing!

Zdá sa, že ide o prehliadnutie vo formule Homebrew. Správna oprava by bola odoslať pull request do homebrew-core s pridaním keyring a jeho závislostí (jaraco.classes, jaraco.context, jaraco.functools, more-itertools) do formuly.

Záver #

Prístup s --break-system-packages je pragmatická oprava tejto medzery v závislosti vo formule OfflineIMAP v Homebrew. Hoci nie je to najelegantnejšie riešenie, funguje spoľahlivo a dá sa ľahko zopakovať v prípade potreby po aktualizáciách Pythonu. Príjemné používanie!

Odkazy #