fathom-python 0.0.25__py3-none-any.whl → 0.0.26__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
fathom/base_client.py CHANGED
@@ -1,18 +1,17 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
- import os
4
3
  import typing
5
4
 
6
5
  import httpx
7
- from .core.api_error import ApiError
8
6
  from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
7
+ from .core.pagination import AsyncPager, SyncPager
9
8
  from .core.request_options import RequestOptions
10
9
  from .environment import FathomApiEnvironment
11
10
  from .raw_base_client import AsyncRawBaseClient, RawBaseClient
12
11
  from .types.list_meetings_request_meeting_type import ListMeetingsRequestMeetingType
13
- from .types.meeting_list_response import MeetingListResponse
14
- from .types.team_list_response import TeamListResponse
15
- from .types.team_member_list_response import TeamMemberListResponse
12
+ from .types.meeting import Meeting
13
+ from .types.team import Team
14
+ from .types.team_member import TeamMember
16
15
 
17
16
 
18
17
  class BaseClient:
@@ -31,7 +30,7 @@ class BaseClient:
31
30
 
32
31
 
33
32
 
34
- api_key : typing.Optional[typing.Union[str, typing.Callable[[], str]]]
33
+ api_key : str
35
34
  timeout : typing.Optional[float]
36
35
  The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.
37
36
 
@@ -52,7 +51,7 @@ class BaseClient:
52
51
  *,
53
52
  base_url: typing.Optional[str] = None,
54
53
  environment: FathomApiEnvironment = FathomApiEnvironment.DEFAULT,
55
- api_key: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = os.getenv("FATHOM_API_KEY"),
54
+ api_key: str,
56
55
  timeout: typing.Optional[float] = None,
57
56
  follow_redirects: typing.Optional[bool] = True,
58
57
  httpx_client: typing.Optional[httpx.Client] = None,
@@ -60,10 +59,6 @@ class BaseClient:
60
59
  _defaulted_timeout = (
61
60
  timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
62
61
  )
63
- if api_key is None:
64
- raise ApiError(
65
- body="The client must be instantiated be either passing in api_key or setting FATHOM_API_KEY"
66
- )
67
62
  self._client_wrapper = SyncClientWrapper(
68
63
  base_url=_get_base_url(base_url=base_url, environment=environment),
69
64
  api_key=api_key,
@@ -98,7 +93,7 @@ class BaseClient:
98
93
  include_transcript: typing.Optional[bool] = None,
99
94
  cursor: typing.Optional[str] = None,
100
95
  request_options: typing.Optional[RequestOptions] = None,
101
- ) -> MeetingListResponse:
96
+ ) -> SyncPager[Meeting]:
102
97
  """
103
98
  Parameters
104
99
  ----------
@@ -144,16 +139,21 @@ class BaseClient:
144
139
 
145
140
  Returns
146
141
  -------
147
- MeetingListResponse
142
+ SyncPager[Meeting]
148
143
  Paginated list of meetings.
149
144
 
150
145
  Examples
151
146
  --------
152
147
  from fathom import FathomApi
153
148
  client = FathomApi(api_key="YOUR_API_KEY", )
154
- client.list_meetings()
149
+ response = client.list_meetings()
150
+ for item in response:
151
+ yield item
152
+ # alternatively, you can paginate page-by-page
153
+ for page in response.iter_pages():
154
+ yield page
155
155
  """
156
- _response = self._raw_client.list_meetings(
156
+ return self._raw_client.list_meetings(
157
157
  recorded_by=recorded_by,
158
158
  teams=teams,
159
159
  calendar_invitees=calendar_invitees,
@@ -163,11 +163,10 @@ class BaseClient:
163
163
  cursor=cursor,
164
164
  request_options=request_options,
165
165
  )
166
- return _response.data
167
166
 
168
167
  def list_teams(
169
168
  self, *, cursor: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
170
- ) -> TeamListResponse:
169
+ ) -> SyncPager[Team]:
171
170
  """
172
171
  Parameters
173
172
  ----------
@@ -179,17 +178,21 @@ class BaseClient:
179
178
 
180
179
  Returns
181
180
  -------
182
- TeamListResponse
181
+ SyncPager[Team]
183
182
  Paginated list of teams.
184
183
 
185
184
  Examples
186
185
  --------
187
186
  from fathom import FathomApi
188
187
  client = FathomApi(api_key="YOUR_API_KEY", )
189
- client.list_teams()
188
+ response = client.list_teams()
189
+ for item in response:
190
+ yield item
191
+ # alternatively, you can paginate page-by-page
192
+ for page in response.iter_pages():
193
+ yield page
190
194
  """
191
- _response = self._raw_client.list_teams(cursor=cursor, request_options=request_options)
192
- return _response.data
195
+ return self._raw_client.list_teams(cursor=cursor, request_options=request_options)
193
196
 
