canvas 0.18.0__tar.gz → 0.19.0__tar.gz

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 (335) hide show
  1. {canvas-0.18.0 → canvas-0.19.0}/PKG-INFO +1 -1
  2. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/validators/manifest_schema.py +12 -0
  3. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/reason_for_visit.py +18 -3
  4. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/tests/test_utils.py +15 -3
  5. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/tests/unit/tests.py +7 -16
  6. canvas-0.19.0/canvas_sdk/questionnaires/__init__.py +3 -0
  7. canvas-0.19.0/canvas_sdk/questionnaires/tests/test_utils.py +74 -0
  8. canvas-0.19.0/canvas_sdk/questionnaires/utils.py +117 -0
  9. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/templates/utils.py +7 -12
  10. canvas-0.19.0/canvas_sdk/utils/plugins.py +25 -0
  11. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/__init__.py +4 -1
  12. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/billing.py +29 -2
  13. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/coverage.py +1 -1
  14. canvas-0.19.0/canvas_sdk/v1/data/reason_for_visit.py +22 -0
  15. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/sandbox.py +6 -6
  16. canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json +52 -0
  17. canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md +11 -0
  18. canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/my_protocol.py +39 -0
  19. canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/questionnaires/example_questionnaire.yml +61 -0
  20. canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_render_template/protocols/__init__.py +0 -0
  21. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/test_plugin_runner.py +12 -12
  22. canvas-0.19.0/pubsub/__init__.py +0 -0
  23. {canvas-0.18.0 → canvas-0.19.0}/pyproject.toml +1 -1
  24. {canvas-0.18.0 → canvas-0.19.0}/.gitignore +0 -0
  25. {canvas-0.18.0 → canvas-0.19.0}/README.md +0 -0
  26. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/__init__.py +0 -0
  27. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/__init__.py +0 -0
  28. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/auth/__init__.py +0 -0
  29. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/auth/tests.py +0 -0
  30. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/auth/utils.py +0 -0
  31. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/__init__.py +0 -0
  32. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/emit.py +0 -0
  33. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_CREATED.ndjson +0 -0
  34. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_UPDATED.ndjson +0 -0
  35. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CANCELED.ndjson +0 -0
  36. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CHECKED_IN.ndjson +0 -0
  37. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CREATED.ndjson +0 -0
  38. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_NO_SHOWED.ndjson +0 -0
  39. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESCHEDULED.ndjson +0 -0
  40. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESTORED.ndjson +0 -0
  41. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_UPDATED.ndjson +0 -0
  42. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__CONDITION_SELECTED.ndjson +0 -0
  43. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_COMMIT.ndjson +0 -0
  44. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_ORIGINATE.ndjson +0 -0
  45. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_UPDATE.ndjson +0 -0
  46. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_COMMIT.ndjson +0 -0
  47. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  48. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_UPDATE.ndjson +0 -0
  49. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_CREATED.ndjson +0 -0
  50. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_UPDATED.ndjson +0 -0
  51. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/CONDITION_ASSESSED.ndjson +0 -0
  52. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/CONDITION_CREATED.ndjson +0 -0
  53. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/CONDITION_UPDATED.ndjson +0 -0
  54. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/CRON.ndjson +0 -0
  55. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ENCOUNTER_CREATED.ndjson +0 -0
  56. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/ENCOUNTER_UPDATED.ndjson +0 -0
  57. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_CREATED.ndjson +0 -0
  58. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_CREATED.ndjson +0 -0
  59. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_UPDATED.ndjson +0 -0
  60. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_UPDATED.ndjson +0 -0
  61. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/INTERVIEW_CREATED.ndjson +0 -0
  62. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/INTERVIEW_UPDATED.ndjson +0 -0
  63. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/LAB_ORDER_CREATED.ndjson +0 -0
  64. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/LAB_ORDER_UPDATED.ndjson +0 -0
  65. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_CREATED.ndjson +0 -0
  66. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_UPDATED.ndjson +0 -0
  67. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_COMMIT.ndjson +0 -0
  68. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_ORIGINATE.ndjson +0 -0
  69. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_UPDATE.ndjson +0 -0
  70. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_COMMIT.ndjson +0 -0
  71. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  72. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_UPDATE.ndjson +0 -0
  73. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT__MEDICATION__POST_SEARCH.ndjson +0 -0
  74. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/PATIENT_CREATED.ndjson +0 -0
  75. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/PATIENT_UPDATED.ndjson +0 -0
  76. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__POST_ORIGINATE.ndjson +0 -0
  77. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  78. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_COMMIT.ndjson +0 -0
  79. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_ORIGINATE.ndjson +0 -0
  80. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_UPDATE.ndjson +0 -0
  81. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_COMMIT.ndjson +0 -0
  82. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  83. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_UPDATE.ndjson +0 -0
  84. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE__QUESTIONNAIRE__POST_SEARCH.ndjson +0 -0
  85. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/TASK_COMMENT_CREATED.ndjson +0 -0
  86. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/TASK_CREATED.ndjson +0 -0
  87. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/TASK_UPDATED.ndjson +0 -0
  88. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_CREATED.ndjson +0 -0
  89. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_UPDATED.ndjson +0 -0
  90. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/logs/__init__.py +0 -0
  91. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/logs/logs.py +0 -0
  92. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/plugin/__init__.py +0 -0
  93. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/plugin/plugin.py +0 -0
  94. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/plugin/tests.py +0 -0
  95. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/run_plugins/__init__.py +0 -0
  96. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/apps/run_plugins/run_plugins.py +0 -0
  97. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/conftest.py +0 -0
  98. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/main.py +0 -0
  99. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/application/cookiecutter.json +0 -0
  100. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/CANVAS_MANIFEST.json +0 -0
  101. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/README.md +0 -0
  102. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/applications/__init__.py +0 -0
  103. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/applications/my_application.py +0 -0
  104. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/assets/python-logo.png +0 -0
  105. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/default/cookiecutter.json +0 -0
  106. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/CANVAS_MANIFEST.json +0 -0
  107. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/README.md +0 -0
  108. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/__init__.py +0 -0
  109. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py +0 -0
  110. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/tests.py +0 -0
  111. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/__init__.py +0 -0
  112. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/context/__init__.py +0 -0
  113. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/context/context.py +0 -0
  114. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/context/tests.py +0 -0
  115. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/print/__init__.py +0 -0
  116. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/print/print.py +0 -0
  117. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/print/tests.py +0 -0
  118. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/urls/__init__.py +0 -0
  119. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/urls/tests.py +0 -0
  120. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/urls/urls.py +0 -0
  121. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/validators/__init__.py +0 -0
  122. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/validators/tests.py +0 -0
  123. {canvas-0.18.0 → canvas-0.19.0}/canvas_cli/utils/validators/validators.py +0 -0
  124. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/effects_pb2.py +0 -0
  125. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/effects_pb2.pyi +0 -0
  126. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/effects_pb2_grpc.py +0 -0
  127. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/events_pb2.py +0 -0
  128. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/events_pb2.pyi +0 -0
  129. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/events_pb2_grpc.py +0 -0
  130. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/plugins_pb2.py +0 -0
  131. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/plugins_pb2.pyi +0 -0
  132. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/messages/plugins_pb2_grpc.py +0 -0
  133. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/services/plugin_runner_pb2.py +0 -0
  134. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/services/plugin_runner_pb2.pyi +0 -0
  135. {canvas-0.18.0 → canvas-0.19.0}/canvas_generated/services/plugin_runner_pb2_grpc.py +0 -0
  136. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/__init__.py +0 -0
  137. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/base.py +0 -0
  138. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/__init__.py +0 -0
  139. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/base.py +0 -0
  140. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/allergy.py +0 -0
  141. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/assess.py +0 -0
  142. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/close_goal.py +0 -0
  143. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/diagnose.py +0 -0
  144. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/exam.py +0 -0
  145. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/family_history.py +0 -0
  146. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/goal.py +0 -0
  147. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/history_present_illness.py +0 -0
  148. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/instruct.py +0 -0
  149. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/lab_order.py +0 -0
  150. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/medical_history.py +0 -0
  151. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/medication_statement.py +0 -0
  152. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/past_surgical_history.py +0 -0
  153. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/perform.py +0 -0
  154. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/plan.py +0 -0
  155. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/prescribe.py +0 -0
  156. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/questionnaire.py +0 -0
  157. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/refill.py +0 -0
  158. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/remove_allergy.py +0 -0
  159. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/review_of_systems.py +0 -0
  160. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/stop_medication.py +0 -0
  161. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/structured_assessment.py +0 -0
  162. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/task.py +0 -0
  163. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/update_diagnosis.py +0 -0
  164. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/update_goal.py +0 -0
  165. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/commands/vitals.py +0 -0
  166. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/constants.py +0 -0
  167. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/tests/protocol/__init__.py +0 -0
  168. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/tests/protocol/tests.py +0 -0
  169. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/tests/schema/__init__.py +0 -0
  170. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/tests/schema/tests.py +0 -0
  171. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/commands/tests/unit/__init__.py +0 -0
  172. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/__init__.py +0 -0
  173. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/banner_alert/__init__.py +0 -0
  174. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/banner_alert/add_banner_alert.py +0 -0
  175. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/banner_alert/remove_banner_alert.py +0 -0
  176. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/banner_alert/tests.py +0 -0
  177. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/base.py +0 -0
  178. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/launch_modal.py +0 -0
  179. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/patient_chart_summary_configuration.py +0 -0
  180. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/patient_portal/__init__.py +0 -0
  181. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/patient_portal/intake_form_results.py +0 -0
  182. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/patient_profile_configuration.py +0 -0
  183. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/protocol_card/__init__.py +0 -0
  184. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/protocol_card/protocol_card.py +0 -0
  185. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/protocol_card/tests.py +0 -0
  186. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/questionnaire_result.py +0 -0
  187. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/show_button.py +0 -0
  188. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/surescripts/__init__.py +0 -0
  189. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/surescripts/surescripts_messages.py +0 -0
  190. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/task/__init__.py +0 -0
  191. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/effects/task/task.py +0 -0
  192. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/events/__init__.py +0 -0
  193. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/events/base.py +0 -0
  194. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/handlers/__init__.py +0 -0
  195. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/handlers/action_button.py +0 -0
  196. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/handlers/application.py +0 -0
  197. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/handlers/base.py +0 -0
  198. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/handlers/cron_task.py +0 -0
  199. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/protocols/__init__.py +0 -0
  200. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/protocols/base.py +0 -0
  201. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/protocols/clinical_quality_measure.py +0 -0
  202. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/protocols/timeframe.py +0 -0
  203. {canvas-0.18.0/canvas_sdk/templates → canvas-0.19.0/canvas_sdk/questionnaires}/tests/__init__.py +0 -0
  204. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/templates/__init__.py +0 -0
  205. {canvas-0.18.0/canvas_sdk → canvas-0.19.0/canvas_sdk/templates}/tests/__init__.py +0 -0
  206. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/templates/tests/test_utils.py +0 -0
  207. {canvas-0.18.0/canvas_sdk/v1 → canvas-0.19.0/canvas_sdk/tests}/__init__.py +0 -0
  208. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/utils/__init__.py +0 -0
  209. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/utils/db.py +0 -0
  210. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/utils/http.py +0 -0
  211. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/utils/stats.py +0 -0
  212. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/utils/tests.py +0 -0
  213. {canvas-0.18.0/canvas_sdk/value_set → canvas-0.19.0/canvas_sdk/v1}/__init__.py +0 -0
  214. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/apps.py +0 -0
  215. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/allergy_intolerance.py +0 -0
  216. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/appointment.py +0 -0
  217. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/assessment.py +0 -0
  218. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/base.py +0 -0
  219. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/care_team.py +0 -0
  220. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/command.py +0 -0
  221. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/common.py +0 -0
  222. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/condition.py +0 -0
  223. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/detected_issue.py +0 -0
  224. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/device.py +0 -0
  225. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/imaging.py +0 -0
  226. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/lab.py +0 -0
  227. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/medication.py +0 -0
  228. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/note.py +0 -0
  229. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/observation.py +0 -0
  230. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/organization.py +0 -0
  231. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/patient.py +0 -0
  232. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/practicelocation.py +0 -0
  233. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/protocol_override.py +0 -0
  234. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/questionnaire.py +0 -0
  235. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/staff.py +0 -0
  236. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/task.py +0 -0
  237. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/team.py +0 -0
  238. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/data/user.py +0 -0
  239. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/v1/models.py +0 -0
  240. {canvas-0.18.0/canvas_sdk/value_set/v2022 → canvas-0.19.0/canvas_sdk/value_set}/__init__.py +0 -0
  241. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/custom.py +0 -0
  242. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/hcc2018.py +0 -0
  243. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/tests/test_value_sets.py +0 -0
  244. {canvas-0.18.0/canvas_sdk/views → canvas-0.19.0/canvas_sdk/value_set/v2022}/__init__.py +0 -0
  245. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/adverse_event.py +0 -0
  246. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/allergy.py +0 -0
  247. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/assessment.py +0 -0
  248. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/communication.py +0 -0
  249. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/condition.py +0 -0
  250. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/device.py +0 -0
  251. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/diagnostic_study.py +0 -0
  252. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/encounter.py +0 -0
  253. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/immunization.py +0 -0
  254. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/individual_characteristic.py +0 -0
  255. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/intervention.py +0 -0
  256. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/laboratory_test.py +0 -0
  257. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/medication.py +0 -0
  258. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/physical_exam.py +0 -0
  259. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/procedure.py +0 -0
  260. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/v2022/symptom.py +0 -0
  261. {canvas-0.18.0 → canvas-0.19.0}/canvas_sdk/value_set/value_set.py +0 -0
  262. {canvas-0.18.0/plugin_runner → canvas-0.19.0/canvas_sdk/views}/__init__.py +0 -0
  263. {canvas-0.18.0 → canvas-0.19.0}/logger/__init__.py +0 -0
  264. {canvas-0.18.0 → canvas-0.19.0}/logger/logger.py +0 -0
  265. {canvas-0.18.0/plugin_runner/tests → canvas-0.19.0/plugin_runner}/__init__.py +0 -0
  266. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/authentication.py +0 -0
  267. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/aws_headers.py +0 -0
  268. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/exceptions.py +0 -0
  269. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/plugin_installer.py +0 -0
  270. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/plugin_runner.py +0 -0
  271. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/example_plugin → canvas-0.19.0/plugin_runner/tests}/__init__.py +0 -0
  272. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/data/plugins/.gitkeep +0 -0
  273. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json +0 -0
  274. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/example_plugin/README.md +0 -0
  275. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/example_plugin/protocols → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/example_plugin}/__init__.py +0 -0
  276. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/example_plugin}/protocols/__init__.py +0 -0
  277. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py +0 -0
  278. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json +0 -0
  279. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md +0 -0
  280. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols}/__init__.py +0 -0
  281. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/my_protocol.py +0 -0
  282. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/__init__.py +0 -0
  283. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/base.py +0 -0
  284. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/__init__.py +0 -0
  285. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/base.py +0 -0
  286. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_load_questionnaire}/protocols/__init__.py +0 -0
  287. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json +0 -0
  288. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md +0 -0
  289. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin}/other_module/__init__.py +0 -0
  290. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module/base.py +0 -0
  291. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin}/protocols/__init__.py +0 -0
  292. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/my_protocol.py +0 -0
  293. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json +0 -0
  294. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md +0 -0
  295. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1 → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin}/other_module/__init__.py +0 -0
  296. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/other_module/base.py +0 -0
  297. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1 → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin}/protocols/__init__.py +0 -0
  298. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/my_protocol.py +0 -0
  299. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json +0 -0
  300. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md +0 -0
  301. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2 → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1}/other_module/__init__.py +0 -0
  302. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/base.py +0 -0
  303. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2 → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1}/protocols/__init__.py +0 -0
  304. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py +0 -0
  305. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json +0 -0
  306. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md +0 -0
  307. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3 → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2}/other_module/__init__.py +0 -0
  308. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/base.py +0 -0
  309. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3 → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2}/protocols/__init__.py +0 -0
  310. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py +0 -0
  311. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json +0 -0
  312. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md +0 -0
  313. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3}/other_module/__init__.py +0 -0
  314. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/base.py +0 -0
  315. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3}/protocols/__init__.py +0 -0
  316. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py +0 -0
  317. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json +0 -0
  318. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md +0 -0
  319. {canvas-0.18.0/plugin_runner/tests/fixtures/plugins/test_render_template/protocols → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module}/__init__.py +0 -0
  320. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/base.py +0 -0
  321. {canvas-0.18.0/pubsub → canvas-0.19.0/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols}/__init__.py +0 -0
  322. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py +0 -0
  323. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json +0 -0
  324. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_render_template/README.md +0 -0
  325. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_render_template/protocols/my_protocol.py +0 -0
  326. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/fixtures/plugins/test_render_template/templates/template.html +0 -0
  327. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/test_application.py +0 -0
  328. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/test_plugin_installer.py +0 -0
  329. {canvas-0.18.0 → canvas-0.19.0}/plugin_runner/tests/test_sandbox.py +0 -0
  330. {canvas-0.18.0 → canvas-0.19.0}/protobufs/canvas_generated/messages/effects.proto +0 -0
  331. {canvas-0.18.0 → canvas-0.19.0}/protobufs/canvas_generated/messages/events.proto +0 -0
  332. {canvas-0.18.0 → canvas-0.19.0}/protobufs/canvas_generated/messages/plugins.proto +0 -0
  333. {canvas-0.18.0 → canvas-0.19.0}/protobufs/canvas_generated/services/plugin_runner.proto +0 -0
  334. {canvas-0.18.0 → canvas-0.19.0}/pubsub/pubsub.py +0 -0
  335. {canvas-0.18.0 → canvas-0.19.0}/settings.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: canvas
3
- Version: 0.18.0
3
+ Version: 0.19.0
4
4
  Summary: SDK to customize event-driven actions in your Canvas instance
5
5
  Author-email: Canvas Team <engineering@canvasmedical.com>
6
6
  License-Expression: MIT
@@ -16,6 +16,7 @@ manifest_schema = {
16
16
  "effects": {"$ref": "#/$defs/component"},
17
17
  "views": {"$ref": "#/$defs/component"},
18
18
  "applications": {"$ref": "#/$defs/applications"},
19
+ "questionnaires": {"$ref": "#/$defs/questionnaires"},
19
20
  },
20
21
  "additionalProperties": False,
21
22
  "minProperties": 1,
@@ -101,5 +102,16 @@ manifest_schema = {
101
102
  "additionalProperties": False,
102
103
  },
103
104
  },
105
+ "questionnaires": {
106
+ "type": "array",
107
+ "items": {
108
+ "type": "object",
109
+ "properties": {
110
+ "template": {"type": "string"},
111
+ },
112
+ "required": ["template"],
113
+ "additionalProperties": False,
114
+ },
115
+ },
104
116
  },
105
117
  }
@@ -1,9 +1,11 @@
1
1
  from typing import Literal
2
+ from uuid import UUID
2
3
 
3
4
  from pydantic_core import InitErrorDetails
