Skip to main content

A Python SDK for gRPC-based file management system

Project description

File Hub Client (tamar-file-hub-client)

file-hub-server 的官方 Python SDK。基于 gRPC 通信,提供异步与同步两套客户端,覆盖文件管理、文件夹、文档、媒体压缩变体、协同电子表格 (Taple) 全部接口。

Server 通过 gRPC 调度 file-hub-executor 完成压缩与跨境同步;本 SDK 只与 Server 直接通信。

目录

安装

pip install tamar-file-hub-client

支持 Python 3.8 ~ 3.12。包内含 py.typed,完整类型注解。

依赖:grpciogrpcio-toolsprotobuf==5.27.2pydantic>=2requestsaiohttpaiofilespython-magic(Windows: python-magic-bin)。

快速开始

同步客户端

from file_hub_client import TamarFileHubClient, Role

with TamarFileHubClient(
    host="grpc.example.com",
    port=50051,
    secure=True,
    credentials={"api_key": "your-api-key"},
) as client:
    client.set_user_context(
        org_id="org-123",
        user_id="user-456",
        role=Role.ACCOUNT,
    )

    result = client.blobs.upload(file=b"hello world")
    print(result.file.id, result.upload_file.file_size)

异步客户端

import asyncio
from file_hub_client import AsyncTamarFileHubClient, Role

async def main():
    async with AsyncTamarFileHubClient(host="grpc.example.com") as client:
        client.set_user_context(org_id="org-123", user_id="user-456", role=Role.ACCOUNT)
        files = await client.files.list_files(folder_id="folder-1", page_size=20)
        for f in files.files:
            print(f.id, f.file_name)

asyncio.run(main())

两套客户端方法签名一致,按运行环境选用。也可通过 get_client() / get_async_client() 获取单例。

客户端构造

TamarFileHubClient(
    host="grpc.example.com",          # 或 FILE_HUB_HOST
    port=50051,                         # 或 FILE_HUB_PORT(可省略)
    secure=True,                        # 或 FILE_HUB_SECURE
    credentials={"api_key": "..."},    # 或 FILE_HUB_API_KEY
    auto_connect=True,
    retry_count=3,
    retry_delay=1.0,
    user_context=UserContext(...),
    request_context=RequestContext(...),
    enable_logging=True,
    log_level="INFO",
    options=[
        ("grpc.max_send_message_length", 100 * 1024 * 1024),
        ("grpc.max_receive_message_length", 100 * 1024 * 1024),
    ],
)

环境变量

构造参数均可由环境变量提供,构造时显式传参的优先级高于环境变量。便于 12-factor 部署:

变量 对应参数 默认值 说明
FILE_HUB_HOST host localhost gRPC 服务器地址,可以是域名或 IP
FILE_HUB_PORT port (空) gRPC 端口;留空时直接以 host 作为完整地址(线上走域名常这样用)
FILE_HUB_SECURE secure false 是否启用 TLS,取值 true / false
FILE_HUB_API_KEY credentials (空) API Key,存在时自动转为 {"api_key": ...}
FILE_HUB_RETRY_COUNT retry_count 3 channel 创建失败时的重试次数;网络连接由首次 RPC 懒建立
FILE_HUB_RETRY_DELAY retry_delay 1.0 channel 创建重试间隔(秒)
# 本地开发
export FILE_HUB_HOST=localhost
export FILE_HUB_PORT=50051
export FILE_HUB_SECURE=false

# 生产(域名 + TLS,无需指定端口)
export FILE_HUB_HOST=api.filehub.example.com
export FILE_HUB_SECURE=true
export FILE_HUB_API_KEY=prod-api-key-xxxxx
# 全部走环境变量,无需传参
with TamarFileHubClient() as client:
    client.set_user_context(org_id="org-123", user_id="user-456")
    ...

UserContext(org_id / user_id / role / actor_id / user_ip)需要通过 set_user_context() 显式设置,不从环境变量读取——它属于业务上下文而非连接配置。完整模板见仓库 .env.example

用户上下文

client.set_user_context(
    org_id="org-123",
    user_id="user-456",
    role=Role.ACCOUNT,        # ACCOUNT | AGENT | SYSTEM
    actor_id="operator-id",   # 可选,操作者
    user_ip="192.168.1.1",    # 可选,审计日志
)

