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
@@ -132,3 +132,13 @@ class CheckboxQuestion(BaseQuestion):
132
132
  self.response.append(
133
133
  {"text": option.name, "value": option.dbid, "comment": comment, "selected": selected}
134
134
  )
135
+
136
+
137
+ __exports__ = (
138
+ "ResponseOption",
139
+ "BaseQuestion",
140
+ "TextQuestion",
141
+ "IntegerQuestion",
142
+ "RadioQuestion",
143
+ "CheckboxQuestion",
144
+ )
@@ -47,3 +47,6 @@ class ReasonForVisitCommand(_BaseCommand):
47
47
  # the commands api does not include the 'structured' field in the fields response
48
48
  command_schema.pop("structured")
49
49
  return command_schema
50
+
51
+
52
+ __exports__ = ("ReasonForVisitCommand",)
@@ -48,3 +48,6 @@ class ReferCommand(BaseCommand):
48
48
  values["service_provider"] = self.service_provider.__dict__
49
49
 
50
50
  return values
51
+
52
+
53
+ __exports__ = ("ReferCommand",)
@@ -43,3 +43,6 @@ class RefillCommand(PrescribeCommand):
43
43
  )
44
44
 
45
45
  return errors
46
+
47
+
48
+ __exports__ = ("RefillCommand",)
@@ -16,3 +16,6 @@ class RemoveAllergyCommand(BaseCommand):
16
16
  json_schema_extra={"commands_api_name": "allergy"},
17
17
  )
18
18
  narrative: str | None = None
19
+
20
+
21
+ __exports__ = ("RemoveAllergyCommand",)
@@ -41,3 +41,6 @@ class ResolveConditionCommand(BaseCommand):
41
41
  )
42
42
 
43
43
  return errors
44
+
45
+
46
+ __exports__ = ("ResolveConditionCommand",)
@@ -7,3 +7,6 @@ class ReviewOfSystemsCommand(QuestionnaireCommand):
7
7
  class Meta:
8
8
  key = "ros"
9
9
  commit_required_fields = ("questionnaire_id",)
10
+
11
+
12
+ __exports__ = ("ReviewOfSystemsCommand",)
@@ -15,3 +15,6 @@ class StopMedicationCommand(_BaseCommand):
15
15
  default=None, json_schema_extra={"commands_api_name": "medication"}
16
16
  )
17
17
  rationale: str | None = None
18
+
19
+
20
+ __exports__ = ("StopMedicationCommand",)
@@ -7,3 +7,6 @@ class StructuredAssessmentCommand(QuestionnaireCommand):
7
7
  class Meta:
8
8
  key = "structuredAssessment"
9
9
  commit_required_fields = ("questionnaire_id",)
10
+
11
+
12
+ __exports__ = ("StructuredAssessmentCommand",)
@@ -39,3 +39,10 @@ class TaskCommand(BaseCommand):
39
39
  comment: str | None = None
40
40
  labels: list[str] | None = None
41
41
  linked_items_urns: list[str] | None = None
42
+
43
+
44
+ __exports__ = (
45
+ "AssigneeType",
46
+ "TaskAssigner",
47
+ "TaskCommand",
48
+ )
@@ -15,3 +15,6 @@ class UpdateDiagnosisCommand(BaseCommand):
15
15
  new_condition_code: str | None = None
16
16
  background: str | None = None
17
17
  narrative: str | None = None
18
+
19
+
20
+ __exports__ = ("UpdateDiagnosisCommand",)
@@ -36,3 +36,6 @@ class UpdateGoalCommand(_BaseCommand):
36
36
  achievement_status: AchievementStatus | None = None
37
37
  priority: Priority | None = None
38
38
  progress: str | None = None
39
+
40
+
41
+ __exports__ = ("UpdateGoalCommand",)
@@ -52,3 +52,6 @@ class VitalsCommand(BaseCommand):
52
52
  respiration_rate: conint(ge=6, le=60) | None = None # type: ignore[valid-type]
