canvas 0.7.1__py3-none-any.whl → 0.8.1__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of canvas might be problematic. Click here for more details.

Files changed (58) hide show
  1. {canvas-0.7.1.dist-info → canvas-0.8.1.dist-info}/METADATA +2 -2
  2. {canvas-0.7.1.dist-info → canvas-0.8.1.dist-info}/RECORD +58 -58
  3. canvas_cli/apps/auth/tests.py +10 -0
  4. canvas_cli/apps/emit/emit.py +0 -1
  5. canvas_cli/apps/logs/logs.py +4 -4
  6. canvas_cli/apps/plugin/plugin.py +55 -43
  7. canvas_cli/apps/plugin/tests.py +4 -2
  8. canvas_cli/conftest.py +1 -0
  9. canvas_cli/main.py +1 -2
  10. canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py +1 -2
  11. canvas_cli/tests.py +36 -26
  12. canvas_cli/utils/context/context.py +4 -2
  13. canvas_cli/utils/context/tests.py +1 -1
  14. canvas_cli/utils/print/tests.py +2 -2
  15. canvas_cli/utils/validators/tests.py +2 -1
  16. canvas_generated/messages/events_pb2.py +2 -2
  17. canvas_generated/messages/events_pb2.pyi +68 -0
  18. canvas_sdk/base.py +1 -1
  19. canvas_sdk/commands/base.py +4 -6
  20. canvas_sdk/commands/commands/prescribe.py +3 -3
  21. canvas_sdk/commands/commands/reason_for_visit.py +1 -1
  22. canvas_sdk/commands/commands/task.py +3 -2
  23. canvas_sdk/commands/commands/vitals.py +0 -1
  24. canvas_sdk/commands/constants.py +3 -1
  25. canvas_sdk/commands/tests/protocol/tests.py +6 -1
  26. canvas_sdk/commands/tests/schema/tests.py +5 -1
  27. canvas_sdk/commands/tests/test_utils.py +27 -12
  28. canvas_sdk/commands/tests/unit/tests.py +3 -0
  29. canvas_sdk/effects/__init__.py +2 -0
  30. canvas_sdk/effects/banner_alert/__init__.py +2 -0
  31. canvas_sdk/effects/banner_alert/tests.py +22 -14
  32. canvas_sdk/effects/protocol_card/__init__.py +2 -0
  33. canvas_sdk/effects/protocol_card/tests.py +10 -6
  34. canvas_sdk/events/__init__.py +2 -0
  35. canvas_sdk/handlers/__init__.py +2 -0
  36. canvas_sdk/protocols/__init__.py +2 -0
  37. canvas_sdk/protocols/base.py +0 -2
  38. canvas_sdk/protocols/clinical_quality_measure.py +2 -1
  39. canvas_sdk/utils/http.py +2 -1
  40. canvas_sdk/utils/tests.py +4 -0
  41. canvas_sdk/v1/data/__init__.py +13 -0
  42. canvas_sdk/v1/data/allergy_intolerance.py +0 -1
  43. canvas_sdk/v1/data/base.py +5 -5
  44. canvas_sdk/v1/data/billing.py +2 -2
  45. canvas_sdk/v1/data/common.py +0 -1
  46. canvas_sdk/v1/data/patient.py +1 -1
  47. canvas_sdk/v1/data/questionnaire.py +2 -1
  48. canvas_sdk/value_set/custom.py +0 -10
  49. canvas_sdk/value_set/tests/test_value_sets.py +4 -0
  50. canvas_sdk/value_set/v2022/individual_characteristic.py +12 -6
  51. canvas_sdk/value_set/v2022/procedure.py +4 -2
  52. canvas_sdk/value_set/value_set.py +1 -1
  53. plugin_runner/plugin_runner.py +4 -3
  54. plugin_runner/sandbox.py +6 -8
  55. plugin_runner/tests/test_plugin_runner.py +1 -2
  56. settings.py +3 -1
  57. {canvas-0.7.1.dist-info → canvas-0.8.1.dist-info}/WHEEL +0 -0
  58. {canvas-0.7.1.dist-info → canvas-0.8.1.dist-info}/entry_points.txt +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)
@@ -1,10 +1,10 @@
1
1
  canvas_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
2
  canvas_cli/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
3
  canvas_cli/apps/auth/__init__.py,sha256=gIwJ2qWvRlLqbiRkudrGqTKV-orlb8OTkG487qoRda4,105
4
- canvas_cli/apps/auth/tests.py,sha256=WK7hSLTK95gEweMRaj3RdPC-qSwjnuulxMUg6D0bY_k,4528
4
+ canvas_cli/apps/auth/tests.py,sha256=_q8YvSN1zVgWh_RyWCo4Dkme67tr0ioQ10AkfkpvTbc,5030
5
5
  canvas_cli/apps/auth/utils.py,sha256=IH5oZB3pdlb4_FRfCZKkNTncx_kdKagpiBqlhtM8h2U,5434
6
6
  canvas_cli/apps/emit/__init__.py,sha256=Fvv6SIbeGV2S5NkigQtamcRwJXIT1n7UcM-wrQoYsRQ,64
