groundx 2.3.3__py3-none-any.whl → 2.3.6__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.
Files changed (80) hide show
  1. groundx/__init__.py +4 -0
  2. groundx/buckets/__init__.py +2 -0
  3. groundx/buckets/client.py +47 -366
  4. groundx/buckets/raw_client.py +628 -0
  5. groundx/client.py +15 -17
  6. groundx/core/__init__.py +5 -0
  7. groundx/core/api_error.py +13 -5
  8. groundx/core/client_wrapper.py +4 -3
  9. groundx/core/force_multipart.py +16 -0
  10. groundx/core/http_client.py +70 -26
  11. groundx/core/http_response.py +55 -0
  12. groundx/core/jsonable_encoder.py +0 -1
  13. groundx/core/pydantic_utilities.py +69 -110
  14. groundx/core/serialization.py +7 -3
  15. groundx/customer/__init__.py +2 -0
  16. groundx/customer/client.py +31 -43
  17. groundx/customer/raw_client.py +91 -0
  18. groundx/documents/__init__.py +2 -0
  19. groundx/documents/client.py +100 -780
  20. groundx/documents/raw_client.py +1404 -0
  21. groundx/errors/__init__.py +2 -0
  22. groundx/errors/bad_request_error.py +4 -3
  23. groundx/errors/unauthorized_error.py +4 -3
  24. groundx/groups/__init__.py +2 -0
  25. groundx/groups/client.py +55 -520
  26. groundx/groups/raw_client.py +901 -0
  27. groundx/health/__init__.py +2 -0
  28. groundx/health/client.py +35 -101
  29. groundx/health/raw_client.py +193 -0
  30. groundx/search/__init__.py +2 -0
  31. groundx/search/client.py +64 -213
  32. groundx/search/raw_client.py +442 -0
  33. groundx/search/types/__init__.py +2 -0
  34. groundx/types/__init__.py +4 -0
  35. groundx/types/bounding_box_detail.py +4 -4
  36. groundx/types/bucket_detail.py +5 -5
  37. groundx/types/bucket_list_response.py +3 -3
  38. groundx/types/bucket_response.py +3 -3
  39. groundx/types/bucket_update_detail.py +4 -4
  40. groundx/types/bucket_update_response.py +3 -3
  41. groundx/types/customer_detail.py +2 -2
  42. groundx/types/customer_response.py +3 -3
  43. groundx/types/document.py +9 -4
  44. groundx/types/document_detail.py +4 -4
  45. groundx/types/document_list_response.py +4 -4
  46. groundx/types/document_local_ingest_request.py +1 -0
  47. groundx/types/document_lookup_response.py +3 -3
  48. groundx/types/document_response.py +3 -3
  49. groundx/types/group_detail.py +4 -4
  50. groundx/types/group_list_response.py +3 -3
  51. groundx/types/group_response.py +3 -3
  52. groundx/types/health_response.py +3 -3
  53. groundx/types/health_response_health.py +3 -3
  54. groundx/types/health_service.py +5 -5
  55. groundx/types/ingest_local_document.py +3 -3
  56. groundx/types/ingest_local_document_metadata.py +4 -4
  57. groundx/types/ingest_remote_document.py +4 -4
  58. groundx/types/ingest_response.py +3 -3
  59. groundx/types/ingest_status.py +3 -3
  60. groundx/types/ingest_status_light.py +3 -3
  61. groundx/types/ingest_status_progress.py +3 -3
  62. groundx/types/ingest_status_progress_cancelled.py +3 -3
  63. groundx/types/ingest_status_progress_complete.py +3 -3
  64. groundx/types/ingest_status_progress_errors.py +3 -3
  65. groundx/types/ingest_status_progress_processing.py +3 -3
  66. groundx/types/message_response.py +2 -2
  67. groundx/types/meter_detail.py +2 -2
  68. groundx/types/processes_status_response.py +3 -3
  69. groundx/types/search_response.py +3 -3
  70. groundx/types/search_response_search.py +3 -3
  71. groundx/types/search_result_item.py +7 -5
  72. groundx/types/search_result_item_pages_item.py +41 -0
  73. groundx/types/subscription_detail.py +3 -3
  74. groundx/types/subscription_detail_meters.py +5 -5
  75. groundx/types/website_source.py +4 -4
  76. {groundx-2.3.3.dist-info → groundx-2.3.6.dist-info}/METADATA +1 -1
  77. groundx-2.3.6.dist-info/RECORD +96 -0
  78. groundx-2.3.3.dist-info/RECORD +0 -87
  79. {groundx-2.3.3.dist-info → groundx-2.3.6.dist-info}/LICENSE +0 -0
  80. {groundx-2.3.3.dist-info → groundx-2.3.6.dist-info}/WHEEL +0 -0