4
5
 
5
6
  from canvas_sdk.commands.base import _BaseCommand
6
7
  from canvas_sdk.commands.constants import Coding
8
+ from canvas_sdk.v1.data import ReasonForVisitSettingCoding
7
9
 
8
10
 
9
11
  class ReasonForVisitCommand(_BaseCommand):
@@ -13,8 +15,7 @@ class ReasonForVisitCommand(_BaseCommand):
13
15
  key = "reasonForVisit"
14
16
 
15
17
  structured: bool = False
16
- # how do we make sure that coding is a valid rfv coding from their home-app?
17
- coding: Coding | None = None
18
+ coding: Coding | UUID | str | None = None
18
19
  comment: str | None = None
19
20
 
20
21
  def _get_error_details(
@@ -27,6 +28,16 @@ class ReasonForVisitCommand(_BaseCommand):
27
28
  "value", "Structured RFV should have a coding.", self.coding
28
29
  )
29
30
  )
31
+
32
+ if self.coding:
33
+ if isinstance(self.coding, str | UUID):
34
+ query = {"id": self.coding}
35
+ error_message = f"ReasonForVisitSettingCoding with id {self.coding} does not exist."
36
+ else:
37
+ query = {"code": self.coding["code"], "system": self.coding["system"]}
38
+ error_message = f"ReasonForVisitSettingCoding with code {self.coding['code']} and system {self.coding['system']} does not exist."
39
+ if not ReasonForVisitSettingCoding.objects.filter(**query).exists():
40
+ errors.append(self._create_error_detail("value", error_message, self.coding))
30
41
  return errors
