canvas 0.32.0__py3-none-any.whl → 0.33.1__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.

Files changed (257) hide show
  1. {canvas-0.32.0.dist-info → canvas-0.33.1.dist-info}/METADATA +2 -1
  2. canvas-0.33.1.dist-info/RECORD +272 -0
  3. canvas_generated/messages/effects_pb2.py +2 -2
  4. canvas_generated/messages/effects_pb2.pyi +4 -0
  5. canvas_sdk/__init__.py +3 -0
  6. canvas_sdk/commands/__init__.py +1 -1
  7. canvas_sdk/commands/base.py +3 -0
  8. canvas_sdk/commands/commands/__init__.py +1 -0
  9. canvas_sdk/commands/commands/adjust_prescription.py +3 -0
  10. canvas_sdk/commands/commands/allergy.py +7 -0
  11. canvas_sdk/commands/commands/assess.py +2 -0
  12. canvas_sdk/commands/commands/close_goal.py +3 -0
  13. canvas_sdk/commands/commands/diagnose.py +3 -0
  14. canvas_sdk/commands/commands/exam.py +3 -0
  15. canvas_sdk/commands/commands/family_history.py +3 -0
  16. canvas_sdk/commands/commands/follow_up.py +3 -0
  17. canvas_sdk/commands/commands/goal.py +3 -0
  18. canvas_sdk/commands/commands/history_present_illness.py +3 -0
  19. canvas_sdk/commands/commands/imaging_order.py +3 -0
  20. canvas_sdk/commands/commands/instruct.py +3 -0
  21. canvas_sdk/commands/commands/lab_order.py +3 -0
  22. canvas_sdk/commands/commands/medical_history.py +3 -0
  23. canvas_sdk/commands/commands/medication_statement.py +2 -0
  24. canvas_sdk/commands/commands/past_surgical_history.py +3 -0
  25. canvas_sdk/commands/commands/perform.py +3 -0
  26. canvas_sdk/commands/commands/plan.py +3 -0
  27. canvas_sdk/commands/commands/prescribe.py +8 -0
  28. canvas_sdk/commands/commands/questionnaire/__init__.py +3 -13
  29. canvas_sdk/commands/commands/questionnaire/question.py +10 -0
  30. canvas_sdk/commands/commands/reason_for_visit.py +3 -0
  31. canvas_sdk/commands/commands/refer.py +3 -0
  32. canvas_sdk/commands/commands/refill.py +3 -0
  33. canvas_sdk/commands/commands/remove_allergy.py +3 -0
  34. canvas_sdk/commands/commands/resolve_condition.py +3 -0
  35. canvas_sdk/commands/commands/review_of_systems.py +3 -0
  36. canvas_sdk/commands/commands/stop_medication.py +3 -0
  37. canvas_sdk/commands/commands/structured_assessment.py +3 -0
  38. canvas_sdk/commands/commands/task.py +7 -0
  39. canvas_sdk/commands/commands/update_diagnosis.py +3 -0
  40. canvas_sdk/commands/commands/update_goal.py +3 -0
  41. canvas_sdk/commands/commands/vitals.py +3 -0
  42. canvas_sdk/commands/constants.py +8 -0
  43. canvas_sdk/effects/__init__.py +1 -1
  44. canvas_sdk/effects/banner_alert/__init__.py +1 -1
  45. canvas_sdk/effects/banner_alert/add_banner_alert.py +3 -0
  46. canvas_sdk/effects/banner_alert/remove_banner_alert.py +3 -0
  47. canvas_sdk/effects/base.py +7 -0
  48. canvas_sdk/effects/billing_line_item/__init__.py +5 -1
  49. canvas_sdk/effects/billing_line_item/add_billing_line_item.py +3 -0
  50. canvas_sdk/effects/billing_line_item/remove_billing_line_item.py +3 -0
  51. canvas_sdk/effects/billing_line_item/update_billing_line_item.py +3 -0
  52. canvas_sdk/effects/launch_modal.py +3 -0
  53. canvas_sdk/effects/patient_chart_summary_configuration.py +3 -0
  54. canvas_sdk/effects/patient_portal/__init__.py +1 -0
  55. canvas_sdk/effects/patient_portal/application_configuration.py +3 -0
  56. canvas_sdk/effects/patient_portal/form_result.py +3 -0
  57. canvas_sdk/effects/patient_portal_menu_configuration.py +3 -0
  58. canvas_sdk/effects/patient_profile_configuration.py +6 -1
  59. canvas_sdk/effects/protocol_card/__init__.py +1 -1
  60. canvas_sdk/effects/protocol_card/protocol_card.py +6 -0
  61. canvas_sdk/effects/questionnaire_result.py +3 -0
  62. canvas_sdk/effects/send_invite.py +46 -0
  63. canvas_sdk/effects/show_button.py +3 -0
  64. canvas_sdk/effects/simple_api.py +9 -0
  65. canvas_sdk/effects/surescripts/__init__.py +2 -2
  66. canvas_sdk/effects/surescripts/surescripts_messages.py +7 -0
  67. canvas_sdk/effects/task/__init__.py +6 -1
  68. canvas_sdk/effects/task/task.py +8 -0
  69. canvas_sdk/effects/update_user.py +81 -0
  70. canvas_sdk/effects/widgets/__init__.py +1 -1
  71. canvas_sdk/effects/widgets/portal_widget.py +3 -0
  72. canvas_sdk/events/__init__.py +6 -1
  73. canvas_sdk/events/base.py +3 -0
  74. canvas_sdk/handlers/__init__.py +1 -1
  75. canvas_sdk/handlers/action_button.py +6 -0
  76. canvas_sdk/handlers/application.py +3 -0
  77. canvas_sdk/handlers/base.py +3 -0
  78. canvas_sdk/handlers/cron_task.py +3 -0
  79. canvas_sdk/handlers/simple_api/__init__.py +3 -2
  80. canvas_sdk/handlers/simple_api/api.py +26 -1
  81. canvas_sdk/handlers/simple_api/exceptions.py +10 -0
  82. canvas_sdk/handlers/simple_api/security.py +21 -5
  83. canvas_sdk/handlers/simple_api/tools.py +9 -0
  84. canvas_sdk/protocols/__init__.py +1 -1
  85. canvas_sdk/protocols/base.py +3 -0
  86. canvas_sdk/protocols/clinical_quality_measure.py +6 -1
  87. canvas_sdk/protocols/timeframe.py +3 -0
  88. canvas_sdk/questionnaires/__init__.py +1 -1
  89. canvas_sdk/questionnaires/utils.py +7 -0
  90. canvas_sdk/templates/__init__.py +1 -1
  91. canvas_sdk/templates/utils.py +3 -0
  92. canvas_sdk/utils/__init__.py +1 -1
  93. canvas_sdk/utils/http.py +69 -35
  94. canvas_sdk/utils/plugins.py +4 -0
  95. canvas_sdk/utils/stats.py +11 -0
  96. canvas_sdk/v1/__init__.py +1 -0
  97. canvas_sdk/v1/apps.py +3 -0
  98. canvas_sdk/v1/data/__init__.py +2 -2
  99. canvas_sdk/v1/data/allergy_intolerance.py +3 -0
  100. canvas_sdk/v1/data/appointment.py +7 -0
  101. canvas_sdk/v1/data/assessment.py +3 -0
  102. canvas_sdk/v1/data/banner_alert.py +3 -0
  103. canvas_sdk/v1/data/base.py +3 -0
  104. canvas_sdk/v1/data/billing.py +7 -0
  105. canvas_sdk/v1/data/care_team.py +7 -0
  106. canvas_sdk/v1/data/command.py +3 -0
  107. canvas_sdk/v1/data/common.py +18 -0
  108. canvas_sdk/v1/data/condition.py +7 -0
  109. canvas_sdk/v1/data/coverage.py +14 -0
  110. canvas_sdk/v1/data/detected_issue.py +3 -0
  111. canvas_sdk/v1/data/device.py +3 -0
  112. canvas_sdk/v1/data/imaging.py +7 -0
  113. canvas_sdk/v1/data/lab.py +16 -0
  114. canvas_sdk/v1/data/medication.py +3 -0
  115. canvas_sdk/v1/data/note.py +9 -0
  116. canvas_sdk/v1/data/observation.py +9 -0
  117. canvas_sdk/v1/data/organization.py +3 -0
  118. canvas_sdk/v1/data/patient.py +20 -3
  119. canvas_sdk/v1/data/practicelocation.py +7 -0
  120. canvas_sdk/v1/data/protocol_override.py +7 -0
  121. canvas_sdk/v1/data/questionnaire.py +16 -3
  122. canvas_sdk/v1/data/reason_for_visit.py +3 -0
  123. canvas_sdk/v1/data/staff.py +3 -0
  124. canvas_sdk/v1/data/task.py +12 -0
  125. canvas_sdk/v1/data/team.py +8 -1
  126. canvas_sdk/v1/data/user.py +5 -1
  127. canvas_sdk/v1/models.py +2 -0
  128. canvas_sdk/value_set/__init__.py +1 -0
  129. canvas_sdk/value_set/_utilities.py +16 -0
  130. canvas_sdk/value_set/custom.py +4 -0
  131. canvas_sdk/value_set/hcc2018.py +3 -0
  132. canvas_sdk/value_set/v2022/__init__.py +1 -0
  133. canvas_sdk/value_set/v2022/adverse_event.py +3 -0
  134. canvas_sdk/value_set/v2022/allergy.py +5 -0
  135. canvas_sdk/value_set/v2022/assessment.py +5 -0
  136. canvas_sdk/value_set/v2022/communication.py +5 -0
  137. canvas_sdk/value_set/v2022/condition.py +5 -0
  138. canvas_sdk/value_set/v2022/device.py +5 -0
  139. canvas_sdk/value_set/v2022/diagnostic_study.py +5 -0
  140. canvas_sdk/value_set/v2022/encounter.py +5 -0
  141. canvas_sdk/value_set/v2022/immunization.py +5 -0
  142. canvas_sdk/value_set/v2022/individual_characteristic.py +5 -0
  143. canvas_sdk/value_set/v2022/intervention.py +5 -0
  144. canvas_sdk/value_set/v2022/laboratory_test.py +5 -0
  145. canvas_sdk/value_set/v2022/medication.py +5 -0
  146. canvas_sdk/value_set/v2022/physical_exam.py +5 -0
  147. canvas_sdk/value_set/v2022/procedure.py +5 -0
  148. canvas_sdk/value_set/v2022/symptom.py +3 -0
  149. canvas_sdk/value_set/value_set.py +9 -0
  150. canvas_sdk/views/__init__.py +1 -0
  151. logger/__init__.py +2 -0
  152. logger/logger.py +3 -0
  153. plugin_runner/aws_headers.py +1 -1
  154. plugin_runner/load_all_plugins.py +202 -0
  155. plugin_runner/plugin_runner.py +26 -24
  156. plugin_runner/sandbox.py +497 -115
  157. protobufs/canvas_generated/messages/effects.proto +3 -0
  158. settings.py +5 -2
  159. canvas-0.32.0.dist-info/RECORD +0 -364
  160. canvas_cli/apps/auth/tests.py +0 -155
  161. canvas_cli/apps/plugin/tests.py +0 -85
  162. canvas_cli/conftest.py +0 -28
  163. canvas_cli/tests.py +0 -217
  164. canvas_cli/utils/context/tests.py +0 -131
  165. canvas_cli/utils/print/tests.py +0 -69
  166. canvas_cli/utils/urls/tests.py +0 -12
  167. canvas_cli/utils/validators/tests.py +0 -37
  168. canvas_sdk/commands/tests/protocol/__init__.py +0 -0
  169. canvas_sdk/commands/tests/protocol/tests.py +0 -83
  170. canvas_sdk/commands/tests/schema/__init__.py +0 -0
  171. canvas_sdk/commands/tests/schema/tests.py +0 -108
  172. canvas_sdk/commands/tests/test_base_command.py +0 -81
  173. canvas_sdk/commands/tests/test_utils.py +0 -375
  174. canvas_sdk/commands/tests/unit/__init__.py +0 -0
  175. canvas_sdk/commands/tests/unit/tests.py +0 -278
  176. canvas_sdk/effects/banner_alert/tests.py +0 -288
  177. canvas_sdk/effects/protocol_card/tests.py +0 -191
  178. canvas_sdk/questionnaires/tests/__init__.py +0 -0
  179. canvas_sdk/questionnaires/tests/test_utils.py +0 -74
  180. canvas_sdk/templates/tests/__init__.py +0 -0
  181. canvas_sdk/templates/tests/test_utils.py +0 -43
  182. canvas_sdk/tests/__init__.py +0 -0
  183. canvas_sdk/tests/handlers/__init__.py +0 -0
  184. canvas_sdk/tests/handlers/test_simple_api.py +0 -1167
  185. canvas_sdk/utils/tests.py +0 -72
  186. canvas_sdk/value_set/tests/test_value_sets.py +0 -72
  187. plugin_runner/tests/__init__.py +0 -0
  188. plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json +0 -29
  189. plugin_runner/tests/fixtures/plugins/example_plugin/README.md +0 -12
  190. plugin_runner/tests/fixtures/plugins/example_plugin/__init__.py +0 -0
  191. plugin_runner/tests/fixtures/plugins/example_plugin/protocols/__init__.py +0 -0
  192. plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py +0 -18
  193. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json +0 -38
  194. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md +0 -11
  195. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/__init__.py +0 -0
  196. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/my_protocol.py +0 -33
  197. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/__init__.py +0 -3
  198. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/base.py +0 -6
  199. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/__init__.py +0 -5
  200. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/base.py +0 -4
  201. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json +0 -52
  202. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md +0 -11
  203. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/__init__.py +0 -0
  204. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/my_protocol.py +0 -39
  205. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/questionnaires/example_questionnaire.yml +0 -61
  206. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json +0 -29
  207. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md +0 -12
  208. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module/__init__.py +0 -0
  209. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module/base.py +0 -10
  210. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/__init__.py +0 -0
  211. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/my_protocol.py +0 -18
  212. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json +0 -29
  213. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md +0 -12
  214. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/other_module/__init__.py +0 -0
  215. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/other_module/base.py +0 -10
  216. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/__init__.py +0 -0
  217. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/my_protocol.py +0 -18
  218. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json +0 -29
  219. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md +0 -12
  220. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/__init__.py +0 -0
  221. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/base.py +0 -3
  222. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/__init__.py +0 -0
  223. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py +0 -18
  224. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json +0 -29
  225. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md +0 -12
  226. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/__init__.py +0 -0
  227. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/base.py +0 -6
  228. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/__init__.py +0 -0
  229. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py +0 -18
  230. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json +0 -29
  231. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md +0 -12
  232. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/__init__.py +0 -0
  233. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/base.py +0 -8
  234. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/__init__.py +0 -0
  235. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py +0 -18
  236. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json +0 -29
  237. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md +0 -12
  238. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/__init__.py +0 -0
  239. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/base.py +0 -3
  240. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py +0 -0
  241. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py +0 -18
  242. plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json +0 -47
  243. plugin_runner/tests/fixtures/plugins/test_render_template/README.md +0 -11
  244. plugin_runner/tests/fixtures/plugins/test_render_template/protocols/__init__.py +0 -0
  245. plugin_runner/tests/fixtures/plugins/test_render_template/protocols/my_protocol.py +0 -43
  246. plugin_runner/tests/fixtures/plugins/test_render_template/templates/template.html +0 -10
  247. plugin_runner/tests/fixtures/plugins/test_simple_api/CANVAS_MANIFEST.json +0 -47
  248. plugin_runner/tests/fixtures/plugins/test_simple_api/README.md +0 -11
  249. plugin_runner/tests/fixtures/plugins/test_simple_api/__init__.py +0 -0
  250. plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/__init__.py +0 -0
  251. plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/my_protocol.py +0 -43
  252. plugin_runner/tests/test_application.py +0 -65
  253. plugin_runner/tests/test_plugin_installer.py +0 -127
  254. plugin_runner/tests/test_plugin_runner.py +0 -388
  255. plugin_runner/tests/test_sandbox.py +0 -137
  256. {canvas-0.32.0.dist-info → canvas-0.33.1.dist-info}/WHEEL +0 -0
  257. {canvas-0.32.0.dist-info → canvas-0.33.1.dist-info}/entry_points.txt +0 -0
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from base64 import b64decode
2
4
  from secrets import compare_digest
