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

Replay stored fields into the Case class on controller initialisation… #2758

Merged
merged 1 commit into from
Jul 18, 2022
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
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,16 @@ class SchemaController:

def __init__(self, store):
self.store = store
self.restore_saved_fields()

def add_field(self, name: str, type_name: str, description: str):
def restore_saved_fields(self) -> None:
"""Find previously-created fields in the store and apply them."""
for field in self.store.get_case_fields():
self.add_field(field.key, field.type, field.data_dictionary_text, False)

def add_field(
self, name: str, type_name: str, description: str, store_field: bool = True
):
global Case
"""Add a field of the specified type to the Case class. There cannot
already be a field of that name, either built in, as part of the
Expand All @@ -20,7 +28,10 @@ def add_field(self, name: str, type_name: str, description: str):
Additionally dataclasses imposes other conditions (for example names
cannot be Python keywords).

The description will be used in the data dictionary."""
The description will be used in the data dictionary.

Fields will by default be added to the store. Set store_field to False if this is not
necessary, for example if the field to be added is coming from the store."""
existing_fields = dataclasses.fields(Case)
if name in [f.name for f in existing_fields]:
raise ConflictError(f"field {name} already exists")
Expand All @@ -33,7 +44,8 @@ def add_field(self, name: str, type_name: str, description: str):
fields_list.append((name, type, dataclasses.field(init=False, default=None)))
# re-invent the Case class
Case = make_custom_case_class("Case", fields_list)
# create a storable model of the field and store it
# FIXME rewrite the validation logic above to use the data model
field_model = Field(name, type_name, description)
self.store.add_field(field_model)
if store_field:
# create a storable model of the field and store it
# FIXME rewrite the validation logic above to use the data model
field_model = Field(name, type_name, description)
self.store.add_field(field_model)
Original file line number Diff line number Diff line change
Expand Up @@ -228,6 +228,12 @@ def case_exclusion_to_bson_compatible_dict(exclusion: CaseExclusionMetadata):
def add_field(self, field: Field):
self.get_schema_collection().insert_one(field.to_dict())

def get_case_fields(self):
return [
Field(doc["key"], doc["type"], doc["data_dictionary_text"])
for doc in self.get_schema_collection().find({})
]


def date_to_datetime(dt: datetime.date) -> datetime.datetime:
"""Convert datetime.date to datetime.datetime for encoding as BSON"""
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import datetime
import pytest

from data_service.controller.schema_controller import SchemaController
Expand All @@ -23,11 +24,16 @@ def case_observer(case_class: type) -> None:


@pytest.fixture
def schema_controller():
store = MemoryStore()
def observing_case_changes():
observe_case_class(case_observer)
yield SchemaController(store)
yield
remove_case_class_observer(case_observer)


@pytest.fixture
def schema_controller(observing_case_changes):
store = MemoryStore()
yield SchemaController(store)
reset_custom_case_fields()


Expand Down Expand Up @@ -70,3 +76,14 @@ def test_added_field_gets_stored(schema_controller):
assert (
field.data_dictionary_text == "A string that describes some feature of a case."
)


def test_stored_field_gets_added(observing_case_changes):
store_with_preexisting_field = MemoryStore()
a_field = Field(
"outcome_date", Field.DATE, "The date on which the case reached an outcome."
)
store_with_preexisting_field.add_field(a_field)
controller = SchemaController(store_with_preexisting_field)
assert "outcome_date" in Case.field_names()
assert Case.field_type("outcome_date") is datetime.date