C2MV commited on
Commit
efd181d
verified
1 Parent(s): 953dc0b

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +42 -45
app.py CHANGED
@@ -334,7 +334,7 @@ class PaperDownloader:
334
  def _download_single_doi(self, doi, progress_callback, cancel_event): # removed async keyword
335
  """Descargar un 煤nico DOI con retroalimentaci贸n de progreso"""
336
  if not doi:
337
- progress_callback(None, "Error: DOI no proporcionado", "Error: DOI no proporcionado","" )
338
  return None
339
  logger.info(f"Starting download process for DOI: {doi}")
340
 
@@ -356,8 +356,8 @@ class PaperDownloader:
356
 
357
  logger.info(f"Descarga exitosa: {filename}")
358
 
359
- progress_callback(filepath, f"Descargado exitosamente: <a href='https://doi.org/{doi}'>{doi}</a>", "", None)
360
-
361
 
362
  else:
363
  logger.warning(f"No se pudo descargar: {doi}")
@@ -367,18 +367,18 @@ class PaperDownloader:
367
 
368
  except CancelledError:
369
  logger.info(f"Download Cancelled DOI: {doi}")
370
- progress_callback(None, f"Download cancelled {doi}","Download Cancelled", None )
371
 
372
  except Exception as e:
373
  logger.error(f"Error processing {doi}: {e}")
374
- progress_callback(None, f"Error processing {doi}: {e}", f"Error processing {doi}: {e}", None )
375
 
376
 
377
  def download_multiple_dois(self, dois_text, progress_callback, cancel_event): #removed async here
378
  """Download multiple DOIs"""
379
  # Validar entrada
380
  if not dois_text:
381
- progress_callback(None, "Error: No DOIs provided", "Error: No DOIs provided","",)
382
  return None
383
 
384
  # Sanitizar y filtrar DOIs
@@ -387,7 +387,7 @@ class PaperDownloader:
387
 
388
  # Validar lista de DOIs
389
  if not dois:
390
- progress_callback(None, "Error: No valid DOIs provided", "Error: No valid DOIs provided", "")
391
  return None
392
 
393
  # Listas para rastrear resultados
@@ -397,14 +397,14 @@ class PaperDownloader:
397
 
398
 
399
  for doi in dois:
400
- self._download_single_doi(doi, lambda a,b,c, d: progress_callback(a,b,c,d) , cancel_event )
401
  if cancel_event.is_set():
402
  logger.info("Downloads cancelled on multiple dois download")
403
- progress_callback(None, "Downloads cancelled","Downloads cancelled","") # early return on cancelled
404
  return None #break here when is cancelled
405
 
406
- result = self.results_dict.get(doi, (None,None,"",None)) # obtain from self.results
407
-
408
  # Manejar diferentes tipos de resultados
409
  if isinstance(result, Exception):
410
  # Excepci贸n inesperada
@@ -438,9 +438,6 @@ class PaperDownloader:
438
  logger.error(f"Error renaming file for {doi}: {rename_error}")
439
  failed_dois.append(f'<a href="https://doi.org/{doi}">{doi}</a> - Error saving file')
440
 
441
-
442
-
443
-
444
  # Crear archivo ZIP si hay archivos descargados
445
  zip_filename = None
446
  if downloaded_files:
@@ -456,7 +453,7 @@ class PaperDownloader:
456
 
457
 
458
  # Devolver resultados
459
- progress_callback( zip_filename if downloaded_files else None, "\n".join(downloaded_links),"\n".join(failed_dois), "")
460
  return
461
 
462
  def process_bibtex(self, bib_file, progress_callback, cancel_event):# removed async here
@@ -467,7 +464,7 @@ class PaperDownloader:
467
  bib_content = f.read()
468
  except Exception as e:
469
  logger.error(f"Error reading uploaded file {bib_file.name}: {e}")
470
- progress_callback(None, f"Error reading uploaded file {bib_file.name}: {e}", f"Error reading uploaded file {bib_file.name}: {e}" , None)
471
  return None
472
 
473
  # Parse BibTeX data
@@ -489,10 +486,10 @@ class PaperDownloader:
489
 
