From 48397d66835668c203b121e0935d88a5708502c6 Mon Sep 17 00:00:00 2001 From: Orion Martin <40585662+95-martin-orion@users.noreply.github.com> Date: Wed, 24 Nov 2021 09:12:29 -0800 Subject: [PATCH] Move "cirq_type" responsibility to protocols (#4704) Fixes #4698. This enforces the `'cirq_type': [.]` convention for JSON serialization by assigning the "cirq_type" field in our protocols instead of in each class. Any external users who define a "cirq_type" will see a warning about this; after a deprecation cycle, we will begin raising errors to prevent explicit definition of "cirq_type" in classes. --- cirq-core/cirq/circuits/circuit_operation.py | 1 - .../cirq/circuits/circuit_operation_test.py | 1 - cirq-core/cirq/circuits/circuit_test.py | 1 - cirq-core/cirq/devices/device.py | 1 - cirq-core/cirq/devices/grid_qubit_test.py | 2 - cirq-core/cirq/devices/line_qubit_test.py | 2 - cirq-core/cirq/devices/named_topologies.py | 7 +- .../experiments/cross_entropy_benchmarking.py | 1 - .../single_qubit_readout_calibration.py | 1 - cirq-core/cirq/ops/boolean_hamiltonian.py | 1 - cirq-core/cirq/ops/clifford_gate.py | 1 - cirq-core/cirq/ops/common_gates.py | 3 - cirq-core/cirq/ops/controlled_gate.py | 1 - cirq-core/cirq/ops/controlled_operation.py | 1 - cirq-core/cirq/ops/fourier_transform.py | 2 - cirq-core/cirq/ops/fsim_gate_test.py | 2 - cirq-core/cirq/ops/global_phase_op_test.py | 1 - cirq-core/cirq/ops/identity.py | 1 - cirq-core/cirq/ops/linear_combinations.py | 1 - cirq-core/cirq/ops/matrix_gates.py | 1 - cirq-core/cirq/ops/measurement_gate.py | 1 - cirq-core/cirq/ops/moment_test.py | 2 +- cirq-core/cirq/ops/named_qubit_test.py | 2 - cirq-core/cirq/ops/pauli_measurement_gate.py | 1 - cirq-core/cirq/ops/pauli_string.py | 2 - cirq-core/cirq/ops/permutation_gate_test.py | 1 - cirq-core/cirq/ops/phased_iswap_gate.py | 1 - cirq-core/cirq/ops/projector.py | 1 - cirq-core/cirq/ops/raw_types_test.py | 5 +- .../cirq/ops/state_preparation_channel.py | 1 - cirq-core/cirq/ops/tags.py | 2 +- .../cirq/protocols/json_serialization.py | 65 +++++++++++++---- .../cirq/protocols/json_serialization_test.py | 72 ++++++++++++++++++- cirq-core/cirq/qis/clifford_tableau_test.py | 1 - .../cirq/sim/clifford/clifford_simulator.py | 1 - cirq-core/cirq/study/resolver.py | 1 - cirq-core/cirq/study/result.py | 1 - .../cirq/testing/no_identifier_qubit_test.py | 4 +- cirq-core/cirq/value/duration.py | 2 +- cirq-core/cirq/value/duration_test.py | 2 +- cirq-core/cirq/value/linear_dict.py | 1 - cirq-core/cirq/value/measurement_key.py | 1 - cirq-core/cirq/value/measurement_key_test.py | 4 +- cirq-core/cirq/value/product_state.py | 1 - .../cirq/work/observable_measurement_data.py | 1 - .../cirq_google/calibration/phased_fsim.py | 2 - .../cirq_google/devices/known_devices.py | 1 - .../cirq_google/devices/known_devices_test.py | 2 - cirq-google/cirq_google/engine/calibration.py | 2 +- .../cirq_google/engine/calibration_result.py | 1 - .../two_qubit_gates/gate_compilation.py | 1 - cirq-google/cirq_google/workflow/io.py | 2 +- .../workflow/quantum_executable.py | 8 +-- .../cirq_google/workflow/quantum_runtime.py | 18 +++-- .../workflow/quantum_runtime_test.py | 6 +- cirq-pasqal/cirq_pasqal/pasqal_device_test.py | 3 +- cirq-pasqal/cirq_pasqal/pasqal_qubits_test.py | 2 - cirq-rigetti/cirq_rigetti/aspen_device.py | 3 - 58 files changed, 155 insertions(+), 104 deletions(-) diff --git a/cirq-core/cirq/circuits/circuit_operation.py b/cirq-core/cirq/circuits/circuit_operation.py index ae1f5cfc51b..29d5fe06889 100644 --- a/cirq-core/cirq/circuits/circuit_operation.py +++ b/cirq-core/cirq/circuits/circuit_operation.py @@ -329,7 +329,6 @@ def __hash__(self): def _json_dict_(self): return { - 'cirq_type': 'CircuitOperation', 'circuit': self.circuit, 'repetitions': self.repetitions, # JSON requires mappings to have keys of basic types. diff --git a/cirq-core/cirq/circuits/circuit_operation_test.py b/cirq-core/cirq/circuits/circuit_operation_test.py index cb675ee4afe..cc5d150eb00 100644 --- a/cirq-core/cirq/circuits/circuit_operation_test.py +++ b/cirq-core/cirq/circuits/circuit_operation_test.py @@ -484,7 +484,6 @@ def test_json_dict(): ) assert op._json_dict_() == { - 'cirq_type': 'CircuitOperation', 'circuit': circuit, 'repetitions': 1, 'qubit_map': sorted([(k, v) for k, v in op.qubit_map.items()]), diff --git a/cirq-core/cirq/circuits/circuit_test.py b/cirq-core/cirq/circuits/circuit_test.py index 4648b2c18e2..13b30675f9e 100644 --- a/cirq-core/cirq/circuits/circuit_test.py +++ b/cirq-core/cirq/circuits/circuit_test.py @@ -4212,7 +4212,6 @@ def test_json_dict(circuit_cls): if circuit_cls == cirq.FrozenCircuit: moments = tuple(moments) assert c._json_dict_() == { - 'cirq_type': circuit_cls.__name__, 'moments': moments, 'device': cirq.UNCONSTRAINED_DEVICE, } diff --git a/cirq-core/cirq/devices/device.py b/cirq-core/cirq/devices/device.py index 8353918dde7..05da94b0ca0 100644 --- a/cirq-core/cirq/devices/device.py +++ b/cirq-core/cirq/devices/device.py @@ -164,7 +164,6 @@ def __repr__(self): def _json_dict_(self): return { 'qids': sorted(self.qids), - 'cirq_type': self.__class__.__name__, } @classmethod diff --git a/cirq-core/cirq/devices/grid_qubit_test.py b/cirq-core/cirq/devices/grid_qubit_test.py index 7a25aea3aba..b5ec318e04a 100644 --- a/cirq-core/cirq/devices/grid_qubit_test.py +++ b/cirq-core/cirq/devices/grid_qubit_test.py @@ -321,13 +321,11 @@ def test_neg(): def test_to_json(): assert cirq.GridQubit(5, 6)._json_dict_() == { - 'cirq_type': 'GridQubit', 'row': 5, 'col': 6, } assert cirq.GridQid(5, 6, dimension=3)._json_dict_() == { - 'cirq_type': 'GridQid', 'row': 5, 'col': 6, 'dimension': 3, diff --git a/cirq-core/cirq/devices/line_qubit_test.py b/cirq-core/cirq/devices/line_qubit_test.py index 30499b4154f..be857fd12d9 100644 --- a/cirq-core/cirq/devices/line_qubit_test.py +++ b/cirq-core/cirq/devices/line_qubit_test.py @@ -214,11 +214,9 @@ def test_neg(): def test_json_dict(): assert cirq.LineQubit(5)._json_dict_() == { - 'cirq_type': 'LineQubit', 'x': 5, } assert cirq.LineQid(5, 3)._json_dict_() == { - 'cirq_type': 'LineQid', 'x': 5, 'dimension': 3, } diff --git a/cirq-core/cirq/devices/named_topologies.py b/cirq-core/cirq/devices/named_topologies.py index 6d9f9303f6f..bdbc8895b53 100644 --- a/cirq-core/cirq/devices/named_topologies.py +++ b/cirq-core/cirq/devices/named_topologies.py @@ -13,7 +13,6 @@ # limitations under the License. import abc -import dataclasses import warnings from dataclasses import dataclass from typing import Dict, List, Tuple, Any, Sequence, Union, Iterable, TYPE_CHECKING @@ -23,16 +22,12 @@ from cirq import _compat from cirq.devices import GridQubit, LineQubit -from cirq.protocols.json_serialization import obj_to_dict_helper +from cirq.protocols.json_serialization import dataclass_json_dict if TYPE_CHECKING: import cirq -def dataclass_json_dict(obj: Any, namespace: str = None) -> Dict[str, Any]: - return obj_to_dict_helper(obj, [f.name for f in dataclasses.fields(obj)], namespace=namespace) - - class NamedTopology(metaclass=abc.ABCMeta): """A topology (graph) with a name. diff --git a/cirq-core/cirq/experiments/cross_entropy_benchmarking.py b/cirq-core/cirq/experiments/cross_entropy_benchmarking.py index 1e069267d5d..b8ed27b6ba1 100644 --- a/cirq-core/cirq/experiments/cross_entropy_benchmarking.py +++ b/cirq-core/cirq/experiments/cross_entropy_benchmarking.py @@ -253,7 +253,6 @@ class CrossEntropyResultDict(Mapping[Tuple['cirq.Qid', ...], CrossEntropyResult] def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'results': list(self.results.items()), } diff --git a/cirq-core/cirq/experiments/single_qubit_readout_calibration.py b/cirq-core/cirq/experiments/single_qubit_readout_calibration.py index b42dd8f9a40..decb3659dae 100644 --- a/cirq-core/cirq/experiments/single_qubit_readout_calibration.py +++ b/cirq-core/cirq/experiments/single_qubit_readout_calibration.py @@ -45,7 +45,6 @@ class SingleQubitReadoutCalibrationResult: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'zero_state_errors': list(self.zero_state_errors.items()), 'one_state_errors': list(self.one_state_errors.items()), 'repetitions': self.repetitions, diff --git a/cirq-core/cirq/ops/boolean_hamiltonian.py b/cirq-core/cirq/ops/boolean_hamiltonian.py index 0be4a2a7241..31502515d2b 100644 --- a/cirq-core/cirq/ops/boolean_hamiltonian.py +++ b/cirq-core/cirq/ops/boolean_hamiltonian.py @@ -94,7 +94,6 @@ def _value_equality_values_(self): def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'qubit_map': self._qubit_map, 'boolean_strs': self._boolean_strs, 'theta': self._theta, diff --git a/cirq-core/cirq/ops/clifford_gate.py b/cirq-core/cirq/ops/clifford_gate.py index d5d0977ee70..1fe8e6419f1 100644 --- a/cirq-core/cirq/ops/clifford_gate.py +++ b/cirq-core/cirq/ops/clifford_gate.py @@ -488,7 +488,6 @@ def _from_json_dict_(cls, n, rs, xs, zs, **kwargs): def _json_dict_(self) -> Dict[str, Any]: json_dict = self._clifford_tableau._json_dict_() - json_dict['cirq_type'] = self.__class__.__name__ return json_dict def _circuit_diagram_info_( diff --git a/cirq-core/cirq/ops/common_gates.py b/cirq-core/cirq/ops/common_gates.py index 0d2eb5c830a..4bef5936e90 100644 --- a/cirq-core/cirq/ops/common_gates.py +++ b/cirq-core/cirq/ops/common_gates.py @@ -318,7 +318,6 @@ def __repr__(self) -> str: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'rads': self._rads, } @@ -539,7 +538,6 @@ def __repr__(self) -> str: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'rads': self._rads, } @@ -825,7 +823,6 @@ def __repr__(self) -> str: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'rads': self._rads, } diff --git a/cirq-core/cirq/ops/controlled_gate.py b/cirq-core/cirq/ops/controlled_gate.py index be8e7af7660..776f472b09b 100644 --- a/cirq-core/cirq/ops/controlled_gate.py +++ b/cirq-core/cirq/ops/controlled_gate.py @@ -260,7 +260,6 @@ def __repr__(self) -> str: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'control_values': self.control_values, 'control_qid_shape': self.control_qid_shape, 'sub_gate': self.sub_gate, diff --git a/cirq-core/cirq/ops/controlled_operation.py b/cirq-core/cirq/ops/controlled_operation.py index 321f9df07bd..151eff60874 100644 --- a/cirq-core/cirq/ops/controlled_operation.py +++ b/cirq-core/cirq/ops/controlled_operation.py @@ -254,7 +254,6 @@ def get_symbol(vals): def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'controls': self.controls, 'control_values': self.control_values, 'sub_operation': self.sub_operation, diff --git a/cirq-core/cirq/ops/fourier_transform.py b/cirq-core/cirq/ops/fourier_transform.py index 66ee7d698a9..e8ebe7bebf8 100644 --- a/cirq-core/cirq/ops/fourier_transform.py +++ b/cirq-core/cirq/ops/fourier_transform.py @@ -42,7 +42,6 @@ def __init__(self, num_qubits: int, *, without_reverse: bool = False): def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'num_qubits': self._num_qubits, 'without_reverse': self._without_reverse, } @@ -98,7 +97,6 @@ def __init__(self, *, num_qubits: int, exponent: Union[float, sympy.Basic]): def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'num_qubits': self._num_qubits, 'exponent': self.exponent, } diff --git a/cirq-core/cirq/ops/fsim_gate_test.py b/cirq-core/cirq/ops/fsim_gate_test.py index 7a7ed934f61..b9e41b1a81b 100644 --- a/cirq-core/cirq/ops/fsim_gate_test.py +++ b/cirq-core/cirq/ops/fsim_gate_test.py @@ -278,7 +278,6 @@ def test_fsim_repr(): def test_fsim_json_dict(): assert cirq.FSimGate(theta=0.123, phi=0.456)._json_dict_() == { - 'cirq_type': 'FSimGate', 'theta': 0.123, 'phi': 0.456, } @@ -799,7 +798,6 @@ def test_phased_fsim_json_dict(): assert cirq.PhasedFSimGate( theta=0.12, zeta=0.34, chi=0.56, gamma=0.78, phi=0.9 )._json_dict_() == { - 'cirq_type': 'PhasedFSimGate', 'theta': 0.12, 'zeta': 0.34, 'chi': 0.56, diff --git a/cirq-core/cirq/ops/global_phase_op_test.py b/cirq-core/cirq/ops/global_phase_op_test.py index c37a9f4c269..22d4302512b 100644 --- a/cirq-core/cirq/ops/global_phase_op_test.py +++ b/cirq-core/cirq/ops/global_phase_op_test.py @@ -268,6 +268,5 @@ def test_diagram(): def test_global_phase_op_json_dict(): assert cirq.GlobalPhaseOperation(-1j)._json_dict_() == { - 'cirq_type': 'GlobalPhaseOperation', 'coefficient': -1j, } diff --git a/cirq-core/cirq/ops/identity.py b/cirq-core/cirq/ops/identity.py index e761e2fce84..0370c2c8a8f 100644 --- a/cirq-core/cirq/ops/identity.py +++ b/cirq-core/cirq/ops/identity.py @@ -115,7 +115,6 @@ def _json_dict_(self) -> Dict[str, Any]: if not all(d == 2 for d in self._qid_shape): other['qid_shape'] = self._qid_shape return { - 'cirq_type': self.__class__.__name__, 'num_qubits': len(self._qid_shape), **other, } diff --git a/cirq-core/cirq/ops/linear_combinations.py b/cirq-core/cirq/ops/linear_combinations.py index 089c1449858..e61f4cca73f 100644 --- a/cirq-core/cirq/ops/linear_combinations.py +++ b/cirq-core/cirq/ops/linear_combinations.py @@ -783,7 +783,6 @@ def _json_dict_(self) -> Dict[str, Any]: key = [[k, v] for k, v in dict(projector_dict).items()] linear_dict.append([key, scalar]) return { - 'cirq_type': self.__class__.__name__, 'linear_dict': linear_dict, } diff --git a/cirq-core/cirq/ops/matrix_gates.py b/cirq-core/cirq/ops/matrix_gates.py index a9286a89ecd..4513d644566 100644 --- a/cirq-core/cirq/ops/matrix_gates.py +++ b/cirq-core/cirq/ops/matrix_gates.py @@ -84,7 +84,6 @@ def __init__( def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'matrix': self._matrix.tolist(), 'qid_shape': self._qid_shape, } diff --git a/cirq-core/cirq/ops/measurement_gate.py b/cirq-core/cirq/ops/measurement_gate.py index 581a51cdc71..db46c8b7eaf 100644 --- a/cirq-core/cirq/ops/measurement_gate.py +++ b/cirq-core/cirq/ops/measurement_gate.py @@ -229,7 +229,6 @@ def _json_dict_(self) -> Dict[str, Any]: if not all(d == 2 for d in self._qid_shape): other['qid_shape'] = self._qid_shape return { - 'cirq_type': self.__class__.__name__, 'num_qubits': len(self._qid_shape), 'key': self.key, 'invert_mask': self.invert_mask, diff --git a/cirq-core/cirq/ops/moment_test.py b/cirq-core/cirq/ops/moment_test.py index 573cb634e00..72e1997affb 100644 --- a/cirq-core/cirq/ops/moment_test.py +++ b/cirq-core/cirq/ops/moment_test.py @@ -374,7 +374,7 @@ def test_json_dict(): a = cirq.NamedQubit('a') b = cirq.NamedQubit('b') mom = cirq.Moment([cirq.CZ(a, b)]) - assert mom._json_dict_() == {'cirq_type': 'Moment', 'operations': (cirq.CZ(a, b),)} + assert mom._json_dict_() == {'operations': (cirq.CZ(a, b),)} def test_inverse(): diff --git a/cirq-core/cirq/ops/named_qubit_test.py b/cirq-core/cirq/ops/named_qubit_test.py index aed024e6af2..392c3635ee5 100644 --- a/cirq-core/cirq/ops/named_qubit_test.py +++ b/cirq-core/cirq/ops/named_qubit_test.py @@ -136,12 +136,10 @@ def test_named_qid_range(): def test_to_json(): assert cirq.NamedQubit('c')._json_dict_() == { - 'cirq_type': 'NamedQubit', 'name': 'c', } assert cirq.NamedQid('c', dimension=3)._json_dict_() == { - 'cirq_type': 'NamedQid', 'name': 'c', 'dimension': 3, } diff --git a/cirq-core/cirq/ops/pauli_measurement_gate.py b/cirq-core/cirq/ops/pauli_measurement_gate.py index eadf8500509..43aa751f9a4 100644 --- a/cirq-core/cirq/ops/pauli_measurement_gate.py +++ b/cirq-core/cirq/ops/pauli_measurement_gate.py @@ -149,7 +149,6 @@ def _value_equality_values_(self) -> Any: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'observable': self._observable, 'key': self.key, } diff --git a/cirq-core/cirq/ops/pauli_string.py b/cirq-core/cirq/ops/pauli_string.py index e721f59dd58..0f0d25f1cb0 100644 --- a/cirq-core/cirq/ops/pauli_string.py +++ b/cirq-core/cirq/ops/pauli_string.py @@ -177,7 +177,6 @@ def _value_equality_values_(self): def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, # JSON requires mappings to have string keys. 'qubit_pauli_map': list(self._qubit_pauli_map.items()), 'coefficient': self.coefficient, @@ -1294,7 +1293,6 @@ def inplace_left_multiply_by( def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, # JSON requires mappings to have string keys. 'pauli_int_dict': list(self.pauli_int_dict.items()), 'coefficient': self.coefficient, diff --git a/cirq-core/cirq/ops/permutation_gate_test.py b/cirq-core/cirq/ops/permutation_gate_test.py index 4001f99d45a..386d62c9ee3 100644 --- a/cirq-core/cirq/ops/permutation_gate_test.py +++ b/cirq-core/cirq/ops/permutation_gate_test.py @@ -71,7 +71,6 @@ def test_permutation_gate_diagram(): def test_permutation_gate_json_dict(): assert cirq.QubitPermutationGate([0, 1, 2])._json_dict_() == { - 'cirq_type': 'QubitPermutationGate', 'permutation': (0, 1, 2), } diff --git a/cirq-core/cirq/ops/phased_iswap_gate.py b/cirq-core/cirq/ops/phased_iswap_gate.py index 473c2484bf0..e0ae692a156 100644 --- a/cirq-core/cirq/ops/phased_iswap_gate.py +++ b/cirq-core/cirq/ops/phased_iswap_gate.py @@ -76,7 +76,6 @@ def _num_qubits_(self) -> int: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'phase_exponent': self._phase_exponent, 'exponent': self._exponent, } diff --git a/cirq-core/cirq/ops/projector.py b/cirq-core/cirq/ops/projector.py index e42affa426c..290ba2351e5 100644 --- a/cirq-core/cirq/ops/projector.py +++ b/cirq-core/cirq/ops/projector.py @@ -148,7 +148,6 @@ def __repr__(self) -> str: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'projector_dict': list(self._projector_dict.items()), 'coefficient': self._coefficient, } diff --git a/cirq-core/cirq/ops/raw_types_test.py b/cirq-core/cirq/ops/raw_types_test.py index afe77fdc639..a75ca8e38b0 100644 --- a/cirq-core/cirq/ops/raw_types_test.py +++ b/cirq-core/cirq/ops/raw_types_test.py @@ -73,7 +73,6 @@ def test_wrapped_qid(): assert str(ValidQubit('a').with_dimension(3)) == 'TQ_a (d=3)' assert ValidQubit('zz').with_dimension(3)._json_dict_() == { - 'cirq_type': '_QubitAsQid', 'qubit': ValidQubit('zz'), 'dimension': 3, } @@ -370,9 +369,7 @@ def _qid_shape_(self): def test_gate_json_dict(): g = cirq.CSWAP # not an eigen gate (which has its own _json_dict_) - assert g._json_dict_() == { - 'cirq_type': 'CSwapGate', - } + assert g._json_dict_() == {} def test_inverse_composite_diagram_info(): diff --git a/cirq-core/cirq/ops/state_preparation_channel.py b/cirq-core/cirq/ops/state_preparation_channel.py index 34bf34d6387..3c1bcab0b5d 100644 --- a/cirq-core/cirq/ops/state_preparation_channel.py +++ b/cirq-core/cirq/ops/state_preparation_channel.py @@ -60,7 +60,6 @@ def _has_unitary_(self) -> bool: def _json_dict_(self) -> Dict[str, Any]: """Converts the gate object into a serializable dictionary""" return { - 'cirq_type': self.__class__.__name__, 'target_state': self._state.tolist(), 'name': self._name, } diff --git a/cirq-core/cirq/ops/tags.py b/cirq-core/cirq/ops/tags.py index a1c4a3c4790..fec819a88e0 100644 --- a/cirq-core/cirq/ops/tags.py +++ b/cirq-core/cirq/ops/tags.py @@ -33,4 +33,4 @@ def __repr__(self) -> str: return 'cirq.VirtualTag()' def _json_dict_(self) -> Dict[str, str]: - return {'cirq_type': self.__class__.__name__} + return {} diff --git a/cirq-core/cirq/protocols/json_serialization.py b/cirq-core/cirq/protocols/json_serialization.py index b3ddb386b91..a32d3691f6b 100644 --- a/cirq-core/cirq/protocols/json_serialization.py +++ b/cirq-core/cirq/protocols/json_serialization.py @@ -16,6 +16,7 @@ import json import numbers import pathlib +import warnings from typing import ( Any, Callable, @@ -38,6 +39,7 @@ import sympy from typing_extensions import Protocol +from cirq._compat import deprecated_parameter from cirq._doc import doc_private from cirq.type_workarounds import NotImplementedType @@ -145,6 +147,20 @@ def _json_namespace_(cls) -> str: pass +# TODO: remove once deprecated parameter goes away. +def _obj_to_dict_helper_helper(obj: Any, attribute_names: Iterable[str]) -> Dict[str, Any]: + d = {} + for attr_name in attribute_names: + d[attr_name] = getattr(obj, attr_name) + return d + + +@deprecated_parameter( + deadline='v0.15', + fix='Define obj._json_namespace_ to return namespace instead.', + parameter_desc='namespace', + match=lambda args, kwargs: 'namespace' in kwargs, +) def obj_to_dict_helper( obj: Any, attribute_names: Iterable[str], namespace: Optional[str] = None ) -> Dict[str, Any]: @@ -165,14 +181,10 @@ def obj_to_dict_helper( key "cirq_type". The namespace name will be joined with the class name via a dot (.) """ + d = {} if namespace is not None: - prefix = f'{namespace}.' - else: - prefix = '' - - d = {'cirq_type': prefix + obj.__class__.__name__} - for attr_name in attribute_names: - d[attr_name] = getattr(obj, attr_name) + d['cirq_type'] = f'{namespace}.' + obj.__class__.__name__ + d.update(_obj_to_dict_helper_helper(obj, attribute_names)) return d @@ -220,8 +232,10 @@ def wrap(cls): cls, init=init, repr=repr, eq=eq, order=order, unsafe_hash=unsafe_hash, frozen=frozen ) + cls._json_namespace_ = lambda: namespace + cls._json_dict_ = lambda obj: obj_to_dict_helper( - obj, [f.name for f in dataclasses.fields(cls)], namespace=namespace + obj, [f.name for f in dataclasses.fields(cls)] ) return cls @@ -237,6 +251,12 @@ def wrap(cls): # pylint: enable=redefined-builtin +@deprecated_parameter( + deadline='v0.15', + fix='Define obj._json_namespace_ to return namespace instead.', + parameter_desc='namespace', + match=lambda args, kwargs: 'namespace' in kwargs, +) def dataclass_json_dict(obj: Any, namespace: str = None) -> Dict[str, Any]: """Return a dictionary suitable for _json_dict_ from a dataclass. @@ -249,7 +269,24 @@ def dataclass_json_dict(obj: Any, namespace: str = None) -> Dict[str, Any]: Although not as elegant, you may want to consider explicitly defining `_json_dict_` on your dataclasses which simply `return dataclass_json_dict(self)`. """ - return obj_to_dict_helper(obj, [f.name for f in dataclasses.fields(obj)], namespace=namespace) + attribute_names = [f.name for f in dataclasses.fields(obj)] + if namespace is not None: + return obj_to_dict_helper(obj, attribute_names, namespace=namespace) + else: + return _obj_to_dict_helper_helper(obj, attribute_names) + + +def _json_dict_with_cirq_type(obj: Any): + base_dict = obj._json_dict_() + if 'cirq_type' in base_dict: + # TODO: upgrade to ValueError in v0.15 + warnings.warn( + f"Found 'cirq_type': '{base_dict['cirq_type']}' in _json_dict_. " + f"Custom values of this field are not permitted, and will produce " + "an error starting in Cirq v0.15.", + DeprecationWarning, + ) + return {'cirq_type': json_cirq_type(type(obj)), **base_dict} class CirqEncoder(json.JSONEncoder): @@ -272,17 +309,17 @@ class CirqEncoder(json.JSONEncoder): def default(self, o): # Object with custom method? if hasattr(o, '_json_dict_'): - return o._json_dict_() + return _json_dict_with_cirq_type(o) # Sympy object? (Must come before general number checks.) # TODO: More support for sympy # Github issue: https://github.com/quantumlib/Cirq/issues/2014 if isinstance(o, sympy.Symbol): - return obj_to_dict_helper(o, ['name'], namespace='sympy') + return {'cirq_type': 'sympy.Symbol', 'name': o.name} if isinstance(o, (sympy.Add, sympy.Mul, sympy.Pow)): - return obj_to_dict_helper(o, ['args'], namespace='sympy') + return {'cirq_type': f'sympy.{o.__class__.__name__}', 'args': o.args} if isinstance(o, sympy.Integer): return {'cirq_type': 'sympy.Integer', 'i': o.p} @@ -675,9 +712,9 @@ def default(self, o): if candidate.obj == o: if not candidate.key in ContextualEncoder.seen: ContextualEncoder.seen.add(candidate.key) - return candidate.obj._json_dict_() + return _json_dict_with_cirq_type(candidate.obj) else: - return _SerializedKey(candidate.key)._json_dict_() + return _json_dict_with_cirq_type(_SerializedKey(candidate.key)) raise ValueError("Object mutated during serialization.") # coverage: ignore cls = ContextualEncoder diff --git a/cirq-core/cirq/protocols/json_serialization_test.py b/cirq-core/cirq/protocols/json_serialization_test.py index d3e67f61760..2845d658d1a 100644 --- a/cirq-core/cirq/protocols/json_serialization_test.py +++ b/cirq-core/cirq/protocols/json_serialization_test.py @@ -75,6 +75,76 @@ def _get_testspecs_for_modules() -> List[ModuleJsonTestSpec]: MODULE_TEST_SPECS = _get_testspecs_for_modules() +def test_deprecated_cirq_type_in_json_dict(): + class HasOldJsonDict: + def __eq__(self, other): + return isinstance(other, HasOldJsonDict) + + def _json_dict_(self): + return {'cirq_type': 'cirq.testing.HasOldJsonDict'} + + @classmethod + def _from_json_dict_(cls, **kwargs): + return cls() + + def custom_resolver(name): + if name == 'cirq.testing.HasOldJsonDict': + return HasOldJsonDict + + test_resolvers = [custom_resolver] + cirq.DEFAULT_RESOLVERS + with cirq.testing.assert_deprecated("Found 'cirq_type'", deadline='v0.15'): + assert_json_roundtrip_works(HasOldJsonDict(), resolvers=test_resolvers) + + +def test_deprecated_obj_to_dict_helper_namespace(): + class HasOldJsonDict: + def __init__(self, x): + self.x = x + + def __eq__(self, other): + return isinstance(other, HasOldJsonDict) and other.x == self.x + + def _json_dict_(self): + return json_serialization.obj_to_dict_helper(self, ['x'], namespace='cirq.testing') + + @classmethod + def _from_json_dict_(cls, x, **kwargs): + return cls(x) + + def custom_resolver(name): + if name == 'cirq.testing.HasOldJsonDict': + return HasOldJsonDict + + test_resolvers = [custom_resolver] + cirq.DEFAULT_RESOLVERS + with cirq.testing.assert_deprecated( + "Found 'cirq_type'", 'Define obj._json_namespace_', deadline='v0.15', count=3 + ): + assert_json_roundtrip_works(HasOldJsonDict(1), resolvers=test_resolvers) + + +def test_deprecated_dataclass_json_dict_namespace(): + @dataclasses.dataclass + class HasOldJsonDict: + x: int + + def _json_dict_(self): + return json_serialization.dataclass_json_dict(self, namespace='cirq.testing') + + @classmethod + def _from_json_dict_(cls, x, **kwargs): + return cls(x) + + def custom_resolver(name): + if name == 'cirq.testing.HasOldJsonDict': + return HasOldJsonDict + + test_resolvers = [custom_resolver] + cirq.DEFAULT_RESOLVERS + with cirq.testing.assert_deprecated( + "Found 'cirq_type'", 'Define obj._json_namespace_', deadline='v0.15', count=5 + ): + assert_json_roundtrip_works(HasOldJsonDict(1), resolvers=test_resolvers) + + def test_line_qubit_roundtrip(): q1 = cirq.LineQubit(12) assert_json_roundtrip_works( @@ -360,7 +430,6 @@ def __eq__(self, other): def _json_dict_(self): return { - "cirq_type": "SBKImpl", "name": self.name, "data_list": self.data_list, "data_tuple": self.data_tuple, @@ -540,7 +609,6 @@ class SerializableTypeObject: def _json_dict_(self): return { - 'cirq_type': 'SerializableTypeObject', 'test_type': json_serialization.json_cirq_type(self.test_type), } diff --git a/cirq-core/cirq/qis/clifford_tableau_test.py b/cirq-core/cirq/qis/clifford_tableau_test.py index b8dd940e663..06f7aba3120 100644 --- a/cirq-core/cirq/qis/clifford_tableau_test.py +++ b/cirq-core/cirq/qis/clifford_tableau_test.py @@ -234,7 +234,6 @@ def test_json_dict(): assert t.stabilizers()[0] == cirq.DensePauliString('Z', coefficient=1) json_dict = t._json_dict_() except_json_dict = { - 'cirq_type': 'CliffordTableau', 'n': 1, 'rs': [False, False], 'xs': [[True], [False]], diff --git a/cirq-core/cirq/sim/clifford/clifford_simulator.py b/cirq-core/cirq/sim/clifford/clifford_simulator.py index dafed64ec61..f017d07bcf4 100644 --- a/cirq-core/cirq/sim/clifford/clifford_simulator.py +++ b/cirq-core/cirq/sim/clifford/clifford_simulator.py @@ -208,7 +208,6 @@ def __init__(self, qubit_map, initial_state: Union[int, clifford.StabilizerState def _json_dict_(self): return { - 'cirq_type': self.__class__.__name__, 'qubit_map': [(k, v) for k, v in self.qubit_map.items()], 'ch_form': self.ch_form, } diff --git a/cirq-core/cirq/study/resolver.py b/cirq-core/cirq/study/resolver.py index f5206640199..c126688e06e 100644 --- a/cirq-core/cirq/study/resolver.py +++ b/cirq-core/cirq/study/resolver.py @@ -233,7 +233,6 @@ def __repr__(self) -> str: def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, # JSON requires mappings to have keys of basic types. 'param_dict': list(self.param_dict.items()), } diff --git a/cirq-core/cirq/study/result.py b/cirq-core/cirq/study/result.py index 70057d17971..93637ae7864 100644 --- a/cirq-core/cirq/study/result.py +++ b/cirq-core/cirq/study/result.py @@ -324,7 +324,6 @@ def _json_dict_(self): 'shape': digits.shape, } return { - 'cirq_type': self.__class__.__name__, 'params': self.params, 'measurements': packed_measurements, } diff --git a/cirq-core/cirq/testing/no_identifier_qubit_test.py b/cirq-core/cirq/testing/no_identifier_qubit_test.py index c64aa00e0fd..d7972b1e3a2 100644 --- a/cirq-core/cirq/testing/no_identifier_qubit_test.py +++ b/cirq-core/cirq/testing/no_identifier_qubit_test.py @@ -27,6 +27,4 @@ def test_comparsion_key(): def test_to_json(): - assert cirq.testing.NoIdentifierQubit()._json_dict_() == { - 'cirq_type': 'NoIdentifierQubit', - } + assert cirq.testing.NoIdentifierQubit()._json_dict_() == {} diff --git a/cirq-core/cirq/value/duration.py b/cirq-core/cirq/value/duration.py index 03b0da9c541..592d0da4fe4 100644 --- a/cirq-core/cirq/value/duration.py +++ b/cirq-core/cirq/value/duration.py @@ -242,7 +242,7 @@ def __repr__(self) -> str: return f'cirq.Duration({unit}={proper_repr(amount)})' def _json_dict_(self) -> Dict[str, Any]: - return {'cirq_type': self.__class__.__name__, 'picos': self.total_picos()} + return {'picos': self.total_picos()} def _attempt_duration_like_to_duration(value: Any) -> Optional[Duration]: diff --git a/cirq-core/cirq/value/duration_test.py b/cirq-core/cirq/value/duration_test.py index debfda7a42b..8ca572e0bd8 100644 --- a/cirq-core/cirq/value/duration_test.py +++ b/cirq-core/cirq/value/duration_test.py @@ -177,7 +177,7 @@ def test_div(): def test_json_dict(): d = Duration(picos=6) - assert d._json_dict_() == {'cirq_type': 'Duration', 'picos': 6} + assert d._json_dict_() == {'picos': 6} def test_str(): diff --git a/cirq-core/cirq/value/linear_dict.py b/cirq-core/cirq/value/linear_dict.py index f8bbac38e2a..ba456f7ffa4 100644 --- a/cirq-core/cirq/value/linear_dict.py +++ b/cirq-core/cirq/value/linear_dict.py @@ -312,7 +312,6 @@ def _json_dict_(self) -> Dict[Any, Any]: if self._has_validator: raise ValueError('LinearDict with a validator is not json serializable.') return { - 'cirq_type': self.__class__.__name__, 'keys': [k for k in self._terms.keys()], 'values': [v for v in self._terms.values()], } diff --git a/cirq-core/cirq/value/measurement_key.py b/cirq-core/cirq/value/measurement_key.py index 1ee402d4aa8..2454c1a5dbe 100644 --- a/cirq-core/cirq/value/measurement_key.py +++ b/cirq-core/cirq/value/measurement_key.py @@ -79,7 +79,6 @@ def __hash__(self): def _json_dict_(self): return { - 'cirq_type': 'MeasurementKey', 'name': self.name, 'path': self.path, } diff --git a/cirq-core/cirq/value/measurement_key_test.py b/cirq-core/cirq/value/measurement_key_test.py index 62655269590..1cc450e32c2 100644 --- a/cirq-core/cirq/value/measurement_key_test.py +++ b/cirq-core/cirq/value/measurement_key_test.py @@ -72,9 +72,9 @@ def test_repr(): def test_json_dict(): mkey = cirq.MeasurementKey('key') - assert mkey._json_dict_() == {'cirq_type': 'MeasurementKey', 'name': 'key', 'path': tuple()} + assert mkey._json_dict_() == {'name': 'key', 'path': tuple()} mkey = cirq.MeasurementKey.parse_serialized('nested:key') - assert mkey._json_dict_() == {'cirq_type': 'MeasurementKey', 'name': 'key', 'path': ('nested',)} + assert mkey._json_dict_() == {'name': 'key', 'path': ('nested',)} def test_with_key_path(): diff --git a/cirq-core/cirq/value/product_state.py b/cirq-core/cirq/value/product_state.py index ba7575ee7eb..ba54265cddf 100644 --- a/cirq-core/cirq/value/product_state.py +++ b/cirq-core/cirq/value/product_state.py @@ -114,7 +114,6 @@ def __hash__(self): def _json_dict_(self): return { - 'cirq_type': self.__class__.__name__, 'states': list(self.states.items()), } diff --git a/cirq-core/cirq/work/observable_measurement_data.py b/cirq-core/cirq/work/observable_measurement_data.py index 1f8377734aa..b4da1a87faf 100644 --- a/cirq-core/cirq/work/observable_measurement_data.py +++ b/cirq-core/cirq/work/observable_measurement_data.py @@ -316,7 +316,6 @@ def ndarray_to_hex_str(a): return _pack_digits(a, pack_bits='never')[0] return { - 'cirq_type': self.__class__.__name__, 'meas_spec': self.meas_spec, 'simul_settings': self.simul_settings, 'qubit_to_index': list(self.qubit_to_index.items()), diff --git a/cirq-google/cirq_google/calibration/phased_fsim.py b/cirq-google/cirq_google/calibration/phased_fsim.py index 30f76e5c43a..9248a5571c8 100644 --- a/cirq-google/cirq_google/calibration/phased_fsim.py +++ b/cirq-google/cirq_google/calibration/phased_fsim.py @@ -331,7 +331,6 @@ class instantiation.""" def _json_dict_(self) -> Dict[str, Any]: """Magic method for the JSON serialization protocol.""" return { - 'cirq_type': 'PhasedFSimCalibrationResult', 'gate': self.gate, 'parameters': [(q_a, q_b, params) for (q_a, q_b), params in self.parameters.items()], 'options': self.options, @@ -747,7 +746,6 @@ class instantiation.""" def _json_dict_(self) -> Dict[str, Any]: """Magic method for the JSON serialization protocol.""" return { - 'cirq_type': 'FloquetPhasedFSimCalibrationRequest', 'pairs': [(pair[0], pair[1]) for pair in self.pairs], 'gate': self.gate, 'options': self.options, diff --git a/cirq-google/cirq_google/devices/known_devices.py b/cirq-google/cirq_google/devices/known_devices.py index e30b5cd3b6b..d4a6bf35a22 100644 --- a/cirq-google/cirq_google/devices/known_devices.py +++ b/cirq-google/cirq_google/devices/known_devices.py @@ -206,7 +206,6 @@ def _from_json_dict_(cls, constant: str, **kwargs): def _json_dict_(self) -> Dict[str, Any]: return { - 'cirq_type': self.__class__.__name__, 'constant': self._repr, } diff --git a/cirq-google/cirq_google/devices/known_devices_test.py b/cirq-google/cirq_google/devices/known_devices_test.py index e22a65c75c3..d3306d73e26 100644 --- a/cirq-google/cirq_google/devices/known_devices_test.py +++ b/cirq-google/cirq_google/devices/known_devices_test.py @@ -464,12 +464,10 @@ def test_multiple_gate_sets(): def test_json_dict(): assert cirq_google.Foxtail._json_dict_() == { - 'cirq_type': '_NamedConstantXmonDevice', 'constant': 'cirq_google.Foxtail', } assert cirq_google.Bristlecone._json_dict_() == { - 'cirq_type': '_NamedConstantXmonDevice', 'constant': 'cirq_google.Bristlecone', } diff --git a/cirq-google/cirq_google/engine/calibration.py b/cirq-google/cirq_google/engine/calibration.py index 800e7f97d8e..18dd442c694 100644 --- a/cirq-google/cirq_google/engine/calibration.py +++ b/cirq-google/cirq_google/engine/calibration.py @@ -154,7 +154,7 @@ def _from_json_dict_(cls, metrics: str, **kwargs) -> 'Calibration': def _json_dict_(self) -> Dict[str, Any]: """Magic method for the JSON serialization protocol.""" - return {'cirq_type': 'Calibration', 'metrics': json_format.MessageToDict(self.to_proto())} + return {'metrics': json_format.MessageToDict(self.to_proto())} def timestamp_str(self, tz: Optional[datetime.tzinfo] = None, timespec: str = 'auto') -> str: """Return a string for the calibration timestamp. diff --git a/cirq-google/cirq_google/engine/calibration_result.py b/cirq-google/cirq_google/engine/calibration_result.py index 35bc6136f7b..bcf54358d32 100644 --- a/cirq-google/cirq_google/engine/calibration_result.py +++ b/cirq-google/cirq_google/engine/calibration_result.py @@ -66,7 +66,6 @@ def _json_dict_(self) -> Dict[str, Any]: else None ) return { - 'cirq_type': 'CalibrationResult', 'code': self.code, 'error_message': self.error_message, 'token': self.token, diff --git a/cirq-google/cirq_google/optimizers/two_qubit_gates/gate_compilation.py b/cirq-google/cirq_google/optimizers/two_qubit_gates/gate_compilation.py index 25ce2a25d46..2ff36358713 100644 --- a/cirq-google/cirq_google/optimizers/two_qubit_gates/gate_compilation.py +++ b/cirq-google/cirq_google/optimizers/two_qubit_gates/gate_compilation.py @@ -113,7 +113,6 @@ def compile_two_qubit_gate(self, unitary: np.ndarray) -> TwoQubitGateCompilation def _json_dict_(self): return { - 'cirq_type': self.__class__.__name__, 'base_gate': self.base_gate.tolist(), 'kak_vecs': self.kak_vecs.tolist(), 'single_qubit_gates': self.single_qubit_gates, diff --git a/cirq-google/cirq_google/workflow/io.py b/cirq-google/cirq_google/workflow/io.py index 544cab16801..7cab45988ea 100644 --- a/cirq-google/cirq_google/workflow/io.py +++ b/cirq-google/cirq_google/workflow/io.py @@ -71,7 +71,7 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self) -> Dict[str, Any]: - return dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return dataclass_json_dict(self) def __repr__(self) -> str: return _compat.dataclass_repr(self, namespace='cirq_google') diff --git a/cirq-google/cirq_google/workflow/quantum_executable.py b/cirq-google/cirq_google/workflow/quantum_executable.py index b11dc475211..a84fbf13b47 100644 --- a/cirq-google/cirq_google/workflow/quantum_executable.py +++ b/cirq-google/cirq_google/workflow/quantum_executable.py @@ -58,7 +58,7 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self) -> Dict[str, Any]: - return cirq.dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return cirq.dataclass_json_dict(self) @classmethod def from_dict(cls, d: Dict[str, Any], *, executable_family: str) -> 'KeyValueExecutableSpec': @@ -99,7 +99,7 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self): - return cirq.dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return cirq.dataclass_json_dict(self) def __repr__(self): return cirq._compat.dataclass_repr(self, namespace='cirq_google') @@ -211,7 +211,7 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self): - return cirq.dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return cirq.dataclass_json_dict(self) @dataclass(frozen=True) @@ -265,4 +265,4 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self) -> Dict[str, Any]: - return cirq.dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return cirq.dataclass_json_dict(self) diff --git a/cirq-google/cirq_google/workflow/quantum_runtime.py b/cirq-google/cirq_google/workflow/quantum_runtime.py index f6a09d5b4ba..96b9358e84d 100644 --- a/cirq-google/cirq_google/workflow/quantum_runtime.py +++ b/cirq-google/cirq_google/workflow/quantum_runtime.py @@ -48,7 +48,7 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self) -> Dict[str, Any]: - return dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return dataclass_json_dict(self) def __repr__(self) -> str: return _compat.dataclass_repr(self, namespace='cirq_google') @@ -72,7 +72,7 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self) -> Dict[str, Any]: - return dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return dataclass_json_dict(self) def __repr__(self) -> str: return _compat.dataclass_repr(self, namespace='cirq_google') @@ -98,7 +98,7 @@ def _json_namespace_(cls) -> str: return 'cirq.google' def _json_dict_(self) -> Dict[str, Any]: - return dataclass_json_dict(self, namespace=cirq.json_namespace(type(self))) + return dataclass_json_dict(self) def __repr__(self) -> str: return _compat.dataclass_repr(self, namespace='cirq_google') @@ -122,8 +122,12 @@ class ExecutableGroupResult: shared_runtime_info: SharedRuntimeInfo executable_results: List[ExecutableResult] + @classmethod + def _json_namespace_(cls) -> str: + return 'cirq.google' + def _json_dict_(self) -> Dict[str, Any]: - return dataclass_json_dict(self, namespace='cirq.google') + return dataclass_json_dict(self) def __repr__(self) -> str: return _compat.dataclass_repr(self, namespace='cirq_google') @@ -144,8 +148,12 @@ class QuantumRuntimeConfiguration: processor: AbstractEngineProcessorShim run_id: Optional[str] = None + @classmethod + def _json_namespace_(cls) -> str: + return 'cirq.google' + def _json_dict_(self) -> Dict[str, Any]: - return dataclass_json_dict(self, namespace='cirq.google') + return dataclass_json_dict(self) def __repr__(self) -> str: return _compat.dataclass_repr(self, namespace='cirq_google') diff --git a/cirq-google/cirq_google/workflow/quantum_runtime_test.py b/cirq-google/cirq_google/workflow/quantum_runtime_test.py index 58636808d73..d422c5709ff 100644 --- a/cirq-google/cirq_google/workflow/quantum_runtime_test.py +++ b/cirq-google/cirq_google/workflow/quantum_runtime_test.py @@ -33,8 +33,12 @@ def get_device(self) -> cirq.Device: def get_sampler(self) -> cirq.Sampler: return cirq.ZerosSampler() + @classmethod + def _json_namespace_(cls) -> str: + return 'cirq.google.testing' + def _json_dict_(self): - return cirq.obj_to_dict_helper(self, attribute_names=[], namespace='cirq.google.testing') + return cirq.obj_to_dict_helper(self, attribute_names=[]) def cg_assert_equivalent_repr(value): diff --git a/cirq-pasqal/cirq_pasqal/pasqal_device_test.py b/cirq-pasqal/cirq_pasqal/pasqal_device_test.py index 28f092b7a71..c13b8b3eb86 100644 --- a/cirq-pasqal/cirq_pasqal/pasqal_device_test.py +++ b/cirq-pasqal/cirq_pasqal/pasqal_device_test.py @@ -271,11 +271,10 @@ def test_repr(): def test_to_json(): dev = PasqalDevice(qubits=[cirq.NamedQubit('q4')]) d = dev._json_dict_() - assert d == {"cirq_type": "PasqalDevice", "qubits": [cirq.NamedQubit('q4')]} + assert d == {"qubits": [cirq.NamedQubit('q4')]} vdev = PasqalVirtualDevice(control_radius=2, qubits=[TwoDQubit(0, 0)]) d = vdev._json_dict_() assert d == { - "cirq_type": "PasqalVirtualDevice", "control_radius": 2, "qubits": [cirq_pasqal.TwoDQubit(0, 0)], } diff --git a/cirq-pasqal/cirq_pasqal/pasqal_qubits_test.py b/cirq-pasqal/cirq_pasqal/pasqal_qubits_test.py index 7d506cc4f30..60256919211 100644 --- a/cirq-pasqal/cirq_pasqal/pasqal_qubits_test.py +++ b/cirq-pasqal/cirq_pasqal/pasqal_qubits_test.py @@ -165,7 +165,6 @@ def test_to_json(): q = ThreeDQubit(1.3, 1, 1) d = q._json_dict_() assert d == { - 'cirq_type': 'ThreeDQubit', 'x': 1.3, 'y': 1, 'z': 1, @@ -173,7 +172,6 @@ def test_to_json(): q = TwoDQubit(1.3, 1) d = q._json_dict_() assert d == { - 'cirq_type': 'TwoDQubit', 'x': 1.3, 'y': 1, } diff --git a/cirq-rigetti/cirq_rigetti/aspen_device.py b/cirq-rigetti/cirq_rigetti/aspen_device.py index 2c2045e0d81..0ade55af8a7 100644 --- a/cirq-rigetti/cirq_rigetti/aspen_device.py +++ b/cirq-rigetti/cirq_rigetti/aspen_device.py @@ -231,7 +231,6 @@ def __repr__(self): def _json_dict_(self): return { - 'cirq_type': 'RigettiQCSAspenDevice', 'isa': self.isa.to_dict(), } @@ -386,7 +385,6 @@ def __repr__(self): def _json_dict_(self): return { - 'cirq_type': 'OctagonalQubit', 'octagon_position': self.octagon_position, } @@ -526,7 +524,6 @@ def __str__(self): def _json_dict_(self): return { - 'cirq_type': 'AspenQubit', 'octagon': self.octagon, 'octagon_position': self.octagon_position, }