7
- canvas_cli/apps/emit/emit.py,sha256=Dj6k9uzL9fF1CbZ_4UYj_bIqCJn_hPBh9iWj2GG2fho,2623
7
+ canvas_cli/apps/emit/emit.py,sha256=5a-wfpWI7K5Nq6YQjS4VCMt-10LfZQ5CDFNUeLy9mzQ,2539
8
8
  canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_CREATED.ndjson,sha256=C0mKBU_zP19WAn3EVRArQ7Pl3FBCyHXOmE9x7ZIKTss,110
9
9
  canvas_cli/apps/emit/event_fixtures/ALLERGY_INTOLERANCE_UPDATED.ndjson,sha256=P2TpFVC13fgg9fFPjfY-NX-hYdXLN-jOE0fmwDY9aMk,110
10
10
  canvas_cli/apps/emit/event_fixtures/APPOINTMENT_CANCELED.ndjson,sha256=5E0JNrfdJfVlW24xkwanHkxUvbMukcdmYpv4OvLqRkI,103
@@ -63,39 +63,39 @@ canvas_cli/apps/emit/event_fixtures/TASK_UPDATED.ndjson,sha256=5K0x5fjO7fwDVvvpp
63
63
  canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_CREATED.ndjson,sha256=p5XQozktqGA9-C6HDXJ3cxDmrYe4p705WdrWE-2R9Dk,1414
64
64
  canvas_cli/apps/emit/event_fixtures/VITAL_SIGN_UPDATED.ndjson,sha256=Er0aUWIYkqbL9JdCaiNBuzizuHiOmFQr5Q2uYTtWj8I,36764
65
65
  canvas_cli/apps/logs/__init__.py,sha256=ehY9SRb6nBw81xZF50yyBlUZJtNR2VeVSNI5sFuWJ7o,64
66
- canvas_cli/apps/logs/logs.py,sha256=ISKRGtphc-fXlLwwsti48rJNs-R9GFjosihao_B29g4,1974
66
+ canvas_cli/apps/logs/logs.py,sha256=BFpZ-2OF2Rs1EMLePo5UjqC9fKQeqm8qZobNTFNCL_M,1972
67
67
  canvas_cli/apps/plugin/__init__.py,sha256=G_nLsu6cdko5OjatnbqUyEboGcNlGGLwpZmCBxMKdfo,236
68
- canvas_cli/apps/plugin/plugin.py,sha256=srH8hUQ_i5TFTQnvNw2-Btkvg7UvTjVZSMRB0LlgkLA,14352
69
- canvas_cli/apps/plugin/tests.py,sha256=nH-LunSfkpFIvcONVeJxr8JQ-z5vZmuZFaZJanB2m2s,2661
68
+ canvas_cli/apps/plugin/plugin.py,sha256=i1c4aKNlUrqlvQSz8agIi8aW2wWb8E5t6oh8sOpVJxw,14826
69
+ canvas_cli/apps/plugin/tests.py,sha256=SsYeYY25ly9TMn-nkJEZjLaPCyFbT4vs1sN_FnQbJ5U,2746
70
70
  canvas_cli/apps/run_plugins/__init__.py,sha256=iAMgX_6D3CdjQodGx_azwhSjouaxquOm8Z8QVXnlTFE,117
71
71
  canvas_cli/apps/run_plugins/run_plugins.py,sha256=qsf6-UhFAZpIL-1C50fzSoIwXMsZISxg2fxzM46UHTA,384
72
- canvas_cli/conftest.py,sha256=pGvVS6VT0Zll_Lp3ezLh2jykOk-2HTBVH8RP5FwLUVw,930
73
- canvas_cli/main.py,sha256=X-ziOQzEEd58asH9PZatQJ79SaLuNAGV_sf9e6lw5sM,2759
72
+ canvas_cli/conftest.py,sha256=0mEjjU7_w9nq-HCvscxFJClw-EeyQYujNLLRPssksZQ,931
73
+ canvas_cli/main.py,sha256=L6JQkt1yxy30cA3-M9v7JD8WMW4i0M5GPr9kZetAito,2728
74
74
  canvas_cli/templates/plugins/default/cookiecutter.json,sha256=dWEB3wJ8U4bko8jX26PgLLg_jgWlafLTNqsGnY1PUcg,124
75
75
  canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/CANVAS_MANIFEST.json,sha256=9N0u5hN0GqjPvUh_B3YHtvyntEvxUGbInbQeprU0TS0,787
76
76
  canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/README.md,sha256=3QKoJQq3YmdplGnDOBMsLCJ3Ya1_aKjoz-QiWc4QfjA,291
77
77
  canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
78
- canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py,sha256=vVV2P59dLZGdWUmkxgeepAjTWOVgag1jSqP9EYLB24I,2240
79
- canvas_cli/tests.py,sha256=2TlU3a6JOdZ-IZ3pO2JLiG2NL8MxGL8kpaSeySoozIg,6162
78
+ canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py,sha256=tYogBLVrydzlH77e2kgGUNjzhfQLKgxyobDwSq3Q6HA,2220
79
+ canvas_cli/tests.py,sha256=kY3eeDL-EIlNCeeTponVeqz9Zb5S12imUUCSzEXuYFw,6527
80
80
  canvas_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
81
81
  canvas_cli/utils/context/__init__.py,sha256=HhYvI-hydP0mV18nJiU7uo5gk0yN7EYNgouxieoGDOE,102
