euler314 commited on
Commit
9cb71bc
Β·
verified Β·
1 Parent(s): a9c2a7c

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +367 -98
app.py CHANGED
@@ -9,6 +9,7 @@ import time
9
  from pathlib import Path
10
  import tempfile
11
  import glob
 
12
 
13
  def ensure_dir(dir_path):
14
  """Ensure directory exists"""
@@ -18,6 +19,14 @@ def check_dependencies():
18
  """Check if required dependencies are available"""
19
  missing_deps = []
20
 
 
 
 
 
 
 
 
 
21
  # Check for patchelf (usually available in HF Spaces)
22
  result = subprocess.run(["which", "patchelf"], capture_output=True)
23
  if result.returncode != 0:
@@ -61,11 +70,32 @@ def get_nuitka_version():
61
  # Extract version number from output like "Nuitka 2.5.0"
62
  version = version_line.split()[-1]
63
  return version
64
- return "unknown"
65
  except:
66
- return "unknown"
67
 
68
- def install_system_packages(packages_content, progress=gr.Progress()):
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
69
  """Note about system packages in HF Spaces - they cannot be installed"""
70
  if not packages_content.strip():
71
  return "No system packages specified."
@@ -78,6 +108,26 @@ def install_system_packages(packages_content, progress=gr.Progress()):
78
  return f"❌ System packages cannot be installed in Hugging Face Spaces:\n{', '.join(packages_list)}\n\nℹ️ HF Spaces runs in a containerized environment without sudo access.\nThese packages need to be pre-installed in the Docker image or available as Python packages."
79
  return "No system packages specified."
80
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
81
  def find_compiled_binary(output_dir, output_filename):
82
  """Find the compiled binary, checking different possible paths"""
83
  # Try direct path first
@@ -105,65 +155,94 @@ def find_compiled_binary(output_dir, output_filename):
105
 
106
  return None
107
 
108
- def compile_with_nuitka(code, requirements, packages, compilation_mode, output_extension, progress=gr.Progress()):
109
  """Compile Python code with Nuitka"""
110
- progress(0, desc="Starting compilation process...")
111
-
112
- # Check Nuitka version
113
- nuitka_version = get_nuitka_version()
114
-
115
- # Check if static libpython is available
116
- has_static_libpython = check_static_libpython()
117
-
118
- # Check dependencies first
119
- missing_deps = check_dependencies()
120
-
121
- # Create unique ID for this compilation
122
- job_id = str(uuid.uuid4())
123
- base_dir = os.path.join(os.getcwd(), "user_code")
124
- job_dir = os.path.join(base_dir, job_id)
125
- output_dir = os.path.join(os.getcwd(), "compiled_output", job_id)
126
-
127
- # Create directories
128
- ensure_dir(job_dir)
129
- ensure_dir(output_dir)
130
-
131
- progress(0.1, desc="Processing packages...")
132
-
133
- # Handle system packages (just log them, can't install in HF Spaces)
134
- packages_result = install_system_packages(packages, progress)
135
-
136
- # Write code to a Python file
137
- script_path = os.path.join(job_dir, "user_script.py")
138
- with open(script_path, "w") as f:
139
- f.write(code)
140
-
141
- # Handle requirements
142
- install_result = "No Python requirements specified."
143
- if requirements.strip():
144
- req_path = os.path.join(job_dir, "requirements.txt")
145
- with open(req_path, "w") as f:
146
- f.write(requirements)
147
-
148
- try:
149
- progress(0.2, desc="Installing Python requirements...")
150
- install_process = subprocess.run(
151
- [sys.executable, "-m", "pip", "install", "--no-cache-dir", "-r", req_path],
152
- capture_output=True,
153
- text=True
154
- )
155
-
156
- if install_process.returncode == 0:
157
- install_result = "βœ… Python requirements installed successfully."
158
- else:
159
- install_result = f"⚠️ Installation completed with warnings. Return code: {install_process.returncode}\n{install_process.stderr}"
160
- except Exception as e:
161
- install_result = f"❌ Error installing requirements: {str(e)}"
162
- return install_result, None, f"Error: {str(e)}", False
163
-
164
- # Compilation
165
  try:
166
- progress(0.3, desc="Starting compilation...")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
167
 
168
  # Build compilation command based on mode