3
5
  from typing import TYPE_CHECKING, Any, Protocol
@@ -24,7 +26,7 @@ class Credentials:
24
26
  class if they wish to just access the request directly in their authentication method.
25
27
  """
26
28
 
27
- def __init__(self, request: "Request") -> None:
29
+ def __init__(self, request: Request) -> None:
28
30
  pass
29
31
 
30
32
 
@@ -36,7 +38,7 @@ class BasicCredentials(Credentials):
36
38
  them as attributes.
37
39
  """
38
40
 
39
- def __init__(self, request: "Request") -> None:
41
+ def __init__(self, request: Request) -> None:
40
42
  super().__init__(request)
41
43
 
42
44
  authorization = request.headers.get("Authorization")
@@ -71,7 +73,7 @@ class BearerCredentials(Credentials):
71
73
  Parses the token from the request Authorization header and saves it as an attribute.
72
74
  """
73
75
 
74
- def __init__(self, request: "Request") -> None:
76
+ def __init__(self, request: Request) -> None:
75
77
  super().__init__(request)
76
78
 
77
79
  authorization = request.headers.get("Authorization")
@@ -101,7 +103,7 @@ class APIKeyCredentials(Credentials):
101
103
 
102
104
  HEADER_NAME = "Authorization"
103
105
 
104
- def __init__(self, request: "Request") -> None:
106
+ def __init__(self, request: Request) -> None:
105
107
  super().__init__(request)
106
108
 
107
109
  if self.HEADER_NAME not in request.headers:
@@ -132,7 +134,7 @@ class SessionCredentials(Credentials):
132
134
  authenticate method.
133
135
  """
