euler314 commited on
Commit
a9c2a7c
Β·
verified Β·
1 Parent(s): 8a3a87e

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +389 -1
app.py CHANGED
@@ -323,4 +323,392 @@ def compile_with_nuitka(code, requirements, packages, compilation_mode, output_e
323
  **Python Requirements**: {install_result}
324
 
325
  ## Binary Information:
326
- {binary_info}
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
323
  **Python Requirements**: {install_result}
324
 
325
  ## Binary Information:
326
+ {binary_info}
327
+
328
+ ## πŸš€ Portability Notes:
329
+ - This binary was compiled with maximum compatibility settings
330
+ - Using --onefile for single-file distribution
331
+ - Added --assume-yes-for-downloads for automatic dependency resolution
332
+ - Used --python-flag=no_site to reduce system dependencies
333
+ - Should work on most compatible Linux systems
334
+
335
+ ## πŸ“‹ Usage Instructions:
336
+ ```bash
337
+ chmod +x {binary_basename}
338
+ ./{binary_basename}
339
+ ```
340
+
341
+ ## ⚠️ HF Spaces Notice:
342
+ This binary was compiled in a Hugging Face Spaces environment. For best results:
343
+ 1. Download the binary to your local system
344
+ 2. Make it executable: `chmod +x filename`
345
+ 3. Run it in a compatible Linux environment"""
346
+
347
+ progress(1.0, desc="Compilation successful!")
348
+ return result_summary, binary_path, compile_output, True
349
+ else:
350
+ error_summary = f"""# ❌ Compilation Failed
351
+
352
+ ## Error Details:
353
+ - **Exit Code**: {process.returncode}
354
+ - **Mode Attempted**: {mode_name}
355
+
356
+ ## Environment Results:
357
+ **System Packages**: {packages_result}
358
+ **Python Requirements**: {install_result}
359
+
360
+ ## Possible Solutions:
361
+ 1. Check your code for syntax errors
362
+ 2. Ensure all imports are available
363
+ 3. Try a different compilation mode
364
+ 4. Review the compilation logs below
365
+
366
+ ## Missing Dependencies:
367
+ {', '.join(missing_deps) if missing_deps else 'None detected'}"""
368
+ return error_summary, None, compile_output, False
369
+
370
+ except Exception as e:
371
+ error_summary = f"""# ❌ Compilation Error
372
+
373
+ ## Error:
374
+ {str(e)}
375
+
376
+ ## Environment Results:
377
+ **System Packages**: {packages_result}
378
+ **Python Requirements**: {install_result}"""
379
+ return error_summary, None, f"Error: {str(e)}", False
380
+
381
+ def run_compiled_binary(binary_path):
382
+ """Run the compiled binary and return the output"""
383
+ if not binary_path or not os.path.exists(binary_path):
384
+ return "❌ No binary available to run."
385
+
386
+ try:
387
+ # Make the binary executable
388
+ os.chmod(binary_path, 0o755)
389
+
390
+ # Run the binary with timeout
391
+ process = subprocess.run(
392
+ [binary_path],
393
+ capture_output=True,
394
+ text=True,
395
+ timeout=30, # Increased timeout for HF Spaces
396
+ cwd=os.path.dirname(binary_path) # Run in binary's directory
397
+ )
398
+
399
+ output = ""
400
+ if process.stdout:
401
+ output += f"## [STDOUT]\n```\n{process.stdout}\n```\n"
402
+ if process.stderr:
403
+ output += f"## [STDERR]\n```\n{process.stderr}\n```\n"
404
+ if process.returncode != 0:
405
+ output += f"## [EXIT CODE]\n{process.returncode}\n"
406
+
407
+ if not output:
408
+ output = "βœ… Binary executed successfully with no output."
409
+ else:
410
+ output = "## πŸ§ͺ Execution Results\n" + output
411
+
412
+ return output
413
+ except subprocess.TimeoutExpired:
414
+ return "⏱️ **Execution timed out after 30 seconds.**\n\nThis might indicate:\n- The program is waiting for input\n- An infinite loop\n- Long-running computation"
415
+ except Exception as e:
416
+ return f"❌ **Error running the binary:**\n\n```\n{str(e)}\n```"
417
+
418
+ # Create Gradio interface
419
+ with gr.Blocks(title="Nuitka Python Compiler for HF Spaces", theme=gr.themes.Soft()) as app:
420
+ gr.Markdown("# πŸš€ Nuitka Python Compiler (HF Spaces Edition)")
421
+ gr.Markdown("Convert your Python code into portable executables using Nuitka, optimized for Hugging Face Spaces.")
422
+
423
+ # Check environment status
424
+ has_static = check_static_libpython()
425
+ missing_deps = check_dependencies()
426
+
427
+ if has_static:
428
+ gr.Markdown("🎯 **Static Libpython Available!** Maximum portability enabled.")
429
+ else:
430
+ gr.Markdown("πŸ”§ **Using alternative portable options.** Static libpython not available.")
431
+
432
+ if missing_deps:
433
+ gr.Markdown(f"⚠️ **Missing dependencies:** {', '.join(missing_deps)}")
434
+ else:
435
+ gr.Markdown("βœ… **All required dependencies available!**")
436
+
437
+ # HF Spaces specific notice
438
+ gr.Markdown("""
439
+ > ℹ️ **Running in Hugging Face Spaces**: System packages cannot be installed.
440
+ > All required dependencies should be pre-installed in the environment.
441
+ """)
442
+
443
+ with gr.Tabs():
444
+ with gr.TabItem("πŸ”§ Compiler"):
445
+ with gr.Row():
446
+ with gr.Column(scale=2):
447
+ code_input = gr.Code(
448
+ value="""# Your Python code here
449
+ print('Hello from compiled Python!')
450
+ print('This is a smart-compiled binary!')
451
+
452
+ # This will work with automatic compatibility detection
453
+ import os, sys
454
+ print(f'Running from: {os.getcwd()}')
455
+ print(f'Python executable: {sys.executable}')
456
+ print('Compilation was optimized for your environment!')
457
+
458
+ # Simple example with user input
459
+ name = input('What is your name? ')
460
+ print(f'Hello, {name}!')""",
461
+ language="python",
462
+ label="Your Python Code",
463
+ lines=20
464
+ )
465
+
466
+ with gr.Column(scale=1):
467
+ with gr.Tabs():
468
+ with gr.TabItem("Python Requirements"):
469
+ requirements_input = gr.Textbox(
470
+ placeholder="""# Add your Python dependencies here
471
+ # Example:
472
+ # numpy==1.24.0
473
+ # pandas==2.0.0
474
+ # requests>=2.28.0
475
+ # matplotlib
476
+ # pillow""",
477
+ lines=8,
478
+ label="requirements.txt content"
479
+ )
480
+
481
+ with gr.TabItem("System Packages"):
482
+ gr.Markdown("⚠️ **System packages cannot be installed in HF Spaces**")
483
+ packages_input = gr.Textbox(
484
+ placeholder="""# System packages (for reference only)
485
+ # These cannot be installed in HF Spaces
486
+ # build-essential
487
+ # libssl-dev
488
+ # ffmpeg""",
489
+ lines=8,
490
+ label="packages.txt content (Reference Only)",
491
+ interactive=True
492
+ )
493
+
494
+ # Fixed dropdown choices
495
+ compilation_mode = gr.Dropdown(
496
+ choices=[
497
+ "Maximum Compatibility (Recommended)",
498
+ "Portable Binary",
499
+ "Standalone Binary"
500
+ ],
501
+ value="Maximum Compatibility (Recommended)",
502
+ label="Compilation Mode"
503
+ )
504
+
505
+ output_extension = gr.Dropdown(
506
+ choices=[".bin", ".sh"],
507
+ value=".bin",
508
+ label="Output File Extension"
509
+ )
510
+
511
+ gr.Markdown(f"πŸ“ **Compiling with Python {get_current_python_version()}**")
512
+ if check_static_libpython():
513
+ gr.Markdown("πŸ”— **Static libpython will be used!**")
514
+ else:
515
+ gr.Markdown("πŸ”§ **Using portable compilation flags**")
516
+
517
+ compile_btn = gr.Button("πŸš€ Compile with Nuitka", variant="primary")
518
+
519
+ # Results section
520
+ with gr.Column(visible=False) as results_section:
521
+ with gr.Accordion("πŸ“Š Compilation Results", open=True):
522
+ result_summary = gr.Markdown()
523
+ with gr.Accordion("πŸ“œ Compilation Logs", open=False):
524
+ compile_logs = gr.Textbox(label="Detailed Compilation Output", lines=15)
525
+ download_file = gr.File(label="πŸ“₯ Download Compiled Binary")
526
+
527
+ # Test run section
528
+ with gr.Row():
529
+ run_btn = gr.Button("πŸ§ͺ Test Run Binary", variant="secondary")
530
+ run_output = gr.Markdown(label="Execution Output")
531
+
532
+ # Variables to store state
533
+ current_binary_path = gr.State(None)
534
+ compilation_success = gr.State(False)
535
+
536
+ def handle_compilation(code, requirements, packages, mode, extension, progress=gr.Progress()):
537
+ summary, binary_path, logs, success = compile_with_nuitka(
538
+ code, requirements, packages, mode, extension, progress
539
+ )
540
+
541
+ if success and binary_path:
542
+ # Create download file
543
+ download_filename = f"compiled_program{extension}"
544
+ download_path = os.path.join(os.path.dirname(binary_path), download_filename)
545
+ shutil.copy2(binary_path, download_path)
546
+
547
+ return (
548
+ gr.update(visible=True), # results_section
549
+ gr.update(value=summary), # result_summary
550
+ gr.update(value=logs), # compile_logs
551
+ gr.update(value=download_path), # download_file
552
+ binary_path, # current_binary_path state
553
+ True # compilation_success state
554
+ )
555
+ else:
556
+ return (
557
+ gr.update(visible=True), # results_section
558
+ gr.update(value=summary), # result_summary
559
+ gr.update(value=logs), # compile_logs
560
+ gr.update(visible=False), # download_file
561
+ None, # current_binary_path state
562
+ False # compilation_success state
563
+ )
564
+
565
+ def handle_run(binary_path):
566
+ if binary_path:
567
+ output = run_compiled_binary(binary_path)
568
+ return gr.update(value=output)
569
+ else:
570
+ return gr.update(value="❌ No binary available to run.")
571
+
572
+ compile_btn.click(
573
+ handle_compilation,
574
+ inputs=[code_input, requirements_input, packages_input, compilation_mode, output_extension],
575
+ outputs=[results_section, result_summary, compile_logs, download_file, current_binary_path, compilation_success]
576
+ )
577
+
578
+ run_btn.click(
579
+ handle_run,
580
+ inputs=[current_binary_path],
581
+ outputs=[run_output]
582
+ )
583
+
584
+ with gr.TabItem("πŸ“– How to Use"):
585
+ gr.Markdown("""
586
+ ## 🎯 Smart Compilation in HF Spaces
587
+
588
+ **Automatic Environment Detection**
589
+
590
+ This app automatically detects your Python environment and chooses the best compilation strategy:
591
+ - Uses static libpython if available (maximum portability)
592
+ - Falls back to highly portable alternatives if not
593
+ - Automatically handles missing dependencies
594
+ - Optimized specifically for Hugging Face Spaces environment
595
+
596
+ ## πŸ“‹ Usage Instructions
597
+
598
+ ### 1. Write Your Code
599
+ - Enter your Python code in the code editor
600
+ - Add any Python package requirements in the requirements tab
601
+
602
+ ### 2. Choose Compilation Mode
603
+ - **Maximum Compatibility**: Best for most use cases (recommended)
604
+ - **Portable Binary**: Smaller size, may need Python runtime
605
+ - **Standalone Binary**: Includes all dependencies (larger)
606
+
607
+ ### 3. Compile
608
+ - Click "Compile with Nuitka"
609
+ - Wait for the compilation to complete
610
+ - Download the resulting binary
611
+
612
+ ### 4. Run Your Binary
613
+
614
+ ```bash
615
+ # On Linux (including WSL)
616
+ chmod +x compiled_program.bin
617
+ ./compiled_program.bin
618
+
619
+ # In WSL, copy to Linux filesystem first
620
+ cp /mnt/c/Users/username/Downloads/compiled_program.bin ~/
621
+ cd ~
622
+ chmod +x compiled_program.bin
623
+ ./compiled_program.bin
624
+ ```
625
+
626
+ ## ⚠️ HF Spaces Limitations
627
+
628
+ - **System packages cannot be installed** (no apt-get access)
629
+ - All required system dependencies must be pre-installed
630
+ - Compilation happens in a containerized environment
631
+ - Binary execution may have resource limits
632
+
633
+ ## πŸ“Š Compilation Modes Comparison
634
+
635
+ | Mode | Size | Portability | Speed | Best For |
636
+ |------|------|-------------|--------|----------|
637
+ | Maximum Compatibility | Medium | Highest | Fast | Distribution |
638
+ | Portable Binary | Small | High | Fastest | Quick testing |
639
+ | Standalone Binary | Large | Highest | Medium | Isolated deployment |
640
+ """)
641
+
642
+ with gr.TabItem("ℹ️ About"):
643
+ gr.Markdown(f"""
644
+ ## 🧠 Smart Compilation Technology
645
+
646
+ **How it works:**
647
+
648
+ 1. **Environment Detection**: Checks if static libpython is available
649
+ 2. **Adaptive Options**: Uses the best available compilation flags
650
+ 3. **Fallback Strategy**: Ensures compilation succeeds even without static linking
651
+ 4. **Automatic Dependencies**: Resolves missing dependencies automatically
652
+ 5. **HF Spaces Optimization**: Adapted for Hugging Face Spaces environment
653
+
654
+ This approach maximizes compatibility across different Python environments while working within HF Spaces constraints.
655
+
656
+ ## βœ… What This Solves
657
+
658
+ **Problems addressed:**
659
+
660
+ - βœ… Static libpython not available error
661
+ - βœ… Python version mismatches
662
+ - βœ… HF Spaces environment limitations
663
+ - βœ… WSL compatibility issues
664
+ - βœ… Dependency resolution
665
+ - βœ… Cross-environment portability
666
+
667
+ ## ☁️ Current Environment Status
668
+
669
+ ```
670
+ Platform: {platform.platform()}
671
+ Architecture: {platform.architecture()[0]}
672
+ Machine: {platform.machine()}
673
+ Python Version: {get_current_python_version()}
674
+ Nuitka Version: {get_nuitka_version()}
675
+ Static Libpython: {'βœ… Available' if check_static_libpython() else '❌ Not Available'}
676
+ Environment: Hugging Face Spaces
677
+ ```
678
+
679
+ ## πŸ“‹ Best Practices
680
+
681
+ **Recommendations:**
682
+
683
+ 1. βœ… Always use "Maximum Compatibility" mode
684
+ 2. βœ… Test with simple scripts first
685
+ 3. βœ… Copy binaries to Linux filesystem in WSL
686
+ 4. βœ… Let the app automatically choose the best settings
687
+ 5. βœ… Check the compilation details for specific optimizations used
688
+ 6. βœ… Avoid system packages that require installation
689
+
690
+ ## πŸ”§ Troubleshooting
691
+
692
+ **Common Issues:**
693
+
694
+ - **Import errors**: Check that all packages are in requirements.txt
695
+ - **Binary won't run**: Ensure you're on a compatible Linux system
696
+ - **Permission denied**: Run `chmod +x filename` before execution
697
+ - **Missing libraries**: Try "Maximum Compatibility" mode
698
+
699
+ ## πŸš€ Future Improvements
700
+
701
+ - Support for more compilation targets
702
+ - Better error messages and diagnostics
703
+ - Automatic dependency detection
704
+ - Cross-platform compilation support
705
+ """)
706
+
707
+ gr.Markdown("---")
708
+ gr.Markdown("πŸ€– Created by Claude 3.7 Sonnet | πŸš€ Powered by Nuitka with Smart Compilation | ☁️ Optimized for HF Spaces")
709
+
710
+ if __name__ == "__main__":
711
+ # Create necessary directories on startup
712
+ ensure_dir("user_code")
713
+ ensure_dir("compiled_output")
714
+ app.launch()