groundx/core/__init__.py CHANGED
@@ -1,10 +1,13 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
+ # isort: skip_file
4
+
3
5
  from .api_error import ApiError
4
6
  from .client_wrapper import AsyncClientWrapper, BaseClientWrapper, SyncClientWrapper
5
7
  from .datetime_utils import serialize_datetime
6
8
  from .file import File, convert_file_dict_to_httpx_tuples, with_content_type
7
9
  from .http_client import AsyncHttpClient, HttpClient
10
+ from .http_response import AsyncHttpResponse, HttpResponse
8
11
  from .jsonable_encoder import jsonable_encoder
9
12
  from .pydantic_utilities import (
10
13
  IS_PYDANTIC_V2,
@@ -24,10 +27,12 @@ __all__ = [
24
27
  "ApiError",
25
28
  "AsyncClientWrapper",
26
29
  "AsyncHttpClient",
30
+ "AsyncHttpResponse",
27
31
  "BaseClientWrapper",
28
32
  "FieldMetadata",
29
33
  "File",
30
34
  "HttpClient",
35
+ "HttpResponse",
31
36
  "IS_PYDANTIC_V2",
32
37
  "RequestOptions",
33
38
  "SyncClientWrapper",
groundx/core/api_error.py CHANGED
@@ -1,15 +1,23 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
- import typing
3
+ from typing import Any, Dict, Optional
4
4
 
5
5
 
6
6
  class ApiError(Exception):
7
- status_code: typing.Optional[int]
8
- body: typing.Any
7
+ headers: Optional[Dict[str, str]]
8
+ status_code: Optional[int]
9
+ body: Any
9
10
 
10
- def __init__(self, *, status_code: typing.Optional[int] = None, body: typing.Any = None):
11
+ def __init__(
12
+ self,
13
+ *,
14
+ headers: Optional[Dict[str, str]] = None,
15
+ status_code: Optional[int] = None,
16
+ body: Any = None,
17
+ ) -> None:
18
+ self.headers = headers
11
19
  self.status_code = status_code
12
20
  self.body = body
13
21
 
14
22
  def __str__(self) -> str:
15
- return f"status_code: {self.status_code}, body: {self.body}"
23
+ return f"headers: {self.headers}, status_code: {self.status_code}, body: {self.body}"
@@ -1,9 +1,9 @@
1
1
  # This file was auto-generated by Fern from our API Definition.
2
2
 
3
3
  import typing
4
+
4
5
  import httpx
5
- from .http_client import HttpClient
6
- from .http_client import AsyncHttpClient
6
+ from .http_client import AsyncHttpClient, HttpClient
7
7
 
8
8
 
9
9
  class BaseClientWrapper:
@@ -14,9 +14,10 @@ class BaseClientWrapper:
14
14
 
15
15
  def get_headers(self) -> typing.Dict[str, str]:
16
16
  headers: typing.Dict[str, str] = {
17
+ "User-Agent": "groundx/2.3.6",
17
18
  "X-Fern-Language": "Python",
18
19
  "X-Fern-SDK-Name": "groundx",
19
- "X-Fern-SDK-Version": "2.3.3",
20
+ "X-Fern-SDK-Version": "2.3.6",
20
21
  }
21
22
  headers["X-API-Key"] = self.api_key
22
23
  return headers
@@ -0,0 +1,16 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+
4
+ class ForceMultipartDict(dict):
5
+ """
6
+ A dictionary subclass that always evaluates to True in boolean contexts.
7
+
8
+ This is used to force multipart/form-data encoding in HTTP requests even when
9
+ the dictionary is empty, which would normally evaluate to False.
10
+ """
11
+
12
+ def __bool__(self):
13
+ return True
14
+
15
+
16
+ FORCE_MULTIPART = ForceMultipartDict()
@@ -2,7 +2,6 @@
2
2
 
3
3
  import asyncio
4
4
  import email.utils
5
- import json
6
5
  import re
7
6
  import time
8
7
  import typing
@@ -11,12 +10,13 @@ from contextlib import asynccontextmanager, contextmanager
11
10
  from random import random
12
11
 
13
12
  import httpx
14
-
15
13
  from .file import File, convert_file_dict_to_httpx_tuples
14
+ from .force_multipart import FORCE_MULTIPART
16
15
  from .jsonable_encoder import jsonable_encoder
17
16
  from .query_encoder import encode_query
18
17
  from .remove_none_from_dict import remove_none_from_dict
19
18
  from .request_options import RequestOptions
19
+ from httpx._types import RequestFiles
20
20
 
21
21
  INITIAL_RETRY_DELAY_SECONDS = 0.5
22
22
  MAX_RETRY_DELAY_SECONDS = 10
@@ -180,11 +180,17 @@ class HttpClient:
180
180
  json: typing.Optional[typing.Any] = None,
181
181
  data: typing.Optional[typing.Any] = None,
182
182
  content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
183
- files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
183
+ files: typing.Optional[
184
+ typing.Union[
185
+ typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
186
+ typing.List[typing.Tuple[str, File]],
187
+ ]
188
+ ] = None,
184
189
  headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
185
190
  request_options: typing.Optional[RequestOptions] = None,
186
191
  retries: int = 2,
187
192
  omit: typing.Optional[typing.Any] = None,
193
+ force_multipart: typing.Optional[bool] = None,
188
194
  ) -> httpx.Response:
189
195
  base_url = self.get_base_url(base_url)
190
196
  timeout = (
@@ -195,6 +201,15 @@ class HttpClient:
195
201
 
196
202
  json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
197
203
 
204
+ request_files: typing.Optional[RequestFiles] = (
205
+ convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
206
+ if (files is not None and files is not omit and isinstance(files, dict))
207
+ else None
208
+ )
209
+
210
+ if (request_files is None or len(request_files) == 0) and force_multipart:
211
+ request_files = FORCE_MULTIPART
212
+
198
213
  response = self.httpx_client.request(
199
214
  method=method,
200
215
  url=urllib.parse.urljoin(f"{base_url}/", path),
@@ -227,11 +242,7 @@ class HttpClient:
227
242
  json=json_body,
228
243
  data=data_body,
229
244
  content=content,
230
- files=(
231
- convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
232
- if (files is not None and files is not omit)
233
- else None
234
- ),
245
+ files=request_files,
235
246
  timeout=timeout,
236
247
  )
237
248
 
@@ -266,11 +277,17 @@ class HttpClient:
266
277
  json: typing.Optional[typing.Any] = None,
267
278
  data: typing.Optional[typing.Any] = None,
268
279
  content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
269
- files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
280
+ files: typing.Optional[
281
+ typing.Union[
282
+ typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
283
+ typing.List[typing.Tuple[str, File]],
284
+ ]
285
+ ] = None,
270
286
  headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
271
287
  request_options: typing.Optional[RequestOptions] = None,
272
288
  retries: int = 2,
273
289
  omit: typing.Optional[typing.Any] = None,
290
+ force_multipart: typing.Optional[bool] = None,
274
291
  ) -> typing.Iterator[httpx.Response]:
275
292
  base_url = self.get_base_url(base_url)
276
293
  timeout = (
@@ -279,6 +296,15 @@ class HttpClient:
279
296
  else self.base_timeout()
280
297
  )
281
298
 
299
+ request_files: typing.Optional[RequestFiles] = (
300
+ convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
301
+ if (files is not None and files is not omit and isinstance(files, dict))
302
+ else None
303
+ )
304
+
305
+ if (request_files is None or len(request_files) == 0) and force_multipart:
306
+ request_files = FORCE_MULTIPART
307
+
282
308
  json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
283
309
 
284
310
  with self.httpx_client.stream(
@@ -313,11 +339,7 @@ class HttpClient:
313
339
  json=json_body,
314
340
  data=data_body,
315
341
  content=content,
316
- files=(
317
- convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
318
- if (files is not None and files is not omit)
319
- else None
320
- ),
342
+ files=request_files,
321
343
  timeout=timeout,
322
344
  ) as stream:
323
345
  yield stream
@@ -356,11 +378,17 @@ class AsyncHttpClient:
356
378
  json: typing.Optional[typing.Any] = None,
357
379
  data: typing.Optional[typing.Any] = None,
358
380
  content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
359
- files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
381
+ files: typing.Optional[
382
+ typing.Union[
383
+ typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
384
+ typing.List[typing.Tuple[str, File]],
385
+ ]
386
+ ] = None,
360
387
  headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
361
388
  request_options: typing.Optional[RequestOptions] = None,
362
389
  retries: int = 2,
363
390
  omit: typing.Optional[typing.Any] = None,
391
+ force_multipart: typing.Optional[bool] = None,
364
392
  ) -> httpx.Response:
365
393
  base_url = self.get_base_url(base_url)
366
394
  timeout = (
@@ -369,6 +397,15 @@ class AsyncHttpClient:
369
397
  else self.base_timeout()
370
398
  )
371
399
 
400
+ request_files: typing.Optional[RequestFiles] = (
401
+ convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
402
+ if (files is not None and files is not omit and isinstance(files, dict))
403
+ else None
404
+ )
405
+
406
+ if (request_files is None or len(request_files) == 0) and force_multipart:
407
+ request_files = FORCE_MULTIPART
408
+
372
409
  json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
373
410
 
374
411
  # Add the input to each of these and do None-safety checks
@@ -404,11 +441,7 @@ class AsyncHttpClient:
404
441
  json=json_body,
405
442
  data=data_body,
406
443
  content=content,
407
- files=(
408
- convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
409
- if files is not None
410
- else None
411
- ),
444
+ files=request_files,
412
445
  timeout=timeout,
413
446
  )
414
447
 
@@ -442,11 +475,17 @@ class AsyncHttpClient:
442
475
  json: typing.Optional[typing.Any] = None,
443
476
  data: typing.Optional[typing.Any] = None,
444
477
  content: typing.Optional[typing.Union[bytes, typing.Iterator[bytes], typing.AsyncIterator[bytes]]] = None,
