@@ -434,7 +434,6 @@ def download_and_install(self):
434434 """Download and install.
435435
436436 Called when ``self.submit_button.clicked`` is emitted.
437-
438437 """
439438 self .setEnabled (False )
440439 QtWidgets .QApplication .processEvents ()
@@ -452,7 +451,18 @@ def download_and_install(self):
452451 filename = "Miniforge3-22.11.1-4-Windows-x86_64.exe"
453452 LOG .info ("Installing miniconda from %s" , url )
454453
455- self ._download (url , filename , when_finished = self ._run_install_python )
454+ try :
455+ self ._download (url , filename , when_finished = self ._run_install_python )
456+ except Exception as err :
457+ if os .name == "nt" :
458+ LOG .warning (
459+ "Download using requests library failed... Going to fallback method for Windows."
460+ )
461+ self ._windows_fallback_download (
462+ url , filename , when_finished = self ._run_install_python
463+ )
464+ else :
465+ raise err
456466 except Exception as e :
457467 self .show_error (str (e ))
458468 self .setEnabled (True )
@@ -540,6 +550,50 @@ def update(b=1, bsize=1, tsize=None):
540550 if when_finished is not None :
541551 when_finished (output_path )
542552
553+ def _windows_fallback_download (self , url , filename , when_finished = None ):
554+ """Download a file. Fallback method for Windows.
555+
556+ Deletes any pre-existing output file with the same name. Then, performs
557+ the download using PowerShell and the Invoke-RestMethod command.
558+
559+ ``when_finished`` must accept one parameter, the path of the file downloaded.
560+
561+ Parameters
562+ ----------
563+ url : str
564+ File to download.
565+ filename : str
566+ The basename of the file to download.
567+ when_finished : callable, optional
568+ Function to call when complete. Function should accept one
569+ parameter: the full path of the file downloaded.
570+ """
571+ # Delete pre-existing cache. This is fail-safe mode
572+ output_path = os .path .join (CACHE_DIR , filename )
573+ if os .path .isfile (output_path ):
574+ os .remove (output_path )
575+
576+ # Perform download using Invoke-RestMethod
577+ out , error_code = run_ps (
578+ f"Invoke-RestMethod '{ url } ' -Method 'GET' -OutFile '{ output_path } '"
579+ )
580+
581+ if error_code :
582+ LOG .error (
583+ f"Error while downloading Python on Windows fail-safe mode: { out .decode ('utf-8' )} "
584+ )
585+ msg = QtWidgets .QMessageBox ()
586+ msg .warning (
587+ self ,
588+ "Error while downloading Python on Windows fail-safe mode!" ,
589+ f"Error message:\n \n { out .decode ('utf-8' )} " ,
590+ )
591+ self .setEnabled (True )
592+ return
593+
594+ if when_finished is not None :
595+ when_finished (output_path )
596+
543597 def _run_install_python (self , filename ):
544598 """Execute the installation process."""
545599 LOG .debug ("Executing run_install_python" )
0 commit comments