-
Notifications
You must be signed in to change notification settings - Fork 8
Python(feat): Remote Files API #366
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Changes from all commits
Commits
Show all changes
135 commits
Select commit
Hold shift + click to select a range
6658b4b
Added remote files to python client
andrew-siftstack 127fdbf
Clean up files
andrew-siftstack fcd7bdb
clean up
andrew-siftstack 4b88663
format
andrew-siftstack 24040a3
clean up
andrew-siftstack b43b279
Annotation -> asset
andrew-siftstack ce28cec
cleanup
andrew-siftstack b215634
cleanup
andrew-siftstack 28dc8c9
remote files has no high level api and must be accessed via their entity
andrew-siftstack dde1af3
lint
andrew-siftstack afb2cd9
clean up
andrew-siftstack f7a5725
clean up
andrew-siftstack a77acef
fix import cycle
andrew-siftstack cc91882
Merge branch 'main' into python/remote_files
andrew-siftstack 669735e
format
andrew-siftstack 4fe0fb9
Merge branch 'python/remote_files' of https://github.com/sift-stack/s…
andrew-siftstack 50df4d0
cleanup
andrew-siftstack 350673a
cleanup
andrew-siftstack c5561e0
clean up
andrew-siftstack c575387
cleanup
andrew-siftstack a13a26f
cleanup
andrew-siftstack 35a63c0
sift client passed through low level remote files
andrew-siftstack e16d500
clean up
andrew-siftstack bb88b8d
cleanup
andrew-siftstack a400416
cleanup
andrew-siftstack d977c45
cleanup
andrew-siftstack ebd53d9
cleanup
andrew-siftstack 21c2cd2
cleanup
andrew-siftstack eae02aa
cleanup
andrew-siftstack 21b464d
cleanup
andrew-siftstack f997848
cleanup
andrew-siftstack 484bdaa
test fixes
andrew-siftstack 1951c44
test fixes
andrew-siftstack 7cc8f59
test fix
andrew-siftstack 86eb728
test fixes
andrew-siftstack 92f2882
test fixes
andrew-siftstack e44727a
test fixes
andrew-siftstack 8217025
test fixes
andrew-siftstack 559797a
Luck/python/remote files (#373)
alexluck-sift dfba223
formatting
andrew-siftstack 616251e
format
andrew-siftstack 53a15a1
cleanup
andrew-siftstack f7e9017
add file attachments api back in
andrew-siftstack 90afb73
format
andrew-siftstack d9a46bd
clean up
andrew-siftstack 69dd11d
test fixes
andrew-siftstack cb9011a
update file attachments
andrew-siftstack a34af86
Merge branch 'main' into python/remote_files
andrew-siftstack e0c8075
clean up
andrew-siftstack bfb3bf3
cleanup
andrew-siftstack efeef8e
Merge branch 'main' of https://github.com/sift-stack/sift into python…
andrew-siftstack 0c13067
cleanup
andrew-siftstack 66e9a8b
format
andrew-siftstack 5fc3d34
clean up
andrew-siftstack df19f31
cleanup
andrew-siftstack 97ab2c2
update interface
andrew-siftstack 8c1d9f4
format
andrew-siftstack b4e3352
cleanup
andrew-siftstack 2eeac8a
cleanup
andrew-siftstack 8cf30a3
cleanup batch delete
andrew-siftstack 6ad71d9
cleanup
andrew-siftstack df3f77f
cleanup
andrew-siftstack 2d91c10
cleanup
andrew-siftstack efbbf29
add file uploads
andrew-siftstack c27086a
ruff check
andrew-siftstack a6faae6
format
andrew-siftstack b9cb983
fix types
andrew-siftstack 8f9f612
format
andrew-siftstack e99170e
small fix
andrew-siftstack 76df1b2
Merge branch 'main' of https://github.com/sift-stack/sift into python…
andrew-siftstack 7f8e2c9
Update sync stubs for file attachments API
andrew-siftstack a573ae6
cleanup
andrew-siftstack d3ce6fc
Merge branch 'main' into python/remote_files
andrew-siftstack bec37f3
cleanup
andrew-siftstack dce8c41
Add missing _run method to FileAttachmentsAPI stubs
andrew-siftstack 951b240
restore rust files
andrew-siftstack 8fa0b46
remove delete from mixin file attachment
andrew-siftstack 80080e3
format
andrew-siftstack c65d283
small fix
andrew-siftstack 2b265d1
Update file attachments list_ method signature in stubs
andrew-siftstack 15b3da3
small fix
andrew-siftstack 1e34e7a
Add entity parameter to file attachments list_ method
andrew-siftstack 01866bf
imports fix
andrew-siftstack 7dc5571
Restore test_value.py that was accidentally deleted
andrew-siftstack 164a013
Restore sift_stream_bindings files to match main
andrew-siftstack 7896a2d
don't use Entity
andrew-siftstack a26b426
add tests and use cel filter
andrew-siftstack 5033bf2
lint fixes
andrew-siftstack e2aeac8
format
andrew-siftstack 009bb9a
type checking
andrew-siftstack 65dcad7
small fix
andrew-siftstack 8580896
small fix
andrew-siftstack 45e4376
small fix
andrew-siftstack 17514ad
white space
andrew-siftstack e860741
circular import
andrew-siftstack 3deb30a
small fixes
andrew-siftstack 3886550
test fix
andrew-siftstack 5a5129b
small fixes
andrew-siftstack 599d14b
format
andrew-siftstack 44124f1
update
andrew-siftstack 9135862
fix
andrew-siftstack cdcad46
remove import
andrew-siftstack 59b1bfe
small fix
andrew-siftstack f77302e
format
andrew-siftstack 53f9be7
small fixes
andrew-siftstack 0ad15de
fix`
andrew-siftstack 05d5f7b
small fix
andrew-siftstack b029190
update stubs
andrew-siftstack 1d9380f
test fixes
andrew-siftstack 1f22818
Update tests
andrew-siftstack fd70963
Update integration tests
andrew-siftstack 792a624
small fixes
andrew-siftstack 7d5633a
small fixes
andrew-siftstack a0c6b76
format
andrew-siftstack 7ff2187
update stubs
andrew-siftstack d493fd2
add test for downloading remote file
andrew-siftstack a333d93
format
andrew-siftstack aef5177
format
andrew-siftstack 4b2283c
list_ refactor and docs fix (#393)
alexluck-sift 2d28ff7
cleanup
andrew-siftstack deb5d68
remote_files download, update cel filters
andrew-siftstack 3d5167c
format
andrew-siftstack 16dd146
format
andrew-siftstack bb9e731
format
andrew-siftstack d09f6d0
cleanup
andrew-siftstack bc1179e
test fixes
andrew-siftstack 80eee3f
add order by back in
andrew-siftstack 99fe7c6
only 1 type at a time
andrew-siftstack cc1e1db
stub fix
andrew-siftstack f5b0e80
small asyncio change
andrew-siftstack f971341
update docstrings and include TODOs
andrew-siftstack ad9cb59
format
andrew-siftstack de952c1
not implemented error
andrew-siftstack 1421cb7
Merge branch 'main' of https://github.com/sift-stack/sift into python…
andrew-siftstack cc96bc0
Merge branch 'main' of https://github.com/sift-stack/sift into python…
andrew-siftstack File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
204 changes: 204 additions & 0 deletions
204
python/lib/sift_client/_internal/low_level_wrappers/remote_files.py
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,204 @@ | ||
| from __future__ import annotations | ||
|
|
||
| import asyncio | ||
| from typing import TYPE_CHECKING, Any, cast | ||
|
|
||
| import requests | ||
| from sift.remote_files.v1.remote_files_pb2 import ( | ||
| BatchDeleteRemoteFilesRequest, | ||
| DeleteRemoteFileRequest, | ||
| GetRemoteFileDownloadUrlRequest, | ||
| GetRemoteFileRequest, | ||
| GetRemoteFileResponse, | ||
| ListRemoteFilesRequest, | ||
| ListRemoteFilesResponse, | ||
| UpdateRemoteFileRequest, | ||
| UpdateRemoteFileResponse, | ||
| ) | ||
| from sift.remote_files.v1.remote_files_pb2_grpc import RemoteFileServiceStub | ||
|
|
||
| from sift_client._internal.low_level_wrappers.base import ( | ||
| LowLevelClientBase, | ||
| ) | ||
| from sift_client.transport import GrpcClient, WithGrpcClient | ||
|
|
||
| if TYPE_CHECKING: | ||
| from sift_client.client import SiftClient | ||
| from sift_client.sift_types.file_attachment import FileAttachment, FileAttachmentUpdate | ||
|
|
||
|
|
||
| class RemoteFilesLowLevelClient(LowLevelClientBase, WithGrpcClient): | ||
| """Low-level client for the RemoteFilesAPI. | ||
|
|
||
| This class provides a thin wrapper around the autogenerated bindings for the RemoteFilesAPI. | ||
| """ | ||
|
|
||
| def __init__(self, grpc_client: GrpcClient): | ||
| """Initialize the RemoteFilesLowLevelClient. | ||
|
|
||
| Args: | ||
| grpc_client: The gRPC client to use for making API calls. | ||
| """ | ||
| super().__init__(grpc_client) | ||
|
|
||
| async def get_remote_file( | ||
| self, remote_file_id: str, sift_client: SiftClient | None = None | ||
| ) -> FileAttachment: | ||
| """Get a remote file by ID. | ||
|
|
||
| Args: | ||
| remote_file_id: The ID of the remote file to retrieve. | ||
| sift_client: The SiftClient to attach to the returned RemoteFile. | ||
|
|
||
| Returns: | ||
| The RemoteFile. | ||
| """ | ||
| from sift_client.sift_types.file_attachment import FileAttachment | ||
|
|
||
| request = GetRemoteFileRequest(remote_file_id=remote_file_id) | ||
| response = await self._grpc_client.get_stub(RemoteFileServiceStub).GetRemoteFile(request) | ||
| grpc_remote_file = cast("GetRemoteFileResponse", response).remote_file | ||
| return FileAttachment._from_proto(grpc_remote_file, sift_client) | ||
|
|
||
| async def list_all_remote_files( | ||
| self, | ||
| query_filter: str | None = None, | ||
| max_results: int | None = None, | ||
| page_size: int | None = None, | ||
| order_by: str | None = None, | ||
| sift_client: SiftClient | None = None, | ||
|
alexluck-sift marked this conversation as resolved.
|
||
| ) -> list[FileAttachment]: | ||
| """List all remote files matching the given query. | ||
|
|
||
| Args: | ||
| query_filter: The CEL query filter. | ||
|
|
||
| max_results: The maximum number of results to return. | ||
| page_size: The number of results to return per page. | ||
| order_by: The field to order by. Not supported by the backend, but it is here for API consistency. TODO: Add to backend | ||
| sift_client: The SiftClient to attach to the returned RemoteFiles. | ||
|
|
||
| Returns: | ||
| A list of RemoteFiles matching the given query. | ||
| """ | ||
| return await self._handle_pagination( | ||
| self.list_remote_files, | ||
| kwargs={"query_filter": query_filter, "sift_client": sift_client}, | ||
| page_size=page_size, | ||
| max_results=max_results, | ||
| order_by=order_by, | ||
| ) | ||
|
|
||
| async def list_remote_files( | ||
| self, | ||
| page_size: int | None = None, | ||
| page_token: str | None = None, | ||
| query_filter: str | None = None, | ||
| order_by: str | None = None, | ||
| sift_client: SiftClient | None = None, | ||
| ) -> tuple[list[FileAttachment], str]: | ||
| """List remote files with pagination support. | ||
|
|
||
| Args: | ||
| page_size: The number of results to return per page. | ||
| page_token: The page token for pagination. | ||
| query_filter: The CEL query filter. | ||
| order_by: The field to order by. Not supported by the backend, but it is here for API consistency. TODO: Add to backend | ||
| sift_client: The SiftClient to attach to the returned RemoteFiles. | ||
|
|
||
| Returns: | ||
| A tuple of (list of RemoteFiles, next_page_token). | ||
| """ | ||
| from sift_client.sift_types.file_attachment import FileAttachment | ||
|
|
||
| if order_by is not None: | ||
| raise NotImplementedError | ||
|
|
||
| request_kwargs: dict[str, Any] = {} | ||
| if page_size is not None: | ||
| request_kwargs["page_size"] = page_size | ||
| if page_token is not None: | ||
| request_kwargs["page_token"] = page_token | ||
| if query_filter is not None: | ||
| request_kwargs["filter"] = query_filter | ||
|
|
||
| request = ListRemoteFilesRequest(**request_kwargs) | ||
| response = await self._grpc_client.get_stub(RemoteFileServiceStub).ListRemoteFiles(request) | ||
| response = cast("ListRemoteFilesResponse", response) | ||
| return [ | ||
| FileAttachment._from_proto(rf, sift_client) for rf in response.remote_files | ||
| ], response.next_page_token | ||
|
|
||
| async def update_remote_file( | ||
| self, update: FileAttachmentUpdate, sift_client: SiftClient | None = None | ||
| ) -> FileAttachment: | ||
| """Update a remote file. | ||
|
|
||
| Args: | ||
| update: The FileAttachmentUpdate containing the fields to update. | ||
| sift_client: The SiftClient to attach to the returned RemoteFile. | ||
|
|
||
| Returns: | ||
| The updated RemoteFile. | ||
| """ | ||
| from sift_client.sift_types.file_attachment import FileAttachment | ||
|
|
||
| grpc_remote_file, update_mask = update.to_proto_with_mask() | ||
| request = UpdateRemoteFileRequest(remote_file=grpc_remote_file, update_mask=update_mask) | ||
| response = await self._grpc_client.get_stub(RemoteFileServiceStub).UpdateRemoteFile(request) | ||
| updated_grpc_remote_file = cast("UpdateRemoteFileResponse", response).remote_file | ||
| return FileAttachment._from_proto(updated_grpc_remote_file, sift_client) | ||
|
|
||
| async def delete_remote_file(self, remote_file_id: str) -> None: | ||
| """Delete a remote file. | ||
|
|
||
| Args: | ||
| remote_file_id: The ID of the remote file to delete. | ||
| """ | ||
| request = DeleteRemoteFileRequest(remote_file_id=remote_file_id) | ||
| await self._grpc_client.get_stub(RemoteFileServiceStub).DeleteRemoteFile(request) | ||
|
|
||
| async def batch_delete_remote_files(self, remote_file_ids: list[str]) -> None: | ||
| """Batch delete remote files. | ||
|
|
||
| Args: | ||
| remote_file_ids: The IDs of the remote files to delete (up to 1000). | ||
| """ | ||
| request = BatchDeleteRemoteFilesRequest(remote_file_ids=remote_file_ids) | ||
| await self._grpc_client.get_stub(RemoteFileServiceStub).BatchDeleteRemoteFiles(request) | ||
|
|
||
| async def get_remote_file_download_url(self, remote_file_id: str) -> str: | ||
| """Get a download URL for a remote file. | ||
|
|
||
| Args: | ||
| remote_file_id: The ID of the remote file. | ||
|
|
||
| Returns: | ||
| The download URL for the remote file. | ||
| """ | ||
| request = GetRemoteFileDownloadUrlRequest(remote_file_id=remote_file_id) | ||
| response = await self._grpc_client.get_stub(RemoteFileServiceStub).GetRemoteFileDownloadUrl( | ||
| request | ||
| ) | ||
| return response.download_url | ||
|
|
||
| async def download_remote_file(self, file_attachment: FileAttachment) -> bytes: | ||
| """Download a remote file. | ||
|
|
||
| Args: | ||
| file_attachment: The FileAttachment to download. | ||
|
|
||
| Returns: | ||
| The downloaded file. | ||
| """ | ||
| url = await self.get_remote_file_download_url(file_attachment._id_or_error) | ||
|
|
||
| # Run the synchronous requests.get in a thread pool to avoid blocking | ||
| def _download(): | ||
| response = requests.get(url) | ||
| response.raise_for_status() | ||
| return response.content | ||
|
|
||
| # Use run_in_executor for Python 3.8 compatibility (asyncio.to_thread was added in 3.9) | ||
| loop = asyncio.get_event_loop() | ||
| return await loop.run_in_executor(None, _download) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,13 @@ | ||
| # Sift Python | ||
|
|
||
| ## Running Integration Tests Locally | ||
|
|
||
| 1. Create Environmental Variables | ||
| a. Create or open a .env file in /python | ||
| b. Add an API key for SIFT_API_KEY | ||
| 2. Start Local Sift | ||
| 3. Asset Data: NostromoLV426 | ||
| a. Ensure that your local Sift instance contains data for the asset NostromoLV426 | ||
| b. If it doesn't them export data for NostromoLV426 from development | ||
| 4. Run tests | ||
| a. Run tests using /python/scripts/dev {test, test-integration, test-all} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.