Skip to content

Commit

Permalink
pep8 #2714
Browse files Browse the repository at this point in the history
  • Loading branch information
iamleeg committed Jun 28, 2022
1 parent 4b54a78 commit 4d2dd96
Show file tree
Hide file tree
Showing 7 changed files with 92 additions and 59 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ def batch_upsert(self, body: dict):
number updated, and any validation errors encountered."""
if body is None:
return "", 415
cases = body.get('cases')
cases = body.get("cases")
if cases is None:
return "", 400
if len(cases) == 0:
Expand All @@ -109,11 +109,7 @@ def batch_upsert(self, body: dict):
errors[str(i)] = e.args[0]
(created, updated) = self.store.batch_upsert(usable_cases)
status = 200 if len(errors) == 0 else 207
response = {
'numCreated': created,
'numUpdated': updated,
'errors': errors
}
response = {"numCreated": created, "numUpdated": updated, "errors": errors}
return jsonify(response), status

def create_anonymised_case_if_valid(self, maybe_case: dict):
Expand All @@ -134,8 +130,13 @@ def check_case_preconditions(self, case: Case):
def anonymise_case(case: Case):
"""Ensure that a stable one-way hash of the source entry ID is stored, and
not the source entry ID itself."""
if case.caseReference is not None and case.caseReference.sourceEntryId is not None:
case.caseReference.sourceEntryId = sha256(case.caseReference.sourceEntryId.encode('utf-8')).hexdigest()
if (
case.caseReference is not None
and case.caseReference.sourceEntryId is not None
):
case.caseReference.sourceEntryId = sha256(
case.caseReference.sourceEntryId.encode("utf-8")
).hexdigest()

@staticmethod
def parse_filter(filter: str) -> Filter:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,11 @@ def list_cases():
return case_controller.create_case(potential_case, num_cases=count)


@app.route("/api/cases/batchUpsert", methods = ['POST'])
@app.route("/api/cases/batchUpsert", methods=["POST"])
def batch_upsert_cases():
return case_controller.batch_upsert(request.get_json())


def set_up_controllers():
global case_controller
store_options = {"mongodb": MongoStore.setup}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

from reusable_data_service.model.case_reference import CaseReference


@dataclasses.dataclass()
class DayZeroCase:
"""This class implements the "day-zero" data schema for Global.health.
Expand Down Expand Up @@ -49,9 +50,11 @@ def from_dict(cls, dictionary: dict[str, Any]) -> type:
).date()
else:
raise ValueError(f"Cannot interpret date {maybe_date}")
elif key == 'caseReference':
elif key == "caseReference":
caseRef = dictionary[key]
value = CaseReference.from_dict(caseRef) if caseRef is not None else None
value = (
CaseReference.from_dict(caseRef) if caseRef is not None else None
)
else:
value = dictionary[key]
setattr(case, key, value)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import bson
import dataclasses


@dataclasses.dataclass
class CaseReference:
"""Represents information about the source of a given case."""

_: dataclasses.KW_ONLY
sourceId: bson.ObjectId = dataclasses.field(init=False, default=None)
sourceEntryId: str = dataclasses.field(init=False, default=None)
Expand All @@ -12,14 +14,14 @@ class CaseReference:
def from_dict(d: dict[str, str]):
"""Create a CaseReference from a dictionary representation."""
ref = CaseReference()
if 'sourceId' in d:
theId = d['sourceId']
if "sourceId" in d:
theId = d["sourceId"]
if isinstance(theId, str):
ref.sourceId = bson.ObjectId(theId)
elif '$oid' in theId:
ref.sourceId = bson.ObjectId(theId['$oid'])
elif "$oid" in theId:
ref.sourceId = bson.ObjectId(theId["$oid"])
else:
raise ValueError(f"Cannot interpret {theId} as an ObjectId")
if 'sourceEntryId' in d:
ref.sourceEntryId = d['sourceEntryId']
if "sourceEntryId" in d:
ref.sourceEntryId = d["sourceEntryId"]
return ref
76 changes: 45 additions & 31 deletions data-serving/reusable-data-service/tests/test_case_controller.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def fetch_cases(self, page: int, limit: int, *args):

