From 2348b1de098ad5fa943f82b8a036d598d8329958 Mon Sep 17 00:00:00 2001 From: Maxim V4S Date: Mon, 21 Oct 2024 12:45:08 +0300 Subject: [PATCH] tests(refactor): use default factory of Field class instead of `[]` Usage of `[]` can cause issues because of closure --- tests/conftest.py | 3 +- .../0_basic_node.py | 4 +- .../1_node_with_partial_outcomes.py | 4 +- .../calibrations/01_first_node.py | 4 +- .../calibrations/02_second_node.py | 4 +- .../calibrations/03_third_node.py | 4 +- .../{04_forth_node.py => 04_fourth_node.py} | 4 +- .../test_basic_orchestrator.py | 5 +- .../calibrations/01_test_state_updates.py | 4 +- .../calibrations/02_node.py | 4 +- .../calibrations/05_test_cal.py | 4 +- .../test_qualibration_graph/test_graph.py | 3 +- .../test_execution_parameters.py | 211 +++++++++--------- .../test_parameter_serialization.py | 8 +- .../calibrations/01_test_state_updates.py | 4 +- .../calibrations/02_node.py | 4 +- .../calibrations/05_test_cal.py | 4 +- .../test_graph_export.py | 4 +- .../unit/test_qualibration_node/test_node.py | 13 +- .../test_qualibration_node/test_node_copy.py | 3 +- 20 files changed, 167 insertions(+), 131 deletions(-) rename tests/integration/test_orchestration/calibrations/{04_forth_node.py => 04_fourth_node.py} (77%) diff --git a/tests/conftest.py b/tests/conftest.py index 28ab145..979a6ed 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,5 @@ import pytest +from pydantic import Field from qualibrate import NodeParameters, QualibrationNode @@ -6,7 +7,7 @@ @pytest.fixture def node(): class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) str_value: str = "test" int_value: int = 1 diff --git a/tests/integration/example_calibration_scripts/0_basic_node.py b/tests/integration/example_calibration_scripts/0_basic_node.py index 2ba2935..0e043be 100644 --- a/tests/integration/example_calibration_scripts/0_basic_node.py +++ b/tests/integration/example_calibration_scripts/0_basic_node.py @@ -1,8 +1,10 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) node = QualibrationNode("basic_node", parameters=Parameters()) diff --git a/tests/integration/example_calibration_scripts/1_node_with_partial_outcomes.py b/tests/integration/example_calibration_scripts/1_node_with_partial_outcomes.py index 14b58ac..f2950f1 100644 --- a/tests/integration/example_calibration_scripts/1_node_with_partial_outcomes.py +++ b/tests/integration/example_calibration_scripts/1_node_with_partial_outcomes.py @@ -1,12 +1,14 @@ from typing import ClassVar +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode from qualibrate.models.outcome import Outcome class Parameters(NodeParameters): targets_name: ClassVar[str] = "qubits" - qubits: list[str] = ["q0", "q1", "q2"] + qubits: list[str] = Field(default_factory=lambda: ["q0", "q1", "q2"]) node = QualibrationNode("node_part_outcome", parameters=Parameters()) diff --git a/tests/integration/test_orchestration/calibrations/01_first_node.py b/tests/integration/test_orchestration/calibrations/01_first_node.py index 6a00fe3..1ddb46a 100644 --- a/tests/integration/test_orchestration/calibrations/01_first_node.py +++ b/tests/integration/test_orchestration/calibrations/01_first_node.py @@ -1,9 +1,11 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode from qualibrate.models.outcome import Outcome class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) str_value: str = "test" diff --git a/tests/integration/test_orchestration/calibrations/02_second_node.py b/tests/integration/test_orchestration/calibrations/02_second_node.py index 81f2a83..23bccf8 100644 --- a/tests/integration/test_orchestration/calibrations/02_second_node.py +++ b/tests/integration/test_orchestration/calibrations/02_second_node.py @@ -1,9 +1,11 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode from qualibrate.models.outcome import Outcome class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) float_value: float = 1.0 diff --git a/tests/integration/test_orchestration/calibrations/03_third_node.py b/tests/integration/test_orchestration/calibrations/03_third_node.py index c415c8e..9857c6b 100644 --- a/tests/integration/test_orchestration/calibrations/03_third_node.py +++ b/tests/integration/test_orchestration/calibrations/03_third_node.py @@ -1,8 +1,10 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) int_value: int = 2 diff --git a/tests/integration/test_orchestration/calibrations/04_forth_node.py b/tests/integration/test_orchestration/calibrations/04_fourth_node.py similarity index 77% rename from tests/integration/test_orchestration/calibrations/04_forth_node.py rename to tests/integration/test_orchestration/calibrations/04_fourth_node.py index 7ad7281..736aa80 100644 --- a/tests/integration/test_orchestration/calibrations/04_forth_node.py +++ b/tests/integration/test_orchestration/calibrations/04_fourth_node.py @@ -1,8 +1,10 @@ +from pydantic import Field + from qualibrate import QualibrationNode, NodeParameters class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) sampling_points: int = 100 diff --git a/tests/integration/test_orchestration/test_basic_orchestrator.py b/tests/integration/test_orchestration/test_basic_orchestrator.py index fc334e1..4bdf430 100644 --- a/tests/integration/test_orchestration/test_basic_orchestrator.py +++ b/tests/integration/test_orchestration/test_basic_orchestrator.py @@ -2,6 +2,7 @@ from typing import Generator import pytest +from pydantic import Field from qualibrate.models.execution_history import ExecutionHistoryItem from qualibrate.models.node_status import NodeStatus @@ -24,7 +25,9 @@ def qualibration_lib() -> Generator[QualibrationLibrary, None, None]: @pytest.fixture def graph_params() -> GraphParameters: class GP(GraphParameters): - qubits: list[str] = ["q1", "q2", "q3", "q4"] + qubits: list[str] = Field( + default_factory=lambda: ["q1", "q2", "q3", "q4"] + ) retries: int = 2 return GP() diff --git a/tests/integration/test_qualibration_graph/calibrations/01_test_state_updates.py b/tests/integration/test_qualibration_graph/calibrations/01_test_state_updates.py index a76be76..6811199 100644 --- a/tests/integration/test_qualibration_graph/calibrations/01_test_state_updates.py +++ b/tests/integration/test_qualibration_graph/calibrations/01_test_state_updates.py @@ -1,8 +1,10 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) str_value: str = "test" int_value: int = 1 float_value: float = 1.0 diff --git a/tests/integration/test_qualibration_graph/calibrations/02_node.py b/tests/integration/test_qualibration_graph/calibrations/02_node.py index c31e61c..7242891 100644 --- a/tests/integration/test_qualibration_graph/calibrations/02_node.py +++ b/tests/integration/test_qualibration_graph/calibrations/02_node.py @@ -1,8 +1,10 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) str_value: str = "test" float_value: float = 1.0 diff --git a/tests/integration/test_qualibration_graph/calibrations/05_test_cal.py b/tests/integration/test_qualibration_graph/calibrations/05_test_cal.py index 75387ae..230dd4b 100644 --- a/tests/integration/test_qualibration_graph/calibrations/05_test_cal.py +++ b/tests/integration/test_qualibration_graph/calibrations/05_test_cal.py @@ -1,3 +1,5 @@ +from pydantic import Field + from qualibrate import QualibrationNode, NodeParameters from quam.components import * import numpy as np @@ -6,7 +8,7 @@ class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) resonator: str = "q1.resonator" sampling_points: int = 100 diff --git a/tests/integration/test_qualibration_graph/test_graph.py b/tests/integration/test_qualibration_graph/test_graph.py index 579ae89..801f279 100644 --- a/tests/integration/test_qualibration_graph/test_graph.py +++ b/tests/integration/test_qualibration_graph/test_graph.py @@ -2,6 +2,7 @@ from typing import Any, Generator, Sequence import pytest +from pydantic import Field from qualibrate.orchestration.qualibration_orchestrator import ( QualibrationOrchestrator, @@ -23,7 +24,7 @@ def qualibration_lib() -> Generator[QualibrationLibrary, None, None]: @pytest.fixture def graph_params() -> GraphParameters: class GP(GraphParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) retries: int = 2 return GP(retries=1) diff --git a/tests/unit/test_parameters/test_execution_parameters.py b/tests/unit/test_parameters/test_execution_parameters.py index c4dd705..540b819 100644 --- a/tests/unit/test_parameters/test_execution_parameters.py +++ b/tests/unit/test_parameters/test_execution_parameters.py @@ -10,20 +10,25 @@ NodesParameters, RunnableParameters, ) +from qualibrate.utils.type_protocols import TargetType class Node1(NodeParameters): - qubits: Optional[List[str]] = ["a", "b", "c"] + qubits: Optional[List[TargetType]] = Field( + default_factory=lambda: ["a", "b", "c"] + ) int_value: int = 1 class Node2(NodeParameters): - qubits: Optional[List[str]] = ["d", "e", "f"] + qubits: Optional[List[TargetType]] = Field( + default_factory=lambda: ["d", "e", "f"] + ) float_value: float = 2.0 class Graph(GraphParameters): - qubits: Optional[List[str]] = ["1", "2", "3"] + qubits: List[TargetType] = Field(default_factory=lambda: ["1", "2", "3"]) str_value: str = "test" @@ -56,11 +61,8 @@ def test_serialize_exclude_targets_default(self): assert ExecutionParams.serialize() == { "parameters": { "qubits": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "default": ["1", "2", "3"], + "items": {"type": "string"}, + "type": "array", "title": "Qubits", "is_targets": True, }, @@ -91,116 +93,113 @@ def test_serialize_exclude_targets_default(self): }, } - def test_serialize_force_exclude_targets(self): - assert ExecutionParams.serialize(exclude_targets=True) == { - "parameters": { - "str_value": { - "default": "test", - "title": "Str Value", - "type": "string", - "is_targets": False, - } - }, - "nodes": { - "node1": { - "int_value": { - "default": 1, - "title": "Int Value", - "type": "integer", + def test_serialize_force_exclude_targets(self): + assert ExecutionParams.serialize(exclude_targets=True) == { + "parameters": { + "str_value": { + "default": "test", + "title": "Str Value", + "type": "string", "is_targets": False, } }, - "node2": { - "float_value": { - "default": 2.0, - "title": "Float Value", - "type": "number", - "is_targets": False, - } + "nodes": { + "node1": { + "int_value": { + "default": 1, + "title": "Int Value", + "type": "integer", + "is_targets": False, + } + }, + "node2": { + "float_value": { + "default": 2.0, + "title": "Float Value", + "type": "number", + "is_targets": False, + } + }, }, - }, - } + } - def test_serialize_force_not_exclude_targets(self): - assert ExecutionParams.serialize(exclude_targets=False) == { - "parameters": { - "qubits": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "default": ["1", "2", "3"], - "title": "Qubits", - "is_targets": True, - }, - "str_value": { - "default": "test", - "title": "Str Value", - "type": "string", - "is_targets": False, - }, - }, - "nodes": { - "node1": { + def test_serialize_force_not_exclude_targets(self): + assert ExecutionParams.serialize(exclude_targets=False) == { + "parameters": { "qubits": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "default": ["a", "b", "c"], + "items": {"type": "string"}, + "type": "array", "title": "Qubits", "is_targets": True, }, - "int_value": { - "default": 1, - "title": "Int Value", - "type": "integer", + "str_value": { + "default": "test", + "title": "Str Value", + "type": "string", "is_targets": False, }, }, - "node2": { - "qubits": { - "anyOf": [ - {"items": {"type": "string"}, "type": "array"}, - {"type": "null"}, - ], - "default": ["d", "e", "f"], - "title": "Qubits", - "is_targets": True, + "nodes": { + "node1": { + "qubits": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "default": ["a", "b", "c"], + "title": "Qubits", + "is_targets": True, + }, + "int_value": { + "default": 1, + "title": "Int Value", + "type": "integer", + "is_targets": False, + }, }, - "float_value": { - "default": 2.0, - "title": "Float Value", - "type": "number", - "is_targets": False, + "node2": { + "qubits": { + "anyOf": [ + {"items": {"type": "string"}, "type": "array"}, + {"type": "null"}, + ], + "default": ["d", "e", "f"], + "title": "Qubits", + "is_targets": True, + }, + "float_value": { + "default": 2.0, + "title": "Float Value", + "type": "number", + "is_targets": False, + }, }, }, - }, - } - - def test_serialize_with_none_parameters_class(self, mocker): - mock_model_fields = mocker.patch( - "qualibrate.parameters.ExecutionParameters.model_fields" - ) - mock_model_fields.__getitem__.return_value = mocker.MagicMock( - annotation=None - ) - - with pytest.raises( - RuntimeError, match="Graph parameters class can't be none" - ): - ExecutionParameters.serialize() - - def test_serialize_none_parameters_class(self, mocker): - mock_model_fields = mocker.patch( - "qualibrate.parameters.ExecutionParameters.model_fields" - ) - mock_model_fields.__getitem__.return_value = mocker.MagicMock( - annotation=RunnableParameters - ) - - with pytest.raises( - RuntimeError, - match="Graph parameters class should be subclass of qualibrate.parameters.GraphParameters", - ): - ExecutionParameters.serialize() + } + + def test_serialize_with_none_parameters_class(self, mocker): + mock_model_fields = mocker.patch( + "qualibrate.parameters.ExecutionParameters.model_fields" + ) + mock_model_fields.__getitem__.return_value = mocker.MagicMock( + annotation=None + ) + + with pytest.raises( + RuntimeError, match="Graph parameters class can't be none" + ): + ExecutionParameters.serialize() + + def test_serialize_none_parameters_class(self, mocker): + mock_model_fields = mocker.patch( + "qualibrate.parameters.ExecutionParameters.model_fields" + ) + mock_model_fields.__getitem__.return_value = mocker.MagicMock( + annotation=RunnableParameters + ) + + with pytest.raises( + RuntimeError, + match="Graph parameters class should be subclass of qualibrate.parameters.GraphParameters", + ): + ExecutionParameters.serialize() diff --git a/tests/unit/test_parameters/test_parameter_serialization.py b/tests/unit/test_parameters/test_parameter_serialization.py index 7b2d983..1af8a3b 100644 --- a/tests/unit/test_parameters/test_parameter_serialization.py +++ b/tests/unit/test_parameters/test_parameter_serialization.py @@ -1,16 +1,17 @@ +from pydantic import Field + from qualibrate.parameters import RunnableParameters def test_parameters_empty_serialization(): class Parameters(RunnableParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) parameters = Parameters() serialized = parameters.serialize() assert serialized == { "qubits": { - "default": [], "items": {"type": "string"}, "title": "Qubits", "type": "array", @@ -20,7 +21,7 @@ class Parameters(RunnableParameters): def test_parameters_default_types_serialization(): class Parameters(RunnableParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) bool_val: bool = False int_val: int = 0 float_val: float = 0.0 @@ -43,7 +44,6 @@ class Parameters(RunnableParameters): }, "str_val": {"default": "", "title": "Str Val", "type": "string"}, "qubits": { - "default": [], "items": {"type": "string"}, "title": "Qubits", "type": "array", diff --git a/tests/unit/test_qualibration_graph/calibrations/01_test_state_updates.py b/tests/unit/test_qualibration_graph/calibrations/01_test_state_updates.py index a76be76..6811199 100644 --- a/tests/unit/test_qualibration_graph/calibrations/01_test_state_updates.py +++ b/tests/unit/test_qualibration_graph/calibrations/01_test_state_updates.py @@ -1,8 +1,10 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) str_value: str = "test" int_value: int = 1 float_value: float = 1.0 diff --git a/tests/unit/test_qualibration_graph/calibrations/02_node.py b/tests/unit/test_qualibration_graph/calibrations/02_node.py index 9209ea8..e3a28b9 100644 --- a/tests/unit/test_qualibration_graph/calibrations/02_node.py +++ b/tests/unit/test_qualibration_graph/calibrations/02_node.py @@ -1,8 +1,10 @@ +from pydantic import Field + from qualibrate import NodeParameters, QualibrationNode class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) str_value: str = "test" float_value: float = 1.0 diff --git a/tests/unit/test_qualibration_graph/calibrations/05_test_cal.py b/tests/unit/test_qualibration_graph/calibrations/05_test_cal.py index 75387ae..230dd4b 100644 --- a/tests/unit/test_qualibration_graph/calibrations/05_test_cal.py +++ b/tests/unit/test_qualibration_graph/calibrations/05_test_cal.py @@ -1,3 +1,5 @@ +from pydantic import Field + from qualibrate import QualibrationNode, NodeParameters from quam.components import * import numpy as np @@ -6,7 +8,7 @@ class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) resonator: str = "q1.resonator" sampling_points: int = 100 diff --git a/tests/unit/test_qualibration_graph/test_graph_export.py b/tests/unit/test_qualibration_graph/test_graph_export.py index 425c382..628c90a 100644 --- a/tests/unit/test_qualibration_graph/test_graph_export.py +++ b/tests/unit/test_qualibration_graph/test_graph_export.py @@ -2,6 +2,7 @@ from typing import Any, Generator, Sequence import pytest +from pydantic import Field from qualibrate.orchestration.qualibration_orchestrator import ( QualibrationOrchestrator, @@ -23,7 +24,7 @@ def qualibration_lib() -> Generator[QualibrationLibrary, None, None]: @pytest.fixture def graph_params() -> GraphParameters: class GP(GraphParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) retries: int = 2 return GP(retries=1) @@ -157,7 +158,6 @@ def test_serialize( "type": "integer", }, "qubits": { - "default": [], "is_targets": True, "items": {"type": "string"}, "title": "Qubits", diff --git a/tests/unit/test_qualibration_node/test_node.py b/tests/unit/test_qualibration_node/test_node.py index edd4e7e..d0b444c 100644 --- a/tests/unit/test_qualibration_node/test_node.py +++ b/tests/unit/test_qualibration_node/test_node.py @@ -3,6 +3,7 @@ from unittest.mock import MagicMock, PropertyMock import pytest +from pydantic import Field from qualibrate import QualibrationNode from qualibrate.models.outcome import Outcome @@ -257,7 +258,9 @@ def test_save_without_storage_manager_no_qualibrate_app( def test__post_run(self, mocker): class P(NodeCreateParametersType): - qubits: list[str] = ["target1", "target2", "target3"] + qubits: list[str] = Field( + default_factory=lambda: ["target1", "target2", "target3"] + ) node = QualibrationNode(name="test_node") last_executed_node = MagicMock() @@ -300,7 +303,9 @@ def test_run_successful( mock_last_executed_node_ctx, ): class P(NodeCreateParametersType): - qubits: list[str] = ["target1", "target2"] + qubits: list[str] = Field( + default_factory=lambda: ["target1", "target2"] + ) node = QualibrationNode(name="test_node") node.filepath = Path("test_path") @@ -351,7 +356,9 @@ def test_run_exception( mock_last_executed_node_ctx, ): class P(NodeCreateParametersType): - qubits: list[str] = ["target1", "target2"] + qubits: list[str] = Field( + default_factory=lambda: ["target1", "target2"] + ) node = QualibrationNode(name="test_node") node.filepath = Path("test_path") diff --git a/tests/unit/test_qualibration_node/test_node_copy.py b/tests/unit/test_qualibration_node/test_node_copy.py index 6bb8390..d841cda 100644 --- a/tests/unit/test_qualibration_node/test_node_copy.py +++ b/tests/unit/test_qualibration_node/test_node_copy.py @@ -1,6 +1,7 @@ from typing import Type import pytest +from pydantic import Field from qualibrate.parameters import NodeParameters from qualibrate.qualibration_node import QualibrationNode @@ -9,7 +10,7 @@ @pytest.fixture def params_with_req() -> Type[NodeParameters]: class Parameters(NodeParameters): - qubits: list[str] = [] + qubits: list[str] = Field(default_factory=list) req_str_param: str int_param: int = 1 float_param: float = 2.0