Repository: PennyLaneAI/pennylane
Pull request #1666 (2021-09-17 11:44:25)

bugfix for device shot list processing
Found when inspecting [PR 1659](https://github.com/PennyLaneAI/pennylane/pull/1659/files).

Previously, this code:
```
import pennylane as qml

dev = qml.device('default.gaussian', wires=1, shots=[2,2])

@qml.qnode(dev)
def circuit():
    return qml.sample(qml.X(0))

circuit(shots=2)
```
Raised the warning:
```
DeviceError: Shots must be a single non-negative integer or a sequence of non-negative integers.
```

This is because the original devices shots (2+2 = 4) was of type `np.int64` instead of type `int`.  

This makes it so device shots will be an int even when derived from a shot list.


github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [.github/CHANGELOG.md](/PennyLaneAI/pennylane/blob/master/.github/CHANGELOG.md) with:
* A one-to-two sentence description of the change. You may include a small working example for new features.
* A link back to this PR.
* Your name (or GitHub username) in the contributors section.
codecov[bot]: # [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1666?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
> :exclamation: No coverage uploaded for pull request base (`v0.18.0-rc0@0e9cbdb`). [Click here to learn what that means](https://docs.codecov.io/docs/error-reference?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#section-missing-base-commit).
> The diff coverage is `n/a`.

[![Impacted file tree graph](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1666/graphs/tree.svg?width=650&height=150&src=pr&token=9S3YzlUgGk&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1666?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)

```diff
@@              Coverage Diff               @@
##             v0.18.0-rc0    #1666   +/-   ##
==============================================
  Coverage               ?   99.14%           
==============================================
  Files                  ?      197           
  Lines                  ?    14431           
  Branches               ?        0           
==============================================
  Hits                   ?    14307           
  Misses                 ?      124           
  Partials               ?        0           
```



------

[Continue to review full report at Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1666?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).
> **Legend** - [Click here to learn more](https://docs.codecov.io/docs/codecov-delta?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI)
> `Δ = absolute <relative> (impact)`, `ø = not affected`, `? = missing data`
> Powered by [Codecov](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1666?src=pr&el=footer&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Last update [0e9cbdb...d9a5ae7](https://codecov.io/gh/PennyLaneAI/pennylane/pull/1666?src=pr&el=lastupdated&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI). Read the [comment docs](https://docs.codecov.io/docs/pull-request-comments?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).


Patch:
diff --git a/.github/CHANGELOG.md b/.github/CHANGELOG.md
index 4592155d8..302a7d6e5 100644
--- a/.github/CHANGELOG.md
+++ b/.github/CHANGELOG.md
@@ -461,6 +461,9 @@ and requirements-ci.txt (unpinned). This latter would be used by the CI.
 
 <h3>Bug fixes</h3>
 
+* Fix bug with shot vectors and `Device` base class.
+  [(#1666)](https://github.com/PennyLaneAI/pennylane/pull/1666)
+
 * Fix bug with norm and Jax tracers (jit) when using `QubiStateVector`.
   [(#1649)](https://github.com/PennyLaneAI/pennylane/pull/1649)
   
diff --git a/pennylane/_device.py b/pennylane/_device.py
index f6c74ee67..3824d2a51 100644
--- a/pennylane/_device.py
+++ b/pennylane/_device.py
@@ -89,7 +89,7 @@ def _process_shot_sequence(shot_list):
     else:
         raise ValueError(f"Unknown shot sequence format {shot_list}")
 
-    total_shots = np.sum(np.prod(shot_vector, axis=1))
+    total_shots = int(np.sum(np.prod(shot_vector, axis=1)))
     return total_shots, shot_vector
 
 
diff --git a/pennylane/circuit_drawer/mpldrawer.py b/pennylane/circuit_drawer/mpldrawer.py
index 58ba86653..2993363df 100644
--- a/pennylane/circuit_drawer/mpldrawer.py
+++ b/pennylane/circuit_drawer/mpldrawer.py
@@ -16,14 +16,12 @@ This module contains the MPLDrawer class for creating circuit diagrams with matp
 """
 from collections.abc import Iterable
 
+has_mpl = True
 try:
     import matplotlib.pyplot as plt
     from matplotlib import patches
 except (ModuleNotFoundError, ImportError) as e:
-    raise ImportError(
-        "Module matplotlib is required for ``MPLDrawer`` class. "
-        "You can install matplotlib via \n\n   pip install matplotlib"
-    ) from e
+    has_mpl = False
 
 
 def _to_tuple(a):
@@ -217,6 +215,12 @@ class MPLDrawer:
 
     def __init__(self, n_layers, n_wires, wire_options=None, figsize=None):
 
+        if not has_mpl:
+            raise ImportError(
+                "Module matplotlib is required for ``MPLDrawer`` class. "
+                "You can install matplotlib via \n\n   pip install matplotlib"
+            )
+
         self.n_layers = n_layers
         self.n_wires = n_wires
 


Test patch:
diff --git a/tests/test_device.py b/tests/test_device.py
index 85518f218..4771ad21e 100644
--- a/tests/test_device.py
+++ b/tests/test_device.py
@@ -166,18 +166,41 @@ def mock_device(monkeypatch):
         yield get_device
 
 
-def test_shot_vector_property():
-    dev = qml.device("default.qubit", wires=1, shots=[1, 3, 3, 4, 4, 4, 3])
-    shot_vector = dev.shot_vector
-    assert len(shot_vector) == 4
-    assert shot_vector[0].shots == 1
-    assert shot_vector[0].copies == 1
-    assert shot_vector[1].shots == 3
-    assert shot_vector[1].copies == 2
-    assert shot_vector[2].shots == 4
-    assert shot_vector[2].copies == 3
-    assert shot_vector[3].shots == 3
-    assert shot_vector[3].copies == 1
+class TestShotVectors:
+    """Tests passing shot vectors, their validation, and processing."""
+
+    def test_shot_vector_property(self):
+        dev = qml.device("default.qubit", wires=1, shots=[1, 3, 3, 4, 4, 4, 3])
+        shot_vector = dev.shot_vector
+        assert len(shot_vector) == 4
+        assert shot_vector[0].shots == 1
+        assert shot_vector[0].copies == 1
+        assert shot_vector[1].shots == 3
+        assert shot_vector[1].copies == 2
+        assert shot_vector[2].shots == 4
+        assert shot_vector[2].copies == 3
+        assert shot_vector[3].shots == 3
+        assert shot_vector[3].copies == 1
+
+        assert dev.shots == 22
+
+    def test_process_shot_sequence(self):
+        """Tests that the helper `_process_shot_sequence` works as expected."""
+        shot_list = [1, 1, 3]
+        total_shots, shot_vector = qml._device._process_shot_sequence(shot_list)
+
+        assert total_shots == 5
+        assert isinstance(total_shots, int)
+
+        assert len(shot_vector) == 2
+
+        for tup in shot_vector:
+            assert isinstance(tup, qml._device.ShotTuple)
+
+        assert shot_vector[0].shots == 1
+        assert shot_vector[0].copies == 2
+        assert shot_vector[1].shots == 3
+        assert shot_vector[1].copies == 1
 
 
 class TestDeviceSupportedLogic: