def test_experiment_tags(self, tmpdir): """Test that the tags context manager is working as designed by adding tags to the experiment when inside the corresponding with statement.""" exp = Experiment(directory=tmpdir, state_class=ExperimentState) assert not exp.tags with exp.tag("test_tag"): assert exp.tags == ["test_tag"] assert not exp.tags with exp.tag("test_tag"): with exp.tag("second_tag"): assert exp.tags == ["test_tag", "second_tag"] assert exp.tags == ["test_tag"]
def test_save_hooks(self, tmpdir): """Test that save pre- and post-hooks are working correctly. Note: this should be done with the property `c` which is part of the NONHASHED_ATTRIBUTES. If we modified `a` or `B`, the hash would change because they contribute to its value, and restoring would fail because no corresponding state is found on disk. See below for test of that behavior. """ from types import MethodType exp = Experiment(directory=tmpdir, state_class=EmptyState) s = EmptyState(experiment_object=exp) # Set c to 5 to begin with s.c = 5 def change_c(self, value): self.c = value s.change_c = MethodType(change_c, s) # Before saving, set c to 6 s.save_pre_hooks = [lambda: s.change_c(6)] # After saving, set c to 7 s.save_post_hooks = [lambda: s.change_c(7)] s.save() # We are after saving, so c should be 7 assert s.c == 7 # Deflate and reload the state from disk. The saved version of the # state should have the value of c that was set before saving, i.e. 6 s.deflate() s.restore() assert s.c == 6
def test_state_lazy_load(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) s = EmptyState(experiment_object=exp) exp.root = s s.save() # Generate a new child state from state `s` r = EmptyState.new_state(s) r.save() exp.save() # Reload the two-state experiment # By default, slim=True exp = Experiment.restore(directory=tmpdir) for node, state in exp.graph.node_map.items(): assert state.slim_loaded # deflated with state.lazy_load(): assert not state.slim_loaded # fully loaded assert state.slim_loaded # deflated # Check behavior change as slim is set to False when exp is restored exp = Experiment.restore(directory=tmpdir, slim=False) for node, state in exp.graph.node_map.items(): assert not state.slim_loaded # deflated with state.lazy_load(): assert not state.slim_loaded # fully loaded # Note: lazy_load deflates the state even if it was initially # fully loaded! assert state.slim_loaded # deflated
def test_spawn_new_tree(self, tmpdir): """ """ exp = Experiment(directory=tmpdir, state_class=EmptyState) # The argument 'c' should be ignored, as it is not set from thew # constructor in spawn_new_tree exp_args = {"a": "first", "B": "second", "c": "shouldnotpropagate"} root = exp.spawn_new_tree(**exp_args) assert type(root) == ExperimentStatePromise root_state = root.get() assert exp.root is root_state assert isinstance(root_state, EmptyState) assert root_state.a == exp_args["a"] assert root_state.B == exp_args["B"] assert root_state.c is None
def test_state_save(self, tmpdir): """Test that a state created within an experiment inherits the right directory and gets saved in there upon calling the `save` method. This should generate a pickle file with the state and a json file with the state info for slim reloading. """ exp = Experiment(directory=tmpdir, state_class=EmptyState) s = EmptyState(experiment_object=exp) # assign within exp assert s.directory == tmpdir s.save() # save state to disk assert os.path.isfile(os.path.join(tmpdir, s.sha())) assert os.path.isfile(os.path.join(tmpdir, s.sha() + ".slim.json"))
def test_new_state(self, tmpdir): """Generating a new state from a previous one using new_state should generate the right connection between the two states, which can be inspected through the setting of a parent_sha and then in the way the experiment graph is drawn when the StaticExperimentTree is reloaded. """ exp = Experiment(directory=tmpdir, state_class=EmptyState) s = EmptyState(experiment_object=exp) # Set it as the root of the experiment exp.root = s s.save() # Generate a new child state from state `s` r = EmptyState.new_state(s) assert r.parent_sha == s.sha() assert r.experiment_object == exp r.save() exp.save() exp = Experiment.restore(directory=tmpdir) # reload experiment # Test that the graph looks as expected with the connection assert len(exp.graph.nodes) == 2 assert exp.graph.edge_map[s.sha()] == set([r.sha()])
def test_state_sha_save_hook(self, tmpdir): """When restoring fails, it returns False. Check that the save post hook sets the new value correctly, thus modifying the hash value of the state when the property that gets modified is part of PROPERTIES. """ from types import MethodType exp = Experiment(directory=tmpdir, state_class=EmptyState) s = EmptyState(experiment_object=exp) # Set a to 5 to begin with s.a = 5 def change_a(self, value): self.a = value s.change_a = MethodType(change_a, s) # After saving, set a to 7 s.save_post_hooks = [lambda: s.change_a(7)] s.save() s.deflate() assert not s.restore()
def test_state_restore(self, tmpdir): # Create state and assign some properties exp = Experiment(directory=tmpdir, state_class=EmptyState) s = EmptyState(experiment_object=exp) s.a = 5 s.B = "hello" s.c = 12345 # Save it to disk s.save() assert not s.from_cache # Deflate it to remove all properties and put it in "slim" state s.deflate() assert not hasattr(s, "a") assert not hasattr(s, "B") assert not hasattr(s, "c") # Restore it from disk to demonstrate that it was saved correctly and # we are able to recover the properties s.restore() assert s.a == 5 assert s.B == "hello" assert s.c == 12345 assert s.from_cache
def test_spawn_new_tree_error(self, tmpdir): exp = Experiment(directory=tmpdir, state_class=EmptyState) exp_args = {} with pytest.raises(KeyError): exp.spawn_new_tree(**exp_args)
def test_experiment_init(self, tmpdir): """Test that the conditions we expect after the initialization of an Experiment are met.""" exp = Experiment(directory=tmpdir, state_class=ExperimentState) assert os.path.isdir(tmpdir) assert exp.root is None