canvas 0.33.0__py3-none-any.whl → 0.34.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of canvas might be problematic. Click here for more details.
- {canvas-0.33.0.dist-info → canvas-0.34.0.dist-info}/METADATA +2 -1
- canvas-0.34.0.dist-info/RECORD +272 -0
- canvas_sdk/__init__.py +3 -0
- canvas_sdk/commands/__init__.py +1 -1
- canvas_sdk/commands/base.py +3 -0
- canvas_sdk/commands/commands/__init__.py +1 -0
- canvas_sdk/commands/commands/adjust_prescription.py +3 -0
- canvas_sdk/commands/commands/allergy.py +7 -0
- canvas_sdk/commands/commands/assess.py +2 -0
- canvas_sdk/commands/commands/close_goal.py +3 -0
- canvas_sdk/commands/commands/diagnose.py +3 -0
- canvas_sdk/commands/commands/exam.py +3 -0
- canvas_sdk/commands/commands/family_history.py +3 -0
- canvas_sdk/commands/commands/follow_up.py +3 -0
- canvas_sdk/commands/commands/goal.py +3 -0
- canvas_sdk/commands/commands/history_present_illness.py +3 -0
- canvas_sdk/commands/commands/imaging_order.py +3 -0
- canvas_sdk/commands/commands/instruct.py +3 -0
- canvas_sdk/commands/commands/lab_order.py +3 -0
- canvas_sdk/commands/commands/medical_history.py +3 -0
- canvas_sdk/commands/commands/medication_statement.py +2 -0
- canvas_sdk/commands/commands/past_surgical_history.py +3 -0
- canvas_sdk/commands/commands/perform.py +3 -0
- canvas_sdk/commands/commands/plan.py +3 -0
- canvas_sdk/commands/commands/prescribe.py +8 -0
- canvas_sdk/commands/commands/questionnaire/__init__.py +3 -13
- canvas_sdk/commands/commands/questionnaire/question.py +10 -0
- canvas_sdk/commands/commands/reason_for_visit.py +3 -0
- canvas_sdk/commands/commands/refer.py +3 -0
- canvas_sdk/commands/commands/refill.py +3 -0
- canvas_sdk/commands/commands/remove_allergy.py +3 -0
- canvas_sdk/commands/commands/resolve_condition.py +3 -0
- canvas_sdk/commands/commands/review_of_systems.py +3 -0
- canvas_sdk/commands/commands/stop_medication.py +3 -0
- canvas_sdk/commands/commands/structured_assessment.py +3 -0
- canvas_sdk/commands/commands/task.py +7 -0
- canvas_sdk/commands/commands/update_diagnosis.py +3 -0
- canvas_sdk/commands/commands/update_goal.py +3 -0
- canvas_sdk/commands/commands/vitals.py +3 -0
- canvas_sdk/commands/constants.py +8 -0
- canvas_sdk/effects/__init__.py +1 -1
- canvas_sdk/effects/banner_alert/__init__.py +1 -1
- canvas_sdk/effects/banner_alert/add_banner_alert.py +3 -0
- canvas_sdk/effects/banner_alert/remove_banner_alert.py +3 -0
- canvas_sdk/effects/base.py +7 -0
- canvas_sdk/effects/billing_line_item/__init__.py +5 -1
- canvas_sdk/effects/billing_line_item/add_billing_line_item.py +3 -0
- canvas_sdk/effects/billing_line_item/remove_billing_line_item.py +3 -0
- canvas_sdk/effects/billing_line_item/update_billing_line_item.py +3 -0
- canvas_sdk/effects/launch_modal.py +3 -0
- canvas_sdk/effects/patient_chart_summary_configuration.py +3 -0
- canvas_sdk/effects/patient_portal/__init__.py +1 -0
- canvas_sdk/effects/patient_portal/application_configuration.py +3 -0
- canvas_sdk/effects/patient_portal/form_result.py +3 -0
- canvas_sdk/effects/patient_portal_menu_configuration.py +3 -0
- canvas_sdk/effects/patient_profile_configuration.py +5 -1
- canvas_sdk/effects/protocol_card/__init__.py +1 -1
- canvas_sdk/effects/protocol_card/protocol_card.py +6 -0
- canvas_sdk/effects/questionnaire_result.py +3 -0
- canvas_sdk/effects/send_invite.py +3 -0
- canvas_sdk/effects/show_button.py +3 -0
- canvas_sdk/effects/simple_api.py +9 -0
- canvas_sdk/effects/surescripts/__init__.py +2 -2
- canvas_sdk/effects/surescripts/surescripts_messages.py +7 -0
- canvas_sdk/effects/task/__init__.py +6 -1
- canvas_sdk/effects/task/task.py +8 -0
- canvas_sdk/effects/update_user.py +3 -0
- canvas_sdk/effects/widgets/__init__.py +1 -1
- canvas_sdk/effects/widgets/portal_widget.py +3 -0
- canvas_sdk/events/__init__.py +6 -1
- canvas_sdk/events/base.py +3 -0
- canvas_sdk/handlers/__init__.py +1 -1
- canvas_sdk/handlers/action_button.py +6 -0
- canvas_sdk/handlers/application.py +3 -0
- canvas_sdk/handlers/base.py +3 -0
- canvas_sdk/handlers/cron_task.py +3 -0
- canvas_sdk/handlers/simple_api/__init__.py +3 -2
- canvas_sdk/handlers/simple_api/api.py +26 -1
- canvas_sdk/handlers/simple_api/exceptions.py +10 -0
- canvas_sdk/handlers/simple_api/security.py +21 -5
- canvas_sdk/handlers/simple_api/tools.py +9 -0
- canvas_sdk/protocols/__init__.py +1 -1
- canvas_sdk/protocols/base.py +3 -0
- canvas_sdk/protocols/clinical_quality_measure.py +6 -1
- canvas_sdk/protocols/timeframe.py +3 -0
- canvas_sdk/questionnaires/__init__.py +1 -1
- canvas_sdk/questionnaires/utils.py +7 -0
- canvas_sdk/templates/__init__.py +1 -1
- canvas_sdk/templates/utils.py +3 -0
- canvas_sdk/utils/__init__.py +1 -1
- canvas_sdk/utils/http.py +94 -35
- canvas_sdk/utils/plugins.py +4 -0
- canvas_sdk/utils/stats.py +11 -0
- canvas_sdk/v1/__init__.py +1 -0
- canvas_sdk/v1/apps.py +3 -0
- canvas_sdk/v1/data/__init__.py +2 -2
- canvas_sdk/v1/data/allergy_intolerance.py +3 -0
- canvas_sdk/v1/data/appointment.py +7 -0
- canvas_sdk/v1/data/assessment.py +3 -0
- canvas_sdk/v1/data/banner_alert.py +3 -0
- canvas_sdk/v1/data/base.py +3 -0
- canvas_sdk/v1/data/billing.py +7 -0
- canvas_sdk/v1/data/care_team.py +7 -0
- canvas_sdk/v1/data/command.py +3 -0
- canvas_sdk/v1/data/common.py +18 -0
- canvas_sdk/v1/data/condition.py +7 -0
- canvas_sdk/v1/data/coverage.py +14 -0
- canvas_sdk/v1/data/detected_issue.py +3 -0
- canvas_sdk/v1/data/device.py +3 -0
- canvas_sdk/v1/data/imaging.py +7 -0
- canvas_sdk/v1/data/lab.py +16 -0
- canvas_sdk/v1/data/medication.py +3 -0
- canvas_sdk/v1/data/note.py +9 -0
- canvas_sdk/v1/data/observation.py +9 -0
- canvas_sdk/v1/data/organization.py +3 -0
- canvas_sdk/v1/data/patient.py +18 -2
- canvas_sdk/v1/data/practicelocation.py +7 -0
- canvas_sdk/v1/data/protocol_override.py +7 -0
- canvas_sdk/v1/data/questionnaire.py +16 -3
- canvas_sdk/v1/data/reason_for_visit.py +3 -0
- canvas_sdk/v1/data/staff.py +3 -0
- canvas_sdk/v1/data/task.py +12 -0
- canvas_sdk/v1/data/team.py +8 -1
- canvas_sdk/v1/data/user.py +3 -0
- canvas_sdk/v1/models.py +2 -0
- canvas_sdk/value_set/__init__.py +1 -0
- canvas_sdk/value_set/_utilities.py +16 -0
- canvas_sdk/value_set/custom.py +4 -0
- canvas_sdk/value_set/hcc2018.py +3 -0
- canvas_sdk/value_set/v2022/__init__.py +1 -0
- canvas_sdk/value_set/v2022/adverse_event.py +3 -0
- canvas_sdk/value_set/v2022/allergy.py +5 -0
- canvas_sdk/value_set/v2022/assessment.py +5 -0
- canvas_sdk/value_set/v2022/communication.py +5 -0
- canvas_sdk/value_set/v2022/condition.py +5 -0
- canvas_sdk/value_set/v2022/device.py +5 -0
- canvas_sdk/value_set/v2022/diagnostic_study.py +5 -0
- canvas_sdk/value_set/v2022/encounter.py +5 -0
- canvas_sdk/value_set/v2022/immunization.py +5 -0
- canvas_sdk/value_set/v2022/individual_characteristic.py +5 -0
- canvas_sdk/value_set/v2022/intervention.py +5 -0
- canvas_sdk/value_set/v2022/laboratory_test.py +5 -0
- canvas_sdk/value_set/v2022/medication.py +5 -0
- canvas_sdk/value_set/v2022/physical_exam.py +5 -0
- canvas_sdk/value_set/v2022/procedure.py +5 -0
- canvas_sdk/value_set/v2022/symptom.py +3 -0
- canvas_sdk/value_set/value_set.py +9 -0
- canvas_sdk/views/__init__.py +1 -0
- logger/__init__.py +2 -0
- logger/logger.py +3 -0
- plugin_runner/aws_headers.py +1 -1
- plugin_runner/load_all_plugins.py +202 -0
- plugin_runner/plugin_runner.py +21 -24
- plugin_runner/sandbox.py +497 -115
- settings.py +5 -2
- canvas-0.33.0.dist-info/RECORD +0 -366
- canvas_cli/apps/auth/tests.py +0 -155
- canvas_cli/apps/plugin/tests.py +0 -85
- canvas_cli/conftest.py +0 -28
- canvas_cli/tests.py +0 -217
- canvas_cli/utils/context/tests.py +0 -131
- canvas_cli/utils/print/tests.py +0 -69
- canvas_cli/utils/urls/tests.py +0 -12
- canvas_cli/utils/validators/tests.py +0 -37
- canvas_sdk/commands/tests/protocol/__init__.py +0 -0
- canvas_sdk/commands/tests/protocol/tests.py +0 -83
- canvas_sdk/commands/tests/schema/__init__.py +0 -0
- canvas_sdk/commands/tests/schema/tests.py +0 -108
- canvas_sdk/commands/tests/test_base_command.py +0 -81
- canvas_sdk/commands/tests/test_utils.py +0 -375
- canvas_sdk/commands/tests/unit/__init__.py +0 -0
- canvas_sdk/commands/tests/unit/tests.py +0 -278
- canvas_sdk/effects/banner_alert/tests.py +0 -288
- canvas_sdk/effects/protocol_card/tests.py +0 -191
- canvas_sdk/questionnaires/tests/__init__.py +0 -0
- canvas_sdk/questionnaires/tests/test_utils.py +0 -74
- canvas_sdk/templates/tests/__init__.py +0 -0
- canvas_sdk/templates/tests/test_utils.py +0 -43
- canvas_sdk/tests/__init__.py +0 -0
- canvas_sdk/tests/handlers/__init__.py +0 -0
- canvas_sdk/tests/handlers/test_simple_api.py +0 -1167
- canvas_sdk/utils/tests.py +0 -72
- canvas_sdk/value_set/tests/test_value_sets.py +0 -72
- plugin_runner/tests/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json +0 -29
- plugin_runner/tests/fixtures/plugins/example_plugin/README.md +0 -12
- plugin_runner/tests/fixtures/plugins/example_plugin/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/example_plugin/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py +0 -18
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json +0 -38
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md +0 -11
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/my_protocol.py +0 -33
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/__init__.py +0 -3
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/base.py +0 -6
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/__init__.py +0 -5
- plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/base.py +0 -4
- plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json +0 -52
- plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md +0 -11
- plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/my_protocol.py +0 -39
- plugin_runner/tests/fixtures/plugins/test_load_questionnaire/questionnaires/example_questionnaire.yml +0 -61
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json +0 -29
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md +0 -12
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module/base.py +0 -10
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/my_protocol.py +0 -18
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json +0 -29
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md +0 -12
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/other_module/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/other_module/base.py +0 -10
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/my_protocol.py +0 -18
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json +0 -29
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md +0 -12
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/base.py +0 -3
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py +0 -18
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json +0 -29
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md +0 -12
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/base.py +0 -6
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py +0 -18
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json +0 -29
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md +0 -12
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/base.py +0 -8
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py +0 -18
- plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json +0 -29
- plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md +0 -12
- plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/base.py +0 -3
- plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py +0 -18
- plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json +0 -47
- plugin_runner/tests/fixtures/plugins/test_render_template/README.md +0 -11
- plugin_runner/tests/fixtures/plugins/test_render_template/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_render_template/protocols/my_protocol.py +0 -43
- plugin_runner/tests/fixtures/plugins/test_render_template/templates/template.html +0 -10
- plugin_runner/tests/fixtures/plugins/test_simple_api/CANVAS_MANIFEST.json +0 -47
- plugin_runner/tests/fixtures/plugins/test_simple_api/README.md +0 -11
- plugin_runner/tests/fixtures/plugins/test_simple_api/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/__init__.py +0 -0
- plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/my_protocol.py +0 -43
- plugin_runner/tests/test_application.py +0 -65
- plugin_runner/tests/test_plugin_installer.py +0 -127
- plugin_runner/tests/test_plugin_runner.py +0 -388
- plugin_runner/tests/test_sandbox.py +0 -137
- {canvas-0.33.0.dist-info → canvas-0.34.0.dist-info}/WHEEL +0 -0
- {canvas-0.33.0.dist-info → canvas-0.34.0.dist-info}/entry_points.txt +0 -0
canvas_sdk/utils/http.py
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import concurrent
|
|
2
2
|
import functools
|
|
3
|
+
import os
|
|
3
4
|
import time
|
|
4
5
|
import urllib.parse
|
|
5
6
|
from collections.abc import Callable, Iterable, Mapping
|
|
@@ -8,7 +9,8 @@ from functools import wraps
|
|
|
8
9
|
from typing import Any, Literal, Protocol, TypeVar, cast
|
|
9
10
|
|
|
10
11
|
import requests
|
|
11
|
-
|
|
12
|
+
|
|
13
|
+
from canvas_sdk.utils.stats import StatsDClientProxy
|
|
12
14
|
|
|
13
15
|
F = TypeVar("F", bound=Callable)
|
|
14
16
|
|
|
@@ -97,34 +99,25 @@ class Http:
|
|
|
97
99
|
|
|
98
100
|
_MAX_REQUEST_TIMEOUT_SECONDS = 30
|
|
99
101
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
def __setattr__(self, name: str, value: Any) -> None:
|
|
104
|
-
"""
|
|
105
|
-
Prevent base_url or session from being updated after initialization.
|
|
106
|
-
"""
|
|
107
|
-
if name in ("base_url", "session"):
|
|
108
|
-
raise AttributeError(f"{name} is read-only")
|
|
109
|
-
|
|
110
|
-
super().__setattr__(name, value)
|
|
102
|
+
_base_url: str
|
|
103
|
+
_session: requests.Session
|
|
111
104
|
|
|
112
105
|
def join_url(self, url: str) -> str:
|
|
113
106
|
"""
|
|
114
107
|
Join a URL to the base_url.
|
|
115
108
|
"""
|
|
116
|
-
joined = urllib.parse.urljoin(self.
|
|
109
|
+
joined = urllib.parse.urljoin(self._base_url, url)
|
|
117
110
|
|
|
118
|
-
if not joined.startswith(self.
|
|
111
|
+
if not joined.startswith(self._base_url):
|
|
119
112
|
raise ValueError("You may not access other URLs using this client.")
|
|
120
113
|
|
|
121
114
|
return joined
|
|
122
115
|
|
|
123
116
|
def __init__(self, base_url: str = "") -> None:
|
|
124
|
-
|
|
125
|
-
|
|
117
|
+
self._base_url = base_url
|
|
118
|
+
self._session = requests.Session()
|
|
126
119
|
|
|
127
|
-
self.statsd_client =
|
|
120
|
+
self.statsd_client = StatsDClientProxy()
|
|
128
121
|
|
|
129
122
|
@staticmethod
|
|
130
123
|
def measure_time(fn: F) -> F:
|
|
@@ -136,7 +129,7 @@ class Http:
|
|
|
136
129
|
result = fn(self, *args, **kwargs)
|
|
137
130
|
end_time = time.time()
|
|
138
131
|
timing = int((end_time - start_time) * 1000)
|
|
139
|
-
self.statsd_client.timing(f"plugins.http_{fn.__name__}", timing)
|
|
132
|
+
self.statsd_client.timing(f"plugins.http_{fn.__name__}", timing, tags={})
|
|
140
133
|
return result
|
|
141
134
|
|
|
142
135
|
return cast(F, wrapper)
|
|
@@ -148,7 +141,7 @@ class Http:
|
|
|
148
141
|
"""Sends a GET request."""
|
|
149
142
|
if headers is None:
|
|
150
143
|
headers = {}
|
|
151
|
-
return self.
|
|
144
|
+
return self._session.get(
|
|
152
145
|
self.join_url(url),
|
|
153
146
|
headers=headers,
|
|
154
147
|
timeout=self._MAX_REQUEST_TIMEOUT_SECONDS,
|
|
@@ -163,7 +156,7 @@ class Http:
|
|
|
163
156
|
headers: Mapping[str, str | bytes | None] | None = None,
|
|
164
157
|
) -> requests.Response:
|
|
165
158
|
"""Sends a POST request."""
|
|
166
|
-
return self.
|
|
159
|
+
return self._session.post(
|
|
167
160
|
self.join_url(url),
|
|
168
161
|
json=json,
|
|
169
162
|
data=data,
|
|
@@ -180,7 +173,7 @@ class Http:
|
|
|
180
173
|
headers: Mapping[str, str | bytes | None] | None = None,
|
|
181
174
|
) -> requests.Response:
|
|
182
175
|
"""Sends a PUT request."""
|
|
183
|
-
return self.
|
|
176
|
+
return self._session.put(
|
|
184
177
|
self.join_url(url),
|
|
185
178
|
json=json,
|
|
186
179
|
data=data,
|
|
@@ -197,7 +190,7 @@ class Http:
|
|
|
197
190
|
headers: Mapping[str, str | bytes | None] | None = None,
|
|
198
191
|
) -> requests.Response:
|
|
199
192
|
"""Sends a PATCH request."""
|
|
200
|
-
return self.
|
|
193
|
+
return self._session.patch(
|
|
201
194
|
self.join_url(url),
|
|
202
195
|
json=json,
|
|
203
196
|
data=data,
|
|
@@ -233,7 +226,75 @@ class Http:
|
|
|
233
226
|
return [future.result() for future in futures]
|
|
234
227
|
|
|
235
228
|
|
|
236
|
-
class
|
|
229
|
+
class JsonOnlyResponse:
|
|
230
|
+
"""
|
|
231
|
+
A very simple Response analog that only allows access to the json() method
|
|
232
|
+
and the status_code.
|
|
233
|
+
|
|
234
|
+
If we returned the response directly the user could look at the request
|
|
235
|
+
headers on the response object and see any authentication headers we sent
|
|
236
|
+
on their behalf.
|
|
237
|
+
"""
|
|
238
|
+
|
|
239
|
+
_json: dict[str, Any] | None
|
|
240
|
+
status_code: int
|
|
241
|
+
|
|
242
|
+
def __init__(self, response: requests.Response):
|
|
243
|
+
self.status_code = response.status_code
|
|
244
|
+
|
|
245
|
+
try:
|
|
246
|
+
self._json = response.json()
|
|
247
|
+
except Exception:
|
|
248
|
+
self._json = None
|
|
249
|
+
|
|
250
|
+
def json(self) -> dict[str, Any] | None:
|
|
251
|
+
return self._json
|
|
252
|
+
|
|
253
|
+
|
|
254
|
+
class JsonOnlyHttp(Http):
|
|
255
|
+
def get(
|
|
256
|
+
self,
|
|
257
|
+
url: str,
|
|
258
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
259
|
+
) -> requests.Response:
|
|
260
|
+
raise NotImplementedError
|
|
261
|
+
|
|
262
|
+
def get_json(
|
|
263
|
+
self,
|
|
264
|
+
url: str,
|
|
265
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
266
|
+
) -> JsonOnlyResponse:
|
|
267
|
+
return JsonOnlyResponse(super().get(url, headers))
|
|
268
|
+
|
|
269
|
+
def post(
|
|
270
|
+
self,
|
|
271
|
+
url: str,
|
|
272
|
+
json: dict | None = None,
|
|
273
|
+
data: dict | str | list | bytes | None = None,
|
|
274
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
275
|
+
) -> requests.Response:
|
|
276
|
+
raise NotImplementedError
|
|
277
|
+
|
|
278
|
+
def put(
|
|
279
|
+
self,
|
|
280
|
+
url: str,
|
|
281
|
+
json: dict | None = None,
|
|
282
|
+
data: dict | str | list | bytes | None = None,
|
|
283
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
284
|
+
) -> requests.Response:
|
|
285
|
+
raise NotImplementedError
|
|
286
|
+
|
|
287
|
+
def patch(
|
|
288
|
+
self,
|
|
289
|
+
url: str,
|
|
290
|
+
json: dict | None = None,
|
|
291
|
+
data: dict | str | list | bytes | None = None,
|
|
292
|
+
headers: Mapping[str, str | bytes | None] | None = None,
|
|
293
|
+
) -> requests.Response:
|
|
294
|
+
raise NotImplementedError
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
class OntologiesHttp(JsonOnlyHttp):
|
|
237
298
|
"""
|
|
238
299
|
An HTTP client for the ontologies service.
|
|
239
300
|
"""
|
|
@@ -241,13 +302,10 @@ class OntologiesHttp(Http):
|
|
|
241
302
|
def __init__(self) -> None:
|
|
242
303
|
super().__init__(base_url="https://ontologies.canvasmedical.com")
|
|
243
304
|
|
|
244
|
-
|
|
245
|
-
import os
|
|
246
|
-
|
|
247
|
-
self.session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
|
|
305
|
+
self._session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
|
|
248
306
|
|
|
249
307
|
|
|
250
|
-
class ScienceHttp(
|
|
308
|
+
class ScienceHttp(JsonOnlyHttp):
|
|
251
309
|
"""
|
|
252
310
|
An HTTP client for the ontologies service.
|
|
253
311
|
"""
|
|
@@ -255,18 +313,19 @@ class ScienceHttp(Http):
|
|
|
255
313
|
def __init__(self) -> None:
|
|
256
314
|
super().__init__(base_url="https://science.canvasmedical.com")
|
|
257
315
|
|
|
258
|
-
|
|
259
|
-
import os
|
|
316
|
+
self._session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
|
|
260
317
|
|
|
261
|
-
self.session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
|
|
262
318
|
|
|
319
|
+
ontologies_http = OntologiesHttp()
|
|
320
|
+
science_http = ScienceHttp()
|
|
263
321
|
|
|
264
|
-
__all__ =
|
|
322
|
+
__all__ = __exports__ = (
|
|
323
|
+
"ThreadPoolExecutor",
|
|
265
324
|
"Http",
|
|
266
|
-
"
|
|
267
|
-
"
|
|
325
|
+
"ontologies_http",
|
|
326
|
+
"science_http",
|
|
268
327
|
"batch_get",
|
|
269
328
|
"batch_post",
|
|
270
329
|
"batch_put",
|
|
271
330
|
"batch_patch",
|
|
272
|
-
|
|
331
|
+
)
|
canvas_sdk/utils/plugins.py
CHANGED
|
@@ -18,8 +18,12 @@ def plugin_only(func: Callable[..., Any]) -> Callable[..., Any]:
|
|
|
18
18
|
|
|
19
19
|
plugin_name = caller.f_globals["__name__"].split(".")[0]
|
|
20
20
|
plugin_dir = Path(PLUGIN_DIRECTORY) / plugin_name
|
|
21
|
+
kwargs["plugin_name"] = plugin_name
|
|
21
22
|
kwargs["plugin_dir"] = plugin_dir.resolve()
|
|
22
23
|
|
|
23
24
|
return func(*args, **kwargs)
|
|
24
25
|
|
|
25
26
|
return wrapper
|
|
27
|
+
|
|
28
|
+
|
|
29
|
+
__exports__ = ()
|
canvas_sdk/utils/stats.py
CHANGED
|
@@ -31,6 +31,9 @@ def tags_to_line_protocol(tags: dict[str, Any]) -> str:
|
|
|
31
31
|
)
|
|
32
32
|
|
|
33
33
|
|
|
34
|
+
STATS_ENABLED = True
|
|
35
|
+
|
|
36
|
+
|
|
34
37
|
class StatsDClientProxy:
|
|
35
38
|
"""Proxy for a StatsD client."""
|
|
36
39
|
|
|
@@ -45,6 +48,9 @@ class StatsDClientProxy:
|
|
|
45
48
|
value (float): The value to report.
|
|
46
49
|
tags (dict[str, str]): Dictionary of tags to attach to the metric.
|
|
47
50
|
"""
|
|
51
|
+
if not STATS_ENABLED:
|
|
52
|
+
return
|
|
53
|
+
|
|
48
54
|
statsd_tags = tags_to_line_protocol(tags)
|
|
49
55
|
self.client.gauge(f"{metric_name},{statsd_tags}", value)
|
|
50
56
|
|
|
@@ -56,8 +62,13 @@ class StatsDClientProxy:
|
|
|
56
62
|
delta (float | timedelta): The value to report.
|
|
57
63
|
tags (dict[str, str]): Dictionary of tags to attach to the metric.
|
|
58
64
|
"""
|
|
65
|
+
if not STATS_ENABLED:
|
|
66
|
+
return
|
|
67
|
+
|
|
59
68
|
statsd_tags = tags_to_line_protocol(tags)
|
|
60
69
|
self.client.timing(f"{metric_name},{statsd_tags}", delta)
|
|
61
70
|
|
|
62
71
|
|
|
63
72
|
statsd_client = StatsDClientProxy()
|
|
73
|
+
|
|
74
|
+
__exports__ = ()
|
canvas_sdk/v1/__init__.py
CHANGED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__exports__ = ()
|
canvas_sdk/v1/apps.py
CHANGED
canvas_sdk/v1/data/__init__.py
CHANGED
|
@@ -54,7 +54,7 @@ from .staff import Staff, StaffContactPoint
|
|
|
54
54
|
from .task import Task, TaskComment, TaskLabel, TaskTaskLabel
|
|
55
55
|
from .user import CanvasUser
|
|
56
56
|
|
|
57
|
-
__all__ =
|
|
57
|
+
__all__ = __exports__ = (
|
|
58
58
|
"Appointment",
|
|
59
59
|
"AppointmentExternalIdentifier",
|
|
60
60
|
"AllergyIntolerance",
|
|
@@ -120,4 +120,4 @@ __all__ = [
|
|
|
120
120
|
"Transactor",
|
|
121
121
|
"TransactorAddress",
|
|
122
122
|
"TransactorPhone",
|
|
123
|
-
|
|
123
|
+
)
|
|
@@ -76,3 +76,10 @@ class AppointmentExternalIdentifier(models.Model):
|
|
|
76
76
|
appointment = models.ForeignKey(
|
|
77
77
|
Appointment, on_delete=models.DO_NOTHING, related_name="external_identifiers"
|
|
78
78
|
)
|
|
79
|
+
|
|
80
|
+
|
|
81
|
+
__exports__ = (
|
|
82
|
+
"AppointmentProgressStatus",
|
|
83
|
+
"Appointment",
|
|
84
|
+
"AppointmentExternalIdentifier",
|
|
85
|
+
)
|
canvas_sdk/v1/data/assessment.py
CHANGED
canvas_sdk/v1/data/base.py
CHANGED
canvas_sdk/v1/data/billing.py
CHANGED
canvas_sdk/v1/data/care_team.py
CHANGED
canvas_sdk/v1/data/command.py
CHANGED
canvas_sdk/v1/data/common.py
CHANGED
|
@@ -154,3 +154,21 @@ class AddressState(models.TextChoices):
|
|
|
154
154
|
|
|
155
155
|
ACTIVE = "active", "Active"
|
|
156
156
|
DELETED = "deleted", "Deleted"
|
|
157
|
+
|
|
158
|
+
|
|
159
|
+
__exports__ = (
|
|
160
|
+
"DocumentReviewMode",
|
|
161
|
+
"OrderStatus",
|
|
162
|
+
"ReviewPatientCommunicationMethod",
|
|
163
|
+
"ReviewStatus",
|
|
164
|
+
"PersonSex",
|
|
165
|
+
"TaxIDType",
|
|
166
|
+
"ColorEnum",
|
|
167
|
+
"Origin",
|
|
168
|
+
"ContactPointSystem",
|
|
169
|
+
"ContactPointUse",
|
|
170
|
+
"ContactPointState",
|
|
171
|
+
"AddressUse",
|
|
172
|
+
"AddressType",
|
|
173
|
+
"AddressState",
|
|
174
|
+
)
|
canvas_sdk/v1/data/condition.py
CHANGED
canvas_sdk/v1/data/coverage.py
CHANGED
|
@@ -292,3 +292,17 @@ class TransactorPhone(models.Model):
|
|
|
292
292
|
|
|
293
293
|
def __str__(self) -> str:
|
|
294
294
|
return f"id={self.id}"
|
|
295
|
+
|
|
296
|
+
|
|
297
|
+
__exports__ = (
|
|
298
|
+
"CoverageStack",
|
|
299
|
+
"CoverageState",
|
|
300
|
+
"CoverageType",
|
|
301
|
+
"CoverageRelationshipCode",
|
|
302
|
+
"TransactorCoverageType",
|
|
303
|
+
"TransactorType",
|
|
304
|
+
"Coverage",
|
|
305
|
+
"Transactor",
|
|
306
|
+
"TransactorAddress",
|
|
307
|
+
"TransactorPhone",
|
|
308
|
+
)
|
canvas_sdk/v1/data/device.py
CHANGED
canvas_sdk/v1/data/imaging.py
CHANGED
|
@@ -97,3 +97,10 @@ class ImagingReport(models.Model):
|
|
|
97
97
|
result_date = models.DateField()
|
|
98
98
|
original_date = models.DateField()
|
|
99
99
|
review = models.ForeignKey(ImagingReview, on_delete=models.DO_NOTHING, null=True)
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
__exports__ = (
|
|
103
|
+
"ImagingOrder",
|
|
104
|
+
"ImagingReview",
|
|
105
|
+
"ImagingReport",
|
|
106
|
+
)
|
canvas_sdk/v1/data/lab.py
CHANGED
|
@@ -349,3 +349,19 @@ class LabPartnerTest(models.Model):
|
|
|
349
349
|
order_name = models.TextField()
|
|
350
350
|
keywords = models.TextField(blank=True)
|
|
351
351
|
cpt_code = models.CharField(max_length=256, blank=True, null=True)
|
|
352
|
+
|
|
353
|
+
|
|
354
|
+
__exports__ = (
|
|
355
|
+
"TransmissionType",
|
|
356
|
+
"LabReport",
|
|
357
|
+
"LabReviewQuerySet",
|
|
358
|
+
"LabReview",
|
|
359
|
+
"LabValue",
|
|
360
|
+
"LabValueCoding",
|
|
361
|
+
"LabOrder",
|
|
362
|
+
"LabOrderReason",
|
|
363
|
+
"LabOrderReasonCondition",
|
|
364
|
+
"LabTest",
|
|
365
|
+
"LabPartner",
|
|
366
|
+
"LabPartnerTest",
|
|
367
|
+
)
|
canvas_sdk/v1/data/medication.py
CHANGED
canvas_sdk/v1/data/note.py
CHANGED
|
@@ -160,3 +160,12 @@ class Note(models.Model):
|
|
|
160
160
|
location = models.ForeignKey("v1.PracticeLocation", on_delete=models.DO_NOTHING, null=True)
|
|
161
161
|
datetime_of_service = models.DateTimeField()
|
|
162
162
|
place_of_service = models.CharField()
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
__exports__ = (
|
|
166
|
+
"NoteTypeCategories",
|
|
167
|
+
"PracticeLocationPOS",
|
|
168
|
+
"NoteTypes",
|
|
169
|
+
"NoteType",
|
|
170
|
+
"Note",
|
|
171
|
+
)
|
|
@@ -122,3 +122,12 @@ class ObservationValueCoding(models.Model):
|
|
|
122
122
|
observation = models.ForeignKey(
|
|
123
123
|
Observation, on_delete=models.DO_NOTHING, related_name="value_codings", null=True
|
|
124
124
|
)
|
|
125
|
+
|
|
126
|
+
|
|
127
|
+
__exports__ = (
|
|
128
|
+
"Observation",
|
|
129
|
+
"ObservationCoding",
|
|
130
|
+
"ObservationComponent",
|
|
131
|
+
"ObservationComponentCoding",
|
|
132
|
+
"ObservationValueCoding",
|
|
133
|
+
)
|
canvas_sdk/v1/data/patient.py
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
1
3
|
from typing import TYPE_CHECKING, Any
|
|
2
4
|
|
|
3
5
|
import arrow
|
|
@@ -82,10 +84,10 @@ class Patient(models.Model):
|
|
|
82
84
|
default_provider_id = models.BigIntegerField()
|
|
83
85
|
user = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, null=True)
|
|
84
86
|
|
|
85
|
-
settings:
|
|
87
|
+
settings: RelatedManager[PatientSetting]
|
|
86
88
|
|
|
87
89
|
@classmethod
|
|
88
|
-
def find(cls, id: str) ->
|
|
90
|
+
def find(cls, id: str) -> Patient:
|
|
89
91
|
"""Find a patient by id."""
|
|
90
92
|
return cls._default_manager.get(id=id)
|
|
91
93
|
|
|
@@ -223,3 +225,17 @@ class PatientSetting(models.Model):
|
|
|
223
225
|
)
|
|
224
226
|
name = models.CharField()
|
|
225
227
|
value = models.JSONField()
|
|
228
|
+
|
|
229
|
+
|
|
230
|
+
__exports__ = (
|
|
231
|
+
"SexAtBirth",
|
|
232
|
+
"PatientSettingConstants",
|
|
233
|
+
"Patient",
|
|
234
|
+
"PatientContactPoint",
|
|
235
|
+
"PatientAddress",
|
|
236
|
+
"PatientExternalIdentifier",
|
|
237
|
+
"PatientSetting",
|
|
238
|
+
# not defined here but used by current plugins
|
|
239
|
+
"ContactPointState",
|
|
240
|
+
"ContactPointSystem",
|
|
241
|
+
)
|
|
@@ -67,3 +67,10 @@ class ProtocolOverride(models.Model):
|
|
|
67
67
|
cycle_quantity = models.IntegerField()
|
|
68
68
|
cycle_unit = models.CharField(choices=IntervalUnit.choices)
|
|
69
69
|
status = models.CharField(choices=Status.choices)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__exports__ = (
|
|
73
|
+
"IntervalUnit",
|
|
74
|
+
"Status",
|
|
75
|
+
"ProtocolOverride",
|
|
76
|
+
)
|
|
@@ -107,7 +107,7 @@ class Questionnaire(models.Model):
|
|
|
107
107
|
code_system = models.CharField()
|
|
108
108
|
code = models.CharField()
|
|
109
109
|
search_tags = models.CharField()
|
|
110
|
-
questions = models.ManyToManyField(Question, through="v1.QuestionnaireQuestionMap")
|
|
110
|
+
questions = models.ManyToManyField(Question, through="v1.QuestionnaireQuestionMap")
|
|
111
111
|
use_in_shx = models.BooleanField()
|
|
112
112
|
carry_forward = models.TextField()
|
|
113
113
|
|
|
@@ -159,9 +159,9 @@ class Interview(models.Model):
|
|
|
159
159
|
)
|
|
160
160
|
note_id = models.BigIntegerField()
|
|
161
161
|
appointment_id = models.BigIntegerField()
|
|
162
|
-
questionnaires = models.ManyToManyField(
|
|
162
|
+
questionnaires = models.ManyToManyField(
|
|
163
163
|
Questionnaire,
|
|
164
|
-
through="v1.InterviewQuestionnaireMap",
|
|
164
|
+
through="v1.InterviewQuestionnaireMap",
|
|
165
165
|
)
|
|
166
166
|
progress_status = models.CharField()
|
|
167
167
|
created = models.DateTimeField()
|
|
@@ -210,3 +210,16 @@ class InterviewQuestionResponse(models.Model):
|
|
|
210
210
|
questionnaire_state = models.TextField()
|
|
211
211
|
interview_state = models.TextField()
|
|
212
212
|
comment = models.CharField()
|
|
213
|
+
|
|
214
|
+
|
|
215
|
+
__exports__ = (
|
|
216
|
+
"ResponseOptionSet",
|
|
217
|
+
"ResponseOption",
|
|
218
|
+
"Question",
|
|
219
|
+
"Questionnaire",
|
|
220
|
+
"QuestionnaireQuestionMap",
|
|
221
|
+
"InterviewQuerySet",
|
|
222
|
+
"Interview",
|
|
223
|
+
"InterviewQuestionnaireMap",
|
|
224
|
+
"InterviewQuestionResponse",
|
|
225
|
+
)
|
canvas_sdk/v1/data/staff.py
CHANGED
|
@@ -84,3 +84,6 @@ class StaffContactPoint(models.Model):
|
|
|
84
84
|
rank = models.IntegerField()
|
|
85
85
|
state = models.CharField(choices=ContactPointState.choices)
|
|
86
86
|
staff = models.ForeignKey(Staff, on_delete=models.DO_NOTHING, related_name="telecom")
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
__exports__ = ("Staff", "StaffContactPoint")
|
canvas_sdk/v1/data/task.py
CHANGED
|
@@ -108,3 +108,15 @@ class TaskTaskLabel(models.Model):
|
|
|
108
108
|
dbid = models.BigIntegerField(primary_key=True)
|
|
109
109
|
task_label = models.ForeignKey(TaskLabel, on_delete=models.DO_NOTHING, null=True)
|
|
110
110
|
task = models.ForeignKey(Task, on_delete=models.DO_NOTHING, null=True)
|
|
111
|
+
|
|
112
|
+
|
|
113
|
+
__exports__ = (
|
|
114
|
+
"TaskType",
|
|
115
|
+
"EventType",
|
|
116
|
+
"TaskStatus",
|
|
117
|
+
"TaskLabelModule",
|
|
118
|
+
"Task",
|
|
119
|
+
"TaskComment",
|
|
120
|
+
"TaskLabel",
|
|
121
|
+
"TaskTaskLabel",
|
|
122
|
+
)
|
canvas_sdk/v1/data/team.py
CHANGED
|
@@ -52,7 +52,7 @@ class Team(models.Model):
|
|
|
52
52
|
name = models.CharField()
|
|
53
53
|
responsibilities = ArrayField(models.CharField(choices=TeamResponsibility.choices))
|
|
54
54
|
members = models.ManyToManyField( # type: ignore[var-annotated]
|
|
55
|
-
"v1.Staff",
|
|
55
|
+
"v1.Staff",
|
|
56
56
|
related_name="teams",
|
|
57
57
|
db_table="canvas_sdk_data_api_team_members_001",
|
|
58
58
|
)
|
|
@@ -74,3 +74,10 @@ class TeamContactPoint(models.Model):
|
|
|
74
74
|
rank = models.IntegerField()
|
|
75
75
|
state = models.CharField(choices=ContactPointState.choices)
|
|
76
76
|
team = models.ForeignKey(Team, on_delete=models.DO_NOTHING, related_name="telecom")
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
__exports__ = (
|
|
80
|
+
"TeamResponsibility",
|
|
81
|
+
"Team",
|
|
82
|
+
"TeamContactPoint",
|
|
83
|
+
)
|