194
197
  def list_team_members(
195
198
  self,
@@ -197,7 +200,7 @@ class BaseClient:
197
200
  team: typing.Optional[str] = None,
198
201
  cursor: typing.Optional[str] = None,
199
202
  request_options: typing.Optional[RequestOptions] = None,
200
- ) -> TeamMemberListResponse:
203
+ ) -> SyncPager[TeamMember]:
201
204
  """
202
205
  Parameters
203
206
  ----------
@@ -212,17 +215,21 @@ class BaseClient:
212
215
 
213
216
  Returns
214
217
  -------
215
- TeamMemberListResponse
218
+ SyncPager[TeamMember]
216
219
  Paginated list of team members.
217
220
 
218
221
  Examples
219
222
  --------
220
223
  from fathom import FathomApi
221
224
  client = FathomApi(api_key="YOUR_API_KEY", )
222
- client.list_team_members()
225
+ response = client.list_team_members()
226
+ for item in response:
227
+ yield item
228
+ # alternatively, you can paginate page-by-page
229
+ for page in response.iter_pages():
230
+ yield page
223
231
  """
224
- _response = self._raw_client.list_team_members(team=team, cursor=cursor, request_options=request_options)
225
- return _response.data
232
+ return self._raw_client.list_team_members(team=team, cursor=cursor, request_options=request_options)
226
233
 
227
234
 
228
235
  class AsyncBaseClient:
@@ -241,7 +248,7 @@ class AsyncBaseClient:
241
248
 
242
249
 
243
250
 
244
- api_key : typing.Optional[typing.Union[str, typing.Callable[[], str]]]
251
+ api_key : str
245
252
  timeout : typing.Optional[float]
246
253
  The timeout to be used, in seconds, for requests. By default the timeout is 60 seconds, unless a custom httpx client is used, in which case this default is not enforced.
247
254
 
@@ -262,7 +269,7 @@ class AsyncBaseClient:
262
269
  *,
263
270
  base_url: typing.Optional[str] = None,
264
271
  environment: FathomApiEnvironment = FathomApiEnvironment.DEFAULT,
265
- api_key: typing.Optional[typing.Union[str, typing.Callable[[], str]]] = os.getenv("FATHOM_API_KEY"),
272
+ api_key: str,
266
273
  timeout: typing.Optional[float] = None,
267
274
  follow_redirects: typing.Optional[bool] = True,
268
275
  httpx_client: typing.Optional[httpx.AsyncClient] = None,
@@ -270,10 +277,6 @@ class AsyncBaseClient:
270
277
  _defaulted_timeout = (
271
278
  timeout if timeout is not None else 60 if httpx_client is None else httpx_client.timeout.read
272
279
  )
273
- if api_key is None:
274
- raise ApiError(
275
- body="The client must be instantiated be either passing in api_key or setting FATHOM_API_KEY"
276
- )
277
280
  self._client_wrapper = AsyncClientWrapper(
278
281
  base_url=_get_base_url(base_url=base_url, environment=environment),
279
282
  api_key=api_key,
@@ -308,7 +311,7 @@ class AsyncBaseClient:
308
311
  include_transcript: typing.Optional[bool] = None,
309
312
  cursor: typing.Optional[str] = None,
310
313
  request_options: typing.Optional[RequestOptions] = None,
311
- ) -> MeetingListResponse:
314
+ ) -> AsyncPager[Meeting]:
312
315
  """
313
316
  Parameters
314
317
  ----------
@@ -354,7 +357,7 @@ class AsyncBaseClient:
354
357
 
355
358
  Returns
356
359
  -------
357
- MeetingListResponse
360
+ AsyncPager[Meeting]
358
361
  Paginated list of meetings.
359
362
 
360
363
  Examples
@@ -363,10 +366,16 @@ class AsyncBaseClient:
363
366
  import asyncio
364
367
  client = AsyncFathomApi(api_key="YOUR_API_KEY", )
365
368
  async def main() -> None:
366
- await client.list_meetings()
369
+ response = await client.list_meetings()
370
+ async for item in response:
371
+ yield item
372
+
373
+ # alternatively, you can paginate page-by-page
374
+ async for page in response.iter_pages():
375
+ yield page
367
376
  asyncio.run(main())
368
377
  """
369
- _response = await self._raw_client.list_meetings(
378
+ return await self._raw_client.list_meetings(
370
379
  recorded_by=recorded_by,
371
380
  teams=teams,
372
381
  calendar_invitees=calendar_invitees,
@@ -376,11 +385,10 @@ class AsyncBaseClient:
376
385
  cursor=cursor,
377
386
  request_options=request_options,
378
387
  )
379
- return _response.data
380
388
 
381
389
  async def list_teams(
382
390
  self, *, cursor: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
383
- ) -> TeamListResponse:
391
+ ) -> AsyncPager[Team]:
384
392
  """
385
393
  Parameters
386
394
  ----------
@@ -392,7 +400,7 @@ class AsyncBaseClient:
392
400
 
393
401
  Returns
394
402
  -------
395
- TeamListResponse
403
+ AsyncPager[Team]
396
404
  Paginated list of teams.
397
405
 
398
406
  Examples
@@ -401,11 +409,16 @@ class AsyncBaseClient:
401
409
  import asyncio
402
410
  client = AsyncFathomApi(api_key="YOUR_API_KEY", )
403
411
  async def main() -> None:
404
- await client.list_teams()
412
+ response = await client.list_teams()
413
+ async for item in response:
414
+ yield item
415
+
416
+ # alternatively, you can paginate page-by-page
417
+ async for page in response.iter_pages():
418
+ yield page
405
419
  asyncio.run(main())
406
420
  """
407
- _response = await self._raw_client.list_teams(cursor=cursor, request_options=request_options)
408
- return _response.data
421
+ return await self._raw_client.list_teams(cursor=cursor, request_options=request_options)
409
422
 