上下文随每次 gRPC 调用透传到 Server,用于资源归属、权限校验、操作审计。


API 导航

85 个公开方法,分布在 5 个服务中。所有方法的 request_id**metadata 参数均为可选,用于链路追踪和 gRPC metadata 注入,下文参数表中省略。

BlobService (client.blobs) — 15 个方法

方法 说明
upload 上传文件(bytes / Path / URL)
generate_upload_url 获取预签名上传 URL
generate_resumable_upload_url 获取断点续传 URL
confirm_upload_completed 确认上传完成
download 下载文件到本地
download_to_bytes 下载文件到内存
generate_download_url 获取下载 URL
batch_generate_download_url 批量获取下载 URL
get_gcs_url 获取 GCS 对象 URL
batch_get_gcs_url 批量获取 GCS 对象 URL
get_compression_status 查询压缩状态
get_compressed_variants 获取压缩变体列表
trigger_recompression 触发重新压缩
generate_variant_download_url 获取变体下载 URL
batch_get_file_status 批量查询文件状态(上传/压缩/同步)

FileService (client.files) — 13 个方法

方法 说明
get_file 获取文件详情
get_files 批量获取文件详情
list_files 分页列表文件
rename_file 重命名文件
delete_file 删除文件
generate_share_link 创建分享链接
visit_file 记录文件访问
get_compression_status 查询压缩状态
get_compressed_variants 获取压缩变体列表
trigger_recompression 触发重新压缩
generate_variant_download_url 获取变体下载 URL
import_from_gcs 从 GCS 导入文件
generate_signed_gcs_url 生成 GCS 签名 URL

FolderService (client.folders) — 9 个方法

方法 说明
create_folder 创建文件夹
get_folder 查询单个文件夹
get_or_create_default_folder 查询或创建默认根文件夹
rename_folder 重命名文件夹
move_folder 移动文件夹
update_folder 同时更新文件夹名称和/或父文件夹
delete_folder 删除文件夹
list_folders 列出文件夹
list_folder_tree 以树形结构列出文件夹

DocumentService (client.documents) — 12 个方法

方法 说明
create_document 创建文档及初始内容
get_document 按 document_id 或 content_id 获取文档
update_document 更新文档内容和标题
delete_document 删除文档
search_documents 搜索可见文档
list_owner_documents 列出用户拥有的文档
list_recently_visited_documents 列出最近访问文档
share_document 分享文档权限
clone_document 克隆文档到目标 org/user
append_document_content 追加文档内容
update_document_content 更新指定 content 节点
add_document_agent_operations 批量创建 agent operation

TapleService (client.taples) — 36 个方法

表操作

方法 说明
create_table 创建表
get_table 获取表详情(table_id 或 file_id)
update_table 更新表名/描述
delete_table 删除表

Sheet 操作

方法 说明
create_sheet 创建 Sheet
get_sheet 获取 Sheet 详情
list_sheets 列出表内所有 Sheet
update_sheet 更新 Sheet 名/描述/位置
delete_sheet 删除 Sheet
get_sheet_version 获取 Sheet 当前版本号
get_sheet_data 获取 Sheet 完整数据
batch_edit_sheet 批量混合编辑(行/列/单元格)

列操作

方法 说明
create_column 创建列
update_column 更新列属性
delete_column 删除列
batch_edit_columns 批量列操作
get_column_data 获取列数据

行操作

方法 说明
create_row 创建行
update_row 更新行属性
delete_row 删除行
batch_edit_rows 批量行操作
get_row_data 获取行数据

单元格操作

方法 说明
edit_cell 编辑单元格
delete_cell 清空单元格
batch_edit_cells 批量单元格操作
get_cell_data 获取单元格数据

视图操作

方法 说明
create_table_view 创建视图
get_table_view 获取视图
list_table_views 列出视图
update_table_view 更新视图
update_table_view_config 更新视图配置
delete_table_view 删除视图
batch_create_table_views 批量创建视图

导入导出

方法 说明
clone_table_data 克隆表到另一用户/组织
export_table_data 导出表数据
import_table_data 导入数据到表

API 参考

以下示例均使用同步客户端。异步客户端方法签名相同,调用时加 await 即可。

BlobService — 文件传输与变体