53
53
  oxygen_saturation: conint(ge=60, le=100) | None = None # type: ignore[valid-type]
54
54
  note: constr(max_length=150) | None = None # type: ignore[valid-type]
55
+
56
+
57
+ __exports__ = ("VitalsCommand",)
@@ -50,3 +50,11 @@ class ServiceProvider(Model):
50
50
  business_phone: str | None = Field(max_length=512, default=None)
51
51
  business_address: str | None = Field(max_length=512, default=None)
52
52
  notes: str | None = Field(max_length=512, default=None)
53
+
54
+
55
+ __exports__ = (
56
+ "CodeSystems",
57
+ "Coding",
58
+ "ClinicalQuantity",
59
+ "ServiceProvider",
60
+ )
@@ -2,4 +2,4 @@ from canvas_generated.messages.effects_pb2 import Effect, EffectType
2
2
 
3
3
  from .base import _BaseEffect
4
4
 
5
- __all__ = ("Effect", "EffectType", "_BaseEffect")
5
+ __all__ = __exports__ = ("Effect", "EffectType", "_BaseEffect")
@@ -1,4 +1,4 @@
1
1
  from canvas_sdk.effects.banner_alert.add_banner_alert import AddBannerAlert
2
2
  from canvas_sdk.effects.banner_alert.remove_banner_alert import RemoveBannerAlert
3
3
 
4
- __all__ = ("AddBannerAlert", "RemoveBannerAlert")
4
+ __all__ = __exports__ = ("AddBannerAlert", "RemoveBannerAlert")
@@ -59,3 +59,6 @@ class AddBannerAlert(_BaseEffect):
59
59
  "key": self.key,
60
60
  "data": self.values,
61
61
  }
62
+
63
+
64
+ __exports__ = ("AddBannerAlert",)
@@ -19,3 +19,6 @@ class RemoveBannerAlert(_BaseEffect):
19
19
  def effect_payload(self) -> dict[str, Any]:
20
20
  """The payload of the effect."""
21
21
  return {"patient": self.patient_id, "patient_filter": self.patient_filter, "key": self.key}
22
+
23
+
24
+ __exports__ = ("RemoveBannerAlert",)
@@ -26,3 +26,10 @@ class _BaseEffect(Model):
26
26
  def apply(self) -> Effect:
27
27
  self._validate_before_effect("apply")
28
28
  return Effect(type=self.Meta.effect_type, payload=json.dumps(self.effect_payload))
29
+
30
+
31
+ __exports__ = (
32
+ "_BaseEffect",
33
+ # Not defined here but used in a current plugin
34
+ "EffectType",
35
+ )
@@ -8,4 +8,8 @@ from canvas_sdk.effects.billing_line_item.update_billing_line_item import (
8
8
  UpdateBillingLineItem,
9
9
  )
10
10
 
11
- __all__ = ("AddBillingLineItem", "UpdateBillingLineItem", "RemoveBillingLineItem")
11
+ __all__ = __exports__ = (
12
+ "AddBillingLineItem",
13
+ "UpdateBillingLineItem",
14
+ "RemoveBillingLineItem",
15
+ )
@@ -36,3 +36,6 @@ class AddBillingLineItem(_BaseEffect):
36
36
  "note_id": self.note_id,
37
37
  "data": self.values,
38
38
  }
39
+
40
+
41
+ __exports__ = ("AddBillingLineItem",)
@@ -20,3 +20,6 @@ class RemoveBillingLineItem(_BaseEffect):
20
20
  return {
21
21
  "billing_line_item_id": self.billing_line_item_id,
22
22
  }
23
+
24
+
25
+ __exports__ = ("RemoveBillingLineItem",)
@@ -42,3 +42,6 @@ class UpdateBillingLineItem(_BaseEffect):
42
42
  "billing_line_item_id": self.billing_line_item_id,
43
43
  "data": self.values,
44
44
  }
45
+
46
+
47
+ __exports__ = ("UpdateBillingLineItem",)
@@ -34,3 +34,6 @@ class LaunchModalEffect(_BaseEffect):
34
34
  raise ValueError("'url' and 'content' are mutually exclusive")
