Spaces:
Running
Running
""" | |
Advanced URL & Text Processing Suite - Professional Edition | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
Enterprise-grade application with advanced features, real-time analytics, | |
parallel processing, and sophisticated UI components. | |
""" | |
import gradio as gr | |
import logging | |
import json | |
import os | |
import sys | |
import threading | |
import queue | |
import time | |
from concurrent.futures import ThreadPoolExecutor, ProcessPoolExecutor | |
from datetime import datetime | |
from pathlib import Path | |
from typing import Dict, List, Optional, Union, Any, Tuple | |
from dataclasses import dataclass, asdict | |
import numpy as np | |
import pandas as pd | |
from url_processor import URLProcessor | |
from file_processor import FileProcessor | |
from qr_processor import QRProcessor | |
# Configure advanced logging with rotation | |
from logging.handlers import RotatingFileHandler | |
log_handler = RotatingFileHandler( | |
'urld_pro.log', | |
maxBytes=10*1024*1024, # 10MB | |
backupCount=5 | |
) | |
log_handler.setFormatter( | |
logging.Formatter('%(asctime)s.%(msecs)03d [%(levelname)s] %(name)s - %(message)s') | |
) | |
logger = logging.getLogger(__name__) | |
logger.addHandler(log_handler) | |
logger.setLevel(logging.INFO) | |
# Advanced Theme Configuration | |
THEME = gr.themes.Soft( | |
primary_hue=gr.themes.colors.indigo, | |
secondary_hue=gr.themes.colors.blue, | |
neutral_hue=gr.themes.colors.slate, | |
spacing_size=gr.themes.sizes.spacing_lg, | |
radius_size=gr.themes.sizes.radius_lg, | |
text_size=gr.themes.sizes.text_lg, | |
).set( | |
body_background_fill="*background_fill_secondary", | |
button_primary_background_fill="*primary_500", | |
button_primary_background_fill_hover="*primary_600", | |
button_primary_text_color="white", | |
button_primary_border_color="*primary_500", | |
button_secondary_background_fill="*secondary_500", | |
button_secondary_background_fill_hover="*secondary_600", | |
button_secondary_text_color="white", | |
button_secondary_border_color="*secondary_500", | |
) | |
# Enhanced CSS with advanced animations and modern design | |
CUSTOM_CSS = """ | |
@import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap'); | |
:root { | |
--primary-color: #4f46e5; | |
--secondary-color: #2563eb; | |
--success-color: #059669; | |
--error-color: #dc2626; | |
--warning-color: #d97706; | |
--info-color: #2563eb; | |
} | |
body { | |
font-family: 'Inter', sans-serif; | |
} | |
.container { | |
max-width: 1400px !important; | |
margin: auto !important; | |
padding: 2rem !important; | |
} | |
.pro-header { | |
text-align: center; | |
margin-bottom: 2rem; | |
padding: 2rem; | |
background: linear-gradient(135deg, var(--primary-color) 0%, var(--secondary-color) 100%); | |
border-radius: 1rem; | |
color: white; | |
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1); | |
} | |
.pro-header h1 { | |
font-size: 2.5rem; | |
font-weight: 700; | |
margin-bottom: 1rem; | |
} | |
.pro-header p { | |
font-size: 1.25rem; | |
opacity: 0.9; | |
} | |
.dashboard { | |
display: grid; | |
grid-template-columns: repeat(auto-fit, minmax(300px, 1fr)); | |
gap: 1rem; | |
margin-bottom: 2rem; | |
} | |
.stat-card { | |
background: white; | |
padding: 1.5rem; | |
border-radius: 1rem; | |
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1), 0 1px 2px -1px rgb(0 0 0 / 0.1); | |
transition: transform 0.2s ease; | |
} | |
.stat-card:hover { | |
transform: translateY(-2px); | |
} | |
.chart-container { | |
background: white; | |
padding: 1rem; | |
border-radius: 1rem; | |
box-shadow: 0 1px 3px 0 rgb(0 0 0 / 0.1); | |
margin-bottom: 1rem; | |
} | |
.pro-tab { | |
transition: all 0.3s ease; | |
} | |
.pro-tab:hover { | |
transform: translateY(-1px); | |
} | |
.pro-button { | |
transition: all 0.2s ease; | |
} | |
.pro-button:hover { | |
transform: translateY(-1px); | |
box-shadow: 0 4px 6px -1px rgb(0 0 0 / 0.1); | |
} | |
.pro-button:active { | |
transform: translateY(0); | |
} | |
.status-message { | |
padding: 1rem; | |
border-radius: 0.5rem; | |
margin: 1rem 0; | |
animation: slideIn 0.3s ease; | |
} | |
.status-message.success { | |
background: #ecfdf5; | |
border: 1px solid var(--success-color); | |
color: var(--success-color); | |
} | |
.status-message.error { | |
background: #fef2f2; | |
border: 1px solid var(--error-color); | |
color: var(--error-color); | |
} | |
.status-message.warning { | |
background: #fffbeb; | |
border: 1px solid var(--warning-color); | |
color: var(--warning-color); | |
} | |
@keyframes slideIn { | |
from { | |
opacity: 0; | |
transform: translateY(-10px); | |
} | |
to { | |
opacity: 1; | |
transform: translateY(0); | |
} | |
} | |
.loading { | |
position: relative; | |
} | |
.loading::after { | |
content: ''; | |
position: absolute; | |
top: 0; | |
left: 0; | |
width: 100%; | |
height: 100%; | |
background: linear-gradient( | |
90deg, | |
rgba(255,255,255,0) 0%, | |
rgba(255,255,255,0.2) 50%, | |
rgba(255,255,255,0) 100% | |
); | |
animation: shimmer 1.5s infinite; | |
} | |
@keyframes shimmer { | |
0% { | |
transform: translateX(-100%); | |
} | |
100% { | |
transform: translateX(100%); | |
} | |
} | |
.pro-footer { | |
text-align: center; | |
margin-top: 3rem; | |
padding: 2rem; | |
background: #f8fafc; | |
border-radius: 1rem; | |
box-shadow: 0 -1px 3px 0 rgb(0 0 0 / 0.1); | |
} | |
""" | |
class ProcessingStats: | |
"""Data class for tracking processing statistics""" | |
total_urls: int = 0 | |
successful_urls: int = 0 | |
failed_urls: int = 0 | |
total_files: int = 0 | |
successful_files: int = 0 | |
failed_files: int = 0 | |
total_qr_codes: int = 0 | |
successful_qr_codes: int = 0 | |
failed_qr_codes: int = 0 | |
processing_time: float = 0.0 | |
last_updated: str = datetime.now().isoformat() | |
class AdvancedProInterface: | |
"""Professional interface with advanced features and real-time analytics""" | |
def __init__(self): | |
"""Initialize the professional interface with advanced components""" | |
self.url_processor = URLProcessor() | |
self.file_processor = FileProcessor() | |
self.qr_processor = QRProcessor() | |
self.stats = ProcessingStats() | |
self.processing_queue = queue.Queue() | |
self.thread_pool = ThreadPoolExecutor(max_workers=10) | |
self.process_pool = ProcessPoolExecutor(max_workers=4) | |
self.processing_history: List[Dict] = [] | |
# Initialize real-time monitoring | |
self._start_monitoring() | |
def _start_monitoring(self): | |
"""Start background monitoring thread""" | |
def monitor(): | |
while True: | |
try: | |
# Update statistics | |
self.stats.last_updated = datetime.now().isoformat() | |
# Process queued items | |
while not self.processing_queue.empty(): | |
item = self.processing_queue.get_nowait() | |
self._process_queued_item(item) | |
time.sleep(1) | |
except Exception as e: | |
logger.error(f"Monitoring error: {e}") | |
threading.Thread(target=monitor, daemon=True).start() | |
def _process_queued_item(self, item: Dict): | |
"""Process queued items with advanced error handling""" | |
try: | |
item_type = item.get('type') | |
if item_type == 'url': | |
self._process_url_item(item) | |
elif item_type == 'file': | |
self._process_file_item(item) | |
elif item_type == 'qr': | |
self._process_qr_item(item) | |
except Exception as e: | |
logger.error(f"Queue processing error: {e}") | |
def _process_url_item(self, item: Dict): | |
"""Process URL items with advanced features""" | |
try: | |
start_time = time.time() | |
results = self.url_processor.process_urls([item['url']], mode=item['mode']) | |
processing_time = time.time() - start_time | |
self.stats.total_urls += 1 | |
if any('error' in r for r in results): | |
self.stats.failed_urls += 1 | |
else: | |
self.stats.successful_urls += 1 | |
self.stats.processing_time += processing_time | |
# Update history | |
self.processing_history.append({ | |
'timestamp': datetime.now().isoformat(), | |
'type': 'url', | |
'url': item['url'], | |
'results': results, | |
'processing_time': processing_time | |
}) | |
except Exception as e: | |
logger.error(f"URL processing error: {e}") | |
self.stats.failed_urls += 1 | |
async def process_urls_parallel(self, urls: str, mode: str) -> Tuple[str, str, str, Dict]: | |
"""Process URLs in parallel with advanced features""" | |
try: | |
url_list = [url.strip() for url in urls.split('\n') if url.strip()] | |
if not url_list: | |
return "", "⚠️ No valid URLs provided", "", {} | |
start_time = time.time() | |
# Process URLs in parallel | |
futures = [] | |
for url in url_list: | |
future = self.thread_pool.submit( | |
self.url_processor.process_urls, | |
[url], | |
mode=mode | |
) | |
futures.append(future) | |
# Collect results | |
results = [] | |
for future in futures: | |
try: | |
result = future.result(timeout=30) | |
results.extend(result) | |
except Exception as e: | |
logger.error(f"URL processing error: {e}") | |
results.append({ | |
'error': str(e), | |
'timestamp': datetime.now().isoformat() | |
}) | |
processing_time = time.time() - start_time | |
# Update statistics | |
self.stats.total_urls += len(url_list) | |
self.stats.successful_urls += len([r for r in results if 'error' not in r]) | |
self.stats.failed_urls += len([r for r in results if 'error' in r]) | |
self.stats.processing_time += processing_time | |
# Generate analytics | |
analytics = self._generate_analytics(results, processing_time) | |
# Format output | |
formatted_results = json.dumps(results, indent=2) | |
summary = self._generate_summary(results) | |
return ( | |
formatted_results, | |
f"✅ Processed {len(url_list)} URLs in {processing_time:.2f}s", | |
summary, | |
analytics | |
) | |
except Exception as e: | |
logger.error(f"Parallel processing error: {e}") | |
return "", f"❌ Error: {str(e)}", "", {} | |
def _generate_analytics(self, results: List[Dict], processing_time: float) -> Dict: | |
"""Generate detailed analytics from processing results""" | |
analytics = { | |
'processing_time': processing_time, | |
'total_items': len(results), | |
'success_rate': len([r for r in results if 'error' not in r]) / len(results) if results else 0, | |
'error_rate': len([r for r in results if 'error' in r]) / len(results) if results else 0, | |
'average_time_per_item': processing_time / len(results) if results else 0, | |
'timestamp': datetime.now().isoformat() | |
} | |
# Add historical trends | |
if self.processing_history: | |
historical_success_rates = [ | |
len([r for r in h['results'] if 'error' not in r]) / len(h['results']) | |
for h in self.processing_history[-10:] # Last 10 operations | |
] | |
analytics['historical_success_rate'] = sum(historical_success_rates) / len(historical_success_rates) | |
return analytics | |
def create_interface(self) -> gr.Blocks: | |
"""Create an advanced professional interface with real-time analytics""" | |
with gr.Blocks(theme=THEME, css=CUSTOM_CSS) as interface: | |
# Professional Header | |
gr.Markdown( | |
""" | |
<div class="pro-header"> | |
<h1>🌐 Advanced URL & Text Processing Suite - Pro</h1> | |
<p>Enterprise-grade toolkit with advanced features and real-time analytics</p> | |
</div> | |
""" | |
) | |
# Real-time Dashboard | |
with gr.Row(elem_classes="dashboard"): | |
with gr.Column(elem_classes="stat-card"): | |
url_stats = gr.JSON( | |
value={ | |
"Total URLs": 0, | |
"Success Rate": "0%", | |
"Avg. Processing Time": "0ms" | |
}, | |
label="URL Processing Stats" | |
) | |
with gr.Column(elem_classes="stat-card"): | |
file_stats = gr.JSON( | |
value={ | |
"Total Files": 0, | |
"Success Rate": "0%", | |
"Avg. Processing Time": "0ms" | |
}, | |
label="File Processing Stats" | |
) | |
with gr.Column(elem_classes="stat-card"): | |
qr_stats = gr.JSON( | |
value={ | |
"Total QR Codes": 0, | |
"Success Rate": "0%", | |
"Avg. Processing Time": "0ms" | |
}, | |
label="QR Code Stats" | |
) | |
# Main Interface Tabs | |
with gr.Tabs() as tabs: | |
# Advanced URL Processing Tab | |
with gr.Tab("🔗 URL Processing", elem_classes="pro-tab"): | |
with gr.Row(): | |
with gr.Column(scale=2): | |
url_input = gr.Textbox( | |
label="URLs", | |
placeholder="Enter URLs (one per line)", | |
lines=5 | |
) | |
with gr.Row(): | |
mode = gr.Radio( | |
choices=["basic", "interactive", "deep"], | |
value="basic", | |
label="Processing Mode" | |
) | |
parallel = gr.Checkbox( | |
label="Enable Parallel Processing", | |
value=True | |
) | |
with gr.Row(): | |
process_btn = gr.Button( | |
"🚀 Process URLs", | |
elem_classes="pro-button" | |
) | |
clear_btn = gr.Button( | |
"🗑️ Clear", | |
elem_classes="pro-button" | |
) | |
with gr.Column(scale=1): | |
gr.Markdown( | |
""" | |
### 📊 Processing Modes | |
#### Basic Mode | |
- Fast content retrieval | |
- Basic metadata extraction | |
- Suitable for simple URLs | |
#### Interactive Mode | |
- Handles JavaScript-rendered content | |
- Social media support | |
- Advanced rate limiting | |
#### Deep Mode | |
- Full content analysis | |
- Link following | |
- Comprehensive metadata | |
""" | |
) | |
with gr.Row(): | |
status_output = gr.Textbox( | |
label="Status", | |
interactive=False | |
) | |
with gr.Tabs(): | |
with gr.Tab("Results"): | |
json_output = gr.JSON( | |
label="Detailed Results" | |
) | |
with gr.Tab("Summary"): | |
summary_output = gr.Textbox( | |
label="Processing Summary", | |
interactive=False, | |
lines=10 | |
) | |
with gr.Tab("Analytics"): | |
analytics_output = gr.Plot( | |
label="Processing Analytics" | |
) | |
# Advanced File Processing Tab | |
with gr.Tab("📁 File Processing", elem_classes="pro-tab"): | |
with gr.Row(): | |
with gr.Column(scale=2): | |
file_input = gr.File( | |
label="Upload Files", | |
file_types=[ | |
".txt", ".pdf", ".doc", ".docx", | |
".zip", ".tar.gz", ".jpg", ".png" | |
], | |
multiple=True | |
) | |
with gr.Row(): | |
process_file_btn = gr.Button( | |
"📥 Process Files", | |
elem_classes="pro-button" | |
) | |
batch_size = gr.Slider( | |
minimum=1, | |
maximum=10, | |
value=3, | |
step=1, | |
label="Batch Size" | |
) | |
with gr.Column(scale=1): | |
gr.Markdown( | |
""" | |
### 📑 Supported Formats | |
#### Documents | |
- PDF files (.pdf) | |
- Word documents (.doc, .docx) | |
- Text files (.txt) | |
#### Archives | |
- ZIP archives (.zip) | |
- TAR archives (.tar.gz) | |
#### Media | |
- Images (.jpg, .png) | |
- And more... | |
""" | |
) | |
with gr.Row(): | |
file_status = gr.Textbox( | |
label="Status", | |
interactive=False | |
) | |
with gr.Tabs(): | |
with gr.Tab("Results"): | |
file_output = gr.File( | |
label="Processed Files" | |
) | |
with gr.Tab("Details"): | |
file_json_output = gr.JSON( | |
label="Processing Details" | |
) | |
with gr.Tab("Analytics"): | |
file_analytics = gr.Plot( | |
label="File Processing Analytics" | |
) | |
# Advanced QR Code Tab | |
with gr.Tab("📱 QR Code", elem_classes="pro-tab"): | |
with gr.Row(): | |
with gr.Column(scale=2): | |
qr_input = gr.Textbox( | |
label="Data", | |
placeholder="Enter data to encode", | |
lines=3 | |
) | |
with gr.Row(): | |
qr_size = gr.Slider( | |
minimum=5, | |
maximum=50, | |
value=10, | |
step=1, | |
label="QR Code Size" | |
) | |
qr_correction = gr.Dropdown( | |
choices=["L", "M", "Q", "H"], | |
value="M", | |
label="Error Correction" | |
) | |
with gr.Row(): | |
generate_qr_btn = gr.Button( | |
"✨ Generate QR", | |
elem_classes="pro-button" | |
) | |
customize_btn = gr.Button( | |
"🎨 Customize", | |
elem_classes="pro-button" | |
) | |
with gr.Column(scale=1): | |
qr_output = gr.Image( | |
label="Generated QR Code" | |
) | |
qr_status = gr.Textbox( | |
label="Status", | |
interactive=False | |
) | |
# Professional Footer | |
gr.Markdown( | |
""" | |
<div class="pro-footer"> | |
<p>Advanced URL & Text Processing Suite - Professional Edition</p> | |
<p style="font-size: 0.9rem;">Version 1.0.0 Pro | © 2024 Advanced URL Processing Team</p> | |
</div> | |
""" | |
) | |
# Event Handlers | |
process_btn.click( | |
fn=self.process_urls_parallel, | |
inputs=[url_input, mode], | |
outputs=[ | |
json_output, | |
status_output, | |
summary_output, | |
analytics_output | |
] | |
) | |
clear_btn.click( | |
fn=lambda: ("", "", "", None), | |
inputs=[], | |
outputs=[ | |
url_input, | |
status_output, | |
summary_output, | |
analytics_output | |
] | |
) | |
process_file_btn.click( | |
fn=self.process_file, | |
inputs=[file_input], | |
outputs=[ | |
file_json_output, | |
file_status, | |
file_output | |
] | |
) | |
generate_qr_btn.click( | |
fn=self.generate_qr, | |
inputs=[qr_input, qr_size], | |
outputs=[qr_output, qr_status] | |
) | |
# Update statistics periodically | |
gr.Markdown.update(every=5) | |
return interface | |
def main(): | |
"""Main entry point with advanced error handling""" | |
try: | |
# Initialize interface | |
app = AdvancedProInterface() | |
interface = app.create_interface() | |
# Launch with professional configuration | |
interface.launch( | |
server_name="0.0.0.0", | |
server_port=8000, | |
share=False, | |
debug=True, | |
enable_queue=True, | |
max_threads=40, | |
auth=None, # Add authentication if needed | |
ssl_keyfile=None, # Add SSL if needed | |
ssl_certfile=None | |
) | |
except Exception as e: | |
logger.error(f"Application startup error: {e}", exc_info=True) | |
sys.exit(1) | |
if __name__ == "__main__": | |
main() | |