blob.upload

上传文件,支持 bytes / 文件路径 / URL 三种输入。

upload(
    file: Union[str, Path, BinaryIO, bytes] = None,
    *,
    folder_id: str = None,
    mode: UploadMode = UploadMode.NORMAL,        # NORMAL | RESUMABLE | STREAM
    is_temporary: bool = False,
    expire_seconds: int = None,
    keep_original_filename: bool = False,
    forbid_overwrite: bool = True,
    url: str = None,                              # 从 URL 拉取上传
    file_name: str = None,
    mime_type: str = None,                        # 显式 MIME,覆盖自动探测
)  FileUploadResponse
from pathlib import Path
from file_hub_client import UploadMode

# 上传字节
result = client.blobs.upload(file=b"hello world")

# 上传本地文件
result = client.blobs.upload(file=Path("/data/photo.jpg"), keep_original_filename=True)

# 断点续传模式
result = client.blobs.upload(file=Path("/data/large.mp4"), mode=UploadMode.RESUMABLE)

# 从 URL 拉取
result = client.blobs.upload(url="https://example.com/data.csv", file_name="data.csv")

# 临时文件(自动过期)
result = client.blobs.upload(file=b"tmp", is_temporary=True, expire_seconds=3600)

blob.generate_upload_url

获取预签名上传 URL,客户端拿到 URL 后自行 PUT 上传。

generate_upload_url(
    file_name: str,
    file_size: int,
    folder_id: str = None,
    file_type: str = "dat",
    mime_type: str = None,
    file_hash: str = None,
    is_temporary: bool = False,
    expire_seconds: int = None,
    keep_original_filename: bool = False,
    forbid_overwrite: bool = True,
)  UploadUrlResponse
resp = client.blobs.generate_upload_url(file_name="report.pdf", file_size=1024 * 1024)
print(resp.upload_url)  # 预签名 PUT URL
print(resp.file.id)     # 已创建的文件 ID

blob.generate_resumable_upload_url

获取断点续传 URL,适用于大文件。

generate_resumable_upload_url(
    file_name: str,
    file_size: int,
    folder_id: str = None,
    file_type: str = "dat",
    mime_type: str = None,
    file_hash: str = None,
    is_temporary: bool = False,
    expire_seconds: int = None,
    keep_original_filename: bool = False,
    forbid_overwrite: bool = False,
)  UploadUrlResponse

blob.confirm_upload_completed

通知 Server 客户端已完成上传(用于预签名 / 断点续传场景)。

confirm_upload_completed(file_id: str)  None
url_resp = client.blobs.generate_resumable_upload_url(file_name="big.zip", file_size=5_000_000_000)
# ... 客户端自行上传到 url_resp.upload_url ...
client.blobs.confirm_upload_completed(file_id=url_resp.upload_file.id)

blob.download

下载文件到本地路径。

download(
    file_id: str,
    *,
    save_path: Union[str, Path] = None,
    chunk_size: int = None,
)  Union[bytes, Path]
client.blobs.download(file_id="file-123", save_path="/local/output.bin")

blob.download_to_bytes

下载文件内容到内存。

download_to_bytes(file_id: str)  bytes
content = client.blobs.download_to_bytes(file_id="file-123")

blob.generate_download_url

获取预签名下载 URL。

generate_download_url(
    file_id: str,
    *,
    is_cdn: bool = True,
    expire_seconds: int = None,
    network_preference: str = None,
)  str
url = client.blobs.generate_download_url(file_id="file-123", expire_seconds=3600)

blob.batch_generate_download_url

批量获取下载 URL。

batch_generate_download_url(
    file_ids: List[str],
    *,
    is_cdn: bool = True,
    expire_seconds: int = None,
    network_preference: str = None,
)  BatchDownloadUrlResponse

blob.get_gcs_url

获取文件的 GCS 对象 URL。

get_gcs_url(file_id: str)  GetGcsUrlResponse

blob.batch_get_gcs_url

批量获取 GCS 对象 URL。

batch_get_gcs_url(file_ids: List[str], *, variant_name: str = "original")  BatchGcsUrlResponse

variant_name 默认 original;指定压缩变体不存在时,服务端会按回退链返回可用版本。

blob.get_compression_status

查询文件压缩状态。

