Skip to content

Commit

Permalink
Replay stored fields into the Case class on controller initialisation #…
Browse files Browse the repository at this point in the history
  • Loading branch information
iamleeg committed Jul 18, 2022
1 parent 47d1725 commit 2a87d98
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 9 deletions.
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

0 comments on commit 2a87d98

Please sign in to comment.