WebashalarForML commited on
Commit
7d75cd8
·
verified ·
1 Parent(s): 4c316b6

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +72 -86
app.py CHANGED
@@ -1833,7 +1833,7 @@ def similarity_matching(input_json_path: str, project_folder:str) -> str:
1833
  # DEFINE PATHS #
1834
  # ============================== #
1835
  image_dirs = [backdrop_images_path, sprite_images_path]
1836
-
1837
  project_json_path = os.path.join(project_folder, "project.json")
1838
 
1839
  # ============================== #
@@ -1869,6 +1869,7 @@ def similarity_matching(input_json_path: str, project_folder:str) -> str:
1869
  SPRITE_DIR / "Crab.sprite3" / "bear_element.png",
1870
  SPRITE_DIR / "Soccer Ball.sprite3" / "cat_football.png",
1871
  ]
 
1872
  # ============================== #
1873
  # DECODE SPRITE IMAGES #
1874
  # ============================== #
@@ -2121,41 +2122,45 @@ def upscale_image(image: Image.Image, scale: int = 2) -> Image.Image:
2121
  logger.error(f"❌ Error during image upscaling: {str(e)}")
2122
  return image
2123
 
2124
- def create_sb3_archive(project_folder: Path, project_id: str) -> Path | None:
2125
  """
2126
  Zips the project folder and renames it to an .sb3 file.
 
2127
  Args:
2128
- project_folder (Path): The path to the directory containing the project.json and assets.
2129
  project_id (str): The unique ID for the project, used for naming the .sb3 file.
 
2130
  Returns:
2131
- Path: The path to the created .sb3 file, or None if an error occurred.
2132
  """
2133
  print(" --------------------------------------- create_sb3_archive INITIALIZE ---------------------------------------")
2134
- output_base_name = GEN_PROJECT_DIR / project_id
 
 
2135
  zip_path = None
2136
  sb3_path = None
2137
  try:
2138
- # shutil.make_archive automatically adds .zip extension
2139
- print(" --------------------------------------- zip_path_str ---------------------------------------", output_base_name, project_folder)
2140
- zip_path_str = shutil.make_archive(str(output_base_name), 'zip', root_dir=str(project_folder))
2141
- zip_path = Path(zip_path_str) # Convert back to Path object
2142
  logger.info(f"Project folder zipped to: {zip_path}")
2143
-
2144
  # 2. Rename the .zip file to .sb3
2145
- sb3_path = GEN_PROJECT_DIR / f"{project_id}.sb3"
2146
  os.rename(zip_path, sb3_path)
 
2147
  logger.info(f"Renamed {zip_path} to {sb3_path}")
2148
 
2149
  return sb3_path
2150
  except Exception as e:
2151
- logger.error(f"Error creating SB3 archive for {project_id}: {e}", exc_info=True)
2152
  # Clean up any partial files if an error occurs
2153
- if zip_path and zip_path.exists():
2154
  os.remove(zip_path)
2155
- if sb3_path and sb3_path.exists():
2156
  os.remove(sb3_path)
2157
  return None
2158
 
 
2159
  @app.route('/')
2160
  def index():
2161
  return render_template('app_index.html')
@@ -2166,30 +2171,28 @@ def download_sb3(project_id):
2166
  Allows users to download the generated .sb3 Scratch project file.
