From d330f614b981567122ecdb7ec97288dc206ba165 Mon Sep 17 00:00:00 2001 From: dvonthenen Date: Wed, 6 Dec 2023 19:01:53 -0800 Subject: [PATCH] Make All Async/Await Deprecated --- deepgram/__init__.py | 10 +- deepgram/client.py | 39 +- ...act_client.py => abstract_async_client.py} | 2 +- deepgram/clients/abstract_sync_client.py | 83 ++++ deepgram/clients/listen.py | 35 +- deepgram/clients/live/client.py | 4 +- deepgram/clients/live/helpers.py | 3 - .../v1/{legacy_client.py => async_client.py} | 20 +- deepgram/clients/manage/client.py | 10 + deepgram/clients/manage/v1/async_client.py | 429 ++++++++++++++++++ deepgram/clients/manage/v1/client.py | 112 ++--- deepgram/clients/onprem/client.py | 10 + deepgram/clients/onprem/v1/async_client.py | 87 ++++ deepgram/clients/onprem/v1/client.py | 22 +- deepgram/clients/prerecorded/client.py | 10 + .../clients/prerecorded/v1/async_client.py | 226 +++++++++ deepgram/clients/prerecorded/v1/client.py | 22 +- examples/README.md | 29 ++ examples/manage/async_invitations/main.py | 71 +++ examples/manage/balances/main.py | 11 +- examples/manage/invitations/main.py | 19 +- examples/manage/keys/main.py | 19 +- examples/manage/members/main.py | 13 +- examples/manage/projects/main.py | 19 +- examples/manage/scopes/main.py | 23 +- examples/manage/usage/main.py | 15 +- examples/prerecorded/async_url/main.py | 45 ++ examples/prerecorded/file/main.py | 13 +- examples/prerecorded/url/main.py | 13 +- examples/streaming/async_http/main.py | 59 +++ examples/streaming/http/main.py | 101 +++-- 31 files changed, 1355 insertions(+), 219 deletions(-) rename deepgram/clients/{abstract_client.py => abstract_async_client.py} (99%) create mode 100644 deepgram/clients/abstract_sync_client.py rename deepgram/clients/live/v1/{legacy_client.py => async_client.py} (90%) create mode 100644 deepgram/clients/manage/v1/async_client.py create mode 100644 deepgram/clients/onprem/v1/async_client.py create mode 100644 deepgram/clients/prerecorded/v1/async_client.py create mode 100644 examples/README.md create mode 100644 examples/manage/async_invitations/main.py create mode 100644 examples/prerecorded/async_url/main.py create mode 100644 examples/streaming/async_http/main.py diff --git a/deepgram/__init__.py b/deepgram/__init__.py index df5054ed..6ac481fd 100644 --- a/deepgram/__init__.py +++ b/deepgram/__init__.py @@ -11,11 +11,18 @@ # live from .clients.live.enums import LiveTranscriptionEvents -from .clients.live.client import LiveClient, LegacyLiveClient, LiveOptions +from .clients.live.client import LiveClient, AsyncLiveClient, LiveOptions + +# onprem +from .clients.onprem.client import ( + OnPremClient, + AsyncOnPremClient, +) # prerecorded from .clients.prerecorded.client import ( PreRecordedClient, + AsyncPreRecordedClient, PrerecordedOptions, PrerecordedSource, FileSource, @@ -25,6 +32,7 @@ # manage from .clients.manage.client import ( ManageClient, + AsyncManageClient, ProjectOptions, KeyOptions, ScopeOptions, diff --git a/deepgram/client.py b/deepgram/client.py index 7751cf42..670672e5 100644 --- a/deepgram/client.py +++ b/deepgram/client.py @@ -7,11 +7,18 @@ import logging, verboselogs import os -from .clients.live.client import LiveOptions -from .clients.prerecorded.client import PrerecordedOptions -from .clients.listen import ListenClient, PreRecordedClient -from .clients.manage.client import ManageClient +from .clients.listen import ( + ListenClient, + PreRecordedClient, + AsyncLiveClient, + AsyncPreRecordedClient, + PrerecordedOptions, + LiveOptions, +) from .clients.onprem.client import OnPremClient +from .clients.onprem.v1.async_client import AsyncOnPremClient +from .clients.manage.client import ManageClient +from .clients.manage.v1.async_client import AsyncManageClient from .options import DeepgramClientOptions from .errors import DeepgramApiKeyError, DeepgramModuleError @@ -66,10 +73,18 @@ def listen(self): def manage(self): return self.Version(self.config, "manage") + @property + def asyncmanage(self): + return self.Version(self.config, "asyncmanage") + @property def onprem(self): return self.Version(self.config, "onprem") + @property + def asynconprem(self): + return self.Version(self.config, "asynconprem") + # INTERNAL CLASSES class Version: def __init__(self, config, parent: str): @@ -99,19 +114,33 @@ def v(self, version: str = ""): self.logger.debug("Version.v LEAVE") raise DeepgramModuleError("Invalid module version") + parent = "" + fileName = "" className = "" match self.parent: case "manage": + parent = "manage" + fileName = "client" className = "ManageClient" + case "asyncmanage": + parent = "manage" + fileName = "async_client" + className = "AsyncManageClient" case "onprem": + parent = "onprem" + fileName = "client" className = "OnPremClient" + case "asynconprem": + parent = "onprem" + fileName = "async_client" + className = "AsyncOnPremClient" case _: self.logger.error("parent unknown: %s", self.parent) self.logger.debug("Version.v LEAVE") raise DeepgramModuleError("Invalid parent type") # create class path - path = f"deepgram.clients.{self.parent}.v{version}.client" + path = f"deepgram.clients.{parent}.v{version}.{fileName}" self.logger.info("path: %s", path) self.logger.info("className: %s", className) diff --git a/deepgram/clients/abstract_client.py b/deepgram/clients/abstract_async_client.py similarity index 99% rename from deepgram/clients/abstract_client.py rename to deepgram/clients/abstract_async_client.py index a71f46b3..d8b53af1 100644 --- a/deepgram/clients/abstract_client.py +++ b/deepgram/clients/abstract_async_client.py @@ -9,7 +9,7 @@ from .errors import DeepgramError, DeepgramApiError, DeepgramUnknownApiError -class AbstractRestfulClient: +class AbstractAsyncRestClient: """ An abstract base class for a RESTful HTTP client. diff --git a/deepgram/clients/abstract_sync_client.py b/deepgram/clients/abstract_sync_client.py new file mode 100644 index 00000000..9f0a4fb9 --- /dev/null +++ b/deepgram/clients/abstract_sync_client.py @@ -0,0 +1,83 @@ +# Copyright 2023 Deepgram SDK contributors. All Rights Reserved. +# Use of this source code is governed by a MIT license that can be found in the LICENSE file. +# SPDX-License-Identifier: MIT + +import httpx +import json + +from ..options import DeepgramClientOptions +from .errors import DeepgramError, DeepgramApiError, DeepgramUnknownApiError + + +class AbstractSyncRestClient: + """ + An abstract base class for a RESTful HTTP client. + + This class provides common HTTP methods (GET, POST, PUT, PATCH, DELETE) for making asynchronous HTTP requests. + It handles error responses and provides basic JSON parsing. + + Args: + url (Dict[str, str]): The base URL for the RESTful API, including any path segments. + headers (Optional[Dict[str, Any]]): Optional HTTP headers to include in requests. + + Attributes: + url (Dict[str, str]): The base URL for the RESTful API. + client (httpx.AsyncClient): An asynchronous HTTP client for making requests. + headers (Optional[Dict[str, Any]]): Optional HTTP headers to include in requests. + + Exceptions: + DeepgramApiError: Raised for known API errors. + DeepgramUnknownApiError: Raised for unknown API errors. + """ + + def __init__(self, config: DeepgramClientOptions): + if config is None: + raise DeepgramError("Config are required") + + self.config = config + + def get(self, url: str, options=None): + return self._handle_request( + "GET", url, params=options, headers=self.config.headers + ) + + def post(self, url: str, options=None, **kwargs): + return self._handle_request( + "POST", url, params=options, headers=self.config.headers, **kwargs + ) + + def put(self, url: str, options=None, **kwargs): + return self._handle_request( + "PUT", url, params=options, headers=self.config.headers, **kwargs + ) + + def patch(self, url: str, options=None, **kwargs): + return self._handle_request( + "PATCH", url, params=options, headers=self.config.headers, **kwargs + ) + + def delete(self, url: str): + return self._handle_request("DELETE", url, headers=self.config.headers) + + def _handle_request(self, method, url, **kwargs): + try: + with httpx.Client() as client: + response = client.request(method, url, **kwargs) + response.raise_for_status() + return response.text + except httpx._exceptions.HTTPError as e: + if isinstance(e, httpx.HTTPStatusError): + status_code = e.response.status_code or 500 + try: + json_object = json.loads(e.response.text) + raise DeepgramApiError( + json_object.get("message"), status_code, json.dumps(json_object) + ) from e + except json.decoder.JSONDecodeError: + raise DeepgramUnknownApiError(e.response.text, status_code) from e + except ValueError as e: + raise DeepgramUnknownApiError(e.response.text, status_code) from e + else: + raise + except Exception as e: + raise diff --git a/deepgram/clients/listen.py b/deepgram/clients/listen.py index 8bbfc49d..b0ad987e 100644 --- a/deepgram/clients/listen.py +++ b/deepgram/clients/listen.py @@ -7,26 +7,37 @@ from ..options import DeepgramClientOptions -from .prerecorded.client import PreRecordedClient -from .live.client import LiveClient, LegacyLiveClient +from .prerecorded.client import ( + PreRecordedClient, + AsyncPreRecordedClient, + PrerecordedOptions, +) +from .live.client import LiveClient, AsyncLiveClient, LiveOptions from .errors import DeepgramModuleError class ListenClient: def __init__(self, config: DeepgramClientOptions): + self.logger = logging.getLogger(__name__) + self.logger.addHandler(logging.StreamHandler()) + self.logger.setLevel(config.verbose) self.config = config @property def prerecorded(self): return self.Version(self.config, "prerecorded") + @property + def asyncprerecorded(self): + return self.Version(self.config, "asyncprerecorded") + @property def live(self): return self.Version(self.config, "live") @property - def legacylive(self): - return LegacyLiveClient(self.config) + def asynclive(self): + return self.Version(self.config, "asynclive") # INTERNAL CLASSES class Version: @@ -57,19 +68,33 @@ def v(self, version: str = ""): self.logger.debug("Version.v LEAVE") raise DeepgramModuleError("Invalid module version") + parent = "" + fileName = "" className = "" match self.parent: case "live": + parent = "live" + fileName = "client" className = "LiveClient" + case "asynclive": + parent = "live" + fileName = "async_client" + className = "AsyncLiveClient" case "prerecorded": + parent = "prerecorded" + fileName = "client" className = "PreRecordedClient" + case "asyncprerecorded": + parent = "prerecorded" + fileName = "async_client" + className = "AsyncPreRecordedClient" case _: self.logger.error("parent unknown: %s", self.parent) self.logger.debug("Version.v LEAVE") raise DeepgramModuleError("Invalid parent type") # create class path - path = f"deepgram.clients.{self.parent}.v{version}.client" + path = f"deepgram.clients.{parent}.v{version}.{fileName}" self.logger.info("path: %s", path) self.logger.info("className: %s", className) diff --git a/deepgram/clients/live/client.py b/deepgram/clients/live/client.py index 36eb029b..782f5119 100644 --- a/deepgram/clients/live/client.py +++ b/deepgram/clients/live/client.py @@ -3,7 +3,7 @@ # SPDX-License-Identifier: MIT from .v1.client import LiveClient as LiveClientLatest -from .v1.legacy_client import LegacyLiveClient as LegacyLiveClientLatest +from .v1.async_client import AsyncLiveClient as AsyncLiveClientLatest from .v1.options import LiveOptions as LiveOptionsLatest """ @@ -25,7 +25,7 @@ def __init__(self, config): super().__init__(config) -class LegacyLiveClient(LegacyLiveClientLatest): +class AsyncLiveClient(AsyncLiveClientLatest): """ Please see LiveClientLatest for details """ diff --git a/deepgram/clients/live/helpers.py b/deepgram/clients/live/helpers.py index 0017f3d1..c1db8482 100644 --- a/deepgram/clients/live/helpers.py +++ b/deepgram/clients/live/helpers.py @@ -3,9 +3,6 @@ # SPDX-License-Identifier: MIT from urllib.parse import urlparse, urlunparse, parse_qs, urlencode -from typing import Dict - -from .errors import DeepgramError def append_query_params(url, params): diff --git a/deepgram/clients/live/v1/legacy_client.py b/deepgram/clients/live/v1/async_client.py similarity index 90% rename from deepgram/clients/live/v1/legacy_client.py rename to deepgram/clients/live/v1/async_client.py index ecbcb68e..f574a8ba 100644 --- a/deepgram/clients/live/v1/legacy_client.py +++ b/deepgram/clients/live/v1/async_client.py @@ -14,7 +14,7 @@ from .options import LiveOptions -class LegacyLiveClient: +class AsyncLiveClient: """ Client for interacting with Deepgram's live transcription services over WebSockets. @@ -51,7 +51,7 @@ def __init__(self, config: DeepgramClientOptions): self.websocket_url = convert_to_websocket_url(self.config.url, self.endpoint) async def __call__(self, options: LiveOptions = None): - self.logger.debug("LegacyLiveClient.__call__ ENTER") + self.logger.debug("AsyncLiveClient.__call__ ENTER") self.logger.info("options: %s", options) self.options = options @@ -65,12 +65,12 @@ async def __call__(self, options: LiveOptions = None): asyncio.create_task(self._start()) self.logger.notice("__call__ succeeded") - self.logger.debug("LegacyLiveClient.__call__ LEAVE") + self.logger.debug("AsyncLiveClient.__call__ LEAVE") return self except websockets.ConnectionClosed as e: await self._emit(LiveTranscriptionEvents.Close, e.code) self.logger.notice("exception: websockets.ConnectionClosed") - self.logger.debug("LegacyLiveClient.__call__ LEAVE") + self.logger.debug("AsyncLiveClient.__call__ LEAVE") def on(self, event, handler): # registers event handlers for specific events if event in LiveTranscriptionEvents and callable(handler): @@ -83,7 +83,7 @@ async def _emit( handler(*args, **kwargs) async def _start(self) -> None: - self.logger.debug("LegacyLiveClient._start ENTER") + self.logger.debug("AsyncLiveClient._start ENTER") async for message in self._socket: try: @@ -113,20 +113,20 @@ async def _start(self) -> None: except json.JSONDecodeError as e: await self._emit(LiveTranscriptionEvents.Error, e.code) self.logger.error("exception: json.JSONDecodeError: %s", str(e)) - self.logger.debug("LegacyLiveClient._start LEAVE") + self.logger.debug("AsyncLiveClient._start LEAVE") async def send(self, data): - self.logger.spam("LegacyLiveClient.send ENTER") + self.logger.spam("AsyncLiveClient.send ENTER") self.logger.spam("data: %s", data) if self._socket: await self._socket.send(data) self.logger.spam("data sent") - self.logger.spam("LegacyLiveClient.send LEAVE") + self.logger.spam("AsyncLiveClient.send LEAVE") async def finish(self): - self.logger.debug("LegacyLiveClient.finish LEAVE") + self.logger.debug("AsyncLiveClient.finish LEAVE") if self._socket: self.logger.notice("send CloseStream...") @@ -136,7 +136,7 @@ async def finish(self): self.logger.notice("socket.wait_closed succeeded") self.logger.notice("finish succeeded") - self.logger.debug("LegacyLiveClient.finish LEAVE") + self.logger.debug("AsyncLiveClient.finish LEAVE") async def _socket_connect(websocket_url, headers): diff --git a/deepgram/clients/manage/client.py b/deepgram/clients/manage/client.py index 410c0dba..5e4f1eba 100644 --- a/deepgram/clients/manage/client.py +++ b/deepgram/clients/manage/client.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: MIT from .v1.client import ManageClient as ManageClientLatest +from .v1.async_client import AsyncManageClient as AsyncManageClientLatest from .v1.options import ( ProjectOptions as ProjectOptionsLatest, KeyOptions as KeyOptionsLatest, @@ -54,3 +55,12 @@ class ManageClient(ManageClientLatest): def __init__(self, config): super().__init__(config) + + +class AsyncManageClient(AsyncManageClientLatest): + """ + Please see AsyncManageClientLatest for details + """ + + def __init__(self, config): + super().__init__(config) diff --git a/deepgram/clients/manage/v1/async_client.py b/deepgram/clients/manage/v1/async_client.py new file mode 100644 index 00000000..3e5c4726 --- /dev/null +++ b/deepgram/clients/manage/v1/async_client.py @@ -0,0 +1,429 @@ +# Copyright 2023 Deepgram SDK contributors. All Rights Reserved. +# Use of this source code is governed by a MIT license that can be found in the LICENSE file. +# SPDX-License-Identifier: MIT + +import logging, verboselogs + +from ....options import DeepgramClientOptions +from ...abstract_async_client import AbstractAsyncRestClient + +from .response import ( + Project, + ProjectsResponse, + Message, + KeysResponse, + KeyResponse, + Key, + MembersResponse, + ScopesResponse, + InvitesResponse, + UsageRequestsResponse, + UsageRequest, + UsageSummaryResponse, + UsageFieldsResponse, + BalancesResponse, + Balance, +) +from .options import ( + ProjectOptions, + KeyOptions, + ScopeOptions, + InviteOptions, + UsageRequestOptions, + UsageSummaryOptions, + UsageFieldsOptions, +) + + +class AsyncManageClient(AbstractAsyncRestClient): + """ + A client for managing Deepgram projects and associated resources via the Deepgram API. + + This class provides methods for performing various operations on Deepgram projects, including: + - Retrieving project details + - Updating project settings + - Managing project members and scopes + - Handling project invitations + - Monitoring project usage and balances + + Args: + config (DeepgramClientOptions): all the options for the client. + + Attributes: + url (str): The base URL of the Deepgram API. + headers (dict): Optional HTTP headers to include in requests. + endpoint (str): The API endpoint for managing projects. + + Raises: + DeepgramApiError: Raised for known API errors. + DeepgramUnknownApiError: Raised for unknown API errors. + Exception: For any other unexpected exceptions. + """ + + def __init__(self, config: DeepgramClientOptions): + self.logger = logging.getLogger(__name__) + self.logger.addHandler(logging.StreamHandler()) + self.logger.setLevel(config.verbose) + self.config = config + self.endpoint = "v1/projects" + super().__init__(config) + + # projects + async def list_projects(self): + return self.get_projects() + + async def get_projects(self): + self.logger.debug("ManageClient.get_projects ENTER") + url = f"{self.config.url}/{self.endpoint}" + self.logger.info("url: %s", url) + json = await self.get(url) + self.logger.info("json: %s", json) + res = ProjectsResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_projects succeeded") + self.logger.debug("ManageClient.get_projects LEAVE") + return res + + async def get_project(self, project_id: str): + self.logger.debug("ManageClient.get_project ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = Project.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_project succeeded") + self.logger.debug("ManageClient.get_project LEAVE") + return res + + async def update_project_option(self, project_id: str, options: ProjectOptions): + self.logger.debug("ManageClient.update_project_option ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.patch(url, json=options) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("update_project_option succeeded") + self.logger.debug("ManageClient.update_project_option LEAVE") + return res + + async def update_project(self, project_id: str, name=""): + self.logger.debug("ManageClient.update_project ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}" + options: ProjectOptions = { + "name": name, + } + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.patch(url, json=options) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("update_project succeeded") + self.logger.debug("ManageClient.update_project LEAVE") + return res + + async def delete_project(self, project_id: str) -> None: + self.logger.debug("ManageClient.delete_project ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}" + json = await self.delete(url) + self.logger.info("json: %s", json) + res = Message.from_json(await self.delete(url)) + self.logger.verbose("result: %s", res) + self.logger.notice("delete_project succeeded") + self.logger.debug("ManageClient.delete_project LEAVE") + return res + + # keys + async def list_keys(self, project_id: str): + return self.get_keys(project_id) + + async def get_keys(self, project_id: str): + self.logger.debug("ManageClient.get_keys ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/keys" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = KeysResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_keys succeeded") + self.logger.debug("ManageClient.get_keys LEAVE") + return res + + async def get_key(self, project_id: str, key_id: str): + self.logger.debug("ManageClient.get_key ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/keys/{key_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("key_id: %s", key_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = KeyResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_key succeeded") + self.logger.debug("ManageClient.get_key LEAVE") + return res + + async def create_key(self, project_id: str, options: KeyOptions): + self.logger.debug("ManageClient.create_key ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/keys" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.post(url, json=options) + self.logger.info("json: %s", json) + res = Key.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("create_key succeeded") + self.logger.debug("ManageClient.create_key LEAVE") + return res + + async def delete_key(self, project_id: str, key_id: str) -> None: + self.logger.debug("ManageClient.delete_key ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/keys/{key_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("key_id: %s", key_id) + json = await self.delete(url) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("delete_key succeeded") + self.logger.debug("ManageClient.delete_key LEAVE") + return res + + # members + async def list_members(self, project_id: str): + return self.get_members(project_id) + + async def get_members(self, project_id: str): + self.logger.debug("ManageClient.get_members ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/members" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = MembersResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_members succeeded") + self.logger.debug("ManageClient.get_members LEAVE") + return res + + async def remove_member(self, project_id: str, member_id: str) -> None: + self.logger.debug("ManageClient.remove_member ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/members/{member_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("member_id: %s", member_id) + json = await self.delete(url) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("remove_member succeeded") + self.logger.debug("ManageClient.remove_member LEAVE") + return res + + # scopes + async def get_member_scopes(self, project_id: str, member_id: str): + self.logger.debug("ManageClient.get_member_scopes ENTER") + url = ( + f"{self.config.url}/{self.endpoint}/{project_id}/members/{member_id}/scopes" + ) + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("member_id: %s", member_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = ScopesResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_member_scopes succeeded") + self.logger.debug("ManageClient.get_member_scopes LEAVE") + return res + + async def update_member_scope( + self, project_id: str, member_id: str, options: ScopeOptions + ): + self.logger.debug("ManageClient.update_member_scope ENTER") + url = ( + f"{self.config.url}/{self.endpoint}/{project_id}/members/{member_id}/scopes" + ) + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.put(url, json=options) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("update_member_scope succeeded") + self.logger.debug("ManageClient.update_member_scope LEAVE") + return res + + # invites + async def list_invites(self, project_id: str): + return self.get_invites(project_id) + + async def get_invites(self, project_id: str): + self.logger.debug("ManageClient.get_invites ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/invites" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = InvitesResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_invites succeeded") + self.logger.debug("ManageClient.get_invites LEAVE") + return res + + async def send_invite_options(self, project_id: str, options: InviteOptions): + self.logger.debug("ManageClient.send_invite_options ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/invites" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.post(url, json=options) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("send_invite_options succeeded") + self.logger.debug("ManageClient.send_invite_options LEAVE") + return res + + async def send_invite(self, project_id: str, email: str, scope="member"): + self.logger.debug("ManageClient.send_invite ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/invites" + options: InviteOptions = { + "email": email, + "scope": scope, + } + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.post(url, json=options) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("send_invite succeeded") + self.logger.debug("ManageClient.send_invite LEAVE") + return res + + async def delete_invite(self, project_id: str, email: str): + self.logger.debug("ManageClient.delete_invite ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/invites/{email}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("email: %s", email) + json = await self.delete(url) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("delete_invite succeeded") + self.logger.debug("ManageClient.delete_invite LEAVE") + return res + + async def leave_project(self, project_id: str): + self.logger.debug("ManageClient.leave_project ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/leave" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + json = await self.delete(url) + self.logger.info("json: %s", json) + res = Message.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("leave_project succeeded") + self.logger.debug("ManageClient.leave_project LEAVE") + return res + + # usage + async def get_usage_requests(self, project_id: str, options: UsageRequestOptions): + self.logger.debug("ManageClient.get_usage_requests ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/requests" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.get(url, options) + self.logger.info("json: %s", json) + res = UsageRequestsResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_usage_requests succeeded") + self.logger.debug("ManageClient.get_usage_requests LEAVE") + return res + + async def get_usage_request(self, project_id: str, request_id: str): + self.logger.debug("ManageClient.get_usage_request ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/requests/{request_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("request_id: %s", request_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = UsageRequest.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_usage_request succeeded") + self.logger.debug("ManageClient.get_usage_request LEAVE") + return res + + async def get_usage_summary(self, project_id: str, options: UsageSummaryOptions): + self.logger.debug("ManageClient.get_usage_summary ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/usage" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.get(url, options) + self.logger.info("json: %s", json) + res = UsageSummaryResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_usage_summary succeeded") + self.logger.debug("ManageClient.get_usage_summary LEAVE") + return res + + async def get_usage_fields(self, project_id: str, options: UsageFieldsOptions): + self.logger.debug("ManageClient.get_usage_fields ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/usage/fields" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + json = await self.get(url, options) + self.logger.info("json: %s", json) + res = UsageFieldsResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_usage_fields succeeded") + self.logger.debug("ManageClient.get_usage_fields LEAVE") + return res + + # balances + async def list_balances(self, project_id: str): + return self.get_balances(project_id) + + async def get_balances(self, project_id: str): + self.logger.debug("ManageClient.get_balances ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/balances" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = BalancesResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_balances succeeded") + self.logger.debug("ManageClient.get_balances LEAVE") + return res + + async def get_balance(self, project_id: str, balance_id: str): + self.logger.debug("ManageClient.get_balance ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/balances/{balance_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("balance_id: %s", balance_id) + json = await self.get(url) + self.logger.info("json: %s", json) + res = Balance.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("get_balance succeeded") + self.logger.debug("ManageClient.get_balance LEAVE") + return res diff --git a/deepgram/clients/manage/v1/client.py b/deepgram/clients/manage/v1/client.py index 7b3132ef..a60075bf 100644 --- a/deepgram/clients/manage/v1/client.py +++ b/deepgram/clients/manage/v1/client.py @@ -5,7 +5,7 @@ import logging, verboselogs from ....options import DeepgramClientOptions -from ...abstract_client import AbstractRestfulClient +from ...abstract_sync_client import AbstractSyncRestClient from .response import ( Project, @@ -35,7 +35,7 @@ ) -class ManageClient(AbstractRestfulClient): +class ManageClient(AbstractSyncRestClient): """ A client for managing Deepgram projects and associated resources via the Deepgram API. @@ -70,14 +70,14 @@ def __init__(self, config: DeepgramClientOptions): super().__init__(config) # projects - async def list_projects(self): + def list_projects(self): return self.get_projects() - async def get_projects(self): + def get_projects(self): self.logger.debug("ManageClient.get_projects ENTER") url = f"{self.config.url}/{self.endpoint}" self.logger.info("url: %s", url) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = ProjectsResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -85,12 +85,12 @@ async def get_projects(self): self.logger.debug("ManageClient.get_projects LEAVE") return res - async def get_project(self, project_id: str): + def get_project(self, project_id: str): self.logger.debug("ManageClient.get_project ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = Project.from_json(json) self.logger.verbose("result: %s", res) @@ -98,13 +98,13 @@ async def get_project(self, project_id: str): self.logger.debug("ManageClient.get_project LEAVE") return res - async def update_project_option(self, project_id: str, options: ProjectOptions): + def update_project_option(self, project_id: str, options: ProjectOptions): self.logger.debug("ManageClient.update_project_option ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.patch(url, json=options) + json = self.patch(url, json=options) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -112,7 +112,7 @@ async def update_project_option(self, project_id: str, options: ProjectOptions): self.logger.debug("ManageClient.update_project_option LEAVE") return res - async def update_project(self, project_id: str, name=""): + def update_project(self, project_id: str, name=""): self.logger.debug("ManageClient.update_project ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}" options: ProjectOptions = { @@ -121,7 +121,7 @@ async def update_project(self, project_id: str, name=""): self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.patch(url, json=options) + json = self.patch(url, json=options) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -129,27 +129,27 @@ async def update_project(self, project_id: str, name=""): self.logger.debug("ManageClient.update_project LEAVE") return res - async def delete_project(self, project_id: str) -> None: + def delete_project(self, project_id: str) -> None: self.logger.debug("ManageClient.delete_project ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}" - json = await self.delete(url) + json = self.delete(url) self.logger.info("json: %s", json) - res = Message.from_json(await self.delete(url)) + res = Message.from_json(self.delete(url)) self.logger.verbose("result: %s", res) self.logger.notice("delete_project succeeded") self.logger.debug("ManageClient.delete_project LEAVE") return res # keys - async def list_keys(self, project_id: str): + def list_keys(self, project_id: str): return self.get_keys(project_id) - async def get_keys(self, project_id: str): + def get_keys(self, project_id: str): self.logger.debug("ManageClient.get_keys ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/keys" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = KeysResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -157,13 +157,13 @@ async def get_keys(self, project_id: str): self.logger.debug("ManageClient.get_keys LEAVE") return res - async def get_key(self, project_id: str, key_id: str): + def get_key(self, project_id: str, key_id: str): self.logger.debug("ManageClient.get_key ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/keys/{key_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("key_id: %s", key_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = KeyResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -171,13 +171,13 @@ async def get_key(self, project_id: str, key_id: str): self.logger.debug("ManageClient.get_key LEAVE") return res - async def create_key(self, project_id: str, options: KeyOptions): + def create_key(self, project_id: str, options: KeyOptions): self.logger.debug("ManageClient.create_key ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/keys" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.post(url, json=options) + json = self.post(url, json=options) self.logger.info("json: %s", json) res = Key.from_json(json) self.logger.verbose("result: %s", res) @@ -185,13 +185,13 @@ async def create_key(self, project_id: str, options: KeyOptions): self.logger.debug("ManageClient.create_key LEAVE") return res - async def delete_key(self, project_id: str, key_id: str) -> None: + def delete_key(self, project_id: str, key_id: str) -> None: self.logger.debug("ManageClient.delete_key ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/keys/{key_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("key_id: %s", key_id) - json = await self.delete(url) + json = self.delete(url) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -200,15 +200,15 @@ async def delete_key(self, project_id: str, key_id: str) -> None: return res # members - async def list_members(self, project_id: str): + def list_members(self, project_id: str): return self.get_members(project_id) - async def get_members(self, project_id: str): + def get_members(self, project_id: str): self.logger.debug("ManageClient.get_members ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/members" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = MembersResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -216,13 +216,13 @@ async def get_members(self, project_id: str): self.logger.debug("ManageClient.get_members LEAVE") return res - async def remove_member(self, project_id: str, member_id: str) -> None: + def remove_member(self, project_id: str, member_id: str) -> None: self.logger.debug("ManageClient.remove_member ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/members/{member_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("member_id: %s", member_id) - json = await self.delete(url) + json = self.delete(url) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -231,7 +231,7 @@ async def remove_member(self, project_id: str, member_id: str) -> None: return res # scopes - async def get_member_scopes(self, project_id: str, member_id: str): + def get_member_scopes(self, project_id: str, member_id: str): self.logger.debug("ManageClient.get_member_scopes ENTER") url = ( f"{self.config.url}/{self.endpoint}/{project_id}/members/{member_id}/scopes" @@ -239,7 +239,7 @@ async def get_member_scopes(self, project_id: str, member_id: str): self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("member_id: %s", member_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = ScopesResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -247,7 +247,7 @@ async def get_member_scopes(self, project_id: str, member_id: str): self.logger.debug("ManageClient.get_member_scopes LEAVE") return res - async def update_member_scope( + def update_member_scope( self, project_id: str, member_id: str, options: ScopeOptions ): self.logger.debug("ManageClient.update_member_scope ENTER") @@ -257,7 +257,7 @@ async def update_member_scope( self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.put(url, json=options) + json = self.put(url, json=options) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -266,15 +266,15 @@ async def update_member_scope( return res # invites - async def list_invites(self, project_id: str): + def list_invites(self, project_id: str): return self.get_invites(project_id) - async def get_invites(self, project_id: str): + def get_invites(self, project_id: str): self.logger.debug("ManageClient.get_invites ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/invites" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = InvitesResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -282,13 +282,13 @@ async def get_invites(self, project_id: str): self.logger.debug("ManageClient.get_invites LEAVE") return res - async def send_invite_options(self, project_id: str, options: InviteOptions): + def send_invite_options(self, project_id: str, options: InviteOptions): self.logger.debug("ManageClient.send_invite_options ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/invites" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.post(url, json=options) + json = self.post(url, json=options) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -296,7 +296,7 @@ async def send_invite_options(self, project_id: str, options: InviteOptions): self.logger.debug("ManageClient.send_invite_options LEAVE") return res - async def send_invite(self, project_id: str, email: str, scope="member"): + def send_invite(self, project_id: str, email: str, scope="member"): self.logger.debug("ManageClient.send_invite ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/invites" options: InviteOptions = { @@ -306,7 +306,7 @@ async def send_invite(self, project_id: str, email: str, scope="member"): self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.post(url, json=options) + json = self.post(url, json=options) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -314,13 +314,13 @@ async def send_invite(self, project_id: str, email: str, scope="member"): self.logger.debug("ManageClient.send_invite LEAVE") return res - async def delete_invite(self, project_id: str, email: str): + def delete_invite(self, project_id: str, email: str): self.logger.debug("ManageClient.delete_invite ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/invites/{email}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("email: %s", email) - json = await self.delete(url) + json = self.delete(url) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -328,12 +328,12 @@ async def delete_invite(self, project_id: str, email: str): self.logger.debug("ManageClient.delete_invite LEAVE") return res - async def leave_project(self, project_id: str): + def leave_project(self, project_id: str): self.logger.debug("ManageClient.leave_project ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/leave" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) - json = await self.delete(url) + json = self.delete(url) self.logger.info("json: %s", json) res = Message.from_json(json) self.logger.verbose("result: %s", res) @@ -342,13 +342,13 @@ async def leave_project(self, project_id: str): return res # usage - async def get_usage_requests(self, project_id: str, options: UsageRequestOptions): + def get_usage_requests(self, project_id: str, options: UsageRequestOptions): self.logger.debug("ManageClient.get_usage_requests ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/requests" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.get(url, options) + json = self.get(url, options) self.logger.info("json: %s", json) res = UsageRequestsResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -356,13 +356,13 @@ async def get_usage_requests(self, project_id: str, options: UsageRequestOptions self.logger.debug("ManageClient.get_usage_requests LEAVE") return res - async def get_usage_request(self, project_id: str, request_id: str): + def get_usage_request(self, project_id: str, request_id: str): self.logger.debug("ManageClient.get_usage_request ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/requests/{request_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("request_id: %s", request_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = UsageRequest.from_json(json) self.logger.verbose("result: %s", res) @@ -370,13 +370,13 @@ async def get_usage_request(self, project_id: str, request_id: str): self.logger.debug("ManageClient.get_usage_request LEAVE") return res - async def get_usage_summary(self, project_id: str, options: UsageSummaryOptions): + def get_usage_summary(self, project_id: str, options: UsageSummaryOptions): self.logger.debug("ManageClient.get_usage_summary ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/usage" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.get(url, options) + json = self.get(url, options) self.logger.info("json: %s", json) res = UsageSummaryResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -384,13 +384,13 @@ async def get_usage_summary(self, project_id: str, options: UsageSummaryOptions) self.logger.debug("ManageClient.get_usage_summary LEAVE") return res - async def get_usage_fields(self, project_id: str, options: UsageFieldsOptions): + def get_usage_fields(self, project_id: str, options: UsageFieldsOptions): self.logger.debug("ManageClient.get_usage_fields ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/usage/fields" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - json = await self.get(url, options) + json = self.get(url, options) self.logger.info("json: %s", json) res = UsageFieldsResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -399,15 +399,15 @@ async def get_usage_fields(self, project_id: str, options: UsageFieldsOptions): return res # balances - async def list_balances(self, project_id: str): + def list_balances(self, project_id: str): return self.get_balances(project_id) - async def get_balances(self, project_id: str): + def get_balances(self, project_id: str): self.logger.debug("ManageClient.get_balances ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/balances" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = BalancesResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -415,13 +415,13 @@ async def get_balances(self, project_id: str): self.logger.debug("ManageClient.get_balances LEAVE") return res - async def get_balance(self, project_id: str, balance_id: str): + def get_balance(self, project_id: str, balance_id: str): self.logger.debug("ManageClient.get_balance ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/balances/{balance_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("balance_id: %s", balance_id) - json = await self.get(url) + json = self.get(url) self.logger.info("json: %s", json) res = Balance.from_json(json) self.logger.verbose("result: %s", res) diff --git a/deepgram/clients/onprem/client.py b/deepgram/clients/onprem/client.py index 9870faa0..6001b374 100644 --- a/deepgram/clients/onprem/client.py +++ b/deepgram/clients/onprem/client.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: MIT from .v1.client import OnPremClient as OnPremClientLatest +from .v1.async_client import AsyncOnPremClient as AsyncOnPremClientLatest """ The client.py points to the current supported version in the SDK. @@ -17,3 +18,12 @@ class OnPremClient(OnPremClientLatest): def __init__(self, config): super().__init__(config) + + +class AsyncOnPremClient(AsyncOnPremClientLatest): + """ + Please see AsyncOnPremClientLatest for details + """ + + def __init__(self, config): + super().__init__(config) diff --git a/deepgram/clients/onprem/v1/async_client.py b/deepgram/clients/onprem/v1/async_client.py new file mode 100644 index 00000000..e241be9a --- /dev/null +++ b/deepgram/clients/onprem/v1/async_client.py @@ -0,0 +1,87 @@ +# Copyright 2023 Deepgram SDK contributors. All Rights Reserved. +# Use of this source code is governed by a MIT license that can be found in the LICENSE file. +# SPDX-License-Identifier: MIT + +import logging, verboselogs + +from ...abstract_async_client import AbstractAsyncRestClient + + +class AsyncOnPremClient(AbstractAsyncRestClient): + """ + Client for interacting with Deepgram's on-premises API. + + This class provides methods to manage and interact with on-premises projects and distribution credentials. + + Args: + config (DeepgramClientOptions): all the options for the client. + + Attributes: + endpoint (str): The API endpoint for on-premises projects. + + Methods: + list_onprem_credentials: Lists on-premises distribution credentials for a specific project. + get_onprem_credentials: Retrieves details of a specific on-premises distribution credential for a project. + create_onprem_credentials: Creates a new on-premises distribution credential for a project. + delete_onprem_credentials: Deletes an on-premises distribution credential for a project. + + """ + + def __init__(self, config): + self.logger = logging.getLogger(__name__) + self.logger.addHandler(logging.StreamHandler()) + self.logger.setLevel(config.verbose) + self.config = config + self.endpoint = "v1/projects" + super().__init__(config) + + async def list_onprem_credentials(self, project_id: str): + self.logger.debug("OnPremClient.list_onprem_credentials ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/onprem/distribution/credentials" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + res = await self.get(url) + self.logger.verbose("result: %s", res) + self.logger.notice("list_onprem_credentials succeeded") + self.logger.debug("OnPremClient.list_onprem_credentials LEAVE") + return res + + async def get_onprem_credentials( + self, project_id: str, distribution_credentials_id: str + ): + self.logger.debug("OnPremClient.get_onprem_credentials ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/onprem/distribution/credentials/{distribution_credentials_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("distribution_credentials_id: %s", distribution_credentials_id) + res = await self.get(url) + self.logger.verbose("result: %s", res) + self.logger.notice("get_onprem_credentials succeeded") + self.logger.debug("OnPremClient.get_onprem_credentials LEAVE") + return res + + async def create_onprem_credentials(self, project_id: str, options): + self.logger.debug("OnPremClient.create_onprem_credentials ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/onprem/distribution/credentials/" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("options: %s", options) + res = await self.post(url, json=options) + self.logger.verbose("result: %s", res) + self.logger.notice("create_onprem_credentials succeeded") + self.logger.debug("OnPremClient.create_onprem_credentials LEAVE") + return res + + async def delete_onprem_credentials( + self, project_id: str, distribution_credentials_id: str + ): + self.logger.debug("OnPremClient.delete_onprem_credentials ENTER") + url = f"{self.config.url}/{self.endpoint}/{project_id}/onprem/distribution/credentials/{distribution_credentials_id}" + self.logger.info("url: %s", url) + self.logger.info("project_id: %s", project_id) + self.logger.info("distrbution_credentials_id: %s", distribution_credentials_id) + res = await self.delete(url) + self.logger.verbose("result: %s", res) + self.logger.notice("delete_onprem_credentials succeeded") + self.logger.debug("OnPremClient.delete_onprem_credentials LEAVE") + return res diff --git a/deepgram/clients/onprem/v1/client.py b/deepgram/clients/onprem/v1/client.py index 51078706..c51e4962 100644 --- a/deepgram/clients/onprem/v1/client.py +++ b/deepgram/clients/onprem/v1/client.py @@ -4,10 +4,10 @@ import logging, verboselogs -from ...abstract_client import AbstractRestfulClient +from ...abstract_sync_client import AbstractSyncRestClient -class OnPremClient(AbstractRestfulClient): +class OnPremClient(AbstractSyncRestClient): """ Client for interacting with Deepgram's on-premises API. @@ -35,44 +35,42 @@ def __init__(self, config): self.endpoint = "v1/projects" super().__init__(config) - async def list_onprem_credentials(self, project_id: str): + def list_onprem_credentials(self, project_id: str): self.logger.debug("OnPremClient.list_onprem_credentials ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/onprem/distribution/credentials" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) - res = await self.get(url) + res = self.get(url) self.logger.verbose("result: %s", res) self.logger.notice("list_onprem_credentials succeeded") self.logger.debug("OnPremClient.list_onprem_credentials LEAVE") return res - async def get_onprem_credentials( - self, project_id: str, distribution_credentials_id: str - ): + def get_onprem_credentials(self, project_id: str, distribution_credentials_id: str): self.logger.debug("OnPremClient.get_onprem_credentials ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/onprem/distribution/credentials/{distribution_credentials_id}" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("distribution_credentials_id: %s", distribution_credentials_id) - res = await self.get(url) + res = self.get(url) self.logger.verbose("result: %s", res) self.logger.notice("get_onprem_credentials succeeded") self.logger.debug("OnPremClient.get_onprem_credentials LEAVE") return res - async def create_onprem_credentials(self, project_id: str, options): + def create_onprem_credentials(self, project_id: str, options): self.logger.debug("OnPremClient.create_onprem_credentials ENTER") url = f"{self.config.url}/{self.endpoint}/{project_id}/onprem/distribution/credentials/" self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("options: %s", options) - res = await self.post(url, json=options) + res = self.post(url, json=options) self.logger.verbose("result: %s", res) self.logger.notice("create_onprem_credentials succeeded") self.logger.debug("OnPremClient.create_onprem_credentials LEAVE") return res - async def delete_onprem_credentials( + def delete_onprem_credentials( self, project_id: str, distribution_credentials_id: str ): self.logger.debug("OnPremClient.delete_onprem_credentials ENTER") @@ -80,7 +78,7 @@ async def delete_onprem_credentials( self.logger.info("url: %s", url) self.logger.info("project_id: %s", project_id) self.logger.info("distrbution_credentials_id: %s", distribution_credentials_id) - res = await self.delete(url) + res = self.delete(url) self.logger.verbose("result: %s", res) self.logger.notice("delete_onprem_credentials succeeded") self.logger.debug("OnPremClient.delete_onprem_credentials LEAVE") diff --git a/deepgram/clients/prerecorded/client.py b/deepgram/clients/prerecorded/client.py index ad506265..e4235719 100644 --- a/deepgram/clients/prerecorded/client.py +++ b/deepgram/clients/prerecorded/client.py @@ -3,6 +3,7 @@ # SPDX-License-Identifier: MIT from .v1.client import PreRecordedClient as PreRecordedClientLatest +from .v1.async_client import AsyncPreRecordedClient as AsyncPreRecordedClientLatest from .v1.options import PrerecordedOptions as PrerecordedOptionsLatest from .source import PrerecordedSource, FileSource, UrlSource @@ -24,3 +25,12 @@ class PreRecordedClient(PreRecordedClientLatest): def __init__(self, config): self.config = config super().__init__(config) + + +class AsyncPreRecordedClient(AsyncPreRecordedClientLatest): + """ + Please see AsyncPreRecordedClientLatest for details + """ + + def __init__(self, config): + super().__init__(config) diff --git a/deepgram/clients/prerecorded/v1/async_client.py b/deepgram/clients/prerecorded/v1/async_client.py new file mode 100644 index 00000000..0e2f8b3b --- /dev/null +++ b/deepgram/clients/prerecorded/v1/async_client.py @@ -0,0 +1,226 @@ +# Copyright 2023 Deepgram SDK contributors. All Rights Reserved. +# Use of this source code is governed by a MIT license that can be found in the LICENSE file. +# SPDX-License-Identifier: MIT + +import logging, verboselogs + +from ...abstract_async_client import AbstractAsyncRestClient +from ..errors import DeepgramTypeError +from ..helpers import is_buffer_source, is_readstream_source, is_url_source +from ..source import UrlSource, FileSource + +from .options import PrerecordedOptions +from .response import AsyncPrerecordedResponse, PrerecordedResponse + + +class AsyncPreRecordedClient(AbstractAsyncRestClient): + """ + A client class for handling pre-recorded audio data. + Provides methods for transcribing audio from URLs and files. + """ + + def __init__(self, config): + self.logger = logging.getLogger(__name__) + self.logger.addHandler(logging.StreamHandler()) + self.logger.setLevel(config.verbose) + self.config = config + super().__init__(config) + + """ + Transcribes audio from a URL source. + + Args: + source (UrlSource): The URL source of the audio to transcribe. + options (PrerecordedOptions): Additional options for the transcription (default is None). + endpoint (str): The API endpoint for the transcription (default is "v1/listen"). + + Returns: + SyncPrerecordedResponse: An object containing the transcription result. + + Raises: + DeepgramApiError: Raised for known API errors. + DeepgramUnknownApiError: Raised for unknown API errors. + Exception: For any other unexpected exceptions. + """ + + async def transcribe_url( + self, + source: UrlSource, + options: PrerecordedOptions = None, + endpoint: str = "v1/listen", + ) -> PrerecordedResponse: + self.logger.debug("PreRecordedClient.transcribe_url ENTER") + + if options is not None and "callback" in options: + self.logger.debug("PreRecordedClient.transcribe_url LEAVE") + return await self.transcribe_url_callback( + source, options["callback"], options, endpoint + ) + + url = f"{self.config.url}/{endpoint}" + if is_url_source(source): + body = source + else: + self.logger.error("Unknown transcription source type") + self.logger.debug("PreRecordedClient.transcribe_url LEAVE") + raise DeepgramTypeError("Unknown transcription source type") + + self.logger.info("url: %s", url) + self.logger.info("source: %s", source) + self.logger.info("options: %s", options) + res = PrerecordedResponse.from_json(await self.post(url, options, json=body)) + self.logger.verbose("result: %s", res) + self.logger.notice("transcribe_url succeeded") + self.logger.debug("PreRecordedClient.transcribe_url LEAVE") + return res + + """ + Transcribes audio from a URL source and sends the result to a callback URL. + + Args: + source (UrlSource): The URL source of the audio to transcribe. + callback (str): The callback URL where the transcription results will be sent. + options (PrerecordedOptions): Additional options for the transcription (default is None). + endpoint (str): The API endpoint for the transcription (default is "v1/listen"). + + Returns: + AsyncPrerecordedResponse: An object containing the request_id or an error message. + + Raises: + DeepgramApiError: Raised for known API errors. + DeepgramUnknownApiError: Raised for unknown API errors. + Exception: For any other unexpected exceptions. + """ + + async def transcribe_url_callback( + self, + source: UrlSource, + callback: str, + options: PrerecordedOptions = None, + endpoint: str = "v1/listen", + ) -> AsyncPrerecordedResponse: + self.logger.debug("PreRecordedClient.transcribe_url_callback ENTER") + + url = f"{self.config.url}/{endpoint}" + if options is None: + options = {} + options["callback"] = callback + if is_url_source(source): + body = source + else: + self.logger.error("Unknown transcription source type") + self.logger.debug("PreRecordedClient.transcribe_url_callback LEAVE") + raise DeepgramTypeError("Unknown transcription source type") + + self.logger.info("url: %s", url) + self.logger.info("source: %s", source) + self.logger.info("options: %s", options) + json = await self.post(url, options, json=body) + self.logger.info("json: %s", json) + res = AsyncPrerecordedResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("transcribe_url_callback succeeded") + self.logger.debug("PreRecordedClient.transcribe_url_callback LEAVE") + return res + + """ + Transcribes audio from a local file source. + + Args: + source (FileSource): The local file source of the audio to transcribe. + options (PrerecordedOptions): Additional options for the transcription (default is None). + endpoint (str): The API endpoint for the transcription (default is "v1/listen"). + + Returns: + SyncPrerecordedResponse: An object containing the transcription result or an error message. + + Raises: + + DeepgramApiError: Raised for known API errors. + DeepgramUnknownApiError: Raised for unknown API errors. + Exception: For any other unexpected exceptions. + """ + + async def transcribe_file( + self, + source: FileSource, + options: PrerecordedOptions = None, + endpoint: str = "v1/listen", + ) -> PrerecordedResponse: + self.logger.debug("PreRecordedClient.transcribe_file ENTER") + + if options is not None and "callback" in options: + self.logger.debug("PreRecordedClient.transcribe_file LEAVE") + return await self.transcribe_file_callback( + source, options["callback"], options, endpoint + ) + + url = f"{self.config.url}/{endpoint}" + if is_buffer_source(source): + body = source["buffer"] + elif is_readstream_source(source): + body = source["stream"] + else: + self.logger.error("Unknown transcription source type") + self.logger.debug("PreRecordedClient.transcribe_file LEAVE") + raise DeepgramTypeError("Unknown transcription source type") + + self.logger.info("url: %s", url) + self.logger.info("options: %s", options) + json = await self.post(url, options, content=body) + self.logger.info("json: %s", json) + res = PrerecordedResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("transcribe_file succeeded") + self.logger.debug("PreRecordedClient.transcribe_file LEAVE") + return res + + """ + Transcribes audio from a local file source and sends the result to a callback URL. + + Args: + source (FileSource): The local file source of the audio to transcribe. + callback (str): The callback URL where the transcription results will be sent. + options (PrerecordedOptions): Additional options for the transcription (default is None). + endpoint (str): The API endpoint for the transcription (default is "v1/listen"). + + Returns: + AsyncPrerecordedResponse: An object containing the request_id or an error message. + + Raises: + DeepgramApiError: Raised for known API errors. + DeepgramUnknownApiError: Raised for unknown API errors. + Exception: For any other unexpected exceptions. + """ + + async def transcribe_file_callback( + self, + source: FileSource, + callback: str, + options: PrerecordedOptions = None, + endpoint: str = "v1/listen", + ) -> AsyncPrerecordedResponse: + self.logger.debug("PreRecordedClient.transcribe_file_callback ENTER") + + url = f"{self.config.url}/{endpoint}" + if options is None: + options = {} + options["callback"] = callback + if is_buffer_source(source): + body = source["buffer"] + elif is_readstream_source(source): + body = source["stream"] + else: + self.logger.error("Unknown transcription source type") + self.logger.debug("PreRecordedClient.transcribe_file_callback LEAVE") + raise DeepgramTypeError("Unknown transcription source type") + + self.logger.info("url: %s", url) + self.logger.info("options: %s", options) + json = await self.post(url, options, json=body) + self.logger.info("json: %s", json) + res = AsyncPrerecordedResponse.from_json(json) + self.logger.verbose("result: %s", res) + self.logger.notice("transcribe_file_callback succeeded") + self.logger.debug("PreRecordedClient.transcribe_file_callback LEAVE") + return res diff --git a/deepgram/clients/prerecorded/v1/client.py b/deepgram/clients/prerecorded/v1/client.py index cadf7fbf..b73a76d5 100644 --- a/deepgram/clients/prerecorded/v1/client.py +++ b/deepgram/clients/prerecorded/v1/client.py @@ -5,7 +5,7 @@ import logging, verboselogs import inspect -from ...abstract_client import AbstractRestfulClient +from ...abstract_sync_client import AbstractSyncRestClient from ..errors import DeepgramTypeError from ..helpers import is_buffer_source, is_readstream_source, is_url_source from ..source import UrlSource, FileSource @@ -14,7 +14,7 @@ from .response import AsyncPrerecordedResponse, PrerecordedResponse -class PreRecordedClient(AbstractRestfulClient): +class PreRecordedClient(AbstractSyncRestClient): """ A client class for handling pre-recorded audio data. Provides methods for transcribing audio from URLs and files. @@ -44,7 +44,7 @@ def __init__(self, config): Exception: For any other unexpected exceptions. """ - async def transcribe_url( + def transcribe_url( self, source: UrlSource, options: PrerecordedOptions = None, @@ -54,7 +54,7 @@ async def transcribe_url( url = f"{self.config.url}/{endpoint}" if options is not None and "callback" in options: self.logger.debug("PreRecordedClient.transcribe_url LEAVE") - return await self.transcribe_url_callback( + return self.transcribe_url_callback( source, options["callback"], options, endpoint ) if is_url_source(source): @@ -70,7 +70,7 @@ async def transcribe_url( if isinstance(options, PrerecordedOptions): self.logger.info("PrerecordedOptions switching class -> json") options = options.to_json() - res = PrerecordedResponse.from_json(await self.post(url, options, json=body)) + res = PrerecordedResponse.from_json(self.post(url, options, json=body)) self.logger.verbose("result: %s", res) self.logger.notice("transcribe_url succeeded") self.logger.debug("PreRecordedClient.transcribe_url LEAVE") @@ -94,7 +94,7 @@ async def transcribe_url( Exception: For any other unexpected exceptions. """ - async def transcribe_url_callback( + def transcribe_url_callback( self, source: UrlSource, callback: str, @@ -120,7 +120,7 @@ async def transcribe_url_callback( if isinstance(options, PrerecordedOptions): self.logger.info("PrerecordedOptions switching class -> json") options = options.to_json() - json = await self.post(url, options, json=body) + json = self.post(url, options, json=body) self.logger.info("json: %s", json) res = AsyncPrerecordedResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -146,7 +146,7 @@ async def transcribe_url_callback( Exception: For any other unexpected exceptions. """ - async def transcribe_file( + def transcribe_file( self, source: FileSource, options: PrerecordedOptions = None, @@ -169,7 +169,7 @@ async def transcribe_file( if isinstance(options, PrerecordedOptions): self.logger.info("PrerecordedOptions switching class -> json") options = options.to_json() - json = await self.post(url, options, content=body) + json = self.post(url, options, content=body) self.logger.info("json: %s", json) res = PrerecordedResponse.from_json(json) self.logger.verbose("result: %s", res) @@ -195,7 +195,7 @@ async def transcribe_file( Exception: For any other unexpected exceptions. """ - async def transcribe_file_callback( + def transcribe_file_callback( self, source: FileSource, callback: str, @@ -222,7 +222,7 @@ async def transcribe_file_callback( if isinstance(options, PrerecordedOptions): self.logger.info("PrerecordedOptions switching class -> json") options = options.to_json() - json = await self.post(url, options, json=body) + json = self.post(url, options, json=body) self.logger.info("json: %s", json) res = AsyncPrerecordedResponse.from_json(json) self.logger.verbose("result: %s", res) diff --git a/examples/README.md b/examples/README.md new file mode 100644 index 00000000..b8469941 --- /dev/null +++ b/examples/README.md @@ -0,0 +1,29 @@ +# Examples for Testing Features Locally + +The example projects are meant to be used to test features locally by contributors working on this SDK. + +## Steps to Test Your Code + +If you are contributing changes to this SDK, you can test those changes by using the `prerecorded`, `streaming`, or `manage` "hello world"-style applications in the `examples` folder. Here are the steps to follow: + +### Set your API Key as an Environment Variable named "DEEPGRAM_API_KEY" + +If using bash, this could be done in your `.bash_profile` like so: + +```bash +export DEEPGRAM_API_KEY = "YOUR_DEEPGRAM_API_KEY" +``` + +or this could also be done by a simple export before executing your python application: + +```bash +DEEPGRAM_API_KEY="YOUR_DEEPGRAM_API_KEY" python main.py +``` + +### Run the project + +If you chose to set an environment variable in your shell profile (ie `.bash_profile`) you can change directory into each example folder and run the example like so: + +```bash +python main.py +``` \ No newline at end of file diff --git a/examples/manage/async_invitations/main.py b/examples/manage/async_invitations/main.py new file mode 100644 index 00000000..7fcfefc3 --- /dev/null +++ b/examples/manage/async_invitations/main.py @@ -0,0 +1,71 @@ +# Copyright 2023 Deepgram SDK contributors. All Rights Reserved. +# Use of this source code is governed by a MIT license that can be found in the LICENSE file. +# SPDX-License-Identifier: MIT + +import asyncio +import os +import sys +from dotenv import load_dotenv + +from deepgram import DeepgramClient, InviteOptions + +load_dotenv() + +# environment variables +API_KEY = os.getenv("DG_API_KEY") + +# Create a Deepgram client using the API key +deepgram: DeepgramClient = DeepgramClient(API_KEY) + + +async def main(): + try: + # get projects + projectResp = await deepgram.asyncmanage.v("1").get_projects() + if projectResp is None: + print(f"ListProjects failed.") + sys.exit(1) + + myId = None + myName = None + for project in projectResp.projects: + myId = project.project_id + myName = project.name + print(f"ListProjects() - ID: {myId}, Name: {myName}") + break + + # list invites + listResp = await deepgram.asyncmanage.v("1").get_invites(myId) + if len(listResp.invites) == 0: + print("No invites found") + else: + for invite in listResp.invites: + print(f"GetInvites() - Name: {invite.email}, Amount: {invite.scope}") + + # send invite + options: InviteOptions = {"email": "spam@spam.com", "scope": "member"} + + getResp = await deepgram.asyncmanage.v("1").send_invite_options(myId, options) + print(f"SendInvite() - Msg: {getResp.message}") + + # list invites + listResp = await deepgram.asyncmanage.v("1").get_invites(myId) + if listResp is None: + print("No invites found") + else: + for invite in listResp.invites: + print(f"GetInvites() - Name: {invite.email}, Amount: {invite.scope}") + + # delete invite + delResp = await deepgram.asyncmanage.v("1").delete_invite(myId, "spam@spam.com") + print(f"DeleteInvite() - Msg: {delResp.message}") + + # # leave invite + # delResp = await deepgram.asyncmanage.leave_project(myId) + # print(f"LeaveProject() - Msg: {delResp.message}") + except Exception as e: + print(f"Exception: {e}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/examples/manage/balances/main.py b/examples/manage/balances/main.py index 9f693913..d4c385fa 100644 --- a/examples/manage/balances/main.py +++ b/examples/manage/balances/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os import sys from dotenv import load_dotenv @@ -20,10 +19,10 @@ deepgram: DeepgramClient = DeepgramClient("", config) -async def main(): +def main(): try: # get projects - projectResp = await deepgram.manage.v("1").get_projects() + projectResp = deepgram.manage.v("1").get_projects() if projectResp is None: print(f"ListProjects failed.") sys.exit(1) @@ -37,7 +36,7 @@ async def main(): break # list balances - listResp = await deepgram.manage.v("1").get_balances(myId) + listResp = deepgram.manage.v("1").get_balances(myId) if listResp is None: print(f"ListBalances failed.") sys.exit(1) @@ -50,11 +49,11 @@ async def main(): ) # get balance - getResp = await deepgram.manage.v("1").get_balance(myId, myBalanceId) + getResp = deepgram.manage.v("1").get_balance(myId, myBalanceId) print(f"GetBalance() - Name: {getResp.balance_id}, Amount: {getResp.amount}") except Exception as e: print(f"Exception: {e}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/manage/invitations/main.py b/examples/manage/invitations/main.py index 6eb04afb..d84e1111 100644 --- a/examples/manage/invitations/main.py +++ b/examples/manage/invitations/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os import sys from dotenv import load_dotenv @@ -15,10 +14,10 @@ deepgram: DeepgramClient = DeepgramClient() -async def main(): +def main(): try: # get projects - projectResp = await deepgram.manage.v("1").get_projects() + projectResp = deepgram.manage.v("1").get_projects() if projectResp is None: print(f"ListProjects failed.") sys.exit(1) @@ -32,8 +31,8 @@ async def main(): break # list invites - listResp = await deepgram.manage.v("1").get_invites(myId) - if listResp is None: + listResp = deepgram.manage.v("1").get_invites(myId) + if len(listResp.invites) == 0: print("No invites found") else: for invite in listResp.invites: @@ -42,11 +41,11 @@ async def main(): # send invite options: InviteOptions = {"email": "spam@spam.com", "scope": "member"} - getResp = await deepgram.manage.v("1").send_invite_options(myId, options) + getResp = deepgram.manage.v("1").send_invite_options(myId, options) print(f"SendInvite() - Msg: {getResp.message}") # list invites - listResp = await deepgram.manage.v("1").get_invites(myId) + listResp = deepgram.manage.v("1").get_invites(myId) if listResp is None: print("No invites found") else: @@ -54,15 +53,15 @@ async def main(): print(f"GetInvites() - Name: {invite.email}, Amount: {invite.scope}") # delete invite - delResp = await deepgram.manage.v("1").delete_invite(myId, "spam@spam.com") + delResp = deepgram.manage.v("1").delete_invite(myId, "spam@spam.com") print(f"DeleteInvite() - Msg: {delResp.message}") # # leave invite - # delResp = await deepgram.manage.v("1").leave_project(myId) + # delResp = deepgram.manage.v("1").leave_project(myId) # print(f"LeaveProject() - Msg: {delResp.message}") except Exception as e: print(f"Exception: {e}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/manage/keys/main.py b/examples/manage/keys/main.py index 3562e6e8..6c87cc4e 100644 --- a/examples/manage/keys/main.py +++ b/examples/manage/keys/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os import sys from dotenv import load_dotenv @@ -15,10 +14,10 @@ deepgram: DeepgramClient = DeepgramClient() -async def main(): +def main(): try: # get projects - projectResp = await deepgram.manage.v("1").get_projects() + projectResp = deepgram.manage.v("1").get_projects() if projectResp is None: print(f"ListProjects failed.") sys.exit(1) @@ -32,7 +31,7 @@ async def main(): break # list keys - listResp = await deepgram.manage.v("1").get_keys(myId) + listResp = deepgram.manage.v("1").get_keys(myId) if listResp is None: print("No keys found") else: @@ -45,7 +44,7 @@ async def main(): options: KeyOptions = {"comment": "MyTestKey", "scopes": ["member"]} myKeyId = None - createResp = await deepgram.manage.v("1").create_key(myId, options) + createResp = deepgram.manage.v("1").create_key(myId, options) if createResp is None: print(f"CreateKey failed.") sys.exit(1) @@ -56,7 +55,7 @@ async def main(): ) # list keys - listResp = await deepgram.manage.v("1").get_keys(myId) + listResp = deepgram.manage.v("1").get_keys(myId) if listResp is None: print("No keys found") else: @@ -66,7 +65,7 @@ async def main(): ) # get key - getResp = await deepgram.manage.v("1").get_key(myId, myKeyId) + getResp = deepgram.manage.v("1").get_key(myId, myKeyId) if getResp is None: print(f"GetKey failed.") sys.exit(1) @@ -76,7 +75,7 @@ async def main(): ) # delete key - deleteResp = await deepgram.manage.v("1").delete_key(myId, myKeyId) + deleteResp = deepgram.manage.v("1").delete_key(myId, myKeyId) if deleteResp is None: print(f"DeleteKey failed.") sys.exit(1) @@ -84,7 +83,7 @@ async def main(): print(f"DeleteKey() - Msg: {deleteResp.message}") # list keys - listResp = await deepgram.manage.v("1").get_keys(myId) + listResp = deepgram.manage.v("1").get_keys(myId) if listResp is None: print("No keys found") else: @@ -97,4 +96,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/manage/members/main.py b/examples/manage/members/main.py index 6a8b3512..00eb321a 100644 --- a/examples/manage/members/main.py +++ b/examples/manage/members/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os import sys from dotenv import load_dotenv @@ -18,10 +17,10 @@ deepgram: DeepgramClient = DeepgramClient() -async def main(): +def main(): try: # get projects - projectResp = await deepgram.manage.v("1").get_projects() + projectResp = deepgram.manage.v("1").get_projects() if projectResp is None: print(f"ListProjects failed.") sys.exit(1) @@ -35,7 +34,7 @@ async def main(): # list members delMemberId = None - listResp = await deepgram.manage.v("1").get_members(myId) + listResp = deepgram.manage.v("1").get_members(myId) if listResp is None: print("No members found") else: @@ -55,7 +54,7 @@ async def main(): print("") sys.exit(1) - deleteResp = await deepgram.manage.v("1").remove_member(myId, delMemberId) + deleteResp = deepgram.manage.v("1").remove_member(myId, delMemberId) if deleteResp is None: print(f"RemoveMember failed.") sys.exit(1) @@ -64,7 +63,7 @@ async def main(): # list members delMemberId = None - listResp = await deepgram.manage.v("1").get_members(myId) + listResp = deepgram.manage.v("1").get_members(myId) if listResp is None: print("No members found") else: @@ -75,4 +74,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/manage/projects/main.py b/examples/manage/projects/main.py index 6a06671a..f78417d7 100644 --- a/examples/manage/projects/main.py +++ b/examples/manage/projects/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os import sys from dotenv import load_dotenv @@ -18,10 +17,10 @@ deepgram: DeepgramClient = DeepgramClient() -async def main(): +def main(): try: # get projects - listResp = await deepgram.manage.v("1").get_projects() + listResp = deepgram.manage.v("1").get_projects() if listResp is None: print(f"ListProjects failed.") sys.exit(1) @@ -37,7 +36,7 @@ async def main(): print(f"ListProjects() - ID: {myId}, Name: {myName}") # get project - getResp = await deepgram.manage.v("1").get_project(myId) + getResp = deepgram.manage.v("1").get_project(myId) print(f"GetProject() - Name: {getResp.name}") # update project @@ -45,30 +44,28 @@ async def main(): "name": "My TEST RENAME Example", } - updateResp = await deepgram.manage.v("1").update_project_option( - myId, updateOptions - ) + updateResp = deepgram.manage.v("1").update_project_option(myId, updateOptions) if updateResp is None: print(f"UpdateProject failed.") sys.exit(1) print(f"UpdateProject() - Msg: {updateResp.message}") # get project - getResp = await deepgram.manage.v("1").get_project(myId) + getResp = deepgram.manage.v("1").get_project(myId) if getResp is None: print(f"GetProject failed.") sys.exit(1) print(f"GetProject() - Name: {getResp.name}") # update project - updateResp = await deepgram.manage.v("1").update_project(myId, name=myName) + updateResp = deepgram.manage.v("1").update_project(myId, name=myName) if updateResp is None: print(f"UpdateProject failed.") sys.exit(1) print(f"UpdateProject() - Msg: {updateResp.message}") # get project - getResp = await deepgram.manage.v("1").get_project(myId) + getResp = deepgram.manage.v("1").get_project(myId) if getResp is None: print(f"GetProject failed.") sys.exit(1) @@ -97,4 +94,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/manage/scopes/main.py b/examples/manage/scopes/main.py index 7be04f9a..0a73ae75 100644 --- a/examples/manage/scopes/main.py +++ b/examples/manage/scopes/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os import sys from dotenv import load_dotenv @@ -18,10 +17,10 @@ deepgram: DeepgramClient = DeepgramClient() -async def main(): +def main(): try: # get projects - projectResp = await deepgram.manage.v("1").get_projects() + projectResp = deepgram.manage.v("1").get_projects() if projectResp is None: print(f"ListProjects failed.") sys.exit(1) @@ -36,7 +35,7 @@ async def main(): # list members memberId = None - listResp = await deepgram.manage.v("1").get_members(myId) + listResp = deepgram.manage.v("1").get_members(myId) if listResp is None: print("No members found") else: @@ -54,7 +53,7 @@ async def main(): sys.exit(1) # get member scope - memberResp = await deepgram.manage.v("1").get_member_scopes(myId, memberId) + memberResp = deepgram.manage.v("1").get_member_scopes(myId, memberId) if memberResp is None: print("No scopes found") sys.exit(1) @@ -65,13 +64,11 @@ async def main(): # update scope options: ScopeOptions = {"scope": "admin"} - updateResp = await deepgram.manage.v("1").update_member_scope( - myId, memberId, options - ) + updateResp = deepgram.manage.v("1").update_member_scope(myId, memberId, options) print(f"UpdateMemberScope() - Msg: {updateResp.message}") # get member scope - memberResp = await deepgram.manage.v("1").get_member_scopes(myId, memberId) + memberResp = deepgram.manage.v("1").get_member_scopes(myId, memberId) if memberResp is None: print("No scopes found") sys.exit(1) @@ -82,13 +79,11 @@ async def main(): # update scope options: ScopeOptions = {"scope": "member"} - updateResp = await deepgram.manage.v("1").update_member_scope( - myId, memberId, options - ) + updateResp = deepgram.manage.v("1").update_member_scope(myId, memberId, options) print(f"UpdateMemberScope() - Msg: {updateResp.message}") # get member scope - memberResp = await deepgram.manage.v("1").get_member_scopes(myId, memberId) + memberResp = deepgram.manage.v("1").get_member_scopes(myId, memberId) if memberResp is None: print("No scopes found") sys.exit(1) @@ -100,4 +95,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/manage/usage/main.py b/examples/manage/usage/main.py index 564b21c6..111292e0 100644 --- a/examples/manage/usage/main.py +++ b/examples/manage/usage/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os import sys from dotenv import load_dotenv @@ -20,10 +19,10 @@ deepgram: DeepgramClient = DeepgramClient() -async def main(): +def main(): try: # get projects - projectResp = await deepgram.manage.v("1").get_projects() + projectResp = deepgram.manage.v("1").get_projects() if projectResp is None: print(f"ListProjects failed.") sys.exit(1) @@ -38,7 +37,7 @@ async def main(): # list requests requestId = None options: UsageRequestOptions = {} - listResp = await deepgram.manage.v("1").get_usage_requests(myId, options) + listResp = deepgram.manage.v("1").get_usage_requests(myId, options) if listResp is None: print("No requests found") else: @@ -49,7 +48,7 @@ async def main(): print("") # get request - reqResp = await deepgram.manage.v("1").get_usage_request(myId, requestId) + reqResp = deepgram.manage.v("1").get_usage_request(myId, requestId) if reqResp is None: print("No request found") else: @@ -61,7 +60,7 @@ async def main(): # get fields options: UsageFieldsOptions = {} - listResp = await deepgram.manage.v("1").get_usage_fields(myId, options) + listResp = deepgram.manage.v("1").get_usage_fields(myId, options) if listResp is None: print(f"UsageFields not found.") sys.exit(1) @@ -76,7 +75,7 @@ async def main(): # list members options: UsageSummaryOptions = {} - listResp = await deepgram.manage.v("1").get_usage_summary(myId, options) + listResp = deepgram.manage.v("1").get_usage_summary(myId, options) if listResp is None: print("UsageSummary not found") else: @@ -87,4 +86,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/prerecorded/async_url/main.py b/examples/prerecorded/async_url/main.py new file mode 100644 index 00000000..b3996f7a --- /dev/null +++ b/examples/prerecorded/async_url/main.py @@ -0,0 +1,45 @@ +# Copyright 2023 Deepgram SDK contributors. All Rights Reserved. +# Use of this source code is governed by a MIT license that can be found in the LICENSE file. +# SPDX-License-Identifier: MIT + +import asyncio +import os +from dotenv import load_dotenv + +from deepgram import DeepgramClient, PrerecordedOptions + +load_dotenv() + +API_KEY = os.getenv("DG_API_KEY") +AUDIO_URL = { + "url": "https://static.deepgram.com/examples/Bueller-Life-moves-pretty-fast.wav" +} + +options: PrerecordedOptions = { + "model": "nova", + "smart_format": "true", + "summarize": "v2", +} + +# STEP 1 Create a Deepgram client using the API key (optional - add config options) +deepgram = DeepgramClient(API_KEY) + + +# STEP 2 Call the transcribe_url method on the prerecorded class +async def transcribe_url(): + url_response = await deepgram.listen.asyncprerecorded.v("1").transcribe_url( + AUDIO_URL, options + ) + return url_response + + +async def main(): + try: + response = await transcribe_url() + print(response) + except Exception as e: + print(f"Exception: {e}") + + +if __name__ == "__main__": + asyncio.run(main()) diff --git a/examples/prerecorded/file/main.py b/examples/prerecorded/file/main.py index b130efca..58339b9d 100644 --- a/examples/prerecorded/file/main.py +++ b/examples/prerecorded/file/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os from dotenv import load_dotenv import logging, verboselogs @@ -34,7 +33,7 @@ # STEP 2 Call the transcribe_file method on the prerecorded class -async def transcribe_file(): +def transcribe_file(): # Logic to read the file with open(AUDIO_FILE, "rb") as file: buffer_data = file.read() @@ -43,15 +42,13 @@ async def transcribe_file(): "buffer": buffer_data, } - file_response = await deepgram.listen.prerecorded.v("1").transcribe_file( - payload, options - ) + file_response = deepgram.listen.prerecorded.v("1").transcribe_file(payload, options) return file_response -async def main(): +def main(): try: - response = await transcribe_file() + response = transcribe_file() print(response) print("") json = response.to_json() @@ -62,4 +59,4 @@ async def main(): if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/prerecorded/url/main.py b/examples/prerecorded/url/main.py index d3127fd2..8fc9aae3 100644 --- a/examples/prerecorded/url/main.py +++ b/examples/prerecorded/url/main.py @@ -2,7 +2,6 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio import os from dotenv import load_dotenv @@ -25,20 +24,18 @@ # STEP 2 Call the transcribe_url method on the prerecorded class -async def transcribe_url(): - url_response = await deepgram.listen.prerecorded.v("1").transcribe_url( - AUDIO_URL, options - ) +def transcribe_url(): + url_response = deepgram.listen.prerecorded.v("1").transcribe_url(AUDIO_URL, options) return url_response -async def main(): +def main(): try: - response = await transcribe_url() + response = transcribe_url() print(response) except Exception as e: print(f"Exception: {e}") if __name__ == "__main__": - asyncio.run(main()) + main() diff --git a/examples/streaming/async_http/main.py b/examples/streaming/async_http/main.py new file mode 100644 index 00000000..f9dcbdab --- /dev/null +++ b/examples/streaming/async_http/main.py @@ -0,0 +1,59 @@ +# Copyright 2023 Deepgram SDK contributors. All Rights Reserved. +# Use of this source code is governed by a MIT license that can be found in the LICENSE file. +# SPDX-License-Identifier: MIT + +import asyncio +import aiohttp +import os +from dotenv import load_dotenv + +from deepgram import DeepgramClient, LiveTranscriptionEvents, LiveOptions + +load_dotenv() + +options: LiveOptions = {"model": "nova", "interim_results": False, "language": "en-US"} + +# URL for the realtime streaming audio you would like to transcribe +URL = "http://stream.live.vc.bbcmedia.co.uk/bbc_world_service" + +deepgram_api_key = os.getenv("DG_API_KEY") + + +async def main(): + deepgram: DeepgramClient = DeepgramClient(deepgram_api_key) + + # Create a websocket connection to Deepgram + try: + dg_connection = await deepgram.listen.asynclive.v("1")(options) + except Exception as e: + print(f"Could not open socket: {e}") + return + + # Listen for transcripts received from Deepgram and write them to the console + dg_connection.on(LiveTranscriptionEvents.Transcript, print) + + # Listen for metadata received from Deepgram and write to the console + dg_connection.on(LiveTranscriptionEvents.Metadata, print) + + # Listen for the connection to close + dg_connection.on( + LiveTranscriptionEvents.Close, + lambda c: print(f"Connection closed with code {c}."), + ) + + # Send streaming audio from the URL to Deepgram + async with aiohttp.ClientSession() as session: + async with session.get(URL) as audio: + while True: + data = await audio.content.readany() + # send audio data through the socket + await dg_connection.send(data) + # If no data is being sent from the live stream, then break out of the loop. + if not data: + break + + # Indicate that we've finished sending data by sending the {"type": "CloseStream"} + await dg_connection.finish() + + +asyncio.run(main()) diff --git a/examples/streaming/http/main.py b/examples/streaming/http/main.py index dcab8be3..fb823e16 100644 --- a/examples/streaming/http/main.py +++ b/examples/streaming/http/main.py @@ -2,56 +2,95 @@ # Use of this source code is governed by a MIT license that can be found in the LICENSE file. # SPDX-License-Identifier: MIT -import asyncio -import aiohttp +import httpx import os from dotenv import load_dotenv +import threading from deepgram import DeepgramClient, LiveTranscriptionEvents, LiveOptions load_dotenv() -options: LiveOptions = {"model": "nova", "interim_results": False, "language": "en-US"} +options = LiveOptions(model="nova", interim_results=False, language="en-US") # URL for the realtime streaming audio you would like to transcribe URL = "http://stream.live.vc.bbcmedia.co.uk/bbc_world_service" -async def main(): +def on_message(result=None): + if result is None: + return + sentence = result.channel.alternatives[0].transcript + if len(sentence) == 0: + return + print(f"speaker: {sentence}") + + +def on_metadata(metadata=None): + if metadata is None: + return + print("") + print(metadata) + print("") + + +def on_error(error=None): + if error is None: + return + print("") + print(error) + print("") + + +def main(): + # config: DeepgramClientOptions = DeepgramClientOptions(options={'keepalive': 'true'}) deepgram: DeepgramClient = DeepgramClient() - # Create a websocket connection to Deepgram try: - dg_connection = await deepgram.listen.legacylive(options) - except Exception as e: - print(f"Could not open socket: {e}") - return + # Create a websocket connection to Deepgram + dg_connection = deepgram.listen.live.v("1") + dg_connection.start(options) + + dg_connection.on(LiveTranscriptionEvents.Transcript, on_message) + dg_connection.on(LiveTranscriptionEvents.Metadata, on_metadata) + dg_connection.on(LiveTranscriptionEvents.Error, on_error) + + lock_exit = threading.Lock() + exit = False + + # define a worker thread + def myThread(): + with httpx.stream("GET", URL) as r: + for data in r.iter_bytes(): + lock_exit.acquire() + if exit: + break + lock_exit.release() - # Listen for transcripts received from Deepgram and write them to the console - dg_connection.on(LiveTranscriptionEvents.Transcript, print) + dg_connection.send(data) - # Listen for metadata received from Deepgram and write to the console - dg_connection.on(LiveTranscriptionEvents.Metadata, print) + # start the worker thread + myHttp = threading.Thread(target=myThread) + myHttp.start() - # Listen for the connection to close - dg_connection.on( - LiveTranscriptionEvents.Close, - lambda c: print(f"Connection closed with code {c}."), - ) + # signal finished + input("Press Enter to stop recording...\n\n") + lock_exit.acquire() + exit = True + lock_exit.release() - # Send streaming audio from the URL to Deepgram - async with aiohttp.ClientSession() as session: - async with session.get(URL) as audio: - while True: - data = await audio.content.readany() - # send audio data through the socket - await dg_connection.send(data) - # If no data is being sent from the live stream, then break out of the loop. - if not data: - break + # Wait for the HTTP thread to close and join + myHttp.join() - # Indicate that we've finished sending data by sending the {"type": "CloseStream"} - await dg_connection.finish() + # Indicate that we've finished sending data by sending the {"type": "CloseStream"} + dg_connection.finish() + + print("Finished") + + except Exception as e: + print(f"Could not open socket: {e}") + return -asyncio.run(main()) +if __name__ == "__main__": + main()