35
35
 
36
36
  return self
37
+
38
+
39
+ __exports__ = ("LaunchModalEffect",)
@@ -38,3 +38,6 @@ class PatientChartSummaryConfiguration(_BaseEffect):
38
38
  def effect_payload(self) -> dict[str, Any]:
39
39
  """The payload of the effect."""
40
40
  return {"data": self.values}
41
+
42
+
43
+ __exports__ = ("PatientChartSummaryConfiguration",)
@@ -0,0 +1 @@
1
+ __exports__ = ()
@@ -20,3 +20,6 @@ class PatientPortalApplicationConfiguration(_BaseEffect):
20
20
  def effect_payload(self) -> dict[str, Any]:
21
21
  """The payload of the effect."""
22
22
  return {"data": self.values}
23
+
24
+
25
+ __exports__ = ("PatientPortalApplicationConfiguration",)
@@ -29,3 +29,6 @@ class FormResult(_BaseEffect):
29
29
  def effect_payload(self) -> dict[str, Any]:
30
30
  """The payload of the effect."""
31
31
  return {"data": self.values}
32
+
33
+
34
+ __exports__ = ("FormResult",)
@@ -34,3 +34,6 @@ class PatientPortalMenuConfiguration(_BaseEffect):
34
34
  def effect_payload(self) -> dict[str, Any]:
35
35
  """The payload of the effect."""
36
36
  return {"data": self.values}
37
+
38
+
39
+ __exports__ = ("PatientPortalMenuConfiguration",)
@@ -9,7 +9,8 @@ from canvas_sdk.effects.base import EffectType, _BaseEffect
9
9
 
10
10
  class PatientProfileConfiguration(_BaseEffect):
11
11
  """
12
- An Effect that will decide which sections appear, and if they start expanded, on the patient's profile in Canvas.
12
+ An Effect that will decide which sections appear, and if they start expanded,
13
+ on the patient's profile in Canvas.
13
14
  """
14
15
 
15
16
  class Meta:
@@ -17,6 +18,7 @@ class PatientProfileConfiguration(_BaseEffect):
17
18
 
18
19
  class Section(Enum):
19
20
  DEMOGRAPHICS = "demographics"
21
+ PORTAL = "portal"
20
22
  PREFERENCES = "preferences"
21
23
  PREFERRED_PHARMACIES = "preferred_pharmacies"
22
24
  PATIENT_CONSENTS = "patient_consents"
@@ -41,3 +43,6 @@ class PatientProfileConfiguration(_BaseEffect):
41
43
  def effect_payload(self) -> dict[str, Any]:
42
44
  """The payload of the effect."""
43
45
  return {"data": self.values}
46
+
47
+
48
+ __exports__ = ("PatientProfileConfiguration",)
@@ -1,3 +1,3 @@
1
1
  from canvas_sdk.effects.protocol_card.protocol_card import ProtocolCard, Recommendation
2
2
 
3
- __all__ = ("ProtocolCard", "Recommendation")
3
+ __all__ = __exports__ = ("ProtocolCard", "Recommendation")
@@ -93,3 +93,9 @@ class ProtocolCard(_BaseEffect):
93
93
  title=title, button=button, href=href, command=command, context=context
94
94
  )
95
95
  self.recommendations.append(recommendation)
96
+
97
+
98
+ __exports__ = (
99
+ "Recommendation",
100
+ "ProtocolCard",
101
+ )
@@ -27,3 +27,6 @@ class CreateQuestionnaireResult(_BaseEffect):
27
27
  "code_system": self.code_system,
28
28
  "code": self.code,
29
29
  }
