canvas 0.7.1__tar.gz → 0.8.1__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 (256) hide show
  1. {canvas-0.7.1 → canvas-0.8.1}/PKG-INFO +2 -2
  2. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/auth/tests.py +10 -0
  3. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/emit.py +0 -1
  4. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/logs/logs.py +4 -4
  5. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/plugin/plugin.py +55 -43
  6. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/plugin/tests.py +4 -2
  7. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/conftest.py +1 -0
  8. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/main.py +1 -2
  9. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py +1 -2
  10. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/tests.py +36 -26
  11. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/context/context.py +4 -2
  12. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/context/tests.py +1 -1
  13. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/print/tests.py +2 -2
  14. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/validators/tests.py +2 -1
  15. canvas-0.8.1/canvas_generated/messages/events_pb2.py +31 -0
  16. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/events_pb2.pyi +68 -0
  17. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/base.py +1 -1
  18. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/base.py +4 -6
  19. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/prescribe.py +3 -3
  20. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/reason_for_visit.py +1 -1
  21. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/task.py +3 -2
  22. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/vitals.py +0 -1
  23. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/constants.py +3 -1
  24. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/tests/protocol/tests.py +6 -1
  25. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/tests/schema/tests.py +5 -1
  26. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/tests/test_utils.py +27 -12
  27. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/tests/unit/tests.py +3 -0
  28. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/__init__.py +2 -0
  29. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/banner_alert/__init__.py +2 -0
  30. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/banner_alert/tests.py +22 -14
  31. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/protocol_card/__init__.py +2 -0
  32. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/protocol_card/tests.py +10 -6
  33. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/events/__init__.py +2 -0
  34. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/handlers/__init__.py +2 -0
  35. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/protocols/__init__.py +2 -0
  36. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/protocols/base.py +0 -2
  37. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/protocols/clinical_quality_measure.py +2 -1
  38. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/utils/http.py +2 -1
  39. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/utils/tests.py +4 -0
  40. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/__init__.py +13 -0
  41. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/allergy_intolerance.py +0 -1
  42. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/base.py +5 -5
  43. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/billing.py +2 -2
  44. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/common.py +0 -1
  45. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/patient.py +1 -1
  46. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/questionnaire.py +2 -1
  47. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/custom.py +0 -10
  48. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/tests/test_value_sets.py +4 -0
  49. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/individual_characteristic.py +12 -6
  50. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/procedure.py +4 -2
  51. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/value_set.py +1 -1
  52. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/plugin_runner.py +4 -3
  53. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/sandbox.py +6 -8
  54. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/test_plugin_runner.py +1 -2
  55. {canvas-0.7.1 → canvas-0.8.1}/pyproject.toml +30 -13
  56. {canvas-0.7.1 → canvas-0.8.1}/settings.py +3 -1
  57. canvas-0.7.1/canvas_generated/messages/events_pb2.py +0 -31
  58. {canvas-0.7.1 → canvas-0.8.1}/README.md +0 -0
  59. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/__init__.py +0 -0
  60. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/__init__.py +0 -0
  61. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/auth/__init__.py +0 -0
  62. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/auth/utils.py +0 -0
  63. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/__init__.py +0 -0
  64. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_CREATED.ndjson +0 -0
  65. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_UPDATED.ndjson +0 -0
  66. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CANCELED.ndjson +0 -0
  67. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CHECKED_IN.ndjson +0 -0
  68. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CREATED.ndjson +0 -0
  69. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_NO_SHOWED.ndjson +0 -0
  70. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESCHEDULED.ndjson +0 -0
  71. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_RESTORED.ndjson +0 -0
  72. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/APPOINTMENT_UPDATED.ndjson +0 -0
  73. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__CONDITION_SELECTED.ndjson +0 -0
  74. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_COMMIT.ndjson +0 -0
  75. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_ORIGINATE.ndjson +0 -0
  76. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__POST_UPDATE.ndjson +0 -0
  77. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_COMMIT.ndjson +0 -0
  78. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  79. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ASSESS_COMMAND__PRE_UPDATE.ndjson +0 -0
  80. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_CREATED.ndjson +0 -0
  81. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/BILLING_LINE_ITEM_UPDATED.ndjson +0 -0
  82. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/CONDITION_ASSESSED.ndjson +0 -0
  83. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/CONDITION_CREATED.ndjson +0 -0
  84. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/CONDITION_UPDATED.ndjson +0 -0
  85. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/CRON.ndjson +0 -0
  86. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ENCOUNTER_CREATED.ndjson +0 -0
  87. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/ENCOUNTER_UPDATED.ndjson +0 -0
  88. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_CREATED.ndjson +0 -0
  89. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_CREATED.ndjson +0 -0
  90. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_STATEMENT_UPDATED.ndjson +0 -0
  91. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/IMMUNIZATION_UPDATED.ndjson +0 -0
  92. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/INTERVIEW_CREATED.ndjson +0 -0
  93. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/INTERVIEW_UPDATED.ndjson +0 -0
  94. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/LAB_ORDER_CREATED.ndjson +0 -0
  95. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/LAB_ORDER_UPDATED.ndjson +0 -0
  96. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_CREATED.ndjson +0 -0
  97. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_LIST_ITEM_UPDATED.ndjson +0 -0
  98. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_COMMIT.ndjson +0 -0
  99. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_ORIGINATE.ndjson +0 -0
  100. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__POST_UPDATE.ndjson +0 -0
  101. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_COMMIT.ndjson +0 -0
  102. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  103. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT_COMMAND__PRE_UPDATE.ndjson +0 -0
  104. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/MEDICATION_STATEMENT__MEDICATION__POST_SEARCH.ndjson +0 -0
  105. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/PATIENT_CREATED.ndjson +0 -0
  106. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/PATIENT_UPDATED.ndjson +0 -0
  107. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__POST_ORIGINATE.ndjson +0 -0
  108. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/PLAN_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  109. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_COMMIT.ndjson +0 -0
  110. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_ORIGINATE.ndjson +0 -0
  111. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__POST_UPDATE.ndjson +0 -0
  112. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_COMMIT.ndjson +0 -0
  113. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_ORIGINATE.ndjson +0 -0
  114. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE_COMMAND__PRE_UPDATE.ndjson +0 -0
  115. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/QUESTIONNAIRE__QUESTIONNAIRE__POST_SEARCH.ndjson +0 -0
  116. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/TASK_COMMENT_CREATED.ndjson +0 -0
  117. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/TASK_CREATED.ndjson +0 -0
  118. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/TASK_UPDATED.ndjson +0 -0
  119. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_CREATED.ndjson +0 -0
  120. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_UPDATED.ndjson +0 -0
  121. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/logs/__init__.py +0 -0
  122. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/plugin/__init__.py +0 -0
  123. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/run_plugins/__init__.py +0 -0
  124. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/apps/run_plugins/run_plugins.py +0 -0
  125. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/templates/plugins/default/cookiecutter.json +0 -0
  126. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/CANVAS_MANIFEST.json +0 -0
  127. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/README.md +0 -0
  128. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/__init__.py +0 -0
  129. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/__init__.py +0 -0
  130. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/context/__init__.py +0 -0
  131. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/print/__init__.py +0 -0
  132. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/print/print.py +0 -0
  133. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/urls/__init__.py +0 -0
  134. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/urls/tests.py +0 -0
  135. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/urls/urls.py +0 -0
  136. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/validators/__init__.py +0 -0
  137. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/validators/manifest_schema.py +0 -0
  138. {canvas-0.7.1 → canvas-0.8.1}/canvas_cli/utils/validators/validators.py +0 -0
  139. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/effects_pb2.py +0 -0
  140. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/effects_pb2.pyi +0 -0
  141. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/effects_pb2_grpc.py +0 -0
  142. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/events_pb2_grpc.py +0 -0
  143. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/plugins_pb2.py +0 -0
  144. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/plugins_pb2.pyi +0 -0
  145. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/messages/plugins_pb2_grpc.py +0 -0
  146. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/services/plugin_runner_pb2.py +0 -0
  147. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/services/plugin_runner_pb2.pyi +0 -0
  148. {canvas-0.7.1 → canvas-0.8.1}/canvas_generated/services/plugin_runner_pb2_grpc.py +0 -0
  149. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/__init__.py +0 -0
  150. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/__init__.py +0 -0
  151. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/allergy.py +0 -0
  152. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/assess.py +0 -0
  153. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/close_goal.py +0 -0
  154. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/diagnose.py +0 -0
  155. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/family_history.py +0 -0
  156. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/goal.py +0 -0
  157. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/history_present_illness.py +0 -0
  158. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/instruct.py +0 -0
  159. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/lab_order.py +0 -0
  160. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/medical_history.py +0 -0
  161. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/medication_statement.py +0 -0
  162. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/past_surgical_history.py +0 -0
  163. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/perform.py +0 -0
  164. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/plan.py +0 -0
  165. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/questionnaire.py +0 -0
  166. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/refill.py +0 -0
  167. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/remove_allergy.py +0 -0
  168. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/stop_medication.py +0 -0
  169. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/update_diagnosis.py +0 -0
  170. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/commands/update_goal.py +0 -0
  171. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/tests/protocol/__init__.py +0 -0
  172. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/tests/schema/__init__.py +0 -0
  173. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/commands/tests/unit/__init__.py +0 -0
  174. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/banner_alert/add_banner_alert.py +0 -0
  175. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/banner_alert/remove_banner_alert.py +0 -0
  176. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/base.py +0 -0
  177. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/patient_chart_summary_configuration.py +0 -0
  178. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/protocol_card/protocol_card.py +0 -0
  179. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/effects/task/task.py +0 -0
  180. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/handlers/base.py +0 -0
  181. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/handlers/cron_task.py +0 -0
  182. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/protocols/timeframe.py +0 -0
  183. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/tests/__init__.py +0 -0
  184. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/utils/__init__.py +0 -0
  185. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/utils/db.py +0 -0
  186. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/utils/stats.py +0 -0
  187. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/__init__.py +0 -0
  188. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/command.py +0 -0
  189. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/condition.py +0 -0
  190. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/detected_issue.py +0 -0
  191. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/device.py +0 -0
  192. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/imaging.py +0 -0
  193. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/lab.py +0 -0
  194. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/medication.py +0 -0
  195. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/note.py +0 -0
  196. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/observation.py +0 -0
  197. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/protocol_override.py +0 -0
  198. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/staff.py +0 -0
  199. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/task.py +0 -0
  200. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/v1/data/user.py +0 -0
  201. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/__init__.py +0 -0
  202. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/__init__.py +0 -0
  203. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/adverse_event.py +0 -0
  204. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/allergy.py +0 -0
  205. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/assessment.py +0 -0
  206. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/communication.py +0 -0
  207. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/condition.py +0 -0
  208. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/device.py +0 -0
  209. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/diagnostic_study.py +0 -0
  210. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/encounter.py +0 -0
  211. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/immunization.py +0 -0
  212. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/intervention.py +0 -0
  213. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/laboratory_test.py +0 -0
  214. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/medication.py +0 -0
  215. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/physical_exam.py +0 -0
  216. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/value_set/v2022/symptom.py +0 -0
  217. {canvas-0.7.1 → canvas-0.8.1}/canvas_sdk/views/__init__.py +0 -0
  218. {canvas-0.7.1 → canvas-0.8.1}/logger/__init__.py +0 -0
  219. {canvas-0.7.1 → canvas-0.8.1}/logger/logger.py +0 -0
  220. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/__init__.py +0 -0
  221. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/authentication.py +0 -0
  222. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/plugin_synchronizer.py +0 -0
  223. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/__init__.py +0 -0
  224. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/data/plugins/.gitkeep +0 -0
  225. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json +0 -0
  226. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/example_plugin/README.md +0 -0
  227. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/example_plugin/__init__.py +0 -0
  228. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/example_plugin/protocols/__init__.py +0 -0
  229. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py +0 -0
  230. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json +0 -0
  231. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md +0 -0
  232. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/__init__.py +0 -0
  233. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/base.py +0 -0
  234. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/__init__.py +0 -0
  235. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py +0 -0
  236. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json +0 -0
  237. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md +0 -0
  238. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/__init__.py +0 -0
  239. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/base.py +0 -0
  240. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/__init__.py +0 -0
  241. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py +0 -0
  242. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json +0 -0
  243. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md +0 -0
  244. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/__init__.py +0 -0
  245. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/base.py +0 -0
  246. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/__init__.py +0 -0
  247. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py +0 -0
  248. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json +0 -0
  249. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md +0 -0
  250. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/__init__.py +0 -0
  251. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/base.py +0 -0
  252. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py +0 -0
  253. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py +0 -0
  254. {canvas-0.7.1 → canvas-0.8.1}/plugin_runner/tests/test_sandbox.py +0 -0
  255. {canvas-0.7.1 → canvas-0.8.1}/pubsub/__init__.py +0 -0
  256. {canvas-0.7.1 → canvas-0.8.1}/pubsub/pubsub.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: canvas
