def from_proto(cls, proto: v2.device_pb2.DeviceSpecification) -> GridDevice:
        """Deserializes the `DeviceSpecification` to a `GridDevice`.

        Args:
            proto: The `DeviceSpecification` proto describing a Google device.

        Raises:
            ValueError: If the given `DeviceSpecification` is invalid. It is invalid if:
                * A `DeviceSpecification.valid_qubits` string is not in the form `<int>_<int>`, thus
                  cannot be parsed as a `cirq.GridQubit`.
                * `DeviceSpecification.valid_targets` refer to qubits which are not in
                  `DeviceSpecification.valid_qubits`.
                * A target set in `DeviceSpecification.valid_targets` has type `SYMMETRIC` but
                  contains targets with repeated qubits, e.g. a qubit pair with a self loop.
        """

        _validate_device_specification(proto)

        # Create qubit set
        all_qubits = {v2.grid_qubit_from_proto_id(q) for q in proto.valid_qubits}

        # Create qubit pair set
        qubit_pairs = [
            (v2.grid_qubit_from_proto_id(target.ids[0]), v2.grid_qubit_from_proto_id(target.ids[1]))
            for ts in proto.valid_targets
            for target in ts.targets
            if len(target.ids) == 2 and ts.target_ordering == v2.device_pb2.TargetSet.SYMMETRIC
        ]

        gateset, gate_durations = _deserialize_gateset_and_gate_durations(proto)

        try:
            metadata = cirq.GridDeviceMetadata(
                qubit_pairs=qubit_pairs,
                gateset=gateset,
                gate_durations=gate_durations if len(gate_durations) > 0 else None,
                all_qubits=all_qubits,
                compilation_target_gatesets=_build_compilation_target_gatesets(gateset),
            )
        except ValueError as ve:  # pragma: no cover
            # Spec errors should have been caught in validation above.
            raise ValueError("DeviceSpecification is invalid.") from ve  # pragma: no cover

        return GridDevice(metadata)
Deserializes the `DeviceSpecification` to a `GridDevice`.

        Args:
            proto: The `DeviceSpecification` proto describing a Google device.

        Raises:
            ValueError: If the given `DeviceSpecification` is invalid. It is invalid if:
                * A `DeviceSpecification.valid_qubits` string is not in the form `<int>_<int>`, thus
                  cannot be parsed as a `cirq.GridQubit`.
                * `DeviceSpecification.valid_targets` refer to qubits which are not in
                  `DeviceSpecification.valid_qubits`.
                * A target set in `DeviceSpecification.valid_targets` has type `SYMMETRIC` but
                  contains targets with repeated qubits, e.g. a qubit pair with a self loop.
        
cirq-google/cirq_google/devices/grid_device.py