82
- canvas_cli/utils/context/context.py,sha256=RIDGCQPLLtelzhXperboouSwYXSNBjLDtq18kH4nr1c,5153
83
- canvas_cli/utils/context/tests.py,sha256=fbnNm_4ZpzFdBGZtzR90mjHa5tMosEE6VLHrwcfl4-k,4266
82
+ canvas_cli/utils/context/context.py,sha256=wk4TxlslF52uD9nXcEZ1eY8L1rcEHk7k-6YBVwaWnVY,5191
83
+ canvas_cli/utils/context/tests.py,sha256=ApQ50Eqzps8wHgVC6DWNRdCRCYTip5UhbQnIF1jutb8,4275
84
84
  canvas_cli/utils/print/__init__.py,sha256=zkRiQCUhPIB3wNGeJ1Hwfd12zJyvbRRiWqequJORvdE,88
85
85
  canvas_cli/utils/print/print.py,sha256=p3Z47LphrV1-lI3RbU_0P8dtUgs9EJjZLDwv-hbwLG8,1401
86
- canvas_cli/utils/print/tests.py,sha256=rJnMlpMOMVkPHiFE2mJ_KNbpLKDK5qA8ZdwUvYxaIAU,2367
86
+ canvas_cli/utils/print/tests.py,sha256=Q8Y6Aq6wW02zHXxJH1t56IQAlTa88WKlyW45PmqZngk,2385
87
87
  canvas_cli/utils/urls/__init__.py,sha256=08hlrQhQ1pKBjlIRaC0j53IkgK723jfK8-j3djvR0ko,81
88
88
  canvas_cli/utils/urls/tests.py,sha256=opXDF2i3lXTdsKJ7ywIRzWDDzZ5KAO0JbGIR3hbJdoE,407
89
89
  canvas_cli/utils/urls/urls.py,sha256=KwWTh5ERrEsZEvdBrZpZB71xtyWkDuglpXUbycWmBOo,798
90
90
  canvas_cli/utils/validators/__init__.py,sha256=rBvSR2O1hWkNAnUBdcr-zUkmqT796_A61b9pnvEhwrM,113
91
91
  canvas_cli/utils/validators/manifest_schema.py,sha256=_WCqFat9AGnOdYWQh20hfWJL-_4d3gDY5PpNQt2AHIE,3165
92
- canvas_cli/utils/validators/tests.py,sha256=cZHLSx7oteOfLOoU1tXGvw88n6itcvUT2B3ZBg-bmEY,1206
92
+ canvas_cli/utils/validators/tests.py,sha256=KhaOdbxGUK2QwL2KnycAJJkqclYQSXF7CKg-scSf0DU,1259
93
93
  canvas_cli/utils/validators/validators.py,sha256=lrUBQ0sF7seTe_pNGsNgASdr2BGp6g-Qui58V4H9qfQ,1598
94
94
  canvas_generated/messages/effects_pb2.py,sha256=2ie5j_MhD4boYsIZiDIWE30xSCXl4nunXcuQcMUkzTY,7800
95
95
  canvas_generated/messages/effects_pb2.pyi,sha256=ecDvQX8UYu0rb-4g6QVSgNWMT9v2WOJwiBdJ0JpU-IU,13349
96
96
  canvas_generated/messages/effects_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
97
- canvas_generated/messages/events_pb2.py,sha256=KMsUKG3T5I1YFzAxFHDOuLI3PSRCbh51pFkoD2mrEIs,37055
98
- canvas_generated/messages/events_pb2.pyi,sha256=kNLyigWqgULpMCHBg9Ge8IGj_AIfG6lyj8swQ_yCIjA,65996
97
+ canvas_generated/messages/events_pb2.py,sha256=l5xpLXJikwHNUoG1-OtatOAjBPOrVlId7xOflINs-YU,39424
98
+ canvas_generated/messages/events_pb2.pyi,sha256=lnY4i2HoC0F-srnnqnT8BemIhJNeY8Hlke-3cb5gFHI,70388
99
99
  canvas_generated/messages/events_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
100
100
  canvas_generated/messages/plugins_pb2.py,sha256=j2yt9uoSlVMtWg-cAoOmxiT-XWbBrqqCBZXOxEz7z4g,1271
101
101
  canvas_generated/messages/plugins_pb2.pyi,sha256=G1seqytP8GlJJh-AL2CJ0VyUNlReEvK61C-Oh8QuGiE,501
@@ -104,9 +104,9 @@ canvas_generated/services/plugin_runner_pb2.py,sha256=RfAo_imYoSuoexq-1IHhMhXZgQ
104
104
  canvas_generated/services/plugin_runner_pb2.pyi,sha256=1w-Pa4k7HtlmQAr7B6sgV64zdZplBKQKHN-S8bjwO3w,265
105
105
  canvas_generated/services/plugin_runner_pb2_grpc.py,sha256=EzJJVkP_AZ3dwBA7OxUito0NSalRmjjg8q9TZ_P18ww,4549
106
106
  canvas_sdk/__init__.py,sha256=d7V1Qsp4hSqp8opmvqp-0J33uibArUjwENMfzSDAdZg,102