30
+
31
+
32
+ __exports__ = ("CreateQuestionnaireResult",)
@@ -0,0 +1,46 @@
1
+ from typing import Any
2
+
3
+ from pydantic_core import InitErrorDetails
4
+
5
+ from canvas_sdk.effects.base import EffectType, _BaseEffect
6
+ from canvas_sdk.v1.data import CanvasUser
7
+
8
+
9
+ class SendInviteEffect(_BaseEffect):
10
+ """
11
+ An Effect that will send an invitation for the Patient Portal.
12
+ """
13
+
14
+ class Meta:
15
+ effect_type = EffectType.PATIENT_PORTAL__SEND_INVITE
16
+
17
+ user_dbid: int
18
+
19
+ @property
20
+ def values(self) -> dict[str, Any]:
21
+ """The user's id."""
22
+ return {"user_dbid": self.user_dbid}
23
+
24
+ @property
25
+ def effect_payload(self) -> dict[str, Any]:
26
+ """The payload of the effect."""
27
+ return {"data": self.values}
28
+
29
+ def _get_error_details(self, method: Any) -> list[InitErrorDetails]:
30
+ errors = super()._get_error_details(method)
31
+
32
+ user_exists = CanvasUser.objects.filter(dbid=self.user_dbid).exists()
33
+
34
+ if not user_exists:
35
+ errors.append(
36
+ self._create_error_detail(
37
+ "value",
38
+ "User does not exist",
39
+ self.user_dbid,
40
+ )
41
+ )
42
+
43
+ return errors
44
+
45
+
46
+ __exports__ = ("SendInviteEffect",)
@@ -27,3 +27,6 @@ class ShowButtonEffect(_BaseEffect):
27
27
  def effect_payload(self) -> dict[str, Any]:
28
28
  """The payload of the effect."""
29
29
  return {"data": self.values}
30
+
31
+
32
+ __exports__ = ("ShowButtonEffect",)
@@ -81,3 +81,12 @@ class HTMLResponse(Response):
81
81
  headers: Mapping[str, Any] | None = None,
82
82
  ):
83
83
  super().__init__(content.encode(), status_code, headers, content_type="text/html")
84
+
85
+
86
+ __exports__ = (
87
+ "JSON",
88
+ "Response",
89
+ "JSONResponse",
90
+ "PlainTextResponse",
91
+ "HTMLResponse",
92
+ )
@@ -4,8 +4,8 @@ from .surescripts_messages import (
4
4
  SendSurescriptsMedicationHistoryRequestEffect,
5
5
  )
6
6
 
7
- __all__ = [
7
+ __all__ = __exports__ = (
8
8
  "SendSurescriptsBenefitsRequestEffect",
9
9
  "SendSurescriptsEligibilityRequestEffect",
10
10
  "SendSurescriptsMedicationHistoryRequestEffect",
11
- ]
11
+ )
@@ -91,3 +91,10 @@ class SendSurescriptsBenefitsRequestEffect(_BaseEffect):
91
91
  def effect_payload(self) -> dict[str, Any]:
92
92
  """Benefits Request effect payload."""
93
93
  return self.values
94
+
95
+
96
+ __exports__ = (
97
+ "SendSurescriptsBenefitsRequestEffect",
98
+ "SendSurescriptsEligibilityRequestEffect",
99
+ "SendSurescriptsMedicationHistoryRequestEffect",
100
+ )
@@ -1,3 +1,8 @@
1
1
  from .task import AddTask, AddTaskComment, TaskStatus, UpdateTask
2
2
 
3
- __all__ = ["AddTask", "AddTaskComment", "TaskStatus", "UpdateTask"]
3
+ __all__ = __exports__ = (
4
+ "AddTask",
5
+ "AddTaskComment",
6
+ "TaskStatus",
7
+ "UpdateTask",
8
+ )
@@ -100,3 +100,11 @@ class UpdateTask(_BaseEffect):
100
100
  else:
101
101
  value_dict[field] = getattr(self, field)
102
102
  return value_dict
