-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #43 from AutoResearch/feat/reorganize-serializers
feature!: allow other serializers and set built-in "pickle" as the default
- Loading branch information
Showing
7 changed files
with
342 additions
and
58 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
import importlib | ||
import logging | ||
import pathlib | ||
from collections import namedtuple | ||
from enum import Enum | ||
from typing import Callable, Dict, Literal, Optional, Tuple, Union | ||
|
||
from autora.state import State | ||
|
||
_logger = logging.getLogger(__name__) | ||
|
||
|
||
class SerializersSupported(str, Enum): | ||
"""Listing of allowed serializers.""" | ||
|
||
pickle = "pickle" | ||
dill = "dill" | ||
yaml = "yaml" | ||
|
||
|
||
_SerializerDef = namedtuple( | ||
"_SerializerDef", ["module", "load", "dump", "dumps", "file_mode"] | ||
) | ||
_serializer_dict: Dict[SerializersSupported, _SerializerDef] = { | ||
SerializersSupported.pickle: _SerializerDef("pickle", "load", "dump", "dumps", "b"), | ||
SerializersSupported.yaml: _SerializerDef( | ||
"autora.serializer._yaml", "load", "dump", "dumps", "" | ||
), | ||
SerializersSupported.dill: _SerializerDef("dill", "load", "dump", "dumps", "b"), | ||
} | ||
|
||
default_serializer = SerializersSupported.pickle | ||
|
||
|
||
def _get_serializer_mode( | ||
serializer: SerializersSupported, interface: Literal["load", "dump", "dumps"] | ||
) -> Tuple[Callable, str]: | ||
serializer_def = _serializer_dict[serializer] | ||
module = serializer_def.module | ||
interface_function_name = getattr(serializer_def, interface) | ||
_logger.debug( | ||
f"_get_serializer_mode: loading {interface_function_name=} from" f" {module=}" | ||
) | ||
module = importlib.import_module(module) | ||
function = getattr(module, interface_function_name) | ||
file_mode = serializer_def.file_mode | ||
return function, file_mode | ||
|
||
|
||
def load_state( | ||
path: Optional[pathlib.Path], | ||
loader: SerializersSupported = default_serializer, | ||
) -> Union[State, None]: | ||
"""Load a State object from a path.""" | ||
if path is not None: | ||
load, file_mode = _get_serializer_mode(loader, "load") | ||
_logger.debug(f"load_state: loading from {path=}") | ||
with open(path, f"r{file_mode}") as f: | ||
state_ = load(f) | ||
else: | ||
_logger.debug(f"load_state: {path=} -> returning None") | ||
state_ = None | ||
return state_ | ||
|
||
|
||
def dump_state( | ||
state_: State, | ||
path: Optional[pathlib.Path], | ||
dumper: SerializersSupported = default_serializer, | ||
) -> None: | ||
"""Write a State object to a path.""" | ||
if path is not None: | ||
dump, file_mode = _get_serializer_mode(dumper, "dump") | ||
_logger.debug(f"dump_state: dumping to {path=}") | ||
path.parent.mkdir(parents=True, exist_ok=True) | ||
with open(path, f"w{file_mode}") as f: | ||
dump(state_, f) | ||
else: | ||
dumps, _ = _get_serializer_mode(dumper, "dumps") | ||
_logger.debug(f"dump_state: {path=} so writing to stdout") | ||
print(dumps(state_)) | ||
return |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,24 @@ | ||
import pathlib | ||
import tempfile | ||
import uuid | ||
|
||
from hypothesis import Verbosity, given, settings | ||
from hypothesis import strategies as st | ||
|
||
from autora.serializer import SerializersSupported, dump_state, load_state | ||
from autora.state import StandardState | ||
|
||
|
||
@given( | ||
st.builds(StandardState, st.text(), st.text(), st.text(), st.lists(st.integers())), | ||
st.sampled_from(SerializersSupported), | ||
) | ||
@settings(verbosity=Verbosity.verbose) | ||
def test_load_inverts_dump(s, serializer): | ||
"""Test that each serializer can be used to serialize and deserialize a state object.""" | ||
with tempfile.TemporaryDirectory() as dir: | ||
path = pathlib.Path(dir, f"{str(uuid.uuid4())}") | ||
print(path, s) | ||
|
||
dump_state(s, path, dumper=serializer) | ||
assert load_state(path, loader=serializer) == s |
Oops, something went wrong.