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,4 +1,6 @@
1
- from typing import TYPE_CHECKING, Any, Self
1
+ from __future__ import annotations
2
+
3
+ from typing import TYPE_CHECKING, Any
2
4
 
3
5
  import arrow
4
6
  from django.contrib.postgres.fields import ArrayField
@@ -80,11 +82,12 @@ class Patient(models.Model):
80
82
  birth_order = models.BigIntegerField()
81
83
  default_location_id = models.BigIntegerField()
82
84
  default_provider_id = models.BigIntegerField()
85
+ user = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, null=True)
83
86
 
84
- settings: "RelatedManager[PatientSetting]"
87
+ settings: RelatedManager[PatientSetting]
85
88
 
86
89
  @classmethod
87
- def find(cls, id: str) -> Self:
90
+ def find(cls, id: str) -> Patient:
88
91
  """Find a patient by id."""
89
92
  return cls._default_manager.get(id=id)
90
93
 
@@ -222,3 +225,17 @@ class PatientSetting(models.Model):
222
225
  )
223
226
  name = models.CharField()
224
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
+ )
@@ -101,3 +101,10 @@ class PracticeLocationSetting(models.Model):
101
101
 
102
102
  def __str__(self) -> str:
103
103
  return self.name
104
+
105
+
106
+ __exports__ = (
107
+ "PracticeLocationPOS",
108
+ "PracticeLocation",
109
+ "PracticeLocationSetting",
110
+ )
@@ -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") # type: ignore[misc, var-annotated]
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( # type: ignore[var-annotated]
162
+ questionnaires = models.ManyToManyField(
163
163
  Questionnaire,
164
- through="v1.InterviewQuestionnaireMap", # type: ignore[misc]
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
+ )
@@ -20,3 +20,6 @@ class ReasonForVisitSettingCoding(models.Model):
20
20
  version = models.CharField()
21
21
 
22
22
  duration = ArrayField(models.DurationField())
23
+
24
+
25
+ __exports__ = ("ReasonForVisitSettingCoding",)
@@ -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")
@@ -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
+ )
@@ -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", # type: ignore[misc]
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
+ )
@@ -9,4 +9,8 @@ class CanvasUser(models.Model):
9
9
  db_table = "canvas_sdk_data_api_auth_user_001"
10
10
 
11
11
  dbid = models.BigIntegerField(db_column="dbid", primary_key=True)
12
- email = models.CharField()
12
+ email = models.EmailField(db_column="email")
13
+ phone_number = models.CharField(db_column="phone_number", max_length=255)
14
+
15
+
16
+ __exports__ = ("CanvasUser",)
canvas_sdk/v1/models.py CHANGED
@@ -2,3 +2,5 @@
2
2
  # reasons. For this reason, we import * from data to avoid duplication.
3
3
 
4
4
  from .data import * # noqa: F403
5
+
6
+ __exports__ = ()
@@ -0,0 +1 @@
1
+ __exports__ = ()
@@ -0,0 +1,16 @@
1
+ from inspect import isclass
2
+ from typing import Any
3
+
4
+ from canvas_sdk.value_set.value_set import ValueSet
5
+
6
+
7
+ def get_overrides(dictionary: dict[str, Any]) -> tuple:
8
+ """
9
+ Return the keys that are ValueSets.
10
+ """
11
+ return tuple(
12
+ key for key, value in dictionary.items() if isclass(value) and issubclass(value, ValueSet)
13
+ )
14
+
15
+
16
+ __exports__ = ()
@@ -1,3 +1,4 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
1
2
  from canvas_sdk.value_set.value_set import ValueSet
2
3
 
3
4
 
@@ -1055,3 +1056,6 @@ class DiabetesOtherClassConditionSuspect(ValueSet):
1055
1056
  "L98498",
1056
1057
  "L98499",
1057
1058
  }
1059
+
1060
+
1061
+ __exports__ = get_overrides(locals().copy())
@@ -55367,3 +55367,6 @@ class HCCConditions(ValueSet):
55367
55367
  if icd10 in HCCConditions.LABELS:
55368
55368
  return cast(float, HCCConditions.LABELS[icd10]["CommunityRAF"])
55369
55369
  return 0
55370
+
55371
+
55372
+ __exports__ = ("HCCConditions",)
@@ -0,0 +1 @@
1
+ __exports__ = ()
@@ -31,3 +31,6 @@ class StatinAllergen(ValueSet):
31
31
  SNOMEDCT = {
32
32
  "372912004", # Substance with 3-hydroxy-3-methylglutaryl-coenzyme A reductase inhibitor mechanism of action (substance)
33
33
  }
