devendergarg14 commited on
Commit
1b5bfb7
·
verified ·
1 Parent(s): 1381ce0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +64 -12
app.py CHANGED
@@ -7,6 +7,59 @@ import shutil
7
  import glob
8
  import base64
9
  import tempfile
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
10
 
11
  # ---------------------------------------------------------
12
  # 1. Helper Functions
@@ -15,37 +68,28 @@ import tempfile
15
  def modify_animation_times(code: str, factor: float) -> str:
16
  """
17
  Safely scales all numeric run_time and wait() values by a given factor.
18
- This single, safe function is now used for both Pre-check and Preview modes.
19
  """
20
  print(f"⚡ Scaling animation times by a factor of {factor}...", flush=True)
21
- # A safe minimum to prevent Manim from crashing with run_time=0
22
  MIN_RUN_TIME = 0.01
23
 
24
  def scale_match(m, is_wait):
25
  try:
26
  val = float(m.group(2))
27
  new_val = val * factor
28
- # For waits, we can go low. For run_time, we must stay above zero.
29
  final_val = new_val if is_wait else max(new_val, MIN_RUN_TIME)
30
  return f"{m.group(1)}{final_val:.3f}"
31
  except ValueError:
32
- # This happens if run_time is a variable. We safely ignore it.
33
  return m.group(0)
34
 
35
- # This safe regex only matches explicit numbers, preventing SyntaxErrors.
36
  code = re.sub(r"(run_time\s*=\s*)(\d+\.?\d*)", lambda m: scale_match(m, False), code)
37
  code = re.sub(r"(self\.wait\s*\(\s*)(\d+\.?\d*)", lambda m: scale_match(m, True), code)
38
  return code
39
 
40
  def run_manim_pre_check(code_str: str) -> (bool, str):
41
  """
42
- Runs Manim with '-s'. This is the clean and safe version.
43
- - Uses the safe `modify_animation_times` function, so no special error handling is needed.
44
- - Any error that occurs is now considered a real, critical error.
45
- - Soft Pass on Timeout remains as a fallback.
46
  """
47
  print("🕵️ Running fast pre-check with 'manim -s'...", flush=True)
48
- # Using a factor of 0.2 provides a good speedup without being overly aggressive.
49
  fast_code = modify_animation_times(code_str, factor=0.1)
50
 
51
  with open("scene_pre_check.py", "w", encoding="utf-8") as f:
@@ -59,8 +103,10 @@ def run_manim_pre_check(code_str: str) -> (bool, str):
59
  print("✅ Pre-check passed.", flush=True)
60
  return True, "Pre-check successful."
61
  else:
62
- # With our safe regex, any error should be treated as a real problem.
63
  stderr_log = process.stderr.decode('utf-8', 'ignore')
 
 
 
64
  print(f"❌ Pre-check failed with a critical error.\n{stderr_log}", flush=True)
65
  return False, f"⚠️ ERROR: Your code failed the pre-check.\n\n--- ERROR LOG ---\n{stderr_log}"
66
 
@@ -89,7 +135,7 @@ def get_resolution_flags(orientation, quality):
89
 
90
  def run_manim(code_str, orientation, quality, timeout):
91
  """
92
- Executes Manim. Partial stitching on Timeout. No recovery on other errors.
93
  """
94
  timeout_sec = float(timeout) if timeout and float(timeout) > 0 else None
95
  print(f"🎬 Starting Full Render: {orientation} @ {quality} (Timeout: {timeout_sec}s)...", flush=True)
@@ -158,6 +204,10 @@ def run_manim(code_str, orientation, quality, timeout):
158
  print(f"✅ Video Render Success: {found_video_path}", flush=True)
159
  return found_video_path, f"✅ Rendering Successful\n\n{full_logs}", True
160
 
 
 
 
 
161
  return None, f"❌ Failure: Video file was not created.\n\n{full_logs}", False
162
 
163
  # ---------------------------------------------------------
@@ -182,6 +232,8 @@ def render_video_from_code(code, orientation, quality, timeout, preview_factor):
182
  video_path, logs, success = run_manim(code_to_render, orientation, quality, timeout)
183
  return video_path, logs, gr.Button(visible=not success)
184
  except Exception as e:
 
 
185
  return None, f"Rendering failed: {str(e)}", gr.Button(visible=True)
186
 
187
  # ---------------------------------------------------------
 
7
  import glob
8
  import base64
9
  import tempfile
10
+ import requests
11
+ import json
12
+ from datetime import datetime
13
+
14
+ # ---------------------------------------------------------
15
+ # 0. Error Logging Helper (GitHub Gist)
16
+ # ---------------------------------------------------------
17
+
18
+ def log_to_gist(content):
19
+ """
20
+ Silently appends the error content to a GitHub Gist file.
21
+ Uses environment variables for security.
22
+ """
23
+ token = os.getenv("GITHUB_TOKEN")
24
+ gist_id = os.getenv("GIST_ID")
25
+
26
+ if not token or not gist_id:
27
+ print("⚠️ GitHub Token or Gist ID not set. Skipping error logging.", flush=True)
28
+ return
29
+
30
+ filename = "manim_error_history.txt"
31
+ url = f"https://api.github.com/gists/{gist_id}"
32
+ headers = {
33
+ "Authorization": f"token {token}",
34
+ "Accept": "application/vnd.github.v3+json"
35
+ }
36
+
37
+ try:
38
+ # 1. Fetch existing content
39
+ resp = requests.get(url, headers=headers, timeout=5)
40
+ if resp.status_code != 200:
41
+ print(f"⚠️ Failed to fetch Gist history: {resp.status_code}", flush=True)
42
+ return
43
+
44
+ current_data = resp.json()
45
+ old_content = current_data.get('files', {}).get(filename, {}).get('content', "")
46
+
47
+ # 2. Format new entry (Newest at the top)
48
+ timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
49
+ new_entry = f"{'='*40}\nDATE: {timestamp}\n{content}\n\n"
50
+ updated_content = new_entry + old_content
51
+
52
+ # 3. Update Gist
53
+ payload = {"files": {filename: {"content": updated_content}}}
54
+ patch_resp = requests.patch(url, headers=headers, data=json.dumps(payload), timeout=5)
55
+
56
+ if patch_resp.status_code == 200:
57
+ print(f"📋 Error logged to GitHub history. URL: https://gist.github.com/{gist_id}", flush=True)
58
+ else:
59
+ print(f"⚠️ Failed to update Gist: {patch_resp.text}", flush=True)
60
+
61
+ except Exception as e:
62
+ print(f"⚠️ Gist Logging Exception: {str(e)}", flush=True)
63
 
64
  # ---------------------------------------------------------
65
  # 1. Helper Functions
 
68
  def modify_animation_times(code: str, factor: float) -> str:
69
  """
70
  Safely scales all numeric run_time and wait() values by a given factor.
 
71
  """
72
  print(f"⚡ Scaling animation times by a factor of {factor}...", flush=True)
 
73
  MIN_RUN_TIME = 0.01
74
 
75
  def scale_match(m, is_wait):
76
  try:
77
  val = float(m.group(2))
78
  new_val = val * factor
 
79
  final_val = new_val if is_wait else max(new_val, MIN_RUN_TIME)
80
  return f"{m.group(1)}{final_val:.3f}"
81
  except ValueError:
 
82
  return m.group(0)
83
 
 
84
  code = re.sub(r"(run_time\s*=\s*)(\d+\.?\d*)", lambda m: scale_match(m, False), code)
85
  code = re.sub(r"(self\.wait\s*\(\s*)(\d+\.?\d*)", lambda m: scale_match(m, True), code)
86
  return code
87
 
88
  def run_manim_pre_check(code_str: str) -> (bool, str):
89
  """
90
+ Runs Manim with '-s'.
 
 
 
91
  """
92
  print("🕵️ Running fast pre-check with 'manim -s'...", flush=True)
 
93
  fast_code = modify_animation_times(code_str, factor=0.1)
94
 
95
  with open("scene_pre_check.py", "w", encoding="utf-8") as f:
 
103
  print("✅ Pre-check passed.", flush=True)
104
  return True, "Pre-check successful."
105
  else:
 
106
  stderr_log = process.stderr.decode('utf-8', 'ignore')
107
+ # --- LOGGING TO GITHUB ---
108
+ log_to_gist(f"PRE-CHECK FAILED:\n{stderr_log}")
109
+
110
  print(f"❌ Pre-check failed with a critical error.\n{stderr_log}", flush=True)
111
  return False, f"⚠️ ERROR: Your code failed the pre-check.\n\n--- ERROR LOG ---\n{stderr_log}"
112
 
 
135
 
136
  def run_manim(code_str, orientation, quality, timeout):
137
  """
138
+ Executes Manim. Partial stitching on Timeout.
139
  """
140
  timeout_sec = float(timeout) if timeout and float(timeout) > 0 else None
141
  print(f"🎬 Starting Full Render: {orientation} @ {quality} (Timeout: {timeout_sec}s)...", flush=True)
 
204
  print(f"✅ Video Render Success: {found_video_path}", flush=True)
205
  return found_video_path, f"✅ Rendering Successful\n\n{full_logs}", True
206
 
207
+ # --- LOGGING TO GITHUB ---
208
+ # If we reached here, the video was not found or failed completely.
209
+ log_to_gist(f"RENDER FAILED:\n{full_logs}")
210
+
211
  return None, f"❌ Failure: Video file was not created.\n\n{full_logs}", False
212
 
213
  # ---------------------------------------------------------
 
232
  video_path, logs, success = run_manim(code_to_render, orientation, quality, timeout)
233
  return video_path, logs, gr.Button(visible=not success)
234
  except Exception as e:
235
+ # --- LOGGING TO GITHUB ---
236
+ log_to_gist(f"CRITICAL APP EXCEPTION:\n{str(e)}")
237
  return None, f"Rendering failed: {str(e)}", gr.Button(visible=True)
238
 
239
  # ---------------------------------------------------------