We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Calling EngineProcessor.list_calibrations gives error
**Description of the issue**

Calling `EngineProcessor.list_calibrations` gives an error.

**How to reproduce the issue**

```python
import cirq

engine = cirq.google.Engine(project_id=PROJECT_ID,
                            proto_version=cirq.google.ProtoVersion.V2)
engine_processor = engine.get_processor('rainbow')
calibrations = engine_processor.list_calibrations()
```
Output:
```
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
~/Projects/Cirq/cirq/google/api/v2/program.py in grid_qubit_from_proto_id(proto_id)
    102         row, col = parts
--> 103         return devices.GridQubit(row=int(row), col=int(col))
    104     except ValueError:

ValueError: invalid literal for int() with base 10: 'q3'

During handling of the above exception, another exception occurred:

ValueError                                Traceback (most recent call last)
<ipython-input-2-69914ce7bc88> in <module>
      4                             proto_version=cirq.google.ProtoVersion.V2)
      5 engine_processor = engine.get_processor('rainbow')
----> 6 calibrations = engine_processor.list_calibrations()

~/Projects/Cirq/cirq/google/engine/engine_processor.py in list_calibrations(self, earliest_timestamp_seconds, latest_timestamp_seconds)
    158         response = self.context.client.list_calibrations(
    159             self.project_id, self.processor_id, filter_str)
--> 160         return [self._to_calibration(c.data) for c in list(response)]
    161 
    162     def get_calibration(self, calibration_timestamp_seconds: int

~/Projects/Cirq/cirq/google/engine/engine_processor.py in <listcomp>(.0)
    158         response = self.context.client.list_calibrations(
    159             self.project_id, self.processor_id, filter_str)
--> 160         return [self._to_calibration(c.data) for c in list(response)]
    161 
    162     def get_calibration(self, calibration_timestamp_seconds: int

~/Projects/Cirq/cirq/google/engine/engine_processor.py in _to_calibration(calibration_any)
    130         metrics = v2.metrics_pb2.MetricsSnapshot.FromString(
    131             calibration_any.value)
--> 132         return calibration.Calibration(metrics)
    133 
    134     def list_calibrations(self,

~/Projects/Cirq/cirq/google/engine/calibration.py in __init__(self, calibration)
     53     def __init__(self, calibration: v2.metrics_pb2.MetricsSnapshot) -> None:
     54         self.timestamp = calibration.timestamp_ms
---> 55         self._metric_dict = self._compute_metric_dict(calibration.metrics)
     56 
     57     def _compute_metric_dict(

~/Projects/Cirq/cirq/google/engine/calibration.py in _compute_metric_dict(self, metrics)
     68             ]
     69             if metric.targets:
---> 70                 qubits = tuple(
     71                     v2.grid_qubit_from_proto_id(t) for t in metric.targets)
     72                 results[name][qubits] = flat_values

~/Projects/Cirq/cirq/google/engine/calibration.py in <genexpr>(.0)
     69             if metric.targets:
     70                 qubits = tuple(
---> 71                     v2.grid_qubit_from_proto_id(t) for t in metric.targets)
     72                 results[name][qubits] = flat_values
     73             else:

~/Projects/Cirq/cirq/google/api/v2/program.py in grid_qubit_from_proto_id(proto_id)
    103         return devices.GridQubit(row=int(row), col=int(col))
    104     except ValueError:
--> 105         raise ValueError(
    106             'GridQubit proto id must be of the form <int>_<int> but was {}'.
    107             format(proto_id))

ValueError: GridQubit proto id must be of the form <int>_<int> but was q3_2
```

**Cirq version**
0.9.0.dev


