Repository: PennyLaneAI/pennylane
Pull request #5218 (2024-02-15 18:29:44)

Clear error message if plugin is not installed
**Context:**
Currently if you try to use `qml.from_qiskit` without the plugin installed, you get the somewhat non-specific
`ValueError: Converter does not exist. Make sure the required plugin is installed and supports conversion.`

**Description of the Change:**
If the "converter does not exist" error is raised when calling `qml.from_qiskit`, the user is shown a more explicit message with instructions for installing the plugin and for contacting the forum if they have issues.



github-actions[bot]: Hello. You may have forgotten to update the changelog!
Please edit [`doc/releases/changelog-dev.md`](/PennyLaneAI/pennylane/blob/master/doc/releases/changelog-dev.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://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5218?src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) Report
Attention: `4 lines` in your changes are missing coverage. Please review.
> Comparison is base [(`6a53702`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/commit/6a537027b31ceaa85751cbaba63d555c8425264f?el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.68% compared to head [(`c246b9a`)](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5218?src=pr&el=desc&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) 99.67%.

| [Files](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5218?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) | Patch % | Lines |
|---|---|---|
| [pennylane/io.py](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5218?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI#diff-cGVubnlsYW5lL2lvLnB5) | 33.33% | [4 Missing :warning: ](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5218?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI) |

<details><summary>Additional details and impacted files</summary>


```diff
@@            Coverage Diff             @@
##           master    #5218      +/-   ##
==========================================
- Coverage   99.68%   99.67%   -0.02%     
==========================================
  Files         396      396              
  Lines       36656    36389     -267     
==========================================
- Hits        36542    36270     -272     
- Misses        114      119       +5     
```



</details>

[:umbrella: View full report in Codecov by Sentry](https://app.codecov.io/gh/PennyLaneAI/pennylane/pull/5218?src=pr&el=continue&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).   
:loudspeaker: Have feedback on the report? [Share it here](https://about.codecov.io/codecov-pr-comment-feedback/?utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=PennyLaneAI).

lillian542: [sc-56069]

Patch:
diff --git a/doc/releases/changelog-dev.md b/doc/releases/changelog-dev.md
index 512076494..0bf8c407c 100644
--- a/doc/releases/changelog-dev.md
+++ b/doc/releases/changelog-dev.md
@@ -293,6 +293,10 @@
   when converting a `QuantumCircuit` using `qml.from_qiskit`.
   [(#5168)](https://github.com/PennyLaneAI/pennylane/pull/5168)
 
+* An error message provides clearer instructions for installing PennyLane-Qiskit if the `qml.from_qiskit` 
+  function fails because the Qiskit converter is missing.
+  [(#5218)](https://github.com/PennyLaneAI/pennylane/pull/5218)
+
 <h3>Breaking changes 💔</h3>
 
 * The entry point convention registering compilers with PennyLane has changed.
diff --git a/pennylane/io.py b/pennylane/io.py
index 752269f66..b0a3d76bc 100644
--- a/pennylane/io.py
+++ b/pennylane/io.py
@@ -142,7 +142,18 @@ def from_qiskit(quantum_circuit, measurements=None):
         1: ───────────────────╰X─┤  vnentropy
 
     """
-    return load(quantum_circuit, format="qiskit", measurements=measurements)
+    try:
+        return load(quantum_circuit, format="qiskit", measurements=measurements)
+    except ValueError as e:
+        if e.args[0].split(".")[0] == "Converter does not exist":
+            raise RuntimeError(
+                "Conversion from Qiskit requires the PennyLane-Qiskit plugin. "
+                "You can install the plugin by running: pip install pennylane-qiskit. "
+                "You may need to restart your kernel or environment after installation. "
+                "If you have any difficulties, you can reach out on the PennyLane forum at "
+                "https://discuss.pennylane.ai/c/pennylane-plugins/pennylane-qiskit/"
+            ) from e
+        raise e
 
 
 def from_qasm(quantum_circuit: str):


Test patch:
diff --git a/tests/test_io.py b/tests/test_io.py
index 9a6504818..9a81b3f13 100644
--- a/tests/test_io.py
+++ b/tests/test_io.py
@@ -71,6 +71,38 @@ class TestLoad:
         ):
             qml.load("Test", format="some_non_existing_format")
 
+    def test_qiskit_not_installed(self, monkeypatch):
+        """Test that a specific error is raised if qml.from_qiskit is called and the qiskit
+        plugin converter isn't found, instead of the generic 'ValueError: Converter does not exist.'
+        """
+
+        # temporarily make a mock_converter_dict with no "qiskit"
+        mock_plugin_converter_dict = {
+            entry_point: MockPluginConverter(entry_point) for entry_point in load_entry_points
+        }
+        del mock_plugin_converter_dict["qiskit"]
+        monkeypatch.setattr(qml.io, "plugin_converters", mock_plugin_converter_dict)
+
+        # calling from_qiskit raises the specific RuntimeError rather than the generic ValueError
+        with pytest.raises(
+            RuntimeError,
+            match="Conversion from Qiskit requires the PennyLane-Qiskit plugin. "
+            "You can install the plugin by",
+        ):
+            qml.from_qiskit("Test")
+
+        # if load raises some other ValueError instead of the "converter does not exist" error, it is unaffected
+        def mock_load_with_error(*args, **kwargs):
+            raise ValueError("Some other error raised than instead of converter does not exist")
+
+        monkeypatch.setattr(qml.io, "load", mock_load_with_error)
+
+        with pytest.raises(
+            ValueError,
+            match="Some other error raised than instead of converter does not exist",
+        ):
+            qml.from_qiskit("Test")
+
     @pytest.mark.parametrize(
         "method,entry_point_name",
         [
@@ -95,7 +127,7 @@ class TestLoad:
                 continue
 
             if mock_plugin_converters[plugin_converter].called:
-                raise Exception(f"The other plugin converter {plugin_converter} was called.")
+                raise RuntimeError(f"The other plugin converter {plugin_converter} was called.")
 
     @pytest.mark.parametrize(
         "method, entry_point_name",
@@ -119,4 +151,4 @@ class TestLoad:
                 continue
 
             if mock_plugin_converters[plugin_converter].called:
-                raise Exception(f"The other plugin converter {plugin_converter} was called.")
+                raise RuntimeError(f"The other plugin converter {plugin_converter} was called.")