34
+
35
+
36
+ __exports__ = ("StatinAllergen",)
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -230,3 +232,6 @@ class StatinAllergen(ValueSet):
230
232
  SNOMEDCT = {
231
233
  "372912004", # Substance with 3-hydroxy-3-methylglutaryl-coenzyme A reductase inhibitor mechanism of action (substance)
232
234
  }
235
+
236
+
237
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -213,3 +215,6 @@ class HistoryOfHipFractureInParent(ValueSet):
213
215
  "445121000124105", # Family history of paternal hip fracture (situation)
214
216
  "445501000124107", # Family history of hip fracture in parent (situation)
215
217
  }
218
+
219
+
220
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -323,3 +325,6 @@ class ConsultantReport(ValueSet):
323
325
  "371531000", # Report of clinical encounter (record artifact)
324
326
  "371545006", # Confirmatory consultation report (record artifact)
325
327
  }
328
+
329
+
330
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -40652,3 +40654,6 @@ class UrinaryRetention(ValueSet):
40652
40654
  "267064002", # Retention of urine (disorder)
40653
40655
  "12245681000119103", # Postprocedural retention of urine (disorder)
40654
40656
  }
40657
+
40658
+
40659
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -172,3 +174,6 @@ class CardiacPacer(ValueSet):
172
174
  "360128001", # Intravenous triggered cardiac pacemaker system (physical object)
173
175
  "424921004", # Permanent cardiac pacemaker, device (physical object)
174
176
  }
177
+
178
+
179
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -4965,3 +4967,6 @@ class DexaDualEnergyXrayAbsorptiometry_BoneDensityForUrologyCare(ValueSet):
4965
4967
  "38265-5", # DXA Radius and Ulna [T-score] Bone density
4966
4968
  "38268-9", # DXA Skeletal system Views for bone density
4967
4969
  }
4970
+
4971
+
4972
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -2562,3 +2564,6 @@ class HospitalServicesForUrologyCare(ValueSet):
2562
2564
  "99283", # Emergency department visit for the evaluation and management of a patient, which requires these 3 key components: An expanded problem focused history; An expanded problem focused examination; and Medical decision making of moderate complexity. Counseling and/or coordination of care with other physicians, other qualified health care professionals, or agencies are provided consistent with the nature of the problem(s) and the patient's and/or family's needs. Usually, the presenting problem(s) are of moderate severity.
2563
2565
  "99284", # Emergency department visit for the evaluation and management of a patient, which requires these 3 key components: A detailed history; A detailed examination; and Medical decision making of moderate complexity. Counseling and/or coordination of care with other physicians, other qualified health care professionals, or agencies are provided consistent with the nature of the problem(s) and the patient's and/or family's needs. Usually, the presenting problem(s) are of high severity, and require urgent evaluation by the physician, or other qualified health care professionals but do not pose an immediate significant threat to life or physiologic function.
2564
2566
  }
2567
+
2568
+
2569
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -339,3 +341,6 @@ class PneumococcalPolysaccharide23Vaccine(ValueSet):
339
341
  "33", # pneumococcal polysaccharide vaccine, 23 valent
340
342
  "109", # pneumococcal vaccine, unspecified formulation
341
343
  }
344
+
345
+
346
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -311,3 +313,6 @@ class White(ValueSet):
311
313
  CDCREC = {
312
314
  "2106-3", # White
313
315
  }
316
+
317
+
318
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -1330,3 +1332,6 @@ class ReferralsWhereWeightAssessmentMayOccur(ValueSet):
1330
1332
  "408289007", # Refer to weight management program (procedure)
1331
1333
  "416790000", # Referral for home physical therapy (procedure)
1332
1334
  }
1335
+
1336
+
1337
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -1248,3 +1250,6 @@ class HumanImmunodeficiencyVirusHivLaboratoryTestCodesAbAndAg(ValueSet):
1248
1250
  "9669-3", # HIV 1 p66 Ab [Presence] in Serum by Immunoblot
1249
1251
  "9821-0", # HIV 1 p24 Ag [Presence] in Serum
1250
1252
  }
1253
+
1254
+
1255
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -5128,3 +5130,6 @@ class MedicationsForBelowNormalBmi(ValueSet):
5128
5130
  "860221", # megestrol acetate 40 MG Oral Tablet
5129
5131
  "860225", # megestrol acetate 40 MG/ML Oral Suspension
5130
5132
  }
5133
+
5134
+
5135
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -199,3 +201,6 @@ class BmiRatio(ValueSet):
199
201
  LOINC = {
200
202
  "39156-5", # Body mass index (BMI) [Ratio]
201
203
  }
204
+
205
+
206
+ __exports__ = get_overrides(locals().copy())
@@ -1,3 +1,5 @@
1
+ from canvas_sdk.value_set._utilities import get_overrides
2
+
1
3
  from ..value_set import ValueSet
