canvas 0.1.15__py3-none-any.whl → 0.2.10__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 (94) hide show
  1. {canvas-0.1.15.dist-info → canvas-0.2.10.dist-info}/METADATA +7 -1
  2. canvas-0.2.10.dist-info/RECORD +143 -0
  3. canvas_cli/apps/plugin/plugin.py +51 -9
  4. canvas_cli/apps/plugin/tests.py +51 -0
  5. canvas_cli/tests.py +193 -4
  6. canvas_cli/utils/validators/manifest_schema.py +1 -0
  7. canvas_generated/messages/effects_pb2.py +2 -2
  8. canvas_generated/messages/effects_pb2.pyi +138 -0
  9. canvas_generated/messages/events_pb2.py +3 -3
  10. canvas_generated/messages/events_pb2.pyi +616 -0
  11. canvas_sdk/__init__.py +7 -0
  12. canvas_sdk/base.py +6 -2
  13. canvas_sdk/commands/__init__.py +26 -0
  14. canvas_sdk/commands/base.py +35 -32
  15. canvas_sdk/commands/commands/allergy.py +49 -0
  16. canvas_sdk/commands/commands/assess.py +1 -1
  17. canvas_sdk/commands/commands/close_goal.py +22 -0
  18. canvas_sdk/commands/commands/diagnose.py +3 -3
  19. canvas_sdk/commands/commands/family_history.py +18 -0
  20. canvas_sdk/commands/commands/goal.py +3 -3
  21. canvas_sdk/commands/commands/history_present_illness.py +1 -1
  22. canvas_sdk/commands/commands/instruct.py +17 -0
  23. canvas_sdk/commands/commands/lab_order.py +33 -0
  24. canvas_sdk/commands/commands/medical_history.py +34 -0
  25. canvas_sdk/commands/commands/medication_statement.py +1 -1
  26. canvas_sdk/commands/commands/past_surgical_history.py +28 -0
  27. canvas_sdk/commands/commands/perform.py +17 -0
  28. canvas_sdk/commands/commands/plan.py +2 -2
  29. canvas_sdk/commands/commands/prescribe.py +10 -7
  30. canvas_sdk/commands/commands/questionnaire.py +1 -1
  31. canvas_sdk/commands/commands/refill.py +16 -0
  32. canvas_sdk/commands/commands/remove_allergy.py +26 -0
  33. canvas_sdk/commands/commands/stop_medication.py +1 -1
  34. canvas_sdk/commands/commands/task.py +52 -0
  35. canvas_sdk/commands/commands/update_diagnosis.py +27 -0
  36. canvas_sdk/commands/commands/update_goal.py +1 -1
  37. canvas_sdk/commands/commands/vitals.py +78 -0
  38. canvas_sdk/commands/constants.py +7 -0
  39. canvas_sdk/commands/tests/protocol/__init__.py +0 -0
  40. canvas_sdk/commands/tests/protocol/tests.py +55 -0
  41. canvas_sdk/commands/tests/schema/__init__.py +0 -0
  42. canvas_sdk/commands/tests/schema/tests.py +104 -0
  43. canvas_sdk/commands/tests/test_utils.py +170 -6
  44. canvas_sdk/commands/tests/unit/__init__.py +0 -0
  45. canvas_sdk/commands/tests/{tests.py → unit/tests.py} +20 -194
  46. canvas_sdk/data/client.py +82 -0
  47. canvas_sdk/data/patient.py +1 -21
  48. canvas_sdk/effects/banner_alert/add_banner_alert.py +8 -7
  49. canvas_sdk/effects/banner_alert/remove_banner_alert.py +3 -2
  50. canvas_sdk/effects/banner_alert/tests.py +224 -0
  51. canvas_sdk/effects/base.py +3 -5
  52. canvas_sdk/effects/patient_chart_summary_configuration.py +39 -0
  53. canvas_sdk/effects/protocol_card/__init__.py +1 -0
  54. canvas_sdk/effects/protocol_card/protocol_card.py +83 -0
  55. canvas_sdk/effects/protocol_card/tests.py +184 -0
  56. canvas_sdk/handlers/base.py +14 -1
  57. canvas_sdk/protocols/base.py +14 -0
  58. canvas_sdk/protocols/clinical_quality_measure.py +41 -0
  59. canvas_sdk/utils/db.py +17 -0
  60. canvas_sdk/v1/__init__.py +0 -0
  61. canvas_sdk/v1/data/__init__.py +3 -0
  62. canvas_sdk/v1/data/allergy_intolerance.py +63 -0
  63. canvas_sdk/v1/data/base.py +47 -0
  64. canvas_sdk/v1/data/condition.py +48 -0
  65. canvas_sdk/v1/data/lab.py +96 -0
  66. canvas_sdk/v1/data/medication.py +54 -0
  67. canvas_sdk/v1/data/patient.py +49 -0
  68. canvas_sdk/v1/data/user.py +10 -0
  69. canvas_sdk/value_set/tests/test_value_sets.py +65 -0
  70. canvas_sdk/value_set/v2022/adverse_event.py +33 -0
  71. canvas_sdk/value_set/v2022/allergy.py +232 -0
  72. canvas_sdk/value_set/v2022/assessment.py +215 -0
  73. canvas_sdk/value_set/v2022/communication.py +325 -0
  74. canvas_sdk/value_set/v2022/condition.py +40654 -0
  75. canvas_sdk/value_set/v2022/device.py +174 -0
  76. canvas_sdk/value_set/v2022/diagnostic_study.py +4967 -0
  77. canvas_sdk/value_set/v2022/encounter.py +2564 -0
  78. canvas_sdk/value_set/v2022/immunization.py +341 -0
  79. canvas_sdk/value_set/v2022/individual_characteristic.py +307 -0
  80. canvas_sdk/value_set/v2022/intervention.py +1356 -0
  81. canvas_sdk/value_set/v2022/laboratory_test.py +1250 -0
  82. canvas_sdk/value_set/v2022/medication.py +5130 -0
  83. canvas_sdk/value_set/v2022/physical_exam.py +201 -0
  84. canvas_sdk/value_set/v2022/procedure.py +4037 -0
  85. canvas_sdk/value_set/v2022/symptom.py +176 -0
  86. canvas_sdk/value_set/value_set.py +91 -0
  87. canvas-0.1.15.dist-info/RECORD +0 -95
  88. canvas_generated/data_access_layer/data_access_layer_pb2.py +0 -30
  89. canvas_generated/data_access_layer/data_access_layer_pb2.pyi +0 -23
  90. canvas_generated/data_access_layer/data_access_layer_pb2_grpc.py +0 -66
  91. canvas_sdk/data/data_access_layer_client.py +0 -95
  92. canvas_sdk/data/exceptions.py +0 -16
  93. {canvas-0.1.15.dist-info → canvas-0.2.10.dist-info}/WHEEL +0 -0
  94. {canvas-0.1.15.dist-info → canvas-0.2.10.dist-info}/entry_points.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: canvas
3
- Version: 0.1.15
3
+ Version: 0.2.10
4
4
  Summary: SDK to customize event-driven actions in your Canvas instance
5
5
  License: MIT
6
6
  Author: Canvas Team
@@ -12,17 +12,23 @@ Classifier: Programming Language :: Python :: 3.11
12
12
  Classifier: Programming Language :: Python :: 3.12
13
13
  Requires-Dist: cookiecutter
14
14
  Requires-Dist: cron-converter (>=1.2.1,<2.0.0)
15
+ Requires-Dist: django (>=5.1.1,<6.0.0)
16
+ Requires-Dist: gql[all] (>=3.5.0,<4.0.0)
15
17
  Requires-Dist: grpcio (>=1.60.1,<2.0.0)
16
18
  Requires-Dist: ipython (>=8.21.0,<9.0.0)
17
19
  Requires-Dist: jsonschema (>=4.21.1,<5.0.0)
18
20
  Requires-Dist: keyring
21
+ Requires-Dist: protobuf (>=4.25.3,<5.0.0)
22
+ Requires-Dist: psycopg[binary] (>=3.2.2,<4.0.0)
19
23
  Requires-Dist: pydantic (>=2.6.1,<3.0.0)
24
+ Requires-Dist: pyjwt (==2.4.0)
20
25
  Requires-Dist: python-dotenv (>=1.0.1,<2.0.0)
21
26
  Requires-Dist: redis (>=5.0.4,<6.0.0)
22
27
  Requires-Dist: requests
23
28
  Requires-Dist: restrictedpython (>=7.1,<8.0)
24
29
  Requires-Dist: statsd (>=4.0.1,<5.0.0)
25
30
  Requires-Dist: typer[all]