2167
  """
2168
  sb3_filename = f"{project_id}.sb3"
2169
- sb3_filepath = GEN_PROJECT_DIR / sb3_filename
2170
 
2171
  try:
2172
- if sb3_filepath.exists():
2173
  logger.info(f"Serving SB3 file for project ID: {project_id}")
 
2174
  return send_from_directory(
2175
- directory=GEN_PROJECT_DIR,
2176
  path=sb3_filename,
2177
- as_attachment=True,
2178
- download_name=sb3_filename
2179
  )
2180
  else:
2181
- logger.warning(f"SB3 file not found for ID: {project_id} at {sb3_filepath}")
2182
  return jsonify({"error": "Scratch project file not found"}), 404
2183
  except Exception as e:
2184
- logger.error(f"Error serving SB3 file for ID {project_id}: {e}", exc_info=True)
2185
  return jsonify({"error": "Failed to retrieve Scratch project file"}), 500
2186
 
 
2187
  @app.route('/process_pdf', methods=['POST'])
2188
  def process_pdf():
2189
- project_id = None
2190
- project_folder = None
2191
- temp_dir = None
2192
- extracted_json_parent_dir = None # Initialize for finally block cleanup or later use
2193
  try:
2194
  logger.info("Received request to process PDF.")
2195
  if 'pdf_file' not in request.files:
@@ -2200,48 +2203,59 @@ def process_pdf():
2200
  if pdf_file.filename == '':
2201
  return jsonify({"error": "Empty filename"}), 400
2202
 
 
 
 
2203
  project_id = str(uuid.uuid4()).replace('-', '')
 
2204
  project_folder = OUTPUT_DIR / project_id
2205
 
2206
- project_folder.mkdir(parents=True, exist_ok=True)
2207
- logger.info(f"Created project folder: {project_folder}")
2208
-
 
 
 
2209
  filename = secure_filename(pdf_file.filename)
2210
- temp_dir = Path(tempfile.mkdtemp())
2211
- saved_pdf_path = temp_dir / filename
2212
  pdf_file.save(saved_pdf_path)
2213
 
 
2214
  logger.info(f"Saved uploaded PDF to: {saved_pdf_path}")
2215
 
2216
- # MODIFIED CALL: Pass JSON_DIR and DETECTED_IMAGE_DIR
2217
- # extract_images_from_pdf now returns the file path to extracted_sprites.json
2218
- # and the parent directory where it was created.
2219
- extracted_sprites_json_file_path, extracted_json_parent_dir = extract_images_from_pdf(
2220
- saved_pdf_path, JSON_DIR, DETECTED_IMAGE_DIR
2221
- )
2222
-
2223
- # Now, directly use extracted_sprites_json_file_path to check for its existence
2224
- if not extracted_sprites_json_file_path.exists():
2225
- logger.error(f"No extracted_sprites.json found at {extracted_sprites_json_file_path}")
2226
- return jsonify({"error": "No extracted_sprites.json found"}), 500
2227
 
2228
- with open(extracted_sprites_json_file_path, 'r') as f:
2229
- sprite_data = json.load(f)
2230
 
2231
- # MODIFIED CALL: Pass the extracted_json_parent_dir (the directory) to similarity_matching
2232
- project_output = similarity_matching(extracted_json_parent_dir, project_folder)
2233
- logger.info("Similarity matching completed.")
 
 
2234
 
2235
  with open(project_output, 'r') as f:
2236
  project_skeleton = json.load(f)
2237
 
2238
- images = convert_from_path(saved_pdf_path, dpi=300)
 
 
2239
  page = images[0]
 
2240
  buf = BytesIO()
2241
  page.save(buf, format="PNG")
2242
  img_bytes = buf.getvalue()
2243
  img_b64 = base64.b64encode(img_bytes).decode("utf-8")
 
2244
 
 
2245
  # initial_state_dict = {
2246
  # "project_json": project_skeleton,
2247
  # "description": "The pseudo code for the script",
@@ -2252,59 +2266,31 @@ def process_pdf():
2252
  # "temporary_node": {},
2253
  # }
2254
 
2255
- # final_state_dict = app_graph.invoke(initial_state_dict)
2256
 
2257
- final_project_json = project_skeleton # final_state_dict['project_json']
 
2258
 
 
2259
  with open(project_output, "w") as f:
2260
  json.dump(final_project_json, f, indent=2)
2261
  logger.info(f"Final project JSON saved to {project_output}")
2262
 
 
2263
  sb3_file_path = create_sb3_archive(project_folder, project_id)
2264
  if sb3_file_path:
2265
  logger.info(f"Successfully created SB3 file: {sb3_file_path}")
2266
- download_url = f"/download_sb3/{project_id}"
 
2267
  print(f"DOWNLOAD_URL: {download_url}")
2268
- return jsonify({"message": "Processed PDF and Game sb3 generated successfully", "project_id": project_id, "download_url": download_url})
2269
  else:
2270
  return jsonify(error="Failed to create SB3 archive"), 500
2271
 
2272
  except Exception as e:
2273
  logger.error(f"Error during processing the pdf workflow for project ID {project_id}: {e}", exc_info=True)
2274
- return jsonify({"error": f"❌ Failed to process PDF: {str(e)}"}), 500
2275
- finally:
2276
- if temp_dir and temp_dir.exists():
2277
- shutil.rmtree(temp_dir)
2278
- logger.info(f"Cleaned up temporary directory: {temp_dir}")
2279
-
2280
- # Optional: Clean up the extracted JSON and image directories for this project_id
2281
- # if extracted_json_parent_dir and extracted_json_parent_dir.exists():
2282
- # shutil.rmtree(extracted_json_parent_dir)
2283
- # logger.info(f"Cleaned up extracted JSON directory: {extracted_json_parent_dir}")
2284
- # if pdf_filename_stem: # You'd need to get pdf_filename_stem from `filename` earlier
2285
- # corresponding_image_dir = DETECTED_IMAGE_DIR / pdf_filename_stem
2286
- # if corresponding_image_dir.exists():
2287
- # shutil.rmtree(corresponding_image_dir)
2288
- # logger.info(f"Cleaned up detected image directory: {corresponding_image_dir}")
2289
-
2290
-
2291
- @app.route('/list_projects', methods=['GET'])
2292
- def list_projects():
2293
- """
2294
- Lists all generated .sb3 files and their download URLs for debugging.
2295
- """
2296
- try:
2297
- sb3_files = []
2298
- for file_path in GEN_PROJECT_DIR.iterdir():
2299
- if file_path.suffix == '.sb3' and file_path.is_file():
2300
- project_id = file_path.stem
2301
- download_url = f"/download_sb3/{project_id}"
2302
- sb3_files.append({"project_id": project_id, "download_url": download_url, "filename": file_path.name})
2303
-
2304
- return jsonify({"generated_sb3_files": sb3_files}), 200
2305
- except Exception as e:
2306
- logger.error(f"Error listing projects: {e}", exc_info=True)
2307
- return jsonify({"error": "Failed to list generated projects"}), 500
2308
-
2309
  if __name__ == '__main__':
 
2310
  app.run(host='0.0.0.0', port=7860, debug=True)
 
1833
  # DEFINE PATHS #
1834
  # ============================== #
1835
  image_dirs = [backdrop_images_path, sprite_images_path]
1836
+ print(" --------------------------------------- input_json_path ---------------------------------------", input_json_path)
1837
  project_json_path = os.path.join(project_folder, "project.json")
1838
 
1839
  # ============================== #
 
1869
  SPRITE_DIR / "Crab.sprite3" / "bear_element.png",
1870
  SPRITE_DIR / "Soccer Ball.sprite3" / "cat_football.png",
1871
  ]
1872
+ print(" --------------------------------------- folder_image_paths ---------------------------------------\n", folder_image_paths)
1873
  # ============================== #
1874
  # DECODE SPRITE IMAGES #
1875
  # ============================== #
 
2122
  logger.error(f"❌ Error during image upscaling: {str(e)}")
2123
  return image
2124
 
2125
+ def create_sb3_archive(project_folder, project_id):
2126
  """
