Skip to content

Commit 7d761ce

Browse files
committed
Sync Python SDK v0.4.1
1 parent bd53b3e commit 7d761ce

File tree

10 files changed

+271
-17
lines changed

10 files changed

+271
-17
lines changed

CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/).
2323
Python SDK - jamaibase
2424

2525
- Add `CodeGenConfig` for python code execution #446
26+
- Remove pydub dependency for SDK `v0.4.1` #488
2627

2728
TS SDK - jamaibase
2829

clients/python/pyproject.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,7 +101,6 @@ dependencies = [
101101
"Pillow>=10.0.1",
102102
"pydantic-settings>=2.0.3",
103103
"pydantic>=2.4.2",
104-
"pydub~=0.25.1",
105104
"srsly>=2.4.8",
106105
"toml>=0.10.2",
107106
"typing_extensions>=4.10.0",

clients/python/src/jamaibase/utils/io.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@
1212
import srsly
1313
import toml
1414
from PIL import ExifTags, Image
15-
from pydub import AudioSegment
1615

1716
from jamaibase.utils.types import JSONInput, JSONOutput
1817

@@ -215,6 +214,8 @@ def generate_audio_thumbnail(file_content: bytes, duration_ms: int = 30000) -> b
215214
Returns:
216215
bytes: The thumbnail audio segment as bytes.
217216
"""
217+
from pydub import AudioSegment
218+
218219
# Use BytesIO to simulate a file object from the byte content
219220
audio = AudioSegment.from_file(BytesIO(file_content))
220221

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
__version__ = "0.4.0"
1+
__version__ = "0.4.1"

clients/python/tests/oss/gen_table/test_export_ops.py

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -966,6 +966,82 @@ def test_export_data(
966966
assert k not in row
967967

968968

969+
@flaky(max_runs=5, min_passes=1, rerun_filter=_rerun_on_fs_error_with_delay)
970+
@pytest.mark.parametrize("client_cls", CLIENT_CLS)
971+
@pytest.mark.parametrize("table_type", TABLE_TYPES)
972+
@pytest.mark.parametrize("delimiter", [","], ids=["comma_delimiter"])
973+
def test_export_reordered_columns_data(
974+
client_cls: Type[JamAI],
975+
table_type: p.TableType,
976+
delimiter: str,
977+
):
978+
jamai = client_cls()
979+
with _create_table(jamai, table_type) as table:
980+
assert isinstance(table, p.TableMetaResponse)
981+
_add_row(
982+
jamai,
983+
table_type,
984+
False,
985+
data={"good": True, "words": 5, "stars": 0.0, "inputs": TEXT, "summary": TEXT},
986+
)
987+
# Reorder columns
988+
new_cols_order = [
989+
"words",
990+
"inputs",
991+
"summary",
992+
"stars",
993+
"photo",
994+
"captioning",
995+
"good",
996+
]
997+
if table_type == p.TableType.knowledge:
998+
new_cols_order = [
999+
"Title",
1000+
"Title Embed",
1001+
"Text",
1002+
"Text Embed",
1003+
"File ID",
1004+
"Page",
1005+
] + new_cols_order
1006+
if table_type == p.TableType.chat:
1007+
new_cols_order = ["User", "AI"] + new_cols_order
1008+
1009+
jamai.table.reorder_columns(
1010+
table_type=table_type,
1011+
request=p.ColumnReorderRequest(
1012+
table_id=TABLE_ID_A,
1013+
column_names=new_cols_order,
1014+
),
1015+
)
1016+
reordered_columns = [
1017+
col_meta.id
1018+
for col_meta in jamai.table.get_table(table_type=table_type, table_id=TABLE_ID_A).cols
1019+
]
1020+
1021+
# Export data
1022+
csv_data = jamai.export_table_data(table_type, TABLE_ID_A, delimiter=delimiter)
1023+
csv_df = csv_to_df(csv_data.decode("utf-8"), sep=delimiter)
1024+
exported_columns = list(csv_df.columns)
1025+
1026+
assert exported_columns == reordered_columns, (
1027+
f"Exported Columns: {','.join(exported_columns)}, "
1028+
f"Reordered Columns: {','.join(reordered_columns)}"
1029+
)
1030+
1031+
# Export selected columns
1032+
csv_data = jamai.export_table_data(
1033+
table_type, TABLE_ID_A, delimiter=delimiter, columns=["good", "words", "summary"]
1034+
)
1035+
csv_df = csv_to_df(csv_data.decode("utf-8"), sep=delimiter)
1036+
selected_exported_columns = list(csv_df.columns)
1037+
selected_reordered_columns = ["ID", "Updated at", "words", "summary", "good"]
1038+
1039+
assert selected_exported_columns == selected_reordered_columns, (
1040+
f"Exported Columns: {','.join(selected_exported_columns)}, "
1041+
f"Reordered Columns: {','.join(selected_reordered_columns)}"
1042+
)
1043+
1044+
9691045
@flaky(max_runs=5, min_passes=1, rerun_filter=_rerun_on_fs_error_with_delay)
9701046
@pytest.mark.parametrize("client_cls", CLIENT_CLS)
9711047
@pytest.mark.parametrize("table_type", TABLE_TYPES)

docker/Dockerfile.frontend

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ ARG CHECK_ORIGIN=false
88
WORKDIR /app
99
COPY ./services/app .
1010
RUN mv .env.example .env
11-
RUN npm ci
11+
RUN npm ci --force
1212

1313
RUN JAMAI_URL=${JAMAI_URL} PUBLIC_JAMAI_URL=${PUBLIC_JAMAI_URL} PUBLIC_IS_SPA=${PUBLIC_IS_SPA} CHECK_ORIGIN=${CHECK_ORIGIN} npx vite build
1414
RUN mv temp build

services/api/src/owl/db/gen_table.py

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,7 +1036,12 @@ def list_rows(
10361036
limit = total - offset
10371037
if order_descending:
10381038
offset = max(0, total - limit - offset)
1039-
rows = table._dataset.to_table(offset=offset, limit=limit).to_pylist()
1039+
if columns is not None:
1040+
if "ID" not in columns:
1041+
columns.insert(0, "ID")
1042+
if "Updated at" not in columns:
1043+
columns.insert(1, "Updated at")
1044+
rows = table._dataset.to_table(columns=columns, offset=offset, limit=limit).to_pylist()
10401045
rows = sorted(rows, reverse=order_descending, key=lambda r: r["ID"])
10411046
rows = self._post_process_rows(
10421047
rows,
@@ -1170,7 +1175,7 @@ def get_conversation_thread(
11701175
def export_csv(
11711176
self,
11721177
table_id: TableName,
1173-
columns: list[ColName] | None = None,
1178+
columns: list[ColName],
11741179
file_path: str = "",
11751180
delimiter: CSVDelimiter | str = ",",
11761181
) -> pd.DataFrame:
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
from typing import Self
2+
3+
import numpy as np
4+
5+
6+
class GenerativeTableCore:
7+
### --- Table CRUD --- ###
8+
9+
# Create
10+
@classmethod
11+
async def create_table(cls, table_id: str) -> Self:
12+
pass
13+
14+
@classmethod
15+
async def duplicate_table(cls, table_id: str) -> Self:
16+
pass
17+
18+
# Read
19+
@classmethod
20+
async def list_tables(cls, table_id: str) -> list[Self]:
21+
pass
22+
23+
@classmethod
24+
async def get_table(cls, table_id: str) -> Self:
25+
pass
26+
27+
async def count_rows(self):
28+
pass
29+
30+
# Update
31+
async def rename_table(self):
32+
pass
33+
34+
async def recreate_fts_index(self):
35+
# Optional
36+
pass
37+
38+
async def recreate_vector_index(self):
39+
# Optional
40+
pass
41+
42+
async def drop_fts_index(self):
43+
# Optional
44+
pass
45+
46+
async def drop_vector_index(self):
47+
# Optional
48+
pass
49+
50+
# Delete
51+
async def drop_table(self):
52+
pass
53+
54+
# Import Export
55+
async def export_table(self):
56+
pass
57+
58+
async def import_table(self):
59+
pass
60+
61+
async def export_data(self):
62+
pass
63+
64+
async def import_data(self):
65+
pass
66+
67+
### --- Column CRUD --- ###
68+
69+
# Create
70+
async def add_column(self):
71+
pass
72+
73+
# Read ops are implemented as table ops
74+
# Update
75+
async def update_gen_config(self):
76+
pass
77+
78+
async def rename_column(self):
79+
pass
80+
81+
async def reorder_columns(self):
82+
# Need to ensure that length of new order list matches the number of columns
83+
pass
84+
85+
# Delete
86+
async def drop_column(self):
87+
pass
88+
89+
### --- Row CRUD --- ###
90+
91+
# Create
92+
async def add_row(self):
93+
pass
94+
95+
async def add_rows(self):
96+
# Optional, if batch operation is supported
97+
pass
98+
99+
# Read
100+
async def list_rows(self):
101+
pass
102+
103+
async def get_row(self):
104+
pass
105+
106+
async def fts_search(self, query: str):
107+
pass
108+
109+
async def vector_search(self, query: list[float] | np.ndarray):
110+
pass
111+
112+
# Update
113+
async def update_row(self):
114+
pass
115+
116+
async def update_rows(self):
117+
# Optional, if batch operation is supported
118+
pass
119+
120+
# Delete
121+
async def delete_row(self):
122+
pass
123+
124+
async def delete_rows(self):
125+
# Optional, if batch operation is supported
126+
pass

services/api/src/owl/routers/gen_table.py

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1379,9 +1379,19 @@ def export_table_data(
13791379
filepath = join(tmp_dir.name, filename)
13801380
# Keep a reference to the directory and only delete upon completion
13811381
bg_tasks.add_task(tmp_dir.cleanup)
1382+
# Get column ordering
1383+
with table.create_session() as session:
1384+
meta = table.open_meta(session, table_id, remove_state_cols=True)
1385+
columns_order = [c.id for c in meta.cols_schema]
1386+
if columns is None:
1387+
columns_to_export = columns_order
1388+
else:
1389+
columns_to_export = [
1390+
col for col in columns_order if col in columns or col.lower() in ("id", "updated at")
1391+
]
13821392
table.export_csv(
13831393
table_id=table_id,
1384-
columns=columns,
1394+
columns=columns_to_export,
13851395
file_path=filepath,
13861396
delimiter=delimiter,
13871397
)

0 commit comments

Comments
 (0)