get_compression_status(file_id: str)  CompressionStatusResponse
status = client.blobs.get_compression_status(file_id="image-456")
print(status.status)  # "pending" | "processing" | "completed" | "failed"

blob.get_compressed_variants

获取文件的所有压缩变体信息。

get_compressed_variants(
    file_id: str,
    *,
    variant_type: str = None,          # 按类型过滤
)  GetVariantsResponse
variants = client.blobs.get_compressed_variants(file_id="image-456")
for v in variants.variants:
    print(v.variant_name, v.width, v.height, v.file_size)

blob.trigger_recompression

触发重新压缩。

trigger_recompression(
    file_id: str,
    *,
    force_reprocess: bool = False,
)  RecompressionResponse

blob.generate_variant_download_url

获取指定压缩变体的下载 URL。

generate_variant_download_url(
    file_id: str,
    variant_name: str,                 # e.g. "thumbnail", "medium", "720p"
    *,
    expire_seconds: int = 3600,
    is_cdn: bool = False,
    network_preference: str = None,
)  VariantDownloadUrlResponse
resp = client.blobs.generate_variant_download_url(file_id="img-1", variant_name="thumbnail")
print(resp.url)

blob.batch_get_file_status

批量查询文件的上传 / 压缩 / 同步三态。

batch_get_file_status(
    file_ids: List[str],
    *,
    include_details: bool = False,
)  BatchFileStatusResponse
batch = client.blobs.batch_get_file_status(file_ids=["a", "b"], include_details=True)
for s in batch.statuses:
    print(s.file_id, s.upload_status, s.compression_status, s.sync_status)

FileService — 元数据与分享

file.get_file

获取单个文件详情。

get_file(file_id: str)  GetFileResponse

file.get_files

批量获取文件详情。

get_files(file_ids: List[str])  GetFilesResponse

file.list_files

分页列出文件,支持多维度过滤。

list_files(
    folder_id: str = None,
    file_name: str = None,
    file_type: List[str] = None,
    created_by_role: str = None,       # "account" | "agent" | "system"
    created_by: str = None,
    page_size: int = 20,
    page: int = 1,
)  FileListResponse
resp = client.files.list_files(folder_id="folder-1", file_type=["image", "video"], page_size=50)
for f in resp.files:
    print(f.id, f.file_name)

file.rename_file

rename_file(file_id: str, new_name: str)  File

file.delete_file

delete_file(file_id: str)  None

file.generate_share_link

创建分享链接,支持密码、过期、次数限制。

generate_share_link(
    file_id: str,
    *,
    is_public: bool = True,
    access_scope: str = "view",
    expire_seconds: int = 86400,
    max_access: int = None,
    share_password: str = None,
)  str
share_id = client.files.generate_share_link(
    file_id="file-123",
    expire_seconds=86400 * 7,
    max_access=100,
    share_password="s3cret",
)

file.visit_file

记录文件访问(审计日志)。

visit_file(
    file_share_id: str,
    access_type: str = "view",
    access_duration: int = 0,
    metadata: Dict[str, Any] = None,
)  None

file.get_compression_status

get_compression_status(file_id: str)  CompressionStatusResponse

file.get_compressed_variants

get_compressed_variants(file_id: str, *, variant_type: str = None)  GetVariantsResponse

file.trigger_recompression

trigger_recompression(file_id: str, *, force_reprocess: bool = False)  RecompressionResponse

file.generate_variant_download_url

generate_variant_download_url(
    file_id: str,
    variant_name: str,
    *,
    expire_seconds: int = 3600,
    is_cdn: bool = False,
    network_preference: str = None,
)  VariantDownloadUrlResponse

file.import_from_gcs

从 GCS URI 导入文件元数据。

import_from_gcs(
    gcs_uri: str,
    operation_type: str,
    *,
    folder_id: str = None,
    file_name: str = None,
    keep_original_filename: bool = False,
    created_by_role: str = None,
    created_by: str = None,
)  ImportFromGcsResponse
resp = client.files.import_from_gcs(
    gcs_uri="gs://bucket/path/to/file.pdf",
    operation_type="copy",
    folder_id="folder-1",
)

file.generate_signed_gcs_url

生成 GCS 签名 URL。

generate_signed_gcs_url(gcs_uri: str, *, expire_seconds: int = None)  SignedGcsUrlResponse

