From 2817bdd91aed3376231e0abe09952f0ea9f6f259 Mon Sep 17 00:00:00 2001 From: Michela Iannaccone Date: Wed, 21 Feb 2024 12:04:27 -0500 Subject: [PATCH 1/6] create assesscommand and fix up tests --- canvas_sdk/commands/__init__.py | 3 +- canvas_sdk/commands/assess/assess.py | 21 ++++ canvas_sdk/commands/assess/constants.py | 9 ++ canvas_sdk/commands/plan/__init__.py | 0 canvas_sdk/commands/plan/tests.py | 137 ------------------------ canvas_sdk/commands/tests.py | 126 ++++++++++++++++++++++ 6 files changed, 158 insertions(+), 138 deletions(-) create mode 100644 canvas_sdk/commands/assess/assess.py create mode 100644 canvas_sdk/commands/assess/constants.py delete mode 100644 canvas_sdk/commands/plan/__init__.py delete mode 100644 canvas_sdk/commands/plan/tests.py create mode 100644 canvas_sdk/commands/tests.py diff --git a/canvas_sdk/commands/__init__.py b/canvas_sdk/commands/__init__.py index f620ef46..4ed01ab4 100644 --- a/canvas_sdk/commands/__init__.py +++ b/canvas_sdk/commands/__init__.py @@ -1,3 +1,4 @@ +from canvas_sdk.commands.assess.assess import AssessCommand from canvas_sdk.commands.plan.plan import PlanCommand -__all__ = ("PlanCommand",) +__all__ = ("PlanCommand", "AssessCommand") diff --git a/canvas_sdk/commands/assess/assess.py b/canvas_sdk/commands/assess/assess.py new file mode 100644 index 00000000..c25a26eb --- /dev/null +++ b/canvas_sdk/commands/assess/assess.py @@ -0,0 +1,21 @@ +from canvas_sdk.commands.assess.constants import AssessStatus +from canvas_sdk.commands.base import _BaseCommand + + +class AssessCommand(_BaseCommand): + """A class for managing an Assess command within a specific note.""" + + condition_id: int | None = None + background: str | None = None + status: AssessStatus | None = None + narrative: str | None = None + + @property + def values(self) -> dict: + """The Assess command's field values.""" + return { + "condition_id": self.condition_id, + "background": self.background, + "status": self.status.value if self.status else None, + "narrative": self.narrative, + } diff --git a/canvas_sdk/commands/assess/constants.py b/canvas_sdk/commands/assess/constants.py new file mode 100644 index 00000000..4b9ae026 --- /dev/null +++ b/canvas_sdk/commands/assess/constants.py @@ -0,0 +1,9 @@ +from enum import Enum + + +class AssessStatus(Enum): + """Enum class for Assess status field.""" + + IMPROVED = "improved" + STABLE = "stable" + DETERIORATED = "deteriorated" diff --git a/canvas_sdk/commands/plan/__init__.py b/canvas_sdk/commands/plan/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/canvas_sdk/commands/plan/tests.py b/canvas_sdk/commands/plan/tests.py deleted file mode 100644 index 8480dd2e..00000000 --- a/canvas_sdk/commands/plan/tests.py +++ /dev/null @@ -1,137 +0,0 @@ -import pytest -from pydantic import ValidationError - -from canvas_sdk.commands import PlanCommand - - -def test_plan_command_init_raises_error_without_user_id() -> None: - with pytest.raises(ValidationError) as e: - PlanCommand() - assert ( - "1 validation error for PlanCommand\nuser_id\n Field required [type=missing, input_value={}, input_type=dict]" - in repr(e.value) - ) - - -def test_plan_command_init_sets_all_kwargs_with_correct_type() -> None: - p = PlanCommand(user_id=1, note_id=100, command_uuid="123", narrative="hello in there") - assert p.__dict__ == { - "user_id": 1, - "note_id": 100, - "command_uuid": "123", - "narrative": "hello in there", - } - - -def test_plan_command_init_sets_all_kwargs_with_correct_none_type() -> None: - p = PlanCommand(user_id=1) - assert p.__dict__ == { - "user_id": 1, - "note_id": None, - "command_uuid": None, - "narrative": None, - } - - -def test_plan_command_raises_error_when_wrong_type_is_set_on_user_id() -> None: - with pytest.raises(ValidationError) as e: - PlanCommand(user_id="1", note_id=100, command_uuid="123", narrative="hello in there") - assert ( - "1 validation error for PlanCommand\nuser_id\n Input should be a valid integer [type=int_type, input_value='1', input_type=str]" - in repr(e.value) - ) - - -def test_plan_command_raises_error_when_wrong_type_is_set_on_note_id() -> None: - with pytest.raises(ValidationError) as e: - PlanCommand(user_id=1, note_id="100", command_uuid="123", narrative="hello in there") - assert ( - "1 validation error for PlanCommand\nnote_id\n Input should be a valid integer [type=int_type, input_value='100', input_type=str]" - in repr(e.value) - ) - - -def test_plan_command_raises_error_when_wrong_type_is_set_on_command_uuid() -> None: - with pytest.raises(ValidationError) as e: - PlanCommand(user_id=1, note_id=100, command_uuid=123, narrative="hello in there") - assert ( - "1 validation error for PlanCommand\ncommand_uuid\n Input should be a valid string [type=string_type, input_value=123, input_type=int]" - in repr(e.value) - ) - - -def test_plan_command_raises_error_when_wrong_type_is_set_on_narrative() -> None: - with pytest.raises(ValidationError) as e: - PlanCommand(user_id=1, note_id=100, command_uuid="123", narrative=143) - assert ( - "1 validation error for PlanCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=143, input_type=int]" - in repr(e.value) - ) - - -def test_plan_command_only_allows_defined_type_to_be_set_on_user_id() -> None: - p = PlanCommand(user_id=1) - with pytest.raises(ValidationError) as e1: - p.user_id = "1" - assert ( - "1 validation error for PlanCommand\nuser_id\n Input should be a valid integer [type=int_type, input_value='1', input_type=str]" - in repr(e1.value) - ) - - with pytest.raises(ValidationError) as e2: - p.user_id = None - assert ( - "1 validation error for PlanCommand\nuser_id\n Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]" - in repr(e2.value) - ) - - p.user_id = 100 - assert p.user_id == 100 - - -def test_plan_command_only_allows_defined_type_to_be_set_on_note_id() -> None: - p = PlanCommand(user_id=1) - with pytest.raises(ValidationError) as e: - p.note_id = "1" - assert ( - "1 validation error for PlanCommand\nnote_id\n Input should be a valid integer [type=int_type, input_value='1', input_type=str]" - in repr(e.value) - ) - - p.note_id = 100 - assert p.note_id == 100 - - p.note_id = None - assert p.note_id is None - - -def test_plan_command_only_allows_defined_type_to_be_set_on_command_uuid() -> None: - p = PlanCommand(user_id=1) - with pytest.raises(ValidationError) as e: - p.command_uuid = 1 - assert ( - "1 validation error for PlanCommand\ncommand_uuid\n Input should be a valid string [type=string_type, input_value=1, input_type=int]" - in repr(e.value) - ) - - p.command_uuid = "100" - assert p.command_uuid == "100" - - p.command_uuid = None - assert p.command_uuid is None - - -def test_plan_command_only_allows_defined_type_to_be_set_on_narrative() -> None: - p = PlanCommand(user_id=1) - with pytest.raises(ValidationError) as e: - p.narrative = 1 - assert ( - "1 validation error for PlanCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=1, input_type=int]" - in repr(e.value) - ) - - p.narrative = "yeah" - assert p.narrative == "yeah" - - p.narrative = None - assert p.narrative is None diff --git a/canvas_sdk/commands/tests.py b/canvas_sdk/commands/tests.py new file mode 100644 index 00000000..4931bd65 --- /dev/null +++ b/canvas_sdk/commands/tests.py @@ -0,0 +1,126 @@ +import pytest +from pydantic import ValidationError + +from canvas_sdk.commands import AssessCommand, PlanCommand +from canvas_sdk.commands.assess.assess import AssessStatus + + +@pytest.mark.parametrize( + "Command,err_kwargs,err_msg", + [ + ( + PlanCommand, + {}, + "1 validation error for PlanCommand\nuser_id\n Field required [type=missing, input_value={}, input_type=dict]", + ), + ( + PlanCommand, + {"user_id": None}, + "1 validation error for PlanCommand\nuser_id\n Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]", + ), + ( + PlanCommand, + {"user_id": "5"}, + "1 validation error for PlanCommand\nuser_id\n Input should be a valid integer [type=int_type, input_value='5', input_type=str]", + ), + ( + PlanCommand, + {"user_id": 5, "note_id": "100"}, + "1 validation error for PlanCommand\nnote_id\n Input should be a valid integer [type=int_type, input_value='100', input_type=str]", + ), + ( + PlanCommand, + {"user_id": 5, "command_uuid": 100}, + "1 validation error for PlanCommand\ncommand_uuid\n Input should be a valid string [type=string_type, input_value=100, input_type=int]", + ), + ( + PlanCommand, + {"user_id": 5, "narrative": 143}, + "1 validation error for PlanCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=143, input_type=int]", + ), + ( + AssessCommand, + {"user_id": 5, "condition_id": "h"}, + "1 validation error for AssessCommand\ncondition_id\n Input should be a valid integer [type=int_type, input_value='h', input_type=str]", + ), + ( + AssessCommand, + {"user_id": 5, "background": 100}, + "1 validation error for AssessCommand\nbackground\n Input should be a valid string [type=string_type, input_value=100, input_type=int]", + ), + ( + AssessCommand, + {"user_id": 5, "status": "active"}, + "1 validation error for AssessCommand\nstatus\n Input should be an instance of AssessStatus [type=is_instance_of, input_value='active', input_type=str]", + ), + ( + AssessCommand, + {"user_id": 5, "narrative": 1}, + "1 validation error for AssessCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + ), + ], +) +def test_command_raises_error_when_kwarg_given_incorrect_type( + Command: PlanCommand | AssessCommand, err_kwargs: dict, err_msg: str +) -> None: + with pytest.raises(ValidationError) as e1: + Command(**err_kwargs) + assert err_msg in repr(e1.value) + + plan = Command(user_id=1) + if not err_kwargs: + return + key, value = list(err_kwargs.items())[-1] + with pytest.raises(ValidationError) as e2: + setattr(plan, key, value) + assert err_msg in repr(e2.value) + + +@pytest.mark.parametrize( + "Command, test_init_kwarg,test_updated_value", + [ + (PlanCommand, {"user_id": 100}, {"user_id": 7}), + (PlanCommand, {"user_id": 100, "note_id": 200}, {"user_id": 100, "note_id": None}), + ( + PlanCommand, + {"user_id": 100, "command_uuid": "800"}, + {"user_id": 100, "command_uuid": None}, + ), + ( + PlanCommand, + {"user_id": 100, "narrative": "123456"}, + {"user_id": 100, "narrative": None}, + ), + ( + AssessCommand, + {"user_id": 100, "condition_id": 100}, + {"user_id": 100, "condition_id": None}, + ), + ( + AssessCommand, + {"user_id": 100, "background": "abcdefg"}, + {"user_id": 100, "background": None}, + ), + ( + AssessCommand, + {"user_id": 100, "status": AssessStatus.DETERIORATED}, + {"user_id": 100, "status": None}, + ), + ( + AssessCommand, + {"user_id": 100, "narrative": "1234567"}, + {"user_id": 100, "narrative": None}, + ), + ], +) +def test_command_allows_kwarg_with_correct_type( + Command: PlanCommand | AssessCommand, test_init_kwarg: dict, test_updated_value: dict +) -> None: + plan = Command(**test_init_kwarg) + + init_k, init_v = list(test_init_kwarg.items())[-1] + assert getattr(plan, init_k) == init_v + + updated_k, updated_v = list(test_updated_value.items())[-1] + setattr(plan, updated_k, updated_v) + assert getattr(plan, updated_k) == updated_v From 9b5bfb56d72c2b627f080d7e8a1d2f101f2d7d8f Mon Sep 17 00:00:00 2001 From: Michela Iannaccone Date: Wed, 21 Feb 2024 12:48:42 -0500 Subject: [PATCH 2/6] make condition_id required --- canvas_sdk/commands/assess/assess.py | 2 +- canvas_sdk/commands/tests.py | 60 +++++++++++++++++++--------- 2 files changed, 42 insertions(+), 20 deletions(-) diff --git a/canvas_sdk/commands/assess/assess.py b/canvas_sdk/commands/assess/assess.py index c25a26eb..e208b9bf 100644 --- a/canvas_sdk/commands/assess/assess.py +++ b/canvas_sdk/commands/assess/assess.py @@ -5,7 +5,7 @@ class AssessCommand(_BaseCommand): """A class for managing an Assess command within a specific note.""" - condition_id: int | None = None + condition_id: int background: str | None = None status: AssessStatus | None = None narrative: str | None = None diff --git a/canvas_sdk/commands/tests.py b/canvas_sdk/commands/tests.py index 4931bd65..62a71fa1 100644 --- a/canvas_sdk/commands/tests.py +++ b/canvas_sdk/commands/tests.py @@ -6,73 +6,95 @@ @pytest.mark.parametrize( - "Command,err_kwargs,err_msg", + "Command,err_kwargs,err_msg,valid_kwargs", [ ( PlanCommand, {}, "1 validation error for PlanCommand\nuser_id\n Field required [type=missing, input_value={}, input_type=dict]", + {"user_id": 1}, ), ( PlanCommand, {"user_id": None}, "1 validation error for PlanCommand\nuser_id\n Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]", + {"user_id": 1}, ), ( PlanCommand, {"user_id": "5"}, "1 validation error for PlanCommand\nuser_id\n Input should be a valid integer [type=int_type, input_value='5', input_type=str]", + {"user_id": 1}, ), ( PlanCommand, {"user_id": 5, "note_id": "100"}, "1 validation error for PlanCommand\nnote_id\n Input should be a valid integer [type=int_type, input_value='100', input_type=str]", + {"user_id": 1}, ), ( PlanCommand, {"user_id": 5, "command_uuid": 100}, "1 validation error for PlanCommand\ncommand_uuid\n Input should be a valid string [type=string_type, input_value=100, input_type=int]", + {"user_id": 1}, ), ( PlanCommand, {"user_id": 5, "narrative": 143}, "1 validation error for PlanCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=143, input_type=int]", + {"user_id": 1}, + ), + ( + AssessCommand, + {"user_id": 5}, + "1 validation error for AssessCommand\ncondition_id\n Field required [type=missing, input_value={'user_id': 5}, input_type=dict]", + {"user_id": 1, "condition_id": 100}, + ), + ( + AssessCommand, + {"user_id": 5, "condition_id": None}, + "1 validation error for AssessCommand\ncondition_id\n Input should be a valid integer [type=int_type, input_value=None, input_type=NoneType]", + {"user_id": 1, "condition_id": 100}, ), ( AssessCommand, {"user_id": 5, "condition_id": "h"}, "1 validation error for AssessCommand\ncondition_id\n Input should be a valid integer [type=int_type, input_value='h', input_type=str]", + {"user_id": 1, "condition_id": 100}, ), ( AssessCommand, - {"user_id": 5, "background": 100}, + {"user_id": 5, "condition_id": 100, "background": 100}, "1 validation error for AssessCommand\nbackground\n Input should be a valid string [type=string_type, input_value=100, input_type=int]", + {"user_id": 1, "condition_id": 100}, ), ( AssessCommand, - {"user_id": 5, "status": "active"}, + {"user_id": 5, "condition_id": 100, "status": "active"}, "1 validation error for AssessCommand\nstatus\n Input should be an instance of AssessStatus [type=is_instance_of, input_value='active', input_type=str]", + {"user_id": 1, "condition_id": 100}, ), ( AssessCommand, - {"user_id": 5, "narrative": 1}, + {"user_id": 5, "condition_id": 100, "narrative": 1}, "1 validation error for AssessCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 1, "condition_id": 100}, ), ], ) def test_command_raises_error_when_kwarg_given_incorrect_type( - Command: PlanCommand | AssessCommand, err_kwargs: dict, err_msg: str + Command: PlanCommand | AssessCommand, err_kwargs: dict, err_msg: str, valid_kwargs: dict ) -> None: with pytest.raises(ValidationError) as e1: Command(**err_kwargs) assert err_msg in repr(e1.value) - plan = Command(user_id=1) - if not err_kwargs: + cmd = Command(**valid_kwargs) + if len(err_kwargs) < len(valid_kwargs): return key, value = list(err_kwargs.items())[-1] with pytest.raises(ValidationError) as e2: - setattr(plan, key, value) + setattr(cmd, key, value) assert err_msg in repr(e2.value) @@ -94,33 +116,33 @@ def test_command_raises_error_when_kwarg_given_incorrect_type( ( AssessCommand, {"user_id": 100, "condition_id": 100}, - {"user_id": 100, "condition_id": None}, + {"user_id": 100, "condition_id": 9}, ), ( AssessCommand, - {"user_id": 100, "background": "abcdefg"}, - {"user_id": 100, "background": None}, + {"user_id": 100, "condition_id": 100, "background": "abcdefg"}, + {"user_id": 100, "condition_id": 100, "background": None}, ), ( AssessCommand, - {"user_id": 100, "status": AssessStatus.DETERIORATED}, - {"user_id": 100, "status": None}, + {"user_id": 100, "condition_id": 100, "status": AssessStatus.DETERIORATED}, + {"user_id": 100, "condition_id": 100, "status": None}, ), ( AssessCommand, - {"user_id": 100, "narrative": "1234567"}, - {"user_id": 100, "narrative": None}, + {"user_id": 100, "condition_id": 100, "narrative": "1234567"}, + {"user_id": 100, "condition_id": 100, "narrative": None}, ), ], ) def test_command_allows_kwarg_with_correct_type( Command: PlanCommand | AssessCommand, test_init_kwarg: dict, test_updated_value: dict ) -> None: - plan = Command(**test_init_kwarg) + cmd = Command(**test_init_kwarg) init_k, init_v = list(test_init_kwarg.items())[-1] - assert getattr(plan, init_k) == init_v + assert getattr(cmd, init_k) == init_v updated_k, updated_v = list(test_updated_value.items())[-1] - setattr(plan, updated_k, updated_v) - assert getattr(plan, updated_k) == updated_v + setattr(cmd, updated_k, updated_v) + assert getattr(cmd, updated_k) == updated_v From 462870d6b75c12d2c1e11486106da537a3a6b177 Mon Sep 17 00:00:00 2001 From: Michela Iannaccone Date: Wed, 21 Feb 2024 14:37:59 -0500 Subject: [PATCH 3/6] create diagnose command --- canvas_sdk/commands/__init__.py | 3 +- canvas_sdk/commands/assess/assess.py | 1 + canvas_sdk/commands/diagnose/diagnose.py | 27 +++++++++ canvas_sdk/commands/tests.py | 75 +++++++++++++++++++++++- 4 files changed, 102 insertions(+), 4 deletions(-) create mode 100644 canvas_sdk/commands/diagnose/diagnose.py diff --git a/canvas_sdk/commands/__init__.py b/canvas_sdk/commands/__init__.py index 4ed01ab4..7db1c51a 100644 --- a/canvas_sdk/commands/__init__.py +++ b/canvas_sdk/commands/__init__.py @@ -1,4 +1,5 @@ from canvas_sdk.commands.assess.assess import AssessCommand +from canvas_sdk.commands.diagnose.diagnose import DiagnoseCommand from canvas_sdk.commands.plan.plan import PlanCommand -__all__ = ("PlanCommand", "AssessCommand") +__all__ = ("PlanCommand", "AssessCommand", "DiagnoseCommand") diff --git a/canvas_sdk/commands/assess/assess.py b/canvas_sdk/commands/assess/assess.py index e208b9bf..1df1f410 100644 --- a/canvas_sdk/commands/assess/assess.py +++ b/canvas_sdk/commands/assess/assess.py @@ -5,6 +5,7 @@ class AssessCommand(_BaseCommand): """A class for managing an Assess command within a specific note.""" + # how do we make sure that condition_id is a valid condition for the patient? condition_id: int background: str | None = None status: AssessStatus | None = None diff --git a/canvas_sdk/commands/diagnose/diagnose.py b/canvas_sdk/commands/diagnose/diagnose.py new file mode 100644 index 00000000..ed8a3e0c --- /dev/null +++ b/canvas_sdk/commands/diagnose/diagnose.py @@ -0,0 +1,27 @@ +from datetime import datetime + +from canvas_sdk.commands.base import _BaseCommand + + +class DiagnoseCommand(_BaseCommand): + """A class for managing a Diagnose command within a specific note.""" + + # how do we make sure icd10_code is a valid code? + icd10_code: str + background: str | None = None + approximate_date_of_onset: datetime | None = None + today_assessment: str | None = None + + @property + def values(self) -> dict: + """The Diagnose command's field values.""" + return { + "icd10_code": self.icd10_code, + "background": self.background, + "approximate_date_of_onset": ( + self.approximate_date_of_onset.isoformat() + if self.approximate_date_of_onset + else None + ), + "today_assessment": self.today_assessment, + } diff --git a/canvas_sdk/commands/tests.py b/canvas_sdk/commands/tests.py index 62a71fa1..222ba05b 100644 --- a/canvas_sdk/commands/tests.py +++ b/canvas_sdk/commands/tests.py @@ -1,7 +1,9 @@ +from datetime import datetime + import pytest from pydantic import ValidationError -from canvas_sdk.commands import AssessCommand, PlanCommand +from canvas_sdk.commands import AssessCommand, DiagnoseCommand, PlanCommand from canvas_sdk.commands.assess.assess import AssessStatus @@ -80,10 +82,55 @@ "1 validation error for AssessCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", {"user_id": 1, "condition_id": 100}, ), + ( + DiagnoseCommand, + {"user_id": 5}, + "1 validation error for DiagnoseCommand\nicd10_code\n Field required [type=missing, input_value={'user_id': 5}, input_type=dict]", + {"user_id": 1, "icd10_code": "Z00"}, + ), + ( + DiagnoseCommand, + {"user_id": 5, "icd10_code": None}, + "1 validation error for DiagnoseCommand\nicd10_code\n Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]", + {"user_id": 1, "icd10_code": "Z00"}, + ), + ( + DiagnoseCommand, + {"user_id": 5, "icd10_code": 1}, + "1 validation error for DiagnoseCommand\nicd10_code\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 1, "icd10_code": "Z00"}, + ), + ( + DiagnoseCommand, + {"user_id": 5, "icd10_code": "Z00", "background": 1}, + "1 validation error for DiagnoseCommand\nbackground\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 1, "icd10_code": "Z00"}, + ), + ( + DiagnoseCommand, + {"user_id": 5, "icd10_code": "Z00", "approximate_date_of_onset": 1}, + "1 validation error for DiagnoseCommand\napproximate_date_of_onset\n Input should be a valid datetime [type=datetime_type, input_value=1, input_type=int]", + {"user_id": 1, "icd10_code": "Z00"}, + ), + ( + DiagnoseCommand, + {"user_id": 5, "icd10_code": "Z00", "approximate_date_of_onset": "1"}, + "1 validation error for DiagnoseCommand\napproximate_date_of_onset\n Input should be a valid datetime [type=datetime_type, input_value='1', input_type=str]", + {"user_id": 1, "icd10_code": "Z00"}, + ), + ( + DiagnoseCommand, + {"user_id": 5, "icd10_code": "Z00", "today_assessment": 1}, + "1 validation error for DiagnoseCommand\ntoday_assessment\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 1, "icd10_code": "Z00"}, + ), ], ) def test_command_raises_error_when_kwarg_given_incorrect_type( - Command: PlanCommand | AssessCommand, err_kwargs: dict, err_msg: str, valid_kwargs: dict + Command: PlanCommand | AssessCommand | DiagnoseCommand, + err_kwargs: dict, + err_msg: str, + valid_kwargs: dict, ) -> None: with pytest.raises(ValidationError) as e1: Command(**err_kwargs) @@ -133,10 +180,32 @@ def test_command_raises_error_when_kwarg_given_incorrect_type( {"user_id": 100, "condition_id": 100, "narrative": "1234567"}, {"user_id": 100, "condition_id": 100, "narrative": None}, ), + ( + DiagnoseCommand, + {"user_id": 1, "icd10_code": "Z00"}, + {"user_id": 1, "icd10_code": "400"}, + ), + ( + DiagnoseCommand, + {"user_id": 1, "icd10_code": "Z00", "background": "123"}, + {"user_id": 1, "icd10_code": "Z00", "background": None}, + ), + ( + DiagnoseCommand, + {"user_id": 1, "icd10_code": "Z00", "approximate_date_of_onset": datetime.now()}, + {"user_id": 1, "icd10_code": "Z00", "approximate_date_of_onset": None}, + ), + ( + DiagnoseCommand, + {"user_id": 1, "icd10_code": "Z00", "today_assessment": "hi"}, + {"user_id": 1, "icd10_code": "Z00", "today_assessment": None}, + ), ], ) def test_command_allows_kwarg_with_correct_type( - Command: PlanCommand | AssessCommand, test_init_kwarg: dict, test_updated_value: dict + Command: PlanCommand | AssessCommand | DiagnoseCommand, + test_init_kwarg: dict, + test_updated_value: dict, ) -> None: cmd = Command(**test_init_kwarg) From 9bd89e96d45e1363f28df586a49779cb9abcb136 Mon Sep 17 00:00:00 2001 From: Michela Iannaccone Date: Wed, 21 Feb 2024 15:05:36 -0500 Subject: [PATCH 4/6] create goal command --- canvas_sdk/commands/__init__.py | 3 +- canvas_sdk/commands/assess/assess.py | 10 +- canvas_sdk/commands/assess/constants.py | 9 -- canvas_sdk/commands/goal/goal.py | 47 ++++++++++ canvas_sdk/commands/tests.py | 120 ++++++++++++++++++++++-- 5 files changed, 171 insertions(+), 18 deletions(-) delete mode 100644 canvas_sdk/commands/assess/constants.py create mode 100644 canvas_sdk/commands/goal/goal.py diff --git a/canvas_sdk/commands/__init__.py b/canvas_sdk/commands/__init__.py index 7db1c51a..3a370bd2 100644 --- a/canvas_sdk/commands/__init__.py +++ b/canvas_sdk/commands/__init__.py @@ -1,5 +1,6 @@ from canvas_sdk.commands.assess.assess import AssessCommand from canvas_sdk.commands.diagnose.diagnose import DiagnoseCommand +from canvas_sdk.commands.goal.goal import GoalCommand from canvas_sdk.commands.plan.plan import PlanCommand -__all__ = ("PlanCommand", "AssessCommand", "DiagnoseCommand") +__all__ = ("PlanCommand", "AssessCommand", "DiagnoseCommand", "GoalCommand") diff --git a/canvas_sdk/commands/assess/assess.py b/canvas_sdk/commands/assess/assess.py index 1df1f410..9d9ce75b 100644 --- a/canvas_sdk/commands/assess/assess.py +++ b/canvas_sdk/commands/assess/assess.py @@ -1,14 +1,20 @@ -from canvas_sdk.commands.assess.constants import AssessStatus +from enum import Enum + from canvas_sdk.commands.base import _BaseCommand class AssessCommand(_BaseCommand): """A class for managing an Assess command within a specific note.""" + class Status(Enum): + IMPROVED = "improved" + STABLE = "stable" + DETERIORATED = "deteriorated" + # how do we make sure that condition_id is a valid condition for the patient? condition_id: int background: str | None = None - status: AssessStatus | None = None + status: Status | None = None narrative: str | None = None @property diff --git a/canvas_sdk/commands/assess/constants.py b/canvas_sdk/commands/assess/constants.py deleted file mode 100644 index 4b9ae026..00000000 --- a/canvas_sdk/commands/assess/constants.py +++ /dev/null @@ -1,9 +0,0 @@ -from enum import Enum - - -class AssessStatus(Enum): - """Enum class for Assess status field.""" - - IMPROVED = "improved" - STABLE = "stable" - DETERIORATED = "deteriorated" diff --git a/canvas_sdk/commands/goal/goal.py b/canvas_sdk/commands/goal/goal.py new file mode 100644 index 00000000..998e2689 --- /dev/null +++ b/canvas_sdk/commands/goal/goal.py @@ -0,0 +1,47 @@ +from datetime import datetime +from enum import Enum + +from canvas_sdk.commands.base import _BaseCommand + + +class GoalCommand(_BaseCommand): + """A class for managing a Goal command within a specific note.""" + + class Priority(Enum): + HIGH = "high-priority" + MEDIUM = "medium-priority" + LOW = "low-priority" + + class AchievementStatus(Enum): + IN_PROGRESS = "in-progress" + IMPROVING = "improving" + WORSENING = "worsening" + NO_CHANGE = "no-change" + ACHIEVED = "achieved" + SUSTAINING = "sustaining" + NOT_ACHIEVED = "not-achieved" + NO_PROGRESS = "no-progress" + NOT_ATTAINABLE = "not-attainable" + + goal_statement: str + start_date: datetime | None = None + due_date: datetime | None = None + today_assessment: str | None = None + achievement_status: AchievementStatus | None = None + priority: Priority | None = None + progress: str | None = None + + @property + def values(self) -> dict: + """The Goal command's field values.""" + return { + "goal_statement": self.goal_statement, + "start_date": (self.start_date.isoformat() if self.start_date else None), + "due_date": (self.start_date.isoformat() if self.start_date else None), + "today_assessment": self.today_assessment, + "achievement_status": ( + self.achievement_status.value if self.achievement_status else None + ), + "priority": (self.priority.value if self.priority else None), + "progress": self.progress, + } diff --git a/canvas_sdk/commands/tests.py b/canvas_sdk/commands/tests.py index 222ba05b..50fee876 100644 --- a/canvas_sdk/commands/tests.py +++ b/canvas_sdk/commands/tests.py @@ -3,8 +3,7 @@ import pytest from pydantic import ValidationError -from canvas_sdk.commands import AssessCommand, DiagnoseCommand, PlanCommand -from canvas_sdk.commands.assess.assess import AssessStatus +from canvas_sdk.commands import AssessCommand, DiagnoseCommand, GoalCommand, PlanCommand @pytest.mark.parametrize( @@ -73,7 +72,7 @@ ( AssessCommand, {"user_id": 5, "condition_id": 100, "status": "active"}, - "1 validation error for AssessCommand\nstatus\n Input should be an instance of AssessStatus [type=is_instance_of, input_value='active', input_type=str]", + "1 validation error for AssessCommand\nstatus\n Input should be an instance of AssessCommand.Status [type=is_instance_of, input_value='active', input_type=str]", {"user_id": 1, "condition_id": 100}, ), ( @@ -124,10 +123,76 @@ "1 validation error for DiagnoseCommand\ntoday_assessment\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", {"user_id": 1, "icd10_code": "Z00"}, ), + ( + GoalCommand, + {"user_id": 5}, + "1 validation error for GoalCommand\ngoal_statement\n Field required [type=missing, input_value={'user_id': 5}, input_type=dict]", + {"user_id": 5, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": None}, + "1 validation error for GoalCommand\ngoal_statement\n Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]", + {"user_id": 5, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": 1}, + "1 validation error for GoalCommand\ngoal_statement\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 5, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "start_date": 1}, + "1 validation error for GoalCommand\nstart_date\n Input should be a valid datetime [type=datetime_type, input_value=1, input_type=int]", + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "start_date": "1"}, + "1 validation error for GoalCommand\nstart_date\n Input should be a valid datetime [type=datetime_type, input_value='1', input_type=str]", + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "due_date": 1}, + "1 validation error for GoalCommand\ndue_date\n Input should be a valid datetime [type=datetime_type, input_value=1, input_type=int]", + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "due_date": "1"}, + "1 validation error for GoalCommand\ndue_date\n Input should be a valid datetime [type=datetime_type, input_value='1', input_type=str]", + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "today_assessment": 1}, + "1 validation error for GoalCommand\ntoday_assessment\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "achievement_status": "improving"}, + "1 validation error for GoalCommand\nachievement_status\n Input should be an instance of GoalCommand.AchievementStatus [type=is_instance_of, input_value='improving', input_type=str]", + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "priority": "medium-priority"}, + "1 validation error for GoalCommand\npriority\n Input should be an instance of GoalCommand.Priority [type=is_instance_of, input_value='medium-priority', input_type=str]", + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 5, "goal_statement": "do some stuff!", "progress": 1}, + "1 validation error for GoalCommand\nprogress\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 5, "goal_statement": "do some stuff!"}, + ), ], ) def test_command_raises_error_when_kwarg_given_incorrect_type( - Command: PlanCommand | AssessCommand | DiagnoseCommand, + Command: PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand, err_kwargs: dict, err_msg: str, valid_kwargs: dict, @@ -172,7 +237,7 @@ def test_command_raises_error_when_kwarg_given_incorrect_type( ), ( AssessCommand, - {"user_id": 100, "condition_id": 100, "status": AssessStatus.DETERIORATED}, + {"user_id": 100, "condition_id": 100, "status": AssessCommand.Status.DETERIORATED}, {"user_id": 100, "condition_id": 100, "status": None}, ), ( @@ -200,10 +265,53 @@ def test_command_raises_error_when_kwarg_given_incorrect_type( {"user_id": 1, "icd10_code": "Z00", "today_assessment": "hi"}, {"user_id": 1, "icd10_code": "Z00", "today_assessment": None}, ), + ( + GoalCommand, + {"user_id": 1, "goal_statement": "get out there!"}, + {"user_id": 1, "goal_statement": "do some stuff!"}, + ), + ( + GoalCommand, + {"user_id": 1, "goal_statement": "get out there!", "start_date": datetime.now()}, + {"user_id": 1, "goal_statement": "get out there!", "start_date": None}, + ), + ( + GoalCommand, + {"user_id": 1, "goal_statement": "get out there!", "due_date": datetime.now()}, + {"user_id": 1, "goal_statement": "get out there!", "due_date": None}, + ), + ( + GoalCommand, + {"user_id": 1, "goal_statement": "get out there!", "today_assessment": "wee-ooo"}, + {"user_id": 1, "goal_statement": "get out there!", "today_assessment": None}, + ), + ( + GoalCommand, + { + "user_id": 100, + "goal_statement": "get out there!", + "achievement_status": GoalCommand.AchievementStatus.IN_PROGRESS, + }, + {"user_id": 100, "goal_statement": "get out there!", "achievement_status": None}, + ), + ( + GoalCommand, + { + "user_id": 100, + "goal_statement": "get out there!", + "priority": GoalCommand.Priority.MEDIUM, + }, + {"user_id": 100, "goal_statement": "get out there!", "priority": None}, + ), + ( + GoalCommand, + {"user_id": 1, "goal_statement": "get out there!", "progress": "hi"}, + {"user_id": 1, "goal_statement": "get out there!", "progress": None}, + ), ], ) def test_command_allows_kwarg_with_correct_type( - Command: PlanCommand | AssessCommand | DiagnoseCommand, + Command: PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand, test_init_kwarg: dict, test_updated_value: dict, ) -> None: From da6b98c08ba43f07d250acd9bbb2856795a0875d Mon Sep 17 00:00:00 2001 From: Michela Iannaccone Date: Wed, 21 Feb 2024 15:15:24 -0500 Subject: [PATCH 5/6] create hpi command --- canvas_sdk/commands/__init__.py | 17 +++++++--- canvas_sdk/commands/{assess => }/assess.py | 0 .../commands/{diagnose => }/diagnose.py | 0 canvas_sdk/commands/{goal => }/goal.py | 0 .../commands/history_present_illness.py | 12 +++++++ canvas_sdk/commands/{plan => }/plan.py | 0 canvas_sdk/commands/tests.py | 33 +++++++++++++++++-- 7 files changed, 54 insertions(+), 8 deletions(-) rename canvas_sdk/commands/{assess => }/assess.py (100%) rename canvas_sdk/commands/{diagnose => }/diagnose.py (100%) rename canvas_sdk/commands/{goal => }/goal.py (100%) create mode 100644 canvas_sdk/commands/history_present_illness.py rename canvas_sdk/commands/{plan => }/plan.py (100%) diff --git a/canvas_sdk/commands/__init__.py b/canvas_sdk/commands/__init__.py index 3a370bd2..76aa21bf 100644 --- a/canvas_sdk/commands/__init__.py +++ b/canvas_sdk/commands/__init__.py @@ -1,6 +1,13 @@ -from canvas_sdk.commands.assess.assess import AssessCommand -from canvas_sdk.commands.diagnose.diagnose import DiagnoseCommand -from canvas_sdk.commands.goal.goal import GoalCommand -from canvas_sdk.commands.plan.plan import PlanCommand +from canvas_sdk.commands.assess import AssessCommand +from canvas_sdk.commands.diagnose import DiagnoseCommand +from canvas_sdk.commands.goal import GoalCommand +from canvas_sdk.commands.history_present_illness import HistoryOfPresentIllnessCommand +from canvas_sdk.commands.plan import PlanCommand -__all__ = ("PlanCommand", "AssessCommand", "DiagnoseCommand", "GoalCommand") +__all__ = ( + "PlanCommand", + "AssessCommand", + "DiagnoseCommand", + "GoalCommand", + "HistoryOfPresentIllnessCommand", +) diff --git a/canvas_sdk/commands/assess/assess.py b/canvas_sdk/commands/assess.py similarity index 100% rename from canvas_sdk/commands/assess/assess.py rename to canvas_sdk/commands/assess.py diff --git a/canvas_sdk/commands/diagnose/diagnose.py b/canvas_sdk/commands/diagnose.py similarity index 100% rename from canvas_sdk/commands/diagnose/diagnose.py rename to canvas_sdk/commands/diagnose.py diff --git a/canvas_sdk/commands/goal/goal.py b/canvas_sdk/commands/goal.py similarity index 100% rename from canvas_sdk/commands/goal/goal.py rename to canvas_sdk/commands/goal.py diff --git a/canvas_sdk/commands/history_present_illness.py b/canvas_sdk/commands/history_present_illness.py new file mode 100644 index 00000000..e43a30a6 --- /dev/null +++ b/canvas_sdk/commands/history_present_illness.py @@ -0,0 +1,12 @@ +from canvas_sdk.commands.base import _BaseCommand + + +class HistoryOfPresentIllnessCommand(_BaseCommand): + """A class for managing a HPI command within a specific note.""" + + narrative: str + + @property + def values(self) -> dict: + """The HPI command's field values.""" + return {"narrative": self.narrative} diff --git a/canvas_sdk/commands/plan/plan.py b/canvas_sdk/commands/plan.py similarity index 100% rename from canvas_sdk/commands/plan/plan.py rename to canvas_sdk/commands/plan.py diff --git a/canvas_sdk/commands/tests.py b/canvas_sdk/commands/tests.py index 50fee876..0ab6a7e8 100644 --- a/canvas_sdk/commands/tests.py +++ b/canvas_sdk/commands/tests.py @@ -3,7 +3,13 @@ import pytest from pydantic import ValidationError -from canvas_sdk.commands import AssessCommand, DiagnoseCommand, GoalCommand, PlanCommand +from canvas_sdk.commands import ( + AssessCommand, + DiagnoseCommand, + GoalCommand, + HistoryOfPresentIllnessCommand, + PlanCommand, +) @pytest.mark.parametrize( @@ -189,10 +195,24 @@ "1 validation error for GoalCommand\nprogress\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", {"user_id": 5, "goal_statement": "do some stuff!"}, ), + ( + HistoryOfPresentIllnessCommand, + {"user_id": 5}, + "1 validation error for HistoryOfPresentIllnessCommand\nnarrative\n Field required [type=missing, input_value={'user_id': 5}, input_type=dict]", + {"user_id": 1, "narrative": "hiya"}, + ), + ( + HistoryOfPresentIllnessCommand, + {"user_id": 5, "narrative": None}, + "1 validation error for HistoryOfPresentIllnessCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]", + {"user_id": 1, "narrative": "hiya"}, + ), ], ) def test_command_raises_error_when_kwarg_given_incorrect_type( - Command: PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand, + Command: ( + PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand | HistoryOfPresentIllnessCommand + ), err_kwargs: dict, err_msg: str, valid_kwargs: dict, @@ -308,10 +328,17 @@ def test_command_raises_error_when_kwarg_given_incorrect_type( {"user_id": 1, "goal_statement": "get out there!", "progress": "hi"}, {"user_id": 1, "goal_statement": "get out there!", "progress": None}, ), + ( + HistoryOfPresentIllnessCommand, + {"user_id": 1, "narrative": "hi!"}, + {"user_id": 1, "narrative": "hows your day!"}, + ), ], ) def test_command_allows_kwarg_with_correct_type( - Command: PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand, + Command: ( + PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand | HistoryOfPresentIllnessCommand + ), test_init_kwarg: dict, test_updated_value: dict, ) -> None: From d580ba3bb6626f0d4c6bc2e4a6d3fdc721aba0a9 Mon Sep 17 00:00:00 2001 From: Michela Iannaccone Date: Wed, 21 Feb 2024 15:22:44 -0500 Subject: [PATCH 6/6] create medication statement command --- canvas_sdk/commands/__init__.py | 2 + canvas_sdk/commands/medication_statement.py | 13 +++++++ canvas_sdk/commands/tests.py | 43 ++++++++++++++++++++- 3 files changed, 56 insertions(+), 2 deletions(-) create mode 100644 canvas_sdk/commands/medication_statement.py diff --git a/canvas_sdk/commands/__init__.py b/canvas_sdk/commands/__init__.py index 76aa21bf..34f4681a 100644 --- a/canvas_sdk/commands/__init__.py +++ b/canvas_sdk/commands/__init__.py @@ -2,6 +2,7 @@ from canvas_sdk.commands.diagnose import DiagnoseCommand from canvas_sdk.commands.goal import GoalCommand from canvas_sdk.commands.history_present_illness import HistoryOfPresentIllnessCommand +from canvas_sdk.commands.medication_statement import MedicationStatementCommand from canvas_sdk.commands.plan import PlanCommand __all__ = ( @@ -10,4 +11,5 @@ "DiagnoseCommand", "GoalCommand", "HistoryOfPresentIllnessCommand", + "MedicationStatementCommand", ) diff --git a/canvas_sdk/commands/medication_statement.py b/canvas_sdk/commands/medication_statement.py new file mode 100644 index 00000000..9ed34caa --- /dev/null +++ b/canvas_sdk/commands/medication_statement.py @@ -0,0 +1,13 @@ +from canvas_sdk.commands.base import _BaseCommand + + +class MedicationStatementCommand(_BaseCommand): + """A class for managing a MedicationStatement command within a specific note.""" + + fdb_code: str + sig: str | None = None + + @property + def values(self) -> dict: + """The MedicationStatement command's field values.""" + return {"fdb_code": self.fdb_code, "sig": self.sig} diff --git a/canvas_sdk/commands/tests.py b/canvas_sdk/commands/tests.py index 0ab6a7e8..f24a60bd 100644 --- a/canvas_sdk/commands/tests.py +++ b/canvas_sdk/commands/tests.py @@ -8,6 +8,7 @@ DiagnoseCommand, GoalCommand, HistoryOfPresentIllnessCommand, + MedicationStatementCommand, PlanCommand, ) @@ -207,11 +208,34 @@ "1 validation error for HistoryOfPresentIllnessCommand\nnarrative\n Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]", {"user_id": 1, "narrative": "hiya"}, ), + ( + MedicationStatementCommand, + {"user_id": 1}, + "1 validation error for MedicationStatementCommand\nfdb_code\n Field required [type=missing, input_value={'user_id': 1}, input_type=dict]", + {"user_id": 1, "fdb_code": "44"}, + ), + ( + MedicationStatementCommand, + {"user_id": 1, "fdb_code": None}, + "1 validation error for MedicationStatementCommand\nfdb_code\n Input should be a valid string [type=string_type, input_value=None, input_type=NoneType]", + {"user_id": 1, "fdb_code": "44"}, + ), + ( + MedicationStatementCommand, + {"user_id": 1, "fdb_code": "44", "sig": 1}, + "1 validation error for MedicationStatementCommand\nsig\n Input should be a valid string [type=string_type, input_value=1, input_type=int]", + {"user_id": 1, "fdb_code": "44"}, + ), ], ) def test_command_raises_error_when_kwarg_given_incorrect_type( Command: ( - PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand | HistoryOfPresentIllnessCommand + PlanCommand + | AssessCommand + | DiagnoseCommand + | GoalCommand + | HistoryOfPresentIllnessCommand + | MedicationStatementCommand ), err_kwargs: dict, err_msg: str, @@ -333,11 +357,26 @@ def test_command_raises_error_when_kwarg_given_incorrect_type( {"user_id": 1, "narrative": "hi!"}, {"user_id": 1, "narrative": "hows your day!"}, ), + ( + MedicationStatementCommand, + {"user_id": 1, "fdb_code": "9888"}, + {"user_id": 1, "fdb_code": "12333"}, + ), + ( + MedicationStatementCommand, + {"user_id": 1, "fdb_code": "9888", "sig": "1pobd"}, + {"user_id": 1, "fdb_code": "9888", "sig": None}, + ), ], ) def test_command_allows_kwarg_with_correct_type( Command: ( - PlanCommand | AssessCommand | DiagnoseCommand | GoalCommand | HistoryOfPresentIllnessCommand + PlanCommand + | AssessCommand + | DiagnoseCommand + | GoalCommand + | HistoryOfPresentIllnessCommand + | MedicationStatementCommand ), test_init_kwarg: dict, test_updated_value: dict,