169
  if compilation_mode == "Maximum Compatibility (Recommended)":
@@ -216,6 +295,9 @@ def compile_with_nuitka(code, requirements, packages, compilation_mode, output_e
216
  mode_name = "Standalone Binary"
217
 
218
  # Run compilation
 
 
 
219
  process = subprocess.Popen(
220
  cmd,
221
  stdout=subprocess.PIPE,
@@ -235,15 +317,25 @@ def compile_with_nuitka(code, requirements, packages, compilation_mode, output_e
235
  line_count += 1
236
 
237
  # Update progress
238
- progress_val = 0.3 + (min(line_count / 200, 0.69) * 0.7)
 
 
239
  if "INFO:" in line:
240
- progress(progress_val, desc=f"Compiling: {line.strip()[:50]}...")
241
- else:
242
- progress(progress_val, desc="Compiling...")
 
 
 
 
 
 
 
243
 
244
  process.wait()
245
 
246
- progress(0.9, desc="Finalizing...")
 
247
 
248
  # Find the compiled binary
249
  output_filename = f"user_script{output_extension}"
@@ -305,7 +397,7 @@ def compile_with_nuitka(code, requirements, packages, compilation_mode, output_e
305
  file_size = os.path.getsize(binary_path) / 1024
306
  binary_basename = os.path.basename(binary_path)
307
 
308
- # Create result summary without f-string to avoid syntax issues
309
  result_summary = f"""# βœ… Compilation Successful!
310
 
311
  ## Compilation Details:
@@ -344,9 +436,11 @@ This binary was compiled in a Hugging Face Spaces environment. For best results:
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:
@@ -357,26 +451,54 @@ This binary was compiled in a Hugging Face Spaces environment. For best 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"""
@@ -424,13 +546,16 @@ with gr.Blocks(title="Nuitka Python Compiler for HF Spaces", theme=gr.themes.Sof
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
 
@@ -509,6 +634,8 @@ print(f'Hello, {name}!')""",
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:
@@ -516,6 +643,11 @@ print(f'Hello, {name}!')""",
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):
@@ -533,33 +665,149 @@ print(f'Hello, {name}!')""",
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):
@@ -572,7 +820,7 @@ print(f'Hello, {name}!')""",
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(
@@ -606,6 +854,7 @@ print(f'Hello, {name}!')""",
606
 
607
  ### 3. Compile
608
  - Click "Compile with Nuitka"
 
609
  - Wait for the compilation to complete
610
  - Download the resulting binary
611
 
@@ -630,6 +879,14 @@ print(f'Hello, {name}!')""",
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 |
@@ -650,6 +907,7 @@ print(f'Hello, {name}!')""",
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
 
@@ -663,6 +921,7 @@ print(f'Hello, {name}!')""",
663
  - βœ… WSL compatibility issues
664
  - βœ… Dependency resolution
665
  - βœ… Cross-environment portability
 
666
 
667
  ## ☁️ Current Environment Status
668
 
@@ -686,6 +945,8 @@ print(f'Hello, {name}!')""",
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
 
@@ -695,6 +956,8 @@ print(f'Hello, {name}!')""",
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
 
@@ -702,6 +965,7 @@ print(f'Hello, {name}!')""",
702
  - Better error messages and diagnostics
703
  - Automatic dependency detection
704
  - Cross-platform compilation support
 
705
  """)
706
 
707
  gr.Markdown("---")
@@ -711,4 +975,9 @@ if __name__ == "__main__":
711
  # Create necessary directories on startup
712
  ensure_dir("user_code")
713
  ensure_dir("compiled_output")
 
 
 
 
 
714
  app.launch()
 
9
  from pathlib import Path
10
  import tempfile
11
  import glob
12
+ import traceback
13
 
14
  def ensure_dir(dir_path):
15
  """Ensure directory exists"""
 
19
  """Check if required dependencies are available"""
20
  missing_deps = []
21
 
22
+ # Check for nuitka first
23
+ try:
24
+ result = subprocess.run([sys.executable, "-m", "nuitka", "--version"], capture_output=True, text=True)
25
+ if result.returncode != 0:
26
+ missing_deps.append("nuitka")
27
+ except:
28
+ missing_deps.append("nuitka")
29
+
30
  # Check for patchelf (usually available in HF Spaces)
31
  result = subprocess.run(["which", "patchelf"], capture_output=True)
32
  if result.returncode != 0:
 
70
  # Extract version number from output like "Nuitka 2.5.0"
71
  version = version_line.split()[-1]
72
  return version
73
+ return "not installed"
74
  except:
75
+ return "not installed"
76
 
77
+ def create_progress_bar(progress, status_text="", show_percentage=True):
78
+ """Create an HTML progress bar"""
79
+ percentage = max(0, min(100, progress * 100))
80
+
81
+ color = "bg-green-500" if percentage == 100 else ("bg-yellow-500" if percentage > 50 else "bg-blue-500")
82
+
83
+ html = f"""
84
+ <div style="width: 100%; background-color: #f0f0f0; border-radius: 10px; padding: 3px; box-shadow: inset 0 2px 4px rgba(0,0,0,0.1);">
85
+ <div style="width: {percentage}%; background: linear-gradient(90deg, #4CAF50 0%, #45a049 100%);
86
+ height: 25px; border-radius: 8px; transition: width 0.3s ease-in-out; display: flex; align-items: center; justify-content: center;">
87
+ <span style="color: white; font-weight: bold; font-size: 12px;">
88
+ {f'{percentage:.1f}%' if show_percentage else ''}
89
+ </span>
90
+ </div>
91
+ </div>
92
+ <div style="margin-top: 8px; text-align: center; color: #333; font-size: 14px; font-weight: 500;">
93
+ {status_text}
94
+ </div>
95
+ """
96
+ return html
97
+
98
+ def install_system_packages(packages_content, progress_callback=None):
99
  """Note about system packages in HF Spaces - they cannot be installed"""
100
  if not packages_content.strip():
101
  return "No system packages specified."
 
108
  return f"❌ System packages cannot be installed in Hugging Face Spaces:\n{', '.join(packages_list)}\n\nℹ️ HF Spaces runs in a containerized environment without sudo access.\nThese packages need to be pre-installed in the Docker image or available as Python packages."
109
  return "No system packages specified."
110
 
111
+ def install_nuitka_if_missing():
112
+ """Try to install Nuitka if it's missing"""
113
+ try:
114
+ # Check if nuitka is already installed
115
+ result = subprocess.run([sys.executable, "-m", "nuitka", "--version"], capture_output=True)
116
+ if result.returncode == 0:
117
+ return True, "Nuitka is already installed"
118
+
119
+ # Try to install nuitka
120
+ print("Installing Nuitka...")
121
+ result = subprocess.run([sys.executable, "-m", "pip", "install", "nuitka"],
122
+ capture_output=True, text=True)
123
+
124
+ if result.returncode == 0:
125
+ return True, "Nuitka installed successfully"
126
+ else:
127
+ return False, f"Failed to install Nuitka: {result.stderr}"
128
+ except Exception as e:
129
+ return False, f"Error installing Nuitka: {str(e)}"
130
+
131
  def find_compiled_binary(output_dir, output_filename):
132
  """Find the compiled binary, checking different possible paths"""
133
  # Try direct path first
 
155
 
156
  return None
157
 
158
+ def compile_with_nuitka(code, requirements, packages, compilation_mode, output_extension, progress_callback=None):
159
  """Compile Python code with Nuitka"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
160
  try:
161
+ # Initialize progress
162
+ if progress_callback:
163
+ progress_callback(0, "Starting compilation process...")
164
+
165
+ # Check if Nuitka is installed
166
+ nuitka_installed, nuitka_msg = install_nuitka_if_missing()
167
+ if not nuitka_installed:
168
+ error_summary = f"""# ❌ Nuitka Not Available
169
+
170
+ ## Error:
171
+ {nuitka_msg}
172
+
173
+ ## Solution:
174
+ Nuitka needs to be installed first. In Hugging Face Spaces, this should be done in the requirements.txt file:
175
+
176
+ ```
177
+ nuitka
178
+ ```
179
+
180
+ Add this to your requirements.txt and redeploy the space."""
181
+ return error_summary, None, nuitka_msg, False
182
+
183
+ if progress_callback:
184
+ progress_callback(0.05, "Checking environment...")
185
+
186
+ # Check Nuitka version
187
+ nuitka_version = get_nuitka_version()
188
+
189
+ # Check if static libpython is available
190
+ has_static_libpython = check_static_libpython()
191
+
192
+ # Check dependencies first
193
+ missing_deps = check_dependencies()
194
+
195
+ if progress_callback:
196
+ progress_callback(0.1, "Setting up compilation directories...")
197
+
198
+ # Create unique ID for this compilation
199
+ job_id = str(uuid.uuid4())
200
+ base_dir = os.path.join(os.getcwd(), "user_code")
201
+ job_dir = os.path.join(base_dir, job_id)
202
+ output_dir = os.path.join(os.getcwd(), "compiled_output", job_id)
203
+
204
+ # Create directories
205
+ ensure_dir(job_dir)
206
+ ensure_dir(output_dir)
207
+
208
+ if progress_callback:
209
+ progress_callback(0.15, "Processing packages...")
210
+
211
+ # Handle system packages (just log them, can't install in HF Spaces)
212
+ packages_result = install_system_packages(packages)
213
+
214
+ # Write code to a Python file
215
+ script_path = os.path.join(job_dir, "user_script.py")
216
+ with open(script_path, "w") as f:
217
+ f.write(code)
218
+
219
+ if progress_callback:
220
+ progress_callback(0.2, "Installing Python requirements...")
221
+
222
+ # Handle requirements
223
+ install_result = "No Python requirements specified."
224
+ if requirements.strip():
225
+ req_path = os.path.join(job_dir, "requirements.txt")
226
+ with open(req_path, "w") as f:
227
+ f.write(requirements)
228
+
229
+ try:
230
+ install_process = subprocess.run(
231
+ [sys.executable, "-m", "pip", "install", "--no-cache-dir", "-r", req_path],
232
+ capture_output=True,
233
+ text=True
234
+ )
235
+
236
+ if install_process.returncode == 0:
237
+ install_result = "βœ… Python requirements installed successfully."
238
+ else:
239
+ install_result = f"⚠️ Installation completed with warnings. Return code: {install_process.returncode}\n{install_process.stderr}"
240
+ except Exception as e:
241
+ install_result = f"❌ Error installing requirements: {str(e)}"
242
+ return install_result, None, f"Error: {str(e)}", False
243
+
244
+ if progress_callback:
245
+ progress_callback(0.3, "Building compilation command...")
246
 
247
  # Build compilation command based on mode
248
  if compilation_mode == "Maximum Compatibility (Recommended)":
 
295
  mode_name = "Standalone Binary"
296
 
297
  # Run compilation
298
+ if progress_callback:
299
+ progress_callback(0.4, "Executing Nuitka compilation...")
300
+
301
  process = subprocess.Popen(
302
  cmd,
303
  stdout=subprocess.PIPE,
 
317
  line_count += 1
318
 
319
  # Update progress
320
+ progress_val = 0.4 + (min(line_count / 200, 0.55) * 0.5)
321
+ status_text = "Compiling..."
322
+
323
  if "INFO:" in line:
324
+ status_text = f"INFO: {line.strip()[:60]}..."
325
+ elif "PROCESSING" in line:
326
+ status_text = f"Processing: {line.strip()[:60]}..."
327
+ elif "Optimizing" in line:
328
+ status_text = f"Optimizing: {line.strip()[:60]}..."
329
+ elif "Creating" in line:
330
+ status_text = f"Creating: {line.strip()[:60]}..."
331
+
332
+ if progress_callback:
333
+ progress_callback(progress_val, status_text)
334
 
335
  process.wait()
336
 
337
+ if progress_callback:
338
+ progress_callback(0.9, "Finalizing compilation...")
339
 
340
  # Find the compiled binary
341
  output_filename = f"user_script{output_extension}"
 
397
  file_size = os.path.getsize(binary_path) / 1024
398
  binary_basename = os.path.basename(binary_path)
399
 
400
+ # Create result summary
401
  result_summary = f"""# βœ… Compilation Successful!
402
 
403
  ## Compilation Details:
 
436
  2. Make it executable: `chmod +x filename`
437
  3. Run it in a compatible Linux environment"""
438
 
439
+ if progress_callback:
440
+ progress_callback(1.0, "Compilation successful! πŸŽ‰")
441
  return result_summary, binary_path, compile_output, True
442
  else:
443
+ # Add more detailed error information
444
  error_summary = f"""# ❌ Compilation Failed
445
 
446
  ## Error Details:
 
451
  **System Packages**: {packages_result}
452
  **Python Requirements**: {install_result}
453
 
454
+ ## Compilation Output:
455
+ ```
456
+ {compile_output}
457
+ ```
458
+
459
  ## Possible Solutions:
460
  1. Check your code for syntax errors
461
+ 2. Ensure all imports are available in requirements.txt
462
  3. Try a different compilation mode
463
+ 4. Review the compilation logs above
464
 
465
  ## Missing Dependencies:
466
+ {', '.join(missing_deps) if missing_deps else 'None detected'}
467
+
468
+ ## Environment Info:
469
+ - **Nuitka Version**: {nuitka_version}
470
+ - **Python Version**: {current_python}
471
+ - **Platform**: {platform.platform()}"""
472
+ if progress_callback:
473
+ progress_callback(1.0, "Compilation failed ❌")
474
  return error_summary, None, compile_output, False
475
 
476
  except Exception as e:
477
+ # Provide detailed error information
478
+ error_trace = traceback.format_exc()
479
  error_summary = f"""# ❌ Compilation Error
480
 
481
  ## Error:
482
  {str(e)}
483
 
484
+ ## Full Error Trace:
485
+ ```
486
+ {error_trace}
487
+ ```
488
+
489
+ ## Environment Status:
490
+ - **Nuitka Version**: {get_nuitka_version()}
491
+ - **Python Version**: {get_current_python_version()}
492
+ - **Working Directory**: {os.getcwd()}
493
+
494
+ ## Troubleshooting Steps:
495
+ 1. Check if Nuitka is properly installed
496
+ 2. Verify your code syntax
497
+ 3. Check available disk space
498
+ 4. Try with simpler code first"""
499
+ if progress_callback:
500
+ progress_callback(1.0, "Error occurred ❌")
501
+ return error_summary, None, f"Error: {str(e)}\n\n{error_trace}", False
502
 
503
  def run_compiled_binary(binary_path):
504
  """Run the compiled binary and return the output"""
 
546
  has_static = check_static_libpython()
547
  missing_deps = check_dependencies()
548
 
549
+ if "nuitka" in missing_deps:
550
+ gr.Markdown("⚠️ **Nuitka is not installed!** Add 'nuitka' to your requirements.txt file.")
551
+
552
  if has_static:
553
  gr.Markdown("🎯 **Static Libpython Available!** Maximum portability enabled.")
554
  else:
555
  gr.Markdown("πŸ”§ **Using alternative portable options.** Static libpython not available.")
556
 
557
+ if [dep for dep in missing_deps if dep != "nuitka"]:
558
+ gr.Markdown(f"⚠️ **Missing dependencies:** {', '.join([dep for dep in missing_deps if dep != 'nuitka'])}")
559
  else:
560
  gr.Markdown("βœ… **All required dependencies available!**")
561
 
 
634
  )
635
 
636
  gr.Markdown(f"πŸ“ **Compiling with Python {get_current_python_version()}**")
637
+ gr.Markdown(f"πŸ”§ **Nuitka Version**: {get_nuitka_version()}")
638
+
639
  if check_static_libpython():
640
  gr.Markdown("πŸ”— **Static libpython will be used!**")
641
  else:
 
643
 
644
  compile_btn = gr.Button("πŸš€ Compile with Nuitka", variant="primary")
645
 
646
+ # Progress Bar Section
647
+ with gr.Column(visible=False) as progress_section:
648
+ gr.Markdown("### πŸ“Š Compilation Progress")
649
+ progress_bar = gr.HTML(create_progress_bar(0, "Ready to compile..."))
650
+
651
  # Results section
652
  with gr.Column(visible=False) as results_section:
653
  with gr.Accordion("πŸ“Š Compilation Results", open=True):
 
665
  current_binary_path = gr.State(None)
666
  compilation_success = gr.State(False)
667
 
668
+ def update_progress_display(progress, status):
669
+ """Update the progress bar display"""
670
+ return gr.update(value=create_progress_bar(progress, status))
671
+
672
+ def handle_compilation(code, requirements, packages, mode, extension):
673
+ try:
674
+ # Show progress section
675
+ yield (
676
+ gr.update(visible=True), # progress_section
677
+ gr.update(value=create_progress_bar(0, "Initializing compilation...")), # progress_bar
678
+ gr.update(visible=False), # results_section (hide initially)
679
+ gr.update(), # result_summary
680
+ gr.update(), # compile_logs
681
+ gr.update(visible=False), # download_file
682
+ None, # current_binary_path
683
+ False # compilation_success
684
+ )
685
+
686
+ # Define progress callback
687
+ def progress_callback(progress, status):
688
+ # This will be called by compile_with_nuitka to update progress
689
+ pass
690
+
691
+ # Start compilation with manual progress updates
692
+ compilation_started = False
693
+
694
+ # Step 1: Initial checks
695
+ yield (
696
+ gr.update(visible=True), # progress_section
697
+ gr.update(value=create_progress_bar(0.1, "Checking Nuitka installation...")), # progress_bar
698
+ gr.update(visible=False), # results_section
699
+ gr.update(), # result_summary
700
+ gr.update(), # compile_logs
701
+ gr.update(visible=False), # download_file
702
+ None, # current_binary_path
703
+ False # compilation_success
704
+ )
705
 
706
+ # Step 2: Environment setup
707
+ yield (
708
+ gr.update(visible=True), # progress_section
709
+ gr.update(value=create_progress_bar(0.2, "Setting up environment...")), # progress_bar
710
+ gr.update(visible=False), # results_section
711
+ gr.update(), # result_summary
712
+ gr.update(), # compile_logs
713
+ gr.update(visible=False), # download_file
714
+ None, # current_binary_path
715
+ False # compilation_success
716
+ )
717
+
718
+ # Step 3: Installing requirements
719
+ yield (
720
+ gr.update(visible=True), # progress_section
721
+ gr.update(value=create_progress_bar(0.3, "Installing requirements...")), # progress_bar
722
+ gr.update(visible=False), # results_section
723
+ gr.update(), # result_summary
724
+ gr.update(), # compile_logs
725
+ gr.update(visible=False), # download_file
726
+ None, # current_binary_path
727
+ False # compilation_success
728
+ )
729
+
730
+ # Step 4: Compilation in progress
731
+ for i in range(4, 9):
732
+ yield (
733
+ gr.update(visible=True), # progress_section
734
+ gr.update(value=create_progress_bar(i/10, "Compiling with Nuitka...")), # progress_bar
735
+ gr.update(visible=False), # results_section
736
+ gr.update(), # result_summary
737
+ gr.update(), # compile_logs
738
+ gr.update(visible=False), # download_file
739
+ None, # current_binary_path
740
+ False # compilation_success
741
+ )
742
+ time.sleep(0.5) # Small delay to show progress
743
+
744
+ # Run the actual compilation
745
+ summary, binary_path, logs, success = compile_with_nuitka(
746
+ code, requirements, packages, mode, extension
747
+ )
748
+
749
+ # Final progress update
750
+ yield (
751
+ gr.update(visible=True), # progress_section
752
+ gr.update(value=create_progress_bar(1.0, "Compilation complete!" if success else "Compilation failed")), # progress_bar
753
  gr.update(visible=True), # results_section
754
  gr.update(value=summary), # result_summary
755
+ gr.update(value=logs), # compile_logs
756
+ gr.update(visible=False), # download_file (initially hidden)
757
+ None, # current_binary_path
758
+ False # compilation_success
759
  )
760
+
761
+ if success and binary_path:
762
+ # Create download file
763
+ download_filename = f"compiled_program{extension}"
764
+ download_path = os.path.join(os.path.dirname(binary_path), download_filename)
765
+ shutil.copy2(binary_path, download_path)
766
+
767
+ # Final update with download file
768
+ yield (
769
+ gr.update(visible=True), # progress_section
770
+ gr.update(value=create_progress_bar(1.0, "βœ… Compilation successful! Ready to download.")), # progress_bar
771
+ gr.update(visible=True), # results_section
772
+ gr.update(value=summary), # result_summary
773
+ gr.update(value=logs), # compile_logs
774
+ gr.update(value=download_path, visible=True), # download_file
775
+ binary_path, # current_binary_path
776
+ True # compilation_success
777
+ )
778
+ else:
779
+ # Final update for failure
780
+ yield (
781
+ gr.update(visible=True), # progress_section
782
+ gr.update(value=create_progress_bar(1.0, "❌ Compilation failed. Check logs for details.")), # progress_bar
783
+ gr.update(visible=True), # results_section
784
+ gr.update(value=summary), # result_summary
785
+ gr.update(value=logs), # compile_logs
786
+ gr.update(visible=False), # download_file
787
+ None, # current_binary_path
788
+ False # compilation_success
789
+ )
790
+
791
+ except Exception as e:
792
+ error_trace = traceback.format_exc()
793
+ error_summary = f"""# ❌ Unexpected Error in Compilation Handler
794
+
795
+ ## Error:
796
+ {str(e)}
797
+
798
+ ## Full Trace:
799
+ ```
800
+ {error_trace}
801
+ ```"""
802
+ yield (
803
+ gr.update(visible=True), # progress_section
804
+ gr.update(value=create_progress_bar(1.0, "❌ Error occurred during compilation")), # progress_bar
805
  gr.update(visible=True), # results_section
806
+ gr.update(value=error_summary), # result_summary
807
+ gr.update(value=f"Error: {str(e)}"), # compile_logs
808
  gr.update(visible=False), # download_file
809
+ None, # current_binary_path
810
+ False # compilation_success
811
  )
812
 
813
  def handle_run(binary_path):
 
820
  compile_btn.click(
821
  handle_compilation,
822
  inputs=[code_input, requirements_input, packages_input, compilation_mode, output_extension],
823
+ outputs=[progress_section, progress_bar, results_section, result_summary, compile_logs, download_file, current_binary_path, compilation_success]
824
  )
825
 
826
  run_btn.click(
 
854
 
855
  ### 3. Compile
856
  - Click "Compile with Nuitka"
857
+ - Watch the progress bar for compilation status
858
  - Wait for the compilation to complete
859
  - Download the resulting binary
860
 
 
879
  - Compilation happens in a containerized environment
880
  - Binary execution may have resource limits
881
 
882
+ ## πŸ“‹ Important Requirements
883
+
884
+ For this app to work in HF Spaces, ensure your `requirements.txt` includes:
885
+ ```
886
+ gradio
887
+ nuitka
888
+ ```
889
+
890
  ## πŸ“Š Compilation Modes Comparison
891
 
892
  | Mode | Size | Portability | Speed | Best For |
 
907
  3. **Fallback Strategy**: Ensures compilation succeeds even without static linking
908
  4. **Automatic Dependencies**: Resolves missing dependencies automatically
909
  5. **HF Spaces Optimization**: Adapted for Hugging Face Spaces environment
910
+ 6. **Real-time Progress**: Shows compilation progress with a visual progress bar
911
 
912
  This approach maximizes compatibility across different Python environments while working within HF Spaces constraints.
913
 
 
921
  - βœ… WSL compatibility issues
922
  - βœ… Dependency resolution
923
  - βœ… Cross-environment portability
924
+ - βœ… Real-time compilation feedback
925
 
926
  ## ☁️ Current Environment Status
927
 
 
945
  4. βœ… Let the app automatically choose the best settings
946
  5. βœ… Check the compilation details for specific optimizations used
947
  6. βœ… Avoid system packages that require installation
948
+ 7. βœ… Include 'nuitka' in your requirements.txt for HF Spaces
949
+ 8. βœ… Watch the progress bar for compilation status
950
 
951
  ## πŸ”§ Troubleshooting
952
 
 
956
  - **Binary won't run**: Ensure you're on a compatible Linux system
957
  - **Permission denied**: Run `chmod +x filename` before execution
958
  - **Missing libraries**: Try "Maximum Compatibility" mode
959
+ - **Nothing happens on click**: Check that Nuitka is installed in requirements.txt
960
+ - **Compilation stuck**: Check the progress bar and logs for details
961
 
962
  ## πŸš€ Future Improvements
963
 
 
965
  - Better error messages and diagnostics
966
  - Automatic dependency detection
967
  - Cross-platform compilation support
968
+ - Enhanced progress tracking
969
  """)
970
 
971
  gr.Markdown("---")
 
975
  # Create necessary directories on startup
976
  ensure_dir("user_code")
977
  ensure_dir("compiled_output")
978
+
979
+ # Check if Nuitka is available
980
+ if "nuitka" in check_dependencies():
981
+ print("WARNING: Nuitka is not installed. Please add 'nuitka' to your requirements.txt file.")
982
+
983
  app.launch()