2127
  Zips the project folder and renames it to an .sb3 file.
2128
+
2129
  Args:
2130
+ project_folder (str): The path to the directory containing the project.json and assets.
2131
  project_id (str): The unique ID for the project, used for naming the .sb3 file.
2132
+
2133
  Returns:
2134
+ str: The path to the created .sb3 file, or None if an error occurred.
2135
  """
2136
  print(" --------------------------------------- create_sb3_archive INITIALIZE ---------------------------------------")
2137
+ # output_filename = os.path.join("outputs", project_id)
2138
+ #output_filename = OUTPUT_DIR / project_id
2139
+ output_filename = GEN_PROJECT_DIR / project_id
2140
  zip_path = None
2141
  sb3_path = None
2142
  try:
2143
+ zip_path = shutil.make_archive(output_filename, 'zip', root_dir=project_folder)
2144
+ print(" --------------------------------------- zip_path_str ---------------------------------------", output_base_name, project_folder)
 
 
2145
  logger.info(f"Project folder zipped to: {zip_path}")
2146
+
2147
  # 2. Rename the .zip file to .sb3
2148
+ sb3_path = f"{output_filename}.sb3"
2149
  os.rename(zip_path, sb3_path)
2150
+ print(" --------------------------------------- rename paths ---------------------------------------", zip_path, sb3_path)
2151
  logger.info(f"Renamed {zip_path} to {sb3_path}")
2152
 
2153
  return sb3_path
2154
  except Exception as e:
2155
+ logger.error(f"Error creating SB3 archive for {project_id}: {e}")
2156
  # Clean up any partial files if an error occurs
2157
+ if zip_path and os.path.exists(zip_path):
2158
  os.remove(zip_path)
2159
+ if sb3_path and os.path.exists(sb3_path):
2160
  os.remove(sb3_path)
2161
  return None
2162
 
2163
+
2164
  @app.route('/')
2165
  def index():
2166
  return render_template('app_index.html')
 
2171
  Allows users to download the generated .sb3 Scratch project file.
2172
  """
