install_deps.py 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081
  1. #!/usr/bin/env python3
  2. # Allow execution from anywhere
  3. import os
  4. import sys
  5. sys.path.insert(0, os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
  6. import argparse
  7. import re
  8. import subprocess
  9. from pathlib import Path
  10. from devscripts.tomlparse import parse_toml
  11. from devscripts.utils import read_file
  12. def parse_args():
  13. parser = argparse.ArgumentParser(description='Install dependencies for yt-dlp')
  14. parser.add_argument(
  15. 'input', nargs='?', metavar='TOMLFILE', default=Path(__file__).parent.parent / 'pyproject.toml',
  16. help='input file (default: %(default)s)')
  17. parser.add_argument(
  18. '-e', '--exclude', metavar='DEPENDENCY', action='append',
  19. help='exclude a dependency')
  20. parser.add_argument(
  21. '-i', '--include', metavar='GROUP', action='append',
  22. help='include an optional dependency group')
  23. parser.add_argument(
  24. '-o', '--only-optional', action='store_true',
  25. help='only install optional dependencies')
  26. parser.add_argument(
  27. '-p', '--print', action='store_true',
  28. help='only print requirements to stdout')
  29. parser.add_argument(
  30. '-u', '--user', action='store_true',
  31. help='install with pip as --user')
  32. return parser.parse_args()
  33. def main():
  34. args = parse_args()
  35. project_table = parse_toml(read_file(args.input))['project']
  36. recursive_pattern = re.compile(rf'{project_table["name"]}\[(?P<group_name>[\w-]+)\]')
  37. optional_groups = project_table['optional-dependencies']
  38. excludes = args.exclude or []
  39. def yield_deps(group):
  40. for dep in group:
  41. if mobj := recursive_pattern.fullmatch(dep):
  42. yield from optional_groups.get(mobj.group('group_name'), [])
  43. else:
  44. yield dep
  45. targets = []
  46. if not args.only_optional: # `-o` should exclude 'dependencies' and the 'default' group
  47. targets.extend(project_table['dependencies'])
  48. if 'default' not in excludes: # `--exclude default` should exclude entire 'default' group
  49. targets.extend(yield_deps(optional_groups['default']))
  50. for include in filter(None, map(optional_groups.get, args.include or [])):
  51. targets.extend(yield_deps(include))
  52. targets = [t for t in targets if re.match(r'[\w-]+', t).group(0).lower() not in excludes]
  53. if args.print:
  54. for target in targets:
  55. print(target)
  56. return
  57. pip_args = [sys.executable, '-m', 'pip', 'install', '-U']
  58. if args.user:
  59. pip_args.append('--user')
  60. pip_args.extend(targets)
  61. return subprocess.call(pip_args)
  62. if __name__ == '__main__':
  63. sys.exit(main())