3
- Version: 0.7.1
3
+ Version: 0.8.1
4
4
  Summary: SDK to customize event-driven actions in your Canvas instance
5
5
  License: MIT
6
6
  Author: Canvas Team
@@ -15,7 +15,7 @@ Requires-Dist: cron-converter (>=1.2.1,<2.0.0)
15
15
  Requires-Dist: django (>=5.1.1,<6.0.0)
16
16
  Requires-Dist: django-stubs[compatible-mypy] (>=5.1.1,<6.0.0)
17
17
  Requires-Dist: django-timezone-utils (>=0.15.0,<0.16.0)
18
- Requires-Dist: env-tools (>=2.3.0,<3.0.0)
18
+ Requires-Dist: env-tools (>=2.4.0,<3.0.0)
19
19
  Requires-Dist: grpcio (>=1.60.1,<2.0.0)
20
20
  Requires-Dist: ipython (>=8.21.0,<9.0.0)
21
21
  Requires-Dist: jsonschema (>=4.21.1,<5.0.0)
@@ -8,6 +8,8 @@ from canvas_cli.apps.auth import get_or_request_api_token
8
8
 
9
9
  @pytest.fixture
10
10
  def valid_token_response() -> Any:
11
+ """Returns a valid token response."""
12
+
11
13
  class TokenResponse:
12
14
  status_code = 200
13
15
 
@@ -19,6 +21,8 @@ def valid_token_response() -> Any:
19
21
 
20
22
  @pytest.fixture
21
23
  def error_token_response() -> Any:
24
+ """Returns an error token response."""
25
+
22
26
  class TokenResponse:
23
27
  status_code = 500
24
28
 
@@ -27,6 +31,8 @@ def error_token_response() -> Any:
27
31
 
28
32
  @pytest.fixture
29
33
  def expired_token_response() -> Any:
34
+ """Returns an expired token response."""
35
+
30
36
  class TokenResponse:
31
37
  status_code = 200
32
38
 
@@ -45,6 +51,7 @@ def test_get_or_request_api_token_uses_stored_token(
45
51
  mock_get_password: MagicMock,
46
52
  valid_token_response: Any,
47
53
  ) -> None:
54
+ """Test that get_or_request_api_token uses a stored token if it is valid."""
48
55
  mock_is_token_valid.return_value = True
49
56
  mock_get_password.return_value = "a-stored-valid-token"
50
57
  mock_post.return_value = valid_token_response
@@ -66,6 +73,7 @@ def test_get_or_request_api_token_requests_token_if_none_stored(
66
73
  mock_set_password: MagicMock,
67
74
  valid_token_response: Any,
68
75
  ) -> None:
76
+ """Test that get_or_request_api_token requests a new token if none is stored."""
69
77
  mock_client_credentials.return_value = "client_id=id&client_secret=secret"
70
78
  mock_get_password.return_value = None
71
79
  mock_post.return_value = valid_token_response
@@ -95,6 +103,7 @@ def test_get_or_request_api_token_raises_exception_if_error_token_response(
95
103
  mock_get_password: MagicMock,
96
104
  error_token_response: Any,
97
105
  ) -> None:
106
+ """Test that get_or_request_api_token raises an exception if an error token response is received."""
98
107
  mock_client_credentials.return_value = "client_id=id&client_secret=secret"
99
108
  mock_get_password.return_value = None
100
109
  mock_post.return_value = error_token_response
@@ -123,6 +132,7 @@ def test_get_or_request_api_token_raises_exception_if_expired_token(
123
132
  mock_get_password: MagicMock,
124
133
  expired_token_response: Any,
125
134
  ) -> None:
135
+ """Test that get_or_request_api_token raises an exception if an expired token is received."""
126
136
  mock_client_credentials.return_value = "client_id=id&client_secret=secret"
127
137
  mock_get_password.return_value = None
128
138
  mock_post.return_value = expired_token_response
@@ -7,7 +7,6 @@ import grpc
7
7
  import typer
8
8
 
9
9
  from canvas_generated.messages.events_pb2 import Event as PluginRunnerEvent
10
- from canvas_generated.messages.events_pb2 import EventType as PluginRunnerEventType
11
10
  from canvas_generated.services.plugin_runner_pb2_grpc import PluginRunnerStub
12
11
 
13
12
 
@@ -1,5 +1,5 @@
1
1
  import json
2
- from typing import Optional, cast
2
+ from typing import cast
3
3
  from urllib.parse import urlparse
4
4
 
5
5
  import typer
@@ -31,9 +31,9 @@ def _on_open(ws: websocket.WebSocket) -> None:
31
31
 
32
32
 
33
33
  def logs(
34
- host: Optional[str] = typer.Option(
34
+ host: str | None = typer.Option(
35
35
  callback=get_default_host, help="Canvas instance to connect to", default=None
36
- )
36
+ ),
37
37
  ) -> None:
38
38
  """Listens and prints log streams from the instance."""
39
39
  if not host:
@@ -62,4 +62,4 @@ def logs(
62
62
  ws.run_forever()
63
63
 
64
64
  except KeyboardInterrupt:
65
- raise typer.Exit(0)
65
+ raise typer.Exit(0) from None
@@ -2,8 +2,9 @@ import ast
2
2
  import json
3
3
  import tarfile
4
4
  import tempfile
5
+ from collections.abc import Iterable
5
6
  from pathlib import Path
6
- from typing import Any, List, Optional, cast
7
+ from typing import Any, cast
7
8
  from urllib.parse import urljoin
8
9
 
9
10
  import requests
@@ -53,14 +54,15 @@ def _build_package(package: Path) -> Path:
53
54
  def _get_name_from_metadata(host: str, token: str, package: Path) -> str | None:
54
55
  """Extract metadata from a provided package and return the package name if it exists in the metadata."""
55
56
  try:
56
- metadata_response = requests.post(
57
- plugin_url(host, "extract-metadata"),
58
- headers={"Authorization": f"Bearer {token}"},
59
- files={"package": open(package, "rb")},
60
- )
57
+ with open(package) as package_file:
58
+ metadata_response = requests.post(
59
+ plugin_url(host, "extract-metadata"),
60
+ headers={"Authorization": f"Bearer {token}"},
61
+ files={"package": package_file},
62
+ )
61
63
  except requests.exceptions.RequestException:
62
64
  print(f"Failed to connect to {host}")
63
- raise typer.Exit(1)
65
+ raise typer.Exit(1) from None
64
66
 
65
67
  if metadata_response.status_code != requests.codes.ok:
66
68
  print(f"Status code {metadata_response.status_code}: {metadata_response.text}")
@@ -116,8 +118,8 @@ def _get_meta_properties(protocol_path: Path, classname: str) -> dict[str, str]:
116
118
 
117
119
 
118
120
  def _get_protocols_with_new_cqm_properties(
119
- protocol_classes: List[dict[str, Any]], plugin: Path
120
- ) -> List[dict[str, Any]] | None:
121
+ protocol_classes: Iterable[dict[str, Any]], plugin: Path
122
+ ) -> Iterable[dict[str, Any]] | None:
121
123
  """Extract the meta properties of any ClinicalQualityMeasure Protocols included in the plugin if they have changed."""
