Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve token-specified login flow. #169

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@

### Improvements

* Improved the login flow when IBMQ tokens are specified as environement variables.
[(#169)](https://github.com/PennyLaneAI/pennylane-qiskit/pull/169)

### Documentation

### Bug fixes
Expand All @@ -15,6 +18,8 @@

This release contains contributions from (in alphabetical order):

Tanner Rogalsky

---

# Release 0.20.0
Expand Down
23 changes: 18 additions & 5 deletions pennylane_qiskit/ibmq.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,24 @@ def __init__(self, wires, provider=None, backend="ibmq_qasm_simulator", shots=10
group = kwargs.get("group", "open")
project = kwargs.get("project", "main")

if token is not None:
# TODO: remove "no cover" when #173 is resolved
if token is not None: # pragma: no cover
# token was provided by the user, so attempt to enable an
# IBM Q account manually
ibmq_kwargs = {"url": url} if url is not None else {}
IBMQ.enable_account(token, **ibmq_kwargs)
def login():
ibmq_kwargs = {"url": url} if url is not None else {}
IBMQ.enable_account(token, **ibmq_kwargs)

active_account = IBMQ.active_account()
if active_account is None:
login()
else:
# There is already an active account:
# If the token is the same, do nothing.
# If the token is different, authenticate with the new account.
if active_account["token"] != token:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might be good to add a test case for this branch too.

IBMQ.disable_account()
login()
else:
# check if an IBM Q account is already active.
#
Expand All @@ -96,13 +109,13 @@ def __init__(self, wires, provider=None, backend="ibmq_qasm_simulator", shots=10

super().__init__(wires=wires, provider=p, backend=backend, shots=shots, **kwargs)

def batch_execute(self, circuits):
def batch_execute(self, circuits): # pragma: no cover
res = super().batch_execute(circuits)
if self.tracker.active:
self._track_run()
return res

def _track_run(self):
def _track_run(self): # pragma: no cover
"""Provide runtime information."""

time_per_step = self._current_job.time_per_step()
Expand Down
43 changes: 42 additions & 1 deletion tests/test_ibmq.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def token():
variable."""
t = os.getenv("IBMQX_TOKEN_TEST", None)

if t is None:
if t is None or t == '':
pytest.skip("Skipping test, no IBMQ token available")

yield t
Expand All @@ -32,6 +32,47 @@ def test_load_from_env(token, monkeypatch):
dev = IBMQDevice(wires=1)
assert dev.provider.credentials.is_ibmq()

def test_load_from_env_multiple_device(token, monkeypatch):
TannerRogalsky marked this conversation as resolved.
Show resolved Hide resolved
"""Test creating multiple IBMQ devices when the environment variable
for the IBMQ token was set."""
monkeypatch.setenv("IBMQX_TOKEN", token)
dev1 = IBMQDevice(wires=1)
dev2 = IBMQDevice(wires=1)

assert dev1.provider.credentials.is_ibmq()
assert dev2.provider.credentials.is_ibmq()

def test_load_from_env_multiple_device_and_token(monkeypatch):
TannerRogalsky marked this conversation as resolved.
Show resolved Hide resolved
"""Test creating multiple devices when the different tokens are defined
using an environment variable."""
mock_provider = "MockProvider"
mock_qiskit_device = MockQiskitDeviceInit()

with monkeypatch.context() as m:
m.setattr(ibmq.QiskitDevice, "__init__", mock_qiskit_device.mocked_init)

creds = []
def enable_account(new_creds):
creds.append(new_creds)
def active_account():
if len(creds) != 0:
return { "token": creds[-1] }
m.setattr(ibmq.IBMQ, "enable_account", enable_account)
m.setattr(ibmq.IBMQ, "disable_account", lambda: None)
m.setattr(ibmq.IBMQ, "active_account", active_account)

m.setenv("IBMQX_TOKEN", "TOKEN1")
dev1 = IBMQDevice(wires=1, provider=mock_provider)
# first login
assert creds == ["TOKEN1"]
dev1 = IBMQDevice(wires=1, provider=mock_provider)
# same token, login is elided
assert creds == ["TOKEN1"]

m.setenv("IBMQX_TOKEN", "TOKEN2")
dev2 = IBMQDevice(wires=1, provider=mock_provider)
# second login
assert creds == ["TOKEN1", "TOKEN2"]

def test_load_kwargs_takes_precedence(token, monkeypatch):
"""Test that with a potentially valid token stored as an environment
Expand Down