Skip to content

Commit

Permalink
Merge pull request #823 from miurahr/topic/miurahr/drop-old-syntax
Browse files Browse the repository at this point in the history
refactor: remove legacy subcommand syntax
  • Loading branch information
miurahr authored Oct 11, 2024
2 parents d3553b3 + 5a2074b commit 46d334a
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 214 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test-install-qt.yml
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ jobs:
args = ["windows", "desktop", qtver, "win64_mingw"]
else:
args = ["windows", "desktop", qtver, "win64_msvc2019_64"]
elif platform == "macOS-latest":
elif platform.startswith("macOS"):
args = ["mac", "desktop", qtver, "clang_64"]
elif qtver.startswith('6.8'):
args = ["linux", "desktop", qtver, "linux_gcc_64"]
Expand Down
98 changes: 35 additions & 63 deletions aqt/installer.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/env python3
#
# Copyright (C) 2018 Linus Jahn <[email protected]>
# Copyright (C) 2019-2021 Hiroshi Miura <[email protected]>
# Copyright (C) 2019-2024 Hiroshi Miura <[email protected]>
# Copyright (C) 2020, Aurélien Gâteau
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
Expand Down Expand Up @@ -109,7 +109,6 @@ class ListToolArgumentParser(ListArgumentParser):
class CommonInstallArgParser(BaseArgumentParser):
"""Install-*/install common arguments"""

is_legacy: bool
target: str
host: str

Expand Down Expand Up @@ -167,8 +166,7 @@ def __init__(self):
title="subcommands",
description="aqt accepts several subcommands:\n"
"install-* subcommands are commands that install components\n"
"list-* subcommands are commands that show available components\n\n"
"commands {install|tool|src|examples|doc} are deprecated and marked for removal\n",
"list-* subcommands are commands that show available components\n",
help="Please refer to each help message by using '--help' with each subcommand",
)
self._make_all_parsers(subparsers)
Expand Down Expand Up @@ -317,8 +315,6 @@ def run_install_qt(self, args: InstallArgParser):
"""Run install subcommand"""
start_time = time.perf_counter()
self.show_aqt_version()
if args.is_legacy:
self._warn_on_deprecated_command("install", "install-qt")
target: str = args.target
os_name: str = args.host
qt_version_or_spec: str = getattr(args, "qt_version", getattr(args, "qt_version_spec", ""))
Expand Down Expand Up @@ -412,12 +408,7 @@ def to_archives(baseurl: str) -> QtArchives:

def _run_src_doc_examples(self, flavor, args, cmd_name: Optional[str] = None):
self.show_aqt_version()
if args.is_legacy:
if cmd_name is None:
self._warn_on_deprecated_command(old_name=flavor, new_name=f"install-{flavor}")
else:
self._warn_on_deprecated_command(old_name=cmd_name, new_name=f"install-{cmd_name}")
elif getattr(args, "target", None) is not None:
if getattr(args, "target", None) is not None:
self._warn_on_deprecated_parameter("target", args.target)
target = "desktop" # The only valid target for src/doc/examples is "desktop"
os_name = args.host
Expand Down Expand Up @@ -504,11 +495,9 @@ def run_install_tool(self, args: InstallToolArgParser):
"""Run tool subcommand"""
start_time = time.perf_counter()
self.show_aqt_version()
if args.is_legacy:
self._warn_on_deprecated_command("tool", "install-tool")
tool_name = args.tool_name # such as tools_openssl_x64
os_name = args.host # windows, linux and mac
target = "desktop" if args.is_legacy else args.target # desktop, android and ios
target = args.target # desktop, android and ios
output_dir = args.outputdir
if output_dir is None:
base_dir = os.getcwd()
Expand Down Expand Up @@ -656,9 +645,9 @@ def show_aqt_version(self, args=None):
"""Display version information"""
self.logger.info(self._format_aqt_version())

def _set_install_qt_parser(self, install_qt_parser, *, is_legacy: bool):
install_qt_parser.set_defaults(func=self.run_install_qt, is_legacy=is_legacy)
self._set_common_arguments(install_qt_parser, is_legacy=is_legacy)
def _set_install_qt_parser(self, install_qt_parser):
install_qt_parser.set_defaults(func=self.run_install_qt)
self._set_common_arguments(install_qt_parser)
self._set_common_options(install_qt_parser)
install_qt_parser.add_argument(
"arch",
Expand Down Expand Up @@ -696,23 +685,20 @@ def _set_install_qt_parser(self, install_qt_parser, *, is_legacy: bool):
"It has no effect when the desktop installation is not required.",
)

def _set_install_tool_parser(self, install_tool_parser, *, is_legacy: bool):
install_tool_parser.set_defaults(func=self.run_install_tool, is_legacy=is_legacy)
def _set_install_tool_parser(self, install_tool_parser):
install_tool_parser.set_defaults(func=self.run_install_tool)
install_tool_parser.add_argument(
"host", choices=["linux", "linux_arm64", "mac", "windows", "windows_arm64"], help="host os name"
)
if not is_legacy:
install_tool_parser.add_argument(
"target",
default=None,
choices=["desktop", "winrt", "android", "ios"],
help="Target SDK.",
)
install_tool_parser.add_argument(
"target",
default=None,
choices=["desktop", "winrt", "android", "ios"],
help="Target SDK.",
)
install_tool_parser.add_argument("tool_name", help="Name of tool such as tools_ifw, tools_mingw")
if is_legacy:
install_tool_parser.add_argument("version", help="Version of tool variant")

tool_variant_opts = {} if is_legacy else {"nargs": "?", "default": None}
tool_variant_opts = {"nargs": "?", "default": None}
install_tool_parser.add_argument(
"tool_variant",
**tool_variant_opts,
Expand All @@ -735,19 +721,16 @@ def _warn_on_deprecated_parameter(self, parameter_name: str, value: str):
)

def _make_all_parsers(self, subparsers: argparse._SubParsersAction) -> None:
deprecated_msg = "This command is deprecated and marked for removal in a future version of aqt."

def make_parser_it(cmd: str, desc: str, is_legacy: bool, set_parser_cmd, formatter_class):
description = f"{desc} {deprecated_msg}" if is_legacy else desc
def make_parser_it(cmd: str, desc: str, set_parser_cmd, formatter_class):
kwargs = {"formatter_class": formatter_class} if formatter_class else {}
p = subparsers.add_parser(cmd, description=description, **kwargs)
set_parser_cmd(p, is_legacy=is_legacy)

def make_parser_sde(cmd: str, desc: str, is_legacy: bool, action, is_add_kde: bool, is_add_modules: bool = True):
description = f"{desc} {deprecated_msg}" if is_legacy else desc
parser = subparsers.add_parser(cmd, description=description)
parser.set_defaults(func=action, is_legacy=is_legacy)
self._set_common_arguments(parser, is_legacy=is_legacy, is_target_deprecated=True)
p = subparsers.add_parser(cmd, description=desc, **kwargs)
set_parser_cmd(p)

def make_parser_sde(cmd: str, desc: str, action, is_add_kde: bool, is_add_modules: bool = True):
parser = subparsers.add_parser(cmd, description=desc)
parser.set_defaults(func=action)
self._set_common_arguments(parser, is_target_deprecated=True)
self._set_common_options(parser)
if is_add_modules:
self._set_module_options(parser)
Expand All @@ -770,24 +753,18 @@ def make_parser_list_sde(cmd: str, desc: str, cmd_type: str):
if cmd_type != "src":
parser.add_argument("-m", "--modules", action="store_true", help="Print list of available modules")

make_parser_it("install-qt", "Install Qt.", False, self._set_install_qt_parser, argparse.RawTextHelpFormatter)
make_parser_it("install-tool", "Install tools.", False, self._set_install_tool_parser, None)
make_parser_sde("install-doc", "Install documentation.", False, self.run_install_doc, False)
make_parser_sde("install-example", "Install examples.", False, self.run_install_example, False)
make_parser_sde("install-src", "Install source.", False, self.run_install_src, True, is_add_modules=False)
make_parser_it("install-qt", "Install Qt.", self._set_install_qt_parser, argparse.RawTextHelpFormatter)
make_parser_it("install-tool", "Install tools.", self._set_install_tool_parser, None)
make_parser_sde("install-doc", "Install documentation.", self.run_install_doc, False)
make_parser_sde("install-example", "Install examples.", self.run_install_example, False)
make_parser_sde("install-src", "Install source.", self.run_install_src, True, is_add_modules=False)