107
- canvas_sdk/base.py,sha256=Qp_bcUFaoGBRtDXuYyTZyQC1Q6-El3w-J5Gkg8U3ps8,2040
107
+ canvas_sdk/base.py,sha256=aaWilIx70lsAE76x7QaJolyIvcFnXDGPw1UMv9t0FDw,2035
108
108
  canvas_sdk/commands/__init__.py,sha256=ApJy2i8IRCL2YFUumk1q-YihLL2YcmLYKKiWFK04evY,2365
109
- canvas_sdk/commands/base.py,sha256=WX6nnP1OlH4LT28N_xmE55gS_FbFcZuLk_dIvSK49VY,5226
109
+ canvas_sdk/commands/base.py,sha256=ScfOo4QXTInhTf6OGLT5dEu81yhZAcgVT8qxwIKWbow,5155
110
110
  canvas_sdk/commands/commands/allergy.py,sha256=_S0tY43sErRlTeUGCC6Thb8gMSD_JiOmRSFdLaDlr48,1296
111
111
  canvas_sdk/commands/commands/assess.py,sha256=IjsvkhzKinRaykMRzbnk6G4JAkzDhyqGG6ZvjDhNAuE,1723
112
112
  canvas_sdk/commands/commands/close_goal.py,sha256=RTmi8fGPEEag8YSrlsPn7sy9Y-WymVuU8IWpXRKgNjg,792
@@ -121,56 +121,56 @@ canvas_sdk/commands/commands/medication_statement.py,sha256=qnX--dtB5wV9Jz6smhq_
121
121
  canvas_sdk/commands/commands/past_surgical_history.py,sha256=mbY1G8MG8jFmyBNL633EL3z3hQDOJfl0tCgBlpQ0M8s,887
122
122
  canvas_sdk/commands/commands/perform.py,sha256=FpumHzPJp5pzb4F0CBW2QbSWdR_5mpib1PTOK5amvZc,470
123
123
  canvas_sdk/commands/commands/plan.py,sha256=uxjXmdNcG32R4S0CJ7fqDaaXTMiJJH9RuvwlWuztlZ0,403
124
- canvas_sdk/commands/commands/prescribe.py,sha256=crgL2FnS8FaLu-C9GWQeMe9W7_gnvO5OH_ku_sVr8OA,2223
124
+ canvas_sdk/commands/commands/prescribe.py,sha256=CWk25bQtpHb7KTNnCIPGaIGEnUQagAJ8fnbRnyPIssc,2176
125
125
  canvas_sdk/commands/commands/questionnaire.py,sha256=Giu4stTzpddO8fH3iVyxm2lUeDwe7AmhfuIfb_0WUj4,644
126
- canvas_sdk/commands/commands/reason_for_visit.py,sha256=20i2A8V4of_Q-Kqb37k-fUJ-JaHVGsrMtoIGZAYhPNw,1480
126
+ canvas_sdk/commands/commands/reason_for_visit.py,sha256=NX_hKyWg2HXFO03uWLOFwrO1v2-kVeez1CSlFIQ38eA,1479
127
127
  canvas_sdk/commands/commands/refill.py,sha256=HC9Nl3_BkGn3HRZ-4YNT9lqIywFVom6PyJChK3_0Zyc,458
128
128
  canvas_sdk/commands/commands/remove_allergy.py,sha256=6CXo3s63z7oqMlROExPWudQBZeSvD3x0SC_efQSb0Lw,748
129
129
  canvas_sdk/commands/commands/stop_medication.py,sha256=h-I95y2P7EgOsKMarHDp8C_MVdpB90e-fzqDWv8-haM,715
130
- canvas_sdk/commands/commands/task.py,sha256=5oQRIocOUKr6O__XMFFr-2DjZv-q1zA0Erbj4_hkruw,1330
130
+ canvas_sdk/commands/commands/task.py,sha256=p-WskHqj_q8TqllarEw73AIW6n2J7uzyIso9l5aLTkY,1342
131
131
  canvas_sdk/commands/commands/update_diagnosis.py,sha256=fqPcKBaiRemo8Qa4H4g6ZvKM2YczVlj9FxpBGjs8J9Q,824
132
132
  canvas_sdk/commands/commands/update_goal.py,sha256=ddvxlDnoTm5k-G5aJ-pW2fMIC-s5K8jYia9tISXsxAk,1580
133
- canvas_sdk/commands/commands/vitals.py,sha256=ZmAok_oMy5Txv52cEmwnLWi0ET9BLmRIMgpbjtMTa4c,3155
134
- canvas_sdk/commands/constants.py,sha256=eYzVI3wKBQUfRbfDm8CoGaKWmkBOwtDeeL91znK6a5A,341
133
+ canvas_sdk/commands/commands/vitals.py,sha256=hOuDXbNwqJbsBAvvkpjrXWqssrdQPxEfCox1NlI0h4A,3127
134
+ canvas_sdk/commands/constants.py,sha256=RqnokmQns-v0QErE1tCxFqFnDxsbRhigRMeTPqLTvz0,360
135
135
  canvas_sdk/commands/tests/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
