packagelister.packagelister_cli

  1import argparse
  2
  3from pathier import Pathier
  4
  5from packagelister import scan
  6
  7""" These are packages whose name doesn't match their `pip install` name.
  8When `packagelister` is generating a requirements file, these substitutions will be made."""
  9
 10pipmappings = {"speech_recognition": "SpeechRecognition"}
 11
 12
 13def main():
 14    def get_args() -> argparse.Namespace:
 15        parser = argparse.ArgumentParser()
 16
 17        parser.add_argument(
 18            "project_path",
 19            nargs="?",
 20            type=str,
 21            default=None,
 22            help=""" The project directory path to scan. """,
 23        )
 24
 25        parser.add_argument(
 26            "-s",
 27            "--show_files",
 28            action="store_true",
 29            help=""" Show which files imported each of the packages. """,
 30        )
 31
 32        parser.add_argument(
 33            "-g",
 34            "--generate_requirements",
 35            action="store_true",
 36            help=""" Generate a requirements.txt file in --project_path. """,
 37        )
 38
 39        parser.add_argument(
 40            "-v",
 41            "--versions",
 42            type=str,
 43            default=None,
 44            choices=["==", "<", "<=", ">", ">=", "~="],
 45            help=""" When generating a requirements.txt file, include the versions of the packages using this relation.
 46            (You may need to put quotes around some of the options.)""",
 47        )
 48
 49        parser.add_argument(
 50            "-i",
 51            "--include_builtins",
 52            action="store_true",
 53            help=""" Include built in standard library modules. """,
 54        )
 55
 56        args = parser.parse_args()
 57
 58        if not args.project_path:
 59            args.project_path = Pathier.cwd()
 60        else:
 61            args.project_path = Pathier(args.project_path)
 62        if not args.project_path.is_absolute():
 63            args.project_path = args.project_path.absolute()
 64
 65        return args
 66
 67    args = get_args()
 68    packages = scan(args.project_path, args.include_builtins)
 69    packages.pop(args.project_path.stem, None)
 70    if args.generate_requirements:
 71        req_path = args.project_path / "requirements.txt"
 72        requirements = "\n".join(
 73            f"{package}{args.versions}{packages[package]['version']}"
 74            if args.versions
 75            else f"{package}"
 76            if packages[package]["version"]
 77            else package
 78            for package in sorted(packages)
 79        )
 80        for mapping in pipmappings:
 81            requirements = requirements.replace(mapping, pipmappings[mapping])
 82        req_path.write_text(requirements)
 83    packages = {
 84        f"{package}=={packages[package]['version']}": packages[package]["files"]
 85        for package in sorted(packages)
 86    }
 87
 88    if args.show_files:
 89        longest_key = max(len(package) for package in packages)
 90        packages = [
 91            f"{package}{' '*(longest_key-len(package)+4)}{', '.join(str(Pathier(file).relative_to(args.project_path)) for file in packages[package])}"
 92            for package in packages
 93        ]
 94
 95    print(f"Packages used in {args.project_path.stem}:")
 96    print(
 97        *packages,
 98        sep="\n",
 99    )
100
101
102if __name__ == "__main__":
103    main()
def main():
 14def main():
 15    def get_args() -> argparse.Namespace:
 16        parser = argparse.ArgumentParser()
 17
 18        parser.add_argument(
 19            "project_path",
 20            nargs="?",
 21            type=str,
 22            default=None,
 23            help=""" The project directory path to scan. """,
 24        )
 25
 26        parser.add_argument(
 27            "-s",
 28            "--show_files",
 29            action="store_true",
 30            help=""" Show which files imported each of the packages. """,
 31        )
 32
 33        parser.add_argument(
 34            "-g",
 35            "--generate_requirements",
 36            action="store_true",
 37            help=""" Generate a requirements.txt file in --project_path. """,
 38        )
 39
 40        parser.add_argument(
 41            "-v",
 42            "--versions",
 43            type=str,
 44            default=None,
 45            choices=["==", "<", "<=", ">", ">=", "~="],
 46            help=""" When generating a requirements.txt file, include the versions of the packages using this relation.
 47            (You may need to put quotes around some of the options.)""",
 48        )
 49
 50        parser.add_argument(
 51            "-i",
 52            "--include_builtins",
 53            action="store_true",
 54            help=""" Include built in standard library modules. """,
 55        )
 56
 57        args = parser.parse_args()
 58
 59        if not args.project_path:
 60            args.project_path = Pathier.cwd()
 61        else:
 62            args.project_path = Pathier(args.project_path)
 63        if not args.project_path.is_absolute():
 64            args.project_path = args.project_path.absolute()
 65
 66        return args
 67
 68    args = get_args()
 69    packages = scan(args.project_path, args.include_builtins)
 70    packages.pop(args.project_path.stem, None)
 71    if args.generate_requirements:
 72        req_path = args.project_path / "requirements.txt"
 73        requirements = "\n".join(
 74            f"{package}{args.versions}{packages[package]['version']}"
 75            if args.versions
 76            else f"{package}"
 77            if packages[package]["version"]
 78            else package
 79            for package in sorted(packages)
 80        )
 81        for mapping in pipmappings:
 82            requirements = requirements.replace(mapping, pipmappings[mapping])
 83        req_path.write_text(requirements)
 84    packages = {
 85        f"{package}=={packages[package]['version']}": packages[package]["files"]
 86        for package in sorted(packages)
 87    }
 88
 89    if args.show_files:
 90        longest_key = max(len(package) for package in packages)
 91        packages = [
 92            f"{package}{' '*(longest_key-len(package)+4)}{', '.join(str(Pathier(file).relative_to(args.project_path)) for file in packages[package])}"
 93            for package in packages
 94        ]
 95
 96    print(f"Packages used in {args.project_path.stem}:")
 97    print(
 98        *packages,
 99        sep="\n",
100    )