410
423
  async def list_team_members(
411
424
  self,
@@ -413,7 +426,7 @@ class AsyncBaseClient:
413
426
  team: typing.Optional[str] = None,
414
427
  cursor: typing.Optional[str] = None,
415
428
  request_options: typing.Optional[RequestOptions] = None,
416
- ) -> TeamMemberListResponse:
429
+ ) -> AsyncPager[TeamMember]:
417
430
  """
418
431
  Parameters
419
432
  ----------
@@ -428,7 +441,7 @@ class AsyncBaseClient:
428
441
 
429
442
  Returns
430
443
  -------
431
- TeamMemberListResponse
444
+ AsyncPager[TeamMember]
432
445
  Paginated list of team members.
433
446
 
434
447
  Examples
@@ -437,11 +450,16 @@ class AsyncBaseClient:
437
450
  import asyncio
438
451
  client = AsyncFathomApi(api_key="YOUR_API_KEY", )
439
452
  async def main() -> None:
440
- await client.list_team_members()
453
+ response = await client.list_team_members()
454
+ async for item in response:
455
+ yield item
456
+
457
+ # alternatively, you can paginate page-by-page
458
+ async for page in response.iter_pages():
459
+ yield page
441
460
  asyncio.run(main())
442
461
  """
443
- _response = await self._raw_client.list_team_members(team=team, cursor=cursor, request_options=request_options)
444
- return _response.data
462
+ return await self._raw_client.list_team_members(team=team, cursor=cursor, request_options=request_options)
445
463
 
446
464
 
447
465
  def _get_base_url(*, base_url: typing.Optional[str] = None, environment: FathomApiEnvironment) -> str:
fathom/core/__init__.py CHANGED
@@ -9,6 +9,7 @@ from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
9
9
  from .http_client import AsyncHttpClient, HttpClient
10
10
  from .http_response import AsyncHttpResponse, HttpResponse
11
11
  from .jsonable_encoder import jsonable_encoder
