Skip to content

Commit

Permalink
Use full class name for account name, spelling
Browse files Browse the repository at this point in the history
Fixes after review:
* use the full class name (module + class) for the account name, in
  order to ensure it is unique, moving the calculation to its own
  function for reusability.
* spelling and other fixes.
  • Loading branch information
diego-plan9 committed Jul 20, 2018
1 parent 8e1ca57 commit 46286a6
Show file tree
Hide file tree
Showing 10 changed files with 59 additions and 20 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ your IBM Q Experience account:
page to `store_credentials`.

After calling `store_credentials()`, your credentials will be stored into disk.
Once they are stored, you can automatically load and use them in your program
Once they are stored, Qiskit will automatically load and use them in your program
via:

```python
Expand Down
2 changes: 1 addition & 1 deletion doc/install.rst
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,7 @@ following contents:
And customize the following lines:

* copy/paste your API token into the space between the quotation marks on the
first line (``APItoken = 'PUT_YOUR_API_TOKEN_HERE``).
first line (``APItoken = 'PUT_YOUR_API_TOKEN_HERE'``).
* if you have access to the IBM Q features, you also need to setup the
values for your url, hub, group, and project. You can do so by filling the
``config`` variable with the values you can find on your IBM Q account
Expand Down
3 changes: 2 additions & 1 deletion qiskit/wrapper/_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ def register(*args, provider_class=IBMQProvider, **kwargs):
"""
# Try to autodiscover credentials if not passed.
if not args and not kwargs and provider_class == IBMQProvider:
kwargs = credentials.discover_credentials().get(IBMQProvider.__name__) or {}
kwargs = credentials.discover_credentials().get(
credentials.get_account_name(IBMQProvider)) or {}
if not kwargs:
raise QISKitError(
'No IBMQ credentials found. Please pass them explicitly or '
Expand Down
1 change: 1 addition & 0 deletions qiskit/wrapper/credentials/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@
from ._configrc import read_credentials_from_qiskitrc, store_credentials
from ._environ import read_credentials_from_environ
from ._qconfig import read_credentials_from_qconfig
from ._utils import get_account_name


logger = logging.getLogger(__name__)
Expand Down
12 changes: 8 additions & 4 deletions qiskit/wrapper/credentials/_configrc.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@

from qiskit import QISKitError
from qiskit.backends.ibmq import IBMQProvider
from ._utils import get_account_name


DEFAULT_QISKITRC_FILE = os.path.join(os.path.expanduser("~"),
Expand Down Expand Up @@ -51,11 +52,14 @@ def read_credentials_from_qiskitrc(filename=None):
credentials_dict = {}
for name in config_parser.sections():
single_credentials = dict(config_parser.items(name))
# TODO: 'proxies' is the only value that is a dict. Consider moving to
# json configuration or splitting into single keys manually.
# Individually convert keys to their right types.
# TODO: consider generalizing, moving to json configuration or a more
# robust alternative.
if 'proxies' in single_credentials.keys():
single_credentials['proxies'] = literal_eval(
single_credentials['proxies'])
if 'verify' in single_credentials.keys():
single_credentials['verify'] = bool(single_credentials['verify'])
credentials_dict[name] = single_credentials

return credentials_dict
Expand Down Expand Up @@ -100,7 +104,7 @@ def store_credentials(provider_class=IBMQProvider, overwrite=False,
the account_name could not be assigned.
"""
# Set the name of the Provider from the class.
account_name = provider_class.__name__
account_name = get_account_name(provider_class)
# Read the current providers stored in the configuration file.
filename = filename or DEFAULT_QISKITRC_FILE
credentials = read_credentials_from_qiskitrc(filename)
Expand All @@ -127,7 +131,7 @@ def remove_credentials(provider_class=IBMQProvider, filename=None):
file.
"""
# Set the name of the Provider from the class.
account_name = provider_class.__name__
account_name = get_account_name(provider_class)
credentials = read_credentials_from_qiskitrc(filename)

try:
Expand Down
4 changes: 2 additions & 2 deletions qiskit/wrapper/credentials/_environ.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
import os

from qiskit.backends.ibmq import IBMQProvider

from ._utils import get_account_name

# Dictionary that maps `ENV_VARIABLE_NAME` to credential parameter.
VARIABLES_MAP = {
Expand Down Expand Up @@ -44,4 +44,4 @@ def read_credentials_from_environ():
if os.getenv(envar_name):
credentials[credential_key] = os.getenv(envar_name)

return {IBMQProvider.__name__: credentials}
return {get_account_name(IBMQProvider): credentials}
3 changes: 2 additions & 1 deletion qiskit/wrapper/credentials/_qconfig.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from qiskit import QISKitError
from qiskit.backends.ibmq import IBMQProvider
from ._utils import get_account_name


DEFAULT_QCONFIG_FILE = 'Qconfig.py'
Expand Down Expand Up @@ -59,4 +60,4 @@ def read_credentials_from_qconfig():
# pylint: disable=broad-except
raise QISKitError('Error loading Qconfig.py: %s' % str(ex))

return {IBMQProvider.__name__: credentials}
return {get_account_name(IBMQProvider): credentials}
25 changes: 25 additions & 0 deletions qiskit/wrapper/credentials/_utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# -*- coding: utf-8 -*-

# Copyright 2018, IBM.
#
# This source code is licensed under the Apache License, Version 2.0 found in
# the LICENSE.txt file in the root directory of this source tree.

"""
Utilities for credentials.
"""


def get_account_name(provider_class):
"""
Return the account name for a particular provider. This name is used by
Qiskit internally and in the configuration file and uniquely identifies
a provider.
Args:
provider_class (class): class for the account.
Returns:
str: the account name.
"""
return '{}.{}'.format(provider_class.__module__, provider_class.__name__)
10 changes: 6 additions & 4 deletions test/python/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@
import unittest
from unittest.util import safe_repr
from qiskit import __path__ as qiskit_path
from qiskit.wrapper.credentials import discover_credentials
from qiskit.backends.ibmq import IBMQProvider
from qiskit.wrapper.credentials import discover_credentials, get_account_name
from qiskit.wrapper.defaultqiskitprovider import DefaultQISKitProvider


Expand Down Expand Up @@ -249,17 +250,18 @@ def _(*args, **kwargs):
_wrapper._DEFAULT_PROVIDER = DefaultQISKitProvider()

# Attempt to read the standard credentials.
account_name = get_account_name(IBMQProvider)
discovered_credentials = discover_credentials()
try:
credentials = next(iter(discovered_credentials.values()))
if account_name in discovered_credentials.keys():
credentials = discovered_credentials[account_name]
kwargs.update({
'QE_TOKEN': credentials.get('token'),
'QE_URL': credentials.get('url'),
'hub': credentials.get('hub'),
'group': credentials.get('group'),
'project': credentials.get('project'),
})
except StopIteration:
else:
raise Exception('Could not locate valid credentials')

return func(*args, **kwargs)
Expand Down
17 changes: 11 additions & 6 deletions test/python/test_registration.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,20 @@
import qiskit
from qiskit import QISKitError
from qiskit.backends.ibmq import IBMQProvider
from qiskit.wrapper.credentials import _configrc, _qconfig, discover_credentials
from qiskit.wrapper.credentials import (_configrc, _qconfig,
discover_credentials, get_account_name)
from qiskit.wrapper.credentials._environ import VARIABLES_MAP
from .common import QiskitTestCase


# TODO: NamedTemporaryFiles do not support name in Windows
@skipIf(os.name == 'nt', 'Test not supported in Windows')
class TestWrapperCredentuals(QiskitTestCase):
class TestWrapperCredentials(QiskitTestCase):
"""Wrapper autoregistration and credentials test case."""
def setUp(self):
super(TestWrapperCredentials, self).setUp()
self.ibmq_account_name = get_account_name(IBMQProvider)

def test_autoregister_no_credentials(self):
"""Test register() with no credentials available."""
with no_file('Qconfig.py'), no_file(_configrc.DEFAULT_QISKITRC_FILE), no_envs():
Expand Down Expand Up @@ -73,8 +78,8 @@ def test_environ_over_qiskitrc(self):
with no_file('Qconfig.py'), custom_envs({'QE_TOKEN': 'ENVIRON_TOKEN'}):
credentials = discover_credentials()

self.assertIn('IBMQProvider', credentials)
self.assertEqual(credentials['IBMQProvider']['token'], 'ENVIRON_TOKEN')
self.assertIn(self.ibmq_account_name, credentials)
self.assertEqual(credentials[self.ibmq_account_name]['token'], 'ENVIRON_TOKEN')

def test_qconfig_over_all(self):
"""Test order, with qconfig"""
Expand All @@ -85,8 +90,8 @@ def test_qconfig_over_all(self):
custom_envs({'QE_TOKEN': 'ENVIRON_TOKEN'}):
credentials = discover_credentials()

self.assertIn('IBMQProvider', credentials)
self.assertEqual(credentials['IBMQProvider']['token'], 'QCONFIG_TOKEN')
self.assertIn(self.ibmq_account_name, credentials)
self.assertEqual(credentials[self.ibmq_account_name]['token'], 'QCONFIG_TOKEN')


# Context managers
Expand Down

0 comments on commit 46286a6

Please sign in to comment.