FolderService — 文件夹管理

folder.create_folder

create_folder(folder_name: str, *, parent_id: str = None)  FolderInfo
folder = client.folders.create_folder(folder_name="Documents", parent_id="root")

folder.get_folder

get_folder(folder_id: str)  FolderInfo

folder.get_or_create_default_folder

get_or_create_default_folder(default_folder_name: str)  FolderInfo

folder.rename_folder

rename_folder(folder_id: str, new_name: str)  FolderInfo

folder.move_folder

move_folder(folder_id: str, new_parent_id: str)  FolderInfo

folder.update_folder

update_folder(
    folder_id: str,
    folder_name: str = None,
    parent_id: str = None,
    parent_id_provided: bool = False,
)  FolderInfo

folder.delete_folder

delete_folder(folder_id: str)  None

folder.list_folders

list_folders(
    parent_id: str = None,
    folder_name: str = None,
    created_by_role: str = None,
    created_by: str = None,
)  FolderListResponse
folders = client.folders.list_folders(parent_id="root")
for f in folders.items:
    print(f.id, f.folder_name)

folder.list_folder_tree

list_folder_tree()  FolderTreeResponse

DocumentService — 文档管理

document.create_document

create_document(
    title: str,
    content: dict = None,
    *,
    folder_id: str = None,
    default_folder_name: str = None,
)  DocumentWithContentResponse
doc = client.documents.create_document(
    title="会议纪要",
    content={"blocks": []},
    folder_id="folder-1",
)
print(doc.document.id, doc.content)

document.get_document

get_document(
    *,
    document_id: str = None,
    content_id: str = None,
    record_visit: bool = False,
    ip_address: str = None,
    device: str = None,
    referrer: str = None,
)  DocumentWithContentResponse

document.update_document

update_document(
    document_id: str,
    content: dict,
    *,
    title: str = None,
)  DocumentWithContentResponse

document.delete_document

delete_document(document_id: str)  None

document.search_documents

search_documents(
    *,
    search_text: str = None,
    limit: int = 100,
    offset: int = 0,
)  DocumentListResponse

document.list_owner_documents

list_owner_documents(
    *,
    user_id: str = None,
    limit: int = 100,
    offset: int = 0,
)  DocumentListResponse

document.list_recently_visited_documents

list_recently_visited_documents(
    *,
    user_id: str = None,
    limit: int = 100,
    offset: int = 0,
)  DocumentListResponse

document.share_document

share_document(
    document_id: str,
    target_user_id: str,
    *,
    permission_type: str = "viewer",
)  DocumentPermissionResponse

document.clone_document

clone_document(
    source_document_id: str,
    target_org_id: str,
    target_user_id: str,
    *,
    target_folder_id: str = None,
    new_document_title: str = None,
    default_folder_name: str = None,
)  CloneDocumentResponse

document.append_document_content

append_document_content(
    document_id: str,
    content: dict,
    *,
    target_org_id: str = None,
    target_user_id: str = None,
)  AppendDocumentContentResponse

document.update_document_content

update_document_content(
    document_id: str,
    content_id: str,
    content: dict,
    *,
    target_org_id: str = None,
    target_user_id: str = None,
)  DocumentWithContentResponse

document.add_document_agent_operations

add_document_agent_operations(operations: List[Dict[str, Any]])  AddDocumentAgentOperationsResponse

TapleService — 协同电子表格

Taple 操作支持 idempotency_key 参数实现幂等;行/列/单元格操作支持 sheet_version(乐观锁)和 client_id(客户端标识)。

taple.create_table

create_table(
    name: str,
    *,
    folder_id: str = None,
    description: str = None,
    idempotency_key: str = None,
)  TableResponse
table = client.taples.create_table(name="Sales Q1", folder_id="folder-1")

taple.get_table

通过 table_idfile_id 获取表详情。

get_table(*, table_id: str = None, file_id: str = None)  TableResponse

taple.update_table

update_table(table_id: str, *, name: str = None, description: str = None)  TableResponse

taple.delete_table

delete_table(table_id: str)  None

taple.create_sheet

create_sheet(
    table_id: str,
    name: str,
    *,
    description: str = None,
    position: int = None,
)  SheetResponse

taple.get_sheet

