canvas 0.32.0__py3-none-any.whl → 0.33.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 (257) hide show
  1. {canvas-0.32.0.dist-info → canvas-0.33.1.dist-info}/METADATA +2 -1
  2. canvas-0.33.1.dist-info/RECORD +272 -0
  3. canvas_generated/messages/effects_pb2.py +2 -2
  4. canvas_generated/messages/effects_pb2.pyi +4 -0
  5. canvas_sdk/__init__.py +3 -0
  6. canvas_sdk/commands/__init__.py +1 -1
  7. canvas_sdk/commands/base.py +3 -0
  8. canvas_sdk/commands/commands/__init__.py +1 -0
  9. canvas_sdk/commands/commands/adjust_prescription.py +3 -0
  10. canvas_sdk/commands/commands/allergy.py +7 -0
  11. canvas_sdk/commands/commands/assess.py +2 -0
  12. canvas_sdk/commands/commands/close_goal.py +3 -0
  13. canvas_sdk/commands/commands/diagnose.py +3 -0
  14. canvas_sdk/commands/commands/exam.py +3 -0
  15. canvas_sdk/commands/commands/family_history.py +3 -0
  16. canvas_sdk/commands/commands/follow_up.py +3 -0
  17. canvas_sdk/commands/commands/goal.py +3 -0
  18. canvas_sdk/commands/commands/history_present_illness.py +3 -0
  19. canvas_sdk/commands/commands/imaging_order.py +3 -0
  20. canvas_sdk/commands/commands/instruct.py +3 -0
  21. canvas_sdk/commands/commands/lab_order.py +3 -0
  22. canvas_sdk/commands/commands/medical_history.py +3 -0
  23. canvas_sdk/commands/commands/medication_statement.py +2 -0
  24. canvas_sdk/commands/commands/past_surgical_history.py +3 -0
  25. canvas_sdk/commands/commands/perform.py +3 -0
  26. canvas_sdk/commands/commands/plan.py +3 -0
  27. canvas_sdk/commands/commands/prescribe.py +8 -0
  28. canvas_sdk/commands/commands/questionnaire/__init__.py +3 -13
  29. canvas_sdk/commands/commands/questionnaire/question.py +10 -0
  30. canvas_sdk/commands/commands/reason_for_visit.py +3 -0
  31. canvas_sdk/commands/commands/refer.py +3 -0
  32. canvas_sdk/commands/commands/refill.py +3 -0
  33. canvas_sdk/commands/commands/remove_allergy.py +3 -0
  34. canvas_sdk/commands/commands/resolve_condition.py +3 -0
  35. canvas_sdk/commands/commands/review_of_systems.py +3 -0
  36. canvas_sdk/commands/commands/stop_medication.py +3 -0
  37. canvas_sdk/commands/commands/structured_assessment.py +3 -0
  38. canvas_sdk/commands/commands/task.py +7 -0
  39. canvas_sdk/commands/commands/update_diagnosis.py +3 -0
  40. canvas_sdk/commands/commands/update_goal.py +3 -0
  41. canvas_sdk/commands/commands/vitals.py +3 -0
  42. canvas_sdk/commands/constants.py +8 -0
  43. canvas_sdk/effects/__init__.py +1 -1
  44. canvas_sdk/effects/banner_alert/__init__.py +1 -1
  45. canvas_sdk/effects/banner_alert/add_banner_alert.py +3 -0
  46. canvas_sdk/effects/banner_alert/remove_banner_alert.py +3 -0
  47. canvas_sdk/effects/base.py +7 -0
  48. canvas_sdk/effects/billing_line_item/__init__.py +5 -1
  49. canvas_sdk/effects/billing_line_item/add_billing_line_item.py +3 -0
  50. canvas_sdk/effects/billing_line_item/remove_billing_line_item.py +3 -0
  51. canvas_sdk/effects/billing_line_item/update_billing_line_item.py +3 -0
  52. canvas_sdk/effects/launch_modal.py +3 -0
  53. canvas_sdk/effects/patient_chart_summary_configuration.py +3 -0
  54. canvas_sdk/effects/patient_portal/__init__.py +1 -0
  55. canvas_sdk/effects/patient_portal/application_configuration.py +3 -0
  56. canvas_sdk/effects/patient_portal/form_result.py +3 -0
  57. canvas_sdk/effects/patient_portal_menu_configuration.py +3 -0
  58. canvas_sdk/effects/patient_profile_configuration.py +6 -1
  59. canvas_sdk/effects/protocol_card/__init__.py +1 -1
  60. canvas_sdk/effects/protocol_card/protocol_card.py +6 -0
  61. canvas_sdk/effects/questionnaire_result.py +3 -0
  62. canvas_sdk/effects/send_invite.py +46 -0
  63. canvas_sdk/effects/show_button.py +3 -0
  64. canvas_sdk/effects/simple_api.py +9 -0
  65. canvas_sdk/effects/surescripts/__init__.py +2 -2
  66. canvas_sdk/effects/surescripts/surescripts_messages.py +7 -0
  67. canvas_sdk/effects/task/__init__.py +6 -1
  68. canvas_sdk/effects/task/task.py +8 -0
  69. canvas_sdk/effects/update_user.py +81 -0
  70. canvas_sdk/effects/widgets/__init__.py +1 -1
  71. canvas_sdk/effects/widgets/portal_widget.py +3 -0
  72. canvas_sdk/events/__init__.py +6 -1
  73. canvas_sdk/events/base.py +3 -0
  74. canvas_sdk/handlers/__init__.py +1 -1
  75. canvas_sdk/handlers/action_button.py +6 -0
  76. canvas_sdk/handlers/application.py +3 -0
  77. canvas_sdk/handlers/base.py +3 -0
  78. canvas_sdk/handlers/cron_task.py +3 -0
  79. canvas_sdk/handlers/simple_api/__init__.py +3 -2
  80. canvas_sdk/handlers/simple_api/api.py +26 -1
  81. canvas_sdk/handlers/simple_api/exceptions.py +10 -0
  82. canvas_sdk/handlers/simple_api/security.py +21 -5
  83. canvas_sdk/handlers/simple_api/tools.py +9 -0
  84. canvas_sdk/protocols/__init__.py +1 -1
  85. canvas_sdk/protocols/base.py +3 -0
  86. canvas_sdk/protocols/clinical_quality_measure.py +6 -1
  87. canvas_sdk/protocols/timeframe.py +3 -0
  88. canvas_sdk/questionnaires/__init__.py +1 -1
  89. canvas_sdk/questionnaires/utils.py +7 -0
  90. canvas_sdk/templates/__init__.py +1 -1
  91. canvas_sdk/templates/utils.py +3 -0
  92. canvas_sdk/utils/__init__.py +1 -1
  93. canvas_sdk/utils/http.py +69 -35
  94. canvas_sdk/utils/plugins.py +4 -0
  95. canvas_sdk/utils/stats.py +11 -0
  96. canvas_sdk/v1/__init__.py +1 -0
  97. canvas_sdk/v1/apps.py +3 -0
  98. canvas_sdk/v1/data/__init__.py +2 -2
  99. canvas_sdk/v1/data/allergy_intolerance.py +3 -0
  100. canvas_sdk/v1/data/appointment.py +7 -0
  101. canvas_sdk/v1/data/assessment.py +3 -0
  102. canvas_sdk/v1/data/banner_alert.py +3 -0
  103. canvas_sdk/v1/data/base.py +3 -0
  104. canvas_sdk/v1/data/billing.py +7 -0
  105. canvas_sdk/v1/data/care_team.py +7 -0
  106. canvas_sdk/v1/data/command.py +3 -0
  107. canvas_sdk/v1/data/common.py +18 -0
  108. canvas_sdk/v1/data/condition.py +7 -0
  109. canvas_sdk/v1/data/coverage.py +14 -0
  110. canvas_sdk/v1/data/detected_issue.py +3 -0
  111. canvas_sdk/v1/data/device.py +3 -0
  112. canvas_sdk/v1/data/imaging.py +7 -0
  113. canvas_sdk/v1/data/lab.py +16 -0
  114. canvas_sdk/v1/data/medication.py +3 -0
  115. canvas_sdk/v1/data/note.py +9 -0
  116. canvas_sdk/v1/data/observation.py +9 -0
  117. canvas_sdk/v1/data/organization.py +3 -0
  118. canvas_sdk/v1/data/patient.py +20 -3
  119. canvas_sdk/v1/data/practicelocation.py +7 -0
  120. canvas_sdk/v1/data/protocol_override.py +7 -0
  121. canvas_sdk/v1/data/questionnaire.py +16 -3
  122. canvas_sdk/v1/data/reason_for_visit.py +3 -0
  123. canvas_sdk/v1/data/staff.py +3 -0
  124. canvas_sdk/v1/data/task.py +12 -0
  125. canvas_sdk/v1/data/team.py +8 -1
  126. canvas_sdk/v1/data/user.py +5 -1
  127. canvas_sdk/v1/models.py +2 -0
  128. canvas_sdk/value_set/__init__.py +1 -0
  129. canvas_sdk/value_set/_utilities.py +16 -0
  130. canvas_sdk/value_set/custom.py +4 -0
  131. canvas_sdk/value_set/hcc2018.py +3 -0
  132. canvas_sdk/value_set/v2022/__init__.py +1 -0
  133. canvas_sdk/value_set/v2022/adverse_event.py +3 -0
  134. canvas_sdk/value_set/v2022/allergy.py +5 -0
  135. canvas_sdk/value_set/v2022/assessment.py +5 -0
  136. canvas_sdk/value_set/v2022/communication.py +5 -0
  137. canvas_sdk/value_set/v2022/condition.py +5 -0
  138. canvas_sdk/value_set/v2022/device.py +5 -0
  139. canvas_sdk/value_set/v2022/diagnostic_study.py +5 -0
  140. canvas_sdk/value_set/v2022/encounter.py +5 -0
  141. canvas_sdk/value_set/v2022/immunization.py +5 -0
  142. canvas_sdk/value_set/v2022/individual_characteristic.py +5 -0
  143. canvas_sdk/value_set/v2022/intervention.py +5 -0
  144. canvas_sdk/value_set/v2022/laboratory_test.py +5 -0
  145. canvas_sdk/value_set/v2022/medication.py +5 -0
  146. canvas_sdk/value_set/v2022/physical_exam.py +5 -0
  147. canvas_sdk/value_set/v2022/procedure.py +5 -0
  148. canvas_sdk/value_set/v2022/symptom.py +3 -0
  149. canvas_sdk/value_set/value_set.py +9 -0
  150. canvas_sdk/views/__init__.py +1 -0
  151. logger/__init__.py +2 -0
  152. logger/logger.py +3 -0
  153. plugin_runner/aws_headers.py +1 -1
  154. plugin_runner/load_all_plugins.py +202 -0
  155. plugin_runner/plugin_runner.py +26 -24
  156. plugin_runner/sandbox.py +497 -115
  157. protobufs/canvas_generated/messages/effects.proto +3 -0
  158. settings.py +5 -2
  159. canvas-0.32.0.dist-info/RECORD +0 -364
  160. canvas_cli/apps/auth/tests.py +0 -155
  161. canvas_cli/apps/plugin/tests.py +0 -85
  162. canvas_cli/conftest.py +0 -28
  163. canvas_cli/tests.py +0 -217
  164. canvas_cli/utils/context/tests.py +0 -131
  165. canvas_cli/utils/print/tests.py +0 -69
  166. canvas_cli/utils/urls/tests.py +0 -12
  167. canvas_cli/utils/validators/tests.py +0 -37
  168. canvas_sdk/commands/tests/protocol/__init__.py +0 -0
  169. canvas_sdk/commands/tests/protocol/tests.py +0 -83
  170. canvas_sdk/commands/tests/schema/__init__.py +0 -0
  171. canvas_sdk/commands/tests/schema/tests.py +0 -108
  172. canvas_sdk/commands/tests/test_base_command.py +0 -81
  173. canvas_sdk/commands/tests/test_utils.py +0 -375
  174. canvas_sdk/commands/tests/unit/__init__.py +0 -0
  175. canvas_sdk/commands/tests/unit/tests.py +0 -278
  176. canvas_sdk/effects/banner_alert/tests.py +0 -288
  177. canvas_sdk/effects/protocol_card/tests.py +0 -191
  178. canvas_sdk/questionnaires/tests/__init__.py +0 -0
  179. canvas_sdk/questionnaires/tests/test_utils.py +0 -74
  180. canvas_sdk/templates/tests/__init__.py +0 -0
  181. canvas_sdk/templates/tests/test_utils.py +0 -43
  182. canvas_sdk/tests/__init__.py +0 -0
  183. canvas_sdk/tests/handlers/__init__.py +0 -0
  184. canvas_sdk/tests/handlers/test_simple_api.py +0 -1167
  185. canvas_sdk/utils/tests.py +0 -72
  186. canvas_sdk/value_set/tests/test_value_sets.py +0 -72
  187. plugin_runner/tests/__init__.py +0 -0
  188. plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json +0 -29
  189. plugin_runner/tests/fixtures/plugins/example_plugin/README.md +0 -12
  190. plugin_runner/tests/fixtures/plugins/example_plugin/__init__.py +0 -0
  191. plugin_runner/tests/fixtures/plugins/example_plugin/protocols/__init__.py +0 -0
  192. plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py +0 -18
  193. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json +0 -38
  194. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md +0 -11
  195. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/__init__.py +0 -0
  196. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/my_protocol.py +0 -33
  197. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/__init__.py +0 -3
  198. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/templates/base.py +0 -6
  199. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/__init__.py +0 -5
  200. plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/utils/base.py +0 -4
  201. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json +0 -52
  202. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md +0 -11
  203. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/__init__.py +0 -0
  204. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/my_protocol.py +0 -39
  205. plugin_runner/tests/fixtures/plugins/test_load_questionnaire/questionnaires/example_questionnaire.yml +0 -61
  206. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json +0 -29
  207. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md +0 -12
  208. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module/__init__.py +0 -0
  209. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/other_module/base.py +0 -10
  210. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/__init__.py +0 -0
  211. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/my_protocol.py +0 -18
  212. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json +0 -29
  213. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md +0 -12
  214. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/other_module/__init__.py +0 -0
  215. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/other_module/base.py +0 -10
  216. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/__init__.py +0 -0
  217. plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/my_protocol.py +0 -18
  218. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json +0 -29
  219. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md +0 -12
  220. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/__init__.py +0 -0
  221. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/other_module/base.py +0 -3
  222. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/__init__.py +0 -0
  223. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py +0 -18
  224. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json +0 -29
  225. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md +0 -12
  226. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/__init__.py +0 -0
  227. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/other_module/base.py +0 -6
  228. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/__init__.py +0 -0
  229. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py +0 -18
  230. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json +0 -29
  231. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md +0 -12
  232. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/__init__.py +0 -0
  233. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/other_module/base.py +0 -8
  234. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/__init__.py +0 -0
  235. plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py +0 -18
  236. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json +0 -29
  237. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md +0 -12
  238. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/__init__.py +0 -0
  239. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/other_module/base.py +0 -3
  240. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py +0 -0
  241. plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py +0 -18
  242. plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json +0 -47
  243. plugin_runner/tests/fixtures/plugins/test_render_template/README.md +0 -11
  244. plugin_runner/tests/fixtures/plugins/test_render_template/protocols/__init__.py +0 -0
  245. plugin_runner/tests/fixtures/plugins/test_render_template/protocols/my_protocol.py +0 -43
  246. plugin_runner/tests/fixtures/plugins/test_render_template/templates/template.html +0 -10
  247. plugin_runner/tests/fixtures/plugins/test_simple_api/CANVAS_MANIFEST.json +0 -47
  248. plugin_runner/tests/fixtures/plugins/test_simple_api/README.md +0 -11
  249. plugin_runner/tests/fixtures/plugins/test_simple_api/__init__.py +0 -0
  250. plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/__init__.py +0 -0
  251. plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/my_protocol.py +0 -43
  252. plugin_runner/tests/test_application.py +0 -65
  253. plugin_runner/tests/test_plugin_installer.py +0 -127
  254. plugin_runner/tests/test_plugin_runner.py +0 -388
  255. plugin_runner/tests/test_sandbox.py +0 -137
  256. {canvas-0.32.0.dist-info → canvas-0.33.1.dist-info}/WHEEL +0 -0
  257. {canvas-0.32.0.dist-info → canvas-0.33.1.dist-info}/entry_points.txt +0 -0
