canvas 0.35.1__py3-none-any.whl → 0.37.0__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.
- {canvas-0.35.1.dist-info → canvas-0.37.0.dist-info}/METADATA +1 -1
- {canvas-0.35.1.dist-info → canvas-0.37.0.dist-info}/RECORD +42 -34
- canvas_cli/apps/plugin/plugin.py +3 -2
- canvas_cli/utils/validators/manifest_schema.py +15 -1
- canvas_generated/messages/effects_pb2.py +2 -2
- canvas_generated/messages/effects_pb2.pyi +8 -0
- canvas_generated/messages/events_pb2.py +2 -2
- canvas_generated/messages/events_pb2.pyi +26 -0
- canvas_sdk/caching/__init__.py +1 -0
- canvas_sdk/caching/base.py +127 -0
- canvas_sdk/caching/client.py +24 -0
- canvas_sdk/caching/exceptions.py +21 -0
- canvas_sdk/caching/plugins.py +20 -0
- canvas_sdk/caching/utils.py +28 -0
- canvas_sdk/commands/__init__.py +2 -0
- canvas_sdk/commands/commands/chart_section_review.py +23 -0
- canvas_sdk/commands/commands/prescribe.py +3 -0
- canvas_sdk/effects/launch_modal.py +1 -0
- canvas_sdk/effects/simple_api.py +61 -2
- canvas_sdk/handlers/simple_api/websocket.py +79 -0
- canvas_sdk/value_set/custom.py +1 -1
- canvas_sdk/value_set/v2022/allergy.py +1 -1
- canvas_sdk/value_set/v2022/assessment.py +1 -1
- canvas_sdk/value_set/v2022/communication.py +1 -1
- canvas_sdk/value_set/v2022/condition.py +1 -1
- canvas_sdk/value_set/v2022/device.py +1 -1
- canvas_sdk/value_set/v2022/diagnostic_study.py +1 -1
- canvas_sdk/value_set/v2022/encounter.py +1 -1
- canvas_sdk/value_set/v2022/immunization.py +1 -1
- canvas_sdk/value_set/v2022/individual_characteristic.py +1 -1
- canvas_sdk/value_set/v2022/intervention.py +1 -1
- canvas_sdk/value_set/v2022/laboratory_test.py +1 -1
- canvas_sdk/value_set/v2022/medication.py +1 -1
- canvas_sdk/value_set/v2022/physical_exam.py +1 -1
- canvas_sdk/value_set/v2022/procedure.py +1 -1
- plugin_runner/plugin_runner.py +15 -1
- plugin_runner/sandbox.py +5 -0
- protobufs/canvas_generated/messages/effects.proto +6 -0
- protobufs/canvas_generated/messages/events.proto +14 -12
- settings.py +28 -0
- {canvas-0.35.1.dist-info → canvas-0.37.0.dist-info}/WHEEL +0 -0
- {canvas-0.35.1.dist-info → canvas-0.37.0.dist-info}/entry_points.txt +0 -0
plugin_runner/plugin_runner.py
CHANGED
|
@@ -32,6 +32,7 @@ from canvas_generated.services.plugin_runner_pb2_grpc import (
|
|
|
32
32
|
from canvas_sdk.effects import Effect
|
|
33
33
|
from canvas_sdk.effects.simple_api import Response
|
|
34
34
|
from canvas_sdk.events import Event, EventRequest, EventResponse, EventType
|
|
35
|
+
from canvas_sdk.handlers.simple_api.websocket import DenyConnection
|
|
35
36
|
from canvas_sdk.protocols import ClinicalQualityMeasure
|
|
36
37
|
from canvas_sdk.utils import metrics
|
|
37
38
|
from canvas_sdk.utils.metrics import measured
|
|
@@ -180,7 +181,11 @@ class PluginRunner(PluginRunnerServicer):
|
|
|
180
181
|
plugin_name = event.target.id
|
|
181
182
|
# filter only for the plugin(s) that were created/updated
|
|
182
183
|
relevant_plugins = [p for p in relevant_plugins if p.startswith(f"{plugin_name}:")]
|
|
183
|
-
elif event_type in {
|
|
184
|
+
elif event_type in {
|
|
185
|
+
EventType.SIMPLE_API_AUTHENTICATE,
|
|
186
|
+
EventType.SIMPLE_API_REQUEST,
|
|
187
|
+
EventType.SIMPLE_API_WEBSOCKET_AUTHENTICATE,
|
|
188
|
+
}:
|
|
184
189
|
# The target plugin's name will be part of the home-app URL path, so other plugins that
|
|
185
190
|
# respond to SimpleAPI request events are not relevant
|
|
186
191
|
plugin_name = event.context["plugin_name"]
|
|
@@ -267,6 +272,15 @@ class PluginRunner(PluginRunnerServicer):
|
|
|
267
272
|
f" {event.context['path']}"
|
|
268
273
|
)
|
|
269
274
|
effect_list = [Response(status_code=HTTPStatus.INTERNAL_SERVER_ERROR).apply()]
|
|
275
|
+
if event.type == EventType.SIMPLE_API_WEBSOCKET_AUTHENTICATE:
|
|
276
|
+
if len(relevant_plugin_handlers) == 0:
|
|
277
|
+
effect_list = [DenyConnection().apply()]
|
|
278
|
+
elif len(relevant_plugin_handlers) > 1:
|
|
279
|
+
log.error(
|
|
280
|
+
f"Multiple handlers responded to {EventType.Name(EventType.SIMPLE_API_WEBSOCKET_AUTHENTICATE)}"
|
|
281
|
+
f" {event.context['channel']}"
|
|
282
|
+
)
|
|
283
|
+
effect_list = [DenyConnection().apply()]
|
|
270
284
|
|
|
271
285
|
# Don't log anything if a plugin handler didn't actually run.
|
|
272
286
|
if relevant_plugins:
|
plugin_runner/sandbox.py
CHANGED
|
@@ -81,6 +81,7 @@ SAFE_EXTERNAL_DUNDER_READ_ATTRIBUTES = {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
CANVAS_TOP_LEVEL_MODULES = (
|
|
84
|
+
"canvas_sdk.caching",
|
|
84
85
|
"canvas_sdk.commands",
|
|
85
86
|
"canvas_sdk.effects",
|
|
86
87
|
"canvas_sdk.events",
|
|
@@ -130,6 +131,10 @@ STANDARD_LIBRARY_MODULES = {
|
|
|
130
131
|
"b64decode",
|
|
131
132
|
"b64encode",
|
|
132
133
|
},
|
|
134
|
+
"collections": {
|
|
135
|
+
"Counter",
|
|
136
|
+
"defaultdict",
|
|
137
|
+
},
|
|
133
138
|
"datetime": {
|
|
134
139
|
"date",
|
|
135
140
|
"datetime",
|
|
@@ -233,6 +233,8 @@ enum EffectType {
|
|
|
233
233
|
COMMIT_ADJUST_PRESCRIPTION_COMMAND = 1303;
|
|
234
234
|
ENTER_IN_ERROR_ADJUST_PRESCRIPTION_COMMAND = 1304;
|
|
235
235
|
|
|
236
|
+
ORIGINATE_CHART_SECTION_REVIEW_COMMAND = 1400;
|
|
237
|
+
|
|
236
238
|
SHOW_ACTION_BUTTON = 1000;
|
|
237
239
|
|
|
238
240
|
PATIENT_PORTAL__FORM_RESULT = 2000;
|
|
@@ -260,6 +262,9 @@ enum EffectType {
|
|
|
260
262
|
LAUNCH_MODAL = 3000;
|
|
261
263
|
|
|
262
264
|
SIMPLE_API_RESPONSE = 4000;
|
|
265
|
+
SIMPLE_API_WEBSOCKET_ACCEPT = 4001;
|
|
266
|
+
SIMPLE_API_WEBSOCKET_DENY = 4002;
|
|
267
|
+
SIMPLE_API_WEBSOCKET_BROADCAST = 4003;
|
|
263
268
|
|
|
264
269
|
UPDATE_USER = 5000;
|
|
265
270
|
|
|
@@ -268,6 +273,7 @@ enum EffectType {
|
|
|
268
273
|
CREATE_SCHEDULE_EVENT = 6002;
|
|
269
274
|
|
|
270
275
|
CREATE_PATIENT = 6003;
|
|
276
|
+
|
|
271
277
|
}
|
|
272
278
|
|
|
273
279
|
message Effect {
|
|
@@ -157,6 +157,8 @@ enum EventType {
|
|
|
157
157
|
ADJUST_PRESCRIPTION__PHARMACY__POST_SEARCH = 2017;
|
|
158
158
|
ADJUST_PRESCRIPTION__CHANGE_MEDICATION_TO__PRE_SEARCH = 2018;
|
|
159
159
|
ADJUST_PRESCRIPTION__CHANGE_MEDICATION_TO__POST_SEARCH = 2019;
|
|
160
|
+
ADJUST_PRESCRIPTION__SUPERVISING_PROVIDER__PRE_SEARCH = 2021;
|
|
161
|
+
ADJUST_PRESCRIPTION__SUPERVISING_PROVIDER__POST_SEARCH = 2022;
|
|
160
162
|
|
|
161
163
|
// ADJUST_PROTOCOL_COMMAND__PRE_ORIGINATE = 3000;
|
|
162
164
|
// ADJUST_PROTOCOL_COMMAND__POST_ORIGINATE = 3001;
|
|
@@ -244,18 +246,12 @@ enum EventType {
|
|
|
244
246
|
CANCEL_PRESCRIPTION__SELECTED_PRESCRIPTION__PRE_SEARCH = 8012;
|
|
245
247
|
CANCEL_PRESCRIPTION__SELECTED_PRESCRIPTION__POST_SEARCH = 8013;
|
|
246
248
|
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
// CHART_SECTION_REVIEW_COMMAND__PRE_DELETE = 9006;
|
|
254
|
-
// CHART_SECTION_REVIEW_COMMAND__POST_DELETE = 9007;
|
|
255
|
-
// CHART_SECTION_REVIEW_COMMAND__PRE_ENTER_IN_ERROR = 9008;
|
|
256
|
-
// CHART_SECTION_REVIEW_COMMAND__POST_ENTER_IN_ERROR = 9009;
|
|
257
|
-
// CHART_SECTION_REVIEW_COMMAND__PRE_EXECUTE_ACTION = 9010;
|
|
258
|
-
// CHART_SECTION_REVIEW_COMMAND__POST_EXECUTE_ACTION = 9011;
|
|
249
|
+
CHART_SECTION_REVIEW_COMMAND__PRE_ORIGINATE = 9000;
|
|
250
|
+
CHART_SECTION_REVIEW_COMMAND__POST_ORIGINATE = 9001;
|
|
251
|
+
CHART_SECTION_REVIEW_COMMAND__PRE_ENTER_IN_ERROR = 9002;
|
|
252
|
+
CHART_SECTION_REVIEW_COMMAND__POST_ENTER_IN_ERROR = 9003;
|
|
253
|
+
CHART_SECTION_REVIEW_COMMAND__PRE_EXECUTE_ACTION = 9004;
|
|
254
|
+
CHART_SECTION_REVIEW_COMMAND__POST_EXECUTE_ACTION = 9005;
|
|
259
255
|
|
|
260
256
|
|
|
261
257
|
CLIPBOARD_COMMAND__PRE_ORIGINATE = 53000;
|
|
@@ -663,6 +659,8 @@ enum EventType {
|
|
|
663
659
|
PRESCRIBE__INDICATIONS__POST_SEARCH = 33015;
|
|
664
660
|
PRESCRIBE__PHARMACY__PRE_SEARCH = 33016;
|
|
665
661
|
PRESCRIBE__PHARMACY__POST_SEARCH = 33017;
|
|
662
|
+
PRESCRIBE__SUPERVISING_PROVIDER__POST_SEARCH = 33019;
|
|
663
|
+
PRESCRIBE__SUPERVISING_PROVIDER__PRE_SEARCH = 33020;
|
|
666
664
|
|
|
667
665
|
QUESTIONNAIRE_COMMAND__PRE_ORIGINATE = 34000;
|
|
668
666
|
QUESTIONNAIRE_COMMAND__POST_ORIGINATE = 34001;
|
|
@@ -763,6 +761,8 @@ enum EventType {
|
|
|
763
761
|
REFILL__INDICATIONS__POST_SEARCH = 39015;
|
|
764
762
|
REFILL__PHARMACY__PRE_SEARCH = 39016;
|
|
765
763
|
REFILL__PHARMACY__POST_SEARCH = 39017;
|
|
764
|
+
REFILL__SUPERVISING_PROVIDER__PRE_SEARCH = 39019;
|
|
765
|
+
REFILL__SUPERVISING_PROVIDER__POST_SEARCH = 39020;
|
|
766
766
|
|
|
767
767
|
REMOVE_ALLERGY_COMMAND__PRE_ORIGINATE = 40000;
|
|
768
768
|
REMOVE_ALLERGY_COMMAND__POST_ORIGINATE = 40001;
|
|
@@ -1093,6 +1093,8 @@ enum EventType {
|
|
|
1093
1093
|
|
|
1094
1094
|
SIMPLE_API_AUTHENTICATE = 130000;
|
|
1095
1095
|
SIMPLE_API_REQUEST = 130001;
|
|
1096
|
+
SIMPLE_API_WEBSOCKET_AUTHENTICATE = 130002;
|
|
1097
|
+
|
|
1096
1098
|
}
|
|
1097
1099
|
|
|
1098
1100
|
message Event {
|
settings.py
CHANGED
|
@@ -9,6 +9,7 @@ from env_tools import env_to_bool
|
|
|
9
9
|
load_dotenv()
|
|
10
10
|
|
|
11
11
|
BASE_DIR = Path(__file__).resolve().parent.resolve()
|
|
12
|
+
FOURTEEN_DAYS = 60 * 60 * 24 * 14
|
|
12
13
|
|
|
13
14
|
ENV = os.getenv("ENV", "development")
|
|
14
15
|
IS_PRODUCTION = ENV == "production"
|
|
@@ -24,6 +25,10 @@ INTEGRATION_TEST_CLIENT_SECRET = os.getenv("INTEGRATION_TEST_CLIENT_SECRET")
|
|
|
24
25
|
|
|
25
26
|
GRAPHQL_ENDPOINT = os.getenv("GRAPHQL_ENDPOINT", "http://localhost:8000/plugins-graphql")
|
|
26
27
|
REDIS_ENDPOINT = os.getenv("REDIS_ENDPOINT", f"redis://{APP_NAME}-redis:6379")
|
|
28
|
+
CANVAS_SDK_PLUGINS_CACHE_LOCATION = os.getenv(
|
|
29
|
+
"CANVAS_SDK_PLUGINS_CACHE_LOCATION", "plugin_io_plugins_cache"
|
|
30
|
+
)
|
|
31
|
+
CANVAS_SDK_CACHE_TIMEOUT_SECONDS = int(os.getenv("CANVAS_SDK_CACHE_TIMEOUT", FOURTEEN_DAYS))
|
|
27
32
|
|
|
28
33
|
|
|
29
34
|
METRICS_ENABLED = env_to_bool("PLUGINS_METRICS_ENABLED", not IS_SCRIPT)
|
|
@@ -110,3 +115,26 @@ TEMPLATES = [
|
|
|
110
115
|
"OPTIONS": {},
|
|
111
116
|
},
|
|
112
117
|
]
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
if IS_TESTING:
|
|
121
|
+
CACHES = {
|
|
122
|
+
"default": {
|
|
123
|
+
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
|
124
|
+
},
|
|
125
|
+
"plugins": {
|
|
126
|
+
"BACKEND": "django.core.cache.backends.locmem.LocMemCache",
|
|
127
|
+
"KEY_PREFIX": CUSTOMER_IDENTIFIER,
|
|
128
|
+
"LOCATION": "plugins_cache",
|
|
129
|
+
"TIMEOUT": CANVAS_SDK_CACHE_TIMEOUT_SECONDS,
|
|
130
|
+
},
|
|
131
|
+
}
|
|
132
|
+
else:
|
|
133
|
+
CACHES = {
|
|
134
|
+
"plugins": {
|
|
135
|
+
"BACKEND": "django.core.cache.backends.db.DatabaseCache",
|
|
136
|
+
"KEY_PREFIX": CUSTOMER_IDENTIFIER,
|
|
137
|
+
"LOCATION": CANVAS_SDK_PLUGINS_CACHE_LOCATION,
|
|
138
|
+
"TIMEOUT": CANVAS_SDK_CACHE_TIMEOUT_SECONDS,
|
|
139
|
+
}
|
|
140
|
+
}
|
|
File without changes
|
|
File without changes
|