31
+ Requires-Dist: typing-extensions (>=4.8,<4.9)
26
32
  Requires-Dist: websocket-client (>=1.7.0,<2.0.0)
27
33
  Description-Content-Type: text/markdown
28
34
 
@@ -0,0 +1,143 @@
1
+ canvas_cli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
2
+ canvas_cli/apps/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
3
+ canvas_cli/apps/auth/__init__.py,sha256=gIwJ2qWvRlLqbiRkudrGqTKV-orlb8OTkG487qoRda4,105
4
+ canvas_cli/apps/auth/tests.py,sha256=WK7hSLTK95gEweMRaj3RdPC-qSwjnuulxMUg6D0bY_k,4528
5
+ canvas_cli/apps/auth/utils.py,sha256=IH5oZB3pdlb4_FRfCZKkNTncx_kdKagpiBqlhtM8h2U,5434
6
+ canvas_cli/apps/logs/__init__.py,sha256=ehY9SRb6nBw81xZF50yyBlUZJtNR2VeVSNI5sFuWJ7o,64
7
+ canvas_cli/apps/logs/logs.py,sha256=Ixue8Z1wgxABunVIx6TzmsH6oZ0FPf2H51Sd3nFUnAI,1969
8
+ canvas_cli/apps/plugin/__init__.py,sha256=G_nLsu6cdko5OjatnbqUyEboGcNlGGLwpZmCBxMKdfo,236
9
+ canvas_cli/apps/plugin/plugin.py,sha256=bfiquQAsGGQnzoJ5bi0bElIHW0l9TYY94O9qXncWPVk,13000
10
+ canvas_cli/apps/plugin/tests.py,sha256=nH-LunSfkpFIvcONVeJxr8JQ-z5vZmuZFaZJanB2m2s,2661
11
+ canvas_cli/conftest.py,sha256=pGvVS6VT0Zll_Lp3ezLh2jykOk-2HTBVH8RP5FwLUVw,930
12
+ canvas_cli/main.py,sha256=lUCh5M7u0KJ9CWOL_oPa0J4284ggxHxteURYv6dGU4g,3790
13
+ canvas_cli/templates/plugins/default/cookiecutter.json,sha256=dWEB3wJ8U4bko8jX26PgLLg_jgWlafLTNqsGnY1PUcg,124
14
+ canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/CANVAS_MANIFEST.json,sha256=9N0u5hN0GqjPvUh_B3YHtvyntEvxUGbInbQeprU0TS0,787
15
+ canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/README.md,sha256=7QdF2JWlWwq6Us9LzkO9XWJU4IU7Q6RD_w8ImcS-hrI,347
16
+ canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
17
+ canvas_cli/templates/plugins/default/{{ cookiecutter.__project_slug }}/protocols/my_protocol.py,sha256=liFrvx-5NRfeODOBbRNB1Cg0P04UvxpAkkLtAiEmckQ,2252
18
+ canvas_cli/tests.py,sha256=64aAOgHrC09UeWqsFo__K3zmSHrXHCtMJAc1rE7ziTc,5916
19
+ canvas_cli/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
+ canvas_cli/utils/context/__init__.py,sha256=HhYvI-hydP0mV18nJiU7uo5gk0yN7EYNgouxieoGDOE,102
21
+ canvas_cli/utils/context/context.py,sha256=Q-MniBuvzDKhLODOOrOVdaRTLz9Lp0m7cAz-i6YRRpA,5138
22
+ canvas_cli/utils/context/tests.py,sha256=aNmAggwvjKV-1WrgIvp66M46EX2QCbbHmity3bSCBTg,4211
23
+ canvas_cli/utils/print/__init__.py,sha256=zkRiQCUhPIB3wNGeJ1Hwfd12zJyvbRRiWqequJORvdE,88
24
+ canvas_cli/utils/print/print.py,sha256=GejLUtC5hfWuKHUBapyEwVHNIaIILxW60_xBQchiGpI,1420
25
+ canvas_cli/utils/print/tests.py,sha256=4kqp_uMpUUjSXokD_Hxs2aMyx50_JzGABAQoNC4XTrM,2376
26
+ canvas_cli/utils/urls/__init__.py,sha256=08hlrQhQ1pKBjlIRaC0j53IkgK723jfK8-j3djvR0ko,81
27
+ canvas_cli/utils/urls/tests.py,sha256=opXDF2i3lXTdsKJ7ywIRzWDDzZ5KAO0JbGIR3hbJdoE,407
28
+ canvas_cli/utils/urls/urls.py,sha256=KwWTh5ERrEsZEvdBrZpZB71xtyWkDuglpXUbycWmBOo,798
29
+ canvas_cli/utils/validators/__init__.py,sha256=rBvSR2O1hWkNAnUBdcr-zUkmqT796_A61b9pnvEhwrM,113
30
+ canvas_cli/utils/validators/manifest_schema.py,sha256=_WCqFat9AGnOdYWQh20hfWJL-_4d3gDY5PpNQt2AHIE,3165
31
+ canvas_cli/utils/validators/tests.py,sha256=cZHLSx7oteOfLOoU1tXGvw88n6itcvUT2B3ZBg-bmEY,1206
32
+ canvas_cli/utils/validators/validators.py,sha256=RKDKxIvZ1IuCPVuhQ1KHdpwu7aewAqT9ZX-nA-LZDdg,1614
33
+ canvas_generated/messages/effects_pb2.py,sha256=U_7Xr8WEOVYXugGPEbd1BdiEYLFeo0s9bB5GGyt2cuE,7763
34
+ canvas_generated/messages/effects_pb2.pyi,sha256=Hfk2TFefljHxAceqTiYd8umhQ35NPMoiNLHVNHyqB0Q,13241
35
+ canvas_generated/messages/effects_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
36
+ canvas_generated/messages/events_pb2.py,sha256=LcOpigZW2ftsxVGUDcFNpUAcTNitlFkw8Rm9lOS_9vg,31635
37
+ canvas_generated/messages/events_pb2.pyi,sha256=Fs83E_auwGY0rasW3-mD1hQCkxcsFNbyuRCXQTy82Fs,56001
38
+ canvas_generated/messages/events_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
39
+ canvas_generated/messages/plugins_pb2.py,sha256=rHXTVHly9zKsA8qoT4cFRGkRKvYt7rPftz4KNT7pEe0,1271
40
+ canvas_generated/messages/plugins_pb2.pyi,sha256=G1seqytP8GlJJh-AL2CJ0VyUNlReEvK61C-Oh8QuGiE,501
41
+ canvas_generated/messages/plugins_pb2_grpc.py,sha256=1oboBPFxaTEXt9Aw7EAj8gXHDCNMhZD2VXqocC9l_gk,159
42
+ canvas_generated/services/plugin_runner_pb2.py,sha256=amsds-ckCjpalFkkC-2mzVsj-gdj5BNY9tx-SRf8WHM,1557
43
+ canvas_generated/services/plugin_runner_pb2.pyi,sha256=1w-Pa4k7HtlmQAr7B6sgV64zdZplBKQKHN-S8bjwO3w,265
44
+ canvas_generated/services/plugin_runner_pb2_grpc.py,sha256=EzJJVkP_AZ3dwBA7OxUito0NSalRmjjg8q9TZ_P18ww,4549
45
+ canvas_sdk/__init__.py,sha256=d7V1Qsp4hSqp8opmvqp-0J33uibArUjwENMfzSDAdZg,102
46
+ canvas_sdk/base.py,sha256=Rli-Tf8G3UUydQvTt0pve56qSaQSiS2USmhNYy17I9Y,1824
47
+ canvas_sdk/commands/__init__.py,sha256=nCh9A598KaUFXspbFjvr7u88eShtIqTjF_oHRIE24Ik,2356
48
+ canvas_sdk/commands/base.py,sha256=P8pcW0sDO8MWYzh3ZLNqG0RLDoxmBcOVXREGEgCpJA0,5140
49
+ canvas_sdk/commands/commands/allergy.py,sha256=c3saKFOsgB3N5jxBfZU5QmC09f8d_oV1q6BLTI1zEi4,1242
50
+ canvas_sdk/commands/commands/assess.py,sha256=IjsvkhzKinRaykMRzbnk6G4JAkzDhyqGG6ZvjDhNAuE,1723
51
+ canvas_sdk/commands/commands/close_goal.py,sha256=3OAMWlDmGBg2qyA0RqlDyEt5rt_QVFQK1fBET6C1g_U,664
52
+ canvas_sdk/commands/commands/diagnose.py,sha256=eM-hGfwoFgRWHDvpSBxni5uxQDxJHDrMFBz0N0nOcsA,1007
53
+ canvas_sdk/commands/commands/family_history.py,sha256=uXUQ0xHE2Ye2uJecAim96gID_WCZtwXvTC9nCnuLWcE,590
54
+ canvas_sdk/commands/commands/goal.py,sha256=VTRJp_w6bEM3CG8nHCL1FqbhrQqtAYT3YCiLM22fE-w,1599
55
+ canvas_sdk/commands/commands/history_present_illness.py,sha256=AcF1835FkqBqgXyeSMkXnGrOqg7jvNXkfP7-JV60ii4,428
56
+ canvas_sdk/commands/commands/instruct.py,sha256=M8YxdzolIbOkMw-ZrXKCX4jDKyBlkSrtfkCCJboSjcQ,507
57
+ canvas_sdk/commands/commands/lab_order.py,sha256=hkPeVBm8Gv1q9i_6mPCG7G4Xnamqkg8l7H4ZGljE9tQ,1046
58
+ canvas_sdk/commands/commands/medical_history.py,sha256=NZiiQFY4mV6IlWPAKhqI6Xl7oGS-m_-xsxGtFGGrpqw,1190
59
+ canvas_sdk/commands/commands/medication_statement.py,sha256=qnX--dtB5wV9Jz6smhq_9coStXlZNwMrN4YnETApuPY,1020
60
+ canvas_sdk/commands/commands/past_surgical_history.py,sha256=mbY1G8MG8jFmyBNL633EL3z3hQDOJfl0tCgBlpQ0M8s,887
61
+ canvas_sdk/commands/commands/perform.py,sha256=FpumHzPJp5pzb4F0CBW2QbSWdR_5mpib1PTOK5amvZc,470
62
+ canvas_sdk/commands/commands/plan.py,sha256=uxjXmdNcG32R4S0CJ7fqDaaXTMiJJH9RuvwlWuztlZ0,403
63
+ canvas_sdk/commands/commands/prescribe.py,sha256=Dbrsixo6eoICjsHN5gDM-vTMY3Iy7lU1dxULOHdFcfM,2209
64
+ canvas_sdk/commands/commands/questionnaire.py,sha256=Giu4stTzpddO8fH3iVyxm2lUeDwe7AmhfuIfb_0WUj4,644
65
+ canvas_sdk/commands/commands/reason_for_visit.py,sha256=20i2A8V4of_Q-Kqb37k-fUJ-JaHVGsrMtoIGZAYhPNw,1480
66
+ canvas_sdk/commands/commands/refill.py,sha256=OZTTiMnhJIM4--iTO-yPqkMwFLXBTOcKyKPxAZ6FL_g,386
67
+ canvas_sdk/commands/commands/remove_allergy.py,sha256=6CXo3s63z7oqMlROExPWudQBZeSvD3x0SC_efQSb0Lw,748
68
+ canvas_sdk/commands/commands/stop_medication.py,sha256=h-I95y2P7EgOsKMarHDp8C_MVdpB90e-fzqDWv8-haM,715
69
+ canvas_sdk/commands/commands/task.py,sha256=d8pIvEOu6HSN0dRt5_X8up3b4PRPe68c4lDNXBvISD8,1330
70
+ canvas_sdk/commands/commands/update_diagnosis.py,sha256=fqPcKBaiRemo8Qa4H4g6ZvKM2YczVlj9FxpBGjs8J9Q,824
71
+ canvas_sdk/commands/commands/update_goal.py,sha256=ddvxlDnoTm5k-G5aJ-pW2fMIC-s5K8jYia9tISXsxAk,1580
72
+ canvas_sdk/commands/commands/vitals.py,sha256=NJVuWJWlB8lFOp02jwLJhXnxxQZbm2J-6zs8aTB-LiY,2753
73
+ canvas_sdk/commands/constants.py,sha256=eYzVI3wKBQUfRbfDm8CoGaKWmkBOwtDeeL91znK6a5A,341
74
+ canvas_sdk/commands/tests/protocol/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
75
+ canvas_sdk/commands/tests/protocol/tests.py,sha256=Pke6UTH3hLXUevWsG0U2KKH3wWxY1KKrZ4-5iFCdCws,1464
76
+ canvas_sdk/commands/tests/schema/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
+ canvas_sdk/commands/tests/schema/tests.py,sha256=5ECkuP_lXThfe1c7W-5Ytnx0_F5VRL3BZ4u__diXTO8,3505
78
+ canvas_sdk/commands/tests/test_utils.py,sha256=WpLpOHyf1z-IE2bh3DOnWUKh4zzEzCDmVLuyCbiG4Uc,10399
79
+ canvas_sdk/commands/tests/unit/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
80
+ canvas_sdk/commands/tests/unit/tests.py,sha256=2AG_YRjFIcgTwLBnWv4OJzsxJmVTXm51APAxP-qIffk,9673
81
+ canvas_sdk/data/__init__.py,sha256=dmqlcw11-0DCbH2lOebwBCq6njSQ6BDhxygmncUgZRs,28
82
+ canvas_sdk/data/base.py,sha256=XbUctLoEdY8egrPzw_x2Ox41nurubh8sl4Kjbhu8rTE,795
83
+ canvas_sdk/data/client.py,sha256=ZG3vKfxjTWJz3LWgrlU2Cv3wmki2To3bIByQQK72zBs,2104
84
+ canvas_sdk/data/patient.py,sha256=IhJxZoQHJPK2O7d7v0UVUTZ_8FYAXZ_sl2BUVvgsztY,130
85
+ canvas_sdk/data/staff.py,sha256=zmwKZlndqFdwsE3j14DD79MSzM9doIkeqqzToGDBjTs,168
86
+ canvas_sdk/data/task.py,sha256=VeOh45M6tQ0IPwPr03yK6EYa8xox3iJhoRBzqUdcq2k,1756
87
+ canvas_sdk/effects/__init__.py,sha256=oChQi5y_8mK2zDiNMwWYp6CaQX1_zbmwXILPF7iSt-4,69
88
+ canvas_sdk/effects/banner_alert/__init__.py,sha256=8z5l9rwonKEcRkvD5q4DWvHPYhKJzwyGuUYoUNKYwX4,158
89
+ canvas_sdk/effects/banner_alert/add_banner_alert.py,sha256=RhMEIc62T5rLO_FltGvOq0XVU_wXIdCcBpxfaQeqCJY,1497
90
+ canvas_sdk/effects/banner_alert/remove_banner_alert.py,sha256=9oLetlX_22B3iRwVZqB4IpA9e9YqZ_1cmWV4vJRNDmE,559
91
+ canvas_sdk/effects/banner_alert/tests.py,sha256=t0SrJGeW1WpCXFIdA7AzslqGR-4iU0ohbi7hzD9lmGg,7472
92
+ canvas_sdk/effects/base.py,sha256=cyTEQ4p3IxZ3mPu6Ancr4Y7RcrVirWBbNUs9V6g7Odc,674
93
+ canvas_sdk/effects/patient_chart_summary_configuration.py,sha256=VdrQgfTJpfqM1ll0nLJisVRQ5HZ-D9F70lHfZOOSeCI,1148
94
+ canvas_sdk/effects/protocol_card/__init__.py,sha256=ESzUYajBBmcTAad2PIwHuV3SgGj4B9JHtf9uop_V4YA,88
95
+ canvas_sdk/effects/protocol_card/protocol_card.py,sha256=OJEJNxHicKUNjRTkN3FHwKb0tmWta5lLw4cQHId1pWw,2353
96
+ canvas_sdk/effects/protocol_card/tests.py,sha256=NZuXqYoL0oRHoALP2-UP1KNHlV2oYSB6L9uQJijoOOQ,6327
97
+ canvas_sdk/events/__init__.py,sha256=JGZ-3uf0Luzr4kg5UqduupD4w6B2WVEgQ9WlcoMaPwE,81
98
+ canvas_sdk/handlers/__init__.py,sha256=VVz2_Xyb9720R2MZmSbGPG0T8u2a5u6zSDkWlwiJZv4,49
99
+ canvas_sdk/handlers/base.py,sha256=7kw95-nYOsphP2_dVoJxBvi2RsuUpwBo5RcKvo924Yw,599
100
+ canvas_sdk/handlers/cron_task.py,sha256=Q4_D3bDKE5hyEpCf0JnGSgZlnLh_g9RSP3oEfIuLJ9Y,945
101
+ canvas_sdk/protocols/__init__.py,sha256=GKtNMsJ5XaNOJUz9adE2_pONLeZqkZIrd9hXAU-jzvU,51
102
+ canvas_sdk/protocols/base.py,sha256=Tn2PrQrP-idp8qGx6HAVhaal0FEKcf7x31zDPpBAl1s,571
103
+ canvas_sdk/protocols/clinical_quality_measure.py,sha256=2P-TsU6dBrQha_2RV5d4GyksgOhgvo82N-ty_YMGx5w,1141
104
+ canvas_sdk/tests/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
105
+ canvas_sdk/utils/__init__.py,sha256=sFuhqcWvXb2-33FOuXZgWuUeC5jZL2MDoqjGoQZGwd8,60
106
+ canvas_sdk/utils/db.py,sha256=0AO5bhu-k9OsAHpXe1RHzyDZnBGHUEzrv8-vYtTIoeA,592
107
+ canvas_sdk/utils/http.py,sha256=YOgUFp7FOFhbDwkGhCiD3JLZ342oNZR-qncMxv2qSjw,2159
108
+ canvas_sdk/utils/stats.py,sha256=7CNBwglLGFDTrEcSjLv3jAcaLzxy4geFNZpQf90osKI,660
109
+ canvas_sdk/utils/tests.py,sha256=t3MScbIfzXkQttMIvj0dRzJlFVS8LFU8WgWRrChM-H0,1931
110
+ canvas_sdk/v1/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
111
+ canvas_sdk/v1/data/__init__.py,sha256=LWAcICOx4fWea_lp_yNt0UIuhgjZMoNOaWx-7ZuM-dg,132
112
+ canvas_sdk/v1/data/allergy_intolerance.py,sha256=pJs2Hiis8YbbqM6FFcpgRSqr7aUwe_1mJjyKzvt9Zl0,2077
113
+ canvas_sdk/v1/data/base.py,sha256=Gpmb3ZwdKdTYuVBkIhI5ziiLInNCVuw_nQN0SExPl1k,1736
114
+ canvas_sdk/v1/data/condition.py,sha256=hJ3APJvRh-dKYwujujdo5kugnc6YXBES7YpUIKUTjhI,1525
115
+ canvas_sdk/v1/data/lab.py,sha256=3KsuwZYjK6krXE7LfHxH1-z2Mib1MnE4g91djhAW2jU,3565
116
+ canvas_sdk/v1/data/medication.py,sha256=XbV_iYgt40n8Q1IcVPtsinW2v-VJEms4T13cFNquBRE,1798
117
+ canvas_sdk/v1/data/patient.py,sha256=wiTenpMm9VUqpwy5U_aCMlhrJIh3zR-fTLBQXYJMx2E,1758
118
+ canvas_sdk/v1/data/user.py,sha256=3ZMeWABqrYt50G0TFV-qyPfqr7ITd3XJ7CVkrdOFHDU,262
119
+ canvas_sdk/value_set/tests/test_value_sets.py,sha256=fl-E1vJN_wnWcr88atoK83N_muX-HrZoRj_aZTl9GpY,2655
120
+ canvas_sdk/value_set/v2022/adverse_event.py,sha256=8zsNFBsLDRY0mrPomzogD-W15xyo2CFFkiEcT2ruGCg,1032
121
+ canvas_sdk/value_set/v2022/allergy.py,sha256=n_P8Aqso5M6spTsatp4K4hzlbwaC3rjUBZs2bZsFVVg,11132
122
+ canvas_sdk/value_set/v2022/assessment.py,sha256=a9hoSxz_VLhfWJp-QrvIUmzSf_cK7x5Da7JsNapg17U,8342
123
+ canvas_sdk/value_set/v2022/communication.py,sha256=FlWMUDx_CKxEVw7JktTzSBykFEHRz2QA6aVVGowwUAc,18036
124
+ canvas_sdk/value_set/v2022/condition.py,sha256=MefRELucxNd5PfnXvxA5DQaAULILGHRb3BKy0a6zsf8,3389919
125
+ canvas_sdk/value_set/v2022/device.py,sha256=TvEXAzC_nnzmHEY2cWZqfLr_niFyXsJ5YqUetiQI-bU,12983
126
+ canvas_sdk/value_set/v2022/diagnostic_study.py,sha256=wo4AQu2p5X51HZ3RsbU5NhUpgv8Fg2mPKs2YexWCMjA,301934
127
+ canvas_sdk/value_set/v2022/encounter.py,sha256=T7CQQ21Uq-ot4HOp1bzMl8NaAxMNLb_f0-ePCoMjMn4,370964
128
+ canvas_sdk/value_set/v2022/immunization.py,sha256=dYPWL2Un1HTUrjKZTh_MBPVmU2ImtMXVaMqVRKP_7MA,13189
129
+ canvas_sdk/value_set/v2022/individual_characteristic.py,sha256=1NZI2r4-9x2qTbYTkjUOAU9PgvMOBB3cpddHFr7msaU,13198
130
+ canvas_sdk/value_set/v2022/intervention.py,sha256=ZULGA6OhrRv4jLDhTD2z1rB92TvjUHY43rp6tanq3hM,79792
131
+ canvas_sdk/value_set/v2022/laboratory_test.py,sha256=x-o7SAjYw5sS9x8tGPcYUg03L_mKxxDu0b6LJsnjmQc,77876
132
+ canvas_sdk/value_set/v2022/medication.py,sha256=L1yNzrwD2nUox8F6x8RSKhmFsn9VcFbFEy1nM7AHRis,316430
133
+ canvas_sdk/value_set/v2022/physical_exam.py,sha256=C5PfLR4YB6pB_0wIy6Wfocyso5a9wuwGoKj84k_jR-U,7645
134
+ canvas_sdk/value_set/v2022/procedure.py,sha256=MA1yBHJskzGyp0nypzTwrR6u4pxZTo20Iv25W4FOIjM,367721
135
+ canvas_sdk/value_set/v2022/symptom.py,sha256=4-ouetYI8soAAZy9Gq8AXBiqTfJjdgfZgWZPhBE-Ing,9384
136
+ canvas_sdk/value_set/value_set.py,sha256=zHwzb6iwE7UlB_Z794_WvJPUJSPQ3q_1G_fR4-GQ_AU,2842
137
+ canvas_sdk/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
138
+ logger/__init__.py,sha256=sf54RfJ48tCbXm5jTHAea3WWuSH5-AXRHxTNNKVuxgA,60
139
+ logger/logger.py,sha256=u103k5-yP62ifK1Hcp-PDTRrw_vOfLGeC-5raxNmBC0,1428
140
+ canvas-0.2.10.dist-info/METADATA,sha256=CBO9pj6Bo3w4jX35sZ2vz3_CJJfZnNDKdJvO6LuSzn0,4500
141
+ canvas-0.2.10.dist-info/WHEEL,sha256=sP946D7jFCHeNz5Iq4fL4Lu-PrWrFsgfLXbbkciIZwg,88
142
+ canvas-0.2.10.dist-info/entry_points.txt,sha256=VSmSo1IZ3aEfL7enmLmlWSraS_IIkoXNVeyXzgRxFiY,46
143
+ canvas-0.2.10.dist-info/RECORD,,
@@ -1,8 +1,11 @@
1
+ import importlib
1
2
  import json