def count_cases(self, *args):
return len(self.cases)

def batch_upsert(self, cases: List[Case]):
"""For testing the case controller, a trivial implementation. Look to
tests of the stores and integration tests for richer expressions of
Expand Down Expand Up @@ -184,60 +184,74 @@ def test_batch_upsert_with_no_case_list_returns_400(case_controller):


def test_batch_upsert_with_empty_case_list_returns_400(case_controller):
(response, status) = case_controller.batch_upsert({ 'cases': [] })
(response, status) = case_controller.batch_upsert({"cases": []})
assert status == 400


def test_batch_upsert_creates_valid_case(case_controller):
with open("./tests/data/case.minimal.json", "r") as minimal_file:
minimal_case_description = json.loads(minimal_file.read())
case_controller.store.upsert_create_count = 1 # store should create this case
(response, status) = case_controller.batch_upsert({ 'cases': [minimal_case_description] })
case_controller.store.upsert_create_count = 1 # store should create this case
(response, status) = case_controller.batch_upsert(
{"cases": [minimal_case_description]}
)
assert status == 200
assert case_controller.store.count_cases() == 1
assert response.json['numCreated'] == 1
assert response.json['numUpdated'] == 0
assert response.json['errors'] == {}
assert response.json["numCreated"] == 1
assert response.json["numUpdated"] == 0
assert response.json["errors"] == {}


def test_batch_upsert_updates_valid_case(case_controller):
with open("./tests/data/case.minimal.json", "r") as minimal_file:
minimal_case_description = json.loads(minimal_file.read())
case_controller.store.upsert_create_count = 0 # store should update this case
(response, status) = case_controller.batch_upsert({ 'cases': [minimal_case_description] })
case_controller.store.upsert_create_count = 0 # store should update this case
(response, status) = case_controller.batch_upsert(
{"cases": [minimal_case_description]}
)
assert status == 200
assert response.json['numCreated'] == 0
assert response.json['numUpdated'] == 1
assert response.json['errors'] == {}
assert response.json["numCreated"] == 0
assert response.json["numUpdated"] == 1
assert response.json["errors"] == {}


def test_batch_upsert_reports_both_updates_and_inserts(case_controller):
with open("./tests/data/case.minimal.json", "r") as minimal_file:
minimal_case_description = json.loads(minimal_file.read())
case_controller.store.upsert_create_count = 1 # store should create one, update other
(response, status) = case_controller.batch_upsert({ 'cases': [minimal_case_description, minimal_case_description] })
case_controller.store.upsert_create_count = (
1 # store should create one, update other
)
(response, status) = case_controller.batch_upsert(
{"cases": [minimal_case_description, minimal_case_description]}
)
assert status == 200
assert response.json['numCreated'] == 1
assert response.json['numUpdated'] == 1
assert response.json['errors'] == {}
assert response.json["numCreated"] == 1
assert response.json["numUpdated"] == 1
assert response.json["errors"] == {}


def test_batch_upsert_reports_errors(case_controller):
case_controller.store.upsert_create_count = 0 # store won't have anything to do in this test anyway
(response, status) = case_controller.batch_upsert({ 'cases': [{}] })
case_controller.store.upsert_create_count = (
0 # store won't have anything to do in this test anyway
)
(response, status) = case_controller.batch_upsert({"cases": [{}]})
assert status == 207
assert response.json['numCreated'] == 0
assert response.json['numUpdated'] == 0
assert response.json['errors'] == {
'0': 'Confirmation Date is mandatory'
}
assert response.json["numCreated"] == 0
assert response.json["numUpdated"] == 0
assert response.json["errors"] == {"0": "Confirmation Date is mandatory"}


def test_batch_upsert_hides_original_source_entry_id(case_controller):
case_controller.store.upsert_create_count = 1 # create the case so we can read it later
case_controller.store.upsert_create_count = (
1 # create the case so we can read it later
)
with open("./tests/data/case.minimal.json", "r") as minimal_file:
case = json.loads(minimal_file.read())
case['caseReference'] = {
'sourceId': '12345678901234567890abcd',
'sourceEntryId': 'foo',
case["caseReference"] = {
"sourceId": "12345678901234567890abcd",
"sourceEntryId": "foo",
}
(response, status) = case_controller.batch_upsert({ 'cases': [case] })
(response, status) = case_controller.batch_upsert({"cases": [case]})
assert status == 200
retrieved_case = case_controller.store.case_by_id('1')
assert retrieved_case.caseReference.sourceEntryId != 'foo'
retrieved_case = case_controller.store.case_by_id("1")
assert retrieved_case.caseReference.sourceEntryId != "foo"
24 changes: 15 additions & 9 deletions data-serving/reusable-data-service/tests/test_case_end_to_end.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,16 +186,22 @@ def test_post_case_validate_only(client_with_patched_mongo):
assert get_response.status_code == 200
assert len(get_response.json["cases"]) == 0


def test_batch_upsert_case(client_with_patched_mongo):
post_response = client_with_patched_mongo.post("/api/cases/batchUpsert", json = {
"cases": [{
"confirmation_date": "2022-01-23T13:45:01.234Z",
"caseReference": {
"sourceId": "abcd12345678901234567890",
"sourceEntryId": "a secret",
}
}]
})
post_response = client_with_patched_mongo.post(
"/api/cases/batchUpsert",
json={
"cases": [
{
"confirmation_date": "2022-01-23T13:45:01.234Z",
"caseReference": {
"sourceId": "abcd12345678901234567890",
"sourceEntryId": "a secret",
},
}
]
},
)
assert post_response.status_code == 200
assert post_response.json["errors"] == {}
# mongomock doesn't correctly track upserts for creation/replacement, so can't test numCreated/numUpdated
Expand Down
10 changes: 8 additions & 2 deletions data-serving/reusable-data-service/tests/test_mongo_store.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
from reusable_data_service.model.filter import Anything
from reusable_data_service.stores.mongo_store import MongoStore


@pytest.fixture
def mongo_store(monkeypatch):
db = mongomock.MongoClient()
Expand All @@ -17,28 +18,32 @@ def fake_mongo(connection_string):
return db

monkeypatch.setattr("pymongo.MongoClient", fake_mongo)
store = MongoStore('mongodb://localhost:27017/outbreak', 'outbreak', 'cases')
store = MongoStore("mongodb://localhost:27017/outbreak", "outbreak", "cases")
yield store


"""
Note that mongomock gets the inserted and updated counts of bulk write actions incorrect
(it seems to always consider ReplaceOne operations as updates, even if they insert).
So these tests don't read those values, they test the state of the database.
"""


def test_store_inserts_case_with_no_case_reference(mongo_store):
with open("./tests/data/case.minimal.json", "r") as minimal_file:
case = Case.from_json(minimal_file.read())
(created, updated) = mongo_store.batch_upsert([case])
assert mongo_store.count_cases(Anything()) == 1


def test_store_inserts_case_with_empty_case_reference(mongo_store):
with open("./tests/data/case.minimal.json", "r") as minimal_file:
case = Case.from_json(minimal_file.read())
case.caseReference = CaseReference()
(created, updated) = mongo_store.batch_upsert([case])
assert mongo_store.count_cases(Anything()) == 1


def test_store_inserts_case_with_populated_case_reference(mongo_store):
with open("./tests/data/case.minimal.json", "r") as minimal_file:
case = Case.from_json(minimal_file.read())
Expand All @@ -49,6 +54,7 @@ def test_store_inserts_case_with_populated_case_reference(mongo_store):
(created, updated) = mongo_store.batch_upsert([case])
assert mongo_store.count_cases(Anything()) == 1


def test_store_updates_case_with_known_case_reference(mongo_store):
with open("./tests/data/case.minimal.json", "r") as minimal_file:
case = Case.from_json(minimal_file.read())
Expand All @@ -57,6 +63,6 @@ def test_store_updates_case_with_known_case_reference(mongo_store):
caseReference.sourceEntryId = "1234"
case.caseReference = caseReference
mongo_store.insert_case(case)
case.confirmation_date = date(2022,1,13)
case.confirmation_date = date(2022, 1, 13)
(created, updated) = mongo_store.batch_upsert([case])
assert mongo_store.count_cases(Anything()) == 1

0 comments on commit 4d2dd96

Please sign in to comment.