@@ -360,7 +360,7 @@ def remove(self, *, ignore_errors: bool = True) -> None:
360360 # delattr on a cached_property may raise on some versions / edge cases
361361 pass
362362
363- def prepare (self ) -> tuple :
363+ def prepare (self ) -> None :
364364 """Prepares the payload.
365365
366366 Directory structure created during preparation:
@@ -369,9 +369,10 @@ def prepare(self) -> tuple:
369369 └── <EXTERNAL_PACKAGE_PATH>/ (external_dir: contains the payload archive and conda exe)
370370 └── base/ (base_dir: represents the base conda environment)
371371 └── pkgs/ (pkgs_dir: staging area for conda package distributions)
372+
373+ Note: base_dir and pkgs_dir are removed after archiving.
372374 """
373- root = self .root
374- external_dir = root / EXTERNAL_PACKAGE_PATH
375+ external_dir = self .root / EXTERNAL_PACKAGE_PATH
375376 external_dir .mkdir (parents = True , exist_ok = True )
376377
377378 # Note that the directory name "base" is also explicitly defined in `run_installation.bat`
@@ -380,9 +381,9 @@ def prepare(self) -> tuple:
380381
381382 pkgs_dir = base_dir / "pkgs"
382383 pkgs_dir .mkdir ()
383- # Render the template files and add them to the necessary config field
384+
384385 self .render_templates ()
385- self .write_pyproject_toml (root , external_dir )
386+ self .write_pyproject_toml (self . root , external_dir )
386387
387388 preconda .write_files (self .info , base_dir )
388389 preconda .copy_extra_files (self .info .get ("extra_files" , []), external_dir )
@@ -392,7 +393,6 @@ def prepare(self) -> tuple:
392393 archive_path = self .make_archive (base_dir , external_dir )
393394 if not archive_path .exists ():
394395 raise RuntimeError (f"Unexpected error, failed to create archive: { archive_path } " )
395- return (root , external_dir , base_dir , pkgs_dir )
396396
397397 def make_archive (self , src : Path , dst : Path ) -> Path :
398398 """Create an archive of the directory 'src'.
@@ -522,40 +522,42 @@ def _stage_conda(self, external_dir: Path) -> None:
522522
523523def create (info , verbose = False ):
524524 if not IS_WINDOWS :
525- raise Exception (f"Invalid platform '{ sys .platform } '. MSI installers require Windows." )
525+ raise OSError (f"Invalid platform '{ sys .platform } '. MSI installers require Windows." )
526526
527527 if not info .get ("_conda_exe_supports_logging" ):
528- raise Exception ("MSI installers require conda-standalone with logging support." )
529-
530- # MSI installers always use conda-standalone for uninstallation.
531- # This ensures proper cleanup of conda init, environments, and shortcuts
532- # via the `conda constructor uninstall` command.
533- info ["uninstall_with_conda_exe" ] = True
534-
535- payload = Payload (info )
536- payload .prepare ()
528+ raise ValueError ("MSI installers require conda-standalone with logging support." )
537529
530+ # Check briefcase exists before doing any work
538531 briefcase = Path (sysconfig .get_path ("scripts" )) / "briefcase.exe"
539532 if not briefcase .exists ():
540533 raise FileNotFoundError (
541534 f"Dependency 'briefcase' does not seem to be installed.\n Tried: { briefcase } "
542535 )
543536
544- logger .info ("Building MSI installer" )
545- run (
546- [briefcase , "package" ] + (["-v" ] if verbose else []),
547- cwd = payload .root ,
548- check = True ,
549- )
550-
551- dist_dir = payload .root / "dist"
552- msi_paths = list (dist_dir .glob ("*.msi" ))
553- if len (msi_paths ) != 1 :
554- raise RuntimeError (f"Found { len (msi_paths )} MSI files in { dist_dir } , expected 1." )
537+ # MSI installers always use conda-standalone for uninstallation.
538+ # This ensures proper cleanup of conda init, environments, and shortcuts
539+ # via the `conda constructor uninstall` command.
540+ info ["uninstall_with_conda_exe" ] = True
555541
556- outpath = Path (info ["_outpath" ])
557- outpath .unlink (missing_ok = True )
558- shutil .move (msi_paths [0 ], outpath )
542+ payload = Payload (info )
543+ try :
544+ payload .prepare ()
545+
546+ logger .info ("Building MSI installer" )
547+ run (
548+ [briefcase , "package" ] + (["-v" ] if verbose else []),
549+ cwd = payload .root ,
550+ check = True ,
551+ )
559552
560- if not info .get ("_debug" ):
561- payload .remove ()
553+ dist_dir = payload .root / "dist"
554+ msi_paths = list (dist_dir .glob ("*.msi" ))
555+ if len (msi_paths ) != 1 :
556+ raise RuntimeError (f"Found { len (msi_paths )} MSI files in { dist_dir } , expected 1." )
557+
558+ outpath = Path (info ["_outpath" ])
559+ outpath .unlink (missing_ok = True )
560+ shutil .move (msi_paths [0 ], outpath )
561+ finally :
562+ if not info .get ("_debug" ):
563+ payload .remove ()
0 commit comments