get_sheet(sheet_id: str)  SheetResponse

taple.list_sheets

list_sheets(table_id: str)  ListSheetsResponse

taple.update_sheet

update_sheet(
    sheet_id: str,
    *,
    name: str = None,
    description: str = None,
    position: int = None,
)  SheetResponse

taple.delete_sheet

delete_sheet(sheet_id: str)  None

taple.get_sheet_version

获取 Sheet 当前版本号(用于乐观锁)。

get_sheet_version(sheet_id: str)  Any

taple.get_sheet_data

获取 Sheet 完整数据,可指定版本。

get_sheet_data(sheet_id: str, version: int = None)  Any

taple.batch_edit_sheet

批量混合编辑,一次请求中包含行/列/单元格操作。

batch_edit_sheet(
    sheet_id: str,
    operations: List[Any],
    sheet_version: int = None,
    client_id: str = None,
)  Any

taple.create_column

create_column(
    sheet_id: str,
    name: str,
    column_type: str = "text",
    *,
    sheet_version: int = None,
    client_id: str = None,
    position: int = None,
    width: int = None,
    description: str = None,
    properties: Dict[str, Any] = None,
)  ColumnResponse
col = client.taples.create_column(sheet_id="sheet-1", name="Revenue", column_type="number")

taple.update_column

update_column(
    sheet_id: str,
    column_key: str,
    *,
    sheet_version: int = None,
    client_id: str = None,
    name: str = None,
    column_type: str = None,
    width: int = None,
    hidden: bool = None,
    description: str = None,
    properties: Dict[str, Any] = None,
)  ColumnResponse

taple.delete_column

delete_column(
    sheet_id: str,
    column_key: str,
    *,
    sheet_version: int = None,
    client_id: str = None,
)  None

taple.batch_edit_columns

batch_edit_columns(
    sheet_id: str,
    operations: List[Dict[str, Any]],
    *,
    sheet_version: int = None,
    client_id: str = None,
)  Any

taple.get_column_data

get_column_data(sheet_id: str, column_key: str)  Any

taple.create_row

create_row(
    sheet_id: str,
    *,
    sheet_version: int = None,
    client_id: str = None,
    position: int = None,
    height: int = None,
    hidden: bool = None,
)  RowResponse

taple.update_row

update_row(
    sheet_id: str,
    row_key: str,
    *,
    sheet_version: int = None,
    client_id: str = None,
    position: int = None,
    height: int = None,
    hidden: bool = None,
)  RowResponse

taple.delete_row

delete_row(
    sheet_id: str,
    row_key: str,
    *,
    sheet_version: int = None,
    client_id: str = None,
)  None

taple.batch_edit_rows

batch_edit_rows(
    sheet_id: str,
    operations: List[Dict[str, Any]],
    *,
    sheet_version: int = None,
    client_id: str = None,
)  Any

taple.get_row_data

get_row_data(sheet_id: str, row_key: str)  Any

taple.edit_cell

编辑单元格内容。

edit_cell(
    sheet_id: str,
    column_key: str,
    row_key: str,
    *,
    sheet_version: int = None,
    client_id: str = None,
    raw_value: str = None,
    formatted_value: str = None,
    formula: str = None,
    data_type: str = None,
    styles: Dict[str, Any] = None,
)  CellResponse
client.taples.edit_cell(
    sheet_id="sheet-1",
    column_key="col-revenue",
    row_key="row-1",
    raw_value="15000",
    data_type="number",
)

taple.delete_cell

delete_cell(
    sheet_id: str,
    column_key: str,
    row_key: str,
    *,
    sheet_version: int = None,
    client_id: str = None,
)  None

taple.batch_edit_cells

batch_edit_cells(
    sheet_id: str,
    operations: List[Dict[str, Any]],
    *,
    sheet_version: int = None,
    client_id: str = None,
)  Any
client.taples.batch_edit_cells(
    sheet_id="sheet-1",
    operations=[
        {"column_key": "col-name", "row_key": "row-1", "raw_value": "Alice"},
        {"column_key": "col-name", "row_key": "row-2", "raw_value": "Bob"},
    ],
)

taple.get_cell_data

get_cell_data(sheet_id: str, column_key: str, row_key: str)  Any

taple.create_table_view