31
42
 
32
43
  @classmethod
@@ -40,4 +51,8 @@ class ReasonForVisitCommand(_BaseCommand):
40
51
  @property
41
52
  def values(self) -> dict:
42
53
  """The ReasonForVisit command's field values."""
43
- return {"structured": self.structured, "coding": self.coding, "comment": self.comment}
54
+ return {
55
+ "structured": self.structured,
56
+ "coding": str(self.coding) if isinstance(self.coding, UUID) else self.coding,
57
+ "comment": self.comment,
58
+ }
@@ -37,6 +37,12 @@ from canvas_sdk.commands.constants import ClinicalQuantity, Coding
37
37
  runner = CliRunner()
38
38
 
39
39
 
40
+ class WrongType:
41
+ """A type to yield ValidationErrors in tests."""
42
+
43
+ wrong_field: str
44
+
45
+
40
46
  class MaskedValue:
41
47
  """A class to mask sensitive values in tests."""
42
48
 
@@ -97,6 +103,8 @@ def fake(field_props: dict, Command: type[_BaseCommand]) -> Any:
97
103
  return Coding(system=random_string(), code=random_string(), display=random_string())
98
104
  case "ClinicalQuantity":
99
105
  return ClinicalQuantity(representative_ndc="ndc", ncpdp_quantity_qualifier_code="code")
106
+ case "WrongType":
107
+ return WrongType()
100
108
  if t[0].isupper():
101
109
  return random.choice(list(getattr(Command, t)))
102
110
 
