Skip to content

Commit 2ad31c9

Browse files
Merge pull request #177 from dvonthenen/restructure-project-part7
Restructure Python v3 (Part 7) - Support API Versioning
2 parents 93bb0d5 + 71cbc9a commit 2ad31c9

File tree

17 files changed

+568
-422
lines changed

17 files changed

+568
-422
lines changed

deepgram/__init__.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,11 @@
1111
from .errors import DeepgramError, DeepgramApiError, DeepgramUnknownApiError, DeepgramUnknownError
1212

1313
# live
14-
from .clients.live.options import LiveOptions
1514
from .clients.live.enums import LiveTranscriptionEvents
15+
from .clients.live.client import LiveClient, LiveOptions
1616

1717
# prerecorded
18-
from .clients.prerecorded.options import PrerecordedOptions
18+
from .clients.prerecorded.client import PreRecordedClient, PrerecordedOptions
1919

2020
# manage
21-
from .clients.manage.client import ManageClient
21+
from .clients.manage.client import ManageClient, ProjectOptions, KeyOptions, ScopeOptions, InviteOptions, UsageRequestOptions, UsageSummaryOptions, UsageFieldsOptions

deepgram/client.py

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@
1010
from .errors import DeepgramError
1111

1212
from .clients.listen import ListenClient
13-
from .clients.manage.client import ManageClient
14-
from .clients.onprem.client import OnPremClient
13+
from .clients.manage.client import ManageClient # FUTURE VERSIONINING:, ManageClientV1
14+
from .clients.onprem.client import OnPremClient # FUTURE VERSIONINING: , OnPremClientV1
1515