136
- canvas_sdk/commands/tests/protocol/tests.py,sha256=AZrN5vk082ZfZzoJtY-ckezC4acofKL5CJZ_EXg3l9s,1506
136
+ canvas_sdk/commands/tests/protocol/tests.py,sha256=9dvN3cEKNW2LM408RkIjeQJbtBg55TqV5ceX8Z4cRcI,1746
137
137
  canvas_sdk/commands/tests/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
- canvas_sdk/commands/tests/schema/tests.py,sha256=ggegssIRQK1ACn7oFp31tCsq19reUfsAvM9OL7mh67s,3505
139
- canvas_sdk/commands/tests/test_utils.py,sha256=0ulIUaIx-srwA_Pbuyx8--XW85Enc9oPlqchutt56UU,9622
138
+ canvas_sdk/commands/tests/schema/tests.py,sha256=rSu146RouMrPLv0G-E6QtgQhG2vkUCCk1M3Baa6fXBg,3701
139
+ canvas_sdk/commands/tests/test_utils.py,sha256=K105HTXCBMy3KS7yShRWBodTNgQ1PPopU0ZeD32dV2s,10383
140
140
  canvas_sdk/commands/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
141
- canvas_sdk/commands/tests/unit/tests.py,sha256=SAgB_gaO3ah69RKgMjp4XzO6WnQjeNR9awOE8BR7IkA,9697
142
- canvas_sdk/effects/__init__.py,sha256=oChQi5y_8mK2zDiNMwWYp6CaQX1_zbmwXILPF7iSt-4,69
143
- canvas_sdk/effects/banner_alert/__init__.py,sha256=8z5l9rwonKEcRkvD5q4DWvHPYhKJzwyGuUYoUNKYwX4,158
141
+ canvas_sdk/commands/tests/unit/tests.py,sha256=FsjNpUxkS4F89g341uuc5GkMCTp_JACTx32wxcwYcWg,9948
142
+ canvas_sdk/effects/__init__.py,sha256=q07D5Wz2YL0uSx_hMYLNeSam-1bt_TKHdY8p7de6qeM,105
143
+ canvas_sdk/effects/banner_alert/__init__.py,sha256=PcMmOjLHP_MOZiP8157JkTdcO4mZTn-kFcRylOB9AK0,209
144
144
  canvas_sdk/effects/banner_alert/add_banner_alert.py,sha256=W4Fv9IHGCWvVtFiH3s68JBRpUb8b3xsncGt2WfgMFc0,1681
145
145
  canvas_sdk/effects/banner_alert/remove_banner_alert.py,sha256=PK_LzXBQ-rOH3fX182ISyutu4W69xyGgMX-1G4g4XhY,613
146
- canvas_sdk/effects/banner_alert/tests.py,sha256=6vid5_pDeBSqgqDoeUeaVsflE0bnuSFgLpfSFV7pXLY,8531
146
+ canvas_sdk/effects/banner_alert/tests.py,sha256=rugzxlHpmIyOpd9gpYI0s1iNWwLJKTldNVBcXenMsLE,9026
147
147
  canvas_sdk/effects/base.py,sha256=znIaDNkCYbzJxf4Q80hLRYUG5H73c8IMq1UCzeBcXjw,714
148
148
  canvas_sdk/effects/patient_chart_summary_configuration.py,sha256=_Gx7UIp4NLaSYYLLcBSOjtOD4Skqot_kt_x8zI3Ccwo,1184
149
- canvas_sdk/effects/protocol_card/__init__.py,sha256=ESzUYajBBmcTAad2PIwHuV3SgGj4B9JHtf9uop_V4YA,88
149
+ canvas_sdk/effects/protocol_card/__init__.py,sha256=AwXAARybFhVIfYwqiRThG6Ne3ARnKgvuvuGUknWpwTo,134
150
150
  canvas_sdk/effects/protocol_card/protocol_card.py,sha256=aL8lXRBm1ByU-X0xzgBepxKnUTLvmr-OC7G-C-EBjy8,2596
151
- canvas_sdk/effects/protocol_card/tests.py,sha256=oL_LZMIVTbPz0bBjrK7KO5dlJncFLfVcqjo1ToO3_O4,6498
151
+ canvas_sdk/effects/protocol_card/tests.py,sha256=ZiDZTjn-Z6UpEfR1S-6XDcJXlPlTPpLbg2PgvkQD8Uk,6815
152
152
  canvas_sdk/effects/task/task.py,sha256=olG7gJN3CC1JKrGU4SdVvRq8qLduPuiNz80C_dTaY58,2837
153
- canvas_sdk/events/__init__.py,sha256=JGZ-3uf0Luzr4kg5UqduupD4w6B2WVEgQ9WlcoMaPwE,81
154
- canvas_sdk/handlers/__init__.py,sha256=VVz2_Xyb9720R2MZmSbGPG0T8u2a5u6zSDkWlwiJZv4,49
153
+ canvas_sdk/events/__init__.py,sha256=uz3VkfY77TsRptFKOmy7V9CJmebbbf1oK2aRb8FOurA,132
154
+ canvas_sdk/handlers/__init__.py,sha256=GeE8w0ev-ThuLJjcgb49OsXM58VmcB16ErU13tE_9tY,77
155
155
  canvas_sdk/handlers/base.py,sha256=7kw95-nYOsphP2_dVoJxBvi2RsuUpwBo5RcKvo924Yw,599