12
+ from .pagination import AsyncPager, SyncPager
12
13
  from .pydantic_utilities import (
13
14
  IS_PYDANTIC_V2,
14
15
  UniversalBaseModel,
@@ -28,6 +29,7 @@ __all__ = [
28
29
  "AsyncClientWrapper",
29
30
  "AsyncHttpClient",
30
31
  "AsyncHttpResponse",
32
+ "AsyncPager",
31
33
  "BaseClientWrapper",
32
34
  "FieldMetadata",
33
35
  "File",
@@ -36,6 +38,7 @@ __all__ = [
36
38
  "IS_PYDANTIC_V2",
37
39
  "RequestOptions",
38
40
  "SyncClientWrapper",
41
+ "SyncPager",
39
42
  "UniversalBaseModel",
40
43
  "UniversalRootModel",
41
44
  "convert_and_respect_annotation_metadata",
@@ -7,33 +7,21 @@ from .http_client import AsyncHttpClient, HttpClient
7
7
 
8
8
 
9
9
  class BaseClientWrapper:
10
- def __init__(
11
- self,
12
- *,
13
- api_key: typing.Union[str, typing.Callable[[], str]],
14
- base_url: str,
15
- timeout: typing.Optional[float] = None,
16
- ):
17
- self._api_key = api_key
10
+ def __init__(self, *, api_key: str, base_url: str, timeout: typing.Optional[float] = None):
11
+ self.api_key = api_key
18
12
  self._base_url = base_url
19
13
  self._timeout = timeout
20
14
 
21
15
  def get_headers(self) -> typing.Dict[str, str]:
22
16
  headers: typing.Dict[str, str] = {
23
- "User-Agent": "fathom-python/0.0.25",
17
+ "User-Agent": "fathom-python/0.0.26",
24
18
  "X-Fern-Language": "Python",
25
19
  "X-Fern-SDK-Name": "fathom-python",
26
- "X-Fern-SDK-Version": "0.0.25",
20
+ "X-Fern-SDK-Version": "0.0.26",
27
21
  }
28
- headers["Authorization"] = f"Bearer {self._get_api_key()}"
22
+ headers["X-Api-Key"] = self.api_key
29
23
  return headers
30
24
 
31
- def _get_api_key(self) -> str:
32
- if isinstance(self._api_key, str):
33
- return self._api_key
34
- else:
35
- return self._api_key()
36
-
37
25
  def get_base_url(self) -> str:
38
26
  return self._base_url
39
27
 
@@ -43,12 +31,7 @@ class BaseClientWrapper:
43
31
 
44
32
  class SyncClientWrapper(BaseClientWrapper):
45
33
  def __init__(
46
- self,
47
- *,
48
- api_key: typing.Union[str, typing.Callable[[], str]],
49
- base_url: str,
50
- timeout: typing.Optional[float] = None,
51
- httpx_client: httpx.Client,
34
+ self, *, api_key: str, base_url: str, timeout: typing.Optional[float] = None, httpx_client: httpx.Client
52
35
  ):
53
36
  super().__init__(api_key=api_key, base_url=base_url, timeout=timeout)
54
37
  self.httpx_client = HttpClient(
@@ -61,12 +44,7 @@ class SyncClientWrapper(BaseClientWrapper):
61
44
 
62
45
  class AsyncClientWrapper(BaseClientWrapper):
63
46
  def __init__(
64
- self,
65
- *,
66
- api_key: typing.Union[str, typing.Callable[[], str]],
67
- base_url: str,
68
- timeout: typing.Optional[float] = None,
69
- httpx_client: httpx.AsyncClient,
47
+ self, *, api_key: str, base_url: str, timeout: typing.Optional[float] = None, httpx_client: httpx.AsyncClient
70
48
  ):
71
49
  super().__init__(api_key=api_key, base_url=base_url, timeout=timeout)
72
50
  self.httpx_client = AsyncHttpClient(
@@ -0,0 +1,82 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from __future__ import annotations
4
+
5
+ from dataclasses import dataclass
6
+ from typing import AsyncIterator, Awaitable, Callable, Generic, Iterator, List, Optional, TypeVar
7
+
8
+ from .http_response import BaseHttpResponse
9
+
10
+ T = TypeVar("T")
11
+ """Generic to represent the underlying type of the results within a page"""
12
+
13
+
14
+ # SDKs implement a Page ABC per-pagination request, the endpoint then returns a pager that wraps this type
15
+ # for example, an endpoint will return SyncPager[UserPage] where UserPage implements the Page ABC. ex:
16
+ #
17
+ # SyncPager<InnerListType>(
18
+ # has_next=response.list_metadata.after is not None,
19
+ # items=response.data,
20
+ # # This should be the outer function that returns the SyncPager again
21
+ # get_next=lambda: list(..., cursor: response.cursor) (or list(..., offset: offset + 1))
22
+ # )
23
+
24
+
25
+ @dataclass(frozen=True)
26
+ class SyncPager(Generic[T]):
27
+ get_next: Optional[Callable[[], Optional[SyncPager[T]]]]
28
+ has_next: bool
29
+ items: Optional[List[T]]
30
+ response: Optional[BaseHttpResponse]
31
+
32
+ # Here we type ignore the iterator to avoid a mypy error
33
+ # caused by the type conflict with Pydanitc's __iter__ method
34
+ # brought in by extending the base model
35
+ def __iter__(self) -> Iterator[T]: # type: ignore[override]
36
+ for page in self.iter_pages():
37
+ if page.items is not None:
38
+ yield from page.items
39
+
40
+ def iter_pages(self) -> Iterator[SyncPager[T]]:
41
+ page: Optional[SyncPager[T]] = self
42
+ while page is not None:
43
+ yield page
44
+
45
+ if not page.has_next or page.get_next is None:
46
+ return
47
+
48
+ page = page.get_next()
49
+ if page is None or page.items is None or len(page.items) == 0:
50
+ return
51
+
52
+ def next_page(self) -> Optional[SyncPager[T]]:
53
+ return self.get_next() if self.get_next is not None else None
54
+
55
+
56
+ @dataclass(frozen=True)
57
+ class AsyncPager(Generic[T]):
58
+ get_next: Optional[Callable[[], Awaitable[Optional[AsyncPager[T]]]]]
59
+ has_next: bool
60
+ items: Optional[List[T]]
61
+ response: Optional[BaseHttpResponse]
62
+
63
+ async def __aiter__(self) -> AsyncIterator[T]:
64
+ async for page in self.iter_pages():
65
+ if page.items is not None:
66
+ for item in page.items:
67
+ yield item
68
+
69
+ async def iter_pages(self) -> AsyncIterator[AsyncPager[T]]:
70
+ page: Optional[AsyncPager[T]] = self
71
+ while page is not None:
72
+ yield page
73
+
74
+ if not page.has_next or page.get_next is None:
75
+ return
76
+
77
+ page = await page.get_next()
78
+ if page is None or page.items is None or len(page.items) == 0:
79
+ return
80
+
81
+ async def next_page(self) -> Optional[AsyncPager[T]]:
82
+ return await self.get_next() if self.get_next is not None else None
fathom/raw_base_client.py CHANGED
@@ -5,14 +5,17 @@ from json.decoder import JSONDecodeError
5
5
 
6
6
  from .core.api_error import ApiError
7
7
  from .core.client_wrapper import AsyncClientWrapper, SyncClientWrapper
8
- from .core.http_response import AsyncHttpResponse, HttpResponse
8
+ from .core.pagination import AsyncPager, BaseHttpResponse, SyncPager
9
9
  from .core.pydantic_utilities import parse_obj_as
10
10
  from .core.request_options import RequestOptions
11
11
  from .errors.bad_request_error import BadRequestError
12
12
  from .errors.unauthorized_error import UnauthorizedError
13
13
  from .types.list_meetings_request_meeting_type import ListMeetingsRequestMeetingType
14
+ from .types.meeting import Meeting
14
15
  from .types.meeting_list_response import MeetingListResponse
16
+ from .types.team import Team
15
17
  from .types.team_list_response import TeamListResponse
18
+ from .types.team_member import TeamMember
16
19
  from .types.team_member_list_response import TeamMemberListResponse
17
20
 
18
21
 
@@ -31,7 +34,7 @@ class RawBaseClient:
31
34
  include_transcript: typing.Optional[bool] = None,
32
35
  cursor: typing.Optional[str] = None,
33
36
  request_options: typing.Optional[RequestOptions] = None,
34
- ) -> HttpResponse[MeetingListResponse]:
37
+ ) -> SyncPager[Meeting]:
35
38
  """
36
39
  Parameters
37
40
  ----------
@@ -77,7 +80,7 @@ class RawBaseClient:
77
80
 
78
81
  Returns
79
82
  -------
80
- HttpResponse[MeetingListResponse]
83
+ SyncPager[Meeting]
81
84
  Paginated list of meetings.
82
85
  """
83
86
  _response = self._client_wrapper.httpx_client.request(
@@ -96,14 +99,29 @@ class RawBaseClient:
96
99
  )
97
100
  try:
98
101
  if 200 <= _response.status_code < 300:
99
- _data = typing.cast(
102
+ _parsed_response = typing.cast(
100
103
  MeetingListResponse,
101
104
  parse_obj_as(
102
105
  type_=MeetingListResponse, # type: ignore
103
106
  object_=_response.json(),
104
107
  ),
105
108
  )
106
- return HttpResponse(response=_response, data=_data)
109
+ _items = _parsed_response.items
110
+ _parsed_next = _parsed_response.next_cursor
111
+ _has_next = _parsed_next is not None and _parsed_next != ""
112
+ _get_next = lambda: self.list_meetings(
113
+ recorded_by=recorded_by,
114
+ teams=teams,
115
+ calendar_invitees=calendar_invitees,
116
+ created_after=created_after,
117
+ meeting_type=meeting_type,
118
+ include_transcript=include_transcript,
119
+ cursor=_parsed_next,
120
+ request_options=request_options,
121
+ )
122
+ return SyncPager(
123
+ has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
124
+ )
107
125
  if _response.status_code == 400:
108
126
  raise BadRequestError(
109
127
  headers=dict(_response.headers),
@@ -133,7 +151,7 @@ class RawBaseClient:
133
151
 
134
152
  def list_teams(
135
153
  self, *, cursor: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
136
- ) -> HttpResponse[TeamListResponse]:
154
+ ) -> SyncPager[Team]:
137
155
  """
138
156
  Parameters
139
157
  ----------
@@ -145,7 +163,7 @@ class RawBaseClient:
145
163
 
146
164
  Returns
147
165
  -------
148
- HttpResponse[TeamListResponse]
166
+ SyncPager[Team]
149
167
  Paginated list of teams.
150
168
  """
151
169
  _response = self._client_wrapper.httpx_client.request(
@@ -158,14 +176,23 @@ class RawBaseClient:
158
176
  )
159
177
  try:
160
178
  if 200 <= _response.status_code < 300:
161
- _data = typing.cast(
179
+ _parsed_response = typing.cast(
162
180
  TeamListResponse,
163
181
  parse_obj_as(
164
182
  type_=TeamListResponse, # type: ignore
165
183
  object_=_response.json(),
166
184
  ),
167
185
  )
168
- return HttpResponse(response=_response, data=_data)
186
+ _items = _parsed_response.items
187
+ _parsed_next = _parsed_response.next_cursor
188
+ _has_next = _parsed_next is not None and _parsed_next != ""
189
+ _get_next = lambda: self.list_teams(
190
+ cursor=_parsed_next,
191
+ request_options=request_options,
192
+ )
193
+ return SyncPager(
194
+ has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
195
+ )
169
196
  if _response.status_code == 400:
170
197
  raise BadRequestError(
171
198
  headers=dict(_response.headers),
@@ -199,7 +226,7 @@ class RawBaseClient:
199
226
  team: typing.Optional[str] = None,
200
227
  cursor: typing.Optional[str] = None,
201
228
  request_options: typing.Optional[RequestOptions] = None,
202
- ) -> HttpResponse[TeamMemberListResponse]:
229
+ ) -> SyncPager[TeamMember]:
203
230
  """
204
231
  Parameters
205
232
  ----------
@@ -214,7 +241,7 @@ class RawBaseClient:
214
241
 
215
242
  Returns
216
243
  -------
217
- HttpResponse[TeamMemberListResponse]
244
+ SyncPager[TeamMember]
218
245
  Paginated list of team members.
219
246
  """
220
247
  _response = self._client_wrapper.httpx_client.request(
@@ -228,14 +255,24 @@ class RawBaseClient:
228
255
  )
229
256
  try:
230
257
  if 200 <= _response.status_code < 300:
231
- _data = typing.cast(
258
+ _parsed_response = typing.cast(
232
259
  TeamMemberListResponse,
233
260
  parse_obj_as(
234
261
  type_=TeamMemberListResponse, # type: ignore
235
262
  object_=_response.json(),
236
263
  ),
237
264
  )
238
- return HttpResponse(response=_response, data=_data)
265
+ _items = _parsed_response.items
266
+ _parsed_next = _parsed_response.next_cursor
267
+ _has_next = _parsed_next is not None and _parsed_next != ""
268
+ _get_next = lambda: self.list_team_members(
269
+ team=team,
270
+ cursor=_parsed_next,
271
+ request_options=request_options,
272
+ )
273
+ return SyncPager(
274
+ has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
275
+ )
239
276
  if _response.status_code == 400:
240
277
  raise BadRequestError(
241
278
  headers=dict(_response.headers),
@@ -279,7 +316,7 @@ class AsyncRawBaseClient:
279
316
  include_transcript: typing.Optional[bool] = None,
280
317
  cursor: typing.Optional[str] = None,
281
318
  request_options: typing.Optional[RequestOptions] = None,
282
- ) -> AsyncHttpResponse[MeetingListResponse]:
319
+ ) -> AsyncPager[Meeting]:
283
320
  """
284
321
  Parameters
285
322
  ----------
@@ -325,7 +362,7 @@ class AsyncRawBaseClient:
325
362
 
326
363
  Returns
327
364
  -------
328
- AsyncHttpResponse[MeetingListResponse]
365
+ AsyncPager[Meeting]
329
366
  Paginated list of meetings.
330
367
  """
331
368
  _response = await self._client_wrapper.httpx_client.request(
@@ -344,14 +381,32 @@ class AsyncRawBaseClient:
344
381
  )
345
382
  try:
346
383
  if 200 <= _response.status_code < 300:
347
- _data = typing.cast(
384
+ _parsed_response = typing.cast(
348
385
  MeetingListResponse,
349
386
  parse_obj_as(
350
387
  type_=MeetingListResponse, # type: ignore
351
388
  object_=_response.json(),
352
389
  ),
353
390
  )
354
- return AsyncHttpResponse(response=_response, data=_data)
391
+ _items = _parsed_response.items
392
+ _parsed_next = _parsed_response.next_cursor
393
+ _has_next = _parsed_next is not None and _parsed_next != ""
394
+
395
+ async def _get_next():
396
+ return await self.list_meetings(
397
+ recorded_by=recorded_by,
398
+ teams=teams,
399
+ calendar_invitees=calendar_invitees,
400
+ created_after=created_after,
401
+ meeting_type=meeting_type,
402
+ include_transcript=include_transcript,
403
+ cursor=_parsed_next,
404
+ request_options=request_options,
405
+ )
406
+
407
+ return AsyncPager(
408
+ has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
409
+ )
355
410
  if _response.status_code == 400:
356
411
  raise BadRequestError(
357
412
  headers=dict(_response.headers),
@@ -381,7 +436,7 @@ class AsyncRawBaseClient:
381
436
 
382
437
  async def list_teams(
383
438
  self, *, cursor: typing.Optional[str] = None, request_options: typing.Optional[RequestOptions] = None
384
- ) -> AsyncHttpResponse[TeamListResponse]:
439
+ ) -> AsyncPager[Team]:
385
440
  """
386
441
  Parameters
387
442
  ----------
@@ -393,7 +448,7 @@ class AsyncRawBaseClient:
393
448
 
394
449
  Returns
395
450
  -------
396
- AsyncHttpResponse[TeamListResponse]
451
+ AsyncPager[Team]
397
452
  Paginated list of teams.
398
453
  """
399
454
  _response = await self._client_wrapper.httpx_client.request(
@@ -406,14 +461,26 @@ class AsyncRawBaseClient:
406
461
  )
407
462
  try:
408
463
  if 200 <= _response.status_code < 300:
409
- _data = typing.cast(
464
+ _parsed_response = typing.cast(
410
465
  TeamListResponse,
411
466
  parse_obj_as(
412
467
  type_=TeamListResponse, # type: ignore
413
468
  object_=_response.json(),
414
469
  ),
415
470
  )
416
- return AsyncHttpResponse(response=_response, data=_data)
471
+ _items = _parsed_response.items
472
+ _parsed_next = _parsed_response.next_cursor
473
+ _has_next = _parsed_next is not None and _parsed_next != ""
474
+
475
+ async def _get_next():
476
+ return await self.list_teams(
477
+ cursor=_parsed_next,
478
+ request_options=request_options,
479
+ )
480
+
481
+ return AsyncPager(
482
+ has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
483
+ )
417
484
  if _response.status_code == 400:
418
485
  raise BadRequestError(
419
486
  headers=dict(_response.headers),
@@ -447,7 +514,7 @@ class AsyncRawBaseClient:
447
514
  team: typing.Optional[str] = None,
448
515
  cursor: typing.Optional[str] = None,
449
516
  request_options: typing.Optional[RequestOptions] = None,
450
- ) -> AsyncHttpResponse[TeamMemberListResponse]:
517
+ ) -> AsyncPager[TeamMember]:
451
518
  """
452
519
  Parameters
453
520
  ----------
@@ -462,7 +529,7 @@ class AsyncRawBaseClient:
462
529
 
463
530
  Returns
464
531
  -------
465
- AsyncHttpResponse[TeamMemberListResponse]
532
+ AsyncPager[TeamMember]
466
533
  Paginated list of team members.
467
534
  """
468
535
  _response = await self._client_wrapper.httpx_client.request(
@@ -476,14 +543,27 @@ class AsyncRawBaseClient:
476
543
  )
477
544
  try:
478
545
  if 200 <= _response.status_code < 300:
479
- _data = typing.cast(
546
+ _parsed_response = typing.cast(
480
547
  TeamMemberListResponse,
481
548
  parse_obj_as(
482
549
  type_=TeamMemberListResponse, # type: ignore
483
550
  object_=_response.json(),
484
551
  ),
485
552
  )
486
- return AsyncHttpResponse(response=_response, data=_data)
553
+ _items = _parsed_response.items
554
+ _parsed_next = _parsed_response.next_cursor
555
+ _has_next = _parsed_next is not None and _parsed_next != ""
556
+
557
+ async def _get_next():
558
+ return await self.list_team_members(
559
+ team=team,
560
+ cursor=_parsed_next,
561
+ request_options=request_options,
562
+ )
563
+
564
+ return AsyncPager(
565
+ has_next=_has_next, items=_items, get_next=_get_next, response=BaseHttpResponse(response=_response)
566
+ )
487
567
  if _response.status_code == 400:
488
568
  raise BadRequestError(
489
569
  headers=dict(_response.headers),
fathom/types/assignee.py CHANGED
@@ -7,8 +7,8 @@ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
7
 
8
8
 
9
9
  class Assignee(UniversalBaseModel):
10
- name: str
11
- email: str
10
+ name: typing.Optional[str] = None
11
+ email: typing.Optional[str] = None
12
12
  team: typing.Optional[str] = None
13
13
 
14
14
  if IS_PYDANTIC_V2:
fathom/types/invitee.py CHANGED
@@ -7,9 +7,9 @@ from ..core.pydantic_utilities import IS_PYDANTIC_V2, UniversalBaseModel
7
7
 
8
8
 
9
9
  class Invitee(UniversalBaseModel):
10
- name: str
10
+ name: typing.Optional[str] = None
11
11
  matched_speaker_display_name: typing.Optional[str] = None
12
- email: str
12
+ email: typing.Optional[str] = None
13
13
  is_external: bool
14
14
 
15
15
  if IS_PYDANTIC_V2:
fathom/types/meeting.py CHANGED
@@ -21,11 +21,6 @@ class Meeting(UniversalBaseModel):
21
21
  Calendar event title.
22
22
  """
23
23
 
24
- abstract: typing.Optional[str] = pydantic.Field(default=None)
25
- """
26
- Short meeting summary.
27
- """
28
-
29
24
  url: str
30
25
  share_url: str
31
26
  created_at: dt.datetime
@@ -8,7 +8,7 @@ from .meeting import Meeting
8
8
 
9
9
 
10
10
  class MeetingListResponse(UniversalBaseModel):
11
- limit: int
11
+ limit: typing.Optional[int] = None
12
12
  next_cursor: typing.Optional[str] = None
13
13
  items: typing.List[Meeting]
14
14
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: fathom-python
3
- Version: 0.0.25
3
+ Version: 0.0.26
4
4
  Summary:
5
5
  Requires-Python: >=3.8,<4.0
6
6
  Classifier: Intended Audience :: Developers
@@ -1,15 +1,16 @@
1
1
  fathom/__init__.py,sha256=dBibCxSr7T9FV3mfW_hkQ1hOPTqt8gPC0dMa4ub3Sv8,1227
2
- fathom/base_client.py,sha256=k-Z2XYZ59MKs82zsTup0edBND7dMz5l4G_S8f_82pGc,16496
2
+ fathom/base_client.py,sha256=QjkVELxT9au4CKaGW20aVrN1X4l6Kw2adYwNI5q3zI8,16767
3
3
  fathom/client.py,sha256=8o_WuoWBVyKB6xDmqqZqOJCBJia8eGrapg0Q6yzNUeg,500
4
- fathom/core/__init__.py,sha256=lTcqUPXcx4112yLDd70RAPeqq6tu3eFMe1pKOqkW9JQ,1562
4
+ fathom/core/__init__.py,sha256=4POYbbRlgR7TwGFY5nmHpaa7nFgXOX_pYHcN1Ezh2p8,1643
5
5
  fathom/core/api_error.py,sha256=44vPoTyWN59gonCIZMdzw7M1uspygiLnr3GNFOoVL2Q,614
6
- fathom/core/client_wrapper.py,sha256=Cl_-KZVFlx_6__7uvloAwptEEkL66J5vHD4W3otURCw,2270
6
+ fathom/core/client_wrapper.py,sha256=yHMMPdugGI0RQIBnwOQGlmMUDCXEUU4-MJ34Sf6UaRQ,1836
7
7
  fathom/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
8
8
  fathom/core/file.py,sha256=d4NNbX8XvXP32z8KpK2Xovv33nFfruIrpz0QWxlgpZk,2663
9
9
  fathom/core/force_multipart.py,sha256=awxh5MtcRYe74ehY8U76jzv6fYM_w_D3Rur7KQQzSDk,429
10
10
  fathom/core/http_client.py,sha256=QurkBvCZZz2Z1d8znp4M2YbOXebBUPcPXRhPIS84Wvk,21214
11
11
  fathom/core/http_response.py,sha256=4uOAtXXFTyFXHLXeQWSfQST9PGcOCRAdHVgGTxdyg84,1334
12
12
  fathom/core/jsonable_encoder.py,sha256=hGgcEEeX11sqxxsll7h15pO3pTNVxk_n79Kcn0laoWA,3655
13
+ fathom/core/pagination.py,sha256=ALaZ0NatgXUByLSuyyMwGABMpANR2cWRePgp5rtNQbo,2868
13
14
  fathom/core/pydantic_utilities.py,sha256=HxbbISfaP1XBvzbIkc0ZcF_GHKd9BfYsJAcFh9B126k,10787
14
15
  fathom/core/query_encoder.py,sha256=ekulqNd0j8TgD7ox-Qbz7liqX8-KP9blvT9DsRCenYM,2144
15
16
  fathom/core/remove_none_from_dict.py,sha256=EU9SGgYidWq7SexuJbNs4-PZ-5Bl3Vppd864mS6vQZw,342
@@ -20,19 +21,19 @@ fathom/errors/__init__.py,sha256=Ua3Z6OWyRhcgrq0FSXOpwmOc4RxyTgzP2LXbkzGbMhk,234
20
21
  fathom/errors/bad_request_error.py,sha256=PnE3v3kETCXm9E3LiNcHLNtjPEUvpe98-r59q-kQb78,338
21
22
  fathom/errors/unauthorized_error.py,sha256=mryinHCAaknn5St2VF17R9XybZUcWRRYWEjxg63dQSA,340
22
23
  fathom/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
23
- fathom/raw_base_client.py,sha256=PUMmbRqTNIDZ2CZQ7j90jOgMkUbRvJiCcRwh106ThFQ,20197
24
+ fathom/raw_base_client.py,sha256=_ZY0vaI3ThHyA7HxSG2a-mz_Rr8MJckFfazPK4xPbbI,23716
24
25
  fathom/types/__init__.py,sha256=Q0EMWBgFpA3vP3JPSIEQ01ek63ptoInTP7dEYoYslSs,1350
25
26
  fathom/types/action_item.py,sha256=twWuS_Rg4R4crXt6OEZmPbk1qQziPiZCY392nbZDui4,854
26
- fathom/types/assignee.py,sha256=miCmTy4uvGVJEkVXif0Spt76R5SYOX-2augtqFHEizc,568
27
+ fathom/types/assignee.py,sha256=9lEX-MEAK-BEIpcCaHEwikpAI7UPJTJqYidJ0pa8bto,616
27
28
  fathom/types/crm_company_match.py,sha256=Eb4ai8sE0hbeJCYpO_qHk_RiE_qbsvUmLsc_dF59NZU,542
28
29
  fathom/types/crm_contact_match.py,sha256=hPi_-tVuCU6y-kmx9PYNbpMgEJmLSfPsXErSac16Ag0,557
29
30
  fathom/types/crm_deal_match.py,sha256=m3VCj78bg0m-AGyLYNt7oNj8fJ7ebgWuRwrROoL70Y0,555
30
31
  fathom/types/crm_matches.py,sha256=c_KwylurVtz-un2m2Dmm1SSiGZgpr-z_Tbw1IIdt7bw,1049
31
32
  fathom/types/fathom_user.py,sha256=pbazdvCuf773i6KykIS1LFOLZs8t114HZzD9pw-w53E,570
32
- fathom/types/invitee.py,sha256=XWoooSUrs9aG30pr14I-DP_uz5Owbb8zeUK92Vj7si8,613
33
+ fathom/types/invitee.py,sha256=ktdjTyobFOHzEiSLqsHijWMtNj63F3e8r-1gtNDi-aI,661
33
34
  fathom/types/list_meetings_request_meeting_type.py,sha256=SuiWhjvW_6CrfxfcPx5MkzHMfVMa1R94WnVFcsDUkyw,185
34
- fathom/types/meeting.py,sha256=n9g9-Q7edtfntRZpCKz4DIOU-5Q-H5ISNIWTfVHBokQ,1594
35
- fathom/types/meeting_list_response.py,sha256=zOLT9Y-vc4qJ_ExdsM_k_l0PaVJhzCg6ehlCqZDDhY4,633
35
+ fathom/types/meeting.py,sha256=B1yiIHp8jmw7nnZsRHwxTN0Yxo20fosos_Se0WOiJ0g,1484
36
+ fathom/types/meeting_list_response.py,sha256=fLwJRhoYln2OevpYqnfBzJ-exCIjk9ewjipkJDKkp7w,657
36
37
  fathom/types/meeting_meeting_type.py,sha256=RDatwTAHwLn7U5mvkWJupIcWqYpGGd_bZPBXUtPb6Q8,166
37
38
  fathom/types/meeting_summary.py,sha256=l1tw0CfcFdc1YFWQ_huBwyAKiaP0eMGy118pl60L0AM,679
38
39
  fathom/types/team.py,sha256=Gcu_IVvtHFZCyEqZBYYOWss0J5O9Vua_QbktgFMjA9k,561
@@ -42,6 +43,6 @@ fathom/types/team_member_list_response.py,sha256=ryj2LciQ7YIjaIrlRISVOYS1Eak1e5S
42
43
  fathom/types/transcript_item.py,sha256=Iooc8CqKxrjxp5CjG-ZWgSzhThWe3h3RF7E6zLbUAwY,732
43
44
  fathom/types/transcript_item_speaker.py,sha256=BGViyMkjOBCK8I_iD3ZeYv3Nl32PIWi5ecsMAEfBwiQ,600
44
45
  fathom/version.py,sha256=ZqzW2It05JBdkkFCwQ_n2tpcYp3ivm-jvdflQl2gd6A,80
45
- fathom_python-0.0.25.dist-info/METADATA,sha256=EuuQcDKl6hlFyYJ_hSkr4dyV94CcYiKoEYVZXAdaJdk,4856
46
- fathom_python-0.0.25.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
47
- fathom_python-0.0.25.dist-info/RECORD,,
46
+ fathom_python-0.0.26.dist-info/METADATA,sha256=wtSnRwhn8WE4h8alhrljc5bi454GftWMbvc71fYr_L0,4856
47
+ fathom_python-0.0.26.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
48
+ fathom_python-0.0.26.dist-info/RECORD,,