# Buggy code
def grid_qubit_from_proto_id(proto_id: str) -> "cirq.GridQubit":
    """Parse a proto id to a `cirq.GridQubit`.

    Proto ids for grid qubits are of the form `{row}_{col}` where `{row}` is
    the integer row of the grid qubit, and `{col}` is the integer column of
    the qubit.

    Args:
        proto_id: The id to convert.

    Returns:
        A `cirq.GridQubit` corresponding to the proto id.

    Raises:
        ValueError: If the string not of the correct format.
    """
    parts = proto_id.split("_")
    if len(parts) != 2:
        raise ValueError(
            "GridQubit proto id must be of the form <int>_<int> but was {}".format(
                proto_id
            )
        )
    try:
        row, col = parts
        return devices.GridQubit(row=int(row), col=int(col))
    except ValueError:
        raise ValueError(
            "GridQubit proto id must be of the form <int>_<int> but was {}".format(
                proto_id
            )
        )


# Traceback (ValueError)
---------------------------------------------------------------------------
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

# Fixed code
def grid_qubit_from_proto_id(proto_id: str) -> "cirq.GridQubit":
    """Parse a proto id to a `cirq.GridQubit`.

    Proto ids for grid qubits are of the form `{row}_{col}` where `{row}` is
    the integer row of the grid qubit, and `{col}` is the integer column of
    the qubit.

    Args:
        proto_id: The id to convert.

    Returns:
        A `cirq.GridQubit` corresponding to the proto id.

    Raises:
        ValueError: If the string not of the correct format.
    """

    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 = match.groups()
        return devices.GridQubit(row=int(row), col=int(col))
    except ValueError:
        raise ValueError(
            "GridQubit proto id must be of the form <int>_<int> but was {}".format(
                proto_id
            )
        )