create_table_view(
    sheet_id: str,
    name: str,
    view_type: str,
    *,
    filter_criteria: Dict[str, Any] = None,
    sort_criteria: Dict[str, Any] = None,
    visible_columns: Dict[str, bool] = None,
    group_criteria: Dict[str, Any] = None,
    is_hidden: bool = False,
    is_default: bool = False,
    config: Dict[str, Any] = None,
)  TableViewResponse
view = client.taples.create_table_view(
    sheet_id="sheet-1",
    name="High Revenue",
    view_type="filter",
    filter_criteria={"column": "Revenue", "operator": ">", "value": "10000"},
    sort_criteria={"column": "Revenue", "order": "desc"},
)

taple.get_table_view

get_table_view(view_id: str)  TableViewResponse

taple.list_table_views

list_table_views(
    *,
    table_id: str = None,
    sheet_id: str = None,
    view_type: str = None,
)  ListTableViewsResponse

taple.update_table_view

update_table_view(
    view_id: str,
    *,
    name: str = None,
    filter_criteria: Dict[str, Any] = None,
    sort_criteria: Dict[str, Any] = None,
    visible_columns: Dict[str, bool] = None,
    group_criteria: Dict[str, Any] = None,
    is_hidden: bool = None,
    is_default: bool = None,
    config: Dict[str, Any] = None,
)  TableViewResponse

taple.update_table_view_config

快捷更新视图配置(仅 config 字段)。

update_table_view_config(view_id: str, config: Dict[str, Any])  TableViewResponse

taple.delete_table_view

delete_table_view(view_id: str)  None

taple.batch_create_table_views

batch_create_table_views(sheet_id: str, views: List[Dict[str, Any]])  BatchCreateTableViewsResponse

taple.clone_table_data

克隆表到另一用户/组织。

clone_table_data(
    source_table_id: str,
    target_org_id: str,
    target_user_id: str,
    *,
    target_folder_id: str = None,
    new_table_name: str = None,
    include_views: bool = False,
)  CloneTableDataResponse
clone = client.taples.clone_table_data(
    source_table_id="table-1",
    target_org_id="org-other",
    target_user_id="user-other",
    new_table_name="Sales Copy",
    include_views=True,
)

taple.export_table_data

导出表数据,支持多种格式。

export_table_data(
    table_id: str,
    format: ExportFormat,              # CSV | XLSX | JSON | PDF | DOCX | PPTX | HTML | MARKDOWN
    *,
    sheet_ids: List[str] = None,
    options: Dict[str, Any] = None,
)  ExportTableDataResponse
from file_hub_client import ExportFormat

export = client.taples.export_table_data(table_id="table-1", format=ExportFormat.CSV)
# export.exported_file_id 可通过 blobs.download 下载

taple.import_table_data

从文件导入数据到表。

import_table_data(
    file_id: str,
    *,
    target_table_id: str = None,       # 导入到已有表
    table_name: str = None,            # 或创建新表
    folder_id: str = None,
    import_mode: str = "APPEND",       # APPEND | OVERWRITE
    skip_first_row: bool = True,
    auto_detect_types: bool = True,
    clear_existing_data: bool = False,
    column_mapping: Dict[str, str] = None,
    date_format: str = "YYYY-MM-DD",
    csv_delimiter: str = ",",
    csv_encoding: str = "UTF-8",
    max_rows: int = 0,                 # 0 = 不限
)  ImportTableDataResponse
# 先上传 CSV
upload = client.blobs.upload(file=Path("/data/sales.csv"))

# 导入到新表
result = client.taples.import_table_data(
    file_id=upload.file.id,
    table_name="Imported Sales",
    folder_id="folder-1",
    import_mode="APPEND",
    auto_detect_types=True,
)

数据模型

所有响应模型基于 Pydantic v2,支持 .model_dump() 序列化。主要类型:

  • 文件:FileUploadFileFileUploadResponseUploadUrlResponseFileListResponseGetFileResponse
  • 压缩:CompressedVariantCompressionStatusResponseGetVariantsResponse
  • 状态枚举:FileUploadStatusFileCompressionStatusFileSyncStatus
  • 状态聚合:FileStatusInfoBatchFileStatusResponse
  • 文件夹:FolderInfoFolderListResponseFolderTreeNodeFolderTreeResponse
  • 文档:DocumentInfoDocumentWithContentResponseDocumentListResponseDocumentPermissionResponse
  • 上下文:UserContextRequestContextRole
  • Taple:TableResponseSheetResponseColumnResponseRowResponseCellResponseTableViewResponse
  • 导入导出:ExportFormatExportTableDataResponseImportTableDataResponseCloneTableDataResponse

