Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

support to install specific tool(s) #60

Merged
merged 4 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.3.0
rev: v4.5.0
hooks:
- id: trailing-whitespace
exclude: \.output
Expand All @@ -12,11 +12,11 @@ repos:
- id: debug-statements
- id: requirements-txt-fixer
- repo: https://github.com/asottile/pyupgrade
rev: v2.37.3
rev: v3.15.0
hooks:
- id: pyupgrade
- repo: https://github.com/pycqa/flake8
rev: '5.0.4'
rev: '7.0.0'
hooks:
- id: flake8
args: [--max-line-length=120]
Expand Down
23 changes: 10 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ clang-tools Introduction
:alt: PyPI - Downloads


Install clang-tools binaries (clang-format, clang-tidy) with pip.
Install clang-tools binaries (clang-format, clang-tidy, clang-query and clang-apply-replacements) with pip.

.. important::
This package only manages binary executables (& corresponding symbolic links) that
Expand All @@ -32,6 +32,7 @@ Features
--------

- Binaries are statically linked for improved portability.
- Binaries can be specified installed for increased flexibility.
- Binaries are checked with SHA512 checksum. This ensures:

1. Downloads are not corrupted.
Expand Down Expand Up @@ -102,6 +103,12 @@ Or install to a specified directory

clang-tools --install 13 --directory .

Or install a specified tool, such as clang-format and clang-query version 14.

.. code-block:: shell

clang-tools --install 14 --tool clang-format clang-query

If the installed directory is in your path, you can run the installed tools.

.. code-block:: shell
Expand All @@ -121,18 +128,8 @@ If the installed directory is in your path, you can run the installed tools.
Supported versions
------------------

clang-format
************
.. csv-table::
:header: "Version", "17", "16", "15", "14", "13", "12", "11", "10", "9", "8", "7"
:stub-columns: 1

Linux,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️
Windows,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️
macOS,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️,✔️

clang-tidy
**********
clang-format, clang-tidy, clang-query, clang-apply-replacements
***************************************************************
.. csv-table::
:header: "Version", "17", "16", "15", "14", "13", "12", "11", "10", "9", "8", "7"
:stub-columns: 1
Expand Down
5 changes: 3 additions & 2 deletions clang_tools/install.py
Original file line number Diff line number Diff line change
Expand Up @@ -249,11 +249,12 @@ def uninstall_clang_tools(version: str, directory: str):


def install_clang_tools(
version: str, directory: str, overwrite: bool, no_progress_bar: bool
version: str, tools: str, directory: str, overwrite: bool, no_progress_bar: bool
) -> None:
"""Wraps functions used to individually install tools.

:param version: The version of the tools to install.
:param tools: The specify tool(s) to install.
:param directory: The installation directory.
:param overwrite: A flag to indicate if the creation of a symlink has
permission to overwrite an existing symlink.
Expand All @@ -265,7 +266,7 @@ def install_clang_tools(
f"{YELLOW}{install_dir}",
f"directory is not in your environment variable PATH.{RESET_COLOR}",
)
for tool_name in ("clang-format", "clang-tidy"):
for tool_name in tools:
native_bin = is_installed(tool_name, version)
if native_bin is None: # (not already installed)
# `install_tool()` guarantees that the binary exists now
Expand Down
24 changes: 16 additions & 8 deletions clang_tools/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,14 @@ def get_parser() -> argparse.ArgumentParser:
metavar="VERSION",
help="Install clang-tools about a specific version.",
)
parser.add_argument(
"-t",
"--tool",
nargs='+',
default=['clang-format', 'clang-tidy'],
metavar="TOOL",
help="Specify which tool(s) to install.",
)
parser.add_argument(
"-d",
"--directory",
Expand Down Expand Up @@ -54,19 +62,19 @@ def main():
"""The main entrypoint to the CLI program."""
parser = get_parser()
args = parser.parse_args()
if not args.install and not args.uninstall:

if args.uninstall:
uninstall_clang_tools(args.uninstall, args.directory)
if args.install:
install_clang_tools(
args.install, args.tool, args.directory, args.overwrite, args.no_progress_bar
)
else:
print(
f"{YELLOW}Nothing to do because `--install` and `--uninstall`",
f"was not specified.{RESET_COLOR}"
)
parser.print_help()
else:
if args.uninstall:
uninstall_clang_tools(args.uninstall, args.directory)
if args.install:
install_clang_tools(
args.install, args.directory, args.overwrite, args.no_progress_bar
)


if __name__ == "__main__":
Expand Down
2 changes: 1 addition & 1 deletion clang_tools/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def download_file(url: str, file_name: str, no_progress_bar: bool) -> Optional[s
return None
assert response.length is not None
length = response.length
buffer = bytes()
buffer = b''
progress_bar = "=" if check_install_os() == "windows" else "█"
while len(buffer) < length:
block_size = int(length / 20)
Expand Down
4 changes: 2 additions & 2 deletions tests/test_install.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@


@pytest.mark.parametrize("version", [str(v) for v in range(7, 17)] + ["12.0.1"])
@pytest.mark.parametrize("tool_name", ["clang-format", "clang-tidy"])
@pytest.mark.parametrize("tool_name", ["clang-format", "clang-tidy", "clang-query", "clang-apply-replacements"])
def test_clang_tools_binary_url(tool_name: str, version: str):
"""Test `clang_tools_binary_url()`"""
url = clang_tools_binary_url(tool_name, version)
Expand Down Expand Up @@ -72,7 +72,7 @@ def test_path_warning(capsys: pytest.CaptureFixture):
2. indicates a failure to download a tool
"""
try:
install_clang_tools("x", ".", False, False)
install_clang_tools("x", "x", ".", False, False)
except OSError as exc:
result = capsys.readouterr()
assert "directory is not in your environment variable PATH" in result.out
Expand Down
13 changes: 10 additions & 3 deletions tests/test_main.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,15 @@ def test_cli_switch(switch_name: str, parser: ArgumentParser):
assert getattr(args, switch_name.replace("-", "_"))


def test_default_args(parser: ArgumentParser):
@pytest.mark.parametrize("name, default_value", [
("install", None),
("uninstall", None),
("overwrite", False),
("no_progress_bar", False),
("directory", ""),
("tool", ['clang-format', 'clang-tidy'])
])
def test_default_args(parser: ArgumentParser, name, default_value):
"""Test the default values of CLI args"""
args = parser.parse_args([])
for name, value in args.__dict__.items():
assert getattr(Args, name) == value
assert getattr(args, name) == default_value