self._make_list_qt_parser(subparsers)
self._make_list_tool_parser(subparsers)
make_parser_list_sde("list-doc", "List documentation archives available (use with install-doc)", "doc")
make_parser_list_sde("list-example", "List example archives available (use with install-example)", "examples")
make_parser_list_sde("list-src", "List source archives available (use with install-src)", "src")

make_parser_it("install", "Install Qt.", True, self._set_install_qt_parser, argparse.RawTextHelpFormatter)
make_parser_it("tool", "Install tools.", True, self._set_install_tool_parser, None)
make_parser_sde("doc", "Install documentation.", True, self.run_install_doc, False)
make_parser_sde("examples", "Install examples.", True, self.run_install_example, False)
make_parser_sde("src", "Install source.", True, self.run_install_src, True)

self._make_common_parsers(subparsers)

def _make_list_qt_parser(self, subparsers: argparse._SubParsersAction):
Expand Down Expand Up @@ -974,14 +951,10 @@ def _set_archive_options(self, subparser):
"(Default: all archives).",
)

def _set_common_arguments(self, subparser, *, is_legacy: bool, is_target_deprecated: bool = False):
def _set_common_arguments(self, subparser, *, is_target_deprecated: bool = False):
"""
Legacy commands require that the version comes before host and target.
Non-legacy commands require that the host and target are before the version.
install-src/doc/example commands do not require a "target" argument anymore, as of 11/22/2021
"""
if is_legacy:
subparser.add_argument("qt_version", help='Qt version in the format of "5.X.Y"')
subparser.add_argument(
"host", choices=["linux", "linux_arm64", "mac", "windows", "windows_arm64"], help="host os name"
)
Expand All @@ -995,12 +968,11 @@ def _set_common_arguments(self, subparser, *, is_legacy: bool, is_target_depreca
)
else:
subparser.add_argument("target", choices=["desktop", "winrt", "android", "ios"], help="target sdk")
if not is_legacy:
subparser.add_argument(
"qt_version_spec",
metavar="(VERSION | SPECIFICATION)",
help='Qt version in the format of "5.X.Y" or SimpleSpec like "5.X" or "<6.X"',
)
subparser.add_argument(
"qt_version_spec",
metavar="(VERSION | SPECIFICATION)",
help='Qt version in the format of "5.X.Y" or SimpleSpec like "5.X" or "<6.X"',
)

def _setup_settings(self, args=None):
# setup logging
Expand Down
10 changes: 0 additions & 10 deletions docs/cli.rst
Original file line number Diff line number Diff line change
Expand Up @@ -778,16 +778,6 @@ You should use the :ref:`List-Tool command` to display what tools and tool varia
See `common options`_.
Legacy subcommands
------------------
The subcommands ``install``, ``tool``, ``src``, ``doc``, and ``examples`` have
been deprecated in favor of the newer ``install-*`` commands, but they remain
in aqt in case you still need to use them. Documentation for these older
commands is still available at https://aqtinstall.readthedocs.io/en/v1.2.4/
Command examples
================
Expand Down
85 changes: 4 additions & 81 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,7 @@ def expected_help(actual, prefix=None):
expected = (
"usage: aqt [-h] [-c CONFIG]\n"
" {install-qt,install-tool,install-doc,install-example,install-src,"
"list-qt,list-tool,list-doc,list-example,list-src,"
"install,tool,doc,examples,src,help,version}\n"
"list-qt,list-tool,list-doc,list-example,list-src,help,version}\n"
" ...\n"
"\n"
"Another unofficial Qt Installer.\n"
Expand All @@ -32,13 +31,9 @@ def expected_help(actual, prefix=None):
" aqt accepts several subcommands:\n"
" install-* subcommands are commands that install components\n"
" list-* subcommands are commands that show available components\n"
" \n"
" commands {install|tool|src|examples|doc} are deprecated and marked for "
"removal\n"
"\n"
" {install-qt,install-tool,install-doc,install-example,install-src,list-qt,"
"list-tool,list-doc,list-example,list-src,"
"install,tool,doc,examples,src,help,version}\n"
"list-tool,list-doc,list-example,list-src,help,version}\n"
" Please refer to each help message by using '--help' "
"with each subcommand\n",
)
Expand Down Expand Up @@ -110,16 +105,12 @@ def test_cli_invalid_version(capsys, invalid_version):
cli._setup_settings()

