5252from domdf_python_tools .typing import PathLike
5353from packaging .specifiers import Specifier
5454from packaging .version import Version
55+ from shippinglabel .checksum import get_record_entry
5556from shippinglabel .requirements import ComparableRequirement , combine_requirements , read_requirements
5657
5758# this package
5859from repo_helper import __version__
59- from repo_helper .conda import compile_requirements , validate_requirements
60+ from repo_helper .conda import get_conda_requirements , make_conda_description
6061from repo_helper .configuration import parse_yaml
6162
6263__all__ = ["Builder" , "build_wheel" , "build_sdist" ]
@@ -102,11 +103,8 @@ def __init__(
102103 re .UNICODE ,
103104 ) + f"-{ self .config ['version' ]} "
104105
105- build_dir = build_dir or self .repo_dir / "build/repo_helper_build"
106- self .build_dir = PathPlus (build_dir )
107- if self .build_dir .is_dir ():
108- shutil .rmtree (self .build_dir )
109- self .build_dir .maybe_make (parents = True )
106+ self .build_dir = PathPlus (build_dir or self .repo_dir / "build/repo_helper_build" )
107+ self .clear_build_dir ()
110108 (self .build_dir / self .pkg_dir ).maybe_make (parents = True )
111109
112110 out_dir = out_dir or self .repo_dir / "dist"
@@ -400,22 +398,12 @@ def write_conda_index(self, build_number: int = 1):
400398 build_string = f"py_{ build_number } "
401399 # https://docs.conda.io/projects/conda-build/en/latest/resources/define-metadata.html#build-number-and-string
402400
403- extras = []
404-
405- for extra in self .config ["conda_extras" ]:
406- extras .extend (self .config ["extras_require" ][extra ])
407-
408- all_requirements = validate_requirements (
409- compile_requirements (self .repo_dir , extras ),
410- self .config ["conda_channels" ],
411- )
412-
413401 index = {
414402 "name" : self .config ["pypi_name" ].lower (),
415403 "version" : self .config ["version" ],
416404 "build" : build_string ,
417405 "build_number" : build_number ,
418- "depends" : [ str ( req ) for req in all_requirements ] ,
406+ "depends" : get_conda_requirements ( self . repo_dir , self . config ) ,
419407 "arch" : None ,
420408 "noarch" : "python" ,
421409 "platform" : None ,
@@ -435,12 +423,7 @@ def write_conda_about(self):
435423 """
436424
437425 github_url = "https://github.com/{username}/{repo_name}" .format_map (self .config )
438-
439- conda_description = self .config ["conda_description" ]
440- if self .config ["conda_channels" ]:
441- conda_description += "\n \n \n "
442- conda_description += "Before installing please ensure you have added the following channels:"
443- conda_description += ", " .join (self .config ["conda_channels" ])
426+ conda_description = make_conda_description (self .config ["conda_description" ], self .config ["conda_channels" ])
444427
445428 about = {
446429 "home" : github_url ,
@@ -478,27 +461,14 @@ def create_wheel_archive(self) -> str:
478461 :return: The filename of the created archive.
479462 """
480463
464+ wheel_filename = self .out_dir / f"{ self .archive_name } -{ self .tag } .whl"
481465 self .out_dir .maybe_make (parents = True )
482466
483- def get_record_entry (path : pathlib .Path , build_dir : pathlib .Path , blocksize : int = 1 << 20 ) -> str :
484- sha256_hash = sha256 ()
485- length = 0
486- with path .open ("rb" ) as f :
487- for byte_block in iter (lambda : f .read (blocksize ), b'' ):
488- sha256_hash .update (byte_block )
489- length += len (byte_block )
490- sha256_hash .update (byte_block )
491-
492- digest = "sha256=" + urlsafe_b64encode (sha256_hash .digest ()).decode ("latin1" ).rstrip ('=' )
493-
494- return f"{ path .relative_to (build_dir ).as_posix ()} ,sha256={ digest } ,{ length } "
495-
496- wheel_filename = self .out_dir / f"{ self .archive_name } -{ self .tag } .whl"
497467 with ZipFile (wheel_filename , mode = 'w' ) as wheel_archive :
498468 with (self .dist_info / "RECORD" ).open ('w' ) as fp :
499469 for file in (self .build_dir / self .pkg_dir ).rglob ('*' ):
500470 if file .is_file ():
501- fp .write (get_record_entry (file , self .build_dir ))
471+ fp .write (get_record_entry (file , relative_to = self .build_dir ))
502472 fp .write ('\n ' )
503473 wheel_archive .write (file , arcname = file .relative_to (self .build_dir ))
504474
@@ -508,7 +478,7 @@ def get_record_entry(path: pathlib.Path, build_dir: pathlib.Path, blocksize: int
508478 if not file .is_file ():
509479 continue
510480
511- fp .write (get_record_entry (file , self .build_dir ))
481+ fp .write (get_record_entry (file , relative_to = self .build_dir ))
512482 fp .write ('\n ' )
513483 wheel_archive .write (file , arcname = file .relative_to (self .build_dir ))
514484
@@ -522,7 +492,8 @@ def get_record_entry(path: pathlib.Path, build_dir: pathlib.Path, blocksize: int
522492 Fore .GREEN (f"{ emoji } Wheel created at { wheel_filename .resolve ()} " ),
523493 color = resolve_color_default (),
524494 )
525- return os .path .basename (wheel_filename )
495+
496+ return wheel_filename .name
526497
527498 def create_conda_archive (self , wheel_contents_dir : PathLike , build_number : int = 1 ) -> str :
528499 """
@@ -535,23 +506,22 @@ def create_conda_archive(self, wheel_contents_dir: PathLike, build_number: int =
535506 """
536507
537508 build_string = f"py_{ build_number } "
538-
539- self .out_dir .maybe_make (parents = True )
540-
509+ site_packages = pathlib .PurePosixPath ("site-packages" )
541510 conda_filename = self .out_dir / f"{ self .config ['pypi_name' ].lower ()} -{ self .config ['version' ]} -{ build_string } .tar.bz2"
511+ wheel_contents_dir = PathPlus (wheel_contents_dir )
542512
543- site_packages = PathPlus ( "site-packages" )
513+ self . out_dir . maybe_make ( parents = True )
544514
545515 with tarfile .open (conda_filename , mode = "w:bz2" ) as conda_archive :
546516 with (self .info_dir / "files" ).open ('w' ) as fp :
547517
548- for file in (PathPlus ( wheel_contents_dir ) / self .pkg_dir ).rglob ('*' ):
518+ for file in (wheel_contents_dir / self .pkg_dir ).rglob ('*' ):
549519 if file .is_file ():
550520 filename = (site_packages / file .relative_to (wheel_contents_dir )).as_posix ()
551521 fp .write (f"{ filename } \n " )
552522 conda_archive .add (str (file ), arcname = filename )
553523
554- for file in (PathPlus ( wheel_contents_dir ) / f"{ self .archive_name } .dist-info" ).rglob ('*' ):
524+ for file in (wheel_contents_dir / f"{ self .archive_name } .dist-info" ).rglob ('*' ):
555525 if file .name == "INSTALLER" :
556526 file .write_text ("conda" )
557527
@@ -652,9 +622,7 @@ def build_conda(self) -> str:
652622 # Build the wheel first and clear the build directory
653623 wheel_file = self .build_wheel ()
654624
655- if self .build_dir .is_dir ():
656- shutil .rmtree (self .build_dir )
657- self .build_dir .maybe_make (parents = True )
625+ self .clear_build_dir ()
658626
659627 for license_file in self .repo_dir .glob ("LICEN[CS]E" ):
660628 target = self .info_dir / "license.txt"
@@ -668,39 +636,7 @@ def build_conda(self) -> str:
668636 if self .verbose :
669637 click .echo ("Installing wheel into temporary directory" )
670638
671- command = [
672- "pip" ,
673- "install" ,
674- str (self .out_dir / wheel_file ),
675- "--target" ,
676- str (tmpdir ),
677- "--no-deps" ,
678- "--no-compile" ,
679- "--no-warn-script-location" ,
680- "--no-warn-conflicts" ,
681- "--disable-pip-version-check" ,
682- ]
683- process = Popen (command , stdout = PIPE )
684- (output , err ) = process .communicate ()
685- exit_code = process .wait ()
686-
687- if self .verbose :
688- click .echo ((output or b'' ).decode ("UTF-8" ))
689- click .echo ((err or b'' ).decode ("UTF-8" ), err = True )
690-
691- if exit_code != 0 :
692- err = err or b''
693-
694- raise abort (
695- dedent (
696- f"""\
697- Command '{ ' ' .join (command )} ' returned non-zero exit code { exit_code } :
698-
699- { indent (err .decode ("UTF-8" ), ' ' )}
700- """
701- ).rstrip () + '\n '
702- )
703-
639+ pip_install_wheel (self .out_dir / wheel_file , tmpdir , self .verbose )
704640 conda_filename = self .create_conda_archive (str (tmpdir ), build_number = build_number )
705641
706642 click .echo (
@@ -709,6 +645,15 @@ def build_conda(self) -> str:
709645 )
710646 return conda_filename
711647
648+ def clear_build_dir (self ) -> None :
649+ """
650+ Clear the build directory of any residue from previous builds.
651+ """
652+
653+ if self .build_dir .is_dir ():
654+ shutil .rmtree (self .build_dir )
655+ self .build_dir .maybe_make (parents = True )
656+
712657
713658# copy_file(repo_dir / "__pkginfo__.py")
714659# copy_file(repo_dir / "requirements.txt")
@@ -753,3 +698,39 @@ def build_sdist(sdist_directory, config_settings=None):
753698
754699def get_requires_for_build_sdist (config_settings = None ):
755700 return []
701+
702+
703+ def pip_install_wheel (wheel_file : PathLike , target_dir : PathLike , verbose : bool = False ):
704+ command = [
705+ "pip" ,
706+ "install" ,
707+ os .fspath (wheel_file ),
708+ "--target" ,
709+ os .fspath (target_dir ),
710+ "--no-deps" ,
711+ "--no-compile" ,
712+ "--no-warn-script-location" ,
713+ "--no-warn-conflicts" ,
714+ "--disable-pip-version-check" ,
715+ ]
716+
717+ process = Popen (command , stdout = PIPE )
718+ (output , err ) = process .communicate ()
719+ exit_code = process .wait ()
720+
721+ if verbose :
722+ click .echo ((output or b'' ).decode ("UTF-8" ))
723+ click .echo ((err or b'' ).decode ("UTF-8" ), err = True )
724+
725+ if exit_code != 0 :
726+ err = err or b''
727+
728+ message = dedent (
729+ f"""\
730+ Command '{ ' ' .join (command )} ' returned non-zero exit code { exit_code } :
731+
732+ { indent (err .decode ("UTF-8" ), ' ' )}
733+ """
734+ )
735+
736+ raise abort (message .rstrip () + '\n ' )
0 commit comments