@@ -17,6 +17,7 @@ import redis.asyncio as redis
17
17
  import sentry_sdk
18
18
  from asgiref.sync import sync_to_async
19
19
  from django.db import connections
20
+ from sentry_sdk.integrations.logging import ignore_logger
20
21
 
21
22
  from canvas_generated.messages.effects_pb2 import EffectType
22
23
  from canvas_generated.messages.plugins_pb2 import ReloadPluginsRequest, ReloadPluginsResponse
@@ -32,7 +33,7 @@ from canvas_sdk.utils.stats import get_duration_ms, statsd_client
32
33
  from logger import log
33
34
  from plugin_runner.authentication import token_for_plugin
34
35
  from plugin_runner.installation import install_plugins
35
- from plugin_runner.sandbox import Sandbox
36
+ from plugin_runner.sandbox import Sandbox, sandbox_from_module
36
37
  from settings import (
37
38
  CHANNEL_NAME,
38
39
  CUSTOMER_IDENTIFIER,
@@ -56,6 +57,10 @@ if SENTRY_DSN:
56
57
  profiles_sample_rate=0.0,
57
58
  )
58
59
 
60
+ # Sentry creates an issue for anything logged with logger.error();
61
+ # we want the exceptions themselves, not these error lines
62
+ ignore_logger("plugin_runner_logger")
63
+
59
64
  with sentry_sdk.configure_scope() as scope:
60
65
  scope.set_tag("customer", CUSTOMER_IDENTIFIER)
61
66
  scope.set_tag("logger", "python")
@@ -315,6 +320,12 @@ async def synchronize_plugins(run_once: bool = False) -> None:
315
320
  while True:
316
321
  message = await pubsub.get_message(ignore_subscribe_messages=True, timeout=5.0)
317
322
 
323
+ await pubsub.check_health()
324
+
325
+ if not pubsub.connection.is_connected: # type: ignore
326
+ log.info("synchronize_plugins: reconnecting to Redis")
327
+ await pubsub.connection.connect() # type: ignore
328
+
318
329
  if message is None:
319
330
  continue
320
331
 
@@ -345,12 +356,6 @@ async def synchronize_plugins(run_once: bool = False) -> None:
345
356
  log.error(f"synchronize_plugins: load_plugins failed: {e}")
346
357
  sentry_sdk.capture_exception(e)
347
358
 
348
- await pubsub.check_health()
349
-
350
- if not pubsub.connection.is_connected: # type: ignore
351
- log.info("synchronize_plugins: reconnecting to Redis")
352
- await pubsub.connection.connect() # type: ignore
353
-
354
359
  if run_once:
355
360
  break
356
361
 
@@ -432,18 +437,6 @@ def find_modules(base_path: pathlib.Path, prefix: str | None = None) -> list[str
432
437
  return modules
433
438
 
434
439
 
435
- def sandbox_from_module(base_path: pathlib.Path, module_name: str) -> Any:
436
- """Sandbox the code execution."""
437
- module_path = base_path / str(module_name.replace(".", "/") + ".py")
438
-
439
- if not module_path.exists():
440
- raise ModuleNotFoundError(f'Could not load module "{module_name}"')
441
-
442
- sandbox = Sandbox(module_path, namespace=module_name)
443
-
444
- return sandbox.execute()
445
-
446
-
447
440
  async def publish_message(message: dict) -> None:
448
441
  """Publish a message to the pubsub channel."""
449
442
  log.info(f'Publishing message to pubsub channel "{CHANNEL_NAME}"')
@@ -460,7 +453,7 @@ def get_client() -> tuple[redis.Redis, redis.client.PubSub]:
460
453
  return client, pubsub
461
454
 
462
455
 
463
- def load_or_reload_plugin(path: pathlib.Path) -> None:
456
+ def load_or_reload_plugin(path: pathlib.Path) -> bool:
464
457
  """Given a path, load or reload a plugin."""
465
458
  log.info(f'Loading plugin at "{path}"')
466
459
 
@@ -476,11 +469,11 @@ def load_or_reload_plugin(path: pathlib.Path) -> None:
476
469
  log.error(f'Unable to load plugin "{name}": {e}')
477
470
  sentry_sdk.capture_exception(e)
478
471
 
479
- return
472
+ return False
480
473
 
481
474
  secrets_file = path / SECRETS_FILE_NAME
482
-
483
475
  secrets_json = {}
476
+
484
477
  if secrets_file.exists():
485
478
  try:
486
479
  secrets_json = json.load(secrets_file.open())
@@ -497,7 +490,9 @@ def load_or_reload_plugin(path: pathlib.Path) -> None:
497
490
  log.error(f'Unable to load plugin "{name}": {str(e)}')
498
491
  sentry_sdk.capture_exception(e)
499
492
 
500
- return
493
+ return False
494
+
495
+ any_failed = False
501
496
 
502
497
  for handler in handlers:
503
498
  # TODO add class colon validation to existing schema validation
@@ -509,10 +504,13 @@ def load_or_reload_plugin(path: pathlib.Path) -> None:
509
504
  log.error(f'Unable to parse class for plugin "{name}": "{handler["class"]}"')
510
505
  sentry_sdk.capture_exception(e)
511
506
 
507
+ any_failed = True
508
+
512
509
  continue
513
510
 
514
511
  try:
515
- result = sandbox_from_module(path.parent, handler_module)
512
+ sandbox = sandbox_from_module(path.parent, handler_module)
513
+ result = sandbox.execute()
516
514
 
517
515
  if name_and_class in LOADED_PLUGINS:
518
516
  log.info(f"Reloading plugin '{name_and_class}'")
@@ -540,6 +538,10 @@ def load_or_reload_plugin(path: pathlib.Path) -> None:
540
538
 
541
539
  sentry_sdk.capture_exception(e)
542
540
 
541
+ any_failed = True
542
+
543
+ return not any_failed
544
+
543
545
 
544
546
  def refresh_event_type_map() -> None:
545
547
  """Ensure the event subscriptions are up to date."""