103
+
104
+
105
+ __exports__ = (
106
+ "AddTask",
107
+ "AddTaskComment",
108
+ "TaskStatus",
109
+ "UpdateTask",
110
+ )
@@ -0,0 +1,81 @@
1
+ from typing import Any, Self
2
+
3
+ from pydantic import model_validator
4
+ from pydantic_core import InitErrorDetails
5
+
6
+ from canvas_sdk.effects.base import EffectType, _BaseEffect
7
+ from canvas_sdk.v1.data import CanvasUser
8
+
9
+
10
+ class UpdateUserEffect(_BaseEffect):
11
+ """
12
+ An Effect that will update the user properties.
13
+ """
14
+
15
+ class Meta:
16
+ effect_type = EffectType.UPDATE_USER
17
+
18
+ # A set to track which fields have been modified.
19
+ _dirty_keys: set[str] = set()
20
+
21
+ def __init__(self, /, **data: Any) -> None:
22
+ super().__init__(**data)
23
+ self._dirty_keys = set()
24
+ self._dirty_keys.update(data.keys())
25
+
26
+ def __setattr__(self, name: str, value: Any) -> None:
27
+ """Set an attribute and mark it as dirty unless excluded."""
28
+ if not name.startswith("_"):
29
+ self._dirty_keys.add(name)
30
+ super().__setattr__(name, value)
31
+
32
+ def is_dirty(self, key: str) -> bool:
33
+ """Returns True if the given property has been modified (i.e. marked as dirty), False otherwise."""
34
+ return key in self._dirty_keys
35
+
36
+ user_dbid: int
37
+ email: str | None = None
38
+ phone_number: str | None = None
39
+
40
+ @property
41
+ def values(self) -> dict[str, Any]:
42
+ """The user's values."""
43
+ result = {}
44
+
45
+ for key in self._dirty_keys:
46
+ result[key] = getattr(self, key)
47
+
48
+ result["dbid"] = self.user_dbid
49
+ return result
50
+
51
+ @property
52
+ def effect_payload(self) -> dict[str, Any]:
53
+ """The payload of the effect."""
54
+ return {"data": self.values}
55
+
56
+ @model_validator(mode="after")
57
+ def check_exclusive_fields(self) -> Self:
58
+ """Check that at least one of mutually exclusive field is set."""
59
+ if self.email is None and self.phone_number is None:
60
+ raise ValueError("one of 'email', 'phone_number' is required")
61
+
62
+ return self
63
+
64
+ def _get_error_details(self, method: Any) -> list[InitErrorDetails]:
65
+ errors = super()._get_error_details(method)
66
+
67
+ user_exists = CanvasUser.objects.filter(dbid=self.user_dbid).exists()
68
+
69
+ if not user_exists:
70
+ errors.append(
71
+ self._create_error_detail(
72
+ "value",
73
+ "User does not exist",
74
+ self.user_dbid,
75
+ )
76
+ )
77
+
78
+ return errors
79
+
80
+
81
+ __exports__ = ("UpdateUserEffect",)
@@ -1,3 +1,3 @@
1
1
  from .portal_widget import PortalWidget
2
2
 
3
- __all__ = ["PortalWidget"]
3
+ __all__ = __exports__ = ("PortalWidget",)
@@ -74,3 +74,6 @@ class PortalWidget(_BaseEffect):
74
74
  )
75
75
 
76
76
  return errors
77
+
78
+
79
+ __exports__ = ("PortalWidget",)
@@ -3,4 +3,9 @@ from canvas_generated.messages.events_pb2 import EventResponse, EventType
3
3
 
4
4
  from .base import Event
5
5
 
6
- __all__ = ("EventRequest", "EventResponse", "EventType", "Event")
6
+ __all__ = __exports__ = (
7
+ "EventRequest",
8
+ "EventResponse",
9
+ "EventType",
10
+ "Event",
11
+ )
canvas_sdk/events/base.py CHANGED
@@ -46,3 +46,6 @@ class Event:
46
46
  self.name = EventType.Name(self.type)
47
47
  self.context = context
48
48
  self.target = TargetType(id=event_request.target, type=target_model)
49
+
50
+
51
+ __exports__ = ("TargetType", "Event")
@@ -1,3 +1,3 @@
1
1
  from canvas_sdk.handlers.base import BaseHandler