2
4
 
3
5
 
@@ -4037,3 +4039,6 @@ class FluorideVarnishApplicationForChildren(ValueSet):
4037
4039
  "234723000", # Topical application of fluoride - tooth (procedure)
4038
4040
  "313042009", # Application of dental fluoride varnish (procedure)
4039
4041
  }
4042
+
4043
+
4044
+ __exports__ = get_overrides(locals().copy())
@@ -174,3 +174,6 @@ class FrailtySymptom(ValueSet):
174
174
  "16018431000119109", # Paresis of right lower limb (finding)
175
175
  "16419651000119103", # Dependence on biphasic positive airway pressure ventilation due to central sleep apnea syndrome (finding)
176
176
  }
177
+
178
+
179
+ __exports__ = ("FrailtySymptom",)
@@ -110,3 +110,12 @@ class ValueSet(CodeConstantsURLMappingMixin, metaclass=ValueSystems):
110
110
  for system in cls.CODE_SYSTEM_MAPPING
111
111
  if hasattr(cls, system)
112
112
  }
113
+
114
+
115
+ __exports__ = (
116
+ "CodeConstants",
117
+ "CodeConstantsURLMappingMixin",
118
+ "CombinedValueSet",
119
+ "ValueSystems",
120
+ "ValueSet",
121
+ )
@@ -0,0 +1 @@
1
+ __exports__ = ()
logger/__init__.py CHANGED
@@ -1,3 +1,5 @@
1
1
  from logger.logger import PluginLogger
2
2
 
3
3
  log = PluginLogger()
4
+
5
+ __exports__ = ("log",)
logger/logger.py CHANGED
@@ -70,3 +70,6 @@ class PluginLogger:
70
70
  def critical(self, message: Any) -> None:
71
71
  """Logs a critical message."""
72
72
  self.logger.critical(message)
73
+
74
+
75
+ __exports__ = ()
@@ -20,7 +20,7 @@ def aws_sig_v4_headers(
20
20
  ) -> dict[str, str]:
21
21
  """Constructs signed headers for use in requests made to AWS."""
22
22
  algorithm = "AWS4-HMAC-SHA256"
23
- now = datetime.datetime.utcnow()
23
+ now = datetime.datetime.now(datetime.UTC)
24
24
  amzdate = now.strftime("%Y%m%dT%H%M%SZ")
25
25
  datestamp = now.strftime("%Y%m%d")
26
26
  payload_hash = hashlib.sha256(payload).hexdigest()