122
124
  has_updates = False
123
125
  protocol_props = []
@@ -146,14 +148,14 @@ def init() -> None:
146
148
  try:
147
149
  project_dir = cookiecutter(str(template))
148
150
  except OutputDirExistsException:
149
- raise typer.BadParameter(f"The supplied directory already exists")
151
+ raise typer.BadParameter("The supplied directory already exists") from None
150
152
 
151
153
  print(f"Project created in {project_dir}")
152
154
 
153
155
 
154
156
  def install(
155
157
  plugin_name: Path = typer.Argument(..., help="Path to plugin to install"),
156
- host: Optional[str] = typer.Option(
158
+ host: str | None = typer.Option(
157
159
  callback=get_default_host,
158
160
  help="Canvas instance to connect to",
159
161
  default=None,
@@ -181,15 +183,16 @@ def install(
181
183
  print(f"Posting {built_package_path.absolute()} to {url}")
182
184
 
183
185
  try:
184
- r = requests.post(
185
- url,
186
- data={"is_enabled": True},
187
- files={"package": open(built_package_path, "rb")},
188
- headers={"Authorization": f"Bearer {token}"},
189
- )
186
+ with open(built_package_path, "rb") as package:
187
+ r = requests.post(
188
+ url,
189
+ data={"is_enabled": True},
190
+ files={"package": package},
191
+ headers={"Authorization": f"Bearer {token}"},
192
+ )
190
193
  except requests.exceptions.RequestException:
191
194
  print(f"Failed to connect to {host}")
192
- raise typer.Exit(1)
195
+ raise typer.Exit(1) from None
193
196
 
194
197
  if r.status_code == requests.codes.created:
195
198
  print(f"Plugin {plugin_name} successfully installed!")
@@ -207,7 +210,7 @@ def install(
207
210
 
208
211
  def uninstall(
209
212
  name: str = typer.Argument(..., help="Plugin name to uninstall"),
210
- host: Optional[str] = typer.Option(
213
+ host: str | None = typer.Option(
211
214
  callback=get_default_host,
212
215
  help="Canvas instance to connect to",
213
216
  default=None,
@@ -232,7 +235,7 @@ def uninstall(
232
235
  )
233
236
  except requests.exceptions.RequestException:
234
237
  print(f"Failed to connect to {host}")
235
- raise typer.Exit(1)
238
+ raise typer.Exit(1) from None
236
239
 
237
240
  if r.status_code == requests.codes.no_content:
238
241
  print(f"Plugin {name} successfully uninstalled!")
@@ -243,7 +246,7 @@ def uninstall(
243
246
 
244
247
  def enable(
245
248
  name: str = typer.Argument(..., help="Plugin name to enable"),
246
- host: Optional[str] = typer.Option(
249
+ host: str | None = typer.Option(
247
250
  callback=get_default_host,
248
251
  help="Canvas instance to connect to",
249
252
  default=None,
@@ -269,7 +272,7 @@ def enable(
269
272
  )
270
273
  except requests.exceptions.RequestException:
271
274
  print(f"Failed to connect to {host}")
272
- raise typer.Exit(1)
275
+ raise typer.Exit(1) from None
273
276
 
274
277
  if r.ok:
275
278
  print(f"Plugin {name} successfully enabled!")
@@ -280,7 +283,7 @@ def enable(
280
283
 
281
284
  def disable(
282
285
  name: str = typer.Argument(..., help="Plugin name to disable"),
283
- host: Optional[str] = typer.Option(
286
+ host: str | None = typer.Option(
284
287
  callback=get_default_host,
285
288
  help="Canvas instance to connect to",
286
289
  default=None,
@@ -306,7 +309,7 @@ def disable(
306
309
  )
307
310
  except requests.exceptions.RequestException:
308
311
  print(f"Failed to connect to {host}")
309
- raise typer.Exit(1)
312
+ raise typer.Exit(1) from None
310
313
 
311
314
  if r.ok:
312
315
  print(f"Plugin {name} successfully disabled!")
@@ -316,11 +319,11 @@ def disable(
316
319
 
317
320
 
318
321
  def list(
319
- host: Optional[str] = typer.Option(
322
+ host: str | None = typer.Option(
320
323
  callback=get_default_host,
321
324
  help="Canvas instance to connect to",
322
325
  default=None,
323
- )
326
+ ),
324
327
  ) -> None:
325
328
  """List all plugins from a Canvas instance."""
326
329
  if not host:
@@ -337,7 +340,7 @@ def list(
337
340
  )
338
341
  except requests.exceptions.RequestException:
339
342
  print(f"Failed to connect to {host}")
340
- raise typer.Exit(1)
343
+ raise typer.Exit(1) from None
341
344
 
342
345
  if r.status_code == requests.codes.ok:
343
346
  plugins = r.json().get("results", [])
@@ -382,7 +385,7 @@ def validate_manifest(
382
385
 
383
386
  except json.JSONDecodeError:
384
387
  print("There was a problem loading the manifest file, please ensure it's valid JSON")
385
- raise typer.Abort()
388
+ raise typer.Abort() from None
386
389
 
387
390
  validate_manifest_file(manifest_json)
388
391
 
@@ -391,14 +394,14 @@ def validate_manifest(
391
394
 
392
395
  def update(
393
396
  name: str = typer.Argument(..., help="Plugin name to update"),
394
- package: Optional[Path] = typer.Option(
397
+ package_path: Path | None = typer.Option(
395
398
  help="Path to a wheel or sdist file containing the python package to install",
396
399
  default=None,
397
400
  ),
398
- is_enabled: Optional[bool] = typer.Option(
401
+ is_enabled: bool | None = typer.Option(
399
402
  None, "--enable/--disable", show_default=False, help="Enable/disable the plugin"
400
403
  ),
401
- host: Optional[str] = typer.Option(
404
+ host: str | None = typer.Option(
402
405
  callback=get_default_host,
403
406
  help="Canvas instance to connect to",
404
407
  default=None,
@@ -408,27 +411,36 @@ def update(
408
411
  if not host:
409
412
  raise typer.BadParameter("Please specify a host or set a default via the `auth` command")
410
413
 
411
- if package:
412
- validate_package(package)
414
+ if package_path:
415
+ validate_package(package_path)
413
416
 
414
417
  token = get_or_request_api_token(host)
415
418
 
416
- print(f"Updating plugin {name} from {host} with {is_enabled=}, {package=}")
417
-
418
- binary_package = {"package": open(package, "rb")} if package else None
419
+ print(f"Updating plugin {name} from {host} with {is_enabled=}, {package_path=}")
419
420
 
420
421
  url = plugin_url(host, name)
421
422
 
422
423
  try:
423
- r = requests.patch(
424
- url,
425
- data={"is_enabled": is_enabled} if is_enabled is not None else {},
426
- files=binary_package,
427
- headers={"Authorization": f"Bearer {token}"},
428
- )
424
+ data = {"is_enabled": is_enabled} if is_enabled is not None else {}
425
+ headers = {"Authorization": f"Bearer {token}"}
426
+
427
+ if package_path:
428
+ with open(package_path, "rb") as package:
429
+ r = requests.patch(
430
+ url,
431
+ data=data,
432
+ headers=headers,
433
+ files={"package": package},
434
+ )
435
+ else:
436
+ r = requests.patch(
437
+ url,
438
+ data=data,
439
+ headers=headers,
440
+ )
429
441
  except requests.exceptions.RequestException:
430
442
  print(f"Failed to connect to {host}")
431
- raise typer.Exit(1)
443
+ raise typer.Exit(1) from None
432
444
 
433
445
  if r.status_code == requests.codes.ok:
434
446
  print("Plugin successfully updated!")
@@ -1,7 +1,8 @@
1
1
  import shutil
2
+ from collections.abc import Generator
2
3
  from datetime import datetime
3
4
  from pathlib import Path
4
- from typing import Any, Generator
5
+ from typing import Any
5
6
 
6
7
  import pytest
7
8
  import typer
@@ -39,12 +40,13 @@ def test_validate_package_valid_file(tmp_path: Path) -> None:
39
40
 
40
41
  @pytest.fixture(scope="session")
41
42
  def init_plugin_name() -> str:
42
- """The plugin name to be used for the canvas cli init test"""
43
+ """The plugin name to be used for the canvas cli init test."""
43
44
  return f"testing_init-{datetime.now().timestamp()}".replace(".", "")
44
45
 
45
46
 
46
47
  @pytest.fixture(autouse=True, scope="session")
47
48
  def clean_up_plugin(init_plugin_name: str) -> Generator[Any, Any, Any]:
49
+ """Cleans up the plugin directory after the test."""
48
50
  yield
49
51
  if Path(f"./{init_plugin_name}").exists():
50
52
  shutil.rmtree(Path(f"./{init_plugin_name}"))
@@ -19,6 +19,7 @@ def monkeypatch_app_dir(tmp_path: Path, monkeypatch: pytest.MonkeyPatch) -> None
19
19
  @pytest.fixture(autouse=True)
20
20
  def reset_context_variables() -> None:
21
21
  """Reset the context properties to their default value.
22
+
22
23
  This is needed because we cannot build a `reset` method in the CLIContext class,
23
24
  because `load_from_file` loads properties dynamically.
24
25
  Also since this is a CLI, it's not expected to keep the global context in memory for more than a run,
@@ -1,6 +1,5 @@
1
1
  import importlib.metadata
2
2
  from pathlib import Path
3
- from typing import Optional
4
3
 
5
4
  import typer
6
5
 
@@ -62,7 +61,7 @@ def get_or_create_config_file() -> Path:
62
61
 
63
62
  @app.callback()
64
63
  def main(
65
- version: Optional[bool] = typer.Option(
64
+ version: bool | None = typer.Option(
66
65
  None, "--version", callback=version_callback, is_eager=True
67
66
  ),
68
67
  ) -> None:
@@ -50,5 +50,4 @@ class Protocol(BaseProtocol):
50
50
 
51
51
  # Return zero, one, or many effects.
52
52
  # Example:
53
- # return [Effect(type=EffectType.LOG, payload=json.dumps(payload))]
54
- return []
53
+ return [Effect(type=EffectType.LOG, payload=json.dumps(payload))]
@@ -1,8 +1,9 @@
1
1
  import os
2
2
  import shutil
3
+ from collections.abc import Callable, Generator
3
4
  from datetime import datetime
4
5
  from pathlib import Path
5
- from typing import Any, Callable, Generator, cast
6
+ from typing import Any, cast
6
7
  from unittest.mock import MagicMock, patch
7
8
  from urllib.parse import urlparse
8
9
 
@@ -20,14 +21,13 @@ runner = CliRunner()
20
21
 
21
22
  @pytest.fixture(scope="session")
22
23
  def plugin_name() -> str:
23
- """The plugin name to be used for the canvas cli test"""
24
+ """The plugin name to be used for the canvas cli test."""
24
25
  return f"cli-{datetime.now().timestamp()}".replace(".", "")
25
26
 
26
27
 
27
28
  @pytest.fixture(scope="session")
28
29
  def create_or_update_config_auth_file_for_testing(plugin_name: str) -> Generator[None, None, None]:
29
30
  """Creates the necessary config file for auth before performing cli tests."""
30
-
31
31
  if not settings.INTEGRATION_TEST_URL:
32
32
  raise ImproperlyConfigured("INTEGRATION_TEST_URL is not set")
33
33
 
@@ -45,19 +45,27 @@ def create_or_update_config_auth_file_for_testing(plugin_name: str) -> Generator
45
45
 
46
46
  temp_path = path.parent / "temp_credentials.ini"
47
47
 
48
- original_content = open(path, "r").read()
49
- open(path, "w").writelines(
50
- [
51
- f"[{host}]\n",
52
- f"client_id={client_id}\n",
53
- f"client_secret={client_secret}\n",
54
- ]
55
- )
56
- open(temp_path, "a").write(original_content)
48
+ # Read the original content
49
+ with open(path) as original_file:
50
+ original_content = original_file.read()
51
+
52
+ # Write new content to the original file
53
+ with open(path, "w") as original_file:
54
+ original_file.writelines(
55
+ [
56
+ f"[{host}]\n",
57
+ f"client_id={client_id}\n",
58
+ f"client_secret={client_secret}\n",
59
+ ]
60
+ )
61
+
62
+ # Append original content to the temp file
63
+ with open(temp_path, "a") as temp_file:
64
+ temp_file.write(original_content)
57
65
 
58
66
  yield
59
67
 
60
- with open(temp_path, "r") as temp:
68
+ with open(temp_path) as temp:
61
69
  original_content = temp.read()
62
70
  with open(path, "w") as f:
63
71
  f.write(original_content)
@@ -66,9 +74,10 @@ def create_or_update_config_auth_file_for_testing(plugin_name: str) -> Generator
66
74
 
67
75
  @pytest.fixture(autouse=True, scope="session")
68
76
  def write_plugin(plugin_name: str) -> Generator[Any, Any, Any]:
77
+ """Writes a plugin to the file system."""
69
78
  runner.invoke(app, "init", input=plugin_name)
70
- protocol = open(f"./{plugin_name}/protocols/my_protocol.py", "w")
71
- p = """
79
+
80
+ protocol_code = """
72
81
  from canvas_sdk.events import EventType
73
82
  from canvas_sdk.protocols import BaseProtocol
74
83
  from logger import log
@@ -81,8 +90,9 @@ class Protocol(BaseProtocol):
81
90
  log.info(self.NARRATIVE_STRING)
82
91
  return []
83
92
  """
84
- protocol.write(p)
85
- protocol.close()
93
+
94
+ with open(f"./{plugin_name}/protocols/my_protocol.py", "w") as protocol:
95
+ protocol.write(protocol_code)
86
96
 
87
97
  yield
88
98
 
@@ -91,12 +101,12 @@ class Protocol(BaseProtocol):
91
101
 
92
102
 
93
103
  def list_empty_plugins(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
94
- """Step 1 - list all plugins"""
104
+ """Step 1 - list all plugins."""
95
105
  return ("list", 0, [], [f"{plugin_name}"])
96
106
 
97
107
 
98
108
  def install_new_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
99
- """Step 2 - install a new plugin"""
109
+ """Step 2 - install a new plugin."""
100
110
  return (
101
111
  f"install {plugin_name}",
102
112
  0,
@@ -111,12 +121,12 @@ def install_new_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]
111
121
 
112
122
 
113
123
  def list_newly_installed_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
114
- """Step 3 - list all plugins, including newly installed one"""
124
+ """Step 3 - list all plugins, including newly installed one."""
115
125
  return ("list", 0, [f"{plugin_name}@0.0.1 enabled"], [])
116
126
 
117
127
 
118
128
  def disable_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
119
- """Step 4 - disable plugin"""
129
+ """Step 4 - disable plugin."""
120
130
  return (
121
131
  f"disable {plugin_name}",
122
132
  0,
@@ -126,12 +136,12 @@ def disable_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
126
136
 
127
137
 
128
138
  def list_disabled_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
129
- """Step 5 - list disabled plugin"""
139
+ """Step 5 - list disabled plugin."""
130
140
  return ("list", 0, [f"{plugin_name}@0.0.1 disabled"], [])
131
141
 
132
142
 
133
143
  def enable_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
134
- """Step 6 - enable the disabled plugin"""
144
+ """Step 6 - enable the disabled plugin."""
135
145
  return (
136
146
  f"enable {plugin_name}",
137
147
  0,
@@ -141,7 +151,7 @@ def enable_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
141
151
 
142
152
 
143
153
  def uninstall_enabled_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
144
- """Step 7 - try to uninstall the enabled plugin"""
154
+ """Step 7 - try to uninstall the enabled plugin."""
145
155
  return (
146
156
  f"uninstall {plugin_name}",
147
157
  1,
@@ -154,7 +164,7 @@ def uninstall_enabled_plugin(plugin_name: str) -> tuple[str, int, list[str], lis
154
164
 
155
165
 
156
166
  def uninstall_disabled_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
157
- """Step 8 - disable and then uninstall the plugin"""
167
+ """Step 8 - disable and then uninstall the plugin."""
158
168
  runner.invoke(app, f"disable {plugin_name}")
159
169
 
160
170
  return (
@@ -192,7 +202,7 @@ def test_canvas_list_install_disable_enable_uninstall(
192
202
  create_or_update_config_auth_file_for_testing: None,
193
203
  step: Callable,
194
204
  ) -> None:
195
- """Tests that the Canvas CLI can list, install, disable, enable, and uninstall a plugin"""
205
+ """Tests that the Canvas CLI can list, install, disable, enable, and uninstall a plugin."""
196
206
  mock_get_password.return_value = None
197
207
  mock_set_password.return_value = None
198
208
 
@@ -1,7 +1,8 @@
1
1
  import functools
2
2
  import json
3
+ from collections.abc import Callable
3
4
  from pathlib import Path
4
- from typing import Any, Callable, TypeVar, cast
5
+ from typing import Any, TypeVar, cast
5
6
 
6
7
  import typer
7
8
 
@@ -12,6 +13,7 @@ F = TypeVar("F", bound=Callable)
12
13
 
13
14
  class CLIContext:
14
15
  """Class that handles configuration across the CLI.
16
+
15
17
  Includes methods for:
16
18
  * Loading a JSON file with configuration keys into memory.
17
19
  * Making a property transient (default, value is not persisted) or persistent (via decorators)
@@ -118,7 +120,7 @@ class CLIContext:
118
120
  success=False,
119
121
  path=str(file),
120
122
  )
121
- raise typer.Abort()
123
+ raise typer.Abort() from None
122
124
 
123
125
  self._config_file_path = file
124
126
 
@@ -1,7 +1,7 @@
1
1
  import json
2
2
  import os
3
+ from collections.abc import Generator
3
4
  from pathlib import Path
4
- from typing import Generator
5
5
 
6
6
  import pytest
7
7
  import typer
@@ -18,7 +18,7 @@ def test_print_json_outputs_valid_json(message: Any, capfd: pytest.CaptureFixtur
18
18
  try:
19
19
  json.loads(output)
20
20
  except ValueError as exc:
21
- assert False, f"{output} is not valid json: {exc}"
21
+ assert AssertionError(f"{output} is not valid json: {exc}")
22
22
 
23
23
 
24
24
  def test_print_json_outputs_kwargs(capfd: pytest.CaptureFixture[str]) -> None:
@@ -33,7 +33,7 @@ def test_print_json_outputs_kwargs(capfd: pytest.CaptureFixture[str]) -> None:
33
33
  assert json_dict.get("a_dict") == {"one": 2}
34
34
 
35
35
  except ValueError as exc:
36
- assert False, f"{output} is not valid json: {exc}"
36
+ assert AssertionError(f"{output} is not valid json: {exc}")
37
37
 
38
38
 
39
39
  def test_print_overrides_default(capfd: pytest.CaptureFixture[str]) -> None:
@@ -5,6 +5,7 @@ from canvas_cli.utils.validators import validate_manifest_file
5
5
 
6
6
  @pytest.fixture
7
7
  def protocol_manifest_example() -> dict:
8
+ """Return a valid protocol manifest example."""
8
9
  return {
9
10
  "sdk_version": "0.3.1",
10
11
  "plugin_version": "1.0.1",
@@ -32,5 +33,5 @@ def protocol_manifest_example() -> dict:
32
33
 
33
34
 
34
35
  def test_manifest_file_schema(protocol_manifest_example: dict) -> None:
35
- """Test that no exception raised when a valid manifest file is validated"""
36
+ """Test that no exception raised when a valid manifest file is validated."""
36
37
  validate_manifest_file(protocol_manifest_example)