--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `cirq/google/api/v2/program.py`
Content:
```
1 # Copyright 2019 The Cirq Developers
2 #
3 # Licensed under the Apache License, Version 2.0 (the "License");
4 # you may not use this file except in compliance with the License.
5 # You may obtain a copy of the License at
6 #
7 #     https://www.apache.org/licenses/LICENSE-2.0
8 #
9 # Unless required by applicable law or agreed to in writing, software
10 # distributed under the License is distributed on an "AS IS" BASIS,
11 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 # See the License for the specific language governing permissions and
13 # limitations under the License.
14 
15 from typing import TYPE_CHECKING
16 
17 from cirq import devices, ops
18 
19 if TYPE_CHECKING:
20     import cirq
21 
22 
23 def qubit_to_proto_id(q: 'cirq.Qid') -> str:
24     """Return a proto id for a `cirq.Qid`.
25 
26     For `cirq.GridQubit`s this id `{row}_{col}` where `{row}` is the integer
27     row of the grid qubit, and `{col}` is the integer column of the qubit.
28 
29     For `cirq.NamedQubit`s this id is the name.
30 
31     For `cirq.LineQubit`s this is string of the `x` attribute.
32     """
33     if isinstance(q, devices.GridQubit):
34         return '{}_{}'.format(q.row, q.col)
35     elif isinstance(q, ops.NamedQubit):
36         return q.name
37     elif isinstance(q, devices.LineQubit):
38         return '{}'.format(q.x)
39     else:
40         raise ValueError('Qubits of type {} do not support proto id'.format(
41             type(q)))
42 
43 
44 def qubit_from_proto_id(proto_id: str) -> 'cirq.Qid':
45     """Return a `cirq.Qid` for a proto id.
46 
47     Proto IDs of the form {int}_{int} are parsed as GridQubits.
48 
49     Proto IDs of the form {int} are parsed as LineQubits.
50 
51     All other proto IDs are parsed as NamedQubits. Note that this will happily
52     accept any string; for circuits which explicitly use Grid or LineQubits,
53     prefer one of the specialized methods below.
54 
55     Args:
56         proto_id: The id to convert.
57 
58     Returns:
59         A `cirq.Qid` corresponding to the proto id.
60     """
61     num_coords = len(proto_id.split('_'))
62     if num_coords == 2:
63         try:
64             grid_q = grid_qubit_from_proto_id(proto_id)
65             return grid_q
66         except ValueError:
67             pass  # Not a grid qubit.
68     elif num_coords == 1:
69         try:
70             line_q = line_qubit_from_proto_id(proto_id)
71             return line_q
72         except ValueError:
73             pass  # Not a line qubit.
74 
75     # named_qubit_from_proto has no failure condition.
76     named_q = named_qubit_from_proto_id(proto_id)
77     return named_q
78 
79 
80 def grid_qubit_from_proto_id(proto_id: str) -> 'cirq.GridQubit':
81     """Parse a proto id to a `cirq.GridQubit`.
82 
83     Proto ids for grid qubits are of the form `{row}_{col}` where `{row}` is
84     the integer row of the grid qubit, and `{col}` is the integer column of
85     the qubit.
86 
87     Args:
88         proto_id: The id to convert.
89 
90     Returns:
91         A `cirq.GridQubit` corresponding to the proto id.
92 
93     Raises:
94         ValueError: If the string not of the correct format.
95     """
96     parts = proto_id.split('_')
97     if len(parts) != 2:
98         raise ValueError(
99             'GridQubit proto id must be of the form <int>_<int> but was {}'.
100             format(proto_id))
101     try:
102         row, col = parts
103         return devices.GridQubit(row=int(row), col=int(col))
104     except ValueError:
105         raise ValueError(
106             'GridQubit proto id must be of the form <int>_<int> but was {}'.
107             format(proto_id))
108 
109 
110 def line_qubit_from_proto_id(proto_id: str) -> 'cirq.LineQubit':
111     """Parse a proto id to a `cirq.LineQubit`.
112 
113     Proto ids for line qubits are integer strings representing the `x`
114     attribute of the line qubit.
115 
116     Args:
117         proto_id: The id to convert.
118 
119     Returns:
120         A `cirq.LineQubit` corresponding to the proto id.
121 
122     Raises:
123         ValueError: If the string is not an integer.
124     """
125     try:
126         return devices.LineQubit(x=int(proto_id))
127     except ValueError:
128         raise ValueError(
129             'Line qubit proto id must be an int but was {}'.format(proto_id))
130 
131 
132 def named_qubit_from_proto_id(proto_id: str) -> 'cirq.NamedQubit':
133     """Parse a proto id to a `cirq.NamedQubit'
134 
135     This simply returns a `cirq.NamedQubit` with a name equal to `proto_id`.
136     """
137     return ops.NamedQubit(proto_id)
138
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/cirq/google/api/v2/program.py b/cirq/google/api/v2/program.py
--- a/cirq/google/api/v2/program.py
+++ b/cirq/google/api/v2/program.py
@@ -11,7 +11,7 @@
 # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 # See the License for the specific language governing permissions and
 # limitations under the License.
-
+import re
 from typing import TYPE_CHECKING
 
 from cirq import devices, ops
@@ -19,6 +19,8 @@
 if TYPE_CHECKING:
     import cirq
 
+GRID_QUBIT_ID_PATTERN = r'^q?(-?\d+)_(-?\d+)$'
+
 
 def qubit_to_proto_id(q: 'cirq.Qid') -> str:
     """Return a proto id for a `cirq.Qid`.