@@ -0,0 +1,202 @@
1
+ #!/usr/bin/env uv run
2
+
3
+ import json
4
+ import logging
5
+ import re
6
+ import sys
7
+ import traceback
8
+ from collections import defaultdict
9
+ from contextlib import redirect_stderr, redirect_stdout
10
+ from glob import glob
11
+ from io import StringIO
12
+ from pathlib import Path
13
+ from textwrap import indent
14
+
15
+ import httpretty
16
+
17
+ from canvas_generated.messages.events_pb2 import PLUGIN_CREATED
18
+ from canvas_generated.messages.events_pb2 import Event as EventRequest
19
+ from canvas_sdk.events.base import Event
20
+ from canvas_sdk.protocols.base import BaseProtocol
21
+ from canvas_sdk.utils import stats
22
+ from plugin_runner.plugin_runner import LOADED_PLUGINS, load_or_reload_plugin
23
+
24
+ stats.STATS_ENABLED = False
25
+
26
+ ORIGINAL_PATH = sys.path.copy()
27
+
28
+
29
+ def enable_httpretty() -> None:
30
+ """
31
+ Prevent any HTTP requests from being made.
32
+ """
33
+ httpretty.enable(verbose=True, allow_net_connect=False)
34
+
35
+ for method in [
36
+ httpretty.GET,
37
+ httpretty.PUT,
38
+ httpretty.POST,
39
+ httpretty.DELETE,
40
+ httpretty.HEAD,
41
+ httpretty.PATCH,
42
+ httpretty.OPTIONS,
43
+ httpretty.CONNECT,
44
+ ]:
45
+ httpretty.register_uri(method, re.compile(r".*"), body="{}")
46
+
47
+
48
+ def disable_httpretty() -> None:
49
+ """
50
+ Allow normal HTTP activity.
51
+ """
52
+ httpretty.disable()
53
+ httpretty.reset()
54
+
55
+
56
+ def main() -> None:
57
+ """
58
+ Iterate through all of our plugins to verify they work with this version of the SDK.
59
+ """
60
+ if len(sys.argv) < 2:
61
+ print("You must specify a base path.")
62
+ sys.exit(1)
63
+
64
+ base_path = sys.argv[1]
65
+
66
+ for folder in glob(f"{base_path}/**/*"):
67
+ path = Path(folder)
68
+
69
+ if "{{" in folder:
70
+ print(f"Ignoring templated path: {folder}")
71
+ continue
72
+
73
+ if not path.is_dir():
74
+ continue
75
+
76
+ if not (path / "CANVAS_MANIFEST.json").exists():
77
+ print(f"Missing CANVAS_MANIFEST.json in {folder}")
78
+ continue
79
+
80
+ sys.path = ORIGINAL_PATH.copy()
81
+
82
+ # this makes plugin imports work and mirrors what the plugin_runner does
83
+ sys.path.append((Path(".") / path.parent).as_posix())
84
+
85
+ print(path)
86
+
87
+ output = StringIO()
88
+
89
+ plugin_runner_logger = logging.getLogger("plugin_runner_logger")
90
+ old_handlers = plugin_runner_logger.handlers.copy()
91
+ plugin_runner_logger.handlers = [logging.StreamHandler(output)]
92
+
93
+ with redirect_stdout(output), redirect_stderr(output):
94
+ success = load_or_reload_plugin(path)
95
+
96
+ output_string = output.getvalue()
97
+
98
+ if not success:
99
+ print()
100
+ print(indent(output_string, prefix=" ").rstrip())
101
+ print()
102
+
103
+ plugin_runner_logger.handlers = old_handlers
104
+
105
+ enable_httpretty()
106
+
107
+ for key, plugin in LOADED_PLUGINS.items():
108
+ Klass: type[BaseProtocol] = plugin["class"]
109
+
110
+ if not hasattr(Klass, "compute") or not callable(Klass.compute):
111
+ print(f"Skipping {key} due to no compute method")
112
+
113
+ event_request = EventRequest(
114
+ type=PLUGIN_CREATED,
115
+ context=json.dumps(
116
+ {
117
+ "key": "test",
118
+ "fields": {
119
+ "coding": {"value": "test"},
120
+ "goal_statement": {"value": "test"},
121
+ "questionnaire": {"text": "test"},
122
+ "medication": {"extra": {"coding": "test"}},
123
+ "ordering_provider": {"value": "test"},
124
+ "text": "test",
125
+ },
126
+ "method": "GET",
127
+ "note_id": 5,
128
+ "note": {
129
+ "uuid": "b2bd0672-ab36-4eca-b105-884f976ae810",
130
+ "id": "b2bd0672-ab36-4eca-b105-884f976ae810",
131
+ },
132
+ "path": "https://test",
133
+ "patient_id": 5,
134
+ "patient": {"id": 5},
135
+ "results": [],
136
+ "search_term": "test",
137
+ "state": "LKD",
138
+ }
139
+ ),
140
+ target="b2bd0672-ab36-4eca-b105-884f976ae810",
141
+ target_type="Patient",
142
+ )
143
+ event = Event(event_request=event_request)
144
+
145
+ try:
146
+ klass = Klass(
147
+ event=event,
148
+ secrets=defaultdict(lambda: "test", {"sentinel": True}),
149
+ environment=defaultdict(lambda: "test", {"sentinel": True}),
150
+ )
151
+ except TypeError as e:
152
+ print(f"Failed to instantiate {key}:", e)
153
+ continue
154
+
155
+ plugin_runner_logger = logging.getLogger("plugin_runner_logger")
156
+ old_handlers = plugin_runner_logger.handlers.copy()
157
+ plugin_runner_logger.handlers = [logging.StreamHandler(output)]
158
+
159
+ output = StringIO()
160
+
161
+ error: Exception | None = None
162
+
163
+ try:
164
+ with redirect_stdout(output), redirect_stderr(output):
165
+ result = klass.compute()
166
+ except TypeError as e:
167
+ error = e
168
+ except KeyError as e:
169
+ error = e
170
+ except Exception as e:
171
+ error = e
172
+
173
+ plugin_runner_logger.handlers = old_handlers
174
+
175
+ result_count = len(result)
176
+ request_count = len(httpretty.latest_requests())
177
+
178
+ print(f"{key}: {result_count}/{request_count}")
179
+
180
+ if error:
181
+ print()
182
+
183
+ # abbreviate these, they come from not being able to access the database
184
+ if "fake_getaddrinfo" in str(error):
185
+ print(indent(str(error), prefix=" ").rstrip())
186
+ else:
187
+ print(indent("".join(traceback.format_exception(error)), prefix=" ").rstrip())
188
+
189
+ print()
190
+
191
+ output_string = output.getvalue()
192
+
193
+ if output_string:
194
+ print()
195
+ print(indent(output_string, prefix=" ").rstrip())
196
+ print()
197
+
198
+ disable_httpretty()
199
+
200
+
201
+ if __name__ == "__main__":
202
+ main()