1
0
Fork 0
mirror of https://github.com/borgbase/vorta synced 2025-01-03 05:36:19 +00:00

Resolve conflight with pytest-xdist and pyobjc.

This commit is contained in:
Manu 2018-12-06 18:14:28 +08:00
parent a2e9bf2886
commit 014f957c56
2 changed files with 54 additions and 39 deletions

View file

@ -1,61 +1,76 @@
# flake8: noqa
"""
A dirty objc implementation to access the macOS Keychain. Because the
keyring implementation was causing trouble when used together with other
objc modules.
From https://gist.github.com/apettinen/5dc7bf1f6a07d148b2075725db6b1950
Adapted from https://gist.github.com/apettinen/5dc7bf1f6a07d148b2075725db6b1950
"""
import keyring
import objc
from ctypes import c_char
from Foundation import NSBundle
Security = NSBundle.bundleWithIdentifier_('com.apple.security')
S_functions = [
('SecKeychainGetTypeID', b'I'),
('SecKeychainItemGetTypeID', b'I'),
('SecKeychainAddGenericPassword', b'i^{OpaqueSecKeychainRef=}I*I*I*o^^{OpaqueSecKeychainItemRef}'),
('SecKeychainOpen', b'i*o^^{OpaqueSecKeychainRef}'),
('SecKeychainFindGenericPassword', b'i@I*I*o^Io^^{OpaquePassBuff}o^^{OpaqueSecKeychainItemRef}'),
]
objc.loadBundleFunctions(Security, globals(), S_functions)
SecKeychainRef = objc.registerCFSignature(
'SecKeychainRef', b'^{OpaqueSecKeychainRef=}', SecKeychainGetTypeID()) # noqa: F821
SecKeychainItemRef = objc.registerCFSignature(
'SecKeychainItemRef', b'^{OpaqueSecKeychainItemRef=}', SecKeychainItemGetTypeID()) # noqa: F821
PassBuffRef = objc.createOpaquePointerType(
"PassBuffRef", b"^{OpaquePassBuff=}", None)
from keyring.backend import KeyringBackend
def resolve_password(password_length, password_buffer):
return (c_char * password_length).from_address(password_buffer.__pointer__)[:].decode('utf-8')
# Get the login keychain
result, login_keychain = SecKeychainOpen(b'login.keychain', None) # noqa: F821
class VortaDarwinKeyring(keyring.backend.KeyringBackend):
class VortaDarwinKeyring(KeyringBackend):
"""Homemade macOS Keychain Service"""
login_keychain = None
def _set_keychain(self):
"""
Lazy import to avoid conflict with pytest-xdist.
"""
import objc
from Foundation import NSBundle
Security = NSBundle.bundleWithIdentifier_('com.apple.security')
S_functions = [
('SecKeychainGetTypeID', b'I'),
('SecKeychainItemGetTypeID', b'I'),
('SecKeychainAddGenericPassword', b'i^{OpaqueSecKeychainRef=}I*I*I*o^^{OpaqueSecKeychainItemRef}'),
('SecKeychainOpen', b'i*o^^{OpaqueSecKeychainRef}'),
('SecKeychainFindGenericPassword', b'i@I*I*o^Io^^{OpaquePassBuff}o^^{OpaqueSecKeychainItemRef}'),
]
objc.loadBundleFunctions(Security, globals(), S_functions)
SecKeychainRef = objc.registerCFSignature('SecKeychainRef', b'^{OpaqueSecKeychainRef=}', SecKeychainGetTypeID())
SecKeychainItemRef = objc.registerCFSignature('SecKeychainItemRef', b'^{OpaqueSecKeychainItemRef=}', SecKeychainItemGetTypeID())
PassBuffRef = objc.createOpaquePointerType('PassBuffRef', b'^{OpaquePassBuff=}', None)
# Get the login keychain
result, login_keychain = SecKeychainOpen(b'login.keychain', None)
self.login_keychain = login_keychain
@classmethod
def priority(cls):
return 5
def set_password(self, service, repo_url, password):
result, keychain_item = SecKeychainAddGenericPassword( # noqa: F821
login_keychain, len(service), service, len(repo_url), repo_url, len(password), password, None)
if not self.login_keychain: self._set_keychain()
SecKeychainAddGenericPassword(
self.login_keychain,
len(service), service.encode(),
len(repo_url), repo_url.encode(),
len(password), password.encode(),
None)
def get_password(self, service, repo_url):
result, password_length, password_buffer, keychain_item = SecKeychainFindGenericPassword( # noqa: F821
login_keychain, len(service), service.encode(), len(repo_url), repo_url.encode(), None, None, None)
if not self.login_keychain: self._set_keychain()
result, password_length, password_buffer, keychain_item = SecKeychainFindGenericPassword(
self.login_keychain, len(service), service.encode(), len(repo_url), repo_url.encode(), None, None, None)
password = None
if (result == 0) and (password_length != 0):
# We apparently were able to find a password
password = resolve_password(password_length, password_buffer)
password = _resolve_password(password_length, password_buffer)
return password
def delete_password(self, service, repo_url):
pass
def _resolve_password(password_length, password_buffer):
from ctypes import c_char
return (c_char * password_length).from_address(password_buffer.__pointer__)[:].decode('utf-8')

View file

@ -7,9 +7,9 @@ def get_updater():
if sys.platform == 'darwin' and getattr(sys, 'frozen', False):
# Use sparkle framework on macOS.
# Examples: https://programtalk.com/python-examples/objc.loadBundle/
from objc import loadBundle
import objc
bundle_path = os.path.join(os.path.dirname(sys.executable), os.pardir, 'Frameworks', 'Sparkle.framework')
loadBundle('Sparkle', globals(), bundle_path)
objc.loadBundle('Sparkle', globals(), bundle_path)
sparkle = SUUpdater.sharedUpdater() # noqa: F821
if SettingsModel.get(key='updates_include_beta').value:
sparkle.SharedUpdater.FeedURL = 'https://borgbase.github.io/vorta/appcast-pre.xml'