1616
class DeepgramClient:
1717
"""
@@ -67,6 +67,16 @@ def listen(self):
6767
def manage(self):
6868
return ManageClient(self.url, self.headers)
6969

70+
# FUTURE VERSIONINING:
71+
# @property
72+
# def manage_v1(self):
73+
# return ManageClientV1(self.url, self.headers)
74+
7075
@property
7176
def onprem(self):
7277
return OnPremClient(self.url, self.headers)
78+
79+
# FUTURE VERSIONINING:
80+
# @property
81+
# def onprem_v1(self):
82+
# return OnPremClientV1(self.url, self.headers)

deepgram/clients/abstract_client.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ async def _handle_request(self, method, url, **kwargs):
5959
try:
6060
with httpx.Client() as client:
6161
response = client.request(method, url, **kwargs)
62-
6362
response.raise_for_status()
6463
return response.json()
6564
except httpx._exceptions.HTTPError as e:

deepgram/clients/listen.py

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22
# Use of this source code is governed by a MIT license that can be found in the LICENSE file.
33
# SPDX-License-Identifier: MIT
44

5-
from .prerecorded.client import PreRecordedClient
6-
from .live.client import LiveClient
5+
from .prerecorded.client import PreRecordedClient # FUTURE VERSIONINING:, PreRecordedClientV1
6+
from .live.client import LiveClient # FUTURE VERSIONINING:, LiveClientV1
77
from typing import Dict, Any, Optional
88

99

@@ -16,7 +16,17 @@ def __init__(self, url: str, api_key: str, headers: Optional[Dict[str, Any]]):
1616
@property
1717
def prerecorded(self):
1818
return PreRecordedClient(self.url, self.headers)
19-
19+
20+
# FUTURE VERSIONINING:
21+
# @property
22+
# def prerecorded_v1(self):
23+
# return PreRecordedClientV1(self.url, self.headers)
24+
2025
@property
2126
def live(self):
2227
return LiveClient(self.url, self.api_key, self.headers)
28+
29+
# FUTURE VERSIONINING:
30+
# @property
31+
# def live_v1(self):
32+
# return LiveClientV1(self.url, self.api_key, self.headers)

deepgram/clients/live/client.py

Lines changed: 12 additions & 96 deletions
Original file line numberDiff line numberDiff line change
@@ -2,104 +2,20 @@
22
# Use of this source code is governed by a MIT license that can be found in the LICENSE file.
33
# SPDX-License-Identifier: MIT
44

5-
from .enums import LiveTranscriptionEvents
6-
from .helpers import convert_to_websocket_url, append_query_params
5+
from .v1_client import LiveClientV1
6+
from .v1_options import LiveOptionsV1
77

8-
from deepgram.errors import DeepgramApiError
8+
'''
9+
The client.py points to the current supported version in the SDK.
10+
Older versions are supported in the SDK for backwards compatibility.
11+
'''
12+
class LiveOptions(LiveOptionsV1):
13+
pass
914

10-
import asyncio
11-
import json
12-
import websockets
13-
14-
class LiveClient:
15+
class LiveClient(LiveClientV1):
1516
"""
16-
Client for interacting with Deepgram's live transcription services over WebSockets.
17-
18-
This class provides methods to establish a WebSocket connection for live transcription and handle real-time transcription events.
19-
20-
Args:
21-
base_url (str): The base URL for WebSocket connection.
22-
api_key (str): The Deepgram API key used for authentication.
23-
headers (dict): Additional HTTP headers for WebSocket connection.
24-
25-
Attributes:
26-
endpoint (str): The API endpoint for live transcription.
27-
_socket (websockets.WebSocketClientProtocol): The WebSocket connection object.
28-
_event_handlers (dict): Dictionary of event handlers for specific events.
29-
websocket_url (str): The WebSocket URL used for connection.
30-
31-
Methods:
32-
__call__: Establishes a WebSocket connection for live transcription.
33-
on: Registers event handlers for specific events.
34-
send: Sends data over the WebSocket connection.
35-
finish: Closes the WebSocket connection gracefully.
17+
Please see LiveClientV1 for details
3618
"""
3719
def __init__(self, base_url, api_key, headers):
38-
self.base_url = base_url
39-
self.api_key = api_key
40-
self.headers = headers
41-
self.endpoint = "v1/listen"
42-
self._socket = None
43-
self._event_handlers = { event: [] for event in LiveTranscriptionEvents }
44-
self.websocket_url = convert_to_websocket_url(base_url, self.endpoint)
45-
46-
async def __call__(self, options=None):
47-
url_with_params = append_query_params(self.websocket_url, options)
48-
try:
49-
self._socket = await _socket_connect(url_with_params, self.headers)
50-
asyncio.create_task(self._start())
51-
return self
52-
except websockets.ConnectionClosed as e:
53-
await self._emit(LiveTranscriptionEvents.Close, e.code)
54-
55-
56-
def on(self, event, handler): # registers event handlers for specific events
57-
if event in LiveTranscriptionEvents and callable(handler):
58-
self._event_handlers[event].append(handler)
59-
60-
async def _emit(self, event, *args, **kwargs): # triggers the registered event handlers for a specific event
61-
for handler in self._event_handlers[event]:
62-
handler(*args, **kwargs)
63-
64-
async def _start(self) -> None:
65-
async for message in self._socket:
66-
try:
67-
data = json.loads(message)
68-
response_type = data.get("type")
69-
if response_type == LiveTranscriptionEvents.Transcript.value:
70-
await self._emit(LiveTranscriptionEvents.Transcript, data)
71-
if "metadata" in data:
72-
await self._emit(LiveTranscriptionEvents.Metadata, data["metadata"])
73-
except json.JSONDecodeError as e:
74-
await self._emit(LiveTranscriptionEvents.Error, e.code)
75-
76-
async def send(self, data):
77-
if self._socket:
78-
await self._socket.send(data)
79-
80-
async def finish(self):
81-
if self._socket:
82-
await self._socket.send(json.dumps({"type": "CloseStream"}))
83-
# await self._socket.send("") # Send a zero-byte message
84-
await self._socket.wait_closed()
85-
86-
async def _socket_connect(websocket_url, headers):
87-
destination = websocket_url
88-
updated_headers = headers
89-
90-
async def attempt():
91-
try:
92-
return await websockets.connect(
93-
destination, extra_headers=updated_headers, ping_interval=5
94-
)
95-
except websockets.exceptions.InvalidHandshake as exc:
96-
raise DeepgramApiError(exc, http_library_error=exc) from exc
97-
98-
# tries = 4
99-
# while tries > 0:
100-
# try:
101-
# return await attempt()
102-
# except Exception as exc:
103-
# tries -= 1
104-
# continue
105-
return await attempt()
20+
super().__init__(base_url, api_key, headers)
21+

deepgram/clients/live/v1_client.py

Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
# Copyright 2023 Deepgram SDK contributors. All Rights Reserved.
2+
# Use of this source code is governed by a MIT license that can be found in the LICENSE file.
3+
# SPDX-License-Identifier: MIT
4+
5+
from .enums import LiveTranscriptionEvents
6+
from .helpers import convert_to_websocket_url, append_query_params
7+
8+
from deepgram.errors import DeepgramApiError
9+
10+
import asyncio
11+
import json
12+
import websockets
13+
14+
class LiveClientV1:
15+
"""
16+
Client for interacting with Deepgram's live transcription services over WebSockets.
17+
18+
This class provides methods to establish a WebSocket connection for live transcription and handle real-time transcription events.
19+
20+
Args:
21+
base_url (str): The base URL for WebSocket connection.
22+
api_key (str): The Deepgram API key used for authentication.
23+
headers (dict): Additional HTTP headers for WebSocket connection.
24+
25+
Attributes:
26+
endpoint (str): The API endpoint for live transcription.
27+
_socket (websockets.WebSocketClientProtocol): The WebSocket connection object.
28+
_event_handlers (dict): Dictionary of event handlers for specific events.
29+
websocket_url (str): The WebSocket URL used for connection.
30+
31+
Methods:
32+
__call__: Establishes a WebSocket connection for live transcription.
33+
on: Registers event handlers for specific events.
34+
send: Sends data over the WebSocket connection.
35+
finish: Closes the WebSocket connection gracefully.
36+
"""
37+
def __init__(self, base_url, api_key, headers):
38+
self.base_url = base_url
39+
self.api_key = api_key
40+
self.headers = headers
41+
self.endpoint = "v1/listen"
42+
self._socket = None
43+
self._event_handlers = { event: [] for event in LiveTranscriptionEvents }
44+
self.websocket_url = convert_to_websocket_url(base_url, self.endpoint)
45+
46+
async def __call__(self, options=None):
47+
url_with_params = append_query_params(self.websocket_url, options)
48+
try:
49+
self._socket = await _socket_connect(url_with_params, self.headers)
50+
asyncio.create_task(self._start())
51+
return self
52+
except websockets.ConnectionClosed as e:
53+
await self._emit(LiveTranscriptionEvents.Close, e.code)
54+
55+
56+
def on(self, event, handler): # registers event handlers for specific events
57+
if event in LiveTranscriptionEvents and callable(handler):
58+
self._event_handlers[event].append(handler)
59+
60+
async def _emit(self, event, *args, **kwargs): # triggers the registered event handlers for a specific event
61+
for handler in self._event_handlers[event]:
62+
handler(*args, **kwargs)
63+
64+
async def _start(self) -> None:
65+
async for message in self._socket:
66+
try:
67+
data = json.loads(message)
68+
response_type = data.get("type")
69+
if response_type == LiveTranscriptionEvents.Transcript.value:
70+
await self._emit(LiveTranscriptionEvents.Transcript, data)
71+
if "metadata" in data:
72+
await self._emit(LiveTranscriptionEvents.Metadata, data["metadata"])
73+
except json.JSONDecodeError as e:
74+
await self._emit(LiveTranscriptionEvents.Error, e.code)
75+
76+
async def send(self, data):
77+
if self._socket:
78+
await self._socket.send(data)
79+
80+
async def finish(self):
81+
if self._socket:
82+
await self._socket.send(json.dumps({"type": "CloseStream"}))
83+
# await self._socket.send("") # Send a zero-byte message
84+
await self._socket.wait_closed()
85+
86+
async def _socket_connect(websocket_url, headers):
87+
destination = websocket_url
88+
updated_headers = headers
89+
90+
async def attempt():
91+
try:
92+
return await websockets.connect(
93+
destination, extra_headers=updated_headers, ping_interval=5
94+
)
95+
except websockets.exceptions.InvalidHandshake as exc:
96+
raise DeepgramApiError(exc, http_library_error=exc) from exc
97+
98+
# tries = 4
99+
# while tries > 0:
100+
# try:
101+
# return await attempt()
102+
# except Exception as exc:
103+
# tries -= 1
104+
# continue
105+
return await attempt()

deepgram/clients/live/options.py renamed to deepgram/clients/live/v1_options.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
from typing import Union, List, TypedDict
66

7-
class LiveOptions(TypedDict, total=False):
7+
class LiveOptionsV1(TypedDict, total=False):
88
callback: str
99
channels: int
1010
diarize: bool

0 commit comments

Comments
 (0)