134
136
 
135
- def __init__(self, request: "Request") -> None:
137
+ def __init__(self, request: Request) -> None:
136
138
  super().__init__(request)
137
139
 
138
140
  if (
@@ -247,3 +249,17 @@ class PatientSessionAuthMixin(AuthSchemeMixin):
247
249
  if credentials.logged_in_user["type"] != "Patient":
248
250
  raise InvalidCredentialsError
249
251
  return True
252
+
253
+
254
+ __exports__ = (
255
+ "Credentials",
256
+ "BasicCredentials",
257
+ "BearerCredentials",
258
+ "APIKeyCredentials",
259
+ "AuthSchemeMixin",
260
+ "BasicAuthMixin",
261
+ "APIKeyAuthMixin",
262
+ "SessionCredentials",
263
+ "StaffSessionAuthMixin",
264
+ "PatientSessionAuthMixin",
265
+ )
@@ -113,3 +113,12 @@ def separate_headers(headers: Mapping[str, str]) -> list[tuple[str, str]]:
113
113
  headers_list.append((key, value.strip()))
114
114
 
115
115
  return headers_list
116
+
117
+
118
+ __exports__ = (
119
+ "KeyType",
120
+ "ValueType",
121
+ "MultiDict",
122
+ "CaseInsensitiveMultiDict",
123
+ "separate_headers",
124
+ )
@@ -1,4 +1,4 @@
1
1
  from canvas_sdk.protocols.base import BaseProtocol
2
2
  from canvas_sdk.protocols.clinical_quality_measure import ClinicalQualityMeasure
3
3
 
4
- __all__ = ("BaseProtocol", "ClinicalQualityMeasure")
4
+ __all__ = __exports__ = ("BaseProtocol", "ClinicalQualityMeasure")
@@ -9,3 +9,6 @@ class BaseProtocol(BaseHandler, ABC):
9
9
  """
10
10
 
11
11
  pass
12
+
13
+
14
+ __exports__ = ("BaseProtocol",)
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from typing import TYPE_CHECKING, Any, cast
2
4
 
3
5
  import arrow
@@ -92,7 +94,7 @@ class ClinicalQualityMeasure(BaseProtocol):
92
94
  incurring more SQL queries.
93
95
  """
94
96
 
95
- def patient_id(model: "type[Model]") -> str:
97
+ def patient_id(model: type[Model]) -> str:
96
98
  if model == Patient:
97
99
  return self.event.target.id
98
100
  else:
@@ -130,3 +132,6 @@ class ClinicalQualityMeasure(BaseProtocol):
130
132
  ) from error
131
133
 
132
134
  return self._patient_id
135
+
136
+
137
+ __exports__ = ("ClinicalQualityMeasure",)
@@ -37,3 +37,6 @@ class Timeframe:
37
37
  start = start.shift(days=days)
38
38
 
39
39
  return Timeframe(start=start, end=end)
40
+
41
+
42
+ __exports__ = ("Timeframe",)
@@ -1,3 +1,3 @@
1
1
  from .utils import from_yaml as questionnaire_from_yaml
2
2
 
3
- __all__ = ("questionnaire_from_yaml",)
3
+ __all__ = __exports__ = ("questionnaire_from_yaml",)
@@ -115,3 +115,10 @@ def json_schema() -> dict[str, Any]:
115
115
  )
116
116
 
117
117
  return schema
118
+
119
+
120
+ __exports__ = (
121
+ "Draft7Validator",
122
+ "ExtendedDraft7Validator",
123
+ "from_yaml",
124
+ )
@@ -1,3 +1,3 @@
1
1
  from .utils import render_to_string
2
2
 
3
- __all__ = ("render_to_string",)
3
+ __all__ = __exports__ = ("render_to_string",)
@@ -37,3 +37,6 @@ def render_to_string(
37
37
  template = Template(template_path.read_text())
38
38
 
39
39
  return template.render(Context(context))
40
+
41
+
42
+ __exports__ = ("render_to_string",)
@@ -1,6 +1,6 @@
1
1
  from canvas_sdk.utils.http import Http, batch_get, batch_patch, batch_post, batch_put
2
2
 
3
- __all__ = (
3
+ __all__ = __exports__ = (
4
4
  "Http",
5
5
  "batch_get",
6
6
  "batch_patch",
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
- import statsd
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
- base_url: str
101
- session: requests.Session
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.base_url, url)
109
+ joined = urllib.parse.urljoin(self._base_url, url)
117
110
 
118
- if not joined.startswith(self.base_url):
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
- super().__setattr__("base_url", base_url)
125
- super().__setattr__("session", requests.Session())
117
+ self._base_url = base_url
118
+ self._session = requests.Session()
126
119
 
127
- self.statsd_client = statsd.StatsClient()
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.session.get(
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.session.post(
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.session.put(
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.session.patch(
193
+ return self._session.patch(
201
194
  self.join_url(url),
202
195
  json=json,
203
196
  data=data,
@@ -233,7 +226,50 @@ class Http:
233
226
  return [future.result() for future in futures]
234
227
 
235
228
 
236
- class OntologiesHttp(Http):
229
+ class JsonOnlyHttp(Http):
230
+ def get(
231
+ self,
232
+ url: str,
233
+ headers: Mapping[str, str | bytes | None] | None = None,
234
+ ) -> requests.Response:
235
+ raise NotImplementedError
236
+
237
+ def get_json(
238
+ self,
239
+ url: str,
240
+ headers: Mapping[str, str | bytes | None] | None = None,
241
+ ) -> dict[str, Any]:
242
+ return super().get(url, headers).json()
243
+
244
+ def post(
245
+ self,
246
+ url: str,
247
+ json: dict | None = None,
248
+ data: dict | str | list | bytes | None = None,
249
+ headers: Mapping[str, str | bytes | None] | None = None,
250
+ ) -> requests.Response:
251
+ raise NotImplementedError
252
+
253
+ def put(
254
+ self,
255
+ url: str,
256
+ json: dict | None = None,
257
+ data: dict | str | list | bytes | None = None,
258
+ headers: Mapping[str, str | bytes | None] | None = None,
259
+ ) -> requests.Response:
260
+ raise NotImplementedError
261
+
262
+ def patch(
263
+ self,
264
+ url: str,
265
+ json: dict | None = None,
266
+ data: dict | str | list | bytes | None = None,
267
+ headers: Mapping[str, str | bytes | None] | None = None,
268
+ ) -> requests.Response:
269
+ raise NotImplementedError
270
+
271
+
272
+ class OntologiesHttp(JsonOnlyHttp):
237
273
  """
238
274
  An HTTP client for the ontologies service.
239
275
  """
@@ -241,13 +277,10 @@ class OntologiesHttp(Http):
241
277
  def __init__(self) -> None:
242
278
  super().__init__(base_url="https://ontologies.canvasmedical.com")
243
279
 
244
- # import here to avoid making it exportable to module importers
245
- import os
246
-
247
- self.session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
280
+ self._session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
248
281
 
249
282
 
250
- class ScienceHttp(Http):
283
+ class ScienceHttp(JsonOnlyHttp):
251
284
  """
252
285
  An HTTP client for the ontologies service.
253
286
  """
@@ -255,18 +288,19 @@ class ScienceHttp(Http):
255
288
  def __init__(self) -> None:
256
289
  super().__init__(base_url="https://science.canvasmedical.com")
257
290
 
258
- # import here to avoid making it exportable to module importers
259
- import os
291
+ self._session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
260
292
 
261
- self.session.headers.update({"Authorization": os.getenv("PRE_SHARED_KEY", "")})
262
293
 
294
+ ontologies_http = OntologiesHttp()
295
+ science_http = ScienceHttp()
263
296
 
264
- __all__ = [
297
+ __all__ = __exports__ = (
298
+ "ThreadPoolExecutor",
265
299
  "Http",
266
- "OntologiesHttp",
267
- "ScienceHttp",
300
+ "ontologies_http",
301
+ "science_http",
268
302
  "batch_get",
269
303
  "batch_post",
270
304
  "batch_put",
271
305
  "batch_patch",
272
- ]
306
+ )
@@ -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
@@ -5,3 +5,6 @@ class CanvasSdkV1Config(AppConfig):
5
5
  """AppConfig for v1 of the SDK data module."""
6
6
 
7
7
  name = "canvas_sdk.v1"
8
+
9
+
10
+ __exports__ = ()
@@ -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
+ )
@@ -77,3 +77,6 @@ class AllergyIntoleranceCoding(models.Model):
77
77
  related_name="codings",
78
78
  null=True,
79
79
  )
80
+
81
+
82
+ __exports__ = ("AllergyIntolerance", "AllergyIntoleranceCoding")
@@ -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
+ )
@@ -38,3 +38,6 @@ class Assessment(models.Model):
38
38
  narrative = models.CharField()
39
39
  background = models.CharField()
40
40
  care_team = models.CharField()
41
+
42
+
43
+ __exports__ = ("AssessmentStatus", "Assessment")
@@ -25,3 +25,6 @@ class BannerAlert(models.Model):
25
25
  intent = models.CharField()
26
26
  href = models.CharField()
27
27
  status = models.CharField()
28
+
29
+
30
+ __exports__ = ("BannerAlert",)
@@ -187,3 +187,6 @@ class ValueSetTimeframeLookupQuerySet(ValueSetLookupQuerySet, TimeframeLookupQue
187
187
  """A class that includes methods for looking up value sets and using timeframes."""
188
188
 
189
189
  pass
190
+
191
+
192
+ __exports__ = ()
@@ -83,3 +83,10 @@ class BillingLineItemModifier(models.Model):
83
83
  related_name="modifiers",
84
84
  null=True,
85
85
  )
86
+
87
+
88
+ __exports__ = (
89
+ "BillingLineItemStatus",
90
+ "BillingLineItem",
91
+ "BillingLineItemModifier",
92
+ )
@@ -58,3 +58,10 @@ class CareTeamMembership(models.Model):
58
58
 
59
59
  def __str__(self) -> str:
60
60
  return f"id={self.id}"
61
+
62
+
63
+ __exports__ = (
64
+ "CareTeamMembershipStatus",
65
+ "CareTeamRole",
66
+ "CareTeamMembership",
67
+ )
@@ -36,3 +36,6 @@ class Command(models.Model):
36
36
  app_label=self._meta.app_label, model_name=self.anchor_object_type
37
37
  )
38
38
  return anchor_model.objects.get(dbid=self.anchor_object_dbid)
39
+
40
+
41
+ __exports__ = ("Command",)
@@ -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
+ )
@@ -76,3 +76,10 @@ class ConditionCoding(models.Model):
76
76
  condition = models.ForeignKey(
77
77
  Condition, on_delete=models.DO_NOTHING, related_name="codings", null=True
78
78
  )
79
+
80
+
81
+ __exports__ = (
82
+ "ClinicalStatus",
83
+ "Condition",
84
+ "ConditionCoding",
85
+ )
@@ -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
+ )
@@ -49,3 +49,6 @@ class DetectedIssueEvidence(models.Model):
49
49
  related_name="evidence",
50
50
  null=True,
51
51
  )
52
+
53
+
54
+ __exports__ = ("DetectedIssue", "DetectedIssueEvidence")
@@ -40,3 +40,6 @@ class Device(models.Model):
40
40
  manufacturing_date = models.DateField()
41
41
  manufacturer = models.CharField()
42
42
  procedure_id = models.BigIntegerField()
43
+
44
+
45
+ __exports__ = ("Device",)
@@ -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
+ )
@@ -72,3 +72,6 @@ class MedicationCoding(models.Model):
72
72
  medication = models.ForeignKey(
73
73
  Medication, on_delete=models.DO_NOTHING, related_name="codings", null=True
74
74
  )
75
+
76
+
77
+ __exports__ = ("Status", "Medication", "MedicationCoding")
@@ -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
+ )
@@ -26,3 +26,6 @@ class Organization(models.Model):
26
26
  group_taxonomy_number = models.CharField()
27
27
  include_zz_qualifier = models.BooleanField()
28
28
  main_location = models.OneToOneField("v1.PracticeLocation", on_delete=models.DO_NOTHING)
29
+
30
+
31
+ __exports__ = ("Organization",)