@@ -108,7 +116,8 @@ def raises_wrong_type_error(
108
116
  """Test that the correct error is raised when the wrong type is passed to a field."""
109
117
  field_props = Command.model_json_schema()["properties"][field]
110
118
  field_type = get_field_type(field_props)
111
- wrong_field_type = "integer" if field_type == "string" else "string"
119
+
120
+ wrong_field_type = "WrongType"
112
121
 
113
122
  with pytest.raises(ValidationError) as e1:
114
123
  err_kwargs = {field: fake({"type": wrong_field_type}, Command)}
@@ -122,8 +131,11 @@ def raises_wrong_type_error(
122
131
  setattr(cmd, field, err_value)
123
132
  err_msg2 = repr(e2.value)
124
133
 
125
- assert f"1 validation error for {Command.__name__}\n{field}" in err_msg1
126
- assert f"1 validation error for {Command.__name__}\n{field}" in err_msg2
134
+ assert "validation error" in err_msg1
135
+ assert f"{Command.__name__}\n{field}" in err_msg1
136
+
137
+ assert "validation error" in err_msg2
138
+ assert f"{Command.__name__}\n{field}" in err_msg1
127
139
 
128
140
  field_type = (
129
141
  "dictionary" if field_type == "Coding" or field_type == "ClinicalQuantity" else field_type
@@ -1,3 +1,5 @@
1
+ import uuid
2
+
1
3
  import pytest
2
4
  from pydantic import ValidationError
3
5
  from typer.testing import CliRunner
@@ -91,24 +93,21 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
91
93
 
92
94
 
93
95
  @pytest.mark.parametrize(
94
- "Command,err_kwargs,err_msg,valid_kwargs",
96
+ "Command,err_kwargs,valid_kwargs",
95
97
  [
96
98
  (
97
99
  PlanCommand,
98
100
  {"narrative": "yo", "note_uuid": 1},
99
- "1 validation error for PlanCommand\nnote_uuid\n Input should be a valid string [type=string_type",
100
101
  {"narrative": "yo", "note_uuid": "00000000-0000-0000-0000-000000000000"},
101
102
  ),
102
103
  (
103
104
  PlanCommand,
104
105
  {"narrative": "yo", "note_uuid": "5", "command_uuid": 5},
105
- "1 validation error for PlanCommand\ncommand_uuid\n Input should be a valid string [type=string_type",
106
106
  {"narrative": "yo", "note_uuid": "5", "command_uuid": "5"},
107
107
  ),
108
108
  (
109
109
  ReasonForVisitCommand,
110
110
  {"note_uuid": "00000000-0000-0000-0000-000000000000", "structured": True},
111
- "1 validation error for ReasonForVisitCommand\n Structured RFV should have a coding",
112
111
  {
113
112
  "note_uuid": "00000000-0000-0000-0000-000000000000",
114
113
  "structured": False,
@@ -120,7 +119,6 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
120
119
  "note_uuid": "00000000-0000-0000-0000-000000000000",
121
120
  "coding": {"code": "x"},
122
121
  },
123
- "1 validation error for ReasonForVisitCommand\ncoding.system\n Field required [type=missing",
124
122
  {"note_uuid": "00000000-0000-0000-0000-000000000000"},
125
123
  ),
126
124
  (
@@ -129,7 +127,6 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
129
127
  "note_uuid": "00000000-0000-0000-0000-000000000000",
130
128
  "coding": {"code": 1, "system": "y"},
131
129
  },
132
- "1 validation error for ReasonForVisitCommand\ncoding.code\n Input should be a valid string [type=string_type",
133
130
  {"note_uuid": "00000000-0000-0000-0000-000000000000"},
134
131
  ),
135
132
  (
@@ -138,7 +135,6 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
138
135
  "note_uuid": "00000000-0000-0000-0000-000000000000",
139
136
  "coding": {"code": None, "system": "y"},
140
137
  },
141
- "1 validation error for ReasonForVisitCommand\ncoding.code\n Input should be a valid string [type=string_type",
142
138
  {"note_uuid": "00000000-0000-0000-0000-000000000000"},
143
139
  ),
144
140
  (
@@ -147,7 +143,6 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
147
143
  "note_uuid": "00000000-0000-0000-0000-000000000000",
148
144
  "coding": {"system": "y"},
149
145
  },
150
- "1 validation error for ReasonForVisitCommand\ncoding.code\n Field required [type=missing",
151
146
  {"note_uuid": "00000000-0000-0000-0000-000000000000"},
152
147
  ),
153
148
  (
@@ -156,7 +151,6 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
156
151
  "note_uuid": "00000000-0000-0000-0000-000000000000",
157
152
  "coding": {"code": "x", "system": 1},
158
153
  },
159
- "1 validation error for ReasonForVisitCommand\ncoding.system\n Input should be a valid string [type=string_type",
160
154
  {"note_uuid": "00000000-0000-0000-0000-000000000000"},
161
155
  ),
162
156
  (
@@ -165,7 +159,6 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
165
159
  "note_uuid": "00000000-0000-0000-0000-000000000000",
166
160
  "coding": {"code": "x", "system": None},
167
161
  },
168
- "1 validation error for ReasonForVisitCommand\ncoding.system\n Input should be a valid string [type=string_type",
169
162
  {"note_uuid": "00000000-0000-0000-0000-000000000000"},
170
163
  ),
171
164
  (
@@ -174,7 +167,6 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
174
167
  "note_uuid": "00000000-0000-0000-0000-000000000000",
175
168
  "coding": {"code": "x", "system": "y", "display": 1},
176
169
  },
177
- "1 validation error for ReasonForVisitCommand\ncoding.display\n Input should be a valid string [type=string_type",
178
170
  {"note_uuid": "00000000-0000-0000-0000-000000000000"},
179
171
  ),
180
172
  ],
