athena-intelligence 0.1.105__py3-none-any.whl → 0.1.107__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.
athena/client.py CHANGED
@@ -1,3 +1,4 @@
1
+ import dataclasses
1
2
  import enum
2
3
  import io
3
4
  import os
@@ -41,6 +42,26 @@ class SpecialEnvironments(enum.Enum):
41
42
  AUTODETECT_ENVIRONMENT = 'AUTO'
42
43
 
43
44
 
45
+ @dataclasses.dataclass
46
+ class AthenaAsset:
47
+ asset_id: str
48
+ data: bytes
49
+ media_type: str
50
+
51
+ def _repr_mimebundle_(self):
52
+ if self.media_type == "application/sql":
53
+ # it is safe to import IPython in `_repr_mimebundle_`
54
+ # as this is only intended to be invoked by IPython.
55
+ from IPython import display # type: ignore[import]
56
+
57
+ code = display.Code(
58
+ data=self.data,
59
+ language="sql",
60
+ )
61
+ return {"text/html": code._repr_html_()}
62
+ return {self.media_type: self.data}
63
+
64
+
44
65
  class WrappedToolsClient(ToolsClient):
45
66
 
46
67
  def get_file(self, asset_id: str) -> io.BytesIO:
@@ -113,6 +134,10 @@ class WrappedToolsClient(ToolsClient):
113
134
  A pandas data frame, series, or core.File
114
135
 
115
136
  parent_folder_id : typing.Optional[str]
137
+ Identifier of the folder into which the asset should be saved
138
+
139
+ name : typing.Optional[str]
140
+ The name for the asset
116
141
 
117
142
  request_options : typing.Optional[RequestOptions]
118
143
  Request-specific configuration.
@@ -133,6 +158,74 @@ class WrappedToolsClient(ToolsClient):
133
158
  return super().save_asset(
134
159
  file=asset_object, parent_folder_id=parent_folder_id, **kwargs
135
160
  )
161
+
162
+ def get_asset(self, asset_id: str) -> Union["pd.DataFrame", AthenaAsset]:
163
+ """
164
+ Parameters
165
+ ----------
166
+ asset_id : str
167
+
168
+ Returns
169
+ -------
170
+ pd.DataFrame or AthenaAsset
171
+
172
+ Examples
173
+ --------
174
+ from athena.client import Athena
175
+
176
+ client = Athena(api_key="YOUR_API_KEY")
177
+ client.tools.get_asset(asset_id="asset_id")
178
+ """
179
+ # while we wait for https://github.com/fern-api/fern/issues/4316
180
+ result = self._client_wrapper.httpx_client.request(
181
+ "api/v0/tools/file/raw-data", method="GET", params={"asset_id": asset_id}
182
+ )
183
+ if result.status_code != 200:
184
+ # let fern handle errors codes
185
+ self.raw_data(asset_id=asset_id)
186
+ raise Exception(
187
+ f"Could not get assset - unhandled error code: {result.status_code}"
188
+ )
189
+
190
+ file_bytes = io.BytesIO(result.read())
191
+
192
+ media_type = result.headers.get("content-type", "").split(";")[0]
193
+
194
+ if media_type == "":
195
+ # fallback to `libmagic` inference
196
+ media_type = _infer_media_type(bytes_io=file_bytes)
197
+
198
+ media_type_aliases = {"image/jpg": "image/jpeg"}
199
+ media_type = media_type_aliases.get(media_type, media_type)
200
+
201
+ supported_media_types = {
202
+ "application/json",
203
+ "application/pdf",
204
+ "image/jpeg",
205
+ "image/gif",
206
+ "image/png",
207
+ "image/svg+xml",
208
+ "image/webp",
209
+ "text/html",
210
+ "text/latex",
211
+ "text/markdown",
212
+ "text/plain",
213
+ "application/sql",
214
+ }
215
+
216
+ data = file_bytes.read()
217
+
218
+ if media_type in supported_media_types:
219
+ return AthenaAsset(
220
+ asset_id=asset_id,
221
+ data=data,
222
+ media_type=media_type,
223
+ )
224
+
225
+ if media_type in _pandas_media_types:
226
+ return _to_pandas_df(file_bytes)
227
+
228
+ raise NotImplementedError("Assets of `{media_type}` type are not yet supported")
136
229
 
137
230
 
138
231
  class WrappedQueryClient(QueryClient):
@@ -376,17 +469,33 @@ def _check_pandas_installed():
376
469
  assert pandas
377
470
 
378
471
 
379
- def _to_pandas_df(bytes_io: io.BytesIO, *args, **kwargs):
380
- import pandas as pd
472
+ def _infer_media_type(bytes_io: io.BytesIO) -> str:
381
473
  import magic
382
474
 
383
475
  # ideally this would be read from response header, but fern SDK for Python hides this info from us
384
476
  media_type = magic.from_buffer(bytes_io.read(2048), mime=True)
385
477
  bytes_io.seek(0)
