Files
unstract/backend/file_management/views.py
Jaseem Jas ba1df894d2 Python 3.9 to 3.12 (#1231)
* python version updated from 3.9 into 3.12

* x2text-service updated with uv and python version 3.12

* x2text-service docker file updated

* Unstract packages updated with uv

* Runner updated with uv

* Promptservice updated with uv

* Platform service updated with uv

* backend service updated with uv

* root pyproject.toml file updated

* sdk version updated in services

* unstract package modules updated based on sdk version:

* docker file update

* pdm lock workflow modified to support uv

* Docs updated based on uv support

* lock automation updated

* snowflake module version updated into 3.14.0

* tox updated to support UV

* tox updated to support UV

* tox updated with pytest

* tox updated with pytest-md-report

* tox updated with module requirements

* python migration from 3.9 to 3.12

* tox updated with module requirements

* runner updated

* Commit uv.lock changes

* runner updated

* Commit uv.lock changes

* pytest.ini added

* x2text-service docker file updated

* pytest.ini removed

* environment updated to test

* docformatter commented on pre-commit

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* some pre-commit issues ignored

* some pre-commit issues ignored

* some pre-commit issues ignored

* some pre-commit issues ignored

* some pre-commit issues ignored

* pre-commit updates

* un used import removed from platfrom service controller

* tox issue fixed

* tox issue fixed

* docker files updated

* backend dockerfile updated

* open installation issue fixed

* Tools docker file updated with base python version 3.12

* python version updated into min 3.12 in pyproject.toml

* linting issue fixed

* uv version upgraded into 0.6.14

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* migrations excluded from ruff

* added PoethePoet task runner

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* feat: Added poe tasks for services (#1248)

* Added poe tasks for services

* reverted FE change made by mistake

* updated tool-sidecar to uv and python to 3.12.9

* minor updates in pyproject descreption

* feat: platform-service logging improvements (#1255)

feat: Used flask util from core to improve logging in platform-service, added core as a dependency to platform-service:

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: Platform-service build issue and numpy issue with Python 3.12 (#1258)

* fix: Platform-service build and numpy issue with Py 3.12

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* fix: Removed backend dockerfile install statements for numpy

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>

* minor: Handled scenario when cost is not calculated due to no usage

* minor: Corrected content shown for workflow input

* fix: Minor fixes, used gthread for prompt-service, runner

* Commit uv.lock changes

* Removed unused line in tool dockerfile

---------

Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Co-authored-by: Chandrasekharan M <chandrasekharan@zipstack.com>
Co-authored-by: Chandrasekharan M <117059509+chandrasekharan-zipstack@users.noreply.github.com>
Co-authored-by: ali-zipstack <muhammad.ali@zipstack.com>
2025-04-24 16:07:02 +05:30

135 lines
5.5 KiB
Python

import logging
from typing import Any
from connector_v2.models import ConnectorInstance
from django.http import HttpRequest
from oauth2client.client import HttpAccessTokenRefreshError
from prompt_studio.prompt_studio_document_manager_v2.models import DocumentManager
from rest_framework import serializers, status, viewsets
from rest_framework.decorators import action
from rest_framework.response import Response
from rest_framework.versioning import URLPathVersioning
from utils.user_session import UserSessionUtils
from file_management.exceptions import (
ConnectorInstanceNotFound,
ConnectorOAuthError,
FileListError,
)
from file_management.file_management_helper import FileManagerHelper
from file_management.serializer import (
FileInfoIdeSerializer,
FileInfoSerializer,
FileListRequestSerializer,
FileUploadSerializer,
)
from unstract.connectors.exceptions import ConnectorError
from unstract.connectors.filesystems.local_storage.local_storage import LocalStorageFS
logger = logging.getLogger(__name__)
class FileManagementViewSet(viewsets.ModelViewSet):
"""FileManagement view.
Handles GET,POST,PUT,PATCH and DELETE
"""
versioning_class = URLPathVersioning
def get_queryset(self):
return ConnectorInstance.objects.all()
def get_serializer_class(self) -> serializers.Serializer:
if self.action == "upload":
return FileUploadSerializer
elif self.action == "download":
return FileListRequestSerializer
else:
# Default serializer class
return FileListRequestSerializer
def list(self, request: HttpRequest) -> Response:
serializer = FileListRequestSerializer(data=request.GET)
serializer.is_valid(raise_exception=True)
# Query params
id: str = serializer.validated_data.get("connector_id")
path: str = serializer.validated_data.get("path")
try:
connector_instance: ConnectorInstance = ConnectorInstance.objects.get(pk=id)
file_system = FileManagerHelper.get_file_system(connector_instance)
files = FileManagerHelper.list_files(file_system, path)
serializer = FileInfoSerializer(files, many=True)
return Response(serializer.data)
except ConnectorInstance.DoesNotExist:
raise ConnectorInstanceNotFound()
except HttpAccessTokenRefreshError as error:
logger.error(
f"HttpAccessTokenRefreshError thrown from file list, error {error}"
)
raise ConnectorOAuthError()
except ConnectorError as error:
logger.error(f"ConnectorError thrown during file list, error {error}")
raise FileListError(core_err=error)
@action(detail=True, methods=["get"])
def download(self, request: HttpRequest) -> Response:
serializer = FileListRequestSerializer(data=request.GET)
serializer.is_valid(raise_exception=True)
id: str = serializer.validated_data.get("connector_id")
path: str = serializer.validated_data.get("path")
connector_instance: ConnectorInstance = ConnectorInstance.objects.get(pk=id)
file_system = FileManagerHelper.get_file_system(connector_instance)
return FileManagerHelper.download_file(file_system, path)
@action(detail=True, methods=["post"])
def upload(self, request: HttpRequest) -> Response:
serializer = FileUploadSerializer(data=request.data)
serializer.is_valid(raise_exception=True)
id: str = serializer.validated_data.get("connector_id")
path: str = serializer.validated_data.get("path")
uploaded_files: Any = serializer.validated_data.get("file")
connector_instance: ConnectorInstance = ConnectorInstance.objects.get(pk=id)
file_system = FileManagerHelper.get_file_system(connector_instance)
for uploaded_file in uploaded_files:
file_name = uploaded_file.name
logger.info(f"Uploading file: {file_name}" if file_name else "Uploading file")
FileManagerHelper.upload_file(file_system, path, uploaded_file, file_name)
return Response({"message": "Files are uploaded successfully!"})
@action(detail=True, methods=["get"])
def delete(self, request: HttpRequest) -> Response:
serializer = FileInfoIdeSerializer(data=request.GET)
serializer.is_valid(raise_exception=True)
document_id: str = serializer.validated_data.get("document_id")
document: DocumentManager = DocumentManager.objects.get(pk=document_id)
file_name: str = document.document_name
tool_id: str = serializer.validated_data.get("tool_id")
file_path = FileManagerHelper.handle_sub_directory_for_tenants(
UserSessionUtils.get_organization_id(request),
is_create=False,
user_id=request.user.user_id,
tool_id=tool_id,
)
path = file_path
file_system = LocalStorageFS(settings={"path": path})
try:
# Delete the document record
document.delete()
# Delete the file
FileManagerHelper.delete_file(file_system, path, file_name)
return Response(
{"data": "File deleted succesfully."},
status=status.HTTP_200_OK,
)
except Exception as exc:
logger.error(f"Exception thrown from file deletion, error {exc}")
return Response(
{"data": "File deletion failed."},
status=status.HTTP_400_BAD_REQUEST,
)