@@ -93,13 +95,14 @@
     Raises:
         ValueError: If the string not of the correct format.
     """
-    parts = proto_id.split('_')
-    if len(parts) != 2:
+
+    match = re.match(GRID_QUBIT_ID_PATTERN, proto_id)
+    if match is None:
         raise ValueError(
             'GridQubit proto id must be of the form <int>_<int> but was {}'.
             format(proto_id))
     try:
-        row, col = parts
+        row, col = match.groups()
         return devices.GridQubit(row=int(row), col=int(col))
     except ValueError:
         raise ValueError(

{"golden_diff": "diff --git a/cirq/google/api/v2/program.py b/cirq/google/api/v2/program.py\n--- a/cirq/google/api/v2/program.py\n+++ b/cirq/google/api/v2/program.py\n@@ -11,7 +11,7 @@\n # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n # See the License for the specific language governing permissions and\n # limitations under the License.\n-\n+import re\n from typing import TYPE_CHECKING\n \n from cirq import devices, ops\n@@ -19,6 +19,8 @@\n if TYPE_CHECKING:\n     import cirq\n \n+GRID_QUBIT_ID_PATTERN = r'^q?(-?\\d+)_(-?\\d+)$'\n+\n \n def qubit_to_proto_id(q: 'cirq.Qid') -> str:\n     \"\"\"Return a proto id for a `cirq.Qid`.\n@@ -93,13 +95,14 @@\n     Raises:\n         ValueError: If the string not of the correct format.\n     \"\"\"\n-    parts = proto_id.split('_')\n-    if len(parts) != 2:\n+\n+    match = re.match(GRID_QUBIT_ID_PATTERN, proto_id)\n+    if match is None:\n         raise ValueError(\n             'GridQubit proto id must be of the form <int>_<int> but was {}'.\n             format(proto_id))\n     try:\n-        row, col = parts\n+        row, col = match.groups()\n         return devices.GridQubit(row=int(row), col=int(col))\n     except ValueError:\n         raise ValueError(\n", "issue": "Calling EngineProcessor.list_calibrations gives error\n**Description of the issue**\r\n\r\nCalling `EngineProcessor.list_calibrations` gives an error.\r\n\r\n**How to reproduce the issue**\r\n\r\n```python\r\nimport cirq\r\n\r\nengine = cirq.google.Engine(project_id=PROJECT_ID,\r\n                            proto_version=cirq.google.ProtoVersion.V2)\r\nengine_processor = engine.get_processor('rainbow')\r\ncalibrations = engine_processor.list_calibrations()\r\n```\r\nOutput:\r\n```\r\n---------------------------------------------------------------------------\r\nValueError                                Traceback (most recent call last)\r\n~/Projects/Cirq/cirq/google/api/v2/program.py in grid_qubit_from_proto_id(proto_id)\r\n    102         row, col = parts\r\n--> 103         return devices.GridQubit(row=int(row), col=int(col))\r\n    104     except ValueError:\r\n\r\nValueError: invalid literal for int() with base 10: 'q3'\r\n\r\nDuring handling of the above exception, another exception occurred:\r\n\r\nValueError                                Traceback (most recent call last)\r\n<ipython-input-2-69914ce7bc88> in <module>\r\n      4                             proto_version=cirq.google.ProtoVersion.V2)\r\n      5 engine_processor = engine.get_processor('rainbow')\r\n----> 6 calibrations = engine_processor.list_calibrations()\r\n\r\n~/Projects/Cirq/cirq/google/engine/engine_processor.py in list_calibrations(self, earliest_timestamp_seconds, latest_timestamp_seconds)\r\n    158         response = self.context.client.list_calibrations(\r\n    159             self.project_id, self.processor_id, filter_str)\r\n--> 160         return [self._to_calibration(c.data) for c in list(response)]\r\n    161 \r\n    162     def get_calibration(self, calibration_timestamp_seconds: int\r\n\r\n~/Projects/Cirq/cirq/google/engine/engine_processor.py in <listcomp>(.0)\r\n    158         response = self.context.client.list_calibrations(\r\n    159             self.project_id, self.processor_id, filter_str)\r\n--> 160         return [self._to_calibration(c.data) for c in list(response)]\r\n    161 \r\n    162     def get_calibration(self, calibration_timestamp_seconds: int\r\n\r\n~/Projects/Cirq/cirq/google/engine/engine_processor.py in _to_calibration(calibration_any)\r\n    130         metrics = v2.metrics_pb2.MetricsSnapshot.FromString(\r\n    131             calibration_any.value)\r\n--> 132         return calibration.Calibration(metrics)\r\n    133 \r\n    134     def list_calibrations(self,\r\n\r\n~/Projects/Cirq/cirq/google/engine/calibration.py in __init__(self, calibration)\r\n     53     def __init__(self, calibration: v2.metrics_pb2.MetricsSnapshot) -> None:\r\n     54         self.timestamp = calibration.timestamp_ms\r\n---> 55         self._metric_dict = self._compute_metric_dict(calibration.metrics)\r\n     56 \r\n     57     def _compute_metric_dict(\r\n\r\n~/Projects/Cirq/cirq/google/engine/calibration.py in _compute_metric_dict(self, metrics)\r\n     68             ]\r\n     69             if metric.targets:\r\n---> 70                 qubits = tuple(\r\n     71                     v2.grid_qubit_from_proto_id(t) for t in metric.targets)\r\n     72                 results[name][qubits] = flat_values\r\n\r\n~/Projects/Cirq/cirq/google/engine/calibration.py in <genexpr>(.0)\r\n     69             if metric.targets:\r\n     70                 qubits = tuple(\r\n---> 71                     v2.grid_qubit_from_proto_id(t) for t in metric.targets)\r\n     72                 results[name][qubits] = flat_values\r\n     73             else:\r\n\r\n~/Projects/Cirq/cirq/google/api/v2/program.py in grid_qubit_from_proto_id(proto_id)\r\n    103         return devices.GridQubit(row=int(row), col=int(col))\r\n    104     except ValueError:\r\n--> 105         raise ValueError(\r\n    106             'GridQubit proto id must be of the form <int>_<int> but was {}'.\r\n    107             format(proto_id))\r\n\r\nValueError: GridQubit proto id must be of the form <int>_<int> but was q3_2\r\n```\r\n\r\n**Cirq version**\r\n0.9.0.dev\r\n\n", "before_files": [{"content": "# Copyright 2019 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\n\nfrom typing import TYPE_CHECKING\n\nfrom cirq import devices, ops\n\nif TYPE_CHECKING:\n    import cirq\n\n\ndef qubit_to_proto_id(q: 'cirq.Qid') -> str:\n    \"\"\"Return a proto id for a `cirq.Qid`.\n\n    For `cirq.GridQubit`s this id `{row}_{col}` where `{row}` is the integer\n    row of the grid qubit, and `{col}` is the integer column of the qubit.\n\n    For `cirq.NamedQubit`s this id is the name.\n\n    For `cirq.LineQubit`s this is string of the `x` attribute.\n    \"\"\"\n    if isinstance(q, devices.GridQubit):\n        return '{}_{}'.format(q.row, q.col)\n    elif isinstance(q, ops.NamedQubit):\n        return q.name\n    elif isinstance(q, devices.LineQubit):\n        return '{}'.format(q.x)\n    else:\n        raise ValueError('Qubits of type {} do not support proto id'.format(\n            type(q)))\n\n\ndef qubit_from_proto_id(proto_id: str) -> 'cirq.Qid':\n    \"\"\"Return a `cirq.Qid` for a proto id.\n\n    Proto IDs of the form {int}_{int} are parsed as GridQubits.\n\n    Proto IDs of the form {int} are parsed as LineQubits.\n\n    All other proto IDs are parsed as NamedQubits. Note that this will happily\n    accept any string; for circuits which explicitly use Grid or LineQubits,\n    prefer one of the specialized methods below.\n\n    Args:\n        proto_id: The id to convert.\n\n    Returns:\n        A `cirq.Qid` corresponding to the proto id.\n    \"\"\"\n    num_coords = len(proto_id.split('_'))\n    if num_coords == 2:\n        try:\n            grid_q = grid_qubit_from_proto_id(proto_id)\n            return grid_q\n        except ValueError:\n            pass  # Not a grid qubit.\n    elif num_coords == 1:\n        try:\n            line_q = line_qubit_from_proto_id(proto_id)\n            return line_q\n        except ValueError:\n            pass  # Not a line qubit.\n\n    # named_qubit_from_proto has no failure condition.\n    named_q = named_qubit_from_proto_id(proto_id)\n    return named_q\n\n\ndef grid_qubit_from_proto_id(proto_id: str) -> 'cirq.GridQubit':\n    \"\"\"Parse a proto id to a `cirq.GridQubit`.\n\n    Proto ids for grid qubits are of the form `{row}_{col}` where `{row}` is\n    the integer row of the grid qubit, and `{col}` is the integer column of\n    the qubit.\n\n    Args:\n        proto_id: The id to convert.\n\n    Returns:\n        A `cirq.GridQubit` corresponding to the proto id.\n\n    Raises:\n        ValueError: If the string not of the correct format.\n    \"\"\"\n    parts = proto_id.split('_')\n    if len(parts) != 2:\n        raise ValueError(\n            'GridQubit proto id must be of the form <int>_<int> but was {}'.\n            format(proto_id))\n    try:\n        row, col = parts\n        return devices.GridQubit(row=int(row), col=int(col))\n    except ValueError:\n        raise ValueError(\n            'GridQubit proto id must be of the form <int>_<int> but was {}'.\n            format(proto_id))\n\n\ndef line_qubit_from_proto_id(proto_id: str) -> 'cirq.LineQubit':\n    \"\"\"Parse a proto id to a `cirq.LineQubit`.\n\n    Proto ids for line qubits are integer strings representing the `x`\n    attribute of the line qubit.\n\n    Args:\n        proto_id: The id to convert.\n\n    Returns:\n        A `cirq.LineQubit` corresponding to the proto id.\n\n    Raises:\n        ValueError: If the string is not an integer.\n    \"\"\"\n    try:\n        return devices.LineQubit(x=int(proto_id))\n    except ValueError:\n        raise ValueError(\n            'Line qubit proto id must be an int but was {}'.format(proto_id))\n\n\ndef named_qubit_from_proto_id(proto_id: str) -> 'cirq.NamedQubit':\n    \"\"\"Parse a proto id to a `cirq.NamedQubit'\n\n    This simply returns a `cirq.NamedQubit` with a name equal to `proto_id`.\n    \"\"\"\n    return ops.NamedQubit(proto_id)\n", "path": "cirq/google/api/v2/program.py"}], "after_files": [{"content": "# Copyright 2019 The Cirq Developers\n#\n# Licensed under the Apache License, Version 2.0 (the \"License\");\n# you may not use this file except in compliance with the License.\n# You may obtain a copy of the License at\n#\n#     https://www.apache.org/licenses/LICENSE-2.0\n#\n# Unless required by applicable law or agreed to in writing, software\n# distributed under the License is distributed on an \"AS IS\" BASIS,\n# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n# See the License for the specific language governing permissions and\n# limitations under the License.\nimport re\nfrom typing import TYPE_CHECKING\n\nfrom cirq import devices, ops\n\nif TYPE_CHECKING:\n    import cirq\n\nGRID_QUBIT_ID_PATTERN = r'^q?(-?\\d+)_(-?\\d+)$'\n\n\ndef qubit_to_proto_id(q: 'cirq.Qid') -> str:\n    \"\"\"Return a proto id for a `cirq.Qid`.\n\n    For `cirq.GridQubit`s this id `{row}_{col}` where `{row}` is the integer\n    row of the grid qubit, and `{col}` is the integer column of the qubit.\n\n    For `cirq.NamedQubit`s this id is the name.\n\n    For `cirq.LineQubit`s this is string of the `x` attribute.\n    \"\"\"\n    if isinstance(q, devices.GridQubit):\n        return '{}_{}'.format(q.row, q.col)\n    elif isinstance(q, ops.NamedQubit):\n        return q.name\n    elif isinstance(q, devices.LineQubit):\n        return '{}'.format(q.x)\n    else:\n        raise ValueError('Qubits of type {} do not support proto id'.format(\n            type(q)))\n\n\ndef qubit_from_proto_id(proto_id: str) -> 'cirq.Qid':\n    \"\"\"Return a `cirq.Qid` for a proto id.\n\n    Proto IDs of the form {int}_{int} are parsed as GridQubits.\n\n    Proto IDs of the form {int} are parsed as LineQubits.\n\n    All other proto IDs are parsed as NamedQubits. Note that this will happily\n    accept any string; for circuits which explicitly use Grid or LineQubits,\n    prefer one of the specialized methods below.\n\n    Args:\n        proto_id: The id to convert.\n\n    Returns:\n        A `cirq.Qid` corresponding to the proto id.\n    \"\"\"\n    num_coords = len(proto_id.split('_'))\n    if num_coords == 2:\n        try:\n            grid_q = grid_qubit_from_proto_id(proto_id)\n            return grid_q\n        except ValueError:\n            pass  # Not a grid qubit.\n    elif num_coords == 1:\n        try:\n            line_q = line_qubit_from_proto_id(proto_id)\n            return line_q\n        except ValueError:\n            pass  # Not a line qubit.\n\n    # named_qubit_from_proto has no failure condition.\n    named_q = named_qubit_from_proto_id(proto_id)\n    return named_q\n\n\ndef grid_qubit_from_proto_id(proto_id: str) -> 'cirq.GridQubit':\n    \"\"\"Parse a proto id to a `cirq.GridQubit`.\n\n    Proto ids for grid qubits are of the form `{row}_{col}` where `{row}` is\n    the integer row of the grid qubit, and `{col}` is the integer column of\n    the qubit.\n\n    Args:\n        proto_id: The id to convert.\n\n    Returns:\n        A `cirq.GridQubit` corresponding to the proto id.\n\n    Raises:\n        ValueError: If the string not of the correct format.\n    \"\"\"\n\n    match = re.match(GRID_QUBIT_ID_PATTERN, proto_id)\n    if match is None:\n        raise ValueError(\n            'GridQubit proto id must be of the form <int>_<int> but was {}'.\n            format(proto_id))\n    try:\n        row, col = match.groups()\n        return devices.GridQubit(row=int(row), col=int(col))\n    except ValueError:\n        raise ValueError(\n            'GridQubit proto id must be of the form <int>_<int> but was {}'.\n            format(proto_id))\n\n\ndef line_qubit_from_proto_id(proto_id: str) -> 'cirq.LineQubit':\n    \"\"\"Parse a proto id to a `cirq.LineQubit`.\n\n    Proto ids for line qubits are integer strings representing the `x`\n    attribute of the line qubit.\n\n    Args:\n        proto_id: The id to convert.\n\n    Returns:\n        A `cirq.LineQubit` corresponding to the proto id.\n\n    Raises:\n        ValueError: If the string is not an integer.\n    \"\"\"\n    try:\n        return devices.LineQubit(x=int(proto_id))\n    except ValueError:\n        raise ValueError(\n            'Line qubit proto id must be an int but was {}'.format(proto_id))\n\n\ndef named_qubit_from_proto_id(proto_id: str) -> 'cirq.NamedQubit':\n    \"\"\"Parse a proto id to a `cirq.NamedQubit'\n\n    This simply returns a `cirq.NamedQubit` with a name equal to `proto_id`.\n    \"\"\"\n    return ops.NamedQubit(proto_id)\n", "path": "cirq/google/api/v2/program.py"}]}