canvas 0.57.1__tar.gz → 0.58.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 (330) hide show
  1. {canvas-0.57.1 → canvas-0.58.0}/PKG-INFO +4 -1
  2. canvas-0.58.0/canvas_cli/apps/run_plugins/run_plugins.py +102 -0
  3. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/templates/plugins/default/cookiecutter.json +2 -1
  4. canvas-0.58.0/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/pyproject.toml +16 -0
  5. {canvas-0.57.1/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }} → canvas-0.58.0/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/{{ cookiecutter.__package_name }}}/CANVAS_MANIFEST.json +2 -2
  6. canvas-0.58.0/canvas_sdk/test_utils/factories/__init__.py +4 -0
  7. canvas-0.58.0/canvas_sdk/test_utils/factories/patient.py +39 -0
  8. canvas-0.58.0/canvas_sdk/test_utils/factories/user.py +13 -0
  9. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/patient.py +67 -47
  10. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/user.py +2 -2
  11. canvas-0.58.0/canvas_sdk/v1/data/utils.py +32 -0
  12. canvas-0.58.0/pubsub/__init__.py +0 -0
  13. {canvas-0.57.1 → canvas-0.58.0}/pyproject.toml +11 -3
  14. {canvas-0.57.1 → canvas-0.58.0}/settings.py +9 -6
  15. canvas-0.57.1/canvas_cli/apps/run_plugins/run_plugins.py +0 -16
  16. canvas-0.57.1/canvas_sdk/v1/data/utils.py +0 -16
  17. {canvas-0.57.1 → canvas-0.58.0}/.gitignore +0 -0
  18. {canvas-0.57.1 → canvas-0.58.0}/README.md +0 -0
  19. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/__init__.py +0 -0
  20. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/__init__.py +0 -0
  21. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/auth/__init__.py +0 -0
  22. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/auth/storage.py +0 -0
  23. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/auth/utils.py +0 -0
  24. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/__init__.py +0 -0
  25. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/emit.py +0 -0
  26. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_CREATED.ndjson +0 -0
  27. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_UPDATED.ndjson +0 -0
  28. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CANCELED.ndjson +0 -0
  29. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CHECKED_IN.ndjson +0 -0
  30. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CREATED.ndjson +0 -0
  31. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_NO_SHOWED.ndjson +0 -0
  32. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESCHEDULED.ndjson +0 -0
  33. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESTORED.ndjson +0 -0
  34. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_UPDATED.ndjson +0 -0
  35. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__CONDITION_SELECTED.ndjson +0 -0
  36. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_COMMIT.ndjson +0 -0
  37. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_ORIGINATE.ndjson +0 -0
  38. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_UPDATE.ndjson +0 -0
  39. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_COMMIT.ndjson +0 -0
  40. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  41. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_UPDATE.ndjson +0 -0
  42. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_CREATED.ndjson +0 -0
  43. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_UPDATED.ndjson +0 -0
  44. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/CONDITION_ASSESSED.ndjson +0 -0
  45. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/CONDITION_CREATED.ndjson +0 -0
  46. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/CONDITION_UPDATED.ndjson +0 -0
  47. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/CRON.ndjson +0 -0
  48. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ENCOUNTER_CREATED.ndjson +0 -0
  49. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/ENCOUNTER_UPDATED.ndjson +0 -0
  50. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_CREATED.ndjson +0 -0
  51. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_CREATED.ndjson +0 -0
  52. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_UPDATED.ndjson +0 -0
  53. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_UPDATED.ndjson +0 -0
  54. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/INTERVIEW_CREATED.ndjson +0 -0
  55. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/INTERVIEW_UPDATED.ndjson +0 -0
  56. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/LAB_ORDER_CREATED.ndjson +0 -0
  57. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/LAB_ORDER_UPDATED.ndjson +0 -0
  58. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_CREATED.ndjson +0 -0
  59. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_UPDATED.ndjson +0 -0
  60. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_COMMIT.ndjson +0 -0
  61. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_ORIGINATE.ndjson +0 -0
  62. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_UPDATE.ndjson +0 -0
  63. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_COMMIT.ndjson +0 -0
  64. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  65. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_UPDATE.ndjson +0 -0
  66. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT__MEDICATION__POST_SEARCH.ndjson +0 -0
  67. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/PATIENT_CREATED.ndjson +0 -0
  68. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/PATIENT_UPDATED.ndjson +0 -0
  69. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__POST_ORIGINATE.ndjson +0 -0
  70. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  71. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_COMMIT.ndjson +0 -0
  72. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_ORIGINATE.ndjson +0 -0
  73. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_UPDATE.ndjson +0 -0
  74. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_COMMIT.ndjson +0 -0
  75. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  76. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_UPDATE.ndjson +0 -0
  77. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE__QUESTIONNAIRE__POST_SEARCH.ndjson +0 -0
  78. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/SIMPLE_API_REQUEST.ndjson +0 -0
  79. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/TASK_COMMENT_CREATED.ndjson +0 -0
  80. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/TASK_CREATED.ndjson +0 -0
  81. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/TASK_UPDATED.ndjson +0 -0
  82. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_CREATED.ndjson +0 -0
  83. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_UPDATED.ndjson +0 -0
  84. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/logs/__init__.py +0 -0
  85. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/logs/logs.py +0 -0
  86. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/plugin/__init__.py +0 -0
  87. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/plugin/plugin.py +0 -0
  88. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/apps/run_plugins/__init__.py +0 -0
  89. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/main.py +0 -0
  90. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/templates/plugins/application/cookiecutter.json +0 -0
  91. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/CANVAS_MANIFEST.json +0 -0
  92. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/README.md +0 -0
  93. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/applications/__init__.py +0 -0
  94. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/applications/my_application.py +0 -0
  95. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/templates/plugins/application/{{ cookiecutter.__project_slug }}/assets/python-logo.png +0 -0
  96. {canvas-0.57.1/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }} → canvas-0.58.0/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/{{ cookiecutter.__package_name }}}/README.md +0 -0
  97. {canvas-0.57.1/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }} → canvas-0.58.0/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/{{ cookiecutter.__package_name }}}/protocols/__init__.py +0 -0
  98. {canvas-0.57.1/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }} → canvas-0.58.0/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/{{ cookiecutter.__package_name }}}/protocols/my_protocol.py +0 -0
  99. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/__init__.py +0 -0
  100. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/context/__init__.py +0 -0
  101. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/context/context.py +0 -0
  102. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/print/__init__.py +0 -0
  103. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/print/print.py +0 -0
  104. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/urls/__init__.py +0 -0
  105. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/urls/urls.py +0 -0
  106. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/validators/__init__.py +0 -0
  107. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/validators/manifest_schema.py +0 -0
  108. {canvas-0.57.1 → canvas-0.58.0}/canvas_cli/utils/validators/validators.py +0 -0
  109. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/effects_pb2.py +0 -0
  110. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/effects_pb2.pyi +0 -0
  111. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/effects_pb2_grpc.py +0 -0
  112. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/events_pb2.py +0 -0
  113. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/events_pb2.pyi +0 -0
  114. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/events_pb2_grpc.py +0 -0
  115. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/plugins_pb2.py +0 -0
  116. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/plugins_pb2.pyi +0 -0
  117. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/messages/plugins_pb2_grpc.py +0 -0
  118. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/services/plugin_runner_pb2.py +0 -0
  119. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/services/plugin_runner_pb2.pyi +0 -0
  120. {canvas-0.57.1 → canvas-0.58.0}/canvas_generated/services/plugin_runner_pb2_grpc.py +0 -0
  121. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/__init__.py +0 -0
  122. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/base.py +0 -0
  123. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/caching/__init__.py +0 -0
  124. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/caching/base.py +0 -0
  125. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/caching/client.py +0 -0
  126. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/caching/exceptions.py +0 -0
  127. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/caching/plugins.py +0 -0
  128. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/caching/utils.py +0 -0
  129. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/__init__.py +0 -0
  130. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/base.py +0 -0
  131. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/__init__.py +0 -0
  132. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/adjust_prescription.py +0 -0
  133. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/allergy.py +0 -0
  134. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/assess.py +0 -0
  135. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/change_medication.py +0 -0
  136. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/chart_section_review.py +0 -0
  137. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/close_goal.py +0 -0
  138. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/diagnose.py +0 -0
  139. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/exam.py +0 -0
  140. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/family_history.py +0 -0
  141. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/follow_up.py +0 -0
  142. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/goal.py +0 -0
  143. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/history_present_illness.py +0 -0
  144. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/imaging_order.py +0 -0
  145. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/immunization_statement.py +0 -0
  146. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/instruct.py +0 -0
  147. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/lab_order.py +0 -0
  148. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/medical_history.py +0 -0
  149. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/medication_statement.py +0 -0
  150. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/past_surgical_history.py +0 -0
  151. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/perform.py +0 -0
  152. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/plan.py +0 -0
  153. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/prescribe.py +0 -0
  154. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/questionnaire/__init__.py +0 -0
  155. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/questionnaire/question.py +0 -0
  156. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/questionnaire/toggle_questions.py +0 -0
  157. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/reason_for_visit.py +0 -0
  158. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/refer.py +0 -0
  159. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/refill.py +0 -0
  160. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/remove_allergy.py +0 -0
  161. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/resolve_condition.py +0 -0
  162. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/review_of_systems.py +0 -0
  163. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/stop_medication.py +0 -0
  164. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/structured_assessment.py +0 -0
  165. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/task.py +0 -0
  166. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/update_diagnosis.py +0 -0
  167. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/update_goal.py +0 -0
  168. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/commands/vitals.py +0 -0
  169. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/commands/constants.py +0 -0
  170. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/__init__.py +0 -0
  171. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/banner_alert/__init__.py +0 -0
  172. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/banner_alert/add_banner_alert.py +0 -0
  173. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/banner_alert/remove_banner_alert.py +0 -0
  174. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/base.py +0 -0
  175. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/billing_line_item/__init__.py +0 -0
  176. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/billing_line_item/add_billing_line_item.py +0 -0
  177. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/billing_line_item/remove_billing_line_item.py +0 -0
  178. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/billing_line_item/update_billing_line_item.py +0 -0
  179. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/compound_medications/__init__.py +0 -0
  180. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/compound_medications/compound_medication.py +0 -0
  181. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/group.py +0 -0
  182. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/launch_modal.py +0 -0
  183. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/note/__init__.py +0 -0
  184. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/note/appointment.py +0 -0
  185. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/note/base.py +0 -0
  186. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/note/message.py +0 -0
  187. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/note/note.py +0 -0
  188. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/panel_configuration.py +0 -0
  189. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient/__init__.py +0 -0
  190. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient/base.py +0 -0
  191. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient/create_patient_external_identifier.py +0 -0
  192. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_chart_group.py +0 -0
  193. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_chart_summary_configuration.py +0 -0
  194. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_metadata/__init__.py +0 -0
  195. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_metadata/base.py +0 -0
  196. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_metadata/patient_metadata_create_form.py +0 -0
  197. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_portal/__init__.py +0 -0
  198. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_portal/application_configuration.py +0 -0
  199. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_portal/form_result.py +0 -0
  200. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_portal_menu_configuration.py +0 -0
  201. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/patient_profile_configuration.py +0 -0
  202. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/payment_processor.py +0 -0
  203. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/protocol_card/__init__.py +0 -0
  204. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/protocol_card/protocol_card.py +0 -0
  205. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/questionnaire_result.py +0 -0
  206. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/send_invite.py +0 -0
  207. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/show_button.py +0 -0
  208. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/simple_api.py +0 -0
  209. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/surescripts/__init__.py +0 -0
  210. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/surescripts/surescripts_messages.py +0 -0
  211. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/task/__init__.py +0 -0
  212. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/task/task.py +0 -0
  213. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/update_user.py +0 -0
  214. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/widgets/__init__.py +0 -0
  215. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/effects/widgets/portal_widget.py +0 -0
  216. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/events/__init__.py +0 -0
  217. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/events/base.py +0 -0
  218. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/__init__.py +0 -0
  219. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/action_button.py +0 -0
  220. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/application.py +0 -0
  221. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/base.py +0 -0
  222. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/cron_task.py +0 -0
  223. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/payment_processors/__init__.py +0 -0
  224. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/payment_processors/base.py +0 -0
  225. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/payment_processors/card.py +0 -0
  226. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/simple_api/__init__.py +0 -0
  227. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/simple_api/api.py +0 -0
  228. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/simple_api/exceptions.py +0 -0
  229. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/simple_api/security.py +0 -0
  230. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/simple_api/tools.py +0 -0
  231. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/handlers/simple_api/websocket.py +0 -0
  232. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/protocols/__init__.py +0 -0
  233. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/protocols/base.py +0 -0
  234. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/protocols/clinical_quality_measure.py +0 -0
  235. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/protocols/timeframe.py +0 -0
  236. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/questionnaires/__init__.py +0 -0
  237. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/questionnaires/utils.py +0 -0
  238. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/templates/__init__.py +0 -0
  239. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/templates/utils.py +0 -0
  240. {canvas-0.57.1/plugin_runner → canvas-0.58.0/canvas_sdk/test_utils}/__init__.py +0 -0
  241. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/utils/__init__.py +0 -0
  242. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/utils/db.py +0 -0
  243. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/utils/http.py +0 -0
  244. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/utils/metrics.py +0 -0
  245. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/utils/plugins.py +0 -0
  246. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/__init__.py +0 -0
  247. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/apps.py +0 -0
  248. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/__init__.py +0 -0
  249. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/allergy_intolerance.py +0 -0
  250. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/appointment.py +0 -0
  251. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/assessment.py +0 -0
  252. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/banner_alert.py +0 -0
  253. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/base.py +0 -0
  254. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/billing.py +0 -0
  255. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/business_line.py +0 -0
  256. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/care_team.py +0 -0
  257. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/charge_description_master.py +0 -0
  258. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/claim.py +0 -0
  259. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/claim_line_item.py +0 -0
  260. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/command.py +0 -0
  261. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/common.py +0 -0
  262. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/compound_medication.py +0 -0
  263. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/condition.py +0 -0
  264. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/coverage.py +0 -0
  265. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/detected_issue.py +0 -0
  266. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/device.py +0 -0
  267. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/discount.py +0 -0
  268. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/fields.py +0 -0
  269. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/imaging.py +0 -0
  270. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/invoice.py +0 -0
  271. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/lab.py +0 -0
  272. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/line_item_transaction.py +0 -0
  273. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/medication.py +0 -0
  274. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/message.py +0 -0
  275. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/note.py +0 -0
  276. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/observation.py +0 -0
  277. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/organization.py +0 -0
  278. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/patient_consent.py +0 -0
  279. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/payment_collection.py +0 -0
  280. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/payor_specific_charge.py +0 -0
  281. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/posting.py +0 -0
  282. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/practicelocation.py +0 -0
  283. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/protocol_override.py +0 -0
  284. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/questionnaire.py +0 -0
  285. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/reason_for_visit.py +0 -0
  286. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/referral.py +0 -0
  287. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/service_provider.py +0 -0
  288. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/staff.py +0 -0
  289. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/task.py +0 -0
  290. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/data/team.py +0 -0
  291. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/v1/models.py +0 -0
  292. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/__init__.py +0 -0
  293. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/custom.py +0 -0
  294. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/hcc2018.py +0 -0
  295. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/__init__.py +0 -0
  296. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/adverse_event.py +0 -0
  297. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/allergy.py +0 -0
  298. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/assessment.py +0 -0
  299. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/communication.py +0 -0
  300. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/condition.py +0 -0
  301. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/device.py +0 -0
  302. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/diagnostic_study.py +0 -0
  303. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/encounter.py +0 -0
  304. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/immunization.py +0 -0
  305. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/individual_characteristic.py +0 -0
  306. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/intervention.py +0 -0
  307. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/laboratory_test.py +0 -0
  308. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/medication.py +0 -0
  309. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/physical_exam.py +0 -0
  310. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/procedure.py +0 -0
  311. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/v2022/symptom.py +0 -0
  312. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/value_set/value_set.py +0 -0
  313. {canvas-0.57.1 → canvas-0.58.0}/canvas_sdk/views/__init__.py +0 -0
  314. {canvas-0.57.1 → canvas-0.58.0}/logger/__init__.py +0 -0
  315. {canvas-0.57.1 → canvas-0.58.0}/logger/logger.py +0 -0
  316. {canvas-0.57.1/pubsub → canvas-0.58.0/plugin_runner}/__init__.py +0 -0
  317. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/allowed-module-imports.json +0 -0
  318. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/authentication.py +0 -0
  319. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/aws_headers.py +0 -0
  320. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/exceptions.py +0 -0
  321. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/generate_allowed_imports.py +0 -0
  322. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/installation.py +0 -0
  323. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/load_all_plugins.py +0 -0
  324. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/plugin_runner.py +0 -0
  325. {canvas-0.57.1 → canvas-0.58.0}/plugin_runner/sandbox.py +0 -0
  326. {canvas-0.57.1 → canvas-0.58.0}/protobufs/canvas_generated/messages/effects.proto +0 -0
  327. {canvas-0.57.1 → canvas-0.58.0}/protobufs/canvas_generated/messages/events.proto +0 -0
  328. {canvas-0.57.1 → canvas-0.58.0}/protobufs/canvas_generated/messages/plugins.proto +0 -0
  329. {canvas-0.57.1 → canvas-0.58.0}/protobufs/canvas_generated/services/plugin_runner.proto +0 -0
  330. {canvas-0.57.1 → canvas-0.58.0}/pubsub/pubsub.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: canvas
3
- Version: 0.57.1
3
+ Version: 0.58.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
@@ -13,6 +13,7 @@ Requires-Dist: django-stubs[compatible-mypy]<6,>=5.1.1
13
13
  Requires-Dist: django-timezone-utils<0.16,>=0.15.0
14
14
  Requires-Dist: django<6,>=5.1.1
15
15
  Requires-Dist: env-tools<3,>=2.4.0
16
+ Requires-Dist: factory-boy>=3.3.3
16
17
  Requires-Dist: frozendict>=2.4.6
17
18
  Requires-Dist: grpcio<2,>=1.60.1
18
19
  Requires-Dist: ipython<9,>=8.21.0
@@ -32,6 +33,8 @@ Requires-Dist: statsd<5,>=4.0.1
32
33
  Requires-Dist: typer
33
34
  Requires-Dist: typing-extensions<4.13,>=4.8
34
35
  Requires-Dist: websocket-client<2,>=1.7.0
36
+ Provides-Extra: test-utils
37
+ Requires-Dist: pytest-canvas; extra == 'test-utils'
35
38
  Description-Content-Type: text/markdown
36
39
 
37
40
  [![codecov](https://codecov.io/gh/canvas-medical/canvas-plugins/graph/badge.svg?token=P8JJUOJ8FH)](https://codecov.io/gh/canvas-medical/canvas-plugins)
@@ -0,0 +1,102 @@
1
+ from collections.abc import Generator
2
+ from contextlib import contextmanager
3
+ from pathlib import Path
4
+
5
+ import django.db
6
+ import typer
7
+ from django.core.management import call_command
8
+
9
+ import settings
10
+ from plugin_runner.plugin_runner import main as run_server
11
+
12
+
13
+ @contextmanager
14
+ def _patch_default_db_connection() -> Generator[None, None, None]:
15
+ """
16
+ Temporarily patch the 'default' Django DB connection to allow db writes.
17
+ """
18
+ original_default = django.db.connections["default"]
19
+ try:
20
+ temp_handler = django.db.utils.ConnectionHandler(
21
+ {"default": settings.SQLITE_WRITE_MODE_DATABASE}
22
+ )
23
+ django.db.connections["default"] = temp_handler["default"]
24
+ yield
25
+ finally:
26
+ django.db.connections["default"] = original_default
27
+
28
+
29
+ def _run_db_seed_file(path: Path) -> None:
30
+ """Run the database setup file to initialize the database."""
31
+ code = path.read_text()
32
+ exec_globals = {"__name__": "__main__"}
33
+ exec(code, exec_globals)
34
+
35
+
36
+ def _reset_db(seed_file: Path | None = None) -> None:
37
+ """Reset the database."""
38
+ settings.SQLITE_DB_PATH.unlink(missing_ok=True)
39
+
40
+ with _patch_default_db_connection():
41
+ call_command("migrate", run_syncdb=True, verbosity=0)
42
+ if seed_file:
43
+ _run_db_seed_file(seed_file)
44
+
45
+
46
+ def run_plugin(
47
+ plugin_directory: str = typer.Argument(..., help="Path to the plugin directory to run."),
48
+ db_seed_file: Path | None = typer.Option(
49
+ help="Path to the database seed file to use.",
50
+ default=None,
51
+ ),
52
+ reset_db: bool = typer.Option(
53
+ help="Reset the database before running the plugin.", default=False
54
+ ),
55
+ ) -> None:
56
+ """
57
+ Run the specified plugin for local development.
58
+ """
59
+ _run_plugins([plugin_directory], db_seed_file=db_seed_file, reset_db=reset_db)
60
+
61
+
62
+ def run_plugins(
63
+ plugin_directories: list[str],
64
+ db_seed_file: Path | None = typer.Option(
65
+ help="Path to the database seed file to use.",
66
+ default=None,
67
+ ),
68
+ reset_db: bool = typer.Option(
69
+ help="Reset the database before running the plugin(s).", default=False
70
+ ),
71
+ ) -> None:
72
+ """
73
+ Run the specified plugins for local development.
74
+ """
75
+ _run_plugins(plugin_directories, db_seed_file=db_seed_file, reset_db=reset_db)
76
+
77
+
78
+ def _run_plugins(
79
+ plugin_directories: list[str], db_seed_file: Path | None = None, reset_db: bool = False
80
+ ) -> None:
81
+ """
82
+ Run the specified plugins for local development.
83
+ """
84
+ if db_seed_file:
85
+ if not db_seed_file.exists():
86
+ raise typer.BadParameter(f"Database setup file not found: {db_seed_file.resolve()}")
87
+ if not db_seed_file.is_file():
88
+ raise typer.BadParameter(
89
+ f"Database setup file is not a regular file: {db_seed_file.resolve()}"
90
+ )
91
+ if not db_seed_file.suffix == ".py":
92
+ raise typer.BadParameter("Database setup file must be a Python script (.py)")
93
+
94
+ if settings.CANVAS_SDK_DB_BACKEND != "sqlite3":
95
+ raise typer.BadParameter(
96
+ "Database backend must be 'sqlite3' for local plugin development. Please unset 'DATABASE_URL' env var."
97
+ )
98
+
99
+ if db_seed_file or reset_db:
100
+ _reset_db(seed_file=db_seed_file)
101
+
102
+ run_server(plugin_directories)
@@ -1,4 +1,5 @@
1
1
  {
2
2
  "project_name": "My Cool Plugin",
3
- "__project_slug": "{{ cookiecutter.project_name.lower().replace(' ', '_') }}"
3
+ "__project_slug": "{{ cookiecutter.project_name.lower().replace(' ', '-') }}",
4
+ "__package_name": "{{ cookiecutter.__project_slug.replace('-', '_') }}"
4
5
  }
@@ -0,0 +1,16 @@
1
+ [project]
2
+ authors = [
3
+ {email = "engineering@canvasmedical.com", name = "Canvas Team"}
4
+ ]
5
+ dependencies = [
6
+ "canvas[test-utils]"
7
+ ]
8
+ description = "Some description of your project."
9
+ license = "MIT"
10
+ name = "{{ cookiecutter.__project_slug }}"
11
+ readme = "{{cookiecutter.__package_name }}/README.md"
12
+ requires-python = ">=3.11"
13
+ version = "0.1.0"
14
+
15
+ [tool.pytest.ini_options]
16
+ python_files = ["*_tests.py", "test_*.py", "tests.py"]
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "sdk_version": "0.1.4",
3
3
  "plugin_version": "0.0.1",
4
- "name": "{{ cookiecutter.__project_slug }}",
4
+ "name": "{{ cookiecutter.__package_name }}",
5
5
  "description": "Edit the description in CANVAS_MANIFEST.json",
6
6
  "components": {
7
7
  "protocols": [
8
8
  {
9
- "class": "{{ cookiecutter.__project_slug }}.protocols.my_protocol:Protocol",
9
+ "class": "{{ cookiecutter.__package_name }}.protocols.my_protocol:Protocol",
10
10
  "description": "A protocol that does xyz..."
11
11
  }
12
12
  ],
@@ -0,0 +1,4 @@
1
+ from .patient import PatientAddressFactory, PatientFactory
2
+ from .user import CanvasUserFactory
3
+
4
+ __all__ = ("CanvasUserFactory", "PatientAddressFactory", "PatientFactory")
@@ -0,0 +1,39 @@
1
+ import datetime
2
+
3
+ import factory
4
+ from factory.fuzzy import FuzzyDate
5
+
6
+ from canvas_sdk.test_utils.factories.user import CanvasUserFactory
7
+ from canvas_sdk.v1.data import Patient, PatientAddress
8
+
9
+
10
+ class PatientAddressFactory(factory.django.DjangoModelFactory[PatientAddress]):
11
+ """Factory for creating a PatientAddress."""
12
+
13
+ class Meta:
14
+ model = PatientAddress
15
+
16
+ line1 = "1234 Main Street"
17
+ line2 = "Apt 3"
18
+ city = "San Francisco"
19
+ district = "Sunset"
20
+ state_code = "CA"
21
+ postal_code = "94112"
22
+ country = "USA"
23
+
24
+
25
+ class PatientFactory(factory.django.DjangoModelFactory[Patient]):
26
+ """Factory for creating a Patient."""
27
+
28
+ class Meta:
29
+ model = Patient
30
+
31
+ birth_date = FuzzyDate(
32
+ start_date=datetime.date.today() - datetime.timedelta(days=100 * 365),
33
+ end_date=datetime.date.today() - datetime.timedelta(days=10 * 365),
34
+ )
35
+ first_name = factory.Faker("first_name")
36
+ middle_name = factory.Faker("first_name")
37
+ last_name = factory.Faker("last_name")
38
+ addresses = factory.RelatedFactory(PatientAddressFactory, "patient")
39
+ user = factory.SubFactory(CanvasUserFactory)
@@ -0,0 +1,13 @@
1
+ import factory
2
+
3
+ from canvas_sdk.v1.data import CanvasUser
4
+
5
+
6
+ class CanvasUserFactory(factory.django.DjangoModelFactory[CanvasUser]):
7
+ """Factory for creating a CanvasUser."""
8
+
9
+ class Meta:
10
+ model = CanvasUser
11
+
12
+ email = factory.Faker("email")
13
+ phone_number = factory.Faker("phone_number")
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from typing import TYPE_CHECKING, Any
3
+ from typing import Any
4
4
 
5
5
  import arrow
6
6
  from django.contrib.postgres.fields import ArrayField
@@ -16,10 +16,7 @@ from canvas_sdk.v1.data.common import (
16
16
  ContactPointSystem,
17
17
  ContactPointUse,
18
18
  )
19
- from canvas_sdk.v1.data.utils import create_key
20
-
21
- if TYPE_CHECKING:
22
- from django_stubs_ext.db.models.manager import RelatedManager
19
+ from canvas_sdk.v1.data.utils import create_key, generate_mrn
23
20
 
24
21
 
25
22
  class SexAtBirth(TextChoices):
@@ -51,45 +48,65 @@ class Patient(Model):
51
48
  id = models.CharField(
52
49
  max_length=32, db_column="key", unique=True, editable=False, default=create_key
53
50
  )
54
- first_name = models.CharField(max_length=255)
55
- last_name = models.CharField(max_length=255)
51
+ first_name = models.CharField(max_length=255, default="", blank=True)
52
+ middle_name = models.CharField(max_length=255, default="", blank=True)
53
+ last_name = models.CharField(max_length=255, default="", blank=True)
54
+ maiden_name = models.CharField(max_length=255, default="", blank=True)
56
55
  birth_date = models.DateField()
57
56
  business_line = models.ForeignKey(
58
- "v1.BusinessLine", on_delete=models.DO_NOTHING, related_name="patients"
57
+ "v1.BusinessLine",
58
+ on_delete=models.DO_NOTHING,
59
+ related_name="patients",
60
+ null=True,
59
61
  )
60
62
  sex_at_birth = models.CharField(choices=SexAtBirth.choices, max_length=3)
61
- created = models.DateTimeField(auto_now_add=True)
62
- modified = models.DateTimeField(auto_now=True)
63
- prefix = models.CharField(max_length=100)
64
- suffix = models.CharField(max_length=100)
65
- middle_name = models.CharField(max_length=255)
66
- maiden_name = models.CharField(max_length=255)
63
+
64
+ prefix = models.CharField(max_length=100, blank=True, default="")
65
+ suffix = models.CharField(max_length=100, blank=True, default="")
67
66
  nickname = models.CharField(max_length=255)
68
- sexual_orientation_term = models.CharField(max_length=255)
69
- sexual_orientation_code = models.CharField(max_length=255)
70
- gender_identity_term = models.CharField(max_length=255)
71
- gender_identity_code = models.CharField(max_length=255)
72
- preferred_pronouns = models.CharField(max_length=255)
73
- biological_race_codes = ArrayField(models.CharField(max_length=100))
74
- last_known_timezone = models.CharField(max_length=32)
75
- mrn = models.CharField(max_length=9)
76
- active = models.BooleanField()
77
- deceased = models.BooleanField()
78
- deceased_datetime = models.DateTimeField()
79
- deceased_cause = models.TextField()
80
- deceased_comment = models.TextField()
81
- other_gender_description = models.CharField(max_length=255)
82
- social_security_number = models.CharField(max_length=9)
83
- administrative_note = models.TextField()
84
- clinical_note = models.TextField()
85
- mothers_maiden_name = models.CharField(max_length=255)
86
- multiple_birth_indicator = models.BooleanField()
87
- birth_order = models.BigIntegerField()
88
- default_location_id = models.BigIntegerField()
89
- default_provider_id = models.BigIntegerField()
67
+ sexual_orientation_term = models.CharField(max_length=255, default="", blank=True)
68
+ sexual_orientation_code = models.CharField(max_length=255, default="", blank=True)
69
+ gender_identity_term = models.CharField(max_length=255, default="", blank=True)
70
+ gender_identity_code = models.CharField(max_length=255, default="", blank=True)
71
+ preferred_pronouns = models.CharField(max_length=255, default="", blank=True)
72
+ biological_race_codes = ArrayField(
73
+ models.CharField(max_length=100, default="", blank=True), default=list, blank=True
74
+ )
75
+ last_known_timezone = models.CharField(max_length=32, null=True, blank=True)
76
+ mrn = models.CharField(max_length=9, unique=True, default=generate_mrn)
77
+ active = models.BooleanField(default=True)
78
+ deceased = models.BooleanField(default=False)
79
+ deceased_datetime = models.DateTimeField(null=True, blank=True)
80
+ deceased_cause = models.TextField(default="", blank=True)
81
+ deceased_comment = models.TextField(default="", blank=True)
82
+ other_gender_description = models.CharField(max_length=255, blank=True, default="")
83
+ social_security_number = models.CharField(max_length=9, blank=True, default="")
84
+ administrative_note = models.TextField(null=True, blank=True)
85
+ clinical_note = models.TextField(default="", blank=True)
86
+ mothers_maiden_name = models.CharField(max_length=255, blank=True, default="")
87
+ multiple_birth_indicator = models.BooleanField(null=True, blank=True)
88
+ birth_order = models.BigIntegerField(null=True, blank=True)
89
+
90
+ default_location = models.ForeignKey(
91
+ "v1.PracticeLocation",
92
+ on_delete=models.SET_NULL,
93
+ default=None,
94
+ null=True,
95
+ blank=True,
96
+ related_name="default_patients",
97
+ )
98
+ default_provider = models.ForeignKey(
99
+ "v1.Staff",
100
+ on_delete=models.SET_NULL,
101
+ default=None,
102
+ null=True,
103
+ blank=True,
104
+ related_name="default_patients",
105
+ )
90
106
  user = models.ForeignKey("v1.CanvasUser", on_delete=models.DO_NOTHING, null=True)
91
107
 
92
- settings: RelatedManager[PatientSetting]
108
+ created = models.DateTimeField(auto_now_add=True)
109
+ modified = models.DateTimeField(auto_now=True)
93
110
 
94
111
  @classmethod
95
112
  def find(cls, id: str) -> Patient:
@@ -179,20 +196,23 @@ class PatientAddress(IdentifiableModel):
179
196
  class Meta:
180
197
  db_table = "canvas_sdk_data_api_patientaddress_001"
181
198
 
182
- line1 = models.CharField(max_length=255)
183
- line2 = models.CharField(max_length=255)
199
+ line1 = models.CharField(max_length=255, default="", blank=True)
200
+ line2 = models.CharField(max_length=255, default="", blank=True)
184
201
  city = models.CharField(max_length=255)
185
- district = models.CharField(max_length=255)
202
+ district = models.CharField(max_length=255, blank=True, default="")
186
203
  state_code = models.CharField(max_length=2)
187
204
  postal_code = models.CharField(max_length=255)
188
- use = models.CharField(choices=AddressUse.choices, max_length=10)
189
- type = models.CharField(choices=AddressType.choices, max_length=10)
190
- longitude = models.FloatField()
191
- latitude = models.FloatField()
192
- start = models.DateField()
193
- end = models.DateField()
205
+ use = models.CharField(choices=AddressUse.choices, max_length=10, default=AddressUse.HOME)
206
+ type = models.CharField(choices=AddressType.choices, max_length=10, default=AddressType.BOTH)
207
+ longitude = models.FloatField(null=True, blank=True)
208
+ latitude = models.FloatField(null=True, blank=True)
209
+ start = models.DateField(null=True, blank=True)
210
+ end = models.DateField(null=True, blank=True)
194
211
  country = models.CharField(max_length=255)
195
- state = models.CharField(choices=AddressState.choices, max_length=20)
212
+ state = models.CharField(
213
+ choices=AddressState.choices, max_length=20, default=AddressState.ACTIVE
214
+ )
215
+
196
216
  patient = models.ForeignKey(
197
217
  "v1.Patient", on_delete=models.DO_NOTHING, related_name="addresses", null=True
198
218
  )
@@ -11,8 +11,8 @@ class CanvasUser(Model):
11
11
 
12
12
  email = models.EmailField(db_column="email")
13
13
  phone_number = models.CharField(db_column="phone_number", max_length=255)
14
- last_invite_date_time = models.DateTimeField()
15
- is_portal_registered = models.BooleanField()
14
+ last_invite_date_time = models.DateTimeField(null=True, blank=True)
15
+ is_portal_registered = models.BooleanField(default=False)
16
16
 
17
17
 
18
18
  __exports__ = ("CanvasUser",)
@@ -0,0 +1,32 @@
1
+ import random
2
+ import string
3
+ import uuid
4
+ from collections.abc import Sequence
5
+ from decimal import Decimal
6
+
7
+
8
+ def quantize(deci: Decimal | float | str | tuple[int, Sequence[int], int]) -> Decimal:
9
+ """Rounds a Decimal value to two decimal places."""
10
+ return Decimal(deci).quantize(Decimal(".01"))
11
+
12
+
13
+ def create_key() -> str:
14
+ """Generates a unique key using UUID4."""
15
+ return uuid.uuid4().hex
16
+
17
+
18
+ def generate_mrn(length: int = 9, max_attempts: int = 100) -> str:
19
+ """Generates a unique Medical Record Number (MRN) of specified length."""
20
+ from canvas_sdk.v1.data import Patient
21
+
22
+ digits = string.digits
23
+
24
+ for _ in range(max_attempts):
25
+ mrn = "".join(random.choices(digits, k=length))
26
+ if not Patient.objects.filter(mrn=mrn).exists():
27
+ return mrn
28
+
29
+ raise RuntimeError(f"Unable to generate a unique MRN after {max_attempts} attempts")
30
+
31
+
32
+ __exports__ = ()
File without changes
@@ -9,11 +9,11 @@ dev = [
9
9
  "mypy>=1.17.0,<2",
10
10
  "pre-commit>=4.3.0,<5",
11
11
  "psutil>=7.0.0",
12
- "pytest",
13
12
  "pytest-cov",
14
- "pytest-django",
13
+ "pytest-django>=4.11,<5",
15
14
  "pytest-freezegun>=0.4.2",
16
15
  "pytest-mock",
16
+ "pytest>=8.4,<9",
17
17
  "python-semantic-release",
18
18
  "requests-mock",
19
19
  "ruff",
@@ -32,6 +32,7 @@ dependencies = [
32
32
  "django-timezone-utils>=0.15.0,<0.16",
33
33
  "django>=5.1.1,<6",
34
34
  "env-tools>=2.4.0,<3",
35
+ "factory-boy>=3.3.3",
35
36
  "frozendict>=2.4.6",
36
37
  "grpcio>=1.60.1,<2",
37
38
  "ipython>=8.21.0,<9",
@@ -57,7 +58,12 @@ license = "MIT"
57
58
  name = "canvas"
58
59
  readme = "README.md"
59
60
  requires-python = ">=3.11,<3.13"
60
- version = "0.57.1"
61
+ version = "0.58.0"
62
+
63
+ [project.optional-dependencies]
64
+ test-utils = [
65
+ "pytest-canvas"
66
+ ]
61
67
 
62
68
  [project.scripts]
63
69
  canvas = "canvas_cli.main:app"
@@ -111,6 +117,7 @@ strict_equality = true
111
117
  strict_optional = true
112
118
  untyped_calls_exclude = [
113
119
  "canvas_generated",
120
+ "factory",
114
121
  "redis"
115
122
  ] # https://github.com/python/typeshed/issues/10592
116
123
  warn_no_return = true
@@ -135,6 +142,7 @@ norecursedirs = [
135
142
  ".mypy_cache",
136
143
  ".pytest_cache",
137
144
  "__pycache__",
145
+ "canvas_cli/templates",
138
146
  "custom-plugins",
139
147
  "node_modules",
140
148
  "static",
@@ -108,18 +108,21 @@ if CANVAS_SDK_DB_BACKEND == "postgres":
108
108
  DATABASES = {"default": db_config}
109
109
 
110
110
  elif CANVAS_SDK_DB_BACKEND == "sqlite3":
111
+ SQLITE_DB_PATH = BASE_DIR / "canvas_db.sqlite3"
112
+ SQLITE_WRITE_MODE_DATABASE = {
113
+ "ENGINE": "django.db.backends.sqlite3",
114
+ "NAME": str(SQLITE_DB_PATH),
115
+ }
116
+
111
117
  DATABASES = {
112
118
  "default": {
113
119
  "ENGINE": "django.db.backends.sqlite3",
114
- "NAME": f"file:{str(BASE_DIR / 'db.sqlite3')}?mode=ro",
120
+ "NAME": f"file:{SQLITE_DB_PATH}?mode=ro",
115
121
  "OPTIONS": {"uri": True},
116
- },
117
- "default-write": {
118
- "ENGINE": "django.db.backends.sqlite3",
119
- "NAME": str(BASE_DIR / "db.sqlite3"),
120
- },
122
+ }
121
123
  }
122
124
 
125
+
123
126
  else:
124
127
  raise ImproperlyConfigured(
125
128
  "Unsupported database backend specified in 'CANVAS_SDK_DB_BACKEND' setting. "
@@ -1,16 +0,0 @@
1
- from plugin_runner.plugin_runner import main as run_server
2
-
3
-
4
- def run_plugin(plugin_directory: str) -> None:
5
- """
6
- Run the specified plugin for local development.
7
- """
8
- return run_plugins([plugin_directory])
9
-
10
-
11
- def run_plugins(plugin_directories: list[str]) -> None:
12
- """
13
- Run the specified plugins for local development.
14
- """
15
- run_server(plugin_directories)
16
- return
@@ -1,16 +0,0 @@
1
- import uuid
2
- from collections.abc import Sequence
3
- from decimal import Decimal
4
-
5
-
6
- def quantize(deci: Decimal | float | str | tuple[int, Sequence[int], int]) -> Decimal:
7
- """Rounds a Decimal value to two decimal places."""
8
- return Decimal(deci).quantize(Decimal(".01"))
9
-
10
-
11
- def create_key() -> str:
12
- """Generates a unique key using UUID4."""
13
- return uuid.uuid4().hex
14
-
15
-
16
- __exports__ = ()
File without changes
File without changes
File without changes