matcher = re.compile(
r"^INFO : aqtinstall\(aqt\) v.* on Python 3.*\n"
# r"^INFO : aqtinstall\(aqt\) v.* on Python 3.*\n"
r"(.*\n)*"
r"ERROR :.*Invalid version: '" + invalid_version + r"'! Please use the form '5\.X\.Y'\.\n.*"
)

for cmd in (
("install", invalid_version, "mac", "desktop"),
("doc", invalid_version, "mac", "desktop"),
("list-qt", "mac", "desktop", "--arch", invalid_version),
):
for cmd in (("list-qt", "mac", "desktop", "--arch", invalid_version),):
cli = Cli()
assert cli.run(cmd) == 1
out, err = capsys.readouterr()
Expand Down Expand Up @@ -234,52 +225,6 @@ def test_cli_input_errors(capsys, cmd, expect_msg, should_show_help):
assert err.rstrip().endswith(expect_msg)


# These commands use the new syntax with the legacy commands
@pytest.mark.parametrize(
"cmd",
(
"install linux desktop 5.10.0",
"install linux desktop 5.10.0 gcc_64",
"src linux desktop 5.10.0",
"doc linux desktop 5.10.0",
"example linux desktop 5.10.0",
"tool windows desktop tools_ifw",
),
)
def test_cli_legacy_commands_with_wrong_syntax(cmd):
cli = Cli()
cli._setup_settings()
with pytest.raises(SystemExit) as e:
cli.run(cmd.split())
assert e.type == SystemExit


@pytest.mark.parametrize(
"cmd",
(
"tool windows desktop tools_ifw qt.tools.ifw.31", # New syntax
"tool windows desktop tools_ifw 1.2.3",
),
)
def test_cli_legacy_tool_new_syntax(monkeypatch, capsys, cmd):
# These incorrect commands cannot be filtered out directly by argparse because
# they have the correct number of arguments.
command = cmd.split()

expected = (
"WARNING : The command 'tool' is deprecated and marked for removal in a future version of aqt.\n"
"In the future, please use the command 'install-tool' instead.\n"
"ERROR : Invalid version: 'tools_ifw'! Please use the form '5.X.Y'.\n"
)

cli = Cli()
cli._setup_settings()
assert 1 == cli.run(command)
out, err = capsys.readouterr()
actual = err[err.index("\n") + 1 :]
assert actual == expected


@pytest.mark.parametrize(
"cmd, expect_err",
(
Expand Down Expand Up @@ -308,28 +253,6 @@ def test_cli_list_qt_deprecated_flags(capsys, cmd: str, expect_err: str):
assert err == expect_err


# These commands come directly from examples in the legacy documentation
@pytest.mark.parametrize(
"cmd",
(
"install 5.10.0 linux desktop", # default arch
"install 5.10.2 linux android android_armv7",
"src 5.15.2 windows desktop --archives qtbase --kde",
"doc 5.15.2 windows desktop -m qtcharts qtnetworkauth",
"examples 5.15.2 windows desktop -m qtcharts qtnetworkauth",
"tool linux tools_ifw 4.0 qt.tools.ifw.40",
),
)
def test_cli_legacy_commands_with_correct_syntax(monkeypatch, cmd):
# Pretend to install correctly when any command is run
for func in ("run_install_qt", "run_install_src", "run_install_doc", "run_install_example", "run_install_tool"):
monkeypatch.setattr(Cli, func, lambda *args, **kwargs: 0)

cli = Cli()
cli._setup_settings()
assert 0 == cli.run(cmd.split())


def test_cli_unexpected_error(monkeypatch, capsys):
def _mocked_run(*args):
raise RuntimeError("Some unexpected error")
Expand Down
Loading

0 comments on commit 46d334a

Please sign in to comment.