156
156
  canvas_sdk/handlers/cron_task.py,sha256=Q4_D3bDKE5hyEpCf0JnGSgZlnLh_g9RSP3oEfIuLJ9Y,945
157
- canvas_sdk/protocols/__init__.py,sha256=t9PD9lCQbWPT1tW6s8w8J5nK-Hb4i5MLCSKnX2Q3eow,132
158
- canvas_sdk/protocols/base.py,sha256=cMCfrLqsdcXfl1mRkRl-tCTgDsUHlxfL4BrwGNkSYe4,177
159
- canvas_sdk/protocols/clinical_quality_measure.py,sha256=yXG-20vCD90N9NUqZ2YKlc4_WDsqYlo_DFHLWw0pyOY,3528
157
+ canvas_sdk/protocols/__init__.py,sha256=3u9zet5D4DX4V953tLCoN1xhaOhAUCwGwscMv-7IIxo,186
158
+ canvas_sdk/protocols/base.py,sha256=GhFZejVrbMdVQ2LkLlRQh0m0wHA7XSUGD0GA3NyeT8U,153
159
+ canvas_sdk/protocols/clinical_quality_measure.py,sha256=8Z3onmmIA8hW0k8-nierCqahlpGuofT52grAP4Dv2fU,3548
160
160
  canvas_sdk/protocols/timeframe.py,sha256=SlTDhTy0TqPXKS9JZFeTVApQJDf8C-NIRLqFJltB17g,1148
161
161
  canvas_sdk/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
162
162
  canvas_sdk/utils/__init__.py,sha256=sFuhqcWvXb2-33FOuXZgWuUeC5jZL2MDoqjGoQZGwd8,60
163
163
  canvas_sdk/utils/db.py,sha256=0AO5bhu-k9OsAHpXe1RHzyDZnBGHUEzrv8-vYtTIoeA,592
164
- canvas_sdk/utils/http.py,sha256=6t2h2ULHcX3eHCpUuHl7rqjLvHg794O6ubDxgzd_2Yg,2240
164
+ canvas_sdk/utils/http.py,sha256=NFEfBT1IaUJVOWFfmzkpxRbhzis7bO1Z7lX_b-LOx_U,2267
165
165
  canvas_sdk/utils/stats.py,sha256=sJhIW_IssUVefQN6rrUAt1P0KvVIUIYcnpZlMHLibNA,732
166
- canvas_sdk/utils/tests.py,sha256=t3MScbIfzXkQttMIvj0dRzJlFVS8LFU8WgWRrChM-H0,1931
166
+ canvas_sdk/utils/tests.py,sha256=0Buh_7PvDU1D081_rSJoYSJwIHMOBbL0gtGS3bSKe7s,2285
167
167
  canvas_sdk/v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
168
- canvas_sdk/v1/data/__init__.py,sha256=DovVoH2i4LJmtVcip8JoQUhecXkIWkOeVclKKJzCUBM,241
169
- canvas_sdk/v1/data/allergy_intolerance.py,sha256=KJg7UR8BJMuASWL5zXZ57JTmC0TQT7FAnODPvdq2mFg,2093
170
- canvas_sdk/v1/data/base.py,sha256=SBnAVSrUvh2lAP5UuYFDlJQ-xT2aQzWyzzMIjhhfS4s,6195
171
- canvas_sdk/v1/data/billing.py,sha256=8zZ8by4rdRmDBXH7mwwxuKC8lQ2NueF-EyzBh3y9Gh8,2046
168
+ canvas_sdk/v1/data/__init__.py,sha256=zm9ZDNey6cFR3Bw4QtQ7wWfpwkxDt256SZN-FORxFP0,437
169
+ canvas_sdk/v1/data/allergy_intolerance.py,sha256=WmBDis-XuMPdyuUhLuv36KFyNUvP7Zg8Y8lacp1nGRY,2039
170
+ canvas_sdk/v1/data/base.py,sha256=ZMZEpwkeg3ewl3QsbPAF7-z1MqqWu5hCR-IibWQCiHI,6189
171
+ canvas_sdk/v1/data/billing.py,sha256=w5vK7aWqOGEkgjrzJWTiDsywUdxFdK7naEImZkvKxHk,2040
172
172
  canvas_sdk/v1/data/command.py,sha256=z9LHw95Vq8efZE5y9r-Ei-Yzt8qj-o-BE3x9BBb4yPQ,945
173
- canvas_sdk/v1/data/common.py,sha256=cx4MYTjCrf7Vja0WUKuY1lUPV9Uy7eapBipsx-clZ5g,3513
173
+ canvas_sdk/v1/data/common.py,sha256=OvF4Oxo3BqE1Cv2lfyA1MXp_q_VHwoihyiJ0ETfa5lY,3459
174
174
  canvas_sdk/v1/data/condition.py,sha256=EHDb9o1ixXFLZKODCpp-2Wvhc6OmiA0ENPSzRId6pAU,1858
175
175
  canvas_sdk/v1/data/detected_issue.py,sha256=c1rKZuPV_tTp_1yDJJa88gIsixpPV_F-a3eooje8BW8,1710
176
176
  canvas_sdk/v1/data/device.py,sha256=uxeQRT8ljzBmDwsARFDB9MZKAVAKOA-pu4nAa6fcHeU,1655
