def test_recovery(tmp_path) -> None: ''' Test `recover`. ''' path = tmp_path / 'artifact' path.mkdir() assert type(recover(Artifact, path)) is DynamicArtifact assert type(recover(DynamicArtifact, path)) is DynamicArtifact assert recover(Artifact, path)._path_ == path assert recover(Artifact, path)._mode_ == 'read-sync' assert recover(Artifact, path, 'write')._mode_ == 'write'
def test_access_modes() -> None: ''' Test using artifacts in "read-sync", "read-async", and "write" mode. ''' def log(artifact: Artifact, event: str) -> None: meta_path = artifact / '_meta_.json' meta = (json.loads(meta_path.read_text()) if meta_path.exists() else { 'events': [] }) meta['events'].append({'type': event}) meta_path.write_text(json.dumps(meta)) with TemporaryDirectory() as root: Path(root, 'rs').mkdir() Path(root, 'ra').mkdir() Path(root, 'w').mkdir() rs_artifact = recover(Artifact, f'{root}/rs', 'write') ra_artifact = recover(Artifact, f'{root}/ra', 'write') w_artifact = recover(Artifact, f'{root}/w', 'write') log(rs_artifact, 'Start') rs_artifact.x = 1 log(rs_artifact, 'Success') rs_artifact._mode_ = 'read-sync' assert rs_artifact.x == 1 with pytest.raises(AttributeError): rs_artifact.y log(ra_artifact, 'Start') ra_artifact.x = 2 ra_artifact._mode_ = 'read-async' assert ra_artifact.x == 2 log(ra_artifact, 'Success') with pytest.raises(AttributeError): ra_artifact.y log(w_artifact, 'Start') w_artifact.x = 3 assert w_artifact.x == 3 assert isinstance(w_artifact.y, ProxyArtifactField)
def test_proxy_fields() -> None: ''' Test the `ProxyArtifactField` class. ''' with TemporaryDirectory() as root: artifact = recover(Artifact, root, 'write') assert isinstance(artifact.a, ProxyArtifactField) a_proxy = artifact.a artifact.a.b = 12 assert artifact.a.b == 12 del a_proxy.b assert public_attrs(artifact.a) == [] artifact.x.append(10) assert artifact.x == [10] artifact.y.z.extend([2, 4, 6]) assert artifact.y.z == [2, 4, 6]
def test_file_operations(ops: List[FileOperation]) -> None: ''' Test reading, writing, and deleting binary files. ''' with TemporaryDirectory() as root: Path(root, 'artifact').mkdir() Path(root, 'raw_path').mkdir() artifact = recover(Artifact, Path(root, 'artifact'), 'write') raw_path = Path(root, 'raw_path') for op in ops: op(raw_path, artifact) for entry in raw_path.iterdir(): assert hasattr(artifact, entry.stem) assert entry.stem in dir(artifact) for key in public_attrs(artifact): entry = getattr(artifact, key) target = raw_path / (key + entry.suffix) assert (entry.read_bytes() == target.read_bytes())
def test_dynamic_artifacts() -> None: ''' Test the `DynamicArtifact` class. ''' with TemporaryDirectory() as root: artifact = recover(DynamicArtifact[Any], root, 'write') assert list(artifact) == [] artifact['a'] = 0.1 assert 'a' in artifact assert len(artifact) == 1 assert list(artifact) == ['a'] assert artifact['a'] == 0.1 del artifact['a'] assert 'a' not in artifact assert len(artifact) == 0 assert list(artifact) == [] artifact['b'] = 'bee' assert 'b' in artifact assert len(artifact) == 1 assert list(artifact) == ['b'] assert artifact['b'] == 'bee'