@@ -182,25 +174,24 @@ def test_command_raises_generic_error_when_kwarg_given_incorrect_type(
182
174
  def test_command_raises_specific_error_when_kwarg_given_incorrect_type(
183
175
  Command: type[PlanCommand] | type[ReasonForVisitCommand],
184
176
  err_kwargs: dict,
185
- err_msg: str,
186
177
  valid_kwargs: dict,
187
178
  ) -> None:
188
179
  """Test that Command raises a specific error when a kwarg is given an incorrect type."""
189
- with pytest.raises(ValidationError) as e1:
180
+ with pytest.raises(ValidationError):
190
181
  cmd = Command(**err_kwargs)
191
182
  cmd.originate()
183
+ cmd.command_uuid = str(uuid.uuid4())
192
184
  cmd.edit()
193
- assert err_msg in repr(e1.value)
194
185
 
195
186
  cmd = Command(**valid_kwargs)
196
187
  if len(err_kwargs) < len(valid_kwargs):
197
188
  return
198
189
  key, value = list(err_kwargs.items())[-1]
199
- with pytest.raises(ValidationError) as e2:
190
+ with pytest.raises(ValidationError):
200
191
  setattr(cmd, key, value)
201
192
  cmd.originate()
193
+ cmd.command_uuid = str(uuid.uuid4())
202
194
  cmd.edit()
203
- assert err_msg in repr(e2.value)
204
195
 
205
196
 
206
197
  @pytest.mark.parametrize(
@@ -0,0 +1,3 @@
1
+ from .utils import from_yaml as questionnaire_from_yaml
2
+
3
+ __all__ = ("questionnaire_from_yaml",)
@@ -0,0 +1,74 @@
1
+ import json
2
+ from pathlib import Path
3
+
4
+ import pytest
5
+ import yaml
6
+
7
+ from canvas_sdk.effects import Effect
8
+ from canvas_sdk.events import Event, EventRequest, EventType
9
+ from canvas_sdk.questionnaires import questionnaire_from_yaml
10
+ from plugin_runner.plugin_runner import LOADED_PLUGINS
11
+ from settings import PLUGIN_DIRECTORY
12
+
13
+
14
+ @pytest.mark.parametrize("install_test_plugin", ["test_load_questionnaire"], indirect=True)
15
+ def test_from_yaml_valid_questionnaire(install_test_plugin: Path, load_test_plugins: None) -> None:
16
+ """Test that the from_yaml function loads a valid questionnaire."""
17
+ plugin = LOADED_PLUGINS[
18
+ "test_load_questionnaire:test_load_questionnaire.protocols.my_protocol:ValidQuestionnaire"
19
+ ]
20
+ result: list[Effect] = plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute()
21
+
22
+ assert (
23
+ yaml.load(
24
+ (
25
+ Path(PLUGIN_DIRECTORY)
26
+ / "test_load_questionnaire/questionnaires/example_questionnaire.yml"
27
+ )
28
+ .resolve()
29
+ .read_text(),
30
+ Loader=yaml.SafeLoader,
31
+ ).items()
32
+ <= json.loads(result[0].payload).items()
33
+ )
34
+
35
+
36
+ @pytest.mark.parametrize("install_test_plugin", ["test_load_questionnaire"], indirect=True)
37
+ def test_from_yaml_invalid_questionnaire(
38
+ install_test_plugin: Path, load_test_plugins: None
39
+ ) -> None:
40
+ """Test that the from_yaml function raises an error for invalid questionnaires."""
41
+ plugin = LOADED_PLUGINS[
42
+ "test_load_questionnaire:test_load_questionnaire.protocols.my_protocol:InvalidQuestionnaire"
43
+ ]
44
+ with pytest.raises(FileNotFoundError):
45
+ plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute()
46
+
47
+
48
+ @pytest.mark.parametrize("install_test_plugin", ["test_load_questionnaire"], indirect=True)
49
+ def test_from_yaml_forbidden_questionnaire(
50
+ install_test_plugin: Path, load_test_plugins: None
51
+ ) -> None:
52
+ """Test that the from_yaml function raises an error for a questionnaire outside plugin package."""
53
+ plugin = LOADED_PLUGINS[
54
+ "test_load_questionnaire:test_load_questionnaire.protocols.my_protocol:ForbiddenQuestionnaire"
55
+ ]
56
+ with pytest.raises(PermissionError):
57
+ plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute()
58
+
59
+
60
+ def test_from_yaml_non_plugin_caller() -> None:
61
+ """Test that the from_yaml function returns None when called outside a plugin."""
62
+ assert questionnaire_from_yaml("questionnaires/example_questionnaire.yml") is None
63
+
64
+
65
+ @pytest.mark.parametrize("install_test_plugin", ["test_load_questionnaire"], indirect=True)
66
+ def test_from_yaml_sets_default_values(install_test_plugin: Path) -> None:
67
+ """Test that the from_yaml function sets default values for properties."""
68
+ globals()["__is_plugin__"] = True
69
+ globals()["__name__"] = "test_load_questionnaire"
70
+
71
+ definition = questionnaire_from_yaml("questionnaires/example_questionnaire.yml")
72
+
73
+ assert definition is not None
74
+ assert definition["display_results_in_social_history_section"] is False
@@ -0,0 +1,117 @@
1
+ import functools
2
+ import json
3
+ from collections.abc import Generator
4
+ from pathlib import Path
5
+ from typing import Any, TypedDict
6
+
7
+ import yaml
8
+ from jsonschema import Draft7Validator, validators
9
+
10
+ from canvas_sdk.utils.plugins import plugin_only
11
+
12
+
13
+ class Response(TypedDict):
14
+ """A Response of a Questionnaire."""
15
+
16
+ name: str
17
+ code: str
18
+ code_description: str
19
+ value: str
20
+
21
+
22
+ class Question(TypedDict):
23
+ """A Question of a Questionnaire."""
24
+
25
+ code_system: str
26
+ code: str
27
+ code_description: str
28
+ content: str
29
+ responses_code_system: str
30
+ responses_type: str
31
+ display_result_in_social_history_section: bool
32
+ responses: list[Response]
33
+
34
+
35
+ class QuestionnaireConfig(TypedDict):
36
+ """A Questionnaire configuration."""
37
+
38
+ name: str
39
+ form_type: str
40
+ code_system: str
41
+ code: str
42
+ can_originate_in_charting: bool
43
+ prologue: str
44
+ display_results_in_social_history_section: bool
45
+ questions: list[Question]
46
+
47
+
48
+ def extend_with_defaults(validator_class: type[Draft7Validator]) -> type[Draft7Validator]:
49
+ """Extend a Draft7Validator with default values for properties."""
50
+ validate_properties = validator_class.VALIDATORS["properties"]
51
+
52
+ def set_defaults(
53
+ validator: Draft7Validator,
54
+ properties: dict[str, Any],
55
+ instance: dict[str, Any],
56
+ schema: dict[str, Any],
57
+ ) -> Generator[Any, None, None]:
58
+ for property, subschema in properties.items():
59
+ if "default" in subschema:
60
+ instance.setdefault(property, subschema["default"])
61
+
62
+ yield from validate_properties(
63
+ validator,
64
+ properties,
65
+ instance,
66
+ schema,
67
+ )
68
+
69
+ return validators.extend(
70
+ validator_class,
71
+ {"properties": set_defaults},
72
+ )
73
+
74
+
75
+ ExtendedDraft7Validator = extend_with_defaults(Draft7Validator)
76
+
77
+
78
+ @plugin_only
79
+ def from_yaml(questionnaire_name: str, **kwargs: Any) -> QuestionnaireConfig | None:
80
+ """Load a Questionnaire configuration from a YAML file.
81
+
82
+ Args:
83
+ questionnaire_name (str): The path to the questionnaire file, relative to the plugin package.
84
+ If the path starts with a forward slash ("/"), it will be stripped during resolution.
85
+ kwargs (Any): Additional keyword arguments.
86
+
87
+ Returns:
88
+ QuestionnaireConfig: The loaded Questionnaire configuration.
89
+
90
+ Raises:
91
+ FileNotFoundError: If the questionnaire file does not exist within the plugin's directory
92
+ or if the resolved path is invalid.
93
+ PermissionError: If the resolved path is outside the plugin's directory.
94
+ ValidationError: If the questionnaire file does not conform to the JSON schema.
95
+ """
96
+ plugin_dir = kwargs["plugin_dir"]
97
+ questionnaire_config_path = Path(plugin_dir / questionnaire_name.lstrip("/")).resolve()
98
+
99
+ if not questionnaire_config_path.is_relative_to(plugin_dir):
100
+ raise PermissionError(f"Invalid Questionnaire '{questionnaire_name}'")
101
+ elif not questionnaire_config_path.exists():
102
+ raise FileNotFoundError(f"Questionnaire {questionnaire_name} not found.")
103
+
104
+ questionnaire_config = yaml.load(questionnaire_config_path.read_text(), Loader=yaml.SafeLoader)
105
+ ExtendedDraft7Validator(json_schema()).validate(questionnaire_config)
106
+
107
+ return questionnaire_config
108
+
109
+
110
+ @functools.cache
111
+ def json_schema() -> dict[str, Any]:
112
+ """Reads the JSON schema for a Questionnaire Config."""
113
+ schema = json.loads(
114
+ (Path(__file__).resolve().parent.parent.parent / "schemas/questionnaire.json").read_text()
115
+ )
116
+
117
+ return schema
@@ -1,13 +1,15 @@
1
- import inspect
2
1
  from pathlib import Path
3
2
  from typing import Any
4
3
 
5
4
  from django.template import Context, Template
6
5
 
7
- from settings import PLUGIN_DIRECTORY
6
+ from canvas_sdk.utils.plugins import plugin_only
8
7
 
9
8
 
10
- def render_to_string(template_name: str, context: dict[str, Any] | None = None) -> str | None:
9
+ @plugin_only
10
+ def render_to_string(
11
+ template_name: str, context: dict[str, Any] | None = None, **kwargs: Any
12
+ ) -> str | None:
11
13
  """Load a template and render it with the given context.
12
14
 
13
15
  Args:
@@ -15,6 +17,7 @@ def render_to_string(template_name: str, context: dict[str, Any] | None = None)
15
17
  If the path starts with a forward slash ("/"), it will be stripped during resolution.
16
18
  context (dict[str, Any] | None): A dictionary of variables to pass to the template
17
19
  for rendering. Defaults to None, which uses an empty context.
20
+ kwargs (Any): Additional keyword arguments.
18
21
 
19
22
  Returns:
20
23
  str: The rendered template as a string.
@@ -23,15 +26,7 @@ def render_to_string(template_name: str, context: dict[str, Any] | None = None)
23
26
  FileNotFoundError: If the template file does not exist within the plugin's directory
24
27
  or if the resolved path is invalid.
25
28
  """
26
- plugins_dir = Path(PLUGIN_DIRECTORY).resolve()
27
- current_frame = inspect.currentframe()
28
- caller = current_frame.f_back if current_frame else None
29
-
30
- if not caller or "__is_plugin__" not in caller.f_globals:
31
- return None
32
-
33
- plugin_name = caller.f_globals["__name__"].split(".")[0]
34
- plugin_dir = plugins_dir / plugin_name
29
+ plugin_dir = kwargs["plugin_dir"]
35
30
  template_path = Path(plugin_dir / template_name.lstrip("/")).resolve()
36
31
 
37
32
  if not template_path.is_relative_to(plugin_dir):
@@ -0,0 +1,25 @@
1
+ import inspect
2
+ from collections.abc import Callable
3
+ from pathlib import Path
4
+ from typing import Any
5
+
6
+ from settings import PLUGIN_DIRECTORY
7
+
8
+
9
+ def plugin_only(func: Callable[..., Any]) -> Callable[..., Any]:
10
+ """Decorator to restrict a function's execution to plugins only."""
11
+
12
+ def wrapper(*args: Any, **kwargs: Any) -> Any:
13
+ current_frame = inspect.currentframe()
14
+ caller = current_frame.f_back if current_frame else None
15
+
16
+ if not caller or "__is_plugin__" not in caller.f_globals:
17
+ return None
18
+
19
+ plugin_name = caller.f_globals["__name__"].split(".")[0]
20
+ plugin_dir = Path(PLUGIN_DIRECTORY) / plugin_name
21
+ kwargs["plugin_dir"] = plugin_dir.resolve()
22
+
23
+ return func(*args, **kwargs)
24
+
25
+ return wrapper
@@ -1,7 +1,7 @@
1
1
  from .allergy_intolerance import AllergyIntolerance, AllergyIntoleranceCoding
2
2
  from .appointment import Appointment
3
3
  from .assessment import Assessment
4
- from .billing import BillingLineItem
4
+ from .billing import BillingLineItem, BillingLineItemModifier
5
5
  from .care_team import CareTeamMembership, CareTeamRole
6
6
  from .command import Command
7
7
  from .condition import Condition, ConditionCoding
@@ -48,6 +48,7 @@ from .questionnaire import (
48
48
  ResponseOption,
49
49
  ResponseOptionSet,
50
50
  )
51
+ from .reason_for_visit import ReasonForVisitSettingCoding
51
52
  from .staff import Staff
52
53
  from .task import Task, TaskComment, TaskLabel, TaskTaskLabel
53
54
  from .user import CanvasUser
@@ -58,6 +59,7 @@ __all__ = [
58
59
  "AllergyIntoleranceCoding",
59
60
  "Assessment",
60
61
  "BillingLineItem",
62
+ "BillingLineItemModifier",
61
63
  "CanvasUser",
62
64
  "CareTeamMembership",
63
65
  "CareTeamRole",
@@ -103,6 +105,7 @@ __all__ = [
103
105
  "Question",
104
106
  "Questionnaire",
105
107
  "QuestionnaireQuestionMap",
108
+ "ReasonForVisitSettingCoding",
106
109
  "ResponseOption",
107
110
  "ResponseOptionSet",
108
111
  "Staff",
@@ -44,10 +44,16 @@ class BillingLineItem(models.Model):
44
44
  created = models.DateTimeField()
45
45
  modified = models.DateTimeField()
46
46
  note = models.ForeignKey(
47
- "v1.Note", on_delete=models.DO_NOTHING, related_name="billing_line_items", null=True
47
+ "v1.Note",
48
+ on_delete=models.DO_NOTHING,
49
+ related_name="billing_line_items",
50
+ null=True,
48
51
  )
49
52
  patient = models.ForeignKey(
50
- "v1.Patient", on_delete=models.DO_NOTHING, related_name="billing_line_items", null=True
53
+ "v1.Patient",
54
+ on_delete=models.DO_NOTHING,
55
+ related_name="billing_line_items",
56
+ null=True,
51
57
  )
52
58
  cpt = models.CharField()
53
59
  charge = models.DecimalField()
@@ -56,3 +62,24 @@ class BillingLineItem(models.Model):
56
62
  command_type = models.CharField()
57
63
  command_id = models.IntegerField()
58
64
  status = models.CharField(choices=BillingLineItemStatus.choices)
65
+
66
+
67
+ class BillingLineItemModifier(models.Model):
68
+ """BillingLineItemModifier."""
69
+
70
+ class Meta:
71
+ managed = False
72
+ db_table = "canvas_sdk_data_api_billinglineitemmodifier_001"
73
+
74
+ dbid = models.BigIntegerField(primary_key=True)
75
+ system = models.CharField()
76
+ version = models.CharField()
77
+ code = models.CharField()
78
+ display = models.CharField()
79
+ user_selected = models.BooleanField()
80
+ line_item = models.ForeignKey(
81
+ "v1.BillingLineItem",
82
+ on_delete=models.DO_NOTHING,
83
+ related_name="modifiers",
84
+ null=True,
85
+ )
@@ -46,7 +46,7 @@ class CoverageRelationshipCode(models.TextChoices):
46
46
  """CoverageRelationshipCode."""
47
47
 
48
48
  SELF = "18", "Self"
49
- SPOUSE = "01" "Spouse"
49
+ SPOUSE = "01", "Spouse"
50
50
  CHILD_INSURED_HAS_FINANCIAL_RESP = "19", "Natural Child, insured has financial responsibility"
51
51
  CHILD_HAS_FINANCIAL_RESP = "43", "Natural Child, insured does not have financial responsibility"
52
52
  STEP_CHILD = "17", "Step Child"
@@ -0,0 +1,22 @@
1
+ from django.contrib.postgres.fields import ArrayField
2
+ from django.db import models
3
+
4
+
5
+ class ReasonForVisitSettingCoding(models.Model):
6
+ """ReasonForVisitSettingCoding."""
7
+
8
+ class Meta:
9
+ managed = False
10
+ db_table = "canvas_sdk_data_api_reasonforvisitsettingcoding_001"
11
+
12
+ objects: models.Manager["ReasonForVisitSettingCoding"]
13
+
14
+ id = models.UUIDField()
15
+ dbid = models.BigIntegerField(primary_key=True)
16
+
17
+ code = models.CharField()
18
+ display = models.CharField()
19
+ system = models.CharField()
20
+ version = models.CharField()
21
+
22
+ duration = ArrayField(models.DurationField())
@@ -45,6 +45,7 @@ ALLOWED_MODULES = frozenset(
45
45
  "canvas_sdk.events",
46
46
  "canvas_sdk.handlers",
47
47
  "canvas_sdk.protocols",
48
+ "canvas_sdk.questionnaires",
48
49
  "canvas_sdk.utils",
49
50
  "canvas_sdk.templates",
50
51
  "canvas_sdk.v1",
@@ -173,12 +174,12 @@ class Sandbox:
173
174
  ):
174
175
  self.warn(
175
176
  node,
176
- f'"{name}" is an invalid variable name because it ' 'starts with "_"',
177
+ f'"{name}" is an invalid variable name because it starts with "_"',
177
178
  )
178
179
  elif name.endswith("__roles__"):
179
180
  self.error(
180
181
  node,
181
- f'"{name}" is an invalid variable name because ' 'it ends with "__roles__".',
182
+ f'"{name}" is an invalid variable name because it ends with "__roles__".',
182
183
  )
183
184
  elif name in FORBIDDEN_FUNC_NAMES:
184
185
  self.error(node, f'"{name}" is a reserved name.')
@@ -215,21 +216,20 @@ class Sandbox:
215
216
  if node.attr.startswith("_") and node.attr != "_":
216
217
  self.warn(
217
218
  node,
218
- f'"{node.attr}" is an invalid attribute name because it starts ' 'with "_".',
219
+ f'"{node.attr}" is an invalid attribute name because it starts with "_".',
219
220
  )
220
221
 
221
222
  if node.attr.endswith("__roles__"):
222
223
  self.error(
223
224
  node,
224
- f'"{node.attr}" is an invalid attribute name because it ends '
225
- 'with "__roles__".',
225
+ f'"{node.attr}" is an invalid attribute name because it ends with "__roles__".',
226
226
  )
227
227
 
228
228
  if isinstance(node.ctx, ast.Load):
229
229
  node = self.node_contents_visit(node)
230
230
  new_node = ast.Call(
231
231
  func=ast.Name("_getattr_", ast.Load()),
232
- args=[node.value, ast.Str(node.attr)],
232
+ args=[node.value, ast.Constant(node.attr)],
233
233
  keywords=[],
234
234
  )
235
235