From 6c0132c83a7dac40155a75c7481b2e8bfaa2235d Mon Sep 17 00:00:00 2001 From: Kyle Roche Date: Mon, 3 Jun 2024 17:09:34 -0700 Subject: [PATCH 01/11] docs, tests, secrets --- .github/workflows/docs-integration-tests.yml | 4 ++ .../drivers/event-listener-drivers.md | 32 ++++++++++++++++ .../pusher_event_listener_driver.py | 38 +++++++++++++++++++ poetry.lock | 3 +- pyproject.toml | 2 + .../test_pusher_event_listener_driver.py | 26 +++++++++++++ 6 files changed, 104 insertions(+), 1 deletion(-) create mode 100644 griptape/drivers/event_listener/pusher_event_listener_driver.py create mode 100644 tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index eb3621870..904b112a8 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -112,6 +112,10 @@ jobs: AWS_IOT_CORE_ENDPOINT: ${{ secrets.INTEG_AWS_IOT_CORE_ENDPOINT }} AWS_IOT_CORE_TOPIC: ${{ secrets.INTEG_AWS_IOT_CORE_TOPIC }} ELEVEN_LABS_API_KEY: ${{ secrets.INTEG_ELEVEN_LABS_API_KEY }} + PUSHER_APP_ID: ${{ secrets.PUSHER_APP_ID }} + PUSHER_KEY: ${{ secrets.PUSHER_KEY }} + PUSHER_SECRET: ${{ secrets.PUSHER_SECRET }} + PUSHER_CLUSTER: ${{ secretes.PUSHER_CLUSTER }} services: postgres: image: ankane/pgvector:v0.5.0 diff --git a/docs/griptape-framework/drivers/event-listener-drivers.md b/docs/griptape-framework/drivers/event-listener-drivers.md index d35489f98..4134c4564 100644 --- a/docs/griptape-framework/drivers/event-listener-drivers.md +++ b/docs/griptape-framework/drivers/event-listener-drivers.md @@ -212,4 +212,36 @@ agent = Agent( agent.run("Analyze the pros and cons of remote work vs. office work") ``` +### Pusher Event Listener Driver +The [PusherEventListenerDriver](../../reference/griptape/drivers/event_listener/pusher_event_listener_driver.md) sends Events to [Pusher](https://pusher.com). + +```python +import os +from griptape.drivers import PusherEventListenerDriver +from griptape.events import ( + EventListener, + FinishStructureRunEvent +) +from griptape.structures import Agent + +agent = Agent( + event_listeners=[ + EventListener( + event_types=[FinishStructureRunEvent], + driver=PusherEventListenerDriver( + batched=False, + app_id=os.environ["PUSHER_APP_ID"], + key=os.environ["PUSHER_KEY"], + secret=os.environ["PUSHER_SECRET"], + cluster=os.environ["PUSHER_CLUSTER"], + channel='my-channel', + event_name='my-event' + ), + ), + ], +) + +agent.run("Analyze the pros and cons of remote work vs. office work") + +``` diff --git a/griptape/drivers/event_listener/pusher_event_listener_driver.py b/griptape/drivers/event_listener/pusher_event_listener_driver.py new file mode 100644 index 000000000..9aefb5a3c --- /dev/null +++ b/griptape/drivers/event_listener/pusher_event_listener_driver.py @@ -0,0 +1,38 @@ +from __future__ import annotations + +import json +from typing import TYPE_CHECKING, Any +from attrs import define, field +from griptape.drivers.event_listener.base_event_listener_driver import BaseEventListenerDriver + +@define +class PusherEventListenerDriver(BaseEventListenerDriver): + app_id: str = field(kw_only=True) + key: str = field(kw_only=True) + secret: str = field(kw_only=True) + cluster: str = field(kw_only=True) + + # message specific + channel: str = field(kw_only=True) + event_name: str = field(kw_only=True) + + if TYPE_CHECKING: + import pusher + + def try_publish_event_payload_batch(self, event_payload_batch: list[dict]) -> None: + pass + + def try_publish_event_payload(self, event_payload: dict) -> None: + pusher_client = pusher.Pusher( + app_id=self.app_id, + key=self.key, + secret=self.secret, + cluster=self.cluster, + ssl=True + ) + + pusher_client.trigger( + channels=self.channel, + event_name=self.event_name, + data=json.dumps(event_payload) + ) \ No newline at end of file diff --git a/poetry.lock b/poetry.lock index 7e6804fcc..40f57243e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -6003,6 +6003,7 @@ drivers-embedding-huggingface = ["huggingface-hub", "transformers"] drivers-embedding-voyageai = ["voyageai"] drivers-event-listener-amazon-iot = ["boto3"] drivers-event-listener-amazon-sqs = ["boto3"] +drivers-event-listener-pusher = [] drivers-memory-conversation-amazon-dynamodb = ["boto3"] drivers-memory-conversation-redis = ["redis"] drivers-prompt-amazon-bedrock = ["anthropic", "boto3"] @@ -6033,4 +6034,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "da89e6bb7aa395fd5badc416ec859e574416ea1fe07ee6f93035fe6a7e314dcd" +content-hash = "8335891edd5a6a312ada0ec78ad29ed31783b0c1f01382293ffec49e82c66354" diff --git a/pyproject.toml b/pyproject.toml index 55ae82ce2..97762f3ed 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,6 +96,7 @@ drivers-web-scraper-markdownify = ["playwright", "beautifulsoup4", "markdownify" drivers-event-listener-amazon-sqs = ["boto3"] drivers-event-listener-amazon-iot = ["boto3"] +drivers-event-listener-pusher = ["pusher"] loaders-dataframe = ["pandas"] loaders-pdf = ["pypdf"] @@ -128,6 +129,7 @@ all = [ "voyageai", "elevenlabs", "torch", + "pusher", # loaders "pandas", diff --git a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py new file mode 100644 index 000000000..5d1548692 --- /dev/null +++ b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py @@ -0,0 +1,26 @@ +from pytest import fixture +from tests.mocks.mock_event import MockEvent +from griptape.drivers.event_listener.pusher_event_listener_driver import PusherEventListenerDriver + +@mock_iotdata +class TestPusherEventListenerDriver: + + @fixture() + def driver(self): + return PusherEventListenerDriver( + app_id="test-app-id", + key="test-key", + secret="test-secret", + cluster="test-cluster", + channel='test-channel', + event_name='test-event' + ) + + def test_init(self, driver): + assert driver + + def test_try_publish_event_payload(self, driver): + driver.try_publish_event_payload(MockEvent().to_dict()) + + def test_try_publish_event_payload_batch(self, driver): + driver.try_publish_event_payload_batch([MockEvent().to_dict() for _ in range(3)]) From 7b6b0c611c2c1026b1f0e7bda386d44f1393de9b Mon Sep 17 00:00:00 2001 From: Kyle Roche Date: Mon, 3 Jun 2024 17:17:06 -0700 Subject: [PATCH 02/11] fixed secrets --- .github/workflows/docs-integration-tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/docs-integration-tests.yml b/.github/workflows/docs-integration-tests.yml index 904b112a8..a87810774 100644 --- a/.github/workflows/docs-integration-tests.yml +++ b/.github/workflows/docs-integration-tests.yml @@ -112,10 +112,10 @@ jobs: AWS_IOT_CORE_ENDPOINT: ${{ secrets.INTEG_AWS_IOT_CORE_ENDPOINT }} AWS_IOT_CORE_TOPIC: ${{ secrets.INTEG_AWS_IOT_CORE_TOPIC }} ELEVEN_LABS_API_KEY: ${{ secrets.INTEG_ELEVEN_LABS_API_KEY }} - PUSHER_APP_ID: ${{ secrets.PUSHER_APP_ID }} - PUSHER_KEY: ${{ secrets.PUSHER_KEY }} - PUSHER_SECRET: ${{ secrets.PUSHER_SECRET }} - PUSHER_CLUSTER: ${{ secretes.PUSHER_CLUSTER }} + PUSHER_APP_ID: ${{ secrets.INTEG_PUSHER_APP_ID }} + PUSHER_KEY: ${{ secrets.INTEG_PUSHER_KEY }} + PUSHER_SECRET: ${{ secrets.INTEG_PUSHER_SECRET }} + PUSHER_CLUSTER: ${{ secretes.INTEG_PUSHER_CLUSTER }} services: postgres: image: ankane/pgvector:v0.5.0 From d48c5956d4d2fd10fe08d6b170e41d36e217d40d Mon Sep 17 00:00:00 2001 From: Kyle Roche Date: Mon, 3 Jun 2024 17:20:21 -0700 Subject: [PATCH 03/11] added extra doc note --- docs/griptape-framework/drivers/event-listener-drivers.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/griptape-framework/drivers/event-listener-drivers.md b/docs/griptape-framework/drivers/event-listener-drivers.md index 4134c4564..6e8f59b22 100644 --- a/docs/griptape-framework/drivers/event-listener-drivers.md +++ b/docs/griptape-framework/drivers/event-listener-drivers.md @@ -214,6 +214,9 @@ agent.run("Analyze the pros and cons of remote work vs. office work") ``` ### Pusher Event Listener Driver +!!! info + This driver requires the `drivers-event-listener-pusher` [extra](../index.md#extras). + The [PusherEventListenerDriver](../../reference/griptape/drivers/event_listener/pusher_event_listener_driver.md) sends Events to [Pusher](https://pusher.com). ```python From 889338e384455b2bf4895701c18e1111a951f6e0 Mon Sep 17 00:00:00 2001 From: Kyle Roche Date: Mon, 3 Jun 2024 17:28:33 -0700 Subject: [PATCH 04/11] fixed deps --- poetry.lock | 72 +++++++++++++++++++++++++++++++++++++++++++++++--- pyproject.toml | 1 + 2 files changed, 70 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 40f57243e..82a265b31 100644 --- a/poetry.lock +++ b/poetry.lock @@ -2974,6 +2974,22 @@ files = [ [package.dependencies] typing-extensions = {version = ">=4.1.0", markers = "python_version < \"3.12\""} +[[package]] +name = "ndg-httpsclient" +version = "0.5.1" +description = "Provides enhanced HTTPS support for httplib and urllib2 using PyOpenSSL" +optional = true +python-versions = ">=2.7,<3.0.dev0 || >=3.4.dev0" +files = [ + {file = "ndg_httpsclient-0.5.1-py2-none-any.whl", hash = "sha256:d2c7225f6a1c6cf698af4ebc962da70178a99bcde24ee6d1961c4f3338130d57"}, + {file = "ndg_httpsclient-0.5.1-py3-none-any.whl", hash = "sha256:dd174c11d971b6244a891f7be2b32ca9853d3797a72edb34fa5d7b07d8fff7d4"}, + {file = "ndg_httpsclient-0.5.1.tar.gz", hash = "sha256:d72faed0376ab039736c2ba12e30695e2788c4aa569c9c3e3d72131de2592210"}, +] + +[package.dependencies] +pyasn1 = ">=0.1.1" +PyOpenSSL = "*" + [[package]] name = "networkx" version = "3.2.1" @@ -3747,6 +3763,30 @@ files = [ [package.extras] tests = ["pytest"] +[[package]] +name = "pusher" +version = "3.3.2" +description = "A Python library to interract with the Pusher Channels API" +optional = true +python-versions = "*" +files = [ + {file = "pusher-3.3.2-py2.py3-none-any.whl", hash = "sha256:4ae2d2dc77eb28043da042796992b8b41454f458c4d8c8e151f7498f2c4374c7"}, + {file = "pusher-3.3.2.tar.gz", hash = "sha256:14f412c8e26562aaf663a114951792fefae01f0d220dac84971f926404620760"}, +] + +[package.dependencies] +ndg-httpsclient = "*" +pyasn1 = "*" +pynacl = "*" +pyopenssl = "*" +requests = ">=2.3.0" +six = "*" +urllib3 = "*" + +[package.extras] +aiohttp = ["aiohttp (>=0.20.0)"] +tornado = ["tornado (>=5.0.0)"] + [[package]] name = "py-partiql-parser" version = "0.5.0" @@ -3996,6 +4036,32 @@ snappy = ["python-snappy"] test = ["pytest (>=7)"] zstd = ["zstandard"] +[[package]] +name = "pynacl" +version = "1.5.0" +description = "Python binding to the Networking and Cryptography (NaCl) library" +optional = true +python-versions = ">=3.6" +files = [ + {file = "PyNaCl-1.5.0-cp36-abi3-macosx_10_10_universal2.whl", hash = "sha256:401002a4aaa07c9414132aaed7f6836ff98f59277a234704ff66878c2ee4a0d1"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.manylinux_2_24_aarch64.whl", hash = "sha256:52cb72a79269189d4e0dc537556f4740f7f0a9ec41c1322598799b0bdad4ef92"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a36d4a9dda1f19ce6e03c9a784a2921a4b726b02e1c736600ca9c22029474394"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl", hash = "sha256:0c84947a22519e013607c9be43706dd42513f9e6ae5d39d3613ca1e142fba44d"}, + {file = "PyNaCl-1.5.0-cp36-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06b8f6fa7f5de8d5d2f7573fe8c863c051225a27b61e6860fd047b1775807858"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a422368fc821589c228f4c49438a368831cb5bbc0eab5ebe1d7fac9dded6567b"}, + {file = "PyNaCl-1.5.0-cp36-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:61f642bf2378713e2c2e1de73444a3778e5f0a38be6fee0fe532fe30060282ff"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win32.whl", hash = "sha256:e46dae94e34b085175f8abb3b0aaa7da40767865ac82c928eeb9e57e1ea8a543"}, + {file = "PyNaCl-1.5.0-cp36-abi3-win_amd64.whl", hash = "sha256:20f42270d27e1b6a29f54032090b972d97f0a1b0948cc52392041ef7831fee93"}, + {file = "PyNaCl-1.5.0.tar.gz", hash = "sha256:8ac7448f09ab85811607bdd21ec2464495ac8b7c66d146bf545b0f08fb9220ba"}, +] + +[package.dependencies] +cffi = ">=1.4.1" + +[package.extras] +docs = ["sphinx (>=1.6.5)", "sphinx-rtd-theme"] +tests = ["hypothesis (>=3.27.0)", "pytest (>=3.2.1,!=3.3.0)"] + [[package]] name = "pyopenssl" version = "24.1.0" @@ -5995,7 +6061,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "google-generativeai", "mail-parser", "markdownify", "marqo", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-google = ["google-generativeai"] @@ -6003,7 +6069,7 @@ drivers-embedding-huggingface = ["huggingface-hub", "transformers"] drivers-embedding-voyageai = ["voyageai"] drivers-event-listener-amazon-iot = ["boto3"] drivers-event-listener-amazon-sqs = ["boto3"] -drivers-event-listener-pusher = [] +drivers-event-listener-pusher = ["pusher"] drivers-memory-conversation-amazon-dynamodb = ["boto3"] drivers-memory-conversation-redis = ["redis"] drivers-prompt-amazon-bedrock = ["anthropic", "boto3"] @@ -6034,4 +6100,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "8335891edd5a6a312ada0ec78ad29ed31783b0c1f01382293ffec49e82c66354" +content-hash = "f1c7f7b21eea9a3bb789a1d220e8d2f323f5769aa076df2d723e0594458864a0" diff --git a/pyproject.toml b/pyproject.toml index 97762f3ed..f9b4d1ba7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -53,6 +53,7 @@ markdownify = {version = "^0.11.6", optional = true} voyageai = {version = "^0.2.1", optional = true} elevenlabs = {version = "^1.1.2", optional = true} torch = {version = "^2.3.0", optional = true} +pusher = {version = "^3.3.2", optional = true} # loaders pandas = {version = "^1.3", optional = true} From e58f65708d0c3f3b25a6f2fd91520d1ca4627cbe Mon Sep 17 00:00:00 2001 From: Kyle Roche Date: Mon, 3 Jun 2024 20:46:53 -0700 Subject: [PATCH 05/11] pyright --- griptape/drivers/event_listener/pusher_event_listener_driver.py | 2 +- .../drivers/event_listener/test_pusher_event_listener_driver.py | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/griptape/drivers/event_listener/pusher_event_listener_driver.py b/griptape/drivers/event_listener/pusher_event_listener_driver.py index 9aefb5a3c..8be054961 100644 --- a/griptape/drivers/event_listener/pusher_event_listener_driver.py +++ b/griptape/drivers/event_listener/pusher_event_listener_driver.py @@ -1,7 +1,7 @@ from __future__ import annotations import json -from typing import TYPE_CHECKING, Any +from typing import TYPE_CHECKING from attrs import define, field from griptape.drivers.event_listener.base_event_listener_driver import BaseEventListenerDriver diff --git a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py index 5d1548692..1e7bb32b7 100644 --- a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py @@ -2,7 +2,6 @@ from tests.mocks.mock_event import MockEvent from griptape.drivers.event_listener.pusher_event_listener_driver import PusherEventListenerDriver -@mock_iotdata class TestPusherEventListenerDriver: @fixture() From 3e7b7b74c681ece21872b59f087466a1a7ec085d Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 4 Jun 2024 08:53:45 -0700 Subject: [PATCH 06/11] Clean up class, implement batch --- .../pusher_event_listener_driver.py | 45 ++++++++++--------- .../test_pusher_event_listener_driver.py | 6 +-- 2 files changed, 26 insertions(+), 25 deletions(-) diff --git a/griptape/drivers/event_listener/pusher_event_listener_driver.py b/griptape/drivers/event_listener/pusher_event_listener_driver.py index 8be054961..d41b679d7 100644 --- a/griptape/drivers/event_listener/pusher_event_listener_driver.py +++ b/griptape/drivers/event_listener/pusher_event_listener_driver.py @@ -1,9 +1,13 @@ from __future__ import annotations -import json from typing import TYPE_CHECKING -from attrs import define, field -from griptape.drivers.event_listener.base_event_listener_driver import BaseEventListenerDriver +from attrs import define, field, Factory +from griptape.drivers import BaseEventListenerDriver +from griptape.utils import import_optional_dependency + +if TYPE_CHECKING: + from pusher import Pusher + @define class PusherEventListenerDriver(BaseEventListenerDriver): @@ -11,28 +15,25 @@ class PusherEventListenerDriver(BaseEventListenerDriver): key: str = field(kw_only=True) secret: str = field(kw_only=True) cluster: str = field(kw_only=True) - - # message specific channel: str = field(kw_only=True) event_name: str = field(kw_only=True) - - if TYPE_CHECKING: - import pusher + pusher_client: Pusher = field( + default=Factory( + lambda self: import_optional_dependency("pusher").Pusher( + app_id=self.app_id, key=self.key, secret=self.secret, cluster=self.cluster, ssl=True + ), + takes_self=True, + ), + kw_only=True, + ) def try_publish_event_payload_batch(self, event_payload_batch: list[dict]) -> None: - pass + data = [ + {"channel": self.channel, "name": self.event_name, "data": event_payload} + for event_payload in event_payload_batch + ] - def try_publish_event_payload(self, event_payload: dict) -> None: - pusher_client = pusher.Pusher( - app_id=self.app_id, - key=self.key, - secret=self.secret, - cluster=self.cluster, - ssl=True - ) + self.pusher_client.trigger_batch(data) - pusher_client.trigger( - channels=self.channel, - event_name=self.event_name, - data=json.dumps(event_payload) - ) \ No newline at end of file + def try_publish_event_payload(self, event_payload: dict) -> None: + self.pusher_client.trigger(channels=self.channel, event_name=self.event_name, data=event_payload) diff --git a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py index 1e7bb32b7..d56983ce6 100644 --- a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py @@ -2,8 +2,8 @@ from tests.mocks.mock_event import MockEvent from griptape.drivers.event_listener.pusher_event_listener_driver import PusherEventListenerDriver -class TestPusherEventListenerDriver: +class TestPusherEventListenerDriver: @fixture() def driver(self): return PusherEventListenerDriver( @@ -11,8 +11,8 @@ def driver(self): key="test-key", secret="test-secret", cluster="test-cluster", - channel='test-channel', - event_name='test-event' + channel="test-channel", + event_name="test-event", ) def test_init(self, driver): From c1de467505777e4d55e83b42f7238811433adb32 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 4 Jun 2024 08:58:37 -0700 Subject: [PATCH 07/11] Fix tests --- griptape/drivers/__init__.py | 2 ++ .../test_pusher_event_listener_driver.py | 19 ++++++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/griptape/drivers/__init__.py b/griptape/drivers/__init__.py index 6c64756e1..f44602f8b 100644 --- a/griptape/drivers/__init__.py +++ b/griptape/drivers/__init__.py @@ -93,6 +93,7 @@ from .event_listener.webhook_event_listener_driver import WebhookEventListenerDriver from .event_listener.aws_iot_core_event_listener_driver import AwsIotCoreEventListenerDriver from .event_listener.griptape_cloud_event_listener_driver import GriptapeCloudEventListenerDriver +from .event_listener.pusher_event_listener_driver import PusherEventListenerDriver from .file_manager.base_file_manager_driver import BaseFileManagerDriver from .file_manager.local_file_manager_driver import LocalFileManagerDriver @@ -193,6 +194,7 @@ "WebhookEventListenerDriver", "AwsIotCoreEventListenerDriver", "GriptapeCloudEventListenerDriver", + "PusherEventListenerDriver", "BaseFileManagerDriver", "LocalFileManagerDriver", "AmazonS3FileManagerDriver", diff --git a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py index d56983ce6..42d8bf6d7 100644 --- a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py @@ -1,9 +1,18 @@ from pytest import fixture from tests.mocks.mock_event import MockEvent -from griptape.drivers.event_listener.pusher_event_listener_driver import PusherEventListenerDriver +from griptape.drivers import PusherEventListenerDriver +from unittest.mock import Mock class TestPusherEventListenerDriver: + @fixture(autouse=True) + def mock_post(self, mocker): + mock_pusher_client = mocker.patch("pusher.Pusher") + mock_pusher_client.return_value.trigger.return_value = Mock() + mock_pusher_client.return_value.trigger_batch.return_value = Mock() + + return mock_pusher_client + @fixture() def driver(self): return PusherEventListenerDriver( @@ -21,5 +30,13 @@ def test_init(self, driver): def test_try_publish_event_payload(self, driver): driver.try_publish_event_payload(MockEvent().to_dict()) + assert driver.pusher_client.trigger.called_with( + channels="test-channel", event_name="test-event", data=MockEvent().to_dict() + ) + def test_try_publish_event_payload_batch(self, driver): driver.try_publish_event_payload_batch([MockEvent().to_dict() for _ in range(3)]) + + assert driver.pusher_client.trigger_batch.called_with( + [{"channel": "test-channel", "name": "test-event", "data": MockEvent().to_dict()} for _ in range(3)] + ) From 1d4dac41bc093a71b0bc4698c7e17815c0bc80c9 Mon Sep 17 00:00:00 2001 From: Kyle Roche Date: Tue, 4 Jun 2024 09:12:09 -0700 Subject: [PATCH 08/11] update changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index cf0d8ed36..54532a017 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `AudioTranscriptionTask` and `AudioTranscriptionClient` for transcribing audio content in Structures. - `OpenAiAudioTranscriptionDriver` for integration with OpenAI's speech-to-text models, including Whisper. - Parameter `env` to `BaseStructureRunDriver` to set environment variables for a Structure Run. +- `PusherEventListenerDriver` to enable listening of framework events over a Pusher WebSocket. ### Changed - **BREAKING**: Updated OpenAI-based image query drivers to remove Vision from the name. From 45a39cd7bbf40ba5648fe34bc24a6a760e77cc44 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 4 Jun 2024 09:22:10 -0700 Subject: [PATCH 09/11] Update changelog --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 54532a017..62a9f49ff 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - `AudioTranscriptionTask` and `AudioTranscriptionClient` for transcribing audio content in Structures. - `OpenAiAudioTranscriptionDriver` for integration with OpenAI's speech-to-text models, including Whisper. - Parameter `env` to `BaseStructureRunDriver` to set environment variables for a Structure Run. -- `PusherEventListenerDriver` to enable listening of framework events over a Pusher WebSocket. +- `PusherEventListenerDriver` to enable sending of framework events over a Pusher WebSocket. ### Changed - **BREAKING**: Updated OpenAI-based image query drivers to remove Vision from the name. From b18108fe4f5a2ec52a0d89b937f8a33d723c5ea2 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 4 Jun 2024 09:23:40 -0700 Subject: [PATCH 10/11] Regenerate poetry.lock --- poetry.lock | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/poetry.lock b/poetry.lock index 82a265b31..7d78e319e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "aiohttp" @@ -6061,7 +6061,7 @@ docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.link testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [extras] -all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "google-generativeai", "mail-parser", "markdownify", "marqo", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] +all = ["anthropic", "beautifulsoup4", "boto3", "cohere", "elevenlabs", "filetype", "google-generativeai", "mail-parser", "markdownify", "marqo", "opensearch-py", "pandas", "pgvector", "pillow", "pinecone-client", "playwright", "psycopg2-binary", "pusher", "pymongo", "pypdf", "redis", "snowflake-sqlalchemy", "sqlalchemy-redshift", "torch", "trafilatura", "transformers", "voyageai"] drivers-embedding-amazon-bedrock = ["boto3"] drivers-embedding-amazon-sagemaker = ["boto3"] drivers-embedding-google = ["google-generativeai"] @@ -6100,4 +6100,4 @@ loaders-pdf = ["pypdf"] [metadata] lock-version = "2.0" python-versions = "^3.9" -content-hash = "f1c7f7b21eea9a3bb789a1d220e8d2f323f5769aa076df2d723e0594458864a0" +content-hash = "b035e9419f6dbc25ee6663b81c49730946b9990641e14aa656080915cb4735b2" From c8bc783730e693c7f1c7e3ac42e0cb2d7ad9d8d8 Mon Sep 17 00:00:00 2001 From: Collin Dutter Date: Tue, 4 Jun 2024 09:44:51 -0700 Subject: [PATCH 11/11] Fix tests --- .../test_pusher_event_listener_driver.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py index 42d8bf6d7..6f0636b5c 100644 --- a/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py +++ b/tests/unit/drivers/event_listener/test_pusher_event_listener_driver.py @@ -28,15 +28,15 @@ def test_init(self, driver): assert driver def test_try_publish_event_payload(self, driver): - driver.try_publish_event_payload(MockEvent().to_dict()) + data = MockEvent().to_dict() + driver.try_publish_event_payload(data) - assert driver.pusher_client.trigger.called_with( - channels="test-channel", event_name="test-event", data=MockEvent().to_dict() - ) + driver.pusher_client.trigger.assert_called_with(channels="test-channel", event_name="test-event", data=data) def test_try_publish_event_payload_batch(self, driver): - driver.try_publish_event_payload_batch([MockEvent().to_dict() for _ in range(3)]) + data = [MockEvent().to_dict() for _ in range(3)] + driver.try_publish_event_payload_batch(data) - assert driver.pusher_client.trigger_batch.called_with( - [{"channel": "test-channel", "name": "test-event", "data": MockEvent().to_dict()} for _ in range(3)] + driver.pusher_client.trigger_batch.assert_called_with( + [{"channel": "test-channel", "name": "test-event", "data": data[i]} for i in range(3)] )