Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
@@ -48,7 +48,6 @@ for directory in [OUTPUTS_DIR, QR_CODES_DIR, TEMP_DIR]:
|
|
48 |
|
49 |
class EnhancedURLProcessor:
|
50 |
"""Advanced URL processing with complete content extraction"""
|
51 |
-
|
52 |
def __init__(self):
|
53 |
self.session = requests.Session()
|
54 |
self.timeout = 15 # Extended timeout for larger content
|
@@ -115,6 +114,7 @@ class EnhancedURLProcessor:
|
|
115 |
encoding = chardet.detect(response.content)['encoding'] or 'utf-8'
|
116 |
else:
|
117 |
encoding = response.encoding
|
|
|
118 |
# Decode content with fallback
|
119 |
try:
|
120 |
raw_content = response.content.decode(encoding, errors='replace')
|
@@ -178,7 +178,6 @@ class EnhancedURLProcessor:
|
|
178 |
|
179 |
class EnhancedFileProcessor:
|
180 |
"""Advanced file processing with complete content extraction"""
|
181 |
-
|
182 |
def __init__(self, max_file_size: int = 5 * 1024 * 1024 * 1024): # 5GB default
|
183 |
self.max_file_size = max_file_size
|
184 |
self.supported_extensions = {
|
@@ -227,10 +226,8 @@ class EnhancedFileProcessor:
|
|
227 |
try:
|
228 |
file_stat = os.stat(file.name)
|
229 |
file_size = file_stat.st_size
|
230 |
-
|
231 |
# Initialize content storage
|
232 |
content_parts = []
|
233 |
-
|
234 |
# Process file in chunks for large files
|
235 |
chunk_size = 10 * 1024 * 1024 # 10MB chunks
|
236 |
with open(file.name, 'rb') as f:
|
@@ -238,7 +235,6 @@ class EnhancedFileProcessor:
|
|
238 |
chunk = f.read(chunk_size)
|
239 |
if not chunk:
|
240 |
break
|
241 |
-
|
242 |
# Detect encoding for each chunk
|
243 |
encoding = chardet.detect(chunk)['encoding'] or 'utf-8'
|
244 |
try:
|
@@ -247,10 +243,8 @@ class EnhancedFileProcessor:
|
|
247 |
except (UnicodeDecodeError, LookupError):
|
248 |
decoded_chunk = chunk.decode('utf-8', errors='replace')
|
249 |
content_parts.append(decoded_chunk)
|
250 |
-
|
251 |
# Combine all chunks
|
252 |
complete_content = ''.join(content_parts)
|
253 |
-
|
254 |
# Check if the content is valid JSON regardless of file extension
|
255 |
try:
|
256 |
if mimetypes.guess_type(file.name)[0] == 'application/json' or file.name.lower().endswith('.json'):
|
@@ -504,15 +498,14 @@ def generate_qr_codes(data: Union[str, Dict, List], combined: bool = True) -> Li
|
|
504 |
|
505 |
def create_qr_sequence_visualizer(output_gallery):
|
506 |
"""Add QR sequence visualization capabilities to the application"""
|
507 |
-
|
508 |
# Create a new tab for the QR code sequence visualization
|
509 |
with gr.Tab("π QR Sequence Visualizer"):
|
510 |
gr.Markdown("""
|
511 |
## QR Code Sequence Visualizer
|
512 |
-
|
513 |
Arrange and visualize your QR code sequences. Enable or disable individual QR codes to see how they connect.
|
514 |
""")
|
515 |
-
|
516 |
# Inputs for the visualizer
|
517 |
with gr.Row():
|
518 |
qr_input = gr.File(
|
@@ -520,43 +513,50 @@ def create_qr_sequence_visualizer(output_gallery):
|
|
520 |
file_types=["image/png", "image/jpeg"],
|
521 |
file_count="multiple"
|
522 |
)
|
523 |
-
|
524 |
with gr.Column():
|
525 |
visualize_btn = gr.Button("π Generate Visualization", variant="primary")
|
526 |
reset_btn = gr.Button("ποΈ Reset", variant="secondary")
|
527 |
-
|
528 |
-
# Container for QR code toggles
|
529 |
qr_toggles_container = gr.HTML(label="QR Code Controls")
|
530 |
-
|
531 |
# Output visualization
|
532 |
with gr.Row():
|
533 |
qr_visualization = gr.Image(label="QR Code Sequence Map", height=600)
|
534 |
qr_preview = gr.Gallery(label="Selected QR Codes", columns=2, height=600)
|
535 |
-
|
536 |
# Status output
|
537 |
visualization_status = gr.Textbox(label="Visualization Status", interactive=False)
|
538 |
-
|
539 |
# Function to process uploaded QR codes
|
540 |
def process_qr_codes(files):
|
541 |
if not files:
|
542 |
return "Please upload QR code images.", None, None, "β οΈ No QR codes uploaded"
|
543 |
-
|
544 |
try:
|
545 |
# Load QR codes and extract metadata
|
546 |
qr_data = []
|
547 |
qr_paths = []
|
548 |
-
|
549 |
for file in files:
|
550 |
try:
|
551 |
img = Image.open(file.name)
|
552 |
-
|
553 |
# Try to decode QR code
|
554 |
try:
|
555 |
detector = qrcode.QRCodeDetector()
|
556 |
data, bbox, _ = detector.detectAndDecode(np.array(img))
|
557 |
if data:
|
558 |
-
|
559 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
560 |
qr_paths.append(file.name)
|
561 |
except Exception as e:
|
562 |
logger.warning(f"Could not decode QR: {e}")
|
@@ -569,10 +569,10 @@ def create_qr_sequence_visualizer(output_gallery):
|
|
569 |
qr_paths.append(file.name)
|
570 |
except Exception as e:
|
571 |
logger.error(f"Error processing QR image {file.name}: {e}")
|
572 |
-
|
573 |
if not qr_data:
|
574 |
return "No valid QR codes found.", None, None, "β Failed to process QR codes"
|
575 |
-
|
576 |
# Sort by chunk_index if available
|
577 |
try:
|
578 |
sorted_data = sorted(zip(qr_data, qr_paths), key=lambda x: x[0].get("chunk_index", 0))
|
@@ -580,36 +580,32 @@ def create_qr_sequence_visualizer(output_gallery):
|
|
580 |
qr_paths = [d[1] for d in sorted_data]
|
581 |
except Exception as e:
|
582 |
logger.error(f"Error sorting QR data: {e}")
|
583 |
-
|
584 |
# Generate toggle controls HTML
|
585 |
toggle_html = '<div style="max-height: 500px; overflow-y: auto; padding: 10px;">'
|
586 |
toggle_html += '<h3>Enable/Disable QR Codes:</h3>'
|
587 |
for i, path in enumerate(qr_paths):
|
588 |
-
toggle_html += f'<div><input type="checkbox" id="qr_toggle_{i}" checked> <label for="qr_toggle_{i}">{path}</label></div>'
|
589 |
toggle_html += '</div>'
|
590 |
-
|
591 |
# Update the toggles container
|
592 |
qr_toggles_container.update(value=toggle_html)
|
593 |
-
|
594 |
-
# Create initial visualization
|
595 |
-
initial_visualization =
|
596 |
qr_visualization.update(value=initial_visualization)
|
597 |
-
|
598 |
return "QR codes processed successfully.", qr_paths, qr_data, "β
Visualization ready!"
|
599 |
except Exception as e:
|
600 |
logger.error(f"Error processing QR codes: {e}")
|
601 |
return "An error occurred while processing QR codes.", None, None, "β Error"
|
602 |
|
603 |
-
# Function to generate visualization
|
604 |
def generate_visualization(qr_paths):
|
605 |
enabled_indices = [i for i in range(len(qr_paths))] # Start with all enabled
|
606 |
-
composite_image =
|
607 |
qr_visualization.update(value=composite_image)
|
608 |
|
609 |
-
|
610 |
-
|
611 |
-
# Later in your code, use it in the button click event
|
612 |
-
visualize_btn.click(visualize_qr_codes, inputs=output_gallery, outputs=None)
|
613 |
# Event handlers
|
614 |
visualize_btn.click(process_qr_codes, inputs=qr_input, outputs=[visualization_status, qr_visualization, qr_preview])
|
615 |
reset_btn.click(lambda: (None, None, None, "β οΈ Visualization reset."), outputs=[visualization_status, qr_visualization, qr_preview])
|
@@ -617,12 +613,11 @@ def create_qr_sequence_visualizer(output_gallery):
|
|
617 |
# Integrate the visualizer into the main application
|
618 |
def visualize_qr_codes(qr_paths):
|
619 |
"""Visualize the generated QR codes with enable/disable functionality"""
|
620 |
-
|
621 |
-
|
622 |
-
|
623 |
-
|
624 |
-
|
625 |
-
visualize_btn.click(visualize_qr_codes, inputs=output_gallery, outputs=None)
|
626 |
|
627 |
def create_modern_interface():
|
628 |
"""Create a modern and visually appealing Gradio interface"""
|
@@ -703,7 +698,6 @@ def create_modern_interface():
|
|
703 |
with gr.Blocks(css=css, title="Advanced Data Processor & QR Generator") as interface:
|
704 |
gr.Markdown("""
|
705 |
# π Advanced Data Processing & QR Code Generator
|
706 |
-
|
707 |
Transform your data into beautifully designed, sequenced QR codes with our cutting-edge processor.
|
708 |
""")
|
709 |
with gr.Tab("π URL Processing"):
|
@@ -852,7 +846,7 @@ def create_modern_interface():
|
|
852 |
outputs=[output_json, output_gallery, output_text]
|
853 |
)
|
854 |
|
855 |
-
# Add the visualization button
|
856 |
visualize_btn = gr.Button("π Visualize QR Codes")
|
857 |
visualize_btn.click(visualize_qr_codes, inputs=output_gallery, outputs=None)
|
858 |
|
@@ -864,15 +858,13 @@ def create_modern_interface():
|
|
864 |
- **Smart JSON Handling**: Processes any size JSON with automatic chunking, either via direct input or file upload.
|
865 |
- **Sequential QR Codes**: Maintains data integrity across multiple codes
|
866 |
- **Modern Design**: Clean, responsive interface with visual feedback
|
867 |
-
|
868 |
-
### π‘ Tips
|
869 |
1. **URLs**: Enter multiple URLs separated by commas or newlines
|
870 |
2. **Files**: Upload any type of file. The processor will attempt to handle supported text-based files, archives (.zip, .tar, .gz), and JSON files.
|
871 |
-
3. **JSON**: Use the example button to see the expected format or upload a .json file. The system will also try to detect JSON content in other file types.
|
872 |
4. **QR Codes**: Choose whether to combine data into sequential codes
|
873 |
5. **Processing**: Monitor the status for real-time feedback
|
874 |
-
|
875 |
-
### π¨ Output
|
876 |
- Generated QR codes are saved in the `output/qr_codes` directory
|
877 |
- Each QR code contains metadata for proper sequencing
|
878 |
- Hover over QR codes in the gallery to see details
|
@@ -888,6 +880,10 @@ def main():
|
|
888 |
# Create and launch interface
|
889 |
interface = create_modern_interface()
|
890 |
|
|
|
|
|
|
|
|
|
891 |
# Launch with configuration
|
892 |
interface.launch(
|
893 |
share=False,
|
|
|
48 |
|
49 |
class EnhancedURLProcessor:
|
50 |
"""Advanced URL processing with complete content extraction"""
|
|
|
51 |
def __init__(self):
|
52 |
self.session = requests.Session()
|
53 |
self.timeout = 15 # Extended timeout for larger content
|
|
|
114 |
encoding = chardet.detect(response.content)['encoding'] or 'utf-8'
|
115 |
else:
|
116 |
encoding = response.encoding
|
117 |
+
|
118 |
# Decode content with fallback
|
119 |
try:
|
120 |
raw_content = response.content.decode(encoding, errors='replace')
|
|
|
178 |
|
179 |
class EnhancedFileProcessor:
|
180 |
"""Advanced file processing with complete content extraction"""
|
|
|
181 |
def __init__(self, max_file_size: int = 5 * 1024 * 1024 * 1024): # 5GB default
|
182 |
self.max_file_size = max_file_size
|
183 |
self.supported_extensions = {
|
|
|
226 |
try:
|
227 |
file_stat = os.stat(file.name)
|
228 |
file_size = file_stat.st_size
|
|
|
229 |
# Initialize content storage
|
230 |
content_parts = []
|
|
|
231 |
# Process file in chunks for large files
|
232 |
chunk_size = 10 * 1024 * 1024 # 10MB chunks
|
233 |
with open(file.name, 'rb') as f:
|
|
|
235 |
chunk = f.read(chunk_size)
|
236 |
if not chunk:
|
237 |
break
|
|
|
238 |
# Detect encoding for each chunk
|
239 |
encoding = chardet.detect(chunk)['encoding'] or 'utf-8'
|
240 |
try:
|
|
|
243 |
except (UnicodeDecodeError, LookupError):
|
244 |
decoded_chunk = chunk.decode('utf-8', errors='replace')
|
245 |
content_parts.append(decoded_chunk)
|
|
|
246 |
# Combine all chunks
|
247 |
complete_content = ''.join(content_parts)
|
|
|
248 |
# Check if the content is valid JSON regardless of file extension
|
249 |
try:
|
250 |
if mimetypes.guess_type(file.name)[0] == 'application/json' or file.name.lower().endswith('.json'):
|
|
|
498 |
|
499 |
def create_qr_sequence_visualizer(output_gallery):
|
500 |
"""Add QR sequence visualization capabilities to the application"""
|
|
|
501 |
# Create a new tab for the QR code sequence visualization
|
502 |
with gr.Tab("π QR Sequence Visualizer"):
|
503 |
gr.Markdown("""
|
504 |
## QR Code Sequence Visualizer
|
505 |
+
|
506 |
Arrange and visualize your QR code sequences. Enable or disable individual QR codes to see how they connect.
|
507 |
""")
|
508 |
+
|
509 |
# Inputs for the visualizer
|
510 |
with gr.Row():
|
511 |
qr_input = gr.File(
|
|
|
513 |
file_types=["image/png", "image/jpeg"],
|
514 |
file_count="multiple"
|
515 |
)
|
516 |
+
|
517 |
with gr.Column():
|
518 |
visualize_btn = gr.Button("π Generate Visualization", variant="primary")
|
519 |
reset_btn = gr.Button("ποΈ Reset", variant="secondary")
|
520 |
+
# Container for QR code toggles
|
|
|
521 |
qr_toggles_container = gr.HTML(label="QR Code Controls")
|
522 |
+
|
523 |
# Output visualization
|
524 |
with gr.Row():
|
525 |
qr_visualization = gr.Image(label="QR Code Sequence Map", height=600)
|
526 |
qr_preview = gr.Gallery(label="Selected QR Codes", columns=2, height=600)
|
527 |
+
|
528 |
# Status output
|
529 |
visualization_status = gr.Textbox(label="Visualization Status", interactive=False)
|
530 |
+
|
531 |
# Function to process uploaded QR codes
|
532 |
def process_qr_codes(files):
|
533 |
if not files:
|
534 |
return "Please upload QR code images.", None, None, "β οΈ No QR codes uploaded"
|
535 |
+
|
536 |
try:
|
537 |
# Load QR codes and extract metadata
|
538 |
qr_data = []
|
539 |
qr_paths = []
|
540 |
+
|
541 |
for file in files:
|
542 |
try:
|
543 |
img = Image.open(file.name)
|
544 |
+
|
545 |
# Try to decode QR code
|
546 |
try:
|
547 |
detector = qrcode.QRCodeDetector()
|
548 |
data, bbox, _ = detector.detectAndDecode(np.array(img))
|
549 |
if data:
|
550 |
+
try:
|
551 |
+
qr_json = json.loads(data)
|
552 |
+
qr_data.append(qr_json)
|
553 |
+
qr_paths.append(file.name)
|
554 |
+
except json.JSONDecodeError:
|
555 |
+
logger.warning(f"Could not decode JSON from QR: {data}")
|
556 |
+
qr_data.append({"data": data}) # Store raw data if JSON fails
|
557 |
+
qr_paths.append(file.name)
|
558 |
+
else:
|
559 |
+
qr_data.append({"data": "Empty QR"})
|
560 |
qr_paths.append(file.name)
|
561 |
except Exception as e:
|
562 |
logger.warning(f"Could not decode QR: {e}")
|
|
|
569 |
qr_paths.append(file.name)
|
570 |
except Exception as e:
|
571 |
logger.error(f"Error processing QR image {file.name}: {e}")
|
572 |
+
|
573 |
if not qr_data:
|
574 |
return "No valid QR codes found.", None, None, "β Failed to process QR codes"
|
575 |
+
|
576 |
# Sort by chunk_index if available
|
577 |
try:
|
578 |
sorted_data = sorted(zip(qr_data, qr_paths), key=lambda x: x[0].get("chunk_index", 0))
|
|
|
580 |
qr_paths = [d[1] for d in sorted_data]
|
581 |
except Exception as e:
|
582 |
logger.error(f"Error sorting QR data: {e}")
|
583 |
+
|
584 |
# Generate toggle controls HTML
|
585 |
toggle_html = '<div style="max-height: 500px; overflow-y: auto; padding: 10px;">'
|
586 |
toggle_html += '<h3>Enable/Disable QR Codes:</h3>'
|
587 |
for i, path in enumerate(qr_paths):
|
588 |
+
toggle_html += f'<div><input type="checkbox" id="qr_toggle_{i}" checked> <label for="qr_toggle_{i}">{os.path.basename(path)}</label></div>'
|
589 |
toggle_html += '</div>'
|
590 |
+
|
591 |
# Update the toggles container
|
592 |
qr_toggles_container.update(value=toggle_html)
|
593 |
+
|
594 |
+
# Create initial visualization (replace with actual visualization logic)
|
595 |
+
initial_visualization = "Visualization will appear here." # Replace with your composite image generation
|
596 |
qr_visualization.update(value=initial_visualization)
|
597 |
+
|
598 |
return "QR codes processed successfully.", qr_paths, qr_data, "β
Visualization ready!"
|
599 |
except Exception as e:
|
600 |
logger.error(f"Error processing QR codes: {e}")
|
601 |
return "An error occurred while processing QR codes.", None, None, "β Error"
|
602 |
|
603 |
+
# Function to generate visualization (replace with actual logic)
|
604 |
def generate_visualization(qr_paths):
|
605 |
enabled_indices = [i for i in range(len(qr_paths))] # Start with all enabled
|
606 |
+
composite_image = "Updated visualization will appear here." # Replace with your composite image generation based on enabled_indices
|
607 |
qr_visualization.update(value=composite_image)
|
608 |
|
|
|
|
|
|
|
|
|
609 |
# Event handlers
|
610 |
visualize_btn.click(process_qr_codes, inputs=qr_input, outputs=[visualization_status, qr_visualization, qr_preview])
|
611 |
reset_btn.click(lambda: (None, None, None, "β οΈ Visualization reset."), outputs=[visualization_status, qr_visualization, qr_preview])
|
|
|
613 |
# Integrate the visualizer into the main application
|
614 |
def visualize_qr_codes(qr_paths):
|
615 |
"""Visualize the generated QR codes with enable/disable functionality"""
|
616 |
+
# This function currently receives the output gallery content (list of file paths)
|
617 |
+
# You might need to adapt this based on how you want to visualize.
|
618 |
+
# For now, let's just log the paths.
|
619 |
+
logger.info(f"Visualizing QR codes: {qr_paths}")
|
620 |
+
return "Visualization placeholder" # Replace with actual visualization logic
|
|
|
621 |
|
622 |
def create_modern_interface():
|
623 |
"""Create a modern and visually appealing Gradio interface"""
|
|
|
698 |
with gr.Blocks(css=css, title="Advanced Data Processor & QR Generator") as interface:
|
699 |
gr.Markdown("""
|
700 |
# π Advanced Data Processing & QR Code Generator
|
|
|
701 |
Transform your data into beautifully designed, sequenced QR codes with our cutting-edge processor.
|
702 |
""")
|
703 |
with gr.Tab("π URL Processing"):
|
|
|
846 |
outputs=[output_json, output_gallery, output_text]
|
847 |
)
|
848 |
|
849 |
+
# Add the visualization button and its click event within the interface scope
|
850 |
visualize_btn = gr.Button("π Visualize QR Codes")
|
851 |
visualize_btn.click(visualize_qr_codes, inputs=output_gallery, outputs=None)
|
852 |
|
|
|
858 |
- **Smart JSON Handling**: Processes any size JSON with automatic chunking, either via direct input or file upload.
|
859 |
- **Sequential QR Codes**: Maintains data integrity across multiple codes
|
860 |
- **Modern Design**: Clean, responsive interface with visual feedback
|
861 |
+
### π‘ Tips
|
|
|
862 |
1. **URLs**: Enter multiple URLs separated by commas or newlines
|
863 |
2. **Files**: Upload any type of file. The processor will attempt to handle supported text-based files, archives (.zip, .tar, .gz), and JSON files.
|
864 |
+
3. **JSON**: Use the example button to see the expected format or upload a .json file. The system will also try to detect JSON content in other file types.
|
865 |
4. **QR Codes**: Choose whether to combine data into sequential codes
|
866 |
5. **Processing**: Monitor the status for real-time feedback
|
867 |
+
### π¨ Output
|
|
|
868 |
- Generated QR codes are saved in the `output/qr_codes` directory
|
869 |
- Each QR code contains metadata for proper sequencing
|
870 |
- Hover over QR codes in the gallery to see details
|
|
|
880 |
# Create and launch interface
|
881 |
interface = create_modern_interface()
|
882 |
|
883 |
+
# Add the QR sequence visualizer tab
|
884 |
+
with interface:
|
885 |
+
create_qr_sequence_visualizer(None) # output_gallery might not be relevant here
|
886 |
+
|
887 |
# Launch with configuration
|
888 |
interface.launch(
|
889 |
share=False,
|