1"""
2Wheel command-line utility.
3"""
4
5from __future__ import annotations
6
7import argparse
8import os
9import sys
10from argparse import ArgumentTypeError
11
12
13class WheelError(Exception):
14 pass
15
16
17def unpack_f(args: argparse.Namespace) -> None:
18 from .unpack import unpack
19
20 unpack(args.wheelfile, args.dest)
21
22
23def pack_f(args: argparse.Namespace) -> None:
24 from .pack import pack
25
26 pack(args.directory, args.dest_dir, args.build_number)
27
28
29def convert_f(args: argparse.Namespace) -> None:
30 from .convert import convert
31
32 convert(args.files, args.dest_dir, args.verbose)
33
34
35def tags_f(args: argparse.Namespace) -> None:
36 from .tags import tags
37
38 names = (
39 tags(
40 wheel,
41 args.python_tag,
42 args.abi_tag,
43 args.platform_tag,
44 args.build,
45 args.remove,
46 )
47 for wheel in args.wheel
48 )
49
50 for name in names:
51 print(name)
52
53
54def version_f(args: argparse.Namespace) -> None:
55 from .. import __version__
56
57 print(f"wheel {__version__}")
58
59
60def parse_build_tag(build_tag: str) -> str:
61 if build_tag and not build_tag[0].isdigit():
62 raise ArgumentTypeError("build tag must begin with a digit")
63 elif "-" in build_tag:
64 raise ArgumentTypeError("invalid character ('-') in build tag")
65
66 return build_tag
67
68
69TAGS_HELP = """\
70Make a new wheel with given tags. Any tags unspecified will remain the same.
71Starting the tags with a "+" will append to the existing tags. Starting with a
72"-" will remove a tag (use --option=-TAG syntax). Multiple tags can be
73separated by ".". The original file will remain unless --remove is given. The
74output filename(s) will be displayed on stdout for further processing.
75"""
76
77
78def parser():
79 p = argparse.ArgumentParser()
80 s = p.add_subparsers(help="commands")
81
82 unpack_parser = s.add_parser("unpack", help="Unpack wheel")
83 unpack_parser.add_argument(
84 "--dest", "-d", help="Destination directory", default="."
85 )
86 unpack_parser.add_argument("wheelfile", help="Wheel file")
87 unpack_parser.set_defaults(func=unpack_f)
88
89 repack_parser = s.add_parser("pack", help="Repack wheel")
90 repack_parser.add_argument("directory", help="Root directory of the unpacked wheel")
91 repack_parser.add_argument(
92 "--dest-dir",
93 "-d",
94 default=os.path.curdir,
95 help="Directory to store the wheel (default %(default)s)",
96 )
97 repack_parser.add_argument(
98 "--build-number", help="Build tag to use in the wheel name"
99 )
100 repack_parser.set_defaults(func=pack_f)
101
102 convert_parser = s.add_parser("convert", help="Convert egg or wininst to wheel")
103 convert_parser.add_argument("files", nargs="*", help="Files to convert")
104 convert_parser.add_argument(
105 "--dest-dir",
106 "-d",
107 default=os.path.curdir,
108 help="Directory to store wheels (default %(default)s)",
109 )
110 convert_parser.add_argument("--verbose", "-v", action="store_true")
111 convert_parser.set_defaults(func=convert_f)
112
113 tags_parser = s.add_parser(
114 "tags", help="Add or replace the tags on a wheel", description=TAGS_HELP
115 )
116 tags_parser.add_argument("wheel", nargs="*", help="Existing wheel(s) to retag")
117 tags_parser.add_argument(
118 "--remove",
119 action="store_true",
120 help="Remove the original files, keeping only the renamed ones",
121 )
122 tags_parser.add_argument(
123 "--python-tag", metavar="TAG", help="Specify an interpreter tag(s)"
124 )
125 tags_parser.add_argument("--abi-tag", metavar="TAG", help="Specify an ABI tag(s)")
126 tags_parser.add_argument(
127 "--platform-tag", metavar="TAG", help="Specify a platform tag(s)"
128 )
129 tags_parser.add_argument(
130 "--build", type=parse_build_tag, metavar="BUILD", help="Specify a build tag"
131 )
132 tags_parser.set_defaults(func=tags_f)
133
134 version_parser = s.add_parser("version", help="Print version and exit")
135 version_parser.set_defaults(func=version_f)
136
137 help_parser = s.add_parser("help", help="Show this help")
138 help_parser.set_defaults(func=lambda args: p.print_help())
139
140 return p
141
142
143def main():
144 p = parser()
145 args = p.parse_args()
146 if not hasattr(args, "func"):
147 p.print_help()
148 else:
149 try:
150 args.func(args)
151 return 0
152 except WheelError as e:
153 print(e, file=sys.stderr)
154
155 return 1