2173
  sb3_filename = f"{project_id}.sb3"
2174
+ sb3_filepath = os.path.join("generated_projects", sb3_filename)
2175
 
2176
  try:
2177
+ if os.path.exists(sb3_filepath):
2178
  logger.info(f"Serving SB3 file for project ID: {project_id}")
2179
+ # send_from_directory serves the file and handles content-disposition for download
2180
  return send_from_directory(
2181
+ directory="generated_projects",
2182
  path=sb3_filename,
2183
+ as_attachment=True, # This makes the browser download the file
2184
+ download_name=sb3_filename # This sets the filename for the download
2185
  )
2186
  else:
2187
+ logger.warning(f"SB3 file not found for ID: {project_id}")
2188
  return jsonify({"error": "Scratch project file not found"}), 404
2189
  except Exception as e:
2190
+ logger.error(f"Error serving SB3 file for ID {project_id}: {e}")
2191
  return jsonify({"error": "Failed to retrieve Scratch project file"}), 500
2192
 
2193
+ # API endpoint
2194
  @app.route('/process_pdf', methods=['POST'])
2195
  def process_pdf():
 
 
 
 
2196
  try:
2197
  logger.info("Received request to process PDF.")
2198
  if 'pdf_file' not in request.files:
 
2203
  if pdf_file.filename == '':
2204
  return jsonify({"error": "Empty filename"}), 400
2205
 
2206
+ # ================================================= #
2207
+ # Generate Random UUID for project folder name #
2208
+ # ================================================= #
2209
  project_id = str(uuid.uuid4()).replace('-', '')
2210
+ # project_folder = os.path.join("outputs", f"{project_id}")
2211
  project_folder = OUTPUT_DIR / project_id
2212
 
2213
+ # =========================================================================== #
2214
+ # Create empty json in project_{random_id} folder #
2215
+ # =========================================================================== #
2216
+ #os.makedirs(project_folder, exist_ok=True)
2217
+
2218
+ # Save the uploaded PDF temporarily
2219
  filename = secure_filename(pdf_file.filename)
