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,23 +1,23 @@
|
||||
import os
|
||||
import logging
|
||||
import os
|
||||
|
||||
import azure.core.exceptions
|
||||
import PyPDF2
|
||||
from azure.core.credentials import AzureKeyCredential
|
||||
from azure.ai.documentintelligence import DocumentIntelligenceClient
|
||||
from azure.ai.documentintelligence.models import AnalyzeOutputOption, AnalyzeResult
|
||||
import azure.core.exceptions
|
||||
from azure.core.credentials import AzureKeyCredential
|
||||
|
||||
from app.celery_app import celery
|
||||
from app.config import settings
|
||||
from app.tasks.retry_config import BaseTaskWithRetry
|
||||
from app.tasks.rotate_pdf_pages import rotate_pdf_pages
|
||||
from app.celery_app import celery
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# Initialize Azure Document Intelligence client with error handling
|
||||
try:
|
||||
document_intelligence_client = DocumentIntelligenceClient(
|
||||
endpoint=settings.azure_endpoint,
|
||||
credential=AzureKeyCredential(settings.azure_ai_key)
|
||||
endpoint=settings.azure_endpoint, credential=AzureKeyCredential(settings.azure_ai_key)
|
||||
)
|
||||
logger.info("Azure Document Intelligence client initialized successfully")
|
||||
except (ValueError, azure.core.exceptions.ClientAuthenticationError) as e:
|
||||
@@ -33,36 +33,38 @@ AZURE_DOC_INTELLIGENCE_LIMITS = {
|
||||
"max_pages": 2000,
|
||||
}
|
||||
|
||||
|
||||
def get_pdf_page_count(file_path):
|
||||
"""Get the number of pages in a PDF file."""
|
||||
try:
|
||||
with open(file_path, 'rb') as file:
|
||||
with open(file_path, "rb") as file:
|
||||
pdf_reader = PyPDF2.PdfReader(file)
|
||||
return len(pdf_reader.pages)
|
||||
except Exception as e:
|
||||
logger.error(f"Error getting PDF page count: {e}")
|
||||
return None
|
||||
|
||||
|
||||
def check_page_rotation(result, filename):
|
||||
"""
|
||||
Checks if pages in the document are rotated and logs the rotation information.
|
||||
|
||||
|
||||
Args:
|
||||
result: The AnalyzeResult from Azure Document Intelligence API
|
||||
filename: The name of the file being processed
|
||||
|
||||
|
||||
Returns:
|
||||
dict: Dictionary mapping page indices (integers) to rotation angles
|
||||
"""
|
||||
logger.error(f"Checking rotation for document: {filename}")
|
||||
rotation_data = {}
|
||||
|
||||
if not hasattr(result, 'pages') or not result.pages:
|
||||
|
||||
if not hasattr(result, "pages") or not result.pages:
|
||||
logger.error(f"No page information available for rotation check: {filename}")
|
||||
return rotation_data
|
||||
|
||||
|
||||
for i, page in enumerate(result.pages):
|
||||
if hasattr(page, 'angle'):
|
||||
if hasattr(page, "angle"):
|
||||
rotation_angle = page.angle
|
||||
if rotation_angle != 0:
|
||||
logger.error(f"Page {i+1} is rotated by {rotation_angle} degrees")
|
||||
@@ -72,15 +74,16 @@ def check_page_rotation(result, filename):
|
||||
logger.error(f"Page {i+1} has no rotation (0 degrees)")
|
||||
else:
|
||||
logger.error(f"Page {i+1} rotation information not available")
|
||||
|
||||
|
||||
return rotation_data
|
||||
|
||||
|
||||
@celery.task(base=BaseTaskWithRetry)
|
||||
def process_with_azure_document_intelligence(filename: str, file_id: int = None):
|
||||
"""
|
||||
Processes a PDF document using Azure Document Intelligence and overlays OCR text onto
|
||||
the local temporary file (stored under <workdir>/tmp).
|
||||
|
||||
|
||||
Steps:
|
||||
0. Verify the file meets Azure Document Intelligence service limits
|
||||
1. Uploads the document for OCR using Azure Document Intelligence.
|
||||
@@ -88,7 +91,7 @@ def process_with_azure_document_intelligence(filename: str, file_id: int = None)
|
||||
3. Saves the OCR-processed PDF locally in the same location as before.
|
||||
4. Checks for page rotation and triggers page rotation if needed.
|
||||
5. Triggers downstream metadata extraction.
|
||||
|
||||
|
||||
Args:
|
||||
filename: Name of the file to process
|
||||
file_id: Optional file ID to pass through to subsequent tasks
|
||||
@@ -101,13 +104,15 @@ def process_with_azure_document_intelligence(filename: str, file_id: int = None)
|
||||
# Check file size against service limits
|
||||
file_size = os.path.getsize(tmp_file_path)
|
||||
if file_size > AZURE_DOC_INTELLIGENCE_LIMITS["max_file_size_bytes"]:
|
||||
error_msg = f"File size ({file_size / (1024 * 1024):.2f} MB) exceeds Azure Document Intelligence limit of 500 MB"
|
||||
error_msg = (
|
||||
f"File size ({file_size / (1024 * 1024):.2f} MB) exceeds Azure Document Intelligence limit of 500 MB"
|
||||
)
|
||||
logger.error(error_msg)
|
||||
return {"error": error_msg, "file": filename, "status": "Failed - Size limit exceeded"}
|
||||
|
||||
# For PDF files, check page count against service limits
|
||||
# "Fail open" approach: only reject if we're sure it exceeds the limit
|
||||
if filename.lower().endswith('.pdf'):
|
||||
if filename.lower().endswith(".pdf"):
|
||||
page_count = get_pdf_page_count(tmp_file_path)
|
||||
if page_count is not None and page_count > AZURE_DOC_INTELLIGENCE_LIMITS["max_pages"]:
|
||||
error_msg = f"PDF page count ({page_count}) exceeds Azure Document Intelligence limit of 2000 pages"
|
||||
@@ -130,9 +135,7 @@ def process_with_azure_document_intelligence(filename: str, file_id: int = None)
|
||||
rotation_data = check_page_rotation(result, filename)
|
||||
|
||||
# Retrieve the processed searchable PDF
|
||||
response = document_intelligence_client.get_analyze_result_pdf(
|
||||
model_id=result.model_id, result_id=operation_id
|
||||
)
|
||||
response = document_intelligence_client.get_analyze_result_pdf(model_id=result.model_id, result_id=operation_id)
|
||||
searchable_pdf_path = tmp_file_path # Overwrite the original PDF location
|
||||
with open(searchable_pdf_path, "wb") as writer:
|
||||
writer.writelines(response)
|
||||
|
||||
Reference in New Issue
Block a user