445
- files: typing.Optional[typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]]] = None,
478
+ files: typing.Optional[
479
+ typing.Union[
480
+ typing.Dict[str, typing.Optional[typing.Union[File, typing.List[File]]]],
481
+ typing.List[typing.Tuple[str, File]],
482
+ ]
483
+ ] = None,
446
484
  headers: typing.Optional[typing.Dict[str, typing.Any]] = None,
447
485
  request_options: typing.Optional[RequestOptions] = None,
448
486
  retries: int = 2,
449
487
  omit: typing.Optional[typing.Any] = None,
488
+ force_multipart: typing.Optional[bool] = None,
450
489
  ) -> typing.AsyncIterator[httpx.Response]:
451
490
  base_url = self.get_base_url(base_url)
452
491
  timeout = (
@@ -455,6 +494,15 @@ class AsyncHttpClient:
455
494
  else self.base_timeout()
456
495
  )
457
496
 
497
+ request_files: typing.Optional[RequestFiles] = (
498
+ convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
499
+ if (files is not None and files is not omit and isinstance(files, dict))
500
+ else None
501
+ )
502
+
503
+ if (request_files is None or len(request_files) == 0) and force_multipart:
504
+ request_files = FORCE_MULTIPART
505
+
458
506
  json_body, data_body = get_request_body(json=json, data=data, request_options=request_options, omit=omit)
459
507
 
460
508
  async with self.httpx_client.stream(
@@ -489,11 +537,7 @@ class AsyncHttpClient:
489
537
  json=json_body,
490
538
  data=data_body,
491
539
  content=content,
492
- files=(
493
- convert_file_dict_to_httpx_tuples(remove_omit_from_dict(remove_none_from_dict(files), omit))
494
- if files is not None
495
- else None
496
- ),
540
+ files=request_files,
497
541
  timeout=timeout,
498
542
  ) as stream:
499
543
  yield stream
@@ -0,0 +1,55 @@
1
+ # This file was auto-generated by Fern from our API Definition.
2
+
3
+ from typing import Dict, Generic, TypeVar
4
+
5
+ import httpx
6
+
7
+ T = TypeVar("T")
8
+ """Generic to represent the underlying type of the data wrapped by the HTTP response."""
9
+
10
+
11
+ class BaseHttpResponse:
12
+ """Minimalist HTTP response wrapper that exposes response headers."""
13
+
14
+ _response: httpx.Response
15
+
16
+ def __init__(self, response: httpx.Response):
17
+ self._response = response
18
+
19
+ @property
20
+ def headers(self) -> Dict[str, str]:
21
+ return dict(self._response.headers)
22
+
23
+
24
+ class HttpResponse(Generic[T], BaseHttpResponse):
25
+ """HTTP response wrapper that exposes response headers and data."""
26
+
27
+ _data: T
28
+
29
+ def __init__(self, response: httpx.Response, data: T):
30
+ super().__init__(response)
31
+ self._data = data
32
+
33
+ @property
34
+ def data(self) -> T:
35
+ return self._data
36
+
37
+ def close(self) -> None:
38
+ self._response.close()
39
+
40
+
41
+ class AsyncHttpResponse(Generic[T], BaseHttpResponse):
42
+ """HTTP response wrapper that exposes response headers and data."""
43
+
44
+ _data: T
45
+
46
+ def __init__(self, response: httpx.Response, data: T):
47
+ super().__init__(response)
48
+ self._data = data
49
+
50
+ @property
51
+ def data(self) -> T:
52
+ return self._data
53
+
54
+ async def close(self) -> None:
55
+ await self._response.aclose()
@@ -17,7 +17,6 @@ from types import GeneratorType
17
17
  from typing import Any, Callable, Dict, List, Optional, Set, Union
18
18
 
19
19
  import pydantic
20
-
21
20
  from .datetime_utils import serialize_datetime
22
21
  from .pydantic_utilities import (
23
22
  IS_PYDANTIC_V2,