490
  for doi in dois:
491
 
492
- self._download_single_doi(doi, lambda a,b,c,d: progress_callback(a,b,c,d), cancel_event )
493
  if cancel_event.is_set():
494
  logger.info("Download Cancelled in bibtex mode")
495
- progress_callback(None, "Download Cancelled", "Download Cancelled", None)
496
  return None #cancel if requested
497
 
498
  result = self.results_dict.get(doi, (None,None,"", None)) # obtain from self.results
@@ -527,7 +524,8 @@ class PaperDownloader:
527
  loop.run_in_executor(self.executor, lambda: self.create_zip(zip_filename,downloaded_files))
528
  logger.info(f"ZIP file created: {zip_filename}")
529
 
530
- progress_callback(zip_filename, "\n".join(downloaded_links), "\n".join(failed_dois), "" ) # send 4 parameters to show on log.
 
531
  return
532
 
533
  def create_zip(self, zip_filename, files):
@@ -549,7 +547,7 @@ def create_gradio_interface():
549
  downloader.results_dict = {} #shared results dict, since it runs on different threads
550
 
551
  def update_progress( message="", logs=""):
552
- return gr.Textbox.update(value=f"{message}"),gr.Textbox.update(value=f"<pre>{logs}</pre>")
553
 
554
 
555
  def download_papers(bib_file, doi_input, dois_input):
@@ -557,55 +555,55 @@ def create_gradio_interface():
557
  downloader.cancel_event = cancel_event # store the event so that it is available to stop the process
558
 
559
  def custom_progress_callback(filepath, message, fail_message, doi=None): #new callback to send to the execution function
560
-
561
  logger.info(f"Callback message: {message}") # log each callback msg
562
 
563
  #store data for single or multiple mode on download_papers execution.
564
  if doi:
565
- downloader.results_dict[doi] = (filepath, message,fail_message, "")
 
 
 
566
 
567
- updates = update_progress(message, fail_message) # sending 2
568
  return updates
569
 
570
  if bib_file:
571
  # Check file type
572
  if not bib_file.name.lower().endswith('.bib'):
573
- return None, "Error: Please upload a .bib file", "Error: Please upload a .bib file", "", None
574
 
575
  downloader.download_task = downloader.executor.submit(
576
  downloader.process_bibtex,
577
  bib_file,
578
- lambda a,b,c, d : update_progress(a,f"{b}<br>{c}"), #convert for ui output, the return data will contain the HTML, added d param since all now needs 4 parm
579
  cancel_event # Added cancelllation event.
580
  )
581
-
582
- return None,"","", "", None # output here correct
583
-
584
  elif doi_input:
585
-
586
- downloader.download_task = downloader.executor.submit( #changed async execution method
587
  downloader._download_single_doi,
588
- doi_input,
589
- lambda a,b,c, d: update_progress(a,f"{b}<br>{c}") , #callback function, format output and send html info, removed lambda from executor calls
590
  cancel_event # Add cancellation event.
591
  )
592
-
593
- return None, "","", "", None # output here correct
594
 
595
  elif dois_input:
596
- downloader.download_task = downloader.executor.submit( #changed async execution method
597
- downloader.download_multiple_dois,
598
  dois_input,
599
- lambda a,b,c, d : update_progress(a,f"{b}<br>{c}") ,#callback function
600
- cancel_event #Add cancellation event.
601
- )
602
 
603
- return None, "","", "", None#output here correct
604
-
605
 
606
  else:
607
- return None, "Please provide a .bib file, a single DOI, or a list of DOIs", "Please provide a .bib file, a single DOI, or a list of DOIs", "", None#output here correct
608
-
609
 
