Skip to content

Commit

Permalink
improve error on setting shots on new device api (#5616)
Browse files Browse the repository at this point in the history
**Context:**

As more devices switch to the new device interface, users may request
properties or behaviours that are no longer there. The current error
messages do not sufficiently alert users to the fact that the device
interface has changed.

**Description of the Change:**

Make a more informative error when trying to set the shots or access a
non-existant attribute.

**Benefits:**

**Possible Drawbacks:**

**Related GitHub Issues:**
  • Loading branch information
albi3ro committed May 2, 2024
1 parent 8fb99cb commit f15151d
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 1 deletion.
4 changes: 4 additions & 0 deletions doc/releases/changelog-0.36.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -551,6 +551,10 @@

<h3>Bug fixes 🐛</h3>

* Improves the error message for setting shots on the new device interface, or trying to access a property
that no longer exists.
[(#5616)](https://github.com/PennyLaneAI/pennylane/pull/5616)

* Fixed a bug where `qml.draw` and `qml.draw_mpl` incorrectly raised errors for circuits collecting statistics on mid-circuit measurements
while using `qml.defer_measurements`.
[(#5610)](https://github.com/PennyLaneAI/pennylane/pull/5610)
Expand Down
18 changes: 18 additions & 0 deletions pennylane/devices/device_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -177,6 +177,14 @@ def __repr__(self):
details = f"({', '.join(details)}) " if details else ""
return f"<{self.name} device {details}at {hex(id(self))}>"

def __getattr__(self, key):
raise AttributeError(
f"{type(self).__name__} has no attribute '{key}'."
" You may be looking for a property or method present in the legacy device interface."
f" Please consult the {type(self).__name__} documentation for an updated list of public"
" properties and methods."
)

@property
def shots(self) -> Shots:
"""Default shots for execution workflows containing this device.
Expand All @@ -187,6 +195,16 @@ def shots(self) -> Shots:
"""
return self._shots

@shots.setter
def shots(self, _):
raise AttributeError(
(
"Shots can no longer be set on a device instance. "
"You can set shots on a call to a QNode, on individual tapes, or "
"create a new device instance instead."
)
)

@property
def wires(self) -> Wires:
"""The device wires.
Expand Down
13 changes: 12 additions & 1 deletion tests/devices/experimental/test_device_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -71,9 +71,20 @@ def test_shots(self):
shots_dev = self.MinimalDevice(shots=100)
assert shots_dev.shots == qml.measurements.Shots(100)

with pytest.raises(AttributeError):
with pytest.raises(
AttributeError, match="Shots can no longer be set on a device instance."
):
self.dev.shots = 100 # pylint: disable=attribute-defined-outside-init

def test_getattr_error(self):
"""Test that querying a property that doesn't exist informs about interface change."""

with pytest.raises(
AttributeError,
match=r"You may be looking for a property or method present in the legacy device",
):
_ = self.dev.expand_fn

def test_tracker_set_on_initialization(self):
"""Test that a new tracker instance is initialized with the class."""
assert isinstance(self.dev.tracker, qml.Tracker)
Expand Down

0 comments on commit f15151d

Please sign in to comment.