style: fix all flake8 linter errors across app/ directory
- Run Black formatter and isort on all app/ files - Remove unused imports (F401) across multiple files - Add # noqa: F401 for intentional re-exports in celery_worker.py, tasks/__init__.py, utils.py, frontend.py, views/base.py - Fix f-strings without placeholders (F541) in azure.py, notification.py, check_credentials.py, upload_to_onedrive.py, settings.py - Fix bare except (E722) in upload_to_sftp.py - Fix block comment format (E265) in models.py - Move imports to top of file to fix E402 in celery_app.py, celery_worker.py - Fix line-too-long (E501) by wrapping strings in multiple files - Remove unused variable (F841) in upload_to_nextcloud.py Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
@@ -1,42 +1,44 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
import os
|
||||
import logging
|
||||
import requests
|
||||
import os
|
||||
|
||||
import dropbox
|
||||
import requests
|
||||
from dropbox.exceptions import ApiError, AuthError
|
||||
|
||||
from app.celery_app import celery
|
||||
from app.config import settings
|
||||
from app.tasks.retry_config import BaseTaskWithRetry
|
||||
from app.celery_app import celery
|
||||
from app.utils.filename_utils import get_unique_filename, sanitize_filename, extract_remote_path
|
||||
from app.utils import log_task_progress
|
||||
from app.database import SessionLocal
|
||||
from app.models import FileRecord
|
||||
from app.utils.filename_utils import extract_remote_path, get_unique_filename
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
def _validate_dropbox_settings():
|
||||
"""Validate that all required Dropbox settings are available."""
|
||||
missing = []
|
||||
|
||||
if not hasattr(settings, 'dropbox_refresh_token') or not settings.dropbox_refresh_token:
|
||||
|
||||
if not hasattr(settings, "dropbox_refresh_token") or not settings.dropbox_refresh_token:
|
||||
missing.append("refresh token")
|
||||
|
||||
if not hasattr(settings, 'dropbox_app_key') or not settings.dropbox_app_key:
|
||||
|
||||
if not hasattr(settings, "dropbox_app_key") or not settings.dropbox_app_key:
|
||||
missing.append("app key")
|
||||
|
||||
if not hasattr(settings, 'dropbox_app_secret') or not settings.dropbox_app_secret:
|
||||
|
||||
if not hasattr(settings, "dropbox_app_secret") or not settings.dropbox_app_secret:
|
||||
missing.append("app secret")
|
||||
|
||||
|
||||
if missing:
|
||||
logger.error(f"Cannot refresh Dropbox token: Missing {', '.join(missing)}")
|
||||
return False
|
||||
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def get_dropbox_access_token():
|
||||
"""Refresh the Dropbox access token using the stored refresh token from ENV."""
|
||||
|
||||
|
||||
# Check if needed settings are available
|
||||
if not _validate_dropbox_settings():
|
||||
return None
|
||||
@@ -49,7 +51,7 @@ def get_dropbox_access_token():
|
||||
"client_id": settings.dropbox_app_key,
|
||||
"client_secret": settings.dropbox_app_secret,
|
||||
}
|
||||
|
||||
|
||||
response = requests.post(token_url, headers=headers, data=data, timeout=settings.http_request_timeout)
|
||||
|
||||
if response.status_code == 200:
|
||||
@@ -59,13 +61,14 @@ def get_dropbox_access_token():
|
||||
logger.error(error_msg)
|
||||
raise Exception(error_msg)
|
||||
|
||||
|
||||
def get_dropbox_client():
|
||||
"""
|
||||
Create and return an authenticated Dropbox client using the configured refresh token.
|
||||
Create and return an authenticated Dropbox client using the configured refresh token.
|
||||
|
||||
Returns:
|
||||
dropbox.Dropbox: Authenticated Dropbox client instance
|
||||
dropbox.Dropbox: Authenticated Dropbox client instance
|
||||
|
||||
Raises:
|
||||
ValueError: If required Dropbox configuration is missing
|
||||
AuthError: If authentication with Dropbox fails
|
||||
@@ -73,72 +76,80 @@ def get_dropbox_client():
|
||||
app_key = settings.dropbox_app_key
|
||||
app_secret = settings.dropbox_app_secret
|
||||
refresh_token = settings.dropbox_refresh_token
|
||||
refresh_token = settings.dropbox_refresh_token
|
||||
|
||||
# Validate configuration
|
||||
if not app_key or not app_secret:
|
||||
raise ValueError("Dropbox app key or app secret is not configured")
|
||||
raise ValueError("Dropbox app key or app secret is not configured")
|
||||
|
||||
if not refresh_token:
|
||||
raise ValueError("Dropbox refresh token is not configured")
|
||||
raise ValueError("Dropbox refresh token is not configured")
|
||||
|
||||
# Create a Dropbox client with refresh token
|
||||
try:
|
||||
try:
|
||||
dbx = dropbox.Dropbox(
|
||||
app_key=app_key,
|
||||
app_secret=app_secret,
|
||||
oauth2_refresh_token=refresh_token
|
||||
)
|
||||
dbx = dropbox.Dropbox(app_key=app_key, app_secret=app_secret, oauth2_refresh_token=refresh_token)
|
||||
|
||||
# Test the connection
|
||||
dbx.users_get_current_account()
|
||||
logger.info("Successfully authenticated with Dropbox")
|
||||
return dbx
|
||||
return dbx
|
||||
|
||||
except AuthError as auth_error:
|
||||
logger.error(f"Dropbox authentication failed: {str(auth_error)}")
|
||||
raise
|
||||
raise
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"Error creating Dropbox client: {str(e)}")
|
||||
raise
|
||||
|
||||
|
||||
@celery.task(base=BaseTaskWithRetry, bind=True)
|
||||
def upload_to_dropbox(self, file_path: str, file_id: int = None):
|
||||
"""
|
||||
Upload a file to Dropbox.
|
||||
Upload a file to Dropbox.
|
||||
|
||||
Args:
|
||||
file_path: Path to the file to upload
|
||||
file_id: Optional file ID to associate with logs
|
||||
"""
|
||||
task_id = self.request.id
|
||||
logger.info(f"[{task_id}] Starting Dropbox upload: {file_path}")
|
||||
logger.info(f"[{task_id}] Starting Dropbox upload: {file_path}")
|
||||
log_task_progress(task_id, "upload_to_dropbox", "in_progress", f"Uploading to Dropbox: {os.path.basename(file_path)}", file_id=file_id)
|
||||
log_task_progress(
|
||||
task_id,
|
||||
"upload_to_dropbox",
|
||||
"in_progress",
|
||||
f"Uploading to Dropbox: {os.path.basename(file_path)}",
|
||||
file_id=file_id,
|
||||
)
|
||||
|
||||
if not os.path.exists(file_path):
|
||||
error_msg = f"File not found: {file_path}"
|
||||
logger.error(f"[{task_id}] {error_msg}")
|
||||
log_task_progress(task_id, "upload_to_dropbox", "failure", error_msg, file_id=file_id)
|
||||
raise FileNotFoundError(error_msg)
|
||||
raise FileNotFoundError(error_msg)
|
||||
|
||||
# Check if Dropbox is properly configured
|
||||
# Check if Dropbox is properly configured
|
||||
if not (hasattr(settings, 'dropbox_app_key') and settings.dropbox_app_key and
|
||||
hasattr(settings, 'dropbox_app_secret') and settings.dropbox_app_secret and
|
||||
if not (
|
||||
hasattr(settings, "dropbox_app_key")
|
||||
and settings.dropbox_app_key
|
||||
and hasattr(settings, "dropbox_app_secret")
|
||||
and settings.dropbox_app_secret
|
||||
and hasattr(settings, "dropbox_refresh_token")
|
||||
and settings.dropbox_refresh_token
|
||||
):
|
||||
logger.info(f"[{task_id}] Dropbox upload skipped: Missing configuration")
|
||||
log_task_progress(task_id, "upload_to_dropbox", "success", "Skipped: Not configured", file_id=file_id)
|
||||
return {"status": "Skipped", "reason": "Dropbox settings not configured"}
|
||||
return {"status": "Skipped", "reason": "Dropbox settings not configured"}
|
||||
|
||||
filename = os.path.basename(file_path)
|
||||
filename = os.path.basename(file_path)
|
||||
|
||||
try:
|
||||
# Get the Dropbox client
|
||||
dbx = get_dropbox_client()
|
||||
dbx = get_dropbox_client()
|
||||
|
||||
# Calculate remote path based on local file structure
|
||||
remote_base = settings.dropbox_folder or ""
|
||||
remote_path = extract_remote_path(file_path, settings.workdir, remote_base)
|
||||
remote_path = extract_remote_path(file_path, settings.workdir, remote_base)
|
||||
|
||||
# Function to check if file exists in Dropbox
|
||||
def check_exists_in_dropbox(path):
|
||||
try:
|
||||
@@ -148,29 +159,29 @@ def upload_to_dropbox(self, file_path: str, file_id: int = None):
|
||||
if e.error.is_path() and e.error.get_path().is_not_found():
|
||||
return False
|
||||
raise
|
||||
raise
|
||||
|
||||
# Get a unique path in case of collision
|
||||
remote_full_path = f"/{remote_path}" # Dropbox paths should start with /
|
||||
remote_full_path = f"/{remote_path}" # Dropbox paths should start with /
|
||||
remote_full_path = remote_full_path.replace('//', '/') # Clean double slashes
|
||||
remote_full_path = remote_full_path.replace("//", "/") # Clean double slashes
|
||||
|
||||
# Check for potential file collision and get a unique name if needed
|
||||
dropbox_path = get_unique_filename(remote_full_path, check_exists_in_dropbox)
|
||||
dropbox_path = get_unique_filename(remote_full_path, check_exists_in_dropbox)
|
||||
|
||||
# Upload the file
|
||||
logger.info(f"[{task_id}] Uploading {filename} to Dropbox at {dropbox_path}")
|
||||
log_task_progress(task_id, "upload_file", "in_progress", f"Uploading to {dropbox_path}", file_id=file_id)
|
||||
log_task_progress(task_id, "upload_file", "in_progress", f"Uploading to {dropbox_path}", file_id=file_id)
|
||||
with open(file_path, "rb") as file_data:
|
||||
# Use files_upload_session for large files to avoid timeouts
|
||||
file_size = os.path.getsize(file_path)
|
||||
if file_size > 10 * 1024 * 1024: # 10 MB threshold for chunked upload
|
||||
cursor = None
|
||||
chunk_size = 4 * 1024 * 1024 # 4 MB chunks
|
||||
file_data.seek(0)
|
||||
file_data.seek(0)
|
||||
|
||||
# Start upload session
|
||||
session_start = dbx.files_upload_session_start(file_data.read(chunk_size))
|
||||
cursor = dropbox.files.UploadSessionCursor(session_start.session_id, file_data.tell())
|
||||
cursor = dropbox.files.UploadSessionCursor(session_start.session_id, file_data.tell())
|
||||
|
||||
# Upload chunks until we reach the end
|
||||
while file_data.tell() < file_size:
|
||||
if (file_size - file_data.tell()) <= chunk_size:
|
||||
@@ -178,7 +189,7 @@ def upload_to_dropbox(self, file_path: str, file_id: int = None):
|
||||
dbx.files_upload_session_finish(
|
||||
file_data.read(chunk_size),
|
||||
cursor,
|
||||
cursor,
|
||||
dropbox.files.CommitInfo(path=dropbox_path, mode=dropbox.files.WriteMode.overwrite),
|
||||
)
|
||||
else:
|
||||
# More chunks to upload
|
||||
@@ -187,20 +198,14 @@ def upload_to_dropbox(self, file_path: str, file_id: int = None):
|
||||
else:
|
||||
# Small file, direct upload
|
||||
file_data.seek(0)
|
||||
file_data.seek(0)
|
||||
dbx.files_upload(
|
||||
file_data.read(),
|
||||
dropbox_path,
|
||||
mode=dropbox.files.WriteMode.overwrite
|
||||
)
|
||||
dbx.files_upload(file_data.read(), dropbox_path, mode=dropbox.files.WriteMode.overwrite)
|
||||
|
||||
logger.info(f"[{task_id}] Successfully uploaded {filename} to Dropbox at {dropbox_path}")
|
||||
logger.info(f"[{task_id}] Successfully uploaded {filename} to Dropbox at {dropbox_path}")
|
||||
log_task_progress(task_id, "upload_to_dropbox", "success", f"Uploaded to Dropbox: {dropbox_path}", file_id=file_id)
|
||||
return {
|
||||
"status": "Completed",
|
||||
"file_path": file_path,
|
||||
"dropbox_path": dropbox_path
|
||||
}
|
||||
log_task_progress(
|
||||
task_id, "upload_to_dropbox", "success", f"Uploaded to Dropbox: {dropbox_path}", file_id=file_id
|
||||
)
|
||||
return {"status": "Completed", "file_path": file_path, "dropbox_path": dropbox_path}
|
||||
|
||||
except AuthError:
|
||||
error_msg = f"Authentication failed while uploading {filename} to Dropbox. Check token."
|
||||
logger.error(f"[{task_id}] {error_msg}")
|
||||
|
||||
Reference in New Issue
Block a user