diff --git a/CHANGES.rst b/CHANGES.rst index db3be646..7efe17bd 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,14 @@ +v23.3.0 +------- + +* #529: macOS backend is no longer viable if the API module + cannot be loaded. Prevents "symbol not found" errors on + macOS 11 (Big Sur) and later when a "universal2" binary + is not used (available for Python 3.8.7 and later). + +* #547: Tests no longer attempt to run macOS backends even + on macOS when the backend is non-viable. + v23.2.2 ------- diff --git a/README.rst b/README.rst index 9ccea5c1..8ea651f2 100644 --- a/README.rst +++ b/README.rst @@ -54,6 +54,13 @@ install dbus-python as a system package. .. _dbus-python: https://gitlab.freedesktop.org/dbus/dbus-python +Compatibility - macOS +===================== + +macOS keychain support macOS 11 (Big Sur) and later requires Python 3.8.7 +or later with the "universal2" binary. See +`#525 `_ for details. + Using Keyring ============= diff --git a/conftest.py b/conftest.py index 2bca317c..ab0021e0 100644 --- a/conftest.py +++ b/conftest.py @@ -1,8 +1,23 @@ -import platform +import ctypes collect_ignore = ["hook-keyring.backend.py"] -if platform.system() != 'Darwin': - collect_ignore.append('keyring/backends/macOS/api.py') + +def macos_api_ignore(): + """ + Starting with macOS 11, the security API becomes + non-viable except on universal2 binaries. + + Ref #525. + """ + + try: + ctypes.CDLL(ctypes.util.find_library('Security')).SecItemAdd + return False + except Exception: + return True + + +collect_ignore.extend(['keyring/backends/macOS/api.py'] * macos_api_ignore()) collect_ignore.append('keyring/devpi_client.py') diff --git a/keyring/backends/macOS/__init__.py b/keyring/backends/macOS/__init__.py index 4a33b8e0..ca91bc98 100644 --- a/keyring/backends/macOS/__init__.py +++ b/keyring/backends/macOS/__init__.py @@ -28,6 +28,8 @@ def priority(cls): """ if platform.system() != 'Darwin': raise RuntimeError("macOS required") + if 'api' not in globals(): + raise RuntimeError("Security API unavailable") return 5 def set_password(self, service, username, password): diff --git a/tests/backends/test_macOS.py b/tests/backends/test_macOS.py index 5d1fd5b0..5cbbad6a 100644 --- a/tests/backends/test_macOS.py +++ b/tests/backends/test_macOS.py @@ -1,16 +1,14 @@ -import sys - import pytest +import keyring from keyring.testing.backend import BackendBasicTests from keyring.backends import macOS -def is_osx_keychain_supported(): - return sys.platform in ('mac', 'darwin') - - -@pytest.mark.skipif(not is_osx_keychain_supported(), reason="Needs macOS") -class TestOSXKeychain(BackendBasicTests): +@pytest.mark.skipif( + not keyring.backends.macOS.Keyring.viable, + reason="macOS backend not viable", +) +class Test_macOSKeychain(BackendBasicTests): def init_keyring(self): return macOS.Keyring()