Spaces:
Running
Running
""" | |
Advanced URL & Text Processing Suite - Main Application | |
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ | |
A sophisticated Gradio interface for URL processing, file manipulation, and QR operations. | |
Features a modern, responsive UI with real-time feedback and advanced processing capabilities. | |
""" | |
import gradio as gr | |
import logging | |
import json | |
import os | |
import sys | |
from datetime import datetime | |
from pathlib import Path | |
from typing import Dict, List, Optional, Union, Any, Tuple | |
from url_processor import URLProcessor | |
from file_processor import FileProcessor | |
from qr_processor import QRProcessor | |
# Configure logging | |
logging.basicConfig( | |
level=logging.INFO, | |
format='%(asctime)s.%(msecs)03d [%(levelname)s] %(name)s - %(message)s', | |
datefmt='%Y-%m-%d %H:%M:%S' | |
) | |
logger = logging.getLogger(__name__) | |
# Modern UI Configuration | |
THEME = gr.themes.Soft( | |
primary_hue="indigo", | |
secondary_hue="blue", | |
neutral_hue="slate", | |
spacing_size=gr.themes.sizes.spacing_md, | |
radius_size=gr.themes.sizes.radius_md, | |
text_size=gr.themes.sizes.text_md, | |
).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", | |
) | |
# Custom CSS for enhanced visual appeal | |
CUSTOM_CSS = """ | |
.container { | |
max-width: 1200px !important; | |
margin: auto !important; | |
padding: 2rem !important; | |
} | |
.header { | |
text-align: center; | |
margin-bottom: 2rem; | |
padding: 1rem; | |
background: linear-gradient(135deg, #6366f1 0%, #2563eb 100%); | |
border-radius: 1rem; | |
color: white; | |
} | |
.status-bar { | |
background: #f8fafc; | |
border-radius: 0.5rem; | |
padding: 0.5rem; | |
margin: 1rem 0; | |
border: 1px solid #e2e8f0; | |
} | |
.success-message { | |
color: #059669; | |
background: #ecfdf5; | |
border: 1px solid #059669; | |
border-radius: 0.5rem; | |
padding: 1rem; | |
margin: 1rem 0; | |
} | |
.error-message { | |
color: #dc2626; | |
background: #fef2f2; | |
border: 1px solid #dc2626; | |
border-radius: 0.5rem; | |
padding: 1rem; | |
margin: 1rem 0; | |
} | |
.tab-nav { | |
background: #f8fafc; | |
border-radius: 0.5rem; | |
padding: 0.5rem; | |
margin-bottom: 1rem; | |
} | |
.tab-nav button { | |
transition: all 0.3s ease; | |
} | |
.tab-nav button:hover { | |
transform: translateY(-1px); | |
} | |
.json-editor { | |
font-family: 'JetBrains Mono', monospace; | |
background: #1e293b; | |
color: #e2e8f0; | |
border-radius: 0.5rem; | |
padding: 1rem; | |
} | |
.file-upload { | |
border: 2px dashed #e2e8f0; | |
border-radius: 1rem; | |
padding: 2rem; | |
text-align: center; | |
transition: all 0.3s ease; | |
} | |
.file-upload:hover { | |
border-color: #6366f1; | |
background: #f8fafc; | |
} | |
@keyframes pulse { | |
0% { transform: scale(1); } | |
50% { transform: scale(1.05); } | |
100% { transform: scale(1); } | |
} | |
.processing { | |
animation: pulse 2s infinite; | |
} | |
""" | |
class AdvancedInterface: | |
"""Advanced Gradio interface with sophisticated processing capabilities""" | |
def __init__(self): | |
"""Initialize processors and interface components""" | |
self.url_processor = URLProcessor() | |
self.file_processor = FileProcessor() | |
self.qr_processor = QRProcessor() | |
self.processing_history: List[Dict] = [] | |
def process_urls(self, urls: str, mode: str) -> Tuple[str, str, str]: | |
"""Process URLs with advanced error handling and result formatting""" | |
try: | |
# Split and clean URLs | |
url_list = [url.strip() for url in urls.split('\n') if url.strip()] | |
if not url_list: | |
return "", "β οΈ No valid URLs provided", "" | |
# Process URLs | |
results = self.url_processor.process_urls(url_list, mode=mode) | |
# Format results | |
formatted_results = json.dumps(results, indent=2) | |
summary = self._generate_summary(results) | |
# Update history | |
self.processing_history.append({ | |
'timestamp': datetime.now().isoformat(), | |
'type': 'url_processing', | |
'input_count': len(url_list), | |
'success_count': len([r for r in results if 'error' not in r]), | |
'results': results | |
}) | |
return formatted_results, f"β Successfully processed {len(url_list)} URLs", summary | |
except Exception as e: | |
logger.error(f"URL processing error: {e}", exc_info=True) | |
return "", f"β Error: {str(e)}", "" | |
def process_file(self, file: gr.File) -> Tuple[str, str, Optional[Path]]: | |
"""Process uploaded file with comprehensive error handling""" | |
try: | |
if not file: | |
return "", "β οΈ No file provided", None | |
results = self.file_processor.process_file(file) | |
# Generate output file | |
output_path = Path('processed_output.json') | |
with open(output_path, 'w') as f: | |
json.dump(results, f, indent=2) | |
# Update history | |
self.processing_history.append({ | |
'timestamp': datetime.now().isoformat(), | |
'type': 'file_processing', | |
'filename': file.name, | |
'results': results | |
}) | |
return ( | |
json.dumps(results, indent=2), | |
f"β Successfully processed {file.name}", | |
output_path | |
) | |
except Exception as e: | |
logger.error(f"File processing error: {e}", exc_info=True) | |
return "", f"β Error: {str(e)}", None | |
def generate_qr(self, data: str, size: int = 10) -> Tuple[Optional[Path], str]: | |
"""Generate QR code with advanced options""" | |
try: | |
if not data: | |
return None, "β οΈ No data provided" | |
result = self.qr_processor.generate_qr_code(data, size=size) | |
if 'error' in result: | |
return None, f"β Error: {result['error']}" | |
# Update history | |
self.processing_history.append({ | |
'timestamp': datetime.now().isoformat(), | |
'type': 'qr_generation', | |
'data_length': len(data), | |
'output_path': result['output_path'] | |
}) | |
return result['output_path'], "β QR code generated successfully" | |
except Exception as e: | |
logger.error(f"QR generation error: {e}", exc_info=True) | |
return None, f"β Error: {str(e)}" | |
def _generate_summary(self, results: List[Dict]) -> str: | |
"""Generate a human-readable summary of processing results""" | |
success_count = len([r for r in results if 'error' not in r]) | |
error_count = len(results) - success_count | |
summary = [ | |
"π Processing Summary", | |
f"Total URLs: {len(results)}", | |
f"Successful: {success_count}", | |
f"Failed: {error_count}", | |
"", | |
"π Details:" | |
] | |
for result in results: | |
if 'error' in result: | |
summary.append(f"β {result['url']}: {result['error']}") | |
else: | |
summary.append(f"β {result['url']}: Successfully processed") | |
return '\n'.join(summary) | |
def create_interface(self) -> gr.Blocks: | |
"""Create a sophisticated Gradio interface""" | |
with gr.Blocks(theme=THEME, css=CUSTOM_CSS) as interface: | |
# Header | |
gr.Markdown( | |
""" | |
<div class="header"> | |
<h1>π Advanced URL & Text Processing Suite</h1> | |
<p>Enterprise-grade toolkit for URL processing, file manipulation, and QR operations</p> | |
</div> | |
""" | |
) | |
# Main tabs | |
with gr.Tabs(elem_classes="tab-nav") as tabs: | |
# URL Processing Tab | |
with gr.Tab("π URL Processing", id=1): | |
with gr.Row(): | |
with gr.Column(scale=2): | |
url_input = gr.Textbox( | |
label="URLs", | |
placeholder="Enter URLs (one per line)", | |
lines=5 | |
) | |
mode = gr.Radio( | |
choices=["basic", "interactive", "deep"], | |
value="basic", | |
label="Processing Mode" | |
) | |
process_btn = gr.Button("π Process URLs", variant="primary") | |
with gr.Column(scale=1): | |
gr.Markdown( | |
""" | |
### π Instructions | |
1. Enter URLs (one per line) | |
2. Select processing mode: | |
- Basic: Simple content fetch | |
- Interactive: Handle dynamic content | |
- Deep: Follow links and analyze deeply | |
3. Click Process to start | |
""" | |
) | |
with gr.Row(): | |
status_output = gr.Textbox(label="Status", interactive=False) | |
clear_btn = gr.Button("ποΈ Clear", variant="secondary") | |
with gr.Accordion("Results", open=False): | |
json_output = gr.JSON(label="Detailed Results") | |
summary_output = gr.Textbox( | |
label="Summary", | |
interactive=False, | |
lines=10 | |
) | |
# File Processing Tab | |
with gr.Tab("π File Processing", id=2): | |
with gr.Row(): | |
with gr.Column(scale=2): | |
file_input = gr.File( | |
label="Upload File", | |
file_types=[".txt", ".pdf", ".zip", ".tar.gz"] | |
) | |
process_file_btn = gr.Button("π₯ Process File", variant="primary") | |
with gr.Column(scale=1): | |
gr.Markdown( | |
""" | |
### π Supported Formats | |
- Text files (.txt) | |
- PDF documents (.pdf) | |
- Archives (.zip, .tar.gz) | |
- Images (.jpg, .png) | |
- And more... | |
""" | |
) | |
with gr.Row(): | |
file_status = gr.Textbox(label="Status", interactive=False) | |
file_output = gr.File(label="Processed Output") | |
with gr.Accordion("Results", open=False): | |
file_json_output = gr.JSON(label="Detailed Results") | |
# QR Code Tab | |
with gr.Tab("π± QR Code", id=3): | |
with gr.Row(): | |
with gr.Column(scale=2): | |
qr_input = gr.Textbox( | |
label="Data", | |
placeholder="Enter data to encode", | |
lines=3 | |
) | |
qr_size = gr.Slider( | |
minimum=5, | |
maximum=50, | |
value=10, | |
step=1, | |
label="QR Code Size" | |
) | |
generate_qr_btn = gr.Button("β¨ Generate QR", variant="primary") | |
with gr.Column(scale=1): | |
qr_output = gr.Image(label="Generated QR Code") | |
qr_status = gr.Textbox(label="Status", interactive=False) | |
# Footer | |
gr.Markdown( | |
""" | |
<div style="text-align: center; margin-top: 2rem; padding: 1rem; background: #f8fafc; border-radius: 0.5rem;"> | |
<p>Made with β€οΈ by Advanced URL Processing Team</p> | |
<p style="font-size: 0.8rem;">Version 1.0.0</p> | |
</div> | |
""" | |
) | |
# Event handlers | |
process_btn.click( | |
fn=self.process_urls, | |
inputs=[url_input, mode], | |
outputs=[json_output, status_output, summary_output] | |
) | |
clear_btn.click( | |
fn=lambda: ("", "", ""), | |
inputs=[], | |
outputs=[url_input, status_output, summary_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] | |
) | |
return interface | |
def main(): | |
"""Main entry point""" | |
try: | |
# Initialize interface | |
app = AdvancedInterface() | |
interface = app.create_interface() | |
# Launch with optimal settings | |
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() |