2
2
 
3
- __all__ = ("BaseHandler",)
3
+ __all__ = __exports__ = ("BaseHandler",)
@@ -78,3 +78,9 @@ class ActionButton(BaseHandler):
78
78
  return self.handle()
79
79
 
80
80
  return []
81
+
82
+
83
+ __exports__ = (
84
+ "SHOW_BUTTON_REGEX",
85
+ "ActionButton",
86
+ )
@@ -27,3 +27,6 @@ class Application(BaseHandler, ABC):
27
27
  def identifier(self) -> str:
28
28
  """The application identifier."""
29
29
  return f"{self.__class__.__module__}:{self.__class__.__qualname__}"
30
+
31
+
32
+ __exports__ = ("Application",)
@@ -57,3 +57,6 @@ class BaseHandler(ABC):
57
57
  def accept_event(self) -> bool:
58
58
  """Determine whether an event should be accepted and handled by the handler."""
59
59
  return True
60
+
61
+
62
+ __exports__ = ("BaseHandler",)
@@ -33,3 +33,6 @@ class CronTask(BaseHandler):
33
33
  if datetime in Cron(self.SCHEDULE):
34
34
  return self.execute()
35
35
  return []
36
+
37
+
38
+ __exports__ = ("CronTask",)
@@ -12,7 +12,8 @@ from .security import (
12
12
  StaffSessionAuthMixin,
13
13
  )
14
14
 
15
- __all__ = [
15
+ __all__ = __exports__ = (
16
+ "api",
16
17
  "APIKeyAuthMixin",
17
18
  "APIKeyCredentials",
18
19
  "AuthSchemeMixin",
@@ -25,4 +26,4 @@ __all__ = [
25
26
  "SimpleAPI",
26
27
  "SimpleAPIRoute",
27
28
  "StaffSessionAuthMixin",
28
- ]
29
+ )
@@ -1,3 +1,4 @@
1
+ import inspect
1
2
  import json
2
3
  import re
3
4
  import traceback
@@ -334,7 +335,10 @@ class SimpleAPIBase(BaseHandler, ABC):
334
335
  """Authenticate the request."""
335
336
  try:
336
337
  # Create the credentials object
337
- credentials_cls = self.authenticate.__annotations__.get("credentials")
338
+ credentials_cls = inspect.get_annotations(self.authenticate, eval_str=True).get(
339
+ "credentials"
340
+ )
341
+
338
342
  if not credentials_cls or not issubclass(credentials_cls, Credentials):
339
343
  raise PluginError(
340
344
  f"Cannot determine authentication scheme for {self.request.path}; "
@@ -512,3 +516,24 @@ class SimpleAPIRoute(SimpleAPIBase, ABC):
512
516
  def patch(self) -> list[Response | Effect]:
513
517
  """Stub method for PATCH handler."""
514
518
  return []
519
+
520
+
521
+ __exports__ = (
522
+ "FormPart",
523
+ "StringFormPart",
524
+ "FileFormPart",
525
+ "parse_multipart_form",
526
+ "Request",
527
+ "SimpleAPIType",
528
+ "RouteHandler",
529
+ "get",
530
+ "post",
531
+ "put",
532
+ "delete",
533
+ "patch",
534
+ "SimpleAPIBase",
535
+ "SimpleAPI",
536
+ "SimpleAPIRoute",
537
+ # Not defined here but used in an existing plugin
538
+ "Credentials",
539
+ )
@@ -37,3 +37,13 @@ class InvalidCredentialsError(AuthenticationError):
37
37
 
38
38
  def __init__(self) -> None:
39
39
  super().__init__("Provided credentials are invalid")
40
+
41
+
42
+ __exports__ = (
43
+ "SimpleAPIException",
44
+ "AuthenticationError",
45
+ "NoAuthorizationHeaderError",
46
+ "AuthenticationSchemeError",
47
+ "InvalidCredentialsFormatError",
48
+ "InvalidCredentialsError",
49
+ )