2220
+ temp_dir = tempfile.mkdtemp()
2221
+ saved_pdf_path = os.path.join(temp_dir, filename)
2222
  pdf_file.save(saved_pdf_path)
2223
 
2224
+ # logger.info(f"Created project folder: {project_folder}")
2225
  logger.info(f"Saved uploaded PDF to: {saved_pdf_path}")
2226
 
2227
+ # Extract & process
2228
+ json_path = None
2229
+ output_path, result = extract_images_from_pdf(saved_pdf_path, json_path)
2230
+ print(" --------------------------------------- zip_path_str ---------------------------------------", output_path, result)
2231
+ # Check extracted_sprites.json for "scratch block" in any 'name'
2232
+ # extracted_dir = os.path.join(JSON_DIR, os.path.splitext(filename)[0])
2233
+ # extracted_sprites_json = os.path.join(extracted_dir, "extracted_sprites.json")
 
 
 
 
2234
 
2235
+ # if not os.path.exists(extracted_sprites_json):
2236
+ # return jsonify({"error": "No extracted_sprites.json found"}), 500
2237
 
2238
+ # with open(extracted_sprites_json, 'r') as f:
2239
+ # sprite_data = json.load(f)
2240
+
2241
+ project_output = similarity_matching(output_path, project_folder)
2242
+ logger.info("Received request to process PDF.")
2243
 
2244
  with open(project_output, 'r') as f:
2245
  project_skeleton = json.load(f)
2246
 
2247
+
2248
+ images = convert_from_path(saved_pdf_path, dpi=300)
2249
+ print(type)
2250
  page = images[0]
2251
+ # img_base64 = base64.b64encode(images).decode("utf-8")
2252
  buf = BytesIO()
2253
  page.save(buf, format="PNG")
2254
  img_bytes = buf.getvalue()
2255
  img_b64 = base64.b64encode(img_bytes).decode("utf-8")
2256
+ #image_paths = await convert_pdf_to_images_async(saved_pdf_path)
2257
 
2258
+ #updating logic here [Dev Patel]
2259
  # initial_state_dict = {
2260
  # "project_json": project_skeleton,
2261
  # "description": "The pseudo code for the script",
 
2266
  # "temporary_node": {},
2267
  # }
2268
 
2269
+ # final_state_dict = app_graph.invoke(initial_state_dict) # Pass dictionary
2270
 
2271
+ # final_project_json = final_state_dict['project_json'] # Access as dict
2272
+ final_project_json = project_skeleton
2273
 
2274
+ # Save the *final* filled project JSON, overwriting the skeleton
2275
  with open(project_output, "w") as f:
2276
  json.dump(final_project_json, f, indent=2)
2277
  logger.info(f"Final project JSON saved to {project_output}")
2278
 
2279
+ # --- Call the new function to create the .sb3 file ---
2280
  sb3_file_path = create_sb3_archive(project_folder, project_id)
2281
  if sb3_file_path:
2282
  logger.info(f"Successfully created SB3 file: {sb3_file_path}")
2283
+ # Instead of returning the local path, return a URL to the download endpoint
2284
+ download_url = f"https://prthm11-scratch-vlm-v1.hf.space/download_sb3/{project_id}"
2285
  print(f"DOWNLOAD_URL: {download_url}")
2286
+ return jsonify({"message": "Procesed PDF and Game sb3 generated successfully", "project_id": project_id, "download_url": download_url})
2287
  else:
2288
  return jsonify(error="Failed to create SB3 archive"), 500
2289
 
2290
  except Exception as e:
2291
  logger.error(f"Error during processing the pdf workflow for project ID {project_id}: {e}", exc_info=True)
2292
+ return jsonify({"error": f"❌ Failed to process PDF: {str(e)}"}), 500
2293
+
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
2294
  if __name__ == '__main__':
2295
+ # os.makedirs("outputs", exist_ok=True) #== commented by P
2296
  app.run(host='0.0.0.0', port=7860, debug=True)