@@ -179,15 +179,15 @@ canvas_sdk/v1/data/lab.py,sha256=nGV2FGDtnj7NcO8WS5LRXv5JUiLjuWMtm0i-PUNsKLk,103
179
179
  canvas_sdk/v1/data/medication.py,sha256=PGOOTnhrPSSExSuQJyIdsDLSg09riMb2usvpRmcUo7s,1998
180
180
  canvas_sdk/v1/data/note.py,sha256=cC0fifgVby04YcjuOAVycpfsDGIGaJ8_INFRXQID2wU,6607
181
181
  canvas_sdk/v1/data/observation.py,sha256=BftaK7tOZaTlfUKoTH_A-X23J4DUFRVWpvZhkBJ1DJg,3710
182
- canvas_sdk/v1/data/patient.py,sha256=0qNdc0JbihikNQaQE3D8Ne82-UmjI9FleQ3aTBYrzC4,2744
182
+ canvas_sdk/v1/data/patient.py,sha256=0OB07_w2DoAYwCFU0mIZ2KDqcM5uwTG9wyhEOepd2pQ,2729
183
183
  canvas_sdk/v1/data/protocol_override.py,sha256=Dra2qf5-VX7qsK5mWy6U5XU7Y9v4NGkobRU4BAeAxkU,1835
184
- canvas_sdk/v1/data/questionnaire.py,sha256=wZNj8wg5aEThrHvA6-Oq5USnViyoeYGlcD5cjNmiULM,6899
184
+ canvas_sdk/v1/data/questionnaire.py,sha256=8RIX_YtxCZd2NK9hK41ehywHA5vHks1wqigZf5LHPvI,6908
185
185
  canvas_sdk/v1/data/staff.py,sha256=J-U5NeKH-P41ph6pWiTd5v-QYQHV0GmvxxGVVUUf1nc,2786
186
186
  canvas_sdk/v1/data/task.py,sha256=9N66XL4B51rla4Q-Tn7STIGvR5Qr6-DNqfMYnT6t8yE,3585
187
187
  canvas_sdk/v1/data/user.py,sha256=DmA8fNNGwiNOmuR-RYxQw1NpxN5yYhgwtRtRBRJ_22g,309
188
188
  canvas_sdk/value_set/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
189
- canvas_sdk/value_set/custom.py,sha256=5ehqic2rROvIgf326LTWhX3hWulatKGQZrEaUzFagCw,18022
190
- canvas_sdk/value_set/tests/test_value_sets.py,sha256=by9_pOl-8cvwBt_y1HSqf6sP8RBsh9XjRkLMVz7caWo,2804
189
+ canvas_sdk/value_set/custom.py,sha256=33ceZ416kJ4sftqMGTQVUpmfMyydSl51gpxmmilM6F0,17842
190
+ canvas_sdk/value_set/tests/test_value_sets.py,sha256=ZoDdR6npR9L8h7qGdQj3B7lRghHI3PBV3klRDYV7wak,3116
191
191
  canvas_sdk/value_set/v2022/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
192
192
  canvas_sdk/value_set/v2022/adverse_event.py,sha256=8zsNFBsLDRY0mrPomzogD-W15xyo2CFFkiEcT2ruGCg,1032
193
193
  canvas_sdk/value_set/v2022/allergy.py,sha256=n_P8Aqso5M6spTsatp4K4hzlbwaC3rjUBZs2bZsFVVg,11132
@@ -198,22 +198,22 @@ canvas_sdk/value_set/v2022/device.py,sha256=TvEXAzC_nnzmHEY2cWZqfLr_niFyXsJ5YqUe
198
198
  canvas_sdk/value_set/v2022/diagnostic_study.py,sha256=wo4AQu2p5X51HZ3RsbU5NhUpgv8Fg2mPKs2YexWCMjA,301934
199
199
  canvas_sdk/value_set/v2022/encounter.py,sha256=PxOkkob8ggpDxKfKG9EtmQQ2teGWCTOeX7_5IJqLiZI,370965
200
200
  canvas_sdk/value_set/v2022/immunization.py,sha256=dYPWL2Un1HTUrjKZTh_MBPVmU2ImtMXVaMqVRKP_7MA,13189
201
- canvas_sdk/value_set/v2022/individual_characteristic.py,sha256=1NZI2r4-9x2qTbYTkjUOAU9PgvMOBB3cpddHFr7msaU,13198
201
+ canvas_sdk/value_set/v2022/individual_characteristic.py,sha256=KgKGV8eq6chWjO_D9tqej1py5w7_DGQSxGPor4pPLYA,13333
202
202
  canvas_sdk/value_set/v2022/intervention.py,sha256=1N0I6pE-RoBgqtQtlBWwTiVYk2ztobUK1TTl1EpKgH4,78653
203
203
  canvas_sdk/value_set/v2022/laboratory_test.py,sha256=x-o7SAjYw5sS9x8tGPcYUg03L_mKxxDu0b6LJsnjmQc,77876
204
204
  canvas_sdk/value_set/v2022/medication.py,sha256=L1yNzrwD2nUox8F6x8RSKhmFsn9VcFbFEy1nM7AHRis,316430
