diff --git a/Orange/widgets/credentials.py b/Orange/widgets/credentials.py new file mode 100644 index 00000000000..eb6132bfa45 --- /dev/null +++ b/Orange/widgets/credentials.py @@ -0,0 +1,38 @@ +import keyring + +SERVICE_NAME = 'Orange3 - {}' + + +class CredentialManager: + """ + Class for storage of passwords in the system keyring service. + All attributes of this class are safely stored. + + Args: + service_name (str): service name used for storing in keyring. + + Examples: + >>> cm = CredentialManager('Widget Name') + >>> cm.username = 'Orange' # store username + >>> cm.password = 'Secret' # store password + + >>> cm.username # get username + 'Orange' + >>> cm.password # get password + 'Secret' + """ + def __init__(self, service_name): + self.__dict__['__service_name'] = SERVICE_NAME.format(service_name) + + @property + def service_name(self): + return self.__dict__['__service_name'] + + def __setattr__(self, key, value): + keyring.set_password(self.service_name, key, value) + + def __getattr__(self, item): + return keyring.get_password(self.service_name, item) + + def __delattr__(self, item): + keyring.delete_password(self.service_name, item) diff --git a/Orange/widgets/tests/test_credentials.py b/Orange/widgets/tests/test_credentials.py new file mode 100644 index 00000000000..5d9341913e5 --- /dev/null +++ b/Orange/widgets/tests/test_credentials.py @@ -0,0 +1,12 @@ +import unittest + +from Orange.widgets.credentials import CredentialManager + + +class CredentialManagerTests(unittest.TestCase): + def test_credential_manager(self): + cm = CredentialManager('Orange') + cm.key = 'Foo' + self.assertEqual(cm.key, 'Foo') + del cm.key + self.assertEqual(cm.key, None) diff --git a/requirements-core.txt b/requirements-core.txt index d25000c4b32..398237ed4d1 100644 --- a/requirements-core.txt +++ b/requirements-core.txt @@ -8,3 +8,5 @@ xlrd>=0.9.2 chardet>=2.3.0 # Multiprocessing abstraction joblib>=0.9.4 +keyring +keyrings.alt # for running test on travis