diff --git a/CLAUDE.md b/CLAUDE.md new file mode 100644 index 000000000..95dfc9843 --- /dev/null +++ b/CLAUDE.md @@ -0,0 +1,67 @@ +# canvas-plugins + +event-driven plugin SDK and runtime for Canvas Medical EHR. published as the `canvas` PyPI package. + +## project layout + +- `canvas_sdk/` - SDK for plugin authors (handlers, effects, commands, events, data models) +- `plugin_runner/` - gRPC service that loads/sandboxes/executes plugins via `RestrictedPython` +- `canvas_cli/` - typer CLI (`canvas init`, `canvas install`, `canvas emit`, etc.) +- `canvas_generated/` - auto-generated protobuf python; **do not edit directly** +- `protobufs/` - source `.proto` definitions +- `pubsub/` - redis pub/sub for plugin reload signals and log streaming +- `logger/` - structured logging with logstash + redis +- `example-plugins/` - tens of reference plugins +- `settings.py` - django settings (sqlite in tests, postgres in prod) +- `conftest.py` - root pytest fixtures + +## companion repo + +`../canvas/home-app/` is the main Canvas app. cross-repo changes are common: +- protobuf changes here must be copied to home-app's `canvas_generated/` +- new SDK data models (`canvas_sdk/v1/data/`) mirror home-app Django models (read-only) +- home-app's `plugin_io/database_views.py` exposes DB views for SDK models +- run `bin/generate-protobufs` after changing `.proto` files + +## key architecture + +- plugins declare handled events in `CANVAS_MANIFEST.json` +- `plugin_runner.plugin_runner.EVENT_HANDLER_MAP` maps event names → handler classes +- `LOADED_PLUGINS` tracks installed plugin metadata +- handlers extend `BaseHandler`, implement `compute()` returning effects +- prefer "handlers" over "protocols" everywhere: use `handlers` key in `CANVAS_MANIFEST.json`, `BaseHandler` over `BaseProtocol`, `canvas_sdk.handlers` over `canvas_sdk.protocols`. the `protocols` names still work but are legacy +- plugin code runs in a `RestrictedPython` sandbox with an allowed-imports whitelist +- `plugin_runner/allowed-module-imports.json` is auto-generated by pre-commit + +## tooling + +- **python**: 3.11, 3.12 (requires >=3.11, <3.13) +- **package manager**: `uv` (>=0.8.0) +- **build**: hatchling +- **release**: python-semantic-release, tag-based versioning + +## commands + +```sh +uv run pytest -m "not integtest" # unit tests +uv run pytest path/to/test.py -k name # specific test +uv run mypy canvas_sdk/ plugin_runner/ # type checking (or use bin/mypy) +uv run ruff check --fix . # lint +uv run ruff format . # format +bin/generate-protobufs # regenerate protobuf python +uv run python -m plugin_runner.generate_allowed_imports # update import whitelist +``` + +## code style + +- prefer simple test functions over test classes +- use `pydantic` for command validation, real types over `Any` + +## testing + +- pytest with django plugin, uses sqlite in test mode +- `conftest.py` fixtures: `install_test_plugin`, `load_test_plugins`, `cli_runner` +- plugin test fixtures live in `plugin_runner/tests/fixtures/plugins/` +- CI tests against python 3.11 and 3.12 matrix +- example plugins each tested independently in CI +- integration tests dispatched to the canvas repo diff --git a/canvas_cli/apps/plugin/plugin.py b/canvas_cli/apps/plugin/plugin.py index 1717e5f03..70c77b28f 100644 --- a/canvas_cli/apps/plugin/plugin.py +++ b/canvas_cli/apps/plugin/plugin.py @@ -186,10 +186,10 @@ def _get_meta_properties(protocol_path: Path, classname: str) -> dict[str, str]: return meta -def _get_protocols_with_new_cqm_properties( +def _get_handlers_with_new_cqm_properties( protocol_classes: Iterable[dict[str, Any]], plugin: Path ) -> Iterable[dict[str, Any]] | None: - """Extract the meta properties of any ClinicalQualityMeasure Protocols included in the plugin if they have changed.""" + """Extract the meta properties of any ClinicalQualityMeasure handlers included in the plugin if they have changed.""" has_updates = False protocol_props = [] for p in protocol_classes: @@ -229,8 +229,8 @@ def parse_secrets(secrets: builtins.list[str]) -> builtins.list[str]: def init( plugin_type: str = typer.Argument( - "protocol", - help="The type of plugin to create. Options are 'application' or 'protocol'.", + "handler", + help="The type of plugin to create. Options are 'application' or 'handler'.", ), ) -> None: """Create a new plugin.""" @@ -604,7 +604,7 @@ def validate_manifest( try: manifest_json = json.loads(manifest.read_text()) protocols = manifest_json.get("components", {}).get("protocols", []) - if new_protocols := _get_protocols_with_new_cqm_properties(protocols, plugin_name): + if new_protocols := _get_handlers_with_new_cqm_properties(protocols, plugin_name): print( f"Updating the CANVAS_MANIFEST.json file for {plugin_name} with CQM meta properties" ) diff --git a/canvas_cli/utils/validators/tests.py b/canvas_cli/utils/validators/tests.py index d5c1ecde2..def255971 100644 --- a/canvas_cli/utils/validators/tests.py +++ b/canvas_cli/utils/validators/tests.py @@ -4,17 +4,17 @@ @pytest.fixture -def protocol_manifest_example() -> dict: - """Return a valid protocol manifest example.""" +def handler_manifest_example() -> dict: + """Return a valid handler manifest example.""" return { "sdk_version": "0.3.1", "plugin_version": "1.0.1", "name": "Prompt to prescribe when assessing condition", "description": "To assist in ....", "components": { - "protocols": [ + "handlers": [ { - "class": "prompt_to_prescribe.protocols.prompt_when_assessing.PromptWhenAssessing", + "class": "prompt_to_prescribe.handlers.prompt_when_assessing.PromptWhenAssessing", "description": "probably the same as the plugin's description", "data_access": { "event": "", @@ -32,6 +32,6 @@ def protocol_manifest_example() -> dict: } -def test_manifest_file_schema(protocol_manifest_example: dict) -> None: +def test_manifest_file_schema(handler_manifest_example: dict) -> None: """Test that no exception raised when a valid manifest file is validated.""" - validate_manifest_file(protocol_manifest_example) + validate_manifest_file(handler_manifest_example) diff --git a/canvas_sdk/protocols/base.py b/canvas_sdk/protocols/base.py index c1583a067..2d3f83ad8 100644 --- a/canvas_sdk/protocols/base.py +++ b/canvas_sdk/protocols/base.py @@ -4,9 +4,7 @@ class BaseProtocol(BaseHandler, ABC): - """ - The class that protocols inherit from. - """ + """Deprecated alias for BaseHandler. Use canvas_sdk.handlers.base.BaseHandler instead.""" pass diff --git a/canvas_sdk/tests/caching/test_plugins.py b/canvas_sdk/tests/caching/test_plugins.py index 0dd4571d8..7daa97691 100644 --- a/canvas_sdk/tests/caching/test_plugins.py +++ b/canvas_sdk/tests/caching/test_plugins.py @@ -78,13 +78,13 @@ def test_plugin_successfully_sets_gets_key_value_in_cache( install_test_plugin: Path, load_test_plugins: None ) -> None: """Test that the plugin successfully sets and gets a key-value pair in the cache.""" - plugin = LOADED_PLUGINS["test_caching_api:test_caching_api.protocols.my_protocol:Protocol"] + plugin = LOADED_PLUGINS["test_caching_api:test_caching_api.handlers.my_handler:Handler"] effects = plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() assert effects[0].payload == "bar" plugin = LOADED_PLUGINS[ - "test_caching_api:test_caching_api.protocols.my_secondary_protocol:Protocol" + "test_caching_api:test_caching_api.handlers.my_secondary_handler:Handler" ] effects = plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() @@ -97,7 +97,7 @@ def test_plugin_access_to_private_properties_cache_is_forbidden( ) -> None: """Test that plugin access to private properties of the cache api is forbidden.""" assert ( - "test_caching_api:test_caching_api.protocols.my_protocol:ForbiddenProtocol" + "test_caching_api:test_caching_api.handlers.my_handler:ForbiddenHandler" not in LOADED_PLUGINS ) diff --git a/canvas_sdk/tests/questionnaires/test_utils.py b/canvas_sdk/tests/questionnaires/test_utils.py index 29238ff17..324c19223 100644 --- a/canvas_sdk/tests/questionnaires/test_utils.py +++ b/canvas_sdk/tests/questionnaires/test_utils.py @@ -15,7 +15,7 @@ def test_from_yaml_valid_questionnaire(install_test_plugin: Path, load_test_plugins: None) -> None: """Test that the from_yaml function loads a valid questionnaire.""" plugin = LOADED_PLUGINS[ - "test_load_questionnaire:test_load_questionnaire.protocols.my_protocol:ValidQuestionnaire" + "test_load_questionnaire:test_load_questionnaire.handlers.my_protocol:ValidQuestionnaire" ] result: list[Effect] = plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() @@ -39,7 +39,7 @@ def test_from_yaml_invalid_questionnaire( ) -> None: """Test that the from_yaml function raises an error for invalid questionnaires.""" plugin = LOADED_PLUGINS[ - "test_load_questionnaire:test_load_questionnaire.protocols.my_protocol:InvalidQuestionnaire" + "test_load_questionnaire:test_load_questionnaire.handlers.my_protocol:InvalidQuestionnaire" ] with pytest.raises(FileNotFoundError): plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() @@ -51,7 +51,7 @@ def test_from_yaml_forbidden_questionnaire( ) -> None: """Test that the from_yaml function raises an error for a questionnaire outside plugin package.""" plugin = LOADED_PLUGINS[ - "test_load_questionnaire:test_load_questionnaire.protocols.my_protocol:ForbiddenQuestionnaire" + "test_load_questionnaire:test_load_questionnaire.handlers.my_protocol:ForbiddenQuestionnaire" ] with pytest.raises(PermissionError): plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() diff --git a/canvas_sdk/tests/templates/test_utils.py b/canvas_sdk/tests/templates/test_utils.py index 47ccb8330..7385ab9e6 100644 --- a/canvas_sdk/tests/templates/test_utils.py +++ b/canvas_sdk/tests/templates/test_utils.py @@ -13,7 +13,7 @@ def test_render_to_string_valid_template( ) -> None: """Test that the render_to_string function loads and renders a valid template.""" plugin = LOADED_PLUGINS[ - "test_render_template:test_render_template.protocols.my_protocol:ValidTemplate" + "test_render_template:test_render_template.handlers.my_protocol:ValidTemplate" ] result: list[Effect] = plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() assert "This is always here" in result[0].payload @@ -26,7 +26,7 @@ def test_render_to_string_valid_child_template( ) -> None: """Test that the render_to_string function allows template inheritance.""" plugin = LOADED_PLUGINS[ - "test_render_template:test_render_template.protocols.my_protocol:TemplateInheritance" + "test_render_template:test_render_template.handlers.my_protocol:TemplateInheritance" ] result: list[Effect] = plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() assert "This is always here" in result[0].payload @@ -40,7 +40,7 @@ def test_render_to_string_invalid_template( ) -> None: """Test that the render_to_string function raises an error for invalid templates.""" plugin = LOADED_PLUGINS[ - "test_render_template:test_render_template.protocols.my_protocol:InvalidTemplate" + "test_render_template:test_render_template.handlers.my_protocol:InvalidTemplate" ] with pytest.raises(FileNotFoundError): plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() @@ -52,7 +52,7 @@ def test_render_to_string_forbidden_template( ) -> None: """Test that the render_to_string function raises an error for a template outside plugin package.""" plugin = LOADED_PLUGINS[ - "test_render_template:test_render_template.protocols.my_protocol:ForbiddenTemplate" + "test_render_template:test_render_template.handlers.my_protocol:ForbiddenTemplate" ] with pytest.raises(PermissionError): plugin["class"](Event(EventRequest(type=EventType.UNKNOWN))).compute() diff --git a/canvas_sdk/tests/utils/test_metrics.py b/canvas_sdk/tests/utils/test_metrics.py index 7817d55c3..0cef9fe7c 100644 --- a/canvas_sdk/tests/utils/test_metrics.py +++ b/canvas_sdk/tests/utils/test_metrics.py @@ -156,7 +156,7 @@ def test_track_plugins_usage_adds_plugin_tags(mock_time: MagicMock) -> None: with ( patch( "canvas_sdk.utils.plugins.is_plugin_caller", - return_value=(True, "my_plugin.protocols.handler"), + return_value=(True, "my_plugin.handlers.handler"), ), measure("block", track_plugins_usage=True, client=client), ): @@ -164,7 +164,7 @@ def test_track_plugins_usage_adds_plugin_tags(mock_time: MagicMock) -> None: tags = pipeline.timing.call_args.kwargs["tags"] assert tags["plugin"] == "my_plugin" - assert tags["handler"] == "my_plugin.protocols.handler" + assert tags["handler"] == "my_plugin.handlers.handler" @patch("canvas_sdk.utils.metrics.time") @@ -218,7 +218,7 @@ def test_track_memory_usage_captures_rss_delta( @patch("canvas_sdk.utils.metrics.log") @patch( "canvas_sdk.utils.plugins.is_plugin_caller", - return_value=(True, "test_plugin.protocols.handler"), + return_value=(True, "test_plugin.handlers.handler"), ) @patch("canvas_sdk.utils.metrics.psutil") @patch("canvas_sdk.utils.metrics.time") @@ -269,7 +269,7 @@ def test_memory_below_threshold_no_warning( @patch("canvas_sdk.utils.metrics.log") @patch( "canvas_sdk.utils.plugins.is_plugin_caller", - return_value=(True, "test_plugin.protocols.handler"), + return_value=(True, "test_plugin.handlers.handler"), ) @patch("canvas_sdk.utils.metrics.psutil") @patch("canvas_sdk.utils.metrics.time") diff --git a/example-plugins/abnormal_lab_task_notification/abnormal_lab_task_notification/CANVAS_MANIFEST.json b/example-plugins/abnormal_lab_task_notification/abnormal_lab_task_notification/CANVAS_MANIFEST.json index 0ae649042..515bab872 100644 --- a/example-plugins/abnormal_lab_task_notification/abnormal_lab_task_notification/CANVAS_MANIFEST.json +++ b/example-plugins/abnormal_lab_task_notification/abnormal_lab_task_notification/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "abnormal_lab_task_notification", "description": "A plugin that creates task notifications for abnormal lab values", "components": { - "protocols": [ + "handlers": [ { "class": "abnormal_lab_task_notification.handlers.abnormal_lab_handler:AbnormalLabHandler", "description": "Monitors lab reports and creates tasks for abnormal values", diff --git a/example-plugins/ai_note_titles/ai_note_titles/CANVAS_MANIFEST.json b/example-plugins/ai_note_titles/ai_note_titles/CANVAS_MANIFEST.json index cb2b0ce00..8df503c45 100644 --- a/example-plugins/ai_note_titles/ai_note_titles/CANVAS_MANIFEST.json +++ b/example-plugins/ai_note_titles/ai_note_titles/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "ai_note_titles", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { "class": "ai_note_titles.handlers.rename_note:Handler", "description": "Renames Notes when locked using OpenAI and the contents of the Note" diff --git a/example-plugins/api_samples/api_samples/CANVAS_MANIFEST.json b/example-plugins/api_samples/api_samples/CANVAS_MANIFEST.json index 478c7ff1c..93069c719 100644 --- a/example-plugins/api_samples/api_samples/CANVAS_MANIFEST.json +++ b/example-plugins/api_samples/api_samples/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "api_samples", "description": "Example usages of the SimpleAPI handler", "components": { - "protocols": [ + "handlers": [ { "class": "api_samples.routes.hello_world:HelloWorldAPI", "description": "Returns a json message" diff --git a/example-plugins/appointment_coverage_label/appointment_coverage_label/CANVAS_MANIFEST.json b/example-plugins/appointment_coverage_label/appointment_coverage_label/CANVAS_MANIFEST.json index b4b0048e4..12f333f00 100644 --- a/example-plugins/appointment_coverage_label/appointment_coverage_label/CANVAS_MANIFEST.json +++ b/example-plugins/appointment_coverage_label/appointment_coverage_label/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name":"appointment_coverage_label", "description": "Automatically manages appointment labels based on patient insurance coverage status. Adds a 'MISSING_COVERAGE' label to appointments for patients without coverage, and removes the label when coverage is subsequently added.", "components":{ - "protocols":[ + "handlers":[ { - "class":"appointment_coverage_label.protocols.appointment_labels:AppointmentLabelsProtocol", + "class":"appointment_coverage_label.handlers.appointment_labels:AppointmentLabelsHandler", "description": "Monitors appointment and coverage events to automatically add or remove the 'MISSING_COVERAGE' label based on patient insurance coverage status.", "data_access":{ "event":"read", diff --git a/example-plugins/appointment_coverage_label/appointment_coverage_label/README.md b/example-plugins/appointment_coverage_label/appointment_coverage_label/README.md index f11c4815b..9d818ae37 100644 --- a/example-plugins/appointment_coverage_label/appointment_coverage_label/README.md +++ b/example-plugins/appointment_coverage_label/appointment_coverage_label/README.md @@ -181,7 +181,7 @@ appointment_coverage_label/ ### Key Components -- **AppointmentLabelsProtocol** - Main protocol class handling both events +- **AppointmentLabelsHandler** - Main protocol class handling both events - **handle_coverage_created()** - Removes labels when coverage is added - **handle_appointment_created()** - Adds labels when appointments are created for patients without coverage - **compute()** - Routes events to appropriate handlers diff --git a/example-plugins/appointment_coverage_label/appointment_coverage_label/protocols/__init__.py b/example-plugins/appointment_coverage_label/appointment_coverage_label/handlers/__init__.py similarity index 100% rename from example-plugins/appointment_coverage_label/appointment_coverage_label/protocols/__init__.py rename to example-plugins/appointment_coverage_label/appointment_coverage_label/handlers/__init__.py diff --git a/example-plugins/appointment_coverage_label/appointment_coverage_label/protocols/appointment_labels.py b/example-plugins/appointment_coverage_label/appointment_coverage_label/handlers/appointment_labels.py similarity index 96% rename from example-plugins/appointment_coverage_label/appointment_coverage_label/protocols/appointment_labels.py rename to example-plugins/appointment_coverage_label/appointment_coverage_label/handlers/appointment_labels.py index 9df533b36..11334b2df 100644 --- a/example-plugins/appointment_coverage_label/appointment_coverage_label/protocols/appointment_labels.py +++ b/example-plugins/appointment_coverage_label/appointment_coverage_label/handlers/appointment_labels.py @@ -2,20 +2,20 @@ from canvas_sdk.effects.note import RemoveAppointmentLabel from canvas_sdk.effects.note.appointment import AddAppointmentLabel from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from canvas_sdk.v1.data import Appointment, Coverage, Patient from logger import log -class AppointmentLabelsProtocol(BaseProtocol): +class AppointmentLabelsHandler(BaseHandler): """ Manages the 'MISSING_COVERAGE' label on patient appointments based on insurance coverage status. - This protocol automatically: + This handler automatically: 1. Adds 'MISSING_COVERAGE' labels to all appointments for patients without insurance coverage 2. Removes 'MISSING_COVERAGE' labels from all appointments when insurance coverage is added - The protocol responds to two events: + The handler responds to two events: - APPOINTMENT_CREATED: Checks if the patient has coverage and adds labels if needed - COVERAGE_CREATED: Removes labels from all appointments when coverage is added @@ -185,7 +185,7 @@ def compute(self) -> list[Effect]: list[Effect]: List of effects from the appropriate handler, or empty list if event type is not recognized """ - log.info(f"AppointmentLabelsProtocol.compute() called for event type: {self.event.type}") + log.info(f"AppointmentLabelsHandler.compute() called for event type: {self.event.type}") if self.event.type == EventType.APPOINTMENT_CREATED: return self.handle_appointment_created() @@ -193,7 +193,7 @@ def compute(self) -> list[Effect]: return self.handle_coverage_created() log.warning( - f"Received unexpected event type '{self.event.type}' in AppointmentLabelsProtocol. " + f"Received unexpected event type '{self.event.type}' in AppointmentLabelsHandler. " "No handler available." ) return [] diff --git a/example-plugins/appointment_coverage_label/tests/test_appointment_labels.py b/example-plugins/appointment_coverage_label/tests/test_appointment_labels.py index 4f31a24a8..d75c06fbf 100644 --- a/example-plugins/appointment_coverage_label/tests/test_appointment_labels.py +++ b/example-plugins/appointment_coverage_label/tests/test_appointment_labels.py @@ -7,25 +7,25 @@ from canvas_sdk.events import EventType -class TestAppointmentLabelsProtocol: - """Test suite for AppointmentLabelsProtocol.""" +class TestAppointmentLabelsHandler: + """Test suite for AppointmentLabelsHandler.""" def test_responds_to_correct_events(self) -> None: """Test that protocol responds to both COVERAGE_CREATED and APPOINTMENT_CREATED events.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) expected_events = [ EventType.Name(EventType.COVERAGE_CREATED), EventType.Name(EventType.APPOINTMENT_CREATED), ] - assert expected_events == AppointmentLabelsProtocol.RESPONDS_TO + assert expected_events == AppointmentLabelsHandler.RESPONDS_TO def test_compute_routes_to_coverage_created_handler(self, monkeypatch: MonkeyPatch) -> None: """Test that compute() routes COVERAGE_CREATED events to correct handler.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event @@ -35,19 +35,19 @@ def test_compute_routes_to_coverage_created_handler(self, monkeypatch: MonkeyPat # Mock context dummy_context = {"patient": {"id": "test-patient-id"}} - # Create protocol instance - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock the handler method - with patch.object(protocol, "handle_coverage_created", return_value=[]) as mock_handler: - protocol.compute() + with patch.object(handler, "handle_coverage_created", return_value=[]) as mock_handler: + handler.compute() mock_handler.assert_called_once() def test_compute_routes_to_appointment_created_handler(self, monkeypatch: MonkeyPatch) -> None: """Test that compute() routes APPOINTMENT_CREATED events to correct handler.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event @@ -57,19 +57,19 @@ def test_compute_routes_to_appointment_created_handler(self, monkeypatch: Monkey # Mock context dummy_context = {"patient": {"id": "test-patient-id"}} - # Create protocol instance - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock the handler method - with patch.object(protocol, "handle_appointment_created", return_value=[]) as mock_handler: - protocol.compute() + with patch.object(handler, "handle_appointment_created", return_value=[]) as mock_handler: + handler.compute() mock_handler.assert_called_once() def test_compute_with_unexpected_event_type(self, monkeypatch: MonkeyPatch) -> None: """Test that compute() handles unexpected event types gracefully.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event with unexpected type @@ -79,17 +79,17 @@ def test_compute_with_unexpected_event_type(self, monkeypatch: MonkeyPatch) -> N # Mock context dummy_context = {"patient": {"id": "test-patient-id"}} - # Create protocol instance - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) - result = protocol.compute() + result = handler.compute() assert result == [] def test_handle_coverage_created_removes_labels(self, monkeypatch: MonkeyPatch) -> None: """Test that handle_coverage_created removes MISSING_COVERAGE labels.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context @@ -112,28 +112,28 @@ def test_handle_coverage_created_removes_labels(self, monkeypatch: MonkeyPatch) mock_queryset.__len__.return_value = 2 mock_queryset.__iter__.return_value = iter([mock_appt1, mock_appt2]) - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: mock_patient_get.return_value = mock_patient with patch( - "appointment_coverage_label.protocols.appointment_labels.Appointment.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Appointment.objects.filter" ) as mock_filter: mock_filter.return_value.prefetch_related.return_value = mock_queryset with patch( - "appointment_coverage_label.protocols.appointment_labels.RemoveAppointmentLabel" + "appointment_coverage_label.handlers.appointment_labels.RemoveAppointmentLabel" ) as mock_effect_class: mock_effect_instance = MagicMock() mock_applied_effect = MagicMock() mock_effect_instance.apply.return_value = mock_applied_effect mock_effect_class.return_value = mock_effect_instance - result = protocol.handle_coverage_created() + result = handler.handle_coverage_created() # Verify RemoveAppointmentLabel was called for both appointments assert mock_effect_class.call_count == 2 @@ -143,8 +143,8 @@ def test_handle_coverage_created_no_appointments_to_update( self, monkeypatch: MonkeyPatch ) -> None: """Test handle_coverage_created when no appointments need labels removed.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context @@ -158,51 +158,51 @@ def test_handle_coverage_created_no_appointments_to_update( mock_queryset = MagicMock() mock_queryset.exists.return_value = False - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: mock_patient_get.return_value = mock_patient with patch( - "appointment_coverage_label.protocols.appointment_labels.Appointment.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Appointment.objects.filter" ) as mock_filter: mock_filter.return_value.prefetch_related.return_value = mock_queryset - result = protocol.handle_coverage_created() + result = handler.handle_coverage_created() assert result == [] def test_handle_coverage_created_patient_not_found(self, monkeypatch: MonkeyPatch) -> None: """Test handle_coverage_created when patient doesn't exist.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context mock_event = MagicMock() dummy_context = {"patient": {"id": "nonexistent-patient"}} - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: - from appointment_coverage_label.protocols.appointment_labels import Patient + from appointment_coverage_label.handlers.appointment_labels import Patient mock_patient_get.side_effect = Patient.DoesNotExist() - result = protocol.handle_coverage_created() + result = handler.handle_coverage_created() assert result == [] def test_handle_appointment_created_adds_labels_when_no_coverage( self, monkeypatch: MonkeyPatch ) -> None: """Test that handle_appointment_created adds labels when patient has no coverage.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context @@ -229,33 +229,33 @@ def test_handle_appointment_created_adds_labels_when_no_coverage( mock_coverage_queryset = MagicMock() mock_coverage_queryset.exists.return_value = False - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: mock_patient_get.return_value = mock_patient with patch( - "appointment_coverage_label.protocols.appointment_labels.Coverage.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Coverage.objects.filter" ) as mock_coverage_filter: mock_coverage_filter.return_value = mock_coverage_queryset with patch( - "appointment_coverage_label.protocols.appointment_labels.Appointment.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Appointment.objects.filter" ) as mock_appt_filter: mock_appt_filter.return_value.exclude.return_value.prefetch_related.return_value = mock_appt_queryset with patch( - "appointment_coverage_label.protocols.appointment_labels.AddAppointmentLabel" + "appointment_coverage_label.handlers.appointment_labels.AddAppointmentLabel" ) as mock_effect_class: mock_effect_instance = MagicMock() mock_applied_effect = MagicMock() mock_effect_instance.apply.return_value = mock_applied_effect mock_effect_class.return_value = mock_effect_instance - result = protocol.handle_appointment_created() + result = handler.handle_appointment_created() # Verify AddAppointmentLabel was called for both appointments assert mock_effect_class.call_count == 2 @@ -265,8 +265,8 @@ def test_handle_appointment_created_no_labels_when_has_coverage( self, monkeypatch: MonkeyPatch ) -> None: """Test that handle_appointment_created doesn't add labels when patient has coverage.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context @@ -280,28 +280,28 @@ def test_handle_appointment_created_no_labels_when_has_coverage( mock_coverage_queryset = MagicMock() mock_coverage_queryset.exists.return_value = True - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: mock_patient_get.return_value = mock_patient with patch( - "appointment_coverage_label.protocols.appointment_labels.Coverage.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Coverage.objects.filter" ) as mock_coverage_filter: mock_coverage_filter.return_value = mock_coverage_queryset - result = protocol.handle_appointment_created() + result = handler.handle_appointment_created() assert result == [] def test_handle_appointment_created_all_appointments_already_labeled( self, monkeypatch: MonkeyPatch ) -> None: """Test handle_appointment_created when all appointments already have labels.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context @@ -319,56 +319,56 @@ def test_handle_appointment_created_all_appointments_already_labeled( mock_appt_queryset = MagicMock() mock_appt_queryset.exists.return_value = False - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: mock_patient_get.return_value = mock_patient with patch( - "appointment_coverage_label.protocols.appointment_labels.Coverage.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Coverage.objects.filter" ) as mock_coverage_filter: mock_coverage_filter.return_value = mock_coverage_queryset with patch( - "appointment_coverage_label.protocols.appointment_labels.Appointment.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Appointment.objects.filter" ) as mock_appt_filter: mock_appt_filter.return_value.exclude.return_value.prefetch_related.return_value = mock_appt_queryset - result = protocol.handle_appointment_created() + result = handler.handle_appointment_created() assert result == [] def test_handle_appointment_created_patient_not_found(self, monkeypatch: MonkeyPatch) -> None: """Test handle_appointment_created when patient doesn't exist.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context mock_event = MagicMock() dummy_context = {"patient": {"id": "nonexistent-patient"}} - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: - from appointment_coverage_label.protocols.appointment_labels import Patient + from appointment_coverage_label.handlers.appointment_labels import Patient mock_patient_get.side_effect = Patient.DoesNotExist() - result = protocol.handle_appointment_created() + result = handler.handle_appointment_created() assert result == [] def test_handle_coverage_created_handles_effect_exception( self, monkeypatch: MonkeyPatch ) -> None: """Test that handle_coverage_created handles exceptions when creating effects.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context @@ -388,30 +388,30 @@ def test_handle_coverage_created_handles_effect_exception( mock_queryset.__len__.return_value = 1 mock_queryset.__iter__.return_value = iter([mock_appt]) - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: mock_patient_get.return_value = mock_patient with patch( - "appointment_coverage_label.protocols.appointment_labels.Appointment.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Appointment.objects.filter" ) as mock_filter: mock_filter.return_value.prefetch_related.return_value = mock_queryset # Mock log.error to prevent exc_info TypeError with ( - patch("appointment_coverage_label.protocols.appointment_labels.log"), + patch("appointment_coverage_label.handlers.appointment_labels.log"), patch( - "appointment_coverage_label.protocols.appointment_labels.RemoveAppointmentLabel" + "appointment_coverage_label.handlers.appointment_labels.RemoveAppointmentLabel" ) as mock_effect_class, ): # Make the effect creation raise an exception mock_effect_class.side_effect = Exception("Effect creation failed") - result = protocol.handle_coverage_created() + result = handler.handle_coverage_created() # Should handle exception gracefully and return empty list assert result == [] @@ -420,8 +420,8 @@ def test_handle_appointment_created_handles_effect_exception( self, monkeypatch: MonkeyPatch ) -> None: """Test that handle_appointment_created handles exceptions when creating effects.""" - from appointment_coverage_label.protocols.appointment_labels import ( - AppointmentLabelsProtocol, + from appointment_coverage_label.handlers.appointment_labels import ( + AppointmentLabelsHandler, ) # Mock event and context @@ -444,35 +444,35 @@ def test_handle_appointment_created_handles_effect_exception( mock_coverage_queryset = MagicMock() mock_coverage_queryset.exists.return_value = False - protocol = AppointmentLabelsProtocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + handler = AppointmentLabelsHandler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "appointment_coverage_label.protocols.appointment_labels.Patient.objects.get" + "appointment_coverage_label.handlers.appointment_labels.Patient.objects.get" ) as mock_patient_get: mock_patient_get.return_value = mock_patient with patch( - "appointment_coverage_label.protocols.appointment_labels.Coverage.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Coverage.objects.filter" ) as mock_coverage_filter: mock_coverage_filter.return_value = mock_coverage_queryset with patch( - "appointment_coverage_label.protocols.appointment_labels.Appointment.objects.filter" + "appointment_coverage_label.handlers.appointment_labels.Appointment.objects.filter" ) as mock_appt_filter: mock_appt_filter.return_value.exclude.return_value.prefetch_related.return_value = mock_appt_queryset # Mock log.error to prevent exc_info TypeError with ( - patch("appointment_coverage_label.protocols.appointment_labels.log"), + patch("appointment_coverage_label.handlers.appointment_labels.log"), patch( - "appointment_coverage_label.protocols.appointment_labels.AddAppointmentLabel" + "appointment_coverage_label.handlers.appointment_labels.AddAppointmentLabel" ) as mock_effect_class, ): # Make the effect creation raise an exception mock_effect_class.side_effect = Exception("Effect creation failed") - result = protocol.handle_appointment_created() + result = handler.handle_appointment_created() # Should handle exception gracefully and return empty list assert result == [] diff --git a/example-plugins/appointment_state_field/appointment_state_field/CANVAS_MANIFEST.json b/example-plugins/appointment_state_field/appointment_state_field/CANVAS_MANIFEST.json index fea23bb96..1ce3c4a49 100644 --- a/example-plugins/appointment_state_field/appointment_state_field/CANVAS_MANIFEST.json +++ b/example-plugins/appointment_state_field/appointment_state_field/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "appointment_state_field", "description": "Adds a US state selection field to appointment forms and filters available providers based on their licensing in the selected state", "components": { - "protocols": [ + "handlers": [ { "class": "appointment_state_field.handlers.form:AppointmentFormFields", "description": "Adds a US state dropdown field to appointment forms" diff --git a/example-plugins/aws_s3/aws_manip/CANVAS_MANIFEST.json b/example-plugins/aws_s3/aws_manip/CANVAS_MANIFEST.json index bfb4fa9ec..57c732326 100644 --- a/example-plugins/aws_s3/aws_manip/CANVAS_MANIFEST.json +++ b/example-plugins/aws_s3/aws_manip/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "aws_manip", "description": "use AWS S3 to store, retrieve and delete documents", "components": { - "protocols": [ + "handlers": [ { "class": "aws_manip.handlers.aws_manip:AwsManip", "description": "AWS extractor based on AWS S3" diff --git a/example-plugins/charting_api_examples/charting_api_examples/CANVAS_MANIFEST.json b/example-plugins/charting_api_examples/charting_api_examples/CANVAS_MANIFEST.json index fe2004f3c..34b42e9ea 100644 --- a/example-plugins/charting_api_examples/charting_api_examples/CANVAS_MANIFEST.json +++ b/example-plugins/charting_api_examples/charting_api_examples/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "charting_api_examples", "description": "A series of custom API routes that showcase SDK charting functionality", "components": { - "protocols": [ + "handlers": [ { "class": "charting_api_examples.routes.notes:NoteAPI", "description": "Endpoints that showcase interactions with notes." diff --git a/example-plugins/coverage_metadata_sync/coverage_metadata_sync/CANVAS_MANIFEST.json b/example-plugins/coverage_metadata_sync/coverage_metadata_sync/CANVAS_MANIFEST.json index 84c967533..92120fd8d 100644 --- a/example-plugins/coverage_metadata_sync/coverage_metadata_sync/CANVAS_MANIFEST.json +++ b/example-plugins/coverage_metadata_sync/coverage_metadata_sync/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "coverage_metadata_sync", "description": "Automatically synchronizes a patient's 'Coverage status' metadata field based on appointment label changes. Updates the metadata to 'Missing' when the MISSING_COVERAGE label is added, and to 'Active' when the label is removed.", "components": { - "protocols": [ + "handlers": [ { - "class": "coverage_metadata_sync.protocols.metadata_sync:CoverageStatusSyncProtocol", + "class": "coverage_metadata_sync.handlers.metadata_sync:CoverageStatusSyncHandler", "description": "Listens for MISSING_COVERAGE label events on appointments and synchronizes the patient's 'coverage_status' metadata field accordingly.", "data_access": { "event": "read", diff --git a/example-plugins/coverage_metadata_sync/coverage_metadata_sync/README.md b/example-plugins/coverage_metadata_sync/coverage_metadata_sync/README.md index b973fb9cb..7ff110e27 100644 --- a/example-plugins/coverage_metadata_sync/coverage_metadata_sync/README.md +++ b/example-plugins/coverage_metadata_sync/coverage_metadata_sync/README.md @@ -247,7 +247,7 @@ coverage_metadata_sync/ ### Key Components -- **CoverageStatusSyncProtocol** - Main protocol class handling label events +- **CoverageStatusSyncHandler** - Main protocol class handling label events - **compute()** - Event routing and metadata update logic - **MONITORED_LABEL** - Constant defining which label triggers updates ("MISSING_COVERAGE") - **METADATA_KEY** - Constant defining metadata field name ("coverage_status") diff --git a/example-plugins/coverage_metadata_sync/coverage_metadata_sync/protocols/__init__.py b/example-plugins/coverage_metadata_sync/coverage_metadata_sync/handlers/__init__.py similarity index 100% rename from example-plugins/coverage_metadata_sync/coverage_metadata_sync/protocols/__init__.py rename to example-plugins/coverage_metadata_sync/coverage_metadata_sync/handlers/__init__.py diff --git a/example-plugins/coverage_metadata_sync/coverage_metadata_sync/protocols/metadata_sync.py b/example-plugins/coverage_metadata_sync/coverage_metadata_sync/handlers/metadata_sync.py similarity index 93% rename from example-plugins/coverage_metadata_sync/coverage_metadata_sync/protocols/metadata_sync.py rename to example-plugins/coverage_metadata_sync/coverage_metadata_sync/handlers/metadata_sync.py index 3f331d4b0..bdc2af7c7 100644 --- a/example-plugins/coverage_metadata_sync/coverage_metadata_sync/protocols/metadata_sync.py +++ b/example-plugins/coverage_metadata_sync/coverage_metadata_sync/handlers/metadata_sync.py @@ -1,7 +1,7 @@ from canvas_sdk.effects import Effect from canvas_sdk.effects.patient_metadata.base import PatientMetadata from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from logger import log # The specific label and metadata key we are working with. @@ -9,11 +9,11 @@ METADATA_KEY = "coverage_status" -class CoverageStatusSyncProtocol(BaseProtocol): +class CoverageStatusSyncHandler(BaseHandler): """ Synchronizes patient metadata based on appointment label changes. - This protocol listens for appointment label events and updates a patient's + This handler listens for appointment label events and updates a patient's 'coverage_status' metadata field when the 'MISSING_COVERAGE' label is added or removed: - When MISSING_COVERAGE label is ADDED → sets coverage_status to "Missing" @@ -22,7 +22,7 @@ class CoverageStatusSyncProtocol(BaseProtocol): This provides a centralized metadata field that reflects the patient's current insurance coverage status, making it easy to query and report on coverage gaps. - The protocol is designed to work seamlessly with the appointment_coverage_label plugin, + The handler is designed to work seamlessly with the appointment_coverage_label plugin, which manages the addition and removal of the MISSING_COVERAGE label based on actual insurance coverage records. """ @@ -91,7 +91,7 @@ def compute(self) -> list[Effect]: else: log.warning( f"Received unexpected event type '{self.event.type}' in " - "CoverageStatusSyncProtocol. This event type is in RESPONDS_TO but " + "CoverageStatusSyncHandler. This event type is in RESPONDS_TO but " "has no handler logic defined." ) return [] diff --git a/example-plugins/coverage_metadata_sync/tests/test_metadata_sync.py b/example-plugins/coverage_metadata_sync/tests/test_metadata_sync.py index a985507c6..deae3f0c9 100644 --- a/example-plugins/coverage_metadata_sync/tests/test_metadata_sync.py +++ b/example-plugins/coverage_metadata_sync/tests/test_metadata_sync.py @@ -1,39 +1,39 @@ from unittest.mock import MagicMock, patch -from coverage_metadata_sync.protocols.metadata_sync import CoverageStatusSyncProtocol +from coverage_metadata_sync.handlers.metadata_sync import CoverageStatusSyncHandler from pytest import MonkeyPatch from canvas_sdk.events import EventType -class TestCoverageStatusSyncProtocol: - """Tests for the CoverageStatusSyncProtocol.""" +class TestCoverageStatusSyncHandler: + """Tests for the CoverageStatusSyncHandler.""" def test_compute_label_added_missing_coverage(self, monkeypatch: MonkeyPatch) -> None: """Test that adding MISSING_COVERAGE label sets coverage_status to 'Missing'.""" - # Create protocol instance - protocol = CoverageStatusSyncProtocol(event=MagicMock()) - protocol.event.type = EventType.APPOINTMENT_LABEL_ADDED + # Create handler instance + handler = CoverageStatusSyncHandler(event=MagicMock()) + handler.event.type = EventType.APPOINTMENT_LABEL_ADDED # Set up context dummy_context = { "patient": {"id": "patient-123"}, "label": "MISSING_COVERAGE", } - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock PatientMetadata with patch( - "coverage_metadata_sync.protocols.metadata_sync.PatientMetadata" + "coverage_metadata_sync.handlers.metadata_sync.PatientMetadata" ) as mock_metadata_class: mock_metadata_instance = MagicMock() mock_upsert_effect = MagicMock() mock_metadata_instance.upsert.return_value = mock_upsert_effect mock_metadata_class.return_value = mock_metadata_instance - with patch("coverage_metadata_sync.protocols.metadata_sync.log"): + with patch("coverage_metadata_sync.handlers.metadata_sync.log"): # Call compute - effects = protocol.compute() + effects = handler.compute() # Verify PatientMetadata was created correctly mock_metadata_class.assert_called_once_with( @@ -49,29 +49,29 @@ def test_compute_label_added_missing_coverage(self, monkeypatch: MonkeyPatch) -> def test_compute_label_removed_missing_coverage(self, monkeypatch: MonkeyPatch) -> None: """Test that removing MISSING_COVERAGE label sets coverage_status to 'Active'.""" - # Create protocol instance - protocol = CoverageStatusSyncProtocol(event=MagicMock()) - protocol.event.type = EventType.APPOINTMENT_LABEL_REMOVED + # Create handler instance + handler = CoverageStatusSyncHandler(event=MagicMock()) + handler.event.type = EventType.APPOINTMENT_LABEL_REMOVED # Set up context dummy_context = { "patient": {"id": "patient-123"}, "label": "MISSING_COVERAGE", } - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock PatientMetadata with patch( - "coverage_metadata_sync.protocols.metadata_sync.PatientMetadata" + "coverage_metadata_sync.handlers.metadata_sync.PatientMetadata" ) as mock_metadata_class: mock_metadata_instance = MagicMock() mock_upsert_effect = MagicMock() mock_metadata_instance.upsert.return_value = mock_upsert_effect mock_metadata_class.return_value = mock_metadata_instance - with patch("coverage_metadata_sync.protocols.metadata_sync.log"): + with patch("coverage_metadata_sync.handlers.metadata_sync.log"): # Call compute - effects = protocol.compute() + effects = handler.compute() # Verify upsert was called with "Active" mock_metadata_instance.upsert.assert_called_once_with(value="Active") @@ -82,107 +82,107 @@ def test_compute_label_removed_missing_coverage(self, monkeypatch: MonkeyPatch) def test_compute_ignores_other_labels(self, monkeypatch: MonkeyPatch) -> None: """Test that events for other labels are ignored.""" - # Create protocol instance - protocol = CoverageStatusSyncProtocol(event=MagicMock()) - protocol.event.type = EventType.APPOINTMENT_LABEL_ADDED + # Create handler instance + handler = CoverageStatusSyncHandler(event=MagicMock()) + handler.event.type = EventType.APPOINTMENT_LABEL_ADDED # Set up context with a different label dummy_context = { "patient": {"id": "patient-123"}, "label": "SOME_OTHER_LABEL", } - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) - with patch("coverage_metadata_sync.protocols.metadata_sync.log"): + with patch("coverage_metadata_sync.handlers.metadata_sync.log"): # Call compute - effects = protocol.compute() + effects = handler.compute() # Should return empty list assert effects == [] def test_compute_no_patient_id(self, monkeypatch: MonkeyPatch) -> None: """Test that missing patient ID returns empty list.""" - # Create protocol instance - protocol = CoverageStatusSyncProtocol(event=MagicMock()) - protocol.event.type = EventType.APPOINTMENT_LABEL_ADDED + # Create handler instance + handler = CoverageStatusSyncHandler(event=MagicMock()) + handler.event.type = EventType.APPOINTMENT_LABEL_ADDED # Set up context without patient ID dummy_context = { "patient": {}, "label": "MISSING_COVERAGE", } - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) - with patch("coverage_metadata_sync.protocols.metadata_sync.log"): + with patch("coverage_metadata_sync.handlers.metadata_sync.log"): # Call compute - effects = protocol.compute() + effects = handler.compute() # Should return empty list assert effects == [] def test_compute_no_label(self, monkeypatch: MonkeyPatch) -> None: """Test that missing label returns empty list.""" - # Create protocol instance - protocol = CoverageStatusSyncProtocol(event=MagicMock()) - protocol.event.type = EventType.APPOINTMENT_LABEL_ADDED + # Create handler instance + handler = CoverageStatusSyncHandler(event=MagicMock()) + handler.event.type = EventType.APPOINTMENT_LABEL_ADDED # Set up context without label dummy_context = { "patient": {"id": "patient-123"}, } - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) - with patch("coverage_metadata_sync.protocols.metadata_sync.log"): + with patch("coverage_metadata_sync.handlers.metadata_sync.log"): # Call compute - effects = protocol.compute() + effects = handler.compute() # Should return empty list assert effects == [] def test_compute_handles_exception(self, monkeypatch: MonkeyPatch) -> None: """Test that exceptions during metadata creation are handled gracefully.""" - # Create protocol instance - protocol = CoverageStatusSyncProtocol(event=MagicMock()) - protocol.event.type = EventType.APPOINTMENT_LABEL_ADDED + # Create handler instance + handler = CoverageStatusSyncHandler(event=MagicMock()) + handler.event.type = EventType.APPOINTMENT_LABEL_ADDED # Set up context dummy_context = { "patient": {"id": "patient-123"}, "label": "MISSING_COVERAGE", } - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock PatientMetadata to raise exception with patch( - "coverage_metadata_sync.protocols.metadata_sync.PatientMetadata" + "coverage_metadata_sync.handlers.metadata_sync.PatientMetadata" ) as mock_metadata_class: mock_metadata_class.side_effect = Exception("Test error") - with patch("coverage_metadata_sync.protocols.metadata_sync.log"): + with patch("coverage_metadata_sync.handlers.metadata_sync.log"): # Call compute - effects = protocol.compute() + effects = handler.compute() # Should return empty list when exception occurs assert effects == [] def test_compute_with_unexpected_event_type(self, monkeypatch: MonkeyPatch) -> None: """Test that unexpected event types are handled gracefully.""" - # Create protocol instance - protocol = CoverageStatusSyncProtocol(event=MagicMock()) + # Create handler instance + handler = CoverageStatusSyncHandler(event=MagicMock()) # Use an event type that's not APPOINTMENT_LABEL_ADDED or APPOINTMENT_LABEL_REMOVED # This simulates the else branch in the code (lines 92-97) - protocol.event.type = EventType.COVERAGE_CREATED # Not a label event type + handler.event.type = EventType.COVERAGE_CREATED # Not a label event type # Set up context with MISSING_COVERAGE label and valid patient dummy_context = { "patient": {"id": "patient-123"}, "label": "MISSING_COVERAGE", } - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) - with patch("coverage_metadata_sync.protocols.metadata_sync.log"): + with patch("coverage_metadata_sync.handlers.metadata_sync.log"): # Call compute - effects = protocol.compute() + effects = handler.compute() # Should return empty list for unexpected event type assert effects == [] diff --git a/example-plugins/example_chart_app/example_chart_app/CANVAS_MANIFEST.json b/example-plugins/example_chart_app/example_chart_app/CANVAS_MANIFEST.json index be3417978..9c890379d 100644 --- a/example-plugins/example_chart_app/example_chart_app/CANVAS_MANIFEST.json +++ b/example-plugins/example_chart_app/example_chart_app/CANVAS_MANIFEST.json @@ -5,7 +5,7 @@ "description": "Used to test various canvas plugins functionality", "url_permissions": [], "components": { - "protocols": [ + "handlers": [ { "class": "example_chart_app.applications.my_application:MyApi", "description": "Provides api for the application", diff --git a/example-plugins/example_patient_portal_page/example_patient_portal_page/CANVAS_MANIFEST.json b/example-plugins/example_patient_portal_page/example_patient_portal_page/CANVAS_MANIFEST.json index b86d93a78..f58d1bec9 100644 --- a/example-plugins/example_patient_portal_page/example_patient_portal_page/CANVAS_MANIFEST.json +++ b/example-plugins/example_patient_portal_page/example_patient_portal_page/CANVAS_MANIFEST.json @@ -19,7 +19,7 @@ "icon": "assets/icon.png" } ], - "protocols": [ + "handlers": [ { "class": "example_patient_portal_page.handlers.my_web_app:MyWebApp", "description": "Serves the application" diff --git a/example-plugins/example_patient_sync/example_patient_sync/CANVAS_MANIFEST.json b/example-plugins/example_patient_sync/example_patient_sync/CANVAS_MANIFEST.json index 44f64145f..ffe6641a3 100644 --- a/example-plugins/example_patient_sync/example_patient_sync/CANVAS_MANIFEST.json +++ b/example-plugins/example_patient_sync/example_patient_sync/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "example_patient_sync", "description": "Example bidirectional patient synchronization between Canvas and a 3rd party system", "components": { - "protocols": [ + "handlers": [ { "class": "example_patient_sync.handlers.patient_sync:PatientSync", "description": "Create or update patients in an external system based on Canvas events" diff --git a/example-plugins/example_provider_companion_app/example_provider_companion_app/CANVAS_MANIFEST.json b/example-plugins/example_provider_companion_app/example_provider_companion_app/CANVAS_MANIFEST.json index c968c7092..22101b098 100644 --- a/example-plugins/example_provider_companion_app/example_provider_companion_app/CANVAS_MANIFEST.json +++ b/example-plugins/example_provider_companion_app/example_provider_companion_app/CANVAS_MANIFEST.json @@ -19,7 +19,7 @@ "icon": "assets/doctor.png" } ], - "protocols": [ + "handlers": [ { "class": "example_provider_companion_app.handlers.my_web_app:MyWebApp", "description": "Serves the application", diff --git a/example-plugins/example_provider_page/example_provider_page/CANVAS_MANIFEST.json b/example-plugins/example_provider_page/example_provider_page/CANVAS_MANIFEST.json index a3531a5ba..d4180822f 100644 --- a/example-plugins/example_provider_page/example_provider_page/CANVAS_MANIFEST.json +++ b/example-plugins/example_provider_page/example_provider_page/CANVAS_MANIFEST.json @@ -19,7 +19,7 @@ "icon": "assets/python-logo.png" } ], - "protocols": [ + "handlers": [ { "class": "example_provider_page.handlers.my_web_app:MyWebApp", "description": "Serves the application", diff --git a/example-plugins/extend_ai_pdf/pdf_manip/CANVAS_MANIFEST.json b/example-plugins/extend_ai_pdf/pdf_manip/CANVAS_MANIFEST.json index 5624f7293..e5a319465 100644 --- a/example-plugins/extend_ai_pdf/pdf_manip/CANVAS_MANIFEST.json +++ b/example-plugins/extend_ai_pdf/pdf_manip/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "pdf_manip", "description": "use extent.ai to extract information from a PDF document", "components": { - "protocols": [ + "handlers": [ { "class": "pdf_manip.handlers.pdf_manip:PdfManip", "description": "PDF extractor based on extent.ai" diff --git a/example-plugins/llm/llm_manip/CANVAS_MANIFEST.json b/example-plugins/llm/llm_manip/CANVAS_MANIFEST.json index 013c45304..5a85d6d5e 100644 --- a/example-plugins/llm/llm_manip/CANVAS_MANIFEST.json +++ b/example-plugins/llm/llm_manip/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "llm_manip", "description": "use LLM to interact with the user", "components": { - "protocols": [ + "handlers": [ { "class": "llm_manip.handlers.llm_manip:LlmManip", "description": "LLM communication wrapper" diff --git a/example-plugins/my_first_plugin/my_first_plugin/CANVAS_MANIFEST.json b/example-plugins/my_first_plugin/my_first_plugin/CANVAS_MANIFEST.json index 1434929d3..9bf70dc5d 100644 --- a/example-plugins/my_first_plugin/my_first_plugin/CANVAS_MANIFEST.json +++ b/example-plugins/my_first_plugin/my_first_plugin/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "my_first_plugin", "description": "A plugin to interact with a Canvas Instance", "components": { - "protocols": [ + "handlers": [ { - "class": "my_first_plugin.protocols.protocol:Protocol", + "class": "my_first_plugin.handlers.handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "ASSESS_COMMAND__CONDITION_SELECTED", diff --git a/example-plugins/my_first_plugin/my_first_plugin/protocols/__init__.py b/example-plugins/my_first_plugin/my_first_plugin/handlers/__init__.py similarity index 100% rename from example-plugins/my_first_plugin/my_first_plugin/protocols/__init__.py rename to example-plugins/my_first_plugin/my_first_plugin/handlers/__init__.py diff --git a/example-plugins/my_first_plugin/my_first_plugin/protocols/protocol.py b/example-plugins/my_first_plugin/my_first_plugin/handlers/handler.py similarity index 80% rename from example-plugins/my_first_plugin/my_first_plugin/protocols/protocol.py rename to example-plugins/my_first_plugin/my_first_plugin/handlers/handler.py index 4def686ba..e404a9742 100644 --- a/example-plugins/my_first_plugin/my_first_plugin/protocols/protocol.py +++ b/example-plugins/my_first_plugin/my_first_plugin/handlers/handler.py @@ -2,12 +2,12 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from logger import log -class Protocol(BaseProtocol): - """You should put a helpful description of this protocol's behavior here.""" +class Handler(BaseHandler): + """You should put a helpful description of this handler's behavior here.""" RESPONDS_TO = EventType.Name(EventType.ASSESS_COMMAND__CONDITION_SELECTED) diff --git a/example-plugins/my_first_plugin/tests/test_protocol.py b/example-plugins/my_first_plugin/tests/test_protocol.py index 4476319a8..b6dab0e2e 100644 --- a/example-plugins/my_first_plugin/tests/test_protocol.py +++ b/example-plugins/my_first_plugin/tests/test_protocol.py @@ -8,39 +8,39 @@ def test_import_protocol() -> None: - """Test that Protocol can be imported without errors.""" - from my_first_plugin.protocols.protocol import Protocol + """Test that Handler can be imported without errors.""" + from my_first_plugin.handlers.handler import Handler # Verify the class exists and has expected attributes - assert Protocol is not None - assert hasattr(Protocol, "RESPONDS_TO") - assert hasattr(Protocol, "compute") - assert hasattr(Protocol, "NARRATIVE_STRING") + assert Handler is not None + assert hasattr(Handler, "RESPONDS_TO") + assert hasattr(Handler, "compute") + assert hasattr(Handler, "NARRATIVE_STRING") def test_protocol_configuration() -> None: - """Test that Protocol has correct configuration.""" - from my_first_plugin.protocols.protocol import Protocol + """Test that Handler has correct configuration.""" + from my_first_plugin.handlers.handler import Handler # Verify configuration - assert EventType.Name(EventType.ASSESS_COMMAND__CONDITION_SELECTED) == Protocol.RESPONDS_TO - assert Protocol.NARRATIVE_STRING == "zebra" + assert EventType.Name(EventType.ASSESS_COMMAND__CONDITION_SELECTED) == Handler.RESPONDS_TO + assert Handler.NARRATIVE_STRING == "zebra" def test_compute_creates_log_effect() -> None: """Test that compute method creates a LOG effect with correct payload.""" - from my_first_plugin.protocols.protocol import Protocol + from my_first_plugin.handlers.handler import Handler # Create mock event mock_event = Mock() mock_event.context = {"note": {"uuid": "test-note-uuid-123"}} - # Create protocol instance - protocol = Protocol(event=mock_event) + # Create handler instance + handler = Handler(event=mock_event) # Mock the logger to prevent actual logging - with patch("my_first_plugin.protocols.protocol.log"): - result = protocol.compute() + with patch("my_first_plugin.handlers.handler.log"): + result = handler.compute() # Verify result is a list with one effect assert len(result) == 1 @@ -59,18 +59,18 @@ def test_compute_creates_log_effect() -> None: def test_compute_logs_narrative_string() -> None: """Test that compute method logs the narrative string.""" - from my_first_plugin.protocols.protocol import Protocol + from my_first_plugin.handlers.handler import Handler # Create mock event mock_event = Mock() mock_event.context = {"note": {"uuid": "another-uuid"}} - # Create protocol instance - protocol = Protocol(event=mock_event) + # Create handler instance + handler = Handler(event=mock_event) # Mock the logger and verify it's called with NARRATIVE_STRING - with patch("my_first_plugin.protocols.protocol.log") as mock_log: - protocol.compute() + with patch("my_first_plugin.handlers.handler.log") as mock_log: + handler.compute() # Verify log.info was called with "zebra" mock_log.info.assert_called_once_with("zebra") diff --git a/example-plugins/note_management_app/note_management_app/CANVAS_MANIFEST.json b/example-plugins/note_management_app/note_management_app/CANVAS_MANIFEST.json index 5cc2fba42..845a284a2 100644 --- a/example-plugins/note_management_app/note_management_app/CANVAS_MANIFEST.json +++ b/example-plugins/note_management_app/note_management_app/CANVAS_MANIFEST.json @@ -13,7 +13,7 @@ "icon": "assets/note_icon.png" } ], - "protocols": [ + "handlers": [ { "class": "note_management_app.handlers.api:AppApi", "description": "SimpleAPI handler for serving the note management application." diff --git a/example-plugins/patient_app_schedule/patient_app_schedule/CANVAS_MANIFEST.json b/example-plugins/patient_app_schedule/patient_app_schedule/CANVAS_MANIFEST.json index e902f70d4..c19d5a710 100644 --- a/example-plugins/patient_app_schedule/patient_app_schedule/CANVAS_MANIFEST.json +++ b/example-plugins/patient_app_schedule/patient_app_schedule/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "patient_app_schedule", "description": "protocols for filtering providers based on care team membership and locations based on appointment history", "components": { - "protocols": [ + "handlers": [ { - "class": "patient_app_schedule.protocols.filters:Providers", + "class": "patient_app_schedule.handlers.filters:Providers", "description": "filter providers based on care team membership", "data_access": { "event": "", @@ -15,7 +15,7 @@ } }, { - "class": "patient_app_schedule.protocols.filters:Locations", + "class": "patient_app_schedule.handlers.filters:Locations", "description": "filter locations based on appointment history", "data_access": { "event": "", diff --git a/example-plugins/patient_app_schedule/patient_app_schedule/protocols/__init__.py b/example-plugins/patient_app_schedule/patient_app_schedule/handlers/__init__.py similarity index 100% rename from example-plugins/patient_app_schedule/patient_app_schedule/protocols/__init__.py rename to example-plugins/patient_app_schedule/patient_app_schedule/handlers/__init__.py diff --git a/example-plugins/patient_app_schedule/patient_app_schedule/protocols/filters.py b/example-plugins/patient_app_schedule/patient_app_schedule/handlers/filters.py similarity index 100% rename from example-plugins/patient_app_schedule/patient_app_schedule/protocols/filters.py rename to example-plugins/patient_app_schedule/patient_app_schedule/handlers/filters.py diff --git a/example-plugins/patient_portal_plugin/patient_portal_plugin/CANVAS_MANIFEST.json b/example-plugins/patient_portal_plugin/patient_portal_plugin/CANVAS_MANIFEST.json index 0c994b532..86ebc1ae9 100644 --- a/example-plugins/patient_portal_plugin/patient_portal_plugin/CANVAS_MANIFEST.json +++ b/example-plugins/patient_portal_plugin/patient_portal_plugin/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "patient_portal_plugin", "description": "Patient Portal Plugin for Canvas", "components": { - "protocols": [ + "handlers": [ { "class": "patient_portal_plugin.handlers.patient_portal_handler:PatientPortalHandler", "description": "The handler that listens for the patient portal `PATIENT_PORTAL__WIDGET_CONFIGURATION` and responds with the patient portal widgets", diff --git a/example-plugins/patient_portal_search_appointments_slots_plugin/patient_portal_search_appointments_slots_plugin/CANVAS_MANIFEST.json b/example-plugins/patient_portal_search_appointments_slots_plugin/patient_portal_search_appointments_slots_plugin/CANVAS_MANIFEST.json index f4907df97..8f4a3e7e8 100644 --- a/example-plugins/patient_portal_search_appointments_slots_plugin/patient_portal_search_appointments_slots_plugin/CANVAS_MANIFEST.json +++ b/example-plugins/patient_portal_search_appointments_slots_plugin/patient_portal_search_appointments_slots_plugin/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "patient_portal_search_appointments_slots_plugin", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { "class": "patient_portal_search_appointments_slots_plugin.handlers.search_appointments_slots_handler:SearchAppointmentsSlotsHandler", "description": "", diff --git a/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/CANVAS_MANIFEST.json b/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/CANVAS_MANIFEST.json index 2b741ed87..84f40e8e9 100644 --- a/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/CANVAS_MANIFEST.json +++ b/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/CANVAS_MANIFEST.json @@ -4,13 +4,13 @@ "name": "patient_summary_chart_groups", "description": "A plugin that groups Psychiatry conditions and medications in the patient summary chart.", "components": { - "protocols": [ + "handlers": [ { - "class": "patient_summary_chart_groups.protocols.my_protocol:Conditions", + "class": "patient_summary_chart_groups.handlers.my_protocol:Conditions", "description": "A protocol that groups Psychiatry conditions" }, { - "class": "patient_summary_chart_groups.protocols.my_protocol:Medications", + "class": "patient_summary_chart_groups.handlers.my_protocol:Medications", "description": "A protocol that groups Psychiatry medications" } ], diff --git a/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/protocols/__init__.py b/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/handlers/__init__.py similarity index 100% rename from example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/protocols/__init__.py rename to example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/handlers/__init__.py diff --git a/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/protocols/my_protocol.py b/example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/handlers/my_protocol.py similarity index 100% rename from example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/protocols/my_protocol.py rename to example-plugins/patient_summary_chart_groups/patient_summary_chart_groups/handlers/my_protocol.py diff --git a/example-plugins/patient_summary_chart_groups/tests/test_my_protocol.py b/example-plugins/patient_summary_chart_groups/tests/test_my_protocol.py index ed28df7bd..b04808300 100644 --- a/example-plugins/patient_summary_chart_groups/tests/test_my_protocol.py +++ b/example-plugins/patient_summary_chart_groups/tests/test_my_protocol.py @@ -8,7 +8,7 @@ from unittest.mock import Mock import pytest -from patient_summary_chart_groups.protocols.my_protocol import Conditions, Medications +from patient_summary_chart_groups.handlers.my_protocol import Conditions, Medications from canvas_sdk.commands.constants import CodeSystems from canvas_sdk.events import EventType diff --git a/example-plugins/plugins_smoke_test/plugins_smoke_test/CANVAS_MANIFEST.json b/example-plugins/plugins_smoke_test/plugins_smoke_test/CANVAS_MANIFEST.json index cb5eda873..bc44f3187 100644 --- a/example-plugins/plugins_smoke_test/plugins_smoke_test/CANVAS_MANIFEST.json +++ b/example-plugins/plugins_smoke_test/plugins_smoke_test/CANVAS_MANIFEST.json @@ -10,7 +10,7 @@ } ], "components": { - "protocols": [ + "handlers": [ { "class": "plugins_smoke_test.applications.my_application:SmokeTestApi", "description": "Provides api for the application", diff --git a/example-plugins/preact_hello_world/preact_hello_world/CANVAS_MANIFEST.json b/example-plugins/preact_hello_world/preact_hello_world/CANVAS_MANIFEST.json index c73491925..e703f04c8 100644 --- a/example-plugins/preact_hello_world/preact_hello_world/CANVAS_MANIFEST.json +++ b/example-plugins/preact_hello_world/preact_hello_world/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "preact_hello_world", "description": "A Hello World demo showing Vite + Preact integration with Canvas plugins", "components": { - "protocols": [ + "handlers": [ { - "class": "preact_hello_world.protocols.counter_button:CounterButton", + "class": "preact_hello_world.handlers.counter_button:CounterButton", "description": "ActionButton that launches a Preact counter demo in the right chart pane" } ], diff --git a/example-plugins/preact_hello_world/preact_hello_world/protocols/__init__.py b/example-plugins/preact_hello_world/preact_hello_world/handlers/__init__.py similarity index 100% rename from example-plugins/preact_hello_world/preact_hello_world/protocols/__init__.py rename to example-plugins/preact_hello_world/preact_hello_world/handlers/__init__.py diff --git a/example-plugins/preact_hello_world/preact_hello_world/protocols/counter_button.py b/example-plugins/preact_hello_world/preact_hello_world/handlers/counter_button.py similarity index 100% rename from example-plugins/preact_hello_world/preact_hello_world/protocols/counter_button.py rename to example-plugins/preact_hello_world/preact_hello_world/handlers/counter_button.py diff --git a/example-plugins/preact_hello_world/tests/protocols/__init__.py b/example-plugins/preact_hello_world/tests/handlers/__init__.py similarity index 100% rename from example-plugins/preact_hello_world/tests/protocols/__init__.py rename to example-plugins/preact_hello_world/tests/handlers/__init__.py diff --git a/example-plugins/preact_hello_world/tests/protocols/test_counter_button.py b/example-plugins/preact_hello_world/tests/handlers/test_counter_button.py similarity index 95% rename from example-plugins/preact_hello_world/tests/protocols/test_counter_button.py rename to example-plugins/preact_hello_world/tests/handlers/test_counter_button.py index 83fe5a01e..0f8b58827 100644 --- a/example-plugins/preact_hello_world/tests/protocols/test_counter_button.py +++ b/example-plugins/preact_hello_world/tests/handlers/test_counter_button.py @@ -2,7 +2,7 @@ from pathlib import Path from unittest.mock import MagicMock, patch -from preact_hello_world.protocols.counter_button import CounterButton +from preact_hello_world.handlers.counter_button import CounterButton from canvas_sdk.handlers.action_button import ActionButton @@ -27,7 +27,7 @@ def test_button_location(self) -> None: assert CounterButton.BUTTON_LOCATION == ActionButton.ButtonLocation.NOTE_HEADER -@patch("preact_hello_world.protocols.counter_button.render_to_string", return_value=COUNTER_HTML) +@patch("preact_hello_world.handlers.counter_button.render_to_string", return_value=COUNTER_HTML) class TestCounterButtonHandle: """Tests for handle() method.""" diff --git a/example-plugins/prescribe_command_test/prescribe_command_test/protocols/buttonone.py b/example-plugins/prescribe_command_test/prescribe_command_test/handlers/buttonone.py similarity index 100% rename from example-plugins/prescribe_command_test/prescribe_command_test/protocols/buttonone.py rename to example-plugins/prescribe_command_test/prescribe_command_test/handlers/buttonone.py diff --git a/example-plugins/protocols/protocols/my_protocol.py b/example-plugins/protocols/protocols/my_protocol.py index 524fc482c..f834257da 100644 --- a/example-plugins/protocols/protocols/my_protocol.py +++ b/example-plugins/protocols/protocols/my_protocol.py @@ -12,7 +12,7 @@ from logger import log -# Inherit from BaseProtocol to properly get registered for events +# Inherit from BaseHandler to properly get registered for events class Handle(BaseHandler): """Handler for prescribe command available actions events.""" diff --git a/example-plugins/recurring_appointments/recurring_appointments/CANVAS_MANIFEST.json b/example-plugins/recurring_appointments/recurring_appointments/CANVAS_MANIFEST.json index 2ca913c20..4244c51ec 100644 --- a/example-plugins/recurring_appointments/recurring_appointments/CANVAS_MANIFEST.json +++ b/example-plugins/recurring_appointments/recurring_appointments/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "recurring_appointments", "description": "Adds configurable recurring appointment functionality with customizable intervals, recurrence types (days/weeks/months), and flexible end conditions that automatically creates follow-up appointments", "components": { - "protocols": [ + "handlers": [ { "class": "recurring_appointments.handlers.recurrence:AppointmentRecurrence", "description": "Automatically creates recurring appointments based on configurable interval, recurrence type, and end condition metadata when an appointment is created" diff --git a/example-plugins/send_all_prescriptions/send_all_prescriptions/CANVAS_MANIFEST.json b/example-plugins/send_all_prescriptions/send_all_prescriptions/CANVAS_MANIFEST.json index 3bdf31448..4e893640d 100644 --- a/example-plugins/send_all_prescriptions/send_all_prescriptions/CANVAS_MANIFEST.json +++ b/example-plugins/send_all_prescriptions/send_all_prescriptions/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "send_all_prescriptions", "description": "Adds a 'Send Prescriptions' button to note footers that allows providers to send all committed prescriptions in a note with a single click, streamlining the prescription workflow.", "components": { - "protocols": [ + "handlers": [ { "class": "send_all_prescriptions.handlers.handler:SendPrescriptionButtonHandler", "description": "Action button that sends all committed prescriptions in the current note.", diff --git a/example-plugins/sendgrid_email/sendgrid_email/CANVAS_MANIFEST.json b/example-plugins/sendgrid_email/sendgrid_email/CANVAS_MANIFEST.json index 219208c9f..90be55c1c 100644 --- a/example-plugins/sendgrid_email/sendgrid_email/CANVAS_MANIFEST.json +++ b/example-plugins/sendgrid_email/sendgrid_email/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "email_sender", "description": "use Sendgrid to send emails, retrieve sent emails, manage inbound and outbound webhooks", "components": { - "protocols": [ + "handlers": [ { "class": "email_sender.handlers.email_manip:EmailManip", "description": "Emails with Sendgrid" diff --git a/example-plugins/simple_note_button_plugin/simple_note_button_plugin/CANVAS_MANIFEST.json b/example-plugins/simple_note_button_plugin/simple_note_button_plugin/CANVAS_MANIFEST.json index 290cc6092..4006b502b 100644 --- a/example-plugins/simple_note_button_plugin/simple_note_button_plugin/CANVAS_MANIFEST.json +++ b/example-plugins/simple_note_button_plugin/simple_note_button_plugin/CANVAS_MANIFEST.json @@ -5,7 +5,7 @@ "description": "A simple plugin that adds a hello world button to note headers", "components": { "commands": [], - "protocols": [ + "handlers": [ { "class": "simple_note_button_plugin.handlers.hello_world_button:HelloWorldButton", "description": "A button that shows hello world message", diff --git a/example-plugins/supervising_provider_plugin/supervising_provider_plugin/CANVAS_MANIFEST.json b/example-plugins/supervising_provider_plugin/supervising_provider_plugin/CANVAS_MANIFEST.json index eaaa183d1..ebf0bcee7 100644 --- a/example-plugins/supervising_provider_plugin/supervising_provider_plugin/CANVAS_MANIFEST.json +++ b/example-plugins/supervising_provider_plugin/supervising_provider_plugin/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "supervising_provider_plugin", "description": "Add annotations to the supervising provider dropdown in Prescribe, Refill, and Adjust Prescription Commands", "components": { - "protocols": [ + "handlers": [ { - "class": "supervising_provider_plugin.protocols.my_protocol:Protocol", + "class": "supervising_provider_plugin.handlers.my_handler:Handler", "description": "Add annotations to the supervising provider dropdown in Prescribe, Refill, and Adjust Prescription Commands", "data_access": { "event": "", diff --git a/example-plugins/supervising_provider_plugin/supervising_provider_plugin/protocols/__init__.py b/example-plugins/supervising_provider_plugin/supervising_provider_plugin/handlers/__init__.py similarity index 100% rename from example-plugins/supervising_provider_plugin/supervising_provider_plugin/protocols/__init__.py rename to example-plugins/supervising_provider_plugin/supervising_provider_plugin/handlers/__init__.py diff --git a/example-plugins/supervising_provider_plugin/supervising_provider_plugin/protocols/my_protocol.py b/example-plugins/supervising_provider_plugin/supervising_provider_plugin/handlers/my_handler.py similarity index 89% rename from example-plugins/supervising_provider_plugin/supervising_provider_plugin/protocols/my_protocol.py rename to example-plugins/supervising_provider_plugin/supervising_provider_plugin/handlers/my_handler.py index ff2b546f8..0eb78068e 100644 --- a/example-plugins/supervising_provider_plugin/supervising_provider_plugin/protocols/my_protocol.py +++ b/example-plugins/supervising_provider_plugin/supervising_provider_plugin/handlers/my_handler.py @@ -2,13 +2,13 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from canvas_sdk.v1.data.staff import Staff from logger import log -class Protocol(BaseProtocol): - """You should put a helpful description of this protocol's behavior here.""" +class Handler(BaseHandler): + """You should put a helpful description of this handler's behavior here.""" RESPONDS_TO = [ EventType.Name(EventType.PRESCRIBE__SUPERVISING_PROVIDER__POST_SEARCH), @@ -19,7 +19,7 @@ class Protocol(BaseProtocol): EventType.Name(EventType.ADJUST_PRESCRIPTION__SUPERVISING_PROVIDER__PRE_SEARCH), ] - NARRATIVE_STRING = "I was inserted from my supervising provider plugin's protocol." + NARRATIVE_STRING = "I was inserted from my supervising provider plugin's handler." def compute(self) -> list[Effect]: """This method gets called when an event of the type RESPONDS_TO is fired.""" diff --git a/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/CANVAS_MANIFEST.json b/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/CANVAS_MANIFEST.json index 42f70ea86..61e0c8045 100644 --- a/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/CANVAS_MANIFEST.json +++ b/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "supervising_provider_prescribe", "description": "This protocol responds to the PRESCRIBE_COMMAND__POST_ORIGINATE event.\n\n It is used to test whether the supervising provider field is automatically populated\n when the Prescribe command is triggered. The protocol reacts to the command's creation\n and sets the field accordingly.\n\n The same logic can be tested for Refill and Adjust Prescription commands by updating\n the RESPONDS_TO event and the command class.", "components": { - "protocols": [ + "handlers": [ { - "class": "supervising_provider_prescribe.protocols.my_protocol:Protocol", + "class": "supervising_provider_prescribe.handlers.my_handler:Handler", "description": "This protocol responds to the PRESCRIBE_COMMAND__POST_ORIGINATE event.\n\n It is used to test whether the supervising provider field is automatically populated\n when the Prescribe command is triggered. The protocol reacts to the command's creation\n and sets the field accordingly.\n\n The same logic can be tested for Refill and Adjust Prescription commands by updating\n the RESPONDS_TO event and the command class.", "data_access": { "event": "", diff --git a/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/protocols/__init__.py b/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/handlers/__init__.py similarity index 100% rename from example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/protocols/__init__.py rename to example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/handlers/__init__.py diff --git a/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/protocols/my_protocol.py b/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/handlers/my_handler.py similarity index 81% rename from example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/protocols/my_protocol.py rename to example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/handlers/my_handler.py index 4f1f92723..42fa7abc7 100644 --- a/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/protocols/my_protocol.py +++ b/example-plugins/supervising_provider_prescribe/supervising_provider_prescribe/handlers/my_handler.py @@ -1,17 +1,17 @@ from canvas_sdk.commands import PrescribeCommand from canvas_sdk.effects import Effect from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from canvas_sdk.v1.data import Staff from logger import log -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - This protocol responds to the PRESCRIBE_COMMAND__POST_ORIGINATE event. + This handler responds to the PRESCRIBE_COMMAND__POST_ORIGINATE event. It is used to test whether the supervising provider field is automatically populated - when the Prescribe command is triggered. The protocol reacts to the command's creation + when the Prescribe command is triggered. The handler reacts to the command's creation and sets the field accordingly. The same logic can be tested for Refill and Adjust Prescription commands by updating diff --git a/example-plugins/supervising_provider_prescribe/tests/test_protocol.py b/example-plugins/supervising_provider_prescribe/tests/test_protocol.py index 789daedd9..abf0d8c19 100644 --- a/example-plugins/supervising_provider_prescribe/tests/test_protocol.py +++ b/example-plugins/supervising_provider_prescribe/tests/test_protocol.py @@ -7,18 +7,18 @@ from canvas_sdk.events import EventType -class TestSupervisingProviderPrescribeProtocol: - """Test suite for supervising_provider_prescribe Protocol.""" +class TestSupervisingProviderPrescribeHandler: + """Test suite for supervising_provider_prescribe Handler.""" def test_responds_to_correct_event(self) -> None: - """Test that Protocol responds to PRESCRIBE_COMMAND__POST_ORIGINATE event.""" - from supervising_provider_prescribe.protocols.my_protocol import Protocol + """Test that Handler responds to PRESCRIBE_COMMAND__POST_ORIGINATE event.""" + from supervising_provider_prescribe.handlers.my_handler import Handler - assert EventType.Name(EventType.PRESCRIBE_COMMAND__POST_ORIGINATE) == Protocol.RESPONDS_TO + assert EventType.Name(EventType.PRESCRIBE_COMMAND__POST_ORIGINATE) == Handler.RESPONDS_TO def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: """Test that compute creates edit effect when staff is available.""" - from supervising_provider_prescribe.protocols.my_protocol import Protocol + from supervising_provider_prescribe.handlers.my_handler import Handler # Mock event and target mock_event = MagicMock() @@ -31,26 +31,26 @@ def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: mock_staff = MagicMock() mock_staff.id = "test-staff-id" - # Create protocol instance - protocol = Protocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = Handler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock Staff.objects.first() with patch( - "supervising_provider_prescribe.protocols.my_protocol.Staff.objects.first" + "supervising_provider_prescribe.handlers.my_handler.Staff.objects.first" ) as mock_staff_first: mock_staff_first.return_value = mock_staff # Mock PrescribeCommand with patch( - "supervising_provider_prescribe.protocols.my_protocol.PrescribeCommand" + "supervising_provider_prescribe.handlers.my_handler.PrescribeCommand" ) as mock_command_class: mock_command_instance = MagicMock() mock_edit_effect = MagicMock() mock_command_instance.edit.return_value = mock_edit_effect mock_command_class.return_value = mock_command_instance - result = protocol.compute() + result = handler.compute() # Verify PrescribeCommand was created with correct parameters mock_command_class.assert_called_once_with( @@ -66,7 +66,7 @@ def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: def test_compute_without_staff_available(self, monkeypatch: MonkeyPatch) -> None: """Test that compute returns empty list when no staff is available.""" - from supervising_provider_prescribe.protocols.my_protocol import Protocol + from supervising_provider_prescribe.handlers.my_handler import Handler # Mock event and target mock_event = MagicMock() @@ -75,24 +75,24 @@ def test_compute_without_staff_available(self, monkeypatch: MonkeyPatch) -> None # Mock context dummy_context = {"patient": {"id": "test-patient-id"}} - # Create protocol instance - protocol = Protocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = Handler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock Staff.objects.first() to return None with patch( - "supervising_provider_prescribe.protocols.my_protocol.Staff.objects.first" + "supervising_provider_prescribe.handlers.my_handler.Staff.objects.first" ) as mock_staff_first: mock_staff_first.return_value = None - result = protocol.compute() + result = handler.compute() # Should return empty list when no staff found assert result == [] def test_compute_uses_target_as_command_uuid(self, monkeypatch: MonkeyPatch) -> None: """Test that compute correctly uses the target as command_uuid.""" - from supervising_provider_prescribe.protocols.my_protocol import Protocol + from supervising_provider_prescribe.handlers.my_handler import Handler # Mock event with specific target mock_event = MagicMock() @@ -106,22 +106,22 @@ def test_compute_uses_target_as_command_uuid(self, monkeypatch: MonkeyPatch) -> mock_staff = MagicMock() mock_staff.id = "test-staff-id" - # Create protocol instance - protocol = Protocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = Handler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "supervising_provider_prescribe.protocols.my_protocol.Staff.objects.first" + "supervising_provider_prescribe.handlers.my_handler.Staff.objects.first" ) as mock_staff_first: mock_staff_first.return_value = mock_staff with patch( - "supervising_provider_prescribe.protocols.my_protocol.PrescribeCommand" + "supervising_provider_prescribe.handlers.my_handler.PrescribeCommand" ) as mock_command_class: mock_command_instance = MagicMock() mock_command_class.return_value = mock_command_instance - protocol.compute() + handler.compute() # Verify command_uuid is set to the target value mock_command_class.assert_called_once() diff --git a/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/CANVAS_MANIFEST.json b/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/CANVAS_MANIFEST.json index 4a2aabb3d..6dc1663e2 100644 --- a/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/CANVAS_MANIFEST.json +++ b/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "supervising_provider_prescribe_protocol", "description": "This protocol responds to the NOTE_STATE_CHANGE_EVENT_CREATED event.\n\n It inserts a ProtocolCard containing a recommended Prescribe command. When the user triggers\n this command, the supervising provider field will be automatically populated.\n\n This plugin is primarily used to test and validate that the supervising provider is correctly\n set during command initialization from a protocol.", "components": { - "protocols": [ + "handlers": [ { - "class": "supervising_provider_prescribe_protocol.protocols.my_protocol:Protocol", + "class": "supervising_provider_prescribe_protocol.handlers.my_handler:Handler", "description": "This protocol responds to the NOTE_STATE_CHANGE_EVENT_CREATED event.\n\n It inserts a ProtocolCard containing a recommended Prescribe command. When the user triggers\n this command, the supervising provider field will be automatically populated.\n\n This plugin is primarily used to test and validate that the supervising provider is correctly\n set during command initialization from a protocol.", "data_access": { "event": "", diff --git a/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/protocols/__init__.py b/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/handlers/__init__.py similarity index 100% rename from example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/protocols/__init__.py rename to example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/handlers/__init__.py diff --git a/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/protocols/my_protocol.py b/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/handlers/my_handler.py similarity index 88% rename from example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/protocols/my_protocol.py rename to example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/handlers/my_handler.py index 4dbd49c37..80cd83ad3 100644 --- a/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/protocols/my_protocol.py +++ b/example-plugins/supervising_provider_prescribe_protocol/supervising_provider_prescribe_protocol/handlers/my_handler.py @@ -2,20 +2,20 @@ from canvas_sdk.effects import Effect from canvas_sdk.effects.protocol_card import ProtocolCard from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from canvas_sdk.v1.data import Staff from logger import log -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - This protocol responds to the NOTE_STATE_CHANGE_EVENT_CREATED event. + This handler responds to the NOTE_STATE_CHANGE_EVENT_CREATED event. It inserts a ProtocolCard containing a recommended Prescribe command. When the user triggers this command, the supervising provider field will be automatically populated. This plugin is primarily used to test and validate that the supervising provider is correctly - set during command initialization from a protocol. + set during command initialization from a handler. """ RESPONDS_TO = EventType.Name(EventType.NOTE_STATE_CHANGE_EVENT_CREATED) diff --git a/example-plugins/supervising_provider_prescribe_protocol/tests/test_protocol.py b/example-plugins/supervising_provider_prescribe_protocol/tests/test_protocol.py index 54292428a..0e5703980 100644 --- a/example-plugins/supervising_provider_prescribe_protocol/tests/test_protocol.py +++ b/example-plugins/supervising_provider_prescribe_protocol/tests/test_protocol.py @@ -8,17 +8,17 @@ class TestSupervisingProviderPrescribeProtocolCard: - """Test suite for supervising_provider_prescribe_protocol Protocol.""" + """Test suite for supervising_provider_prescribe_protocol Handler.""" def test_responds_to_correct_event(self) -> None: - """Test that Protocol responds to NOTE_STATE_CHANGE_EVENT_CREATED event.""" - from supervising_provider_prescribe_protocol.protocols.my_protocol import Protocol + """Test that Handler responds to NOTE_STATE_CHANGE_EVENT_CREATED event.""" + from supervising_provider_prescribe_protocol.handlers.my_handler import Handler - assert EventType.Name(EventType.NOTE_STATE_CHANGE_EVENT_CREATED) == Protocol.RESPONDS_TO + assert EventType.Name(EventType.NOTE_STATE_CHANGE_EVENT_CREATED) == Handler.RESPONDS_TO def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: """Test that compute creates protocol card with prescribe recommendation when staff available.""" - from supervising_provider_prescribe_protocol.protocols.my_protocol import Protocol + from supervising_provider_prescribe_protocol.handlers.my_handler import Handler # Mock event mock_event = MagicMock() @@ -30,19 +30,19 @@ def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: mock_staff = MagicMock() mock_staff.id = "test-staff-id" - # Create protocol instance - protocol = Protocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = Handler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock Staff.objects.first() with patch( - "supervising_provider_prescribe_protocol.protocols.my_protocol.Staff.objects.first" + "supervising_provider_prescribe_protocol.handlers.my_handler.Staff.objects.first" ) as mock_staff_first: mock_staff_first.return_value = mock_staff # Mock PrescribeCommand with patch( - "supervising_provider_prescribe_protocol.protocols.my_protocol.PrescribeCommand" + "supervising_provider_prescribe_protocol.handlers.my_handler.PrescribeCommand" ) as mock_command_class: mock_command_instance = MagicMock() mock_recommendation = MagicMock() @@ -51,7 +51,7 @@ def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: # Mock ProtocolCard with patch( - "supervising_provider_prescribe_protocol.protocols.my_protocol.ProtocolCard" + "supervising_provider_prescribe_protocol.handlers.my_handler.ProtocolCard" ) as mock_card_class: mock_card_instance = MagicMock() mock_card_instance.recommendations = [] @@ -59,7 +59,7 @@ def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: mock_card_instance.apply.return_value = mock_applied_card mock_card_class.return_value = mock_card_instance - result = protocol.compute() + result = handler.compute() # Verify ProtocolCard was created with correct parameters mock_card_class.assert_called_once_with( @@ -89,7 +89,7 @@ def test_compute_with_staff_available(self, monkeypatch: MonkeyPatch) -> None: def test_compute_without_staff_available(self, monkeypatch: MonkeyPatch) -> None: """Test that compute returns empty list when no staff is available.""" - from supervising_provider_prescribe_protocol.protocols.my_protocol import Protocol + from supervising_provider_prescribe_protocol.handlers.my_handler import Handler # Mock event mock_event = MagicMock() @@ -97,24 +97,24 @@ def test_compute_without_staff_available(self, monkeypatch: MonkeyPatch) -> None # Mock context dummy_context = {"patient_id": "test-patient-id", "note_id": "test-note-id"} - # Create protocol instance - protocol = Protocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = Handler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) # Mock Staff.objects.first() to return None with patch( - "supervising_provider_prescribe_protocol.protocols.my_protocol.Staff.objects.first" + "supervising_provider_prescribe_protocol.handlers.my_handler.Staff.objects.first" ) as mock_staff_first: mock_staff_first.return_value = None - result = protocol.compute() + result = handler.compute() # Should return empty list when no staff found assert result == [] def test_compute_uses_context_patient_id(self, monkeypatch: MonkeyPatch) -> None: """Test that compute uses patient_id from context.""" - from supervising_provider_prescribe_protocol.protocols.my_protocol import Protocol + from supervising_provider_prescribe_protocol.handlers.my_handler import Handler # Mock event mock_event = MagicMock() @@ -127,28 +127,28 @@ def test_compute_uses_context_patient_id(self, monkeypatch: MonkeyPatch) -> None mock_staff = MagicMock() mock_staff.id = "test-staff-id" - # Create protocol instance - protocol = Protocol(event=mock_event) - monkeypatch.setattr(type(protocol), "context", property(lambda self: dummy_context)) + # Create handler instance + handler = Handler(event=mock_event) + monkeypatch.setattr(type(handler), "context", property(lambda self: dummy_context)) with patch( - "supervising_provider_prescribe_protocol.protocols.my_protocol.Staff.objects.first" + "supervising_provider_prescribe_protocol.handlers.my_handler.Staff.objects.first" ) as mock_staff_first: mock_staff_first.return_value = mock_staff with ( patch( - "supervising_provider_prescribe_protocol.protocols.my_protocol.PrescribeCommand" + "supervising_provider_prescribe_protocol.handlers.my_handler.PrescribeCommand" ), patch( - "supervising_provider_prescribe_protocol.protocols.my_protocol.ProtocolCard" + "supervising_provider_prescribe_protocol.handlers.my_handler.ProtocolCard" ) as mock_card_class, ): mock_card_instance = MagicMock() mock_card_instance.recommendations = [] mock_card_class.return_value = mock_card_instance - protocol.compute() + handler.compute() # Verify ProtocolCard was created with correct patient_id mock_card_class.assert_called_once() diff --git a/example-plugins/twilio_sms_mms/twilio_sms_mms/CANVAS_MANIFEST.json b/example-plugins/twilio_sms_mms/twilio_sms_mms/CANVAS_MANIFEST.json index c87114e79..eac3f68c3 100644 --- a/example-plugins/twilio_sms_mms/twilio_sms_mms/CANVAS_MANIFEST.json +++ b/example-plugins/twilio_sms_mms/twilio_sms_mms/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "twilio_sms_mms", "description": "use Twillio to send and receive SMS/MMS", "components": { - "protocols": [ + "handlers": [ { "class": "twilio_sms_mms.handlers.sms_manip:SmsManip", "description": "SMS/MMS with Twilio" diff --git a/example-plugins/upsert_patient_metadata/upsert_patient_metadata/CANVAS_MANIFEST.json b/example-plugins/upsert_patient_metadata/upsert_patient_metadata/CANVAS_MANIFEST.json index 2837f0072..24adb2d44 100644 --- a/example-plugins/upsert_patient_metadata/upsert_patient_metadata/CANVAS_MANIFEST.json +++ b/example-plugins/upsert_patient_metadata/upsert_patient_metadata/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "upsert_patient_metadata", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { "class": "upsert_patient_metadata.handlers.my_handler:MyHandler", "description": "A handler that does xyz..." diff --git a/example-plugins/vitals_visualizer_plugin/vitals_visualizer_plugin/CANVAS_MANIFEST.json b/example-plugins/vitals_visualizer_plugin/vitals_visualizer_plugin/CANVAS_MANIFEST.json index cd6c4d12d..3fd6d686c 100644 --- a/example-plugins/vitals_visualizer_plugin/vitals_visualizer_plugin/CANVAS_MANIFEST.json +++ b/example-plugins/vitals_visualizer_plugin/vitals_visualizer_plugin/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "vitals_visualizer_plugin", "description": "A plugin that adds visualization capabilities to patient vital signs in the chart summary", "components": { - "protocols": [ + "handlers": [ { "class": "vitals_visualizer_plugin.handlers.vitals_button:VitalsVisualizerButton", "description": "A button that opens vitals visualization modal", diff --git a/plugin_runner/load_all_plugins.py b/plugin_runner/load_all_plugins.py index 811a9ef23..329585950 100755 --- a/plugin_runner/load_all_plugins.py +++ b/plugin_runner/load_all_plugins.py @@ -17,7 +17,7 @@ from canvas_generated.messages.events_pb2 import PLUGIN_CREATED from canvas_generated.messages.events_pb2 import Event as EventRequest from canvas_sdk.events.base import Event -from canvas_sdk.protocols.base import BaseProtocol +from canvas_sdk.handlers.base import BaseHandler from plugin_runner.plugin_runner import LOADED_PLUGINS, load_or_reload_plugin ORIGINAL_PATH = sys.path.copy() @@ -102,7 +102,7 @@ def main() -> None: enable_httpretty() for key, plugin in LOADED_PLUGINS.items(): - Klass: type[BaseProtocol] = plugin["class"] + Klass: type[BaseHandler] = plugin["class"] if not hasattr(Klass, "compute") or not callable(Klass.compute): print(f"Skipping {key} due to no compute method") diff --git a/plugin_runner/sandbox.py b/plugin_runner/sandbox.py index a6195f475..7e72de26f 100644 --- a/plugin_runner/sandbox.py +++ b/plugin_runner/sandbox.py @@ -654,7 +654,7 @@ def __init__( namespace: str, evaluated_modules: dict[str, bool] | None = None, ) -> None: - self.namespace = namespace or "protocols" + self.namespace = namespace or "handlers" self.package_name = self.namespace.split(".")[0] if not source_code.exists(): diff --git a/plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json index 5a8e600b6..8262a3e00 100644 --- a/plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/example_plugin/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "example_plugin", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "example_plugin.protocols.my_protocol:Protocol", + "class": "example_plugin.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/example_plugin/README.md b/plugin_runner/tests/fixtures/plugins/example_plugin/README.md index 069c11075..b6fa89c9a 100644 --- a/plugin_runner/tests/fixtures/plugins/example_plugin/README.md +++ b/plugin_runner/tests/fixtures/plugins/example_plugin/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/example_plugin/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/example_plugin/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/example_plugin/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/example_plugin/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/example_plugin/handlers/my_handler.py similarity index 76% rename from plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/example_plugin/handlers/my_handler.py index 52f9d2e08..2203a9d07 100644 --- a/plugin_runner/tests/fixtures/plugins/example_plugin/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/example_plugin/handlers/my_handler.py @@ -1,11 +1,11 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_caching_api/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_caching_api/CANVAS_MANIFEST.json index 28b342863..c30770103 100644 --- a/plugin_runner/tests/fixtures/plugins/test_caching_api/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_caching_api/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_caching_api", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_caching_api.protocols.my_protocol:Protocol", + "class": "test_caching_api.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -15,7 +15,7 @@ } }, { - "class": "test_caching_api.protocols.my_secondary_protocol:Protocol", + "class": "test_caching_api.handlers.my_secondary_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -24,7 +24,7 @@ } }, { - "class": "test_caching_api.protocols.invalid_protocol:InvalidProtocol", + "class": "test_caching_api.handlers.invalid_handler:InvalidHandler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_caching_api/README.md b/plugin_runner/tests/fixtures/plugins/test_caching_api/README.md index 3d622596f..9787dd48b 100644 --- a/plugin_runner/tests/fixtures/plugins/test_caching_api/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_caching_api/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/invalid_protocol.py b/plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/invalid_handler.py similarity index 73% rename from plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/invalid_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/invalid_handler.py index 8bda78b3f..c670b846d 100644 --- a/plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/invalid_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/invalid_handler.py @@ -1,12 +1,12 @@ from canvas_sdk.caching.plugins import get_cache from canvas_sdk.effects import Effect from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class InvalidProtocol(BaseProtocol): +class InvalidHandler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/my_handler.py similarity index 77% rename from plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/my_handler.py index 6ed4b32f1..d3bc4dafc 100644 --- a/plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/my_handler.py @@ -1,12 +1,12 @@ from canvas_sdk.caching.plugins import get_cache from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/my_secondary_protocol.py b/plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/my_secondary_handler.py similarity index 82% rename from plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/my_secondary_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/my_secondary_handler.py index 70f0a5897..7b7c3ea56 100644 --- a/plugin_runner/tests/fixtures/plugins/test_caching_api/protocols/my_secondary_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_caching_api/handlers/my_secondary_handler.py @@ -1,12 +1,12 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from test_caching_api.wrapper import WrappedCache, wrapped_get_cache -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_caching_api/wrapper.py b/plugin_runner/tests/fixtures/plugins/test_caching_api/wrapper.py index 9f1382908..7636f6b36 100644 --- a/plugin_runner/tests/fixtures/plugins/test_caching_api/wrapper.py +++ b/plugin_runner/tests/fixtures/plugins/test_caching_api/wrapper.py @@ -8,14 +8,14 @@ def wrapped_get_cache(*args: Any, **kwargs: Any) -> Any: """ This contrived method just exists to ensure that we can import `get_cache` - from files that are imported from the main protocol. + from files that are imported from the main handler. """ return get_cache(*args, **kwargs) class WrappedCache: """ - Contrived class ensuring we can call get_cache from non-protocol code. + Contrived class ensuring we can call get_cache from non-handler code. """ @classmethod diff --git a/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json index d268cb78a..53cd8cb5f 100644 --- a/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_implicit_imports_plugin", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_implicit_imports_plugin.protocols.my_protocol:Forbidden", + "class": "test_implicit_imports_plugin.handlers.my_protocol:Forbidden", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -15,7 +15,7 @@ } }, { - "class": "test_implicit_imports_plugin.protocols.my_protocol:Allowed", + "class": "test_implicit_imports_plugin.handlers.my_protocol:Allowed", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md b/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md index 1a15b04e2..a9efffa24 100644 --- a/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/README.md @@ -8,4 +8,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/handlers/my_protocol.py similarity index 73% rename from plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/handlers/my_protocol.py index e317fc135..715fdc37d 100644 --- a/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_implicit_imports_plugin/handlers/my_protocol.py @@ -1,11 +1,11 @@ from canvas_sdk.effects import Effect from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from logger import log -class Forbidden(BaseProtocol): - """You should put a helpful description of this protocol's behavior here.""" +class Forbidden(BaseHandler): + """You should put a helpful description of this handler's behavior here.""" # Name the event type you wish to run in response to RESPONDS_TO = EventType.Name(EventType.UNKNOWN) @@ -19,8 +19,8 @@ def compute(self) -> list[Effect]: return [] -class Allowed(BaseProtocol): - """You should put a helpful description of this protocol's behavior here.""" +class Allowed(BaseHandler): + """You should put a helpful description of this handler's behavior here.""" RESPONDS_TO = EventType.Name(EventType.UNKNOWN) diff --git a/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json index a7030642d..659ce0a95 100644 --- a/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_load_questionnaire", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_load_questionnaire.protocols.my_protocol:ValidQuestionnaire", + "class": "test_load_questionnaire.handlers.my_protocol:ValidQuestionnaire", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -15,7 +15,7 @@ } }, { - "class": "test_load_questionnaire.protocols.my_protocol:InvalidQuestionnaire", + "class": "test_load_questionnaire.handlers.my_protocol:InvalidQuestionnaire", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -24,7 +24,7 @@ } }, { - "class": "test_load_questionnaire.protocols.my_protocol:ForbiddenQuestionnaire", + "class": "test_load_questionnaire.handlers.my_protocol:ForbiddenQuestionnaire", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md b/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md index feb1a9abd..6b1c23800 100644 --- a/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/README.md @@ -8,4 +8,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_load_questionnaire/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/handlers/my_protocol.py similarity index 83% rename from plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_load_questionnaire/handlers/my_protocol.py index c0653115c..96a5ae82a 100644 --- a/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_load_questionnaire/handlers/my_protocol.py @@ -7,7 +7,7 @@ class ValidQuestionnaire(BaseHandler): - """You should put a helpful description of this protocol's behavior here.""" + """You should put a helpful description of this handler's behavior here.""" RESPONDS_TO = [EventType.Name(EventType.UNKNOWN)] @@ -18,7 +18,7 @@ def compute(self) -> list[Effect]: class InvalidQuestionnaire(BaseHandler): - """You should put a helpful description of this protocol's behavior here.""" + """You should put a helpful description of this handler's behavior here.""" RESPONDS_TO = [EventType.Name(EventType.UNKNOWN)] @@ -29,7 +29,7 @@ def compute(self) -> list[Effect]: class ForbiddenQuestionnaire(BaseHandler): - """You should put a helpful description of this protocol's behavior here.""" + """You should put a helpful description of this handler's behavior here.""" RESPONDS_TO = [EventType.Name(EventType.UNKNOWN)] diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json index 0c049dd72..74dbec6a9 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_module_forbidden_imports_plugin", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_module_forbidden_imports_plugin.protocols.my_protocol:Protocol", + "class": "test_module_forbidden_imports_plugin.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md index 0e61f0476..b56eccacd 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/handlers/my_handler.py similarity index 76% rename from plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/handlers/my_handler.py index 27951a8b7..e63b3e66b 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_plugin/handlers/my_handler.py @@ -2,12 +2,12 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json index 8ba4ab990..eaee97f60 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_module_forbidden_imports_runtime_plugin", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_module_forbidden_imports_runtime_plugin.protocols.my_protocol:Protocol", + "class": "test_module_forbidden_imports_runtime_plugin.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md index c446cd3fc..18230120e 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/handlers/my_handler.py similarity index 76% rename from plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/handlers/my_handler.py index a2f8d36b5..e42997161 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_module_forbidden_imports_runtime_plugin/handlers/my_handler.py @@ -1,11 +1,11 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json index de02fb9ad..c85c2c612 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_module_imports_outside_plugin_v1", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_module_imports_outside_plugin_v1.protocols.my_protocol:Protocol", + "class": "test_module_imports_outside_plugin_v1.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md index ba81885c9..304b4edb2 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/handlers/my_handler.py similarity index 75% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/handlers/my_handler.py index 787ff2608..75ac380f6 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v1/handlers/my_handler.py @@ -2,12 +2,12 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json index ec175a74d..491f535a7 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_module_imports_outside_plugin_v2", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_module_imports_outside_plugin_v2.protocols.my_protocol:Protocol", + "class": "test_module_imports_outside_plugin_v2.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md index c632b3147..38488e2a1 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/handlers/my_handler.py similarity index 76% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/handlers/my_handler.py index 8b9bec4bd..34b0e28cd 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v2/handlers/my_handler.py @@ -2,12 +2,12 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json index 5213f1c5d..05f449b1f 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_module_imports_outside_plugin_v3", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_module_imports_outside_plugin_v3.protocols.my_protocol:Protocol", + "class": "test_module_imports_outside_plugin_v3.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md index 64b2c01e2..c74dfc1b0 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/handlers/my_handler.py similarity index 76% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/handlers/my_handler.py index 3feb07d83..abb73a270 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_outside_plugin_v3/handlers/my_handler.py @@ -2,12 +2,12 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json index feb01dc70..09a7b0a24 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_module_imports_plugin", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_module_imports_plugin.protocols.my_protocol:Protocol", + "class": "test_module_imports_plugin.handlers.my_handler:Handler", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md b/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md index 202c94a9d..80b08a814 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/README.md @@ -9,4 +9,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/handlers/my_handler.py similarity index 75% rename from plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/handlers/my_handler.py index 63f01fa4f..ea567bd5a 100644 --- a/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/protocols/my_protocol.py +++ b/plugin_runner/tests/fixtures/plugins/test_module_imports_plugin/handlers/my_handler.py @@ -1,12 +1,12 @@ from canvas_sdk.effects import Effect, EffectType from canvas_sdk.events import EventType -from canvas_sdk.protocols import BaseProtocol +from canvas_sdk.handlers import BaseHandler from test_module_imports_plugin.other_module.base import import_me -class Protocol(BaseProtocol): +class Handler(BaseHandler): """ - You should put a helpful description of this protocol's behavior here. + You should put a helpful description of this handler's behavior here. """ # Name the event type you wish to run in response to diff --git a/plugin_runner/tests/fixtures/plugins/test_payment_processor/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_payment_processor/CANVAS_MANIFEST.json index 839203b03..e47a97a69 100644 --- a/plugin_runner/tests/fixtures/plugins/test_payment_processor/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_payment_processor/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_payment_processor", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_payment_processor.protocols.my_protocol:CustomPaymentProcessor", + "class": "test_payment_processor.handlers.my_protocol:CustomPaymentProcessor", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_payment_processor/README.md b/plugin_runner/tests/fixtures/plugins/test_payment_processor/README.md index 20c35d536..648f7f0b4 100644 --- a/plugin_runner/tests/fixtures/plugins/test_payment_processor/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_payment_processor/README.md @@ -8,4 +8,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_payment_processor/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_payment_processor/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_payment_processor/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_payment_processor/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_payment_processor/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_payment_processor/handlers/my_protocol.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_payment_processor/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_payment_processor/handlers/my_protocol.py diff --git a/plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json index 5b8de848c..a46fa27c1 100644 --- a/plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_render_template/CANVAS_MANIFEST.json @@ -4,9 +4,9 @@ "name": "test_render_template", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { - "class": "test_render_template.protocols.my_protocol:ValidTemplate", + "class": "test_render_template.handlers.my_protocol:ValidTemplate", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -15,7 +15,7 @@ } }, { - "class": "test_render_template.protocols.my_protocol:TemplateInheritance", + "class": "test_render_template.handlers.my_protocol:TemplateInheritance", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -24,7 +24,7 @@ } }, { - "class": "test_render_template.protocols.my_protocol:InvalidTemplate", + "class": "test_render_template.handlers.my_protocol:InvalidTemplate", "description": "A protocol that does xyz...", "data_access": { "event": "", @@ -33,7 +33,7 @@ } }, { - "class": "test_render_template.protocols.my_protocol:ForbiddenTemplate", + "class": "test_render_template.handlers.my_protocol:ForbiddenTemplate", "description": "A protocol that does xyz...", "data_access": { "event": "", diff --git a/plugin_runner/tests/fixtures/plugins/test_render_template/README.md b/plugin_runner/tests/fixtures/plugins/test_render_template/README.md index 28556f0c5..9b791da14 100644 --- a/plugin_runner/tests/fixtures/plugins/test_render_template/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_render_template/README.md @@ -8,4 +8,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_render_template/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_render_template/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_render_template/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_render_template/handlers/__init__.py diff --git a/plugin_runner/tests/fixtures/plugins/test_render_template/protocols/my_protocol.py b/plugin_runner/tests/fixtures/plugins/test_render_template/handlers/my_protocol.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_render_template/protocols/my_protocol.py rename to plugin_runner/tests/fixtures/plugins/test_render_template/handlers/my_protocol.py diff --git a/plugin_runner/tests/fixtures/plugins/test_simple_api/CANVAS_MANIFEST.json b/plugin_runner/tests/fixtures/plugins/test_simple_api/CANVAS_MANIFEST.json index 70faf7d46..a11d031a7 100644 --- a/plugin_runner/tests/fixtures/plugins/test_simple_api/CANVAS_MANIFEST.json +++ b/plugin_runner/tests/fixtures/plugins/test_simple_api/CANVAS_MANIFEST.json @@ -4,7 +4,7 @@ "name": "test_simple_api", "description": "Edit the description in CANVAS_MANIFEST.json", "components": { - "protocols": [ + "handlers": [ { "class": "test_simple_api.api.handler:Route", "description": "A protocol that does xyz...", diff --git a/plugin_runner/tests/fixtures/plugins/test_simple_api/README.md b/plugin_runner/tests/fixtures/plugins/test_simple_api/README.md index 6c1c986cd..1e305cef5 100644 --- a/plugin_runner/tests/fixtures/plugins/test_simple_api/README.md +++ b/plugin_runner/tests/fixtures/plugins/test_simple_api/README.md @@ -8,4 +8,4 @@ A description of this plugin ### Important Note! The CANVAS_MANIFEST.json is used when installing your plugin. Please ensure it -gets updated if you add, remove, or rename protocols. +gets updated if you add, remove, or rename handlers. diff --git a/plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/__init__.py b/plugin_runner/tests/fixtures/plugins/test_simple_api/handlers/__init__.py similarity index 100% rename from plugin_runner/tests/fixtures/plugins/test_simple_api/protocols/__init__.py rename to plugin_runner/tests/fixtures/plugins/test_simple_api/handlers/__init__.py diff --git a/plugin_runner/tests/test_plugin_runner.py b/plugin_runner/tests/test_plugin_runner.py index d9a805369..451849293 100644 --- a/plugin_runner/tests/test_plugin_runner.py +++ b/plugin_runner/tests/test_plugin_runner.py @@ -51,9 +51,9 @@ def plugin_runner() -> PluginRunner: @pytest.mark.parametrize("install_test_plugin", ["example_plugin"], indirect=True) def test_load_plugins_with_valid_plugin(install_test_plugin: Path, load_test_plugins: None) -> None: """Test loading plugins with a valid plugin.""" - assert "example_plugin:example_plugin.protocols.my_protocol:Protocol" in LOADED_PLUGINS + assert "example_plugin:example_plugin.handlers.my_handler:Handler" in LOADED_PLUGINS assert ( - LOADED_PLUGINS["example_plugin:example_plugin.protocols.my_protocol:Protocol"]["active"] + LOADED_PLUGINS["example_plugin:example_plugin.handlers.my_handler:Handler"]["active"] is True ) @@ -67,12 +67,12 @@ def test_load_plugins_with_plugin_that_imports_other_modules_within_plugin_packa ) -> None: """Test loading plugins with a valid plugin that imports other modules within the current plugin package.""" assert ( - "test_module_imports_plugin:test_module_imports_plugin.protocols.my_protocol:Protocol" + "test_module_imports_plugin:test_module_imports_plugin.handlers.my_handler:Handler" in LOADED_PLUGINS ) assert ( LOADED_PLUGINS[ - "test_module_imports_plugin:test_module_imports_plugin.protocols.my_protocol:Protocol" + "test_module_imports_plugin:test_module_imports_plugin.handlers.my_handler:Handler" ]["active"] is True ) @@ -140,7 +140,7 @@ def test_load_plugins_with_plugin_that_imports_forbidden_modules_at_runtime( with pytest.raises(ImportError, match="is not an allowed import."): load_or_reload_plugin(install_test_plugin) class_handler = LOADED_PLUGINS[ - "test_module_forbidden_imports_runtime_plugin:test_module_forbidden_imports_runtime_plugin.protocols.my_protocol:Protocol" + "test_module_forbidden_imports_runtime_plugin:test_module_forbidden_imports_runtime_plugin.handlers.my_handler:Handler" ]["class"] class_handler(Event(EventRequest(type=EventType.UNKNOWN))).compute() @@ -159,7 +159,7 @@ def test_plugin_that_implicitly_imports_allowed_modules( with caplog.at_level(logging.INFO): load_or_reload_plugin(install_test_plugin) class_handler = LOADED_PLUGINS[ - "test_implicit_imports_plugin:test_implicit_imports_plugin.protocols.my_protocol:Allowed" + "test_implicit_imports_plugin:test_implicit_imports_plugin.handlers.my_protocol:Allowed" ]["class"] class_handler(Event(EventRequest(type=EventType.UNKNOWN))).compute() @@ -185,7 +185,7 @@ def test_plugin_that_implicitly_imports_forbidden_modules( ): load_or_reload_plugin(install_test_plugin) class_handler = LOADED_PLUGINS[ - "test_implicit_imports_plugin:test_implicit_imports_plugin.protocols.my_protocol:Forbidden" + "test_implicit_imports_plugin:test_implicit_imports_plugin.handlers.my_protocol:Forbidden" ]["class"] class_handler(Event(EventRequest(type=EventType.UNKNOWN))).compute() @@ -216,9 +216,9 @@ def test_reload_plugin(install_test_plugin: Path, load_test_plugins: None) -> No """Test reloading a plugin.""" load_plugins() - assert "example_plugin:example_plugin.protocols.my_protocol:Protocol" in LOADED_PLUGINS + assert "example_plugin:example_plugin.handlers.my_handler:Handler" in LOADED_PLUGINS assert ( - LOADED_PLUGINS["example_plugin:example_plugin.protocols.my_protocol:Protocol"]["active"] + LOADED_PLUGINS["example_plugin:example_plugin.handlers.my_handler:Handler"]["active"] is True ) @@ -228,10 +228,10 @@ def test_remove_plugin_should_be_removed_from_loaded_plugins( install_test_plugin: Path, load_test_plugins: None ) -> None: """Test removing a plugin.""" - assert "example_plugin:example_plugin.protocols.my_protocol:Protocol" in LOADED_PLUGINS + assert "example_plugin:example_plugin.handlers.my_handler:Handler" in LOADED_PLUGINS shutil.rmtree(install_test_plugin) load_plugins() - assert "example_plugin:example_plugin.protocols.my_protocol:Protocol" not in LOADED_PLUGINS + assert "example_plugin:example_plugin.handlers.my_handler:Handler" not in LOADED_PLUGINS @pytest.mark.parametrize("install_test_plugin", ["example_plugin"], indirect=True) @@ -244,7 +244,7 @@ def test_load_plugins_should_refresh_event_handler_map( load_plugins() assert EventType.Name(EventType.UNKNOWN) in EVENT_HANDLER_MAP assert EVENT_HANDLER_MAP[EventType.Name(EventType.UNKNOWN)] == [ - "example_plugin:example_plugin.protocols.my_protocol:Protocol" + "example_plugin:example_plugin.handlers.my_handler:Handler" ] @@ -258,7 +258,7 @@ def test_load_plugin_should_refresh_event_handler_map( load_plugin(install_test_plugin) assert EventType.Name(EventType.UNKNOWN) in EVENT_HANDLER_MAP assert EVENT_HANDLER_MAP[EventType.Name(EventType.UNKNOWN)] == [ - "example_plugin:example_plugin.protocols.my_protocol:Protocol" + "example_plugin:example_plugin.handlers.my_handler:Handler" ] @@ -267,13 +267,13 @@ def test_unload_plugin_should_remove_from_loaded_plugins( install_test_plugin: Path, load_test_plugins: None ) -> None: """Test that unloading a plugin successfully removes it from loaded plugins.""" - assert "example_plugin:example_plugin.protocols.my_protocol:Protocol" in LOADED_PLUGINS + assert "example_plugin:example_plugin.handlers.my_handler:Handler" in LOADED_PLUGINS assert ( - LOADED_PLUGINS["example_plugin:example_plugin.protocols.my_protocol:Protocol"]["active"] + LOADED_PLUGINS["example_plugin:example_plugin.handlers.my_handler:Handler"]["active"] is True ) unload_plugin("example_plugin") - assert "example_plugin:example_plugin.protocols.my_protocol:Protocol" not in LOADED_PLUGINS + assert "example_plugin:example_plugin.handlers.my_handler:Handler" not in LOADED_PLUGINS @pytest.mark.parametrize("install_test_plugin", ["example_plugin"], indirect=True) @@ -285,7 +285,7 @@ def test_unload_plugin_should_refresh_event_handler_map( class OtherPluginHandler: RESPONDS_TO = EventType.Name(EventType.UNKNOWN) - LOADED_PLUGINS["other_example_plugin:example_plugin.protocols.my_protocol:Protocol"] = { + LOADED_PLUGINS["other_example_plugin:example_plugin.handlers.my_handler:Handler"] = { "active": True, "class": OtherPluginHandler, "sandbox": None, @@ -295,7 +295,7 @@ class OtherPluginHandler: unload_plugin("example_plugin") assert ( - "example_plugin:example_plugin.protocols.my_protocol:Protocol" + "example_plugin:example_plugin.handlers.my_handler:Handler" not in EVENT_HANDLER_MAP[EventType.Name(EventType.UNKNOWN)] ) @@ -621,7 +621,7 @@ def test_simple_api_websocket( [ PaymentProcessorMetadata( identifier=base64.b64encode( - b"test_payment_processor.protocols.my_protocol:CustomPaymentProcessor" + b"test_payment_processor.handlers.my_protocol:CustomPaymentProcessor" ).decode("utf-8"), type=PaymentProcessorMetadata.PaymentProcessorType.CARD, ).apply() @@ -631,7 +631,7 @@ def test_simple_api_websocket( EventType.REVENUE__PAYMENT_PROCESSOR__SELECTED, { "identifier": base64.b64encode( - b"test_payment_processor.protocols.my_protocol:CustomPaymentProcessor" + b"test_payment_processor.handlers.my_protocol:CustomPaymentProcessor" ).decode("utf-8"), }, [ @@ -652,7 +652,7 @@ def test_simple_api_websocket( EventType.REVENUE__PAYMENT_PROCESSOR__CHARGE, { "identifier": base64.b64encode( - b"test_payment_processor.protocols.my_protocol:CustomPaymentProcessor" + b"test_payment_processor.handlers.my_protocol:CustomPaymentProcessor" ).decode("utf-8"), "amount": "1.23", "token": "tok_123", @@ -672,7 +672,7 @@ def test_simple_api_websocket( EventType.REVENUE__PAYMENT_PROCESSOR__PAYMENT_METHODS__LIST, { "identifier": base64.b64encode( - b"test_payment_processor.protocols.my_protocol:CustomPaymentProcessor" + b"test_payment_processor.handlers.my_protocol:CustomPaymentProcessor" ).decode("utf-8"), "patient": { "id": "patient_1", @@ -704,7 +704,7 @@ def test_simple_api_websocket( EventType.REVENUE__PAYMENT_PROCESSOR__PAYMENT_METHODS__ADD, { "identifier": base64.b64encode( - b"test_payment_processor.protocols.my_protocol:CustomPaymentProcessor" + b"test_payment_processor.handlers.my_protocol:CustomPaymentProcessor" ).decode("utf-8"), "patient": { "id": "patient_1", @@ -726,7 +726,7 @@ def test_simple_api_websocket( EventType.REVENUE__PAYMENT_PROCESSOR__PAYMENT_METHODS__REMOVE, { "identifier": base64.b64encode( - b"test_payment_processor.protocols.my_protocol:CustomPaymentProcessor" + b"test_payment_processor.handlers.my_protocol:CustomPaymentProcessor" ).decode("utf-8"), "patient": { "id": "patient_1", diff --git a/plugin_runner/tests/test_sandbox.py b/plugin_runner/tests/test_sandbox.py index ad0c704e3..a873fa202 100644 --- a/plugin_runner/tests/test_sandbox.py +++ b/plugin_runner/tests/test_sandbox.py @@ -24,7 +24,7 @@ def _sandbox_from_code( source_code: str, - module_name: str = "plugin_name.protocols.protocol", + module_name: str = "plugin_name.handlers.protocol", extra_source_code: str | None = None, extra_module_name: str | None = None, ) -> Sandbox: