3 # Allow execution from anywhere
7 sys
.path
.insert(0, os
.path
.dirname(os
.path
.dirname(os
.path
.abspath(__file__
))))
13 from pathlib
import Path
15 from devscripts
.tomlparse
import parse_toml
16 from devscripts
.utils
import read_file
20 parser
= argparse
.ArgumentParser(description
='Install dependencies for yt-dlp')
22 'input', nargs
='?', metavar
='TOMLFILE', default
=Path(__file__
).parent
.parent
/ 'pyproject.toml',
23 help='input file (default: %(default)s)')
25 '-e', '--exclude', metavar
='DEPENDENCY', action
='append',
26 help='exclude a dependency')
28 '-i', '--include', metavar
='GROUP', action
='append',
29 help='include an optional dependency group')
31 '-o', '--only-optional', action
='store_true',
32 help='only install optional dependencies')
34 '-p', '--print', action
='store_true',
35 help='only print requirements to stdout')
37 '-u', '--user', action
='store_true',
38 help='install with pip as --user')
39 return parser
.parse_args()
44 project_table
= parse_toml(read_file(args
.input))['project']
45 recursive_pattern
= re
.compile(rf
'{project_table["name"]}\[(?P<group_name>[\w-]+)\]')
46 optional_groups
= project_table
['optional-dependencies']
47 excludes
= args
.exclude
or []
49 def yield_deps(group
):
51 if mobj
:= recursive_pattern
.fullmatch(dep
):
52 yield from optional_groups
.get(mobj
.group('group_name'), [])
57 if not args
.only_optional
: # `-o` should exclude 'dependencies' and the 'default' group
58 targets
.extend(project_table
['dependencies'])
59 if 'default' not in excludes
: # `--exclude default` should exclude entire 'default' group
60 targets
.extend(yield_deps(optional_groups
['default']))
62 for include
in filter(None, map(optional_groups
.get
, args
.include
or [])):
63 targets
.extend(yield_deps(include
))
65 targets
= [t
for t
in targets
if re
.match(r
'[\w-]+', t
).group(0).lower() not in excludes
]
68 for target
in targets
:
72 pip_args
= [sys
.executable
, '-m', 'pip', 'install', '-U']
74 pip_args
.append('--user')
75 pip_args
.extend(targets
)
77 return subprocess
.call(pip_args
)
80 if __name__
== '__main__':