Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed JobStore.from_dict_spec so that the original dict_spec is not modified #331

Merged
merged 2 commits into from
Jun 8, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 14 additions & 5 deletions src/jobflow/core/store.py
Original file line number Diff line number Diff line change
Expand Up @@ -672,12 +672,21 @@ def all_subclasses(cl):


def _construct_store(spec_dict, valid_stores):
"""Parse the dict containing {"type": <StoreType>} recursively."""
store_type = spec_dict.pop("type")
for k, v in spec_dict.items():
"""Parse the dict containing {"type": <StoreType>} recursively.

Note: the spec is copied so that if this is used programmatically, the type
is not removed from the original spec_dict, which may be used afterwards,
(e.g. stored in a database), or if there is some validation by a pydantic
schema.
This does not occur when using jobflow's standard loading of a config file
as it is only called once.
"""
_spec_dict = dict(spec_dict)
store_type = _spec_dict.pop("type")
for k, v in _spec_dict.items():
if isinstance(v, dict) and "type" in v:
spec_dict[k] = _construct_store(v, valid_stores)
return valid_stores[store_type](**spec_dict)
_spec_dict[k] = _construct_store(v, valid_stores)
return valid_stores[store_type](**_spec_dict)


def _prepare_load(
Expand Down
39 changes: 39 additions & 0 deletions tests/core/test_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -434,6 +434,45 @@ def test_from_db_file(test_data):
JobStore.from_file(test_data / "db_bad.yaml")


def test_from_dict_spec():
from jobflow import JobStore

dict_spec = {
"docs_store": {
"type": "MongoStore",
"database": "jobflow_unittest",
"collection_name": "outputs",
"host": "localhost",
"port": 27017,
}
}
JobStore.from_dict_spec(dict_spec)
assert "type" in dict_spec["docs_store"]
dict_spec = {
"docs_store": {
"type": "MongoStore",
"database": "jobflow_unittest",
"collection_name": "outputs",
"host": "localhost",
"port": 27017,
},
"additional_stores": {
"data": {
"type": "GridFSStore",
"database": "jobflow_unittest",
"collection_name": "outputs_blobs",
"host": "localhost",
"port": 27017,
}
},
}
JobStore.from_dict_spec(dict_spec)
assert "type" in dict_spec["docs_store"]
assert dict_spec["docs_store"]["type"] == "MongoStore"
assert "type" in dict_spec["additional_stores"]["data"]
assert dict_spec["additional_stores"]["data"]["type"] == "GridFSStore"


def test_ensure_index(memory_jobstore):
assert memory_jobstore.ensure_index("test_key")
# TODO: How to check for exception?