478
+ return media_type
479
+
480
+
481
+ _pandas_media_types = {
482
+ "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
483
+ "application/vnd.apache.parquet",
484
+ "application/octet-stream",
485
+ "application/vnd.ms-excel",
486
+ "text/csv",
487
+ "application/csv",
488
+ }
489
+
490
+
491
+ def _to_pandas_df(bytes_io: io.BytesIO, *args, **kwargs):
492
+ import pandas as pd
493
+
494
+ media_type = _infer_media_type(bytes_io)
386
495
 
387
496
  if media_type == 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet':
388
497
  return pd.read_excel(bytes_io, *args, engine='openpyxl', **kwargs)
389
- elif media_type == 'application/vnd.apache.parquet':
498
+ elif media_type in {'application/vnd.apache.parquet', 'application/octet-stream'}:
390
499
  return pd.read_parquet(bytes_io, *args, **kwargs)
391
500
  elif media_type == 'application/vnd.ms-excel':
392
501
  return pd.read_excel(bytes_io, *args, **kwargs)
@@ -17,7 +17,7 @@ class BaseClientWrapper:
17
17
  headers: typing.Dict[str, str] = {
18
18
  "X-Fern-Language": "Python",
19
19
  "X-Fern-SDK-Name": "athena-intelligence",
20
- "X-Fern-SDK-Version": "0.1.105",
20
+ "X-Fern-SDK-Version": "0.1.107",
21
21
  }
22
22
  headers["X-API-KEY"] = self.api_key
23
23
  return headers
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: athena-intelligence
3
- Version: 0.1.105
3
+ Version: 0.1.107
4
4
  Summary: Athena Intelligence Python Library
5
5
  Requires-Python: >=3.8,<4.0
6
6
  Classifier: Intended Audience :: Developers
@@ -1,9 +1,9 @@
1
1
  athena/__init__.py,sha256=EtDa2cZbHfqJnBxCrjErWF1oJWH0cbJbFB7bkxeOFnE,1392
2
2
  athena/base_client.py,sha256=TlP599mOBvj7Tk8IpFe5dgrDM98GJu3lEQh_zwl4vtA,5439
3
- athena/client.py,sha256=9hj9SzW7OhAIY8yKHA0WObOtx8-1W4aLSHduqkBHJT0,14722
3
+ athena/client.py,sha256=OhZA99pgQ2kEy18GoyUt25AZdqjQ49YdXvaewz3llLU,17939
4
4
  athena/core/__init__.py,sha256=UFXpYzcGxWQUucU1TkjOQ9mGWN3A5JohluOIWVYKU4I,973
5
5
  athena/core/api_error.py,sha256=RE8LELok2QCjABadECTvtDp7qejA1VmINCh6TbqPwSE,426
6
- athena/core/client_wrapper.py,sha256=ijXhms74o95_1sms0mC87d_xv0uBTKXzxH7pmz9YEKE,1806
6
+ athena/core/client_wrapper.py,sha256=A07xONnQhSHb3pTSjJC_rKQUFDhHJycf4wvFEh5XkfI,1806
7
7
  athena/core/datetime_utils.py,sha256=nBys2IsYrhPdszxGKCNRPSOCwa-5DWOHG95FB8G9PKo,1047
8
8
  athena/core/file.py,sha256=sy1RUGZ3aJYuw998bZytxxo6QdgKmlnlgBaMvwEKCGg,1480
9
9
  athena/core/http_client.py,sha256=Z4NuAsJD-51yqmoME17O5sxwx5orSp1wsnd6bPyKcgA,17768
@@ -41,6 +41,6 @@ athena/types/file_too_large_error.py,sha256=AinkrcgR7lcTILAD8RX0x48P3GlSoAh1Oihx
41
41
  athena/types/parent_folder_error.py,sha256=ZMF-i3mZY6Mu1n5uQ60Q3mIIfehlWuXtgFUkSYspkx8,1120
42
42
  athena/types/save_asset_request_out.py,sha256=5bpBaUV3oeuL_hz4s07c-6MQHkn4cBsyxgT_SD5oi6I,1193
43
43
  athena/version.py,sha256=8aYAOJtVLaJLpRp6mTiEIhnl8gXA7yE0aDtZ-3mKQ4k,87
44
- athena_intelligence-0.1.105.dist-info/METADATA,sha256=0-dSyqtK9SICscX0vlve617c46HjDvYdj6NdWuZcn9k,5274
45
- athena_intelligence-0.1.105.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
46
- athena_intelligence-0.1.105.dist-info/RECORD,,
44
+ athena_intelligence-0.1.107.dist-info/METADATA,sha256=wuYxYlnBqbPOgg6rVwFafRSoIWxRjvn8QnbhenZExgg,5274
45
+ athena_intelligence-0.1.107.dist-info/WHEEL,sha256=Zb28QaM1gQi8f4VCBhsUklF61CTlNYfs9YAZn-TOGFk,88
46
+ athena_intelligence-0.1.107.dist-info/RECORD,,