3
+ import os
4
+ import sys
2
5
  import tarfile
3
6
  import tempfile
4
7
  from pathlib import Path
5
- from typing import Optional
8
+ from typing import Any, List, Optional
6
9
  from urllib.parse import urljoin
7
10
 
8
11
  import requests
@@ -69,6 +72,30 @@ def _get_name_from_metadata(host: str, token: str, package: Path) -> Optional[st
69
72
  return metadata.get("name")
70
73
 
71
74
 
75
+ def _get_protocols_with_new_cqm_properties(
76
+ protocol_classes: List[dict[str, Any]]
77
+ ) -> List[dict[str, Any]] | None:
78
+ """Extract the meta properties of any ClinicalQualityMeasure Protocols included in the plugin if they have changed."""
79
+
80
+ def get_new_meta_properties(protocol_class: dict[str, str]) -> dict[str, str]:
81
+ mod, classname = protocol_class["class"].split(":")
82
+ module = importlib.import_module(mod)
83
+ _class = getattr(module, classname)
84
+ if not hasattr(_class, "_meta") or _class._meta() == protocol_class.get("meta"):
85
+ return {}
86
+ return {"meta": _class._meta()}
87
+
88
+ has_updates = False
89
+ new_protocols = []
90
+ for p in protocol_classes:
91
+ m = get_new_meta_properties(p)
92
+ new_protocols.append(p | m)
93
+ if m:
94
+ has_updates = True
95
+
96
+ return new_protocols if has_updates else None
97
+
98
+
72
99
  def get_base_plugin_template_path() -> Path:
73
100
  """Return context's base_plugin_template_path, so it can be used as a Typer default."""
74
101
  return context.plugin_template_dir / context.default_plugin_template_name
@@ -126,7 +153,7 @@ def install(
126
153
  raise typer.Exit(1)
127
154
 
128
155
  if r.status_code == requests.codes.created:
129
- print("Plugin successfully installed!")
156
+ print(f"Plugin {plugin_name} successfully installed!")
130
157
 
131
158
  # If we got a bad_request, means there's a duplicate plugin and install can't handle that.
132
159
  # So we need to get the plugin-name from the package and call `update` directly
@@ -168,7 +195,7 @@ def uninstall(
168
195
  raise typer.Exit(1)
169
196
 
170
197
  if r.status_code == requests.codes.no_content:
171
- print(r.text)
198
+ print(f"Plugin {name} successfully uninstalled!")
172
199
  else:
173
200
  print(f"Status code {r.status_code}: {r.text}")
174
201
  raise typer.Exit(1)
@@ -273,9 +300,12 @@ def list(
273
300
  raise typer.Exit(1)
274
301
 
275
302
  if r.status_code == requests.codes.ok:
276
- for plugin in r.json().get("results", []):
303
+ plugins = r.json().get("results", [])
304
+ if not plugins:
305
+ print(f"No plugins are currently installed on {host}")
306
+ for plugin in plugins:
277
307
  print(
278
- f"{plugin['name']}@{plugin['version']}\t{'enabled' if plugin['is_enabled'] else 'not enabled'}"
308
+ f"{plugin['name']}@{plugin['version']}\t{'enabled' if plugin['is_enabled'] else 'disabled'}"
279
309
  )
280
310
  else:
281
311
  print(f"Status code {r.status_code}: {r.text}")
@@ -287,27 +317,39 @@ def validate_manifest(
287
317
  ) -> None:
288
318
  """Validate the Canvas Manifest json file."""
289
319
  if not plugin_name.exists():
290
- raise typer.BadParameter(f"Plugin '{plugin_name}' does not exist")
320
+ raise typer.BadParameter(f"Plugin {plugin_name} does not exist")
291
321
 
292
322
  if not plugin_name.is_dir():
293
- raise typer.BadParameter(f"Plugin '{plugin_name}' is not a directory, nothing to validate")
323
+ raise typer.BadParameter(f"Plugin {plugin_name} is not a directory, nothing to validate")
294
324
 
295
325
  manifest = plugin_name / "CANVAS_MANIFEST.json"
296
326
 
297
327
  if not manifest.exists():
298
328
  raise typer.BadParameter(
299
- f"Plugin '{plugin_name}' does not have a CANVAS_MANIFEST.json file to validate"
329
+ f"Plugin {plugin_name} does not have a CANVAS_MANIFEST.json file to validate"
300
330
  )
301
331
 
302
332
  try:
303
333
  manifest_json = json.loads(manifest.read_text())
334
+
335
+ sys.path.append(str(plugin_name.parent.absolute()))
336
+ if new_protocols := _get_protocols_with_new_cqm_properties(
337
+ manifest_json.get("components", {}).get("protocols", [])
338
+ ):
339
+ print(
340
+ f"Updating the CANVAS_MANIFEST.json file for {plugin_name} with CQM meta properties"
341
+ )
342
+ manifest_json["components"]["protocols"] = new_protocols
343
+ manifest.write_text(json.dumps(manifest_json))
344
+ manifest_json = json.loads(manifest.read_text())
345
+
304
346
  except json.JSONDecodeError:
305
347
  print("There was a problem loading the manifest file, please ensure it's valid JSON")
306
348
  raise typer.Abort()
307
349
 
308
350
  validate_manifest_file(manifest_json)
309
351
 
310
- print(f"Plugin '{plugin_name}' has a valid CANVAS_MANIFEST.json file")
352
+ print(f"Plugin {plugin_name} has a valid CANVAS_MANIFEST.json file")
311
353
 
312
354
 
313
355
  def update(
@@ -1,9 +1,14 @@
1
+ import shutil
2
+ from datetime import datetime
1
3
  from pathlib import Path
4
+ from typing import Any, Generator
2
5
 
3
6
  import pytest
4
7
  import typer
5
8
  from typer.testing import CliRunner
6
9
 
10
+ from canvas_cli.main import app
11
+
7
12
  from .plugin import validate_package
8
13
 
9
14
  runner = CliRunner()
@@ -30,3 +35,49 @@ def test_validate_package_valid_file(tmp_path: Path) -> None:
30
35
  package_path.write_text("something")
31
36
  result = validate_package(package_path)
32
37
  assert result == package_path
38
+
39
+
40
+ @pytest.fixture(scope="session")
41
+ def init_plugin_name() -> str:
42
+ """The plugin name to be used for the canvas cli init test"""
43
+ return f"testing_init-{datetime.now().timestamp()}".replace(".", "")
44
+
45
+
46
+ @pytest.fixture(autouse=True, scope="session")
47
+ def clean_up_plugin(init_plugin_name: str) -> Generator[Any, Any, Any]:
48
+ yield
49
+ if Path(f"./{init_plugin_name}").exists():
50
+ shutil.rmtree(Path(f"./{init_plugin_name}"))
51
+
52
+
53
+ def test_canvas_init(init_plugin_name: str) -> None:
54
+ """Tests that the CLI successfully creates a plugin with init."""
55
+ result = runner.invoke(app, "init", input=init_plugin_name)
56
+ assert result.exit_code == 0
57
+
58
+ # plugin directory exists
59
+ plugin = Path(f"./{init_plugin_name}")
60
+ assert plugin.exists()
61
+ assert plugin.is_dir()
62
+
63
+ # manifest file exists
64
+ manifest = Path(f"./{init_plugin_name}/CANVAS_MANIFEST.json")
65
+ assert manifest.exists()
66
+ assert manifest.is_file()
67
+ manifest_result = runner.invoke(app, f"validate-manifest {init_plugin_name}")
68
+ assert manifest_result.exit_code == 0
69
+
70
+ # readme file exists
71
+ readme = Path(f"./{init_plugin_name}/README.md")
72
+ assert readme.exists()
73
+ assert readme.is_file()
74
+
75
+ # protocols dir exists
76
+ protocols = Path(f"./{init_plugin_name}/protocols")
77
+ assert protocols.exists()
78
+ assert protocols.is_dir()
79
+
80
+ # protocol file exists in protocols dir
81
+ protocol = Path(f"./{init_plugin_name}/protocols/my_protocol.py")
82
+ assert protocol.exists()
83
+ assert protocol.is_file()
canvas_cli/tests.py CHANGED
@@ -1,11 +1,200 @@
1
+ import os
2
+ import shutil
3
+ from datetime import datetime
4
+ from pathlib import Path
5
+ from typing import Any, Callable, Generator
6
+ from unittest.mock import MagicMock, patch
7
+ from urllib.parse import urlparse
8
+
9
+ import pytest
1
10
  from typer.testing import CliRunner
2
11
 
12
+ import settings
13
+ from canvas_cli.apps.auth.utils import CONFIG_PATH
14
+
3
15
  from .main import app
4
16
 
5
17
  runner = CliRunner()
6
18
 
7
19
 
8
- def test_version_callback_exits_successfully() -> None:
9
- """Tests the CLI exits with 0 when calling with `--version`."""
10
- result = runner.invoke(app, "--version")
11
- assert result.exit_code == 0
20
+ @pytest.fixture(scope="session")
21
+ def plugin_name() -> str:
22
+ """The plugin name to be used for the canvas cli test"""
23
+ return f"cli-{datetime.now().timestamp()}".replace(".", "")
24
+
25
+
26
+ @pytest.fixture(autouse=True, scope="session")
27
+ def create_or_update_config_auth_file_for_testing(plugin_name: str) -> Generator[Any, Any, Any]:
28
+ """Creates the necessary config file for auth before performing cli tests."""
29
+
30
+ host = urlparse(settings.INTEGRATION_TEST_URL).hostname.replace(".canvasmedical.com", "")
31
+ client_id = settings.INTEGRATION_TEST_CLIENT_ID
32
+ client_secret = settings.INTEGRATION_TEST_CLIENT_SECRET
33
+
34
+ path = CONFIG_PATH
35
+ if not path.exists():
36
+ if not path.parent.exists():
37
+ path.parent.mkdir()
38
+ path.touch()
39
+
40
+ temp_path = path.parent / "temp_credentials.ini"
41
+
42
+ original_content = open(path, "r").read()
43
+ open(path, "w").writelines(
44
+ [
45
+ f"[{host}]\n",
46
+ f"client_id={client_id}\n",
47
+ f"client_secret={client_secret}\n",
48
+ ]
49
+ )
50
+ open(temp_path, "a").write(original_content)
51
+
52
+ yield
53
+
54
+ with open(temp_path, "r") as temp:
55
+ original_content = temp.read()
56
+ with open(path, "w") as f:
57
+ f.write(original_content)
58
+ os.remove(temp_path)
59
+
60
+
61
+ @pytest.fixture(autouse=True, scope="session")
62
+ def write_plugin(plugin_name: str) -> Generator[Any, Any, Any]:
63
+ runner.invoke(app, "init", input=plugin_name)
64
+ protocol = open(f"./{plugin_name}/protocols/my_protocol.py", "w")
65
+ p = """
66
+ from canvas_sdk.events import EventType
67
+ from canvas_sdk.protocols import BaseProtocol
68
+ from logger import log
69
+
70
+ class Protocol(BaseProtocol):
71
+ RESPONDS_TO = EventType.Name(EventType.ASSESS_COMMAND__CONDITION_SELECTED)
72
+ NARRATIVE_STRING = "I was inserted from my plugin's protocol."
73
+
74
+ def compute(self):
75
+ log.info(self.NARRATIVE_STRING)
76
+ return []
77
+ """
78
+ protocol.write(p)
79
+ protocol.close()
80
+
81
+ yield
82
+
83
+ if Path(f"./{plugin_name}").exists():
84
+ shutil.rmtree(Path(f"./{plugin_name}"))
85
+
86
+
87
+ def list_empty_plugins(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
88
+ """Step 1 - list all plugins"""
89
+ return ("list", 0, [], [f"{plugin_name}"])
90
+
91
+
92
+ def install_new_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
93
+ """Step 2 - install a new plugin"""
94
+ return (
95
+ f"install {plugin_name}",
96
+ 0,
97
+ [
98
+ f"Plugin {plugin_name} has a valid CANVAS_MANIFEST.json file",
99
+ "Installing plugin:",
100
+ "Posting",
101
+ f"Plugin {plugin_name} successfully installed!",
102
+ ],
103
+ [],
104
+ )
105
+
106
+
107
+ def list_newly_installed_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
108
+ """Step 3 - list all plugins, including newly installed one"""
109
+ return ("list", 0, [f"{plugin_name}@0.0.1 enabled"], [])
110
+
111
+
112
+ def disable_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
113
+ """Step 4 - disable plugin"""
114
+ return (
115
+ f"disable {plugin_name}",
116
+ 0,
117
+ [f"Disabling {plugin_name} using ", f"Plugin {plugin_name} successfully disabled!"],
118
+ [],
119
+ )
120
+
121
+
122
+ def list_disabled_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
123
+ """Step 5 - list disabled plugin"""
124
+ return ("list", 0, [f"{plugin_name}@0.0.1 disabled"], [])
125
+
126
+
127
+ def enable_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
128
+ """Step 6 - enable the disabled plugin"""
129
+ return (
130
+ f"enable {plugin_name}",
131
+ 0,
132
+ [f"Enabling {plugin_name} using ", f"Plugin {plugin_name} successfully enabled!"],
133
+ [],
134
+ )
135
+
136
+
137
+ def uninstall_enabled_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
138
+ """Step 7 - try to uninstall the enabled plugin"""
139
+ return (
140
+ f"uninstall {plugin_name}",
141
+ 1,
142
+ [
143
+ f"Uninstalling {plugin_name} using",
144
+ 'Status code 403: {"detail":"Cannot delete an enabled plugin."}',
145
+ ],
146
+ [],
147
+ )
148
+
149
+
150
+ def uninstall_disabled_plugin(plugin_name: str) -> tuple[str, int, list[str], list[str]]:
151
+ """Step 8 - disable and then uninstall the plugin"""
152
+ runner.invoke(app, f"disable {plugin_name}")
153
+
154
+ return (
155
+ f"uninstall {plugin_name}",
156
+ 0,
157
+ [
158
+ f"Uninstalling {plugin_name} using",
159
+ f"Plugin {plugin_name} successfully uninstalled!",
160
+ ],
161
+ [],
162
+ )
163
+
164
+
165
+ @patch("keyring.get_password")
166
+ @patch("keyring.set_password")
167
+ @pytest.mark.integtest
168
+ @pytest.mark.parametrize(
169
+ "step",
170
+ [
171
+ (list_empty_plugins),
172
+ (install_new_plugin),
173
+ (list_newly_installed_plugin),
174
+ (disable_plugin),
175
+ (list_disabled_plugin),
176
+ (enable_plugin),
177
+ (uninstall_enabled_plugin),
178
+ (uninstall_disabled_plugin),
179
+ (list_empty_plugins),
180
+ ],
181
+ )
182
+ def test_canvas_list_install_disable_enable_uninstall(
183
+ mock_get_password: MagicMock,
184
+ mock_set_password: MagicMock,
185
+ plugin_name: str,
186
+ step: Callable,
187
+ ) -> None:
188
+ """Tests that the Canvas CLI can list, install, disable, enable, and uninstall a plugin"""
189
+ mock_get_password.return_value = None
190
+ mock_set_password.return_value = None
191
+
192
+ (command, expected_exit_code, expected_outputs, expected_no_outputs) = step(plugin_name)
193
+
194
+ result = runner.invoke(app, command)
195
+
196
+ assert result.exit_code == expected_exit_code
197
+ for expected_output in expected_outputs:
198
+ assert expected_output in result.stdout
199
+ for expected_no_output in expected_no_outputs:
200
+ assert expected_no_output not in result.stdout
@@ -61,6 +61,7 @@ manifest_schema = {
61
61
  "properties": {
62
62
  "class": {"type": "string"},
63
63
  "description": {"type": "string"},
64
+ "meta": {"type": "object"},
64
65
  "data_access": {
65
66
  "type": "object",
66
67
  "properties": {
@@ -14,7 +14,7 @@ _sym_db = _symbol_database.Default()
14
14
 
15
15
 
16
16
 
17
- DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'canvas_generated/messages/effects.proto\x12\x06\x63\x61nvas\"P\n\x06\x45\x66\x66\x65\x63t\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.canvas.EffectType\x12\x0f\n\x07payload\x18\x02 \x01(\t\x12\x13\n\x0bplugin_name\x18\x03 \x01(\t*\xd1\x0f\n\nEffectType\x12\x12\n\x0eUNKNOWN_EFFECT\x10\x00\x12\x07\n\x03LOG\x10\x01\x12\x14\n\x10\x41\x44\x44_PLAN_COMMAND\x10\x02\x12\x1f\n\x1b\x41UTOCOMPLETE_SEARCH_RESULTS\x10\x03\x12\x14\n\x10\x41\x44\x44_BANNER_ALERT\x10\x04\x12\x17\n\x13REMOVE_BANNER_ALERT\x10\x05\x12\x1c\n\x18ORIGINATE_ASSESS_COMMAND\x10\x06\x12\x17\n\x13\x45\x44IT_ASSESS_COMMAND\x10\x07\x12\x19\n\x15\x44\x45LETE_ASSESS_COMMAND\x10\x08\x12\x19\n\x15\x43OMMIT_ASSESS_COMMAND\x10\t\x12!\n\x1d\x45NTER_IN_ERROR_ASSESS_COMMAND\x10\n\x12\x1e\n\x1aORIGINATE_DIAGNOSE_COMMAND\x10\x0b\x12\x19\n\x15\x45\x44IT_DIAGNOSE_COMMAND\x10\x0c\x12\x1b\n\x17\x44\x45LETE_DIAGNOSE_COMMAND\x10\r\x12\x1b\n\x17\x43OMMIT_DIAGNOSE_COMMAND\x10\x0e\x12#\n\x1f\x45NTER_IN_ERROR_DIAGNOSE_COMMAND\x10\x0f\x12\x1a\n\x16ORIGINATE_GOAL_COMMAND\x10\x10\x12\x15\n\x11\x45\x44IT_GOAL_COMMAND\x10\x11\x12\x17\n\x13\x44\x45LETE_GOAL_COMMAND\x10\x12\x12\x17\n\x13\x43OMMIT_GOAL_COMMAND\x10\x13\x12\x1f\n\x1b\x45NTER_IN_ERROR_GOAL_COMMAND\x10\x14\x12\x19\n\x15ORIGINATE_HPI_COMMAND\x10\x15\x12\x14\n\x10\x45\x44IT_HPI_COMMAND\x10\x16\x12\x16\n\x12\x44\x45LETE_HPI_COMMAND\x10\x17\x12\x16\n\x12\x43OMMIT_HPI_COMMAND\x10\x18\x12\x1e\n\x1a\x45NTER_IN_ERROR_HPI_COMMAND\x10\x19\x12*\n&ORIGINATE_MEDICATION_STATEMENT_COMMAND\x10\x1a\x12%\n!EDIT_MEDICATION_STATEMENT_COMMAND\x10\x1b\x12\'\n#DELETE_MEDICATION_STATEMENT_COMMAND\x10\x1c\x12\'\n#COMMIT_MEDICATION_STATEMENT_COMMAND\x10\x1d\x12/\n+ENTER_IN_ERROR_MEDICATION_STATEMENT_COMMAND\x10\x1e\x12\x1a\n\x16ORIGINATE_PLAN_COMMAND\x10\x1f\x12\x15\n\x11\x45\x44IT_PLAN_COMMAND\x10 \x12\x17\n\x13\x44\x45LETE_PLAN_COMMAND\x10!\x12\x17\n\x13\x43OMMIT_PLAN_COMMAND\x10\"\x12\x1f\n\x1b\x45NTER_IN_ERROR_PLAN_COMMAND\x10#\x12\x1f\n\x1bORIGINATE_PRESCRIBE_COMMAND\x10$\x12\x1a\n\x16\x45\x44IT_PRESCRIBE_COMMAND\x10%\x12\x1c\n\x18\x44\x45LETE_PRESCRIBE_COMMAND\x10&\x12\x1c\n\x18\x43OMMIT_PRESCRIBE_COMMAND\x10\'\x12$\n ENTER_IN_ERROR_PRESCRIBE_COMMAND\x10(\x12#\n\x1fORIGINATE_QUESTIONNAIRE_COMMAND\x10)\x12\x1e\n\x1a\x45\x44IT_QUESTIONNAIRE_COMMAND\x10*\x12 \n\x1c\x44\x45LETE_QUESTIONNAIRE_COMMAND\x10+\x12 \n\x1c\x43OMMIT_QUESTIONNAIRE_COMMAND\x10,\x12(\n$ENTER_IN_ERROR_QUESTIONNAIRE_COMMAND\x10-\x12&\n\"ORIGINATE_REASON_FOR_VISIT_COMMAND\x10.\x12!\n\x1d\x45\x44IT_REASON_FOR_VISIT_COMMAND\x10/\x12#\n\x1f\x44\x45LETE_REASON_FOR_VISIT_COMMAND\x10\x30\x12#\n\x1f\x43OMMIT_REASON_FOR_VISIT_COMMAND\x10\x31\x12+\n\'ENTER_IN_ERROR_REASON_FOR_VISIT_COMMAND\x10\x32\x12%\n!ORIGINATE_STOP_MEDICATION_COMMAND\x10\x33\x12 \n\x1c\x45\x44IT_STOP_MEDICATION_COMMAND\x10\x34\x12\"\n\x1e\x44\x45LETE_STOP_MEDICATION_COMMAND\x10\x35\x12\"\n\x1e\x43OMMIT_STOP_MEDICATION_COMMAND\x10\x36\x12*\n&ENTER_IN_ERROR_STOP_MEDICATION_COMMAND\x10\x37\x12!\n\x1dORIGINATE_UPDATE_GOAL_COMMAND\x10\x38\x12\x1c\n\x18\x45\x44IT_UPDATE_GOAL_COMMAND\x10\x39\x12\x1e\n\x1a\x44\x45LETE_UPDATE_GOAL_COMMAND\x10:\x12\x1e\n\x1a\x43OMMIT_UPDATE_GOAL_COMMAND\x10;\x12&\n\"ENTER_IN_ERROR_UPDATE_GOAL_COMMAND\x10<\x12\x0f\n\x0b\x43REATE_TASK\x10\x64\x12\x0f\n\x0bUPDATE_TASK\x10\x65\x12\x17\n\x13\x43REATE_TASK_COMMENT\x10\x66\x62\x06proto3')
17
+ DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\'canvas_generated/messages/effects.proto\x12\x06\x63\x61nvas\"P\n\x06\x45\x66\x66\x65\x63t\x12 \n\x04type\x18\x01 \x01(\x0e\x32\x12.canvas.EffectType\x12\x0f\n\x07payload\x18\x02 \x01(\t\x12\x13\n\x0bplugin_name\x18\x03 \x01(\t*\xda!\n\nEffectType\x12\x12\n\x0eUNKNOWN_EFFECT\x10\x00\x12\x07\n\x03LOG\x10\x01\x12\x14\n\x10\x41\x44\x44_PLAN_COMMAND\x10\x02\x12\x1f\n\x1b\x41UTOCOMPLETE_SEARCH_RESULTS\x10\x03\x12\x14\n\x10\x41\x44\x44_BANNER_ALERT\x10\x04\x12\x17\n\x13REMOVE_BANNER_ALERT\x10\x05\x12\x1c\n\x18ORIGINATE_ASSESS_COMMAND\x10\x06\x12\x17\n\x13\x45\x44IT_ASSESS_COMMAND\x10\x07\x12\x19\n\x15\x44\x45LETE_ASSESS_COMMAND\x10\x08\x12\x19\n\x15\x43OMMIT_ASSESS_COMMAND\x10\t\x12!\n\x1d\x45NTER_IN_ERROR_ASSESS_COMMAND\x10\n\x12\x1e\n\x1aORIGINATE_DIAGNOSE_COMMAND\x10\x0b\x12\x19\n\x15\x45\x44IT_DIAGNOSE_COMMAND\x10\x0c\x12\x1b\n\x17\x44\x45LETE_DIAGNOSE_COMMAND\x10\r\x12\x1b\n\x17\x43OMMIT_DIAGNOSE_COMMAND\x10\x0e\x12#\n\x1f\x45NTER_IN_ERROR_DIAGNOSE_COMMAND\x10\x0f\x12\x1a\n\x16ORIGINATE_GOAL_COMMAND\x10\x10\x12\x15\n\x11\x45\x44IT_GOAL_COMMAND\x10\x11\x12\x17\n\x13\x44\x45LETE_GOAL_COMMAND\x10\x12\x12\x17\n\x13\x43OMMIT_GOAL_COMMAND\x10\x13\x12\x1f\n\x1b\x45NTER_IN_ERROR_GOAL_COMMAND\x10\x14\x12\x19\n\x15ORIGINATE_HPI_COMMAND\x10\x15\x12\x14\n\x10\x45\x44IT_HPI_COMMAND\x10\x16\x12\x16\n\x12\x44\x45LETE_HPI_COMMAND\x10\x17\x12\x16\n\x12\x43OMMIT_HPI_COMMAND\x10\x18\x12\x1e\n\x1a\x45NTER_IN_ERROR_HPI_COMMAND\x10\x19\x12*\n&ORIGINATE_MEDICATION_STATEMENT_COMMAND\x10\x1a\x12%\n!EDIT_MEDICATION_STATEMENT_COMMAND\x10\x1b\x12\'\n#DELETE_MEDICATION_STATEMENT_COMMAND\x10\x1c\x12\'\n#COMMIT_MEDICATION_STATEMENT_COMMAND\x10\x1d\x12/\n+ENTER_IN_ERROR_MEDICATION_STATEMENT_COMMAND\x10\x1e\x12\x1a\n\x16ORIGINATE_PLAN_COMMAND\x10\x1f\x12\x15\n\x11\x45\x44IT_PLAN_COMMAND\x10 \x12\x17\n\x13\x44\x45LETE_PLAN_COMMAND\x10!\x12\x17\n\x13\x43OMMIT_PLAN_COMMAND\x10\"\x12\x1f\n\x1b\x45NTER_IN_ERROR_PLAN_COMMAND\x10#\x12\x1f\n\x1bORIGINATE_PRESCRIBE_COMMAND\x10$\x12\x1a\n\x16\x45\x44IT_PRESCRIBE_COMMAND\x10%\x12\x1c\n\x18\x44\x45LETE_PRESCRIBE_COMMAND\x10&\x12\x1c\n\x18\x43OMMIT_PRESCRIBE_COMMAND\x10\'\x12$\n ENTER_IN_ERROR_PRESCRIBE_COMMAND\x10(\x12#\n\x1fORIGINATE_QUESTIONNAIRE_COMMAND\x10)\x12\x1e\n\x1a\x45\x44IT_QUESTIONNAIRE_COMMAND\x10*\x12 \n\x1c\x44\x45LETE_QUESTIONNAIRE_COMMAND\x10+\x12 \n\x1c\x43OMMIT_QUESTIONNAIRE_COMMAND\x10,\x12(\n$ENTER_IN_ERROR_QUESTIONNAIRE_COMMAND\x10-\x12&\n\"ORIGINATE_REASON_FOR_VISIT_COMMAND\x10.\x12!\n\x1d\x45\x44IT_REASON_FOR_VISIT_COMMAND\x10/\x12#\n\x1f\x44\x45LETE_REASON_FOR_VISIT_COMMAND\x10\x30\x12#\n\x1f\x43OMMIT_REASON_FOR_VISIT_COMMAND\x10\x31\x12+\n\'ENTER_IN_ERROR_REASON_FOR_VISIT_COMMAND\x10\x32\x12%\n!ORIGINATE_STOP_MEDICATION_COMMAND\x10\x33\x12 \n\x1c\x45\x44IT_STOP_MEDICATION_COMMAND\x10\x34\x12\"\n\x1e\x44\x45LETE_STOP_MEDICATION_COMMAND\x10\x35\x12\"\n\x1e\x43OMMIT_STOP_MEDICATION_COMMAND\x10\x36\x12*\n&ENTER_IN_ERROR_STOP_MEDICATION_COMMAND\x10\x37\x12!\n\x1dORIGINATE_UPDATE_GOAL_COMMAND\x10\x38\x12\x1c\n\x18\x45\x44IT_UPDATE_GOAL_COMMAND\x10\x39\x12\x1e\n\x1a\x44\x45LETE_UPDATE_GOAL_COMMAND\x10:\x12\x1e\n\x1a\x43OMMIT_UPDATE_GOAL_COMMAND\x10;\x12&\n\"ENTER_IN_ERROR_UPDATE_GOAL_COMMAND\x10<\x12\x1d\n\x19ORIGINATE_PERFORM_COMMAND\x10=\x12\x18\n\x14\x45\x44IT_PERFORM_COMMAND\x10>\x12\x1a\n\x16\x44\x45LETE_PERFORM_COMMAND\x10?\x12\x1a\n\x16\x43OMMIT_PERFORM_COMMAND\x10@\x12\"\n\x1e\x45NTER_IN_ERROR_PERFORM_COMMAND\x10\x41\x12\x1e\n\x1aORIGINATE_INSTRUCT_COMMAND\x10\x42\x12\x19\n\x15\x45\x44IT_INSTRUCT_COMMAND\x10\x43\x12\x1b\n\x17\x44\x45LETE_INSTRUCT_COMMAND\x10\x44\x12\x1b\n\x17\x43OMMIT_INSTRUCT_COMMAND\x10\x45\x12#\n\x1f\x45NTER_IN_ERROR_INSTRUCT_COMMAND\x10\x46\x12\x1f\n\x1bORIGINATE_LAB_ORDER_COMMAND\x10G\x12\x1a\n\x16\x45\x44IT_LAB_ORDER_COMMAND\x10H\x12\x1c\n\x18\x44\x45LETE_LAB_ORDER_COMMAND\x10I\x12\x1c\n\x18\x43OMMIT_LAB_ORDER_COMMAND\x10J\x12$\n ENTER_IN_ERROR_LAB_ORDER_COMMAND\x10K\x12$\n ORIGINATE_FAMILY_HISTORY_COMMAND\x10L\x12\x1f\n\x1b\x45\x44IT_FAMILY_HISTORY_COMMAND\x10M\x12!\n\x1d\x44\x45LETE_FAMILY_HISTORY_COMMAND\x10N\x12!\n\x1d\x43OMMIT_FAMILY_HISTORY_COMMAND\x10O\x12)\n%ENTER_IN_ERROR_FAMILY_HISTORY_COMMAND\x10P\x12\x1d\n\x19ORIGINATE_ALLERGY_COMMAND\x10Q\x12\x18\n\x14\x45\x44IT_ALLERGY_COMMAND\x10R\x12\x1a\n\x16\x44\x45LETE_ALLERGY_COMMAND\x10S\x12\x1a\n\x16\x43OMMIT_ALLERGY_COMMAND\x10T\x12\"\n\x1e\x45NTER_IN_ERROR_ALLERGY_COMMAND\x10U\x12$\n ORIGINATE_REMOVE_ALLERGY_COMMAND\x10V\x12\x1f\n\x1b\x45\x44IT_REMOVE_ALLERGY_COMMAND\x10W\x12!\n\x1d\x44\x45LETE_REMOVE_ALLERGY_COMMAND\x10X\x12!\n\x1d\x43OMMIT_REMOVE_ALLERGY_COMMAND\x10Y\x12)\n%ENTER_IN_ERROR_REMOVE_ALLERGY_COMMAND\x10Z\x12&\n\"ORIGINATE_SURGICAL_HISTORY_COMMAND\x10[\x12!\n\x1d\x45\x44IT_SURGICAL_HISTORY_COMMAND\x10\\\x12#\n\x1f\x44\x45LETE_SURGICAL_HISTORY_COMMAND\x10]\x12#\n\x1f\x43OMMIT_SURGICAL_HISTORY_COMMAND\x10^\x12+\n\'ENTER_IN_ERROR_SURGICAL_HISTORY_COMMAND\x10_\x12\x0f\n\x0b\x43REATE_TASK\x10\x64\x12\x0f\n\x0bUPDATE_TASK\x10\x65\x12\x17\n\x13\x43REATE_TASK_COMMENT\x10\x66\x12%\n!ORIGINATE_MEDICAL_HISTORY_COMMAND\x10g\x12 \n\x1c\x45\x44IT_MEDICAL_HISTORY_COMMAND\x10h\x12\"\n\x1e\x44\x45LETE_MEDICAL_HISTORY_COMMAND\x10i\x12\"\n\x1e\x43OMMIT_MEDICAL_HISTORY_COMMAND\x10j\x12*\n&ENTER_IN_ERROR_MEDICAL_HISTORY_COMMAND\x10k\x12\x1f\n\x1b\x41\x44\x44_OR_UPDATE_PROTOCOL_CARD\x10n\x12\x1b\n\x16ORIGINATE_TASK_COMMAND\x10\x85\x01\x12\x16\n\x11\x45\x44IT_TASK_COMMAND\x10\x86\x01\x12\x18\n\x13\x44\x45LETE_TASK_COMMAND\x10\x87\x01\x12\x18\n\x13\x43OMMIT_TASK_COMMAND\x10\x88\x01\x12 \n\x1b\x45NTER_IN_ERROR_TASK_COMMAND\x10\x89\x01\x12\x1c\n\x18ORIGINATE_REFILL_COMMAND\x10q\x12\x17\n\x13\x45\x44IT_REFILL_COMMAND\x10r\x12\x19\n\x15\x44\x45LETE_REFILL_COMMAND\x10s\x12\x19\n\x15\x43OMMIT_REFILL_COMMAND\x10t\x12!\n\x1d\x45NTER_IN_ERROR_REFILL_COMMAND\x10u\x12\x1c\n\x18ORIGINATE_VITALS_COMMAND\x10v\x12\x17\n\x13\x45\x44IT_VITALS_COMMAND\x10w\x12\x19\n\x15\x44\x45LETE_VITALS_COMMAND\x10x\x12\x19\n\x15\x43OMMIT_VITALS_COMMAND\x10y\x12!\n\x1d\x45NTER_IN_ERROR_VITALS_COMMAND\x10z\x12&\n\"ORIGINATE_UPDATE_DIAGNOSIS_COMMAND\x10{\x12!\n\x1d\x45\x44IT_UPDATE_DIAGNOSIS_COMMAND\x10|\x12#\n\x1f\x44\x45LETE_UPDATE_DIAGNOSIS_COMMAND\x10}\x12#\n\x1f\x43OMMIT_UPDATE_DIAGNOSIS_COMMAND\x10~\x12+\n\'ENTER_IN_ERROR_UPDATE_DIAGNOSIS_COMMAND\x10\x7f\x12!\n\x1cORIGINATE_CLOSE_GOAL_COMMAND\x10\x80\x01\x12\x1c\n\x17\x45\x44IT_CLOSE_GOAL_COMMAND\x10\x81\x01\x12\x1e\n\x19\x44\x45LETE_CLOSE_GOAL_COMMAND\x10\x82\x01\x12\x1e\n\x19\x43OMMIT_CLOSE_GOAL_COMMAND\x10\x83\x01\x12&\n!ENTER_IN_ERROR_CLOSE_GOAL_COMMAND\x10\x84\x01\x12-\n(ANNOTATE_PATIENT_CHART_CONDITION_RESULTS\x10\xc8\x01\x12%\n ANNOTATE_CLAIM_CONDITION_RESULTS\x10\xac\x02\x12(\n#SHOW_PATIENT_CHART_SUMMARY_SECTIONS\x10\x90\x03\x62\x06proto3')
18
18
 
19
19
  _globals = globals()
20
20
  _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals)
@@ -22,7 +22,7 @@ _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'canvas_generated.messages.e
22
22
  if _descriptor._USE_C_DESCRIPTORS == False:
23
23
  DESCRIPTOR._options = None
24
24
  _globals['_EFFECTTYPE']._serialized_start=134
25
- _globals['_EFFECTTYPE']._serialized_end=2135
25
+ _globals['_EFFECTTYPE']._serialized_end=4448
26
26
  _globals['_EFFECT']._serialized_start=51
27
27
  _globals['_EFFECT']._serialized_end=131
28
28
  # @@protoc_insertion_point(module_scope)