Skip to content

Commit

Permalink
Refactor json_test's TEST_OBJECTS value into test data files (#2527)
Browse files Browse the repository at this point in the history
This spreads out the gigantic list a bit, but mainly it allows us a format for adding backwards compatibility tests (where the repr file contains the intended result, instead of the object that initially produced the JSON).

The test files were generated by iterating over the test object and using cirq.to_json and repr.

Fixes #2425

This is maybe the third time I find myself refactoring this code. I wonder what the next one will be?
  • Loading branch information
Strilanc authored and CirqBot committed Nov 14, 2019
1 parent 6d5087c commit 4ff38cf
Show file tree
Hide file tree
Showing 202 changed files with 3,090 additions and 252 deletions.
18 changes: 18 additions & 0 deletions cirq/_compat.py
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,24 @@ def proper_repr(value: Any) -> str:
return repr(value)


def proper_eq(a: Any, b: Any) -> bool:
"""Compares objects for equality, working around __eq__ not always working.
For example, in numpy a == b broadcasts and returns an array instead of
doing what np.array_equal(a, b) does. This method uses np.array_equal(a, b)
when dealing with numpy arrays.
"""
if type(a) == type(b):
if isinstance(a, np.ndarray):
return np.array_equal(a, b)
if isinstance(a, (pd.DataFrame, pd.Index, pd.MultiIndex)):
return a.equals(b)
if isinstance(a, (tuple, list)):
return len(a) == len(b) and all(
proper_eq(x, y) for x, y in zip(a, b))
return a == b


def deprecated(*, deadline: str, fix: str, func_name: Optional[str] = None
) -> Callable[[Callable], Callable]:
"""Marks a function as deprecated.
Expand Down
21 changes: 20 additions & 1 deletion cirq/_compat_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,12 @@
import pandas as pd
import sympy

from cirq._compat import proper_repr, deprecated, deprecated_parameter
from cirq._compat import (
proper_repr,
deprecated,
deprecated_parameter,
proper_eq,
)


def test_proper_repr():
Expand Down Expand Up @@ -56,6 +61,20 @@ def test_proper_repr_data_frame():
pd.testing.assert_frame_equal(df2, df)


def test_proper_eq():
assert proper_eq(1, 1)
assert not proper_eq(1, 2)

assert proper_eq(np.array([1, 2, 3]), np.array([1, 2, 3]))
assert not proper_eq(np.array([1, 2, 3]), np.array([1, 2, 3, 4]))
assert not proper_eq(np.array([1, 2, 3]), np.array([[1, 2, 3]]))
assert not proper_eq(np.array([1, 2, 3]), np.array([1, 4, 3]))

assert proper_eq(pd.Index([1, 2, 3]), pd.Index([1, 2, 3]))
assert not proper_eq(pd.Index([1, 2, 3]), pd.Index([1, 2, 3, 4]))
assert not proper_eq(pd.Index([1, 2, 3]), pd.Index([1, 4, 3]))


def test_deprecated():

@deprecated(deadline='vNever', fix='Roll some dice.', func_name='test_func')
Expand Down
13 changes: 9 additions & 4 deletions cirq/google/devices/known_devices.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

from typing import Dict, Optional, Iterable, List, Set, Tuple

from cirq import value
from cirq._doc import document
from cirq.devices import GridQubit
from cirq.google import gate_sets, serializable_gate_set
Expand Down Expand Up @@ -172,14 +173,18 @@ def __init__(self, constant: str, **kwargs) -> None:
def __repr__(self):
return self._repr

@classmethod
def _from_json_dict_(cls, constant: str, **kwargs):
if constant == Foxtail._repr:
return Foxtail
if constant == Bristlecone._repr:
return Bristlecone
raise ValueError(f'Unrecognized xmon device name: {constant!r}')

def _json_dict_(self):
return {
'cirq_type': self.__class__.__name__,
'constant': self._repr,
'measurement_duration': self._measurement_duration,
'exp_w_duration': self._exp_w_duration,
'exp_11_duration': self._exp_z_duration,
'qubits': sorted(self.qubits)
}


Expand Down
13 changes: 5 additions & 8 deletions cirq/google/devices/known_devices_test.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import numpy as np
import pytest

import cirq
import cirq.google as cg
Expand Down Expand Up @@ -377,21 +378,17 @@ def test_json_dict():
assert cg.Foxtail._json_dict_() == {
'cirq_type': '_NamedConstantXmonDevice',
'constant': 'cirq.google.Foxtail',
'measurement_duration': cirq.Duration(nanos=4000),
'exp_w_duration': cirq.Duration(nanos=20),
'exp_11_duration': cirq.Duration(nanos=50),
'qubits': sorted(cirq.google.Foxtail.qubits)
}

assert cirq.google.Bristlecone._json_dict_() == {
'cirq_type': '_NamedConstantXmonDevice',
'constant': 'cirq.google.Bristlecone',
'measurement_duration': cirq.Duration(nanos=4000),
'exp_w_duration': cirq.Duration(nanos=20),
'exp_11_duration': cirq.Duration(nanos=50),
'qubits': sorted(cirq.google.Bristlecone.qubits)
}

from cirq.google.devices.known_devices import _NamedConstantXmonDevice
with pytest.raises(ValueError, match='xmon device name'):
_NamedConstantXmonDevice._from_json_dict_('the_unknown_fiddler')


def test_sycamore_device():
q0 = cirq.GridQubit(5, 4)
Expand Down
5 changes: 4 additions & 1 deletion cirq/protocols/json.py
Original file line number Diff line number Diff line change
Expand Up @@ -317,7 +317,10 @@ def _cirq_object_hook(d, resolvers: List[Callable[[str], Union[None, Type]]]):

# pylint: disable=function-redefined
@overload
def to_json(obj: Any, file_or_fn: Union[IO, str], *, indent=2,
def to_json(obj: Any,
file_or_fn: Union[IO, pathlib.Path, str],
*,
indent=2,
cls=CirqEncoder) -> None:
pass

Expand Down

0 comments on commit 4ff38cf

Please sign in to comment.