异常

全部继承自 FileHubError

异常 触发
FileNotFoundError 文件不存在
FolderNotFoundError 文件夹不存在
DocumentNotFoundError 文档不存在
UploadError 上传失败
DownloadError 下载失败
ExportError 导出 / 转换失败
StorageError 存储后端错误
PermissionError 鉴权 / 权限不足
ValidationError 参数校验失败
ConnectionError gRPC 连接失败
TimeoutError 操作超时

每个异常包含 .code / .message / .details

from file_hub_client.exceptions import FileNotFoundError, UploadError

try:
    client.blobs.download_to_bytes(file_id="nonexistent")
except FileNotFoundError as e:
    print(e.message, e.details)

传输细节

  • 主通道:gRPC over HTTP/2,支持 TLS;SDK 内部以单 channel 起步,并按活跃 RPC 数在请求路径上惰性扩展多 channel。
  • 大文件:上传 / 下载默认通过 Server 签发的预签名 URL 走 HTTP 直传/直下,绕过 gRPC 消息体大小限制;SDK 内置 HttpUploader / HttpDownloader 处理分块、续传、流式。
  • MIME 探测:上传时若未显式提供 mime_type,通过 python-magic 读取魔数自动判定(覆盖 26+ 常见格式)。
  • 重试:仅对明确查询类 gRPC 方法(如 Get / List / Search / BatchGet)在明显传输故障时做一次换 channel failover retry;上传、创建、更新、删除和 Generate*Url 默认不自动重试。

开发

# 编辑安装
pip install -e ".[dev]"

# 生成 gRPC 代码
python make_grpc.py

# 测试
pytest tests/
TEST_MODE=async pytest tests/file/    # 仅异步用例
TEST_MODE=sync  pytest tests/file/    # 仅同步用例

# 构建发行包
python setup.py sdist bdist_wheel

设计要点

  1. 同步 / 异步双 API,签名一致 — 上层应用按运行环境选用,不需要重写业务代码。
  2. gRPC + HTTP 混合传输 — 元数据走 gRPC,大文件走预签名 URL,兼顾低延迟与大对象支持。
  3. 上下文驱动UserContext / RequestContext 在每个调用透传,Server 据此做归属、权限、审计。
  4. 状态聚合接口batch_get_file_status 一次拿到上传 / 压缩 / 同步三态,便于客户端轮询。
  5. 类型完备 — Pydantic v2 + py.typed,IDE 提示与静态检查友好。

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

tamar_file_hub_client-0.3.9.tar.gz (171.0 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

tamar_file_hub_client-0.3.9-py3-none-any.whl (181.1 kB view details)

Uploaded Python 3

File details

Details for the file tamar_file_hub_client-0.3.9.tar.gz.

File metadata

  • Download URL: tamar_file_hub_client-0.3.9.tar.gz
  • Upload date:
  • Size: 171.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.12.8

File hashes

Hashes for tamar_file_hub_client-0.3.9.tar.gz
Algorithm Hash digest
SHA256 0b1b9cebdb5bc3889a2e6f6fb6d20fedbbdbb8d09938e016aa6379f667a9914a
MD5 2f48bdaf6631a2ba81047b838ff70edb
BLAKE2b-256 f715d2499fe4f17a997e793bb32ad6b4eb145a12b4a4d73eb4208eb04580997e

See more details on using hashes here.

File details

Details for the file tamar_file_hub_client-0.3.9-py3-none-any.whl.

File metadata

File hashes

Hashes for tamar_file_hub_client-0.3.9-py3-none-any.whl
Algorithm Hash digest
SHA256 e4d7ffa5ee59f92f31268ec1c60b0355b3b02d664d4c90a9e0638a8799e6efc9
MD5 413432d5ed2d49cccd236d4280cca95e
BLAKE2b-256 a94be42436316b3ba4105430b3bc237bff36fd411723515ece42238fdee2238b

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page