5959 "Omit_management" : omit_mgmt ,
6060}
6161
62+
6263def apply_compatibility_filter (package_set : List [str ]) -> List [str ]:
6364 """
6465 This function takes in a set of paths to python packages. It returns the set filtered by compatibility with the currently running python executable.
@@ -393,39 +394,6 @@ def build_and_install_dev_reqs(file: str, pkg_root: str) -> None:
393394 shutil .rmtree (os .path .join (pkg_root , ".tmp_whl_dir" ))
394395
395396
396- def find_whl (package_name : str , version : str , whl_directory : str ) -> str :
397- """Helper function to find where the built whl resides.
398-
399- :param str package_name: the name of the package, e.g. azure-core
400- :param str version: the version used to build the whl
401- :param str whl_directory: the absolute path to the temp directory where the whls are built
402- :return: The absolute path to the whl built
403- """
404- if not os .path .exists (whl_directory ):
405- logging .error ("Whl directory is incorrect" )
406- exit (1 )
407-
408- parsed_version = parse (version )
409-
410- logging .info ("Searching whl for package {0}-{1}" .format (package_name , parsed_version .base_version ))
411- whl_name_format = "{0}-{1}*.whl" .format (package_name .replace ("-" , "_" ), parsed_version .base_version )
412- whls = []
413- for root , dirnames , filenames in os .walk (whl_directory ):
414- for filename in fnmatch .filter (filenames , whl_name_format ):
415- whls .append (os .path .join (root , filename ))
416-
417- whls = [os .path .relpath (w , whl_directory ) for w in whls ]
418-
419- if not whls :
420- logging .error (
421- "whl is not found in whl directory {0} for package {1}-{2}" .format (
422- whl_directory , package_name , parsed_version .base_version
423- )
424- )
425- exit (1 )
426-
427- return whls [0 ]
428-
429397def build_whl_for_req (req : str , package_path : str ) -> str :
430398 """Builds a whl from the dev_requirements file.
431399
@@ -434,6 +402,7 @@ def build_whl_for_req(req: str, package_path: str) -> str:
434402 :return: The absolute path to the whl built or the requirement if a third-party package
435403 """
436404 from ci_tools .build import create_package
405+
437406 if ".." in req :
438407 # Create temp path if it doesn't exist
439408 temp_dir = os .path .join (package_path , ".tmp_whl_dir" )
@@ -446,9 +415,130 @@ def build_whl_for_req(req: str, package_path: str) -> str:
446415 logging .info ("Building wheel for package {}" .format (parsed .name ))
447416 create_package (req_pkg_path , temp_dir , enable_sdist = False )
448417
449- whl_path = os .path .join (temp_dir , find_whl (parsed .name , parsed .version , temp_dir ))
418+ whl_path = os .path .join (temp_dir , find_whl (temp_dir , parsed .name , parsed .version ))
450419 logging .info ("Wheel for package {0} is {1}" .format (parsed .name , whl_path ))
451420 logging .info ("Replacing dev requirement. Old requirement:{0}, New requirement:{1}" .format (req , whl_path ))
452421 return whl_path
453422 else :
454423 return req
424+
425+
426+ def find_sdist (dist_dir : str , pkg_name : str , pkg_version : str ) -> str :
427+ """This function attempts to look within a directory (and all subdirs therein) and find a source distribution for the targeted package and version."""
428+ # This function will find a sdist for given package name
429+ if not os .path .exists (dist_dir ):
430+ logging .error ("dist_dir is incorrect" )
431+ return
432+
433+ if pkg_name is None :
434+ logging .error ("Package name cannot be empty to find sdist" )
435+ return
436+
437+ pkg_name_format = f"{ pkg_name } -{ pkg_version } .zip"
438+ pkg_name_format_alt = "${0}-{1}.tar.gz"
439+
440+ packages = []
441+ for root , dirnames , filenames in os .walk (dist_dir ):
442+ for filename in fnmatch .filter (filenames , pkg_name_format ):
443+ packages .append (os .path .join (root , filename ))
444+
445+ packages = [os .path .relpath (w , dist_dir ) for w in packages ]
446+
447+ if not packages :
448+ logging .error ("No sdist is found in directory %s with package name format %s" , dist_dir , pkg_name_format )
449+ return
450+ return packages [0 ]
451+
452+
453+ def get_interpreter_compatible_tags () -> List [str ]:
454+ """
455+ This function invokes pip from the invoking interpreter and discovers which tags the interpreter is compatible with.
456+ """
457+
458+ commands = [sys .executable , "-m" , "pip" , "debug" , "--verbose" ]
459+
460+ output = subprocess .run (
461+ commands ,
462+ check = True ,
463+ capture_output = True ,
464+ ).stdout .decode (encoding = "utf-8" )
465+
466+ tag_strings = output .split (os .linesep )
467+
468+ for index , value in enumerate (tag_strings ):
469+ if "Compatible tags" in value :
470+ break
471+
472+ tags = tag_strings [index + 1 :]
473+
474+ return [tag .strip () for tag in tags if tag ]
475+
476+
477+ def check_whl_against_tags (whl_name : str , tags : List [str ]) -> bool :
478+ for tag in tags :
479+ if tag in whl_name :
480+ return True
481+ return False
482+
483+
484+ def find_whl (whl_dir : str , pkg_name : str , pkg_version : str ) -> str :
485+ """This function attempts to look within a directory (and all subdirs therein) and find a wheel that matches our targeted name and version AND
486+ whose compilation is compatible with the invoking interpreter."""
487+ if not os .path .exists (whl_dir ):
488+ logging .error ("whl_dir is incorrect" )
489+ return
490+
491+ if pkg_name is None :
492+ logging .error ("Package name cannot be empty to find whl" )
493+ return
494+
495+ pkg_name_format = f"{ pkg_name .replace ('-' , '_' )} -{ pkg_version } *.whl"
496+ whls = []
497+
498+ # todo: replace with glob, we aren't using py2 anymore!
499+ for root , dirnames , filenames in os .walk (whl_dir ):
500+ for filename in fnmatch .filter (filenames , pkg_name_format ):
501+ whls .append (os .path .join (root , filename ))
502+
503+ whls = [os .path .relpath (w , whl_dir ) for w in whls ]
504+
505+ if not whls :
506+ logging .error ("No whl is found in directory %s with package name format %s" , whl_dir , pkg_name_format )
507+ logging .info ("List of whls in directory: %s" , glob .glob (os .path .join (whl_dir , "*.whl" )))
508+ return
509+
510+ compatible_tags = get_interpreter_compatible_tags ()
511+
512+ logging .debug ("Dumping visible tags and whls" )
513+ logging .debug (compatible_tags )
514+ logging .debug (whls )
515+
516+ if whls :
517+ # grab the first whl that matches a tag from our compatible_tags list
518+ for whl in whls :
519+ if check_whl_against_tags (whl , compatible_tags ):
520+ logging .info (f"Found whl { whl } " )
521+ return whl
522+
523+ # if whl is platform independent then there should only be one whl in filtered list
524+ if len (whls ) > 1 :
525+ # if we have reached here, that means we have whl specific to platform as well.
526+ # for now we are failing the test if platform specific wheels are found. Todo: enhance to find platform specific whl
527+ logging .error (f"We were unable to locate a compatible wheel for { pkg_name } " )
528+ sys .exit (1 )
529+
530+ return None
531+
532+
533+ def discover_prebuilt_package (dist_directory : str , setup_path : str , package_type : str ) -> List [str ]:
534+ """Discovers a prebuild wheel or sdist for a given setup path."""
535+ packages = []
536+ pkg = ParsedSetup .from_path (setup_path )
537+ if package_type == "wheel" :
538+ prebuilt_package = find_whl (dist_directory , pkg .name , pkg .version )
539+ else :
540+ prebuilt_package = find_sdist (dist_directory , pkg .name , pkg .version )
541+
542+ if prebuilt_package is not None :
543+ packages .append (prebuilt_package )
544+ return packages
0 commit comments