205
205
  canvas_sdk/value_set/v2022/physical_exam.py,sha256=C5PfLR4YB6pB_0wIy6Wfocyso5a9wuwGoKj84k_jR-U,7645
206
- canvas_sdk/value_set/v2022/procedure.py,sha256=MA1yBHJskzGyp0nypzTwrR6u4pxZTo20Iv25W4FOIjM,367721
206
+ canvas_sdk/value_set/v2022/procedure.py,sha256=CxbGfQc_YkQa1JpwZq90uSLaSSD4k-gPWmVNz3ard9E,367807
207
207
  canvas_sdk/value_set/v2022/symptom.py,sha256=4-ouetYI8soAAZy9Gq8AXBiqTfJjdgfZgWZPhBE-Ing,9384
208
- canvas_sdk/value_set/value_set.py,sha256=SFufN1LeqUjWNqr1ymScNhaDlFXRLGOK53ckwiHUxIY,3936
208
+ canvas_sdk/value_set/value_set.py,sha256=KPrnlrbzzbspqmdFtPnt_raWscXiKiyTOMcPfVavt2w,3929
209
209
  canvas_sdk/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
210
210
  logger/__init__.py,sha256=9o2iRCjzFEhfULgXvrrECRFK-4IslWJTqKKjTCEUbq8,61
211
211
  logger/logger.py,sha256=axf7UffBJtETjwDCtmi1IaaJKsvcFj8zaLfouGsq68A,1847
212
212
  plugin_runner/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
213
213
  plugin_runner/authentication.py,sha256=SDPso2AogtLAV_H0LuMDp99IMZuF3oTq-Q_AXAvJ8uc,1116
214
- plugin_runner/plugin_runner.py,sha256=Ae7ApJLeV_wo431wfqXHdE1xEkOcGrnOQ8TvHKQ3mkw,13447
214
+ plugin_runner/plugin_runner.py,sha256=qnN0Ujsbs4if0fiJIIJ_CMEubdc6z9Y3yJXtb8Kq98I,13451
215
215
  plugin_runner/plugin_synchronizer.py,sha256=t3zzfDw-bDK_hvUDQ434qaQuKLGgBGndzaCRAnSpuTU,2554
216
- plugin_runner/sandbox.py,sha256=vXzG_4i29OT4zQtldsEyf2eb_PB3V8MtBoJS92slw4E,9595
216
+ plugin_runner/sandbox.py,sha256=7eMZNuKy3H_JQZo11kAdev7lUoMYpg0DiEbs_bKrzbk,9501
217
217
  plugin_runner/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
218
218
  plugin_runner/tests/data/plugins/.gitkeep,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
219
219
  plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json,sha256=J9T_E5vqUX4HITHbFsd6JQpw3YvMS4wR_lhI5JL2KMk,749
@@ -245,12 +245,12 @@ plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/__i
245
245
  plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/base.py,sha256=tCBNAaKH8x-Ngyxru4Zzsiq7z3KSh9PUoKZ8EEKE5iU,83
246
246
  plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
247
247
  plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py,sha256=V_6DPXsJaD12zGyKqGjYY2JFtKEk4E0eIAgBWax_MGc,629
248
- plugin_runner/tests/test_plugin_runner.py,sha256=KVTAE7jKbcKF2_5VUH4bkfPwemXpJeuA_kQA1nanDjQ,7514
248
+ plugin_runner/tests/test_plugin_runner.py,sha256=8w0nnt6PAnmnJbX-UDtRVEPh9JXdT_PlLy0JBbjoRHU,7522
249
249
  plugin_runner/tests/test_sandbox.py,sha256=I44rz0sbxqtWm6mAG8fGhneE1yu9M-K3PMkE4zqHG0A,3438
250
250
  pubsub/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
251
251
  pubsub/pubsub.py,sha256=pyTW0JU8mtaqiAV6g6xjZwel1CVy2EonPMU-_vkmhUM,1044
252
- settings.py,sha256=to4MXxHXTnDhhPpc8JbPuIMtxPX9cCZFuE5tfBwbROQ,2065
253
- canvas-0.7.1.dist-info/METADATA,sha256=YAoFCVq9zqh6gJAfMFSVEwByfyGgc-rygPuDLhsO80w,4663
254
- canvas-0.7.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
255
- canvas-0.7.1.dist-info/entry_points.txt,sha256=VSmSo1IZ3aEfL7enmLmlWSraS_IIkoXNVeyXzgRxFiY,46
256
- canvas-0.7.1.dist-info/RECORD,,
252
+ settings.py,sha256=6YTybI0eNeuDamnXdRrEUOBICf9bM1uW1lCwj4IR9sU,2081
253
+ canvas-0.8.1.dist-info/METADATA,sha256=oRCTBDikhw0IZcizZpGWXye9dYRtt0cKV_gk2snL3BE,4663
254
+ canvas-0.8.1.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
255
+ canvas-0.8.1.dist-info/entry_points.txt,sha256=VSmSo1IZ3aEfL7enmLmlWSraS_IIkoXNVeyXzgRxFiY,46
256
+ canvas-0.8.1.dist-info/RECORD,,
@@ -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}"))
canvas_cli/conftest.py CHANGED
@@ -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,
canvas_cli/main.py CHANGED
@@ -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))]