610
  with gr.Blocks(theme="Hev832/Applio", css="""
611
  .gradio-container {
@@ -666,10 +664,9 @@ def create_gradio_interface():
666
  submit_button.click(
667
  download_papers,
668
  inputs=[bib_file, doi_input, dois_input],
669
- outputs=[output_file, downloaded_dois_textbox, failed_dois_textbox,logs, single_file ] # the new output should be a tuple and we output logs too for debugging.
670
  )
671
 
672
-
673
  interface.title="馃敩 Academic Paper Batch Downloader"
674
  interface.description="Upload a BibTeX file or enter DOIs to download PDFs. We'll attempt to fetch PDFs from multiple sources like Sci-Hub, Libgen, Google Scholar and Crossref. You can use any of the three inputs at any moment."
675
 
 
334
  def _download_single_doi(self, doi, progress_callback, cancel_event): # removed async keyword
335
  """Descargar un 煤nico DOI con retroalimentaci贸n de progreso"""
336
  if not doi:
337
+ progress_callback(None, "Error: DOI no proporcionado", "Error: DOI no proporcionado","" , None)
338
  return None
339
  logger.info(f"Starting download process for DOI: {doi}")
340
 
 
356
 
357
  logger.info(f"Descarga exitosa: {filename}")
358
 
359
+ progress_callback(filepath, f"Descargado exitosamente: <a href='https://doi.org/{doi}'>{doi}</a>", "", None ) # 4 args with filepath at begin
360
+
361
 
362
  else:
363
  logger.warning(f"No se pudo descargar: {doi}")
 
367
 
368
  except CancelledError:
369
  logger.info(f"Download Cancelled DOI: {doi}")
370
+ progress_callback(None, f"Download cancelled {doi}","Download Cancelled", None) #send proper types with null values
371
 
372
  except Exception as e:
373
  logger.error(f"Error processing {doi}: {e}")
374
+ progress_callback(None, f"Error processing {doi}: {e}", f"Error processing {doi}: {e}", None ) #send proper type of results
375
 
376
 
377
  def download_multiple_dois(self, dois_text, progress_callback, cancel_event): #removed async here
378
  """Download multiple DOIs"""
379
  # Validar entrada
380
  if not dois_text:
381
+ progress_callback(None, "Error: No DOIs provided", "Error: No DOIs provided","", None)
382
  return None
383
 
384
  # Sanitizar y filtrar DOIs
 
387
 
388
  # Validar lista de DOIs
389
  if not dois:
390
+ progress_callback(None, "Error: No valid DOIs provided", "Error: No valid DOIs provided","", None)
391
  return None
392
 
393
  # Listas para rastrear resultados
 
397
 
398
 
399
  for doi in dois:
400
+ self._download_single_doi(doi, lambda a,b,c,d: progress_callback(a,b,c, d) , cancel_event )
401
  if cancel_event.is_set():
402
  logger.info("Downloads cancelled on multiple dois download")
403
+ progress_callback(None, "Downloads cancelled","Downloads cancelled","", None) # early return on cancelled
404
  return None #break here when is cancelled
405
 
406
+ result = self.results_dict.get(doi, (None,None,"", None)) # obtain from self.results
407
+
408
  # Manejar diferentes tipos de resultados
409
  if isinstance(result, Exception):
410
  # Excepci贸n inesperada
 
438
  logger.error(f"Error renaming file for {doi}: {rename_error}")
439
  failed_dois.append(f'<a href="https://doi.org/{doi}">{doi}</a> - Error saving file')
440
 
 
 
 
441
  # Crear archivo ZIP si hay archivos descargados
442
  zip_filename = None
443
  if downloaded_files:
 
453
 
454
 
455
  # Devolver resultados
456
+ progress_callback( zip_filename if downloaded_files else None, "\n".join(downloaded_links),"\n".join(failed_dois), "" , None ) # Send null for zip result to fill params
457
  return
458
 
459
  def process_bibtex(self, bib_file, progress_callback, cancel_event):# removed async here
 
464
  bib_content = f.read()
465
  except Exception as e:
466
  logger.error(f"Error reading uploaded file {bib_file.name}: {e}")
467
+ progress_callback(None, f"Error reading uploaded file {bib_file.name}: {e}", f"Error reading uploaded file {bib_file.name}: {e}", None )
468
  return None
469
 
470
  # Parse BibTeX data
 
486
 
487
  for doi in dois:
488
 
489
+ self._download_single_doi(doi, lambda a,b,c, d: progress_callback(a,b,c, d), cancel_event )
490
  if cancel_event.is_set():
491
  logger.info("Download Cancelled in bibtex mode")
492
+ progress_callback(None, "Download Cancelled", "Download Cancelled", None)
493
  return None #cancel if requested
494
 
495
  result = self.results_dict.get(doi, (None,None,"", None)) # obtain from self.results
 
524
  loop.run_in_executor(self.executor, lambda: self.create_zip(zip_filename,downloaded_files))
525
  logger.info(f"ZIP file created: {zip_filename}")
526
 
527
+ progress_callback(zip_filename, "\n".join(downloaded_links), "\n".join(failed_dois), "", None )#added a "", None in order to work correctly on Blocks interface output
528
+
529
  return
530
 
531
  def create_zip(self, zip_filename, files):
 
547
  downloader.results_dict = {} #shared results dict, since it runs on different threads
548
 
549
  def update_progress( message="", logs=""):
550
+ return gr.Textbox.update(value=f"{message}"),gr.Textbox.update(value=f"<pre>{logs}</pre>")
551
 
552
 
553
  def download_papers(bib_file, doi_input, dois_input):
 
555
  downloader.cancel_event = cancel_event # store the event so that it is available to stop the process
556
 
557
  def custom_progress_callback(filepath, message, fail_message, doi=None): #new callback to send to the execution function
558
+
559
  logger.info(f"Callback message: {message}") # log each callback msg
560
 
561
  #store data for single or multiple mode on download_papers execution.
562
  if doi:
563
+ downloader.results_dict[doi] = (filepath, message,fail_message, "")
564
+
565
+
566
+ updates = update_progress(message, fail_message) #send update info.
567
 
 
568
  return updates
569
 
570
  if bib_file:
571
  # Check file type
572
  if not bib_file.name.lower().endswith('.bib'):
573
+ return None, "Error: Please upload a .bib file", "Error: Please upload a .bib file", "", None #add empty string to satisfy 5 out
574
 
575
  downloader.download_task = downloader.executor.submit(
576
  downloader.process_bibtex,
577
  bib_file,
578
+ lambda a,b,c, d: update_progress(a,f"{b}<br>{c}"), #convert for ui output, the return data will contain the HTML, send 4
579
  cancel_event # Added cancelllation event.
580
  )
581
+
582
+ return None,"","", "", None # returns five
583
+
584
  elif doi_input:
585
+ downloader.download_task = downloader.executor.submit( #changed async execution method
 
586
  downloader._download_single_doi,
587
+ doi_input,
588
+ lambda a,b,c,d: update_progress(a,f"{b}<br>{c}") , #callback function, format output and send html info, removed lambda from executor calls
589
  cancel_event # Add cancellation event.
590
  )
591
+
592
+ return None,"","", "", None # returns five
593
 
594
  elif dois_input:
595
+ downloader.download_task = downloader.executor.submit( #changed async execution method
596
+ downloader.download_multiple_dois,
597
  dois_input,
598
+ lambda a,b,c, d: update_progress(a,f"{b}<br>{c}"), #callback function
599
+ cancel_event #Add cancellation event.
600
+ )
601
 
602
+ return None, "","", "", None #returns five
 
603
 
604
  else:
605
+ return None, "Please provide a .bib file, a single DOI, or a list of DOIs", "Please provide a .bib file, a single DOI, or a list of DOIs", "", None#returns five
606
+
607
 
608
  with gr.Blocks(theme="Hev832/Applio", css="""
609
  .gradio-container {
 
664
  submit_button.click(
665
  download_papers,
666
  inputs=[bib_file, doi_input, dois_input],
667
+ outputs=[output_file, downloaded_dois_textbox, failed_dois_textbox,logs, single_file ] # the new output should be a tuple and we output logs too for debugging.
668
  )
669
 
 
670
  interface.title="馃敩 Academic Paper Batch Downloader"
671
  interface.description="Upload a BibTeX file or enter DOIs to download PDFs. We'll attempt to fetch PDFs from multiple sources like Sci-Hub, Libgen, Google Scholar and Crossref. You can use any of the three inputs at any moment."
672