From 0e16bb8f77cb14bc1f608ff4e53f38642028efb5 Mon Sep 17 00:00:00 2001 From: Mo Zaatar Date: Wed, 14 Dec 2022 15:10:50 +0800 Subject: [PATCH 1/7] feature(doctor): initial command output --- README.md | 2 + src/algokit/cli/__init__.py | 2 + src/algokit/cli/doctor.py | 62 +++++++++ src/algokit/core/doctor.py | 127 ++++++++++++++++++ tests/doctor/test_doctor.py | 29 ++++ ...st_doctor.test_doctor_default.approved.txt | 46 +++++++ .../test_doctor.test_doctor_help.approved.txt | 6 + tests/test_root.test_help.approved.txt | 1 + 8 files changed, 275 insertions(+) create mode 100644 src/algokit/cli/doctor.py create mode 100644 src/algokit/core/doctor.py create mode 100644 tests/doctor/test_doctor.py create mode 100644 tests/doctor/test_doctor.test_doctor_default.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_help.approved.txt diff --git a/README.md b/README.md index 5c8240e7..dd3ce182 100644 --- a/README.md +++ b/README.md @@ -75,6 +75,8 @@ Here's how to test it out and maybe even start hacking, assuming you have access 4. Run `pipx install ./dist/algokit--` (ie the .whl file) 5. You can now run `algokit` and should see a help message! 🎉 + 4. Recommended: Run `algokit doctor` to check the system is ready to enjoy development on Algorand! + ### Update To update a previous algokit installation you can simply run `pipx reinstall algokit` and it'll grab the latest from wherever it was installed from. Note: If you installed a specific version e.g. `pipx install git+https://github.com/algorandfoundation/algokit-cli@v.13-beta` then this command won't have any effect since that repository tag will point to the same version. diff --git a/src/algokit/cli/__init__.py b/src/algokit/cli/__init__.py index 194789da..d705ffa4 100644 --- a/src/algokit/cli/__init__.py +++ b/src/algokit/cli/__init__.py @@ -1,5 +1,6 @@ import click from algokit.cli.bootstrap import bootstrap_group +from algokit.cli.doctor import doctor_command from algokit.cli.goal import goal_command from algokit.cli.init import init_command from algokit.cli.sandbox import sandbox_group @@ -22,3 +23,4 @@ def algokit() -> None: algokit.add_command(sandbox_group) algokit.add_command(goal_command) algokit.add_command(bootstrap_group) +algokit.add_command(doctor_command) diff --git a/src/algokit/cli/doctor.py b/src/algokit/cli/doctor.py new file mode 100644 index 00000000..ce96891a --- /dev/null +++ b/src/algokit/cli/doctor.py @@ -0,0 +1,62 @@ +import logging +import platform + +import click +from algokit.core.doctor import DoctorFunctions + +logger = logging.getLogger(__name__) + + +@click.command( + "doctor", + short_help="Run the Algorand doctor CLI.", + context_settings={ + "ignore_unknown_options": True, + }, +) +@click.option( + "--copy-to-clipboard", + "-c", + help="Copy the contents of the doctor message (in Markdown format) in the user's clipboard.", + is_flag=True, + default=False, +) +def doctor_command(copy_to_clipboard: bool) -> None: + os_type = platform.system().lower() + + result_lines = [] + doctor_functions = DoctorFunctions() + result_lines.append(doctor_functions.get_date()) + result_lines.append(doctor_functions.get_algokit_version()) + if os_type == "windows": + result_lines.append(doctor_functions.get_choco_info()) + if os_type == "darwin": + result_lines.append(doctor_functions.get_brew_info()) + result_lines.append(doctor_functions.get_os(os_type)) + result_lines.append(doctor_functions.get_docker_info()) + result_lines.append(doctor_functions.get_docker_compose_info()) + + result_lines.append(doctor_functions.get_git_info(os_type == "windows")) + + result_lines.append(doctor_functions.get_algokit_python_info()) + result_lines.append(doctor_functions.get_global_info()) + result_lines.append(doctor_functions.get_pipx_info()) + result_lines.append(doctor_functions.get_poetry_info()) + + result_lines.append(doctor_functions.get_node_info()) + + result_lines.append(doctor_functions.get_npm_info()) + + result_lines.append( + ( + "If you are experiencing a problem with algokit, feel free to submit an issue " + "via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, " + "if you want to populate this message in your clipboard, run `algokit doctor -c`" + ) + ) + + logger.info("".join(result_lines)) + + if copy_to_clipboard: + logger.info("Contents copied to your clipboard") + # TODO: copy to clipboard diff --git a/src/algokit/core/doctor.py b/src/algokit/core/doctor.py new file mode 100644 index 00000000..f893609c --- /dev/null +++ b/src/algokit/core/doctor.py @@ -0,0 +1,127 @@ +import logging +import platform +from datetime import datetime, timezone + +from algokit.core import proc + +logger = logging.getLogger(__name__) + + +class DoctorFunctions: + def get_date(self) -> str: + return f"Time: {format(datetime.now(timezone.utc).astimezone().isoformat())}\n" + + def get_algokit_version(self) -> str: + algokit_info = self.get_installed_software_version(["pip", "show", "AlgoKit"]) + return f"AlgoKit: {algokit_info['version']} {algokit_info['location']}" + + def get_installed_software_version(self, command: list[str]) -> dict[str, str]: + package_info_lines = proc.run(command).output.splitlines() + results: dict[str, str] = {} + for line in package_info_lines: + line_parts = line.split(":") + results[line_parts[0].lower().strip()] = line_parts[1].strip() + return results + + def get_choco_info(self) -> str: + choco_version = proc.run(["choco"]).output.splitlines()[0].split(" v")[1] + return f"\nChocolatey installed version:{choco_version}" + + def get_brew_info(self) -> str: + brew_version = proc.run(["brew", "-v"]).output.splitlines()[0].split(" ")[1] + return f"\nBrew installed version: {brew_version}" + + def get_os(self, os_type: str) -> str: + os_version = "" + if os_type == "windows": + os_version = platform.win32_ver()[0] + elif os_type == "darwin": + os_version = platform.mac_ver()[0] + else: + os_version = platform.version() + return f"\nOS: {os_type} {os_version}" + + def get_docker_info(self) -> str: + try: + docker_version = proc.run(["docker", "-v"]).output.splitlines()[0].split(" ")[2].split(",")[0] + return f"\nDocker: {docker_version}" + except Exception: + return ( + "\nDocker: None found" + "\nDocker required to `run algokit sandbox` command; install via https://docs.docker.com/get-docker/" + ) + + def get_docker_compose_info(self) -> str: + docker_compose_minimum_version_message = ( + "\nDocker Compose 2.5 required to `run algokit sandbox command`; " + "install via https://docs.docker.com/compose/install/" + ) + try: + docker_version = proc.run(["docker-compose", "-v"]).output.splitlines()[0].split(" v")[2] + message = f"\nDocker Compose: {docker_version}" + if not docker_version.startswith("2.5"): + message += f"{docker_compose_minimum_version_message}" + return message + except Exception: + return f"\nDocker compose: None found{docker_compose_minimum_version_message}" + + def get_git_info(self, is_windows: bool) -> str: + try: + git_version = proc.run(["git", "-v"]).output.splitlines()[0].split(" ")[2] + return f"Git: {git_version}" + except Exception: + if is_windows: + return ( + "\nGit required to `run algokit init`;" + "install via `choco install git` if using Chocolatey or " + "via https://github.com/git-guides/install-git#install-git-on-windows" + ) + else: + return ( + "\nOtherwise: Git required to run algokit init; " + "install via https://github.com/git-guides/install-git" + ) + + def get_algokit_python_info(self) -> str: + return "\n[TODO] AlgoKit Python: (base path: )" + + def get_global_info(self) -> str: + return "\n[TODO] Global Python: | None found" + + def get_pipx_info(self) -> str: + try: + pipx_version = proc.run(["pipx", "--version"]).output.splitlines()[0] + return f"\nPipx: {pipx_version}" + except Exception: + return "\nPipx: None found\nPipx is required to install Poetry; install via https://pypa.github.io/pipx/" + + def get_poetry_info(self) -> str: + try: + poetry_version = ( + proc.run(["poetry", "--version"]).output.splitlines()[-1].split("version ")[1].split(")")[0] + ) + return f"\nPoetry: {poetry_version}" + except Exception: + return ( + "\nPipx: None found\nPoetry is required for some Python-based templates; " + "install via algokit bootstrap within project directory, " + "or via https://python-poetry.org/docs/#installation" + ) + + def get_node_info(self) -> str: + try: + node_version = proc.run(["node", "-v"]).output.splitlines()[0].split("v")[1] + return f"\nNode: {node_version}" + except Exception: + return ( + "\nNode: None found\nNode.js is required for some Node.js-based templates; " + "install via algokit bootstrap within project directory, " + "or via https://nodejs.dev/en/learn/how-to-install-nodejs/" + ) + + def get_npm_info(self) -> str: + try: + npm_version = proc.run(["npm", "-v"]).output + return f"\nNpm: {npm_version}" + except Exception: + return "\nNpm: None found" diff --git a/tests/doctor/test_doctor.py b/tests/doctor/test_doctor.py new file mode 100644 index 00000000..be5dcdb6 --- /dev/null +++ b/tests/doctor/test_doctor.py @@ -0,0 +1,29 @@ +from datetime import datetime, timezone + +import pytest +from pytest_mock import MockerFixture +from utils.approvals import verify +from utils.click_invoker import invoke + +FAKE_NOW = datetime(2020, 3, 11, 14, 0, 0) + + +@pytest.fixture(autouse=True) +def test_time_now(mocker: MockerFixture): + mock_date = mocker.patch("algokit.core.doctor.datetime") + fake_now = datetime(1990, 12, 31, 14, 0, 0, tzinfo=timezone.utc) + mock_date.now.return_value = fake_now + + +def test_doctor_help(mocker: MockerFixture): + result = invoke("doctor -h") + + assert result.exit_code == 0 + verify(result.output) + + +def test_doctor_default(mocker: MockerFixture): + result = invoke("doctor") + + assert result.exit_code == 0 + verify(result.output) diff --git a/tests/doctor/test_doctor.test_doctor_default.approved.txt b/tests/doctor/test_doctor.test_doctor_default.approved.txt new file mode 100644 index 00000000..6629ae8d --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_default.approved.txt @@ -0,0 +1,46 @@ +DEBUG: Running 'pip show AlgoKit' in '{current_working_directory}' +DEBUG: pip: Name: algokit +DEBUG: pip: Version: 0.1.0 +DEBUG: pip: Summary: Algorand development kit command line interface +DEBUG: pip: Home-page: +DEBUG: pip: Author: Algorand Foundation +DEBUG: pip: Author-email: contact@algorand.foundation +DEBUG: pip: License: MIT +DEBUG: pip: Location: {current_working_directory}/.venv/lib/python3.11/site-packages +DEBUG: pip: Requires: click, copier, httpx, questionary +DEBUG: pip: Required-by: +DEBUG: Running 'brew -v' in '{current_working_directory}' +DEBUG: brew: Homebrew 3.6.14 +DEBUG: brew: Homebrew/homebrew-core (git revision d7bde1056b7; last commit 2022-12-07) +DEBUG: brew: Homebrew/homebrew-cask (git revision 6fb50d235a; last commit 2022-12-07) +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.12.2 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: git: git version 2.37.1 (Apple Git-137.1) +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: Configuration file exists at /Users/mzaatar/Library/Application Support/pypoetry, reusing this directory. +DEBUG: poetry: +DEBUG: poetry: Consider moving configuration to /Users/mzaatar/Library/Preferences/pypoetry, as support for the legacy directory will be removed in an upcoming release. +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T22:00:00+08:00 +AlgoKit: 0.1.0 {current_working_directory}/.venv/lib/python3.11/site-packages +Brew installed version: 3.6.14 +OS: darwin 13.0.1 +Docker: 20.10.21 +Docker Compose: 2.12.2 +Docker Compose 2.5 required to `run algokit sandbox command`; install via https://docs.docker.com/compose/install/Git: 2.37.1 +[TODO] AlgoKit Python: (base path: ) +[TODO] Global Python: | None found +Pipx: 1.1.0 +Poetry: 1.2.2 +Node: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_help.approved.txt b/tests/doctor/test_doctor.test_doctor_help.approved.txt new file mode 100644 index 00000000..32d732a9 --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_help.approved.txt @@ -0,0 +1,6 @@ +Usage: algokit doctor [OPTIONS] + +Options: + -c, --copy-to-clipboard Copy the contents of the doctor message (in Markdown + format) in the user's clipboard. + -h, --help Show this message and exit. diff --git a/tests/test_root.test_help.approved.txt b/tests/test_root.test_help.approved.txt index 9ad64f9d..487f3f0f 100644 --- a/tests/test_root.test_help.approved.txt +++ b/tests/test_root.test_help.approved.txt @@ -11,6 +11,7 @@ Options: Commands: bootstrap Bootstrap AlgoKit project dependencies. + doctor Run the Algorand doctor CLI. goal Run the Algorand goal CLI against the AlgoKit Sandbox. init Initializes a new project. sandbox Manage the AlgoKit sandbox. From e7a309024d2fc5704950e1138eb44b0f242f8bdb Mon Sep 17 00:00:00 2001 From: Mo Zaatar Date: Wed, 14 Dec 2022 22:22:00 +0800 Subject: [PATCH 2/7] feat(doctor): address pr comments and add more logic --- README.md | 2 +- poetry.lock | 36 +++++- pyproject.toml | 4 + src/algokit/cli/doctor.py | 68 ++++++----- src/algokit/core/doctor.py | 109 ++++++++++-------- ...st_doctor.test_doctor_default.approved.txt | 13 ++- .../test_doctor.test_doctor_help.approved.txt | 2 +- 7 files changed, 146 insertions(+), 88 deletions(-) diff --git a/README.md b/README.md index dd3ce182..6ddb65b9 100644 --- a/README.md +++ b/README.md @@ -75,7 +75,7 @@ Here's how to test it out and maybe even start hacking, assuming you have access 4. Run `pipx install ./dist/algokit--` (ie the .whl file) 5. You can now run `algokit` and should see a help message! 🎉 - 4. Recommended: Run `algokit doctor` to check the system is ready to enjoy development on Algorand! +> Recommended: Run `algokit doctor` to check the system is ready to enjoy development on Algorand! ### Update diff --git a/poetry.lock b/poetry.lock index 16e80684..74e9542e 100644 --- a/poetry.lock +++ b/poetry.lock @@ -749,6 +749,14 @@ python-versions = ">=3.6" [package.dependencies] pyparsing = ">=2.0.2,<3.0.5 || >3.0.5" +[[package]] +name = "pasteboard" +version = "0.3.3" +description = "Pasteboard - Python interface for reading from NSPasteboard (macOS clipboard)" +category = "main" +optional = false +python-versions = ">=3.6,<4.0" + [[package]] name = "pathspec" version = "0.10.2" @@ -946,6 +954,21 @@ category = "dev" optional = false python-versions = "*" +[[package]] +name = "pyperclip3" +version = "0.4.1" +description = "Cross-platform clipboard utilities supporting both binary and text data." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pasteboard = {version = "0.3.3", markers = "platform_system == \"Darwin\""} +pywin32 = {version = ">=1.0", markers = "platform_system == \"Windows\""} + +[package.extras] +test = ["pytest"] + [[package]] name = "pytest" version = "7.2.0" @@ -1429,7 +1452,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "1.1" python-versions = "^3.10" -content-hash = "8c1e4d9767957b7b2cab2e06e7bfe4c37069214ebae65806b00d9dda569aa4f4" +content-hash = "a7e113b681edf34cad17a770013c75930ce54cac18dbe4cf2260bef395fdd88b" [metadata.files] aiohttp = [ @@ -2201,6 +2224,13 @@ packaging = [ {file = "packaging-21.3-py3-none-any.whl", hash = "sha256:ef103e05f519cdc783ae24ea4e2e0f508a9c99b2d4969652eed6a2e1ea5bd522"}, {file = "packaging-21.3.tar.gz", hash = "sha256:dd47c42927d89ab911e606518907cc2d3a1f38bbd026385970643f9c5b8ecfeb"}, ] +pasteboard = [ + {file = "pasteboard-0.3.3-cp36-cp36m-macosx_10_15_x86_64.whl", hash = "sha256:afd171e200316f6b3d3da381476921ca57cb8f26d2fa418f779454913918dbb9"}, + {file = "pasteboard-0.3.3-cp37-cp37m-macosx_10_15_x86_64.whl", hash = "sha256:f99dd6c7039b755756b2068942c4c2487d6366e5a56eafd6db0ae7aa2a371a0e"}, + {file = "pasteboard-0.3.3-cp38-cp38-macosx_10_15_x86_64.whl", hash = "sha256:19229dfa28f41afb5e731ac81e52bbc4212f67d678c082d3e3621cec0628a773"}, + {file = "pasteboard-0.3.3-cp39-cp39-macosx_10_15_x86_64.whl", hash = "sha256:20a5c53bae8ac8186ecdd621020fb1b072d45a35f9f11a8e4cd5e82d76b485d0"}, + {file = "pasteboard-0.3.3.tar.gz", hash = "sha256:d80275e76ff1eaaa5ca3d0e0fd8aecd5ea1298523dfd51f3774b5aaebdde02cf"}, +] pathspec = [ {file = "pathspec-0.10.2-py3-none-any.whl", hash = "sha256:88c2606f2c1e818b978540f73ecc908e13999c6c3a383daf3705652ae79807a5"}, {file = "pathspec-0.10.2.tar.gz", hash = "sha256:8f6bf73e5758fd365ef5d58ce09ac7c27d2833a8d7da51712eac6e27e35141b0"}, @@ -2298,6 +2328,10 @@ pyparsing = [ pyperclip = [ {file = "pyperclip-1.8.2.tar.gz", hash = "sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"}, ] +pyperclip3 = [ + {file = "pyperclip3-0.4.1-py3-none-any.whl", hash = "sha256:4631290a04858313f410d72cc6f72cbfe732eca4572124b1c1ae98f1eb779451"}, + {file = "pyperclip3-0.4.1.tar.gz", hash = "sha256:3d99793b610431624259190f48d60deb630643472f28e8012d425d8212acd27b"}, +] pytest = [ {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, diff --git a/pyproject.toml b/pyproject.toml index ebbf7100..c25d1d6b 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,6 +12,7 @@ click = "^8.1.3" httpx = "^0.23.1" copier = "^7.0.1" questionary = "^1.10.0" +pyperclip3 = "^0.4.1" [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" @@ -101,3 +102,6 @@ upload_to_repository = false tag_commit = true branch = "main" commit_message = "{version}\n\nskip-checks: true" + +[pyperclip3] +ignore_missing_imports = true diff --git a/src/algokit/cli/doctor.py b/src/algokit/cli/doctor.py index ce96891a..872b3cfa 100644 --- a/src/algokit/cli/doctor.py +++ b/src/algokit/cli/doctor.py @@ -2,9 +2,15 @@ import platform import click +import pyperclip3 from algokit.core.doctor import DoctorFunctions logger = logging.getLogger(__name__) +DOCTOR_END_MESSAGE = ( + "If you are experiencing a problem with algokit, feel free to submit an issue " + "via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, " + "if you want to populate this message in your clipboard, run `algokit doctor -c`" +) @click.command( @@ -17,46 +23,46 @@ @click.option( "--copy-to-clipboard", "-c", - help="Copy the contents of the doctor message (in Markdown format) in the user's clipboard.", + help="Copy the contents of the doctor message (in Markdown format) in your clipboard.", is_flag=True, default=False, ) -def doctor_command(copy_to_clipboard: bool) -> None: +def doctor_command(*, copy_to_clipboard: bool) -> None: os_type = platform.system().lower() - result_lines = [] + service_outputs: dict[str, str] = {} + service_outputs_contents_lines: list[str] = [] doctor_functions = DoctorFunctions() - result_lines.append(doctor_functions.get_date()) - result_lines.append(doctor_functions.get_algokit_version()) + + service_outputs["Time"] = doctor_functions.get_date() + service_outputs["AlgoKit"] = doctor_functions.get_algokit_info() if os_type == "windows": - result_lines.append(doctor_functions.get_choco_info()) + service_outputs["Chocolatey"] = doctor_functions.get_choco_info() if os_type == "darwin": - result_lines.append(doctor_functions.get_brew_info()) - result_lines.append(doctor_functions.get_os(os_type)) - result_lines.append(doctor_functions.get_docker_info()) - result_lines.append(doctor_functions.get_docker_compose_info()) - - result_lines.append(doctor_functions.get_git_info(os_type == "windows")) - - result_lines.append(doctor_functions.get_algokit_python_info()) - result_lines.append(doctor_functions.get_global_info()) - result_lines.append(doctor_functions.get_pipx_info()) - result_lines.append(doctor_functions.get_poetry_info()) + service_outputs["Brew"] = doctor_functions.get_brew_info() + service_outputs["OS"] = doctor_functions.get_os(os_type) + service_outputs["Docker"] = doctor_functions.get_docker_info() + service_outputs["Docker Compose"] = doctor_functions.get_docker_compose_info() + service_outputs["Git"] = doctor_functions.get_git_info(os_type) + service_outputs["AlgoKit Python"] = doctor_functions.get_algokit_python_info() + service_outputs["Global Python"] = doctor_functions.get_global_python_info() + service_outputs["Pipx"] = doctor_functions.get_pipx_info() + service_outputs["Poetry"] = doctor_functions.get_poetry_info() + service_outputs["Node.js"] = doctor_functions.get_node_info() + service_outputs["Npm"] = doctor_functions.get_npm_info() - result_lines.append(doctor_functions.get_node_info()) - - result_lines.append(doctor_functions.get_npm_info()) - - result_lines.append( - ( - "If you are experiencing a problem with algokit, feel free to submit an issue " - "via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, " - "if you want to populate this message in your clipboard, run `algokit doctor -c`" - ) - ) + # Print the status details + if copy_to_clipboard: + for key, value in service_outputs.items(): + logger.info(click.style(f"{key}: ", bold=True) + f"{value}") + service_outputs_contents_lines.append(f"{key}: {value}\n") + service_outputs_contents_lines.append(DOCTOR_END_MESSAGE) + else: + for key, value in service_outputs.items(): + logger.info(click.style(f"{key}: ", bold=True) + f"{value}") - logger.info("".join(result_lines)) + # print end message anyway + logger.info(DOCTOR_END_MESSAGE) if copy_to_clipboard: - logger.info("Contents copied to your clipboard") - # TODO: copy to clipboard + pyperclip3.copy("".join(service_outputs_contents_lines)) diff --git a/src/algokit/core/doctor.py b/src/algokit/core/doctor.py index f893609c..2275e694 100644 --- a/src/algokit/core/doctor.py +++ b/src/algokit/core/doctor.py @@ -6,30 +6,33 @@ logger = logging.getLogger(__name__) +DOCKER_COMPOSE_MINIMUM_VERSION = "2.5" + +docker_compose_minimum_version_message = ( + f"\nDocker Compose {DOCKER_COMPOSE_MINIMUM_VERSION} required to `run algokit sandbox command`; " + "install via https://docs.docker.com/compose/install/" +) + class DoctorFunctions: def get_date(self) -> str: - return f"Time: {format(datetime.now(timezone.utc).astimezone().isoformat())}\n" + return format(datetime.now(timezone.utc).astimezone().isoformat()) - def get_algokit_version(self) -> str: + def get_algokit_info(self) -> str: algokit_info = self.get_installed_software_version(["pip", "show", "AlgoKit"]) - return f"AlgoKit: {algokit_info['version']} {algokit_info['location']}" - - def get_installed_software_version(self, command: list[str]) -> dict[str, str]: - package_info_lines = proc.run(command).output.splitlines() - results: dict[str, str] = {} - for line in package_info_lines: - line_parts = line.split(":") - results[line_parts[0].lower().strip()] = line_parts[1].strip() - return results + return f"{algokit_info['version']} {algokit_info['location']}" def get_choco_info(self) -> str: - choco_version = proc.run(["choco"]).output.splitlines()[0].split(" v")[1] - return f"\nChocolatey installed version:{choco_version}" + try: + return proc.run(["choco"]).output.splitlines()[0].split(" v")[1] + except Exception: + return "None found" def get_brew_info(self) -> str: - brew_version = proc.run(["brew", "-v"]).output.splitlines()[0].split(" ")[1] - return f"\nBrew installed version: {brew_version}" + try: + return proc.run(["brew", "-v"]).output.splitlines()[0].split(" ")[1] + except Exception: + return "None found" def get_os(self, os_type: str) -> str: os_version = "" @@ -39,71 +42,66 @@ def get_os(self, os_type: str) -> str: os_version = platform.mac_ver()[0] else: os_version = platform.version() - return f"\nOS: {os_type} {os_version}" + return f"{os_type} {os_version}" def get_docker_info(self) -> str: try: docker_version = proc.run(["docker", "-v"]).output.splitlines()[0].split(" ")[2].split(",")[0] - return f"\nDocker: {docker_version}" + return docker_version except Exception: return ( - "\nDocker: None found" - "\nDocker required to `run algokit sandbox` command; install via https://docs.docker.com/get-docker/" + "None found.\nDocker required to `run algokit sandbox` command;" + " install via https://docs.docker.com/get-docker/" ) def get_docker_compose_info(self) -> str: - docker_compose_minimum_version_message = ( - "\nDocker Compose 2.5 required to `run algokit sandbox command`; " - "install via https://docs.docker.com/compose/install/" - ) try: - docker_version = proc.run(["docker-compose", "-v"]).output.splitlines()[0].split(" v")[2] - message = f"\nDocker Compose: {docker_version}" - if not docker_version.startswith("2.5"): - message += f"{docker_compose_minimum_version_message}" - return message + docker_compose_version = proc.run(["docker-compose", "-v"]).output.splitlines()[0].split(" v")[2] + return ( + docker_compose_version + if self.is_minimum_version(docker_compose_version, DOCKER_COMPOSE_MINIMUM_VERSION) + else f"{docker_compose_version}.\n{docker_compose_minimum_version_message}" + ) except Exception: - return f"\nDocker compose: None found{docker_compose_minimum_version_message}" + return f"None found. {docker_compose_minimum_version_message}" - def get_git_info(self, is_windows: bool) -> str: + def get_git_info(self, system: str) -> str: try: git_version = proc.run(["git", "-v"]).output.splitlines()[0].split(" ")[2] - return f"Git: {git_version}" + return git_version except Exception: - if is_windows: + if system == "windows": return ( - "\nGit required to `run algokit init`;" + "Git required to `run algokit init`;" "install via `choco install git` if using Chocolatey or " "via https://github.com/git-guides/install-git#install-git-on-windows" ) + else: - return ( - "\nOtherwise: Git required to run algokit init; " - "install via https://github.com/git-guides/install-git" - ) + return "Git required to run algokit init; " "install via https://github.com/git-guides/install-git" def get_algokit_python_info(self) -> str: - return "\n[TODO] AlgoKit Python: (base path: )" + return proc.run(["python", "--version"]).output.splitlines()[0].split(" ")[1] - def get_global_info(self) -> str: - return "\n[TODO] Global Python: | None found" + def get_global_python_info(self) -> str: + return "[TODO] | None found" def get_pipx_info(self) -> str: try: pipx_version = proc.run(["pipx", "--version"]).output.splitlines()[0] - return f"\nPipx: {pipx_version}" + return pipx_version except Exception: - return "\nPipx: None found\nPipx is required to install Poetry; install via https://pypa.github.io/pipx/" + return "None found.\nPipx is required to install Poetry; install via https://pypa.github.io/pipx/" def get_poetry_info(self) -> str: try: poetry_version = ( proc.run(["poetry", "--version"]).output.splitlines()[-1].split("version ")[1].split(")")[0] ) - return f"\nPoetry: {poetry_version}" + return poetry_version except Exception: return ( - "\nPipx: None found\nPoetry is required for some Python-based templates; " + "None found.\nPoetry is required for some Python-based templates; " "install via algokit bootstrap within project directory, " "or via https://python-poetry.org/docs/#installation" ) @@ -111,17 +109,30 @@ def get_poetry_info(self) -> str: def get_node_info(self) -> str: try: node_version = proc.run(["node", "-v"]).output.splitlines()[0].split("v")[1] - return f"\nNode: {node_version}" + return node_version except Exception: return ( - "\nNode: None found\nNode.js is required for some Node.js-based templates; " - "install via algokit bootstrap within project directory, " + "None found.\nNode.js is required for some Node.js-based templates; " + "install via `algokit bootstrap` within project directory, " "or via https://nodejs.dev/en/learn/how-to-install-nodejs/" ) def get_npm_info(self) -> str: try: npm_version = proc.run(["npm", "-v"]).output - return f"\nNpm: {npm_version}" + return npm_version except Exception: - return "\nNpm: None found" + return "None found" + + def get_installed_software_version(self, command: list[str]) -> dict[str, str]: + package_info_lines = proc.run(command).output.splitlines() + results: dict[str, str] = {} + for line in package_info_lines: + line_parts = line.split(":") + results[line_parts[0].lower().strip()] = line_parts[1].strip() + return results + + def is_minimum_version(self, system_version: str, minimum_version: str) -> bool: + system_version_as_tuple = tuple(map(int, (system_version.split(".")))) + minimum_version_as_tuple = tuple(map(int, (minimum_version.split(".")))) + return system_version_as_tuple >= minimum_version_as_tuple diff --git a/tests/doctor/test_doctor.test_doctor_default.approved.txt b/tests/doctor/test_doctor.test_doctor_default.approved.txt index 6629ae8d..19ee914a 100644 --- a/tests/doctor/test_doctor.test_doctor_default.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_default.approved.txt @@ -19,6 +19,8 @@ DEBUG: Running 'docker-compose -v' in '{current_working_directory}' DEBUG: docker-compose: Docker Compose version v2.12.2 DEBUG: Running 'git -v' in '{current_working_directory}' DEBUG: git: git version 2.37.1 (Apple Git-137.1) +DEBUG: Running 'python --version' in '{current_working_directory}' +DEBUG: python: Python 3.11.0 DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: pipx: 1.1.0 DEBUG: Running 'poetry --version' in '{current_working_directory}' @@ -32,15 +34,16 @@ DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 Time: 1990-12-31T22:00:00+08:00 AlgoKit: 0.1.0 {current_working_directory}/.venv/lib/python3.11/site-packages -Brew installed version: 3.6.14 +Brew: 3.6.14 OS: darwin 13.0.1 Docker: 20.10.21 Docker Compose: 2.12.2 -Docker Compose 2.5 required to `run algokit sandbox command`; install via https://docs.docker.com/compose/install/Git: 2.37.1 -[TODO] AlgoKit Python: (base path: ) -[TODO] Global Python: | None found +Git: 2.37.1 +AlgoKit Python: 3.11.0 +Global Python: [TODO] | None found Pipx: 1.1.0 Poetry: 1.2.2 -Node: 18.12.1 +Node.js: 18.12.1 Npm: 8.19.2 + If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_help.approved.txt b/tests/doctor/test_doctor.test_doctor_help.approved.txt index 32d732a9..cafd5d02 100644 --- a/tests/doctor/test_doctor.test_doctor_help.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_help.approved.txt @@ -2,5 +2,5 @@ Usage: algokit doctor [OPTIONS] Options: -c, --copy-to-clipboard Copy the contents of the doctor message (in Markdown - format) in the user's clipboard. + format) in your clipboard. -h, --help Show this message and exit. From 5c0e67a987dd5e142ac75bb488f431c537bd5098 Mon Sep 17 00:00:00 2001 From: Mo Zaatar Date: Thu, 15 Dec 2022 09:05:55 +0800 Subject: [PATCH 3/7] fix mypy type error --- pyproject.toml | 3 --- src/algokit/cli/doctor.py | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index c25d1d6b..02104326 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -102,6 +102,3 @@ upload_to_repository = false tag_commit = true branch = "main" commit_message = "{version}\n\nskip-checks: true" - -[pyperclip3] -ignore_missing_imports = true diff --git a/src/algokit/cli/doctor.py b/src/algokit/cli/doctor.py index 872b3cfa..b3ffd093 100644 --- a/src/algokit/cli/doctor.py +++ b/src/algokit/cli/doctor.py @@ -2,7 +2,7 @@ import platform import click -import pyperclip3 +import pyperclip3 # type: ignore from algokit.core.doctor import DoctorFunctions logger = logging.getLogger(__name__) From 6bfb30093e005cb59e92aefe4714ff492ec2582b Mon Sep 17 00:00:00 2001 From: Mo Zaatar Date: Thu, 15 Dec 2022 10:04:05 +0800 Subject: [PATCH 4/7] feat(doctor): colouring output --- src/algokit/cli/doctor.py | 23 +++-- src/algokit/core/doctor.py | 179 ++++++++++++++++++++++--------------- 2 files changed, 126 insertions(+), 76 deletions(-) diff --git a/src/algokit/cli/doctor.py b/src/algokit/cli/doctor.py index b3ffd093..c6b831ac 100644 --- a/src/algokit/cli/doctor.py +++ b/src/algokit/cli/doctor.py @@ -3,7 +3,7 @@ import click import pyperclip3 # type: ignore -from algokit.core.doctor import DoctorFunctions +from algokit.core.doctor import DoctorFunctions, ProcessResult logger = logging.getLogger(__name__) DOCTOR_END_MESSAGE = ( @@ -30,7 +30,7 @@ def doctor_command(*, copy_to_clipboard: bool) -> None: os_type = platform.system().lower() - service_outputs: dict[str, str] = {} + service_outputs: dict[str, ProcessResult] = {} service_outputs_contents_lines: list[str] = [] doctor_functions = DoctorFunctions() @@ -51,15 +51,28 @@ def doctor_command(*, copy_to_clipboard: bool) -> None: service_outputs["Node.js"] = doctor_functions.get_node_info() service_outputs["Npm"] = doctor_functions.get_npm_info() + critical_services = ["Docker", "Docker Compose", "Git"] # Print the status details if copy_to_clipboard: for key, value in service_outputs.items(): - logger.info(click.style(f"{key}: ", bold=True) + f"{value}") - service_outputs_contents_lines.append(f"{key}: {value}\n") + color = "green" + if value.exit_code != 0: + if key in critical_services: + color = "red" + else: + color = "yellow" + logger.info(click.style(f"{key}: ", bold=True) + click.style(f"{value.info}", fg=color)) + service_outputs_contents_lines.append(f"{key}: {value.info}\n") service_outputs_contents_lines.append(DOCTOR_END_MESSAGE) else: for key, value in service_outputs.items(): - logger.info(click.style(f"{key}: ", bold=True) + f"{value}") + color = "green" + if value.exit_code != 0: + if key in critical_services: + color = "red" + else: + color = "yellow" + logger.info(click.style(f"{key}: ", bold=True) + click.style(f"{value.info}", fg=color)) # print end message anyway logger.info(DOCTOR_END_MESSAGE) diff --git a/src/algokit/core/doctor.py b/src/algokit/core/doctor.py index 2275e694..bf38f2c5 100644 --- a/src/algokit/core/doctor.py +++ b/src/algokit/core/doctor.py @@ -1,3 +1,4 @@ +import dataclasses import logging import platform from datetime import datetime, timezone @@ -14,27 +15,42 @@ ) +@dataclasses.dataclass +class ProcessResult: + info: str + exit_code: int + + class DoctorFunctions: - def get_date(self) -> str: - return format(datetime.now(timezone.utc).astimezone().isoformat()) + def get_date(self) -> ProcessResult: + return ProcessResult(format(datetime.now(timezone.utc).astimezone().isoformat()), 0) - def get_algokit_info(self) -> str: - algokit_info = self.get_installed_software_version(["pip", "show", "AlgoKit"]) - return f"{algokit_info['version']} {algokit_info['location']}" + def get_algokit_info(self) -> ProcessResult: + try: + process_results = proc.run(["pip", "show", "AlgoKit"]) + algokit_info: dict[str, str] = {} + for line in process_results.output.splitlines(): + line_parts = line.split(":") + algokit_info[line_parts[0].lower().strip()] = line_parts[1].strip() + return ProcessResult(f"{algokit_info['version']} {algokit_info['location']}", process_results.exit_code) + except Exception: + return ProcessResult("Not found", 1) - def get_choco_info(self) -> str: + def get_choco_info(self) -> ProcessResult: try: - return proc.run(["choco"]).output.splitlines()[0].split(" v")[1] + process_results = proc.run(["choco"]) + return ProcessResult(process_results.output.splitlines()[0].split(" v")[1], process_results.exit_code) except Exception: - return "None found" + return ProcessResult("None found", 1) - def get_brew_info(self) -> str: + def get_brew_info(self) -> ProcessResult: try: - return proc.run(["brew", "-v"]).output.splitlines()[0].split(" ")[1] + process_results = proc.run(["brew", "-v"]) + return ProcessResult(process_results.output.splitlines()[0].split(" ")[1], process_results.exit_code) except Exception: - return "None found" + return ProcessResult("None found", 1) - def get_os(self, os_type: str) -> str: + def get_os(self, os_type: str) -> ProcessResult: os_version = "" if os_type == "windows": os_version = platform.win32_ver()[0] @@ -42,95 +58,116 @@ def get_os(self, os_type: str) -> str: os_version = platform.mac_ver()[0] else: os_version = platform.version() - return f"{os_type} {os_version}" + return ProcessResult(f"{os_type} {os_version}", 0) - def get_docker_info(self) -> str: + def get_docker_info(self) -> ProcessResult: try: - docker_version = proc.run(["docker", "-v"]).output.splitlines()[0].split(" ")[2].split(",")[0] - return docker_version + process_results = proc.run(["docker", "-v"]) + return ProcessResult( + process_results.output.splitlines()[0].split(" ")[2].split(",")[0], process_results.exit_code + ) except Exception: - return ( - "None found.\nDocker required to `run algokit sandbox` command;" - " install via https://docs.docker.com/get-docker/" + return ProcessResult( + ( + "None found.\nDocker required to `run algokit sandbox` command;" + " install via https://docs.docker.com/get-docker/" + ), + 1, ) - def get_docker_compose_info(self) -> str: + def get_docker_compose_info(self) -> ProcessResult: try: - docker_compose_version = proc.run(["docker-compose", "-v"]).output.splitlines()[0].split(" v")[2] - return ( - docker_compose_version - if self.is_minimum_version(docker_compose_version, DOCKER_COMPOSE_MINIMUM_VERSION) - else f"{docker_compose_version}.\n{docker_compose_minimum_version_message}" + process_results = proc.run(["docker-compose", "-v"]) + docker_compose_version = process_results.output.splitlines()[0].split(" v")[2] + minimum_version_met = self.is_minimum_version(docker_compose_version, DOCKER_COMPOSE_MINIMUM_VERSION) + return ProcessResult( + ( + docker_compose_version + if minimum_version_met + else f"{docker_compose_version}.\n{docker_compose_minimum_version_message}" + ), + process_results.exit_code if minimum_version_met else 1, ) except Exception: - return f"None found. {docker_compose_minimum_version_message}" + return ProcessResult(f"None found. {docker_compose_minimum_version_message}", 1) - def get_git_info(self, system: str) -> str: + def get_git_info(self, system: str) -> ProcessResult: try: - git_version = proc.run(["git", "-v"]).output.splitlines()[0].split(" ")[2] - return git_version + process_results = proc.run(["git", "-v"]) + return ProcessResult(process_results.output.splitlines()[0].split(" ")[2], process_results.exit_code) except Exception: if system == "windows": - return ( - "Git required to `run algokit init`;" - "install via `choco install git` if using Chocolatey or " - "via https://github.com/git-guides/install-git#install-git-on-windows" + return ProcessResult( + ( + "Git required to `run algokit init`; install via `choco install git` if using Chocolatey or " + "via https://github.com/git-guides/install-git#install-git-on-windows" + ), + 1, ) - else: - return "Git required to run algokit init; " "install via https://github.com/git-guides/install-git" - - def get_algokit_python_info(self) -> str: - return proc.run(["python", "--version"]).output.splitlines()[0].split(" ")[1] + return ProcessResult( + "Git required to run algokit init; " "install via https://github.com/git-guides/install-git", 1 + ) - def get_global_python_info(self) -> str: - return "[TODO] | None found" + def get_algokit_python_info(self) -> ProcessResult: + try: + process_results = proc.run(["python", "--version"]) + return ProcessResult(process_results.output.splitlines()[0].split(" ")[1], process_results.exit_code) + except Exception: + return ProcessResult("None found.", 1) - def get_pipx_info(self) -> str: + def get_global_python_info(self) -> ProcessResult: try: - pipx_version = proc.run(["pipx", "--version"]).output.splitlines()[0] - return pipx_version + # [TODO] | None found + process_results = proc.run(["python", "--version"]) + return ProcessResult(process_results.output.splitlines()[0].split(" ")[1], process_results.exit_code) except Exception: - return "None found.\nPipx is required to install Poetry; install via https://pypa.github.io/pipx/" + return ProcessResult("None found.", 1) - def get_poetry_info(self) -> str: + def get_pipx_info(self) -> ProcessResult: try: - poetry_version = ( - proc.run(["poetry", "--version"]).output.splitlines()[-1].split("version ")[1].split(")")[0] + process_results = proc.run(["pipx", "--version"]) + return ProcessResult(process_results.output.splitlines()[0], process_results.exit_code) + except Exception: + return ProcessResult( + "None found.\nPipx is required to install Poetry; install via https://pypa.github.io/pipx/", 1 ) - return poetry_version + + def get_poetry_info(self) -> ProcessResult: + try: + process_results = proc.run(["poetry", "--version"]) + poetry_version = process_results.output.splitlines()[-1].split("version ")[1].split(")")[0] + return ProcessResult(poetry_version, process_results.exit_code) except Exception: - return ( - "None found.\nPoetry is required for some Python-based templates; " - "install via algokit bootstrap within project directory, " - "or via https://python-poetry.org/docs/#installation" + return ProcessResult( + ( + "None found.\nPoetry is required for some Python-based templates; " + "install via algokit bootstrap within project directory, " + "or via https://python-poetry.org/docs/#installation" + ), + 1, ) - def get_node_info(self) -> str: + def get_node_info(self) -> ProcessResult: try: - node_version = proc.run(["node", "-v"]).output.splitlines()[0].split("v")[1] - return node_version + process_results = proc.run(["node", "-v"]) + return ProcessResult(process_results.output.splitlines()[0].split("v")[1], process_results.exit_code) except Exception: - return ( - "None found.\nNode.js is required for some Node.js-based templates; " - "install via `algokit bootstrap` within project directory, " - "or via https://nodejs.dev/en/learn/how-to-install-nodejs/" + return ProcessResult( + ( + "None found.\nNode.js is required for some Node.js-based templates; " + "install via `algokit bootstrap` within project directory, " + "or via https://nodejs.dev/en/learn/how-to-install-nodejs/" + ), + 1, ) - def get_npm_info(self) -> str: + def get_npm_info(self) -> ProcessResult: try: - npm_version = proc.run(["npm", "-v"]).output - return npm_version + process_results = proc.run(["npm", "-v"]) + return ProcessResult(process_results.output, process_results.exit_code) except Exception: - return "None found" - - def get_installed_software_version(self, command: list[str]) -> dict[str, str]: - package_info_lines = proc.run(command).output.splitlines() - results: dict[str, str] = {} - for line in package_info_lines: - line_parts = line.split(":") - results[line_parts[0].lower().strip()] = line_parts[1].strip() - return results + return ProcessResult("None found", 1) def is_minimum_version(self, system_version: str, minimum_version: str) -> bool: system_version_as_tuple = tuple(map(int, (system_version.split(".")))) From b0fe39aafe34b74bf8aebba1e9ec5f4e8048923e Mon Sep 17 00:00:00 2001 From: Mo Zaatar Date: Thu, 15 Dec 2022 11:57:10 +0800 Subject: [PATCH 5/7] feat(doctor): refactor --- poetry.lock | 40 ++--- pyproject.toml | 2 +- src/algokit/cli/doctor.py | 40 ++--- src/algokit/core/doctor.py | 309 +++++++++++++++++++----------------- tests/doctor/test_doctor.py | 16 +- 5 files changed, 216 insertions(+), 191 deletions(-) diff --git a/poetry.lock b/poetry.lock index 74e9542e..2208c4ac 100644 --- a/poetry.lock +++ b/poetry.lock @@ -901,6 +901,21 @@ python-versions = ">=3.6.2" [package.dependencies] wcwidth = "*" +[[package]] +name = "pyclip" +version = "0.7.0" +description = "Cross-platform clipboard utilities supporting both binary and text data." +category = "main" +optional = false +python-versions = "*" + +[package.dependencies] +pasteboard = {version = "0.3.3", markers = "platform_system == \"Darwin\""} +pywin32 = {version = ">=1.0", markers = "platform_system == \"Windows\""} + +[package.extras] +test = ["pytest"] + [[package]] name = "pycparser" version = "2.21" @@ -954,21 +969,6 @@ category = "dev" optional = false python-versions = "*" -[[package]] -name = "pyperclip3" -version = "0.4.1" -description = "Cross-platform clipboard utilities supporting both binary and text data." -category = "main" -optional = false -python-versions = "*" - -[package.dependencies] -pasteboard = {version = "0.3.3", markers = "platform_system == \"Darwin\""} -pywin32 = {version = ">=1.0", markers = "platform_system == \"Windows\""} - -[package.extras] -test = ["pytest"] - [[package]] name = "pytest" version = "7.2.0" @@ -1452,7 +1452,7 @@ testing = ["flake8 (<5)", "func-timeout", "jaraco.functools", "jaraco.itertools" [metadata] lock-version = "1.1" python-versions = "^3.10" -content-hash = "a7e113b681edf34cad17a770013c75930ce54cac18dbe4cf2260bef395fdd88b" +content-hash = "ac48cd3e24e5ba742d46a35f0557b1c497da443b24daf95dcbc76f8482cfb2e9" [metadata.files] aiohttp = [ @@ -2275,6 +2275,10 @@ prompt-toolkit = [ {file = "prompt_toolkit-3.0.36-py3-none-any.whl", hash = "sha256:aa64ad242a462c5ff0363a7b9cfe696c20d55d9fc60c11fd8e632d064804d305"}, {file = "prompt_toolkit-3.0.36.tar.gz", hash = "sha256:3e163f254bef5a03b146397d7c1963bd3e2812f0964bb9a24e6ec761fd28db63"}, ] +pyclip = [ + {file = "pyclip-0.7.0-py3-none-any.whl", hash = "sha256:a7b7ea2cfad2dd61e86a529af588d006070d3eb0bd32981afaee5215f4604fec"}, + {file = "pyclip-0.7.0.tar.gz", hash = "sha256:57602047a4ceab709bdcd42f3dde6449a3349b95c16154cfdce27376a2072491"}, +] pycparser = [ {file = "pycparser-2.21-py2.py3-none-any.whl", hash = "sha256:8ee45429555515e1f6b185e78100aea234072576aa43ab53aefcae078162fca9"}, {file = "pycparser-2.21.tar.gz", hash = "sha256:e644fdec12f7872f86c58ff790da456218b10f863970249516d60a5eaca77206"}, @@ -2328,10 +2332,6 @@ pyparsing = [ pyperclip = [ {file = "pyperclip-1.8.2.tar.gz", hash = "sha256:105254a8b04934f0bc84e9c24eb360a591aaf6535c9def5f29d92af107a9bf57"}, ] -pyperclip3 = [ - {file = "pyperclip3-0.4.1-py3-none-any.whl", hash = "sha256:4631290a04858313f410d72cc6f72cbfe732eca4572124b1c1ae98f1eb779451"}, - {file = "pyperclip3-0.4.1.tar.gz", hash = "sha256:3d99793b610431624259190f48d60deb630643472f28e8012d425d8212acd27b"}, -] pytest = [ {file = "pytest-7.2.0-py3-none-any.whl", hash = "sha256:892f933d339f068883b6fd5a459f03d85bfcb355e4981e146d2c7616c21fef71"}, {file = "pytest-7.2.0.tar.gz", hash = "sha256:c4014eb40e10f11f355ad4e3c2fb2c6c6d1919c73f3b5a433de4708202cade59"}, diff --git a/pyproject.toml b/pyproject.toml index 02104326..eea46df3 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -12,7 +12,7 @@ click = "^8.1.3" httpx = "^0.23.1" copier = "^7.0.1" questionary = "^1.10.0" -pyperclip3 = "^0.4.1" +pyclip = "^0.7.0" [tool.poetry.group.dev.dependencies] pytest = "^7.2.0" diff --git a/src/algokit/cli/doctor.py b/src/algokit/cli/doctor.py index c6b831ac..ec6915a8 100644 --- a/src/algokit/cli/doctor.py +++ b/src/algokit/cli/doctor.py @@ -2,8 +2,9 @@ import platform import click -import pyperclip3 # type: ignore -from algokit.core.doctor import DoctorFunctions, ProcessResult +import pyclip # type: ignore +from algokit.core import doctor as doctor_functions +from algokit.core.doctor import ProcessResult logger = logging.getLogger(__name__) DOCTOR_END_MESSAGE = ( @@ -28,11 +29,9 @@ default=False, ) def doctor_command(*, copy_to_clipboard: bool) -> None: + return_code = 0 os_type = platform.system().lower() - service_outputs: dict[str, ProcessResult] = {} - service_outputs_contents_lines: list[str] = [] - doctor_functions = DoctorFunctions() service_outputs["Time"] = doctor_functions.get_date() service_outputs["AlgoKit"] = doctor_functions.get_algokit_info() @@ -53,29 +52,18 @@ def doctor_command(*, copy_to_clipboard: bool) -> None: critical_services = ["Docker", "Docker Compose", "Git"] # Print the status details - if copy_to_clipboard: - for key, value in service_outputs.items(): - color = "green" - if value.exit_code != 0: - if key in critical_services: - color = "red" - else: - color = "yellow" - logger.info(click.style(f"{key}: ", bold=True) + click.style(f"{value.info}", fg=color)) - service_outputs_contents_lines.append(f"{key}: {value.info}\n") - service_outputs_contents_lines.append(DOCTOR_END_MESSAGE) - else: - for key, value in service_outputs.items(): - color = "green" - if value.exit_code != 0: - if key in critical_services: - color = "red" - else: - color = "yellow" - logger.info(click.style(f"{key}: ", bold=True) + click.style(f"{value.info}", fg=color)) + for key, value in service_outputs.items(): + color = "green" + if value.exit_code != 0: + color = "red" if key in critical_services else "yellow" + return_code = 1 + logger.info(click.style(f"{key}: ", bold=True) + click.style(f"{value.info}", fg=color)) # print end message anyway logger.info(DOCTOR_END_MESSAGE) if copy_to_clipboard: - pyperclip3.copy("".join(service_outputs_contents_lines)) + pyclip.copy("\n".join(f"{key}: {value.info}" for key, value in service_outputs.items())) + + if return_code != 0: + raise click.exceptions.Exit(code=1) diff --git a/src/algokit/core/doctor.py b/src/algokit/core/doctor.py index bf38f2c5..d8cb2589 100644 --- a/src/algokit/core/doctor.py +++ b/src/algokit/core/doctor.py @@ -1,6 +1,8 @@ import dataclasses import logging import platform +import shutil +import sys from datetime import datetime, timezone from algokit.core import proc @@ -9,7 +11,7 @@ DOCKER_COMPOSE_MINIMUM_VERSION = "2.5" -docker_compose_minimum_version_message = ( +DOCKER_COMPOSE_MINIMUM_VERSION_MESSAGE = ( f"\nDocker Compose {DOCKER_COMPOSE_MINIMUM_VERSION} required to `run algokit sandbox command`; " "install via https://docs.docker.com/compose/install/" ) @@ -21,155 +23,176 @@ class ProcessResult: exit_code: int -class DoctorFunctions: - def get_date(self) -> ProcessResult: - return ProcessResult(format(datetime.now(timezone.utc).astimezone().isoformat()), 0) - - def get_algokit_info(self) -> ProcessResult: - try: - process_results = proc.run(["pip", "show", "AlgoKit"]) - algokit_info: dict[str, str] = {} - for line in process_results.output.splitlines(): - line_parts = line.split(":") - algokit_info[line_parts[0].lower().strip()] = line_parts[1].strip() - return ProcessResult(f"{algokit_info['version']} {algokit_info['location']}", process_results.exit_code) - except Exception: - return ProcessResult("Not found", 1) - - def get_choco_info(self) -> ProcessResult: - try: - process_results = proc.run(["choco"]) - return ProcessResult(process_results.output.splitlines()[0].split(" v")[1], process_results.exit_code) - except Exception: - return ProcessResult("None found", 1) - - def get_brew_info(self) -> ProcessResult: - try: - process_results = proc.run(["brew", "-v"]) - return ProcessResult(process_results.output.splitlines()[0].split(" ")[1], process_results.exit_code) - except Exception: - return ProcessResult("None found", 1) - - def get_os(self, os_type: str) -> ProcessResult: - os_version = "" - if os_type == "windows": - os_version = platform.win32_ver()[0] - elif os_type == "darwin": - os_version = platform.mac_ver()[0] - else: - os_version = platform.version() - return ProcessResult(f"{os_type} {os_version}", 0) - - def get_docker_info(self) -> ProcessResult: - try: - process_results = proc.run(["docker", "-v"]) - return ProcessResult( - process_results.output.splitlines()[0].split(" ")[2].split(",")[0], process_results.exit_code - ) - except Exception: +def get_date() -> ProcessResult: + return ProcessResult(format(datetime.now(timezone.utc).astimezone().isoformat()), 0) + + +def get_algokit_info() -> ProcessResult: + try: + pipx_list_process_results = proc.run(["pipx", "list", "--short"]) + algokit_pipx_line = [ + line for line in pipx_list_process_results.output.splitlines() if line.startswith("algokit") + ] + algokit_version = algokit_pipx_line[0].split(" ")[1] + + algokit_location = "" + pipx_env_process_results = proc.run(["pipx", "environment"]) + algokit_pip_line = [ + line for line in pipx_env_process_results.output.splitlines() if line.startswith("PIPX_LOCAL_VENVS") + ] + pipx_venv_location = algokit_pip_line[0].split("=")[1] + algokit_location = f"{pipx_venv_location}/algokit" + return ProcessResult(f"{algokit_version} {algokit_location}", 0) + except Exception: + return ProcessResult("None found", 1) + + +def get_choco_info() -> ProcessResult: + try: + process_results = proc.run(["choco"]) + return ProcessResult(process_results.output.splitlines()[0].split(" v")[1], process_results.exit_code) + except Exception: + return ProcessResult("None found", 1) + + +def get_brew_info() -> ProcessResult: + try: + process_results = proc.run(["brew", "-v"]) + return ProcessResult(process_results.output.splitlines()[0].split(" ")[1], process_results.exit_code) + except Exception: + return ProcessResult("None found", 1) + + +def get_os(os_type: str) -> ProcessResult: + os_version = "" + if os_type == "windows": + os_version = platform.win32_ver()[0] + elif os_type == "darwin": + os_version = platform.mac_ver()[0] + else: + os_version = platform.version() + return ProcessResult(f"{os_type} {os_version}", 0) + + +def get_docker_info() -> ProcessResult: + try: + process_results = proc.run(["docker", "-v"]) + return ProcessResult( + process_results.output.splitlines()[0].split(" ")[2].split(",")[0], process_results.exit_code + ) + except Exception: + return ProcessResult( + ( + "None found.\nDocker required to `run algokit sandbox` command;" + " install via https://docs.docker.com/get-docker/" + ), + 1, + ) + + +def get_docker_compose_info() -> ProcessResult: + try: + process_results = proc.run(["docker-compose", "-v"]) + docker_compose_version = process_results.output.splitlines()[0].split(" v")[2] + minimum_version_met = is_minimum_version(docker_compose_version, DOCKER_COMPOSE_MINIMUM_VERSION) + return ProcessResult( + ( + docker_compose_version + if minimum_version_met + else f"{docker_compose_version}{DOCKER_COMPOSE_MINIMUM_VERSION_MESSAGE}" + ), + process_results.exit_code if minimum_version_met else 1, + ) + except Exception: + return ProcessResult(f"None found. {DOCKER_COMPOSE_MINIMUM_VERSION_MESSAGE}", 1) + + +def get_git_info(system: str) -> ProcessResult: + try: + process_results = proc.run(["git", "-v"]) + return ProcessResult(process_results.output.splitlines()[0].split(" ")[2], process_results.exit_code) + except Exception: + if system == "windows": return ProcessResult( ( - "None found.\nDocker required to `run algokit sandbox` command;" - " install via https://docs.docker.com/get-docker/" + "None found.\nGit required to `run algokit init`; install via `choco install git` " + "if using Chocolatey or via https://github.com/git-guides/install-git#install-git-on-windows" ), 1, ) - - def get_docker_compose_info(self) -> ProcessResult: - try: - process_results = proc.run(["docker-compose", "-v"]) - docker_compose_version = process_results.output.splitlines()[0].split(" v")[2] - minimum_version_met = self.is_minimum_version(docker_compose_version, DOCKER_COMPOSE_MINIMUM_VERSION) - return ProcessResult( - ( - docker_compose_version - if minimum_version_met - else f"{docker_compose_version}.\n{docker_compose_minimum_version_message}" - ), - process_results.exit_code if minimum_version_met else 1, - ) - except Exception: - return ProcessResult(f"None found. {docker_compose_minimum_version_message}", 1) - - def get_git_info(self, system: str) -> ProcessResult: - try: - process_results = proc.run(["git", "-v"]) - return ProcessResult(process_results.output.splitlines()[0].split(" ")[2], process_results.exit_code) - except Exception: - if system == "windows": - return ProcessResult( - ( - "Git required to `run algokit init`; install via `choco install git` if using Chocolatey or " - "via https://github.com/git-guides/install-git#install-git-on-windows" - ), - 1, - ) - else: - return ProcessResult( - "Git required to run algokit init; " "install via https://github.com/git-guides/install-git", 1 - ) - - def get_algokit_python_info(self) -> ProcessResult: - try: - process_results = proc.run(["python", "--version"]) - return ProcessResult(process_results.output.splitlines()[0].split(" ")[1], process_results.exit_code) - except Exception: - return ProcessResult("None found.", 1) - - def get_global_python_info(self) -> ProcessResult: - try: - # [TODO] | None found - process_results = proc.run(["python", "--version"]) - return ProcessResult(process_results.output.splitlines()[0].split(" ")[1], process_results.exit_code) - except Exception: - return ProcessResult("None found.", 1) - - def get_pipx_info(self) -> ProcessResult: - try: - process_results = proc.run(["pipx", "--version"]) - return ProcessResult(process_results.output.splitlines()[0], process_results.exit_code) - except Exception: - return ProcessResult( - "None found.\nPipx is required to install Poetry; install via https://pypa.github.io/pipx/", 1 - ) - - def get_poetry_info(self) -> ProcessResult: - try: - process_results = proc.run(["poetry", "--version"]) - poetry_version = process_results.output.splitlines()[-1].split("version ")[1].split(")")[0] - return ProcessResult(poetry_version, process_results.exit_code) - except Exception: + else: return ProcessResult( - ( - "None found.\nPoetry is required for some Python-based templates; " - "install via algokit bootstrap within project directory, " - "or via https://python-poetry.org/docs/#installation" - ), + "None found.\nGit required to run 1algokit init`; " + "install via https://github.com/git-guides/install-git", 1, ) - def get_node_info(self) -> ProcessResult: - try: - process_results = proc.run(["node", "-v"]) - return ProcessResult(process_results.output.splitlines()[0].split("v")[1], process_results.exit_code) - except Exception: - return ProcessResult( - ( - "None found.\nNode.js is required for some Node.js-based templates; " - "install via `algokit bootstrap` within project directory, " - "or via https://nodejs.dev/en/learn/how-to-install-nodejs/" - ), - 1, - ) - def get_npm_info(self) -> ProcessResult: - try: - process_results = proc.run(["npm", "-v"]) - return ProcessResult(process_results.output, process_results.exit_code) - except Exception: - return ProcessResult("None found", 1) - - def is_minimum_version(self, system_version: str, minimum_version: str) -> bool: - system_version_as_tuple = tuple(map(int, (system_version.split(".")))) - minimum_version_as_tuple = tuple(map(int, (minimum_version.split(".")))) - return system_version_as_tuple >= minimum_version_as_tuple +def get_algokit_python_info() -> ProcessResult: + try: + python_version = sys.version_info + return ProcessResult(f"{python_version.major}.{python_version.minor}.{python_version.micro}", 0) + except Exception: + return ProcessResult("None found.", 1) + + +def get_global_python_info() -> ProcessResult: + try: + global_python3_version = proc.run(["python3", "--version"]).output.splitlines()[0].split(" ")[1] + global_python3_location = shutil.which("python3") + return ProcessResult(f"{global_python3_version} {global_python3_location}", 0) + except Exception: + return ProcessResult("None found.", 1) + + +def get_pipx_info() -> ProcessResult: + try: + process_results = proc.run(["pipx", "--version"]) + return ProcessResult(process_results.output.splitlines()[0], process_results.exit_code) + except Exception: + return ProcessResult( + "None found.\nPipx is required to install Poetry; install via https://pypa.github.io/pipx/", 1 + ) + + +def get_poetry_info() -> ProcessResult: + try: + process_results = proc.run(["poetry", "--version"]) + poetry_version = process_results.output.splitlines()[-1].split("version ")[1].split(")")[0] + return ProcessResult(poetry_version, process_results.exit_code) + except Exception: + return ProcessResult( + ( + "None found.\nPoetry is required for some Python-based templates; install via `algokit bootstrap` " + "within project directory, or via https://python-poetry.org/docs/#installation" + ), + 1, + ) + + +def get_node_info() -> ProcessResult: + try: + process_results = proc.run(["node", "-v"]) + return ProcessResult(process_results.output.splitlines()[0].split("v")[1], process_results.exit_code) + except Exception: + return ProcessResult( + ( + "None found.\nNode.js is required for some Node.js-based templates; install via `algokit bootstrap` " + "within project directory, or via https://nodejs.dev/en/learn/how-to-install-nodejs/" + ), + 1, + ) + + +def get_npm_info() -> ProcessResult: + try: + process_results = proc.run(["npm", "-v"]) + return ProcessResult(process_results.output, process_results.exit_code) + except Exception: + return ProcessResult("None found", 1) + + +def is_minimum_version(system_version: str, minimum_version: str) -> bool: + system_version_as_tuple = tuple(map(int, (system_version.split(".")))) + minimum_version_as_tuple = tuple(map(int, (minimum_version.split(".")))) + return system_version_as_tuple >= minimum_version_as_tuple diff --git a/tests/doctor/test_doctor.py b/tests/doctor/test_doctor.py index be5dcdb6..76a0b549 100644 --- a/tests/doctor/test_doctor.py +++ b/tests/doctor/test_doctor.py @@ -4,6 +4,7 @@ from pytest_mock import MockerFixture from utils.approvals import verify from utils.click_invoker import invoke +from utils.proc_mock import ProcMock FAKE_NOW = datetime(2020, 3, 11, 14, 0, 0) @@ -22,7 +23,20 @@ def test_doctor_help(mocker: MockerFixture): verify(result.output) -def test_doctor_default(mocker: MockerFixture): +def test_doctor_successful(proc_mock: ProcMock, mocker: MockerFixture): + proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) + proc_mock.set_output(["choco"]) + proc_mock.set_output(["brew", "-v"]) + proc_mock.set_output(["docker", "-v"]) + proc_mock.set_output(["docker-compose", "-v"]) + proc_mock.set_output(["git", "-v"], ["AlgoKit Results"]) + proc_mock.set_output(["python", "--version"]) + proc_mock.set_output(["pipx", "--version"]) + proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) + proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) + proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) + proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) + result = invoke("doctor") assert result.exit_code == 0 From 58d57080e53b24f60e6a4315e09e920032fdf0b0 Mon Sep 17 00:00:00 2001 From: Mo Zaatar Date: Thu, 15 Dec 2022 14:56:43 +0800 Subject: [PATCH 6/7] feat(doctor): adding tests --- src/algokit/core/doctor.py | 17 +- tests/doctor/test_doctor.py | 161 +++++++++++++++--- ...test_doctor_all_failed_on_mac.approved.txt | 30 ++++ ...st_doctor.test_doctor_default.approved.txt | 49 ------ ...st_doctor_successful_on_linux.approved.txt | 38 +++++ ...test_doctor_successful_on_mac.approved.txt | 42 +++++ ..._doctor_successful_on_windows.approved.txt | 42 +++++ ..._doctor.test_doctor_with_copy.approved.txt | 42 +++++ ...r_with_docker_compose_warning.approved.txt | 43 +++++ ...octor_with_git_warning_on_mac.approved.txt | 43 +++++ ...r_with_git_warning_on_windows.approved.txt | 42 +++++ 11 files changed, 473 insertions(+), 76 deletions(-) create mode 100644 tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt delete mode 100644 tests/doctor/test_doctor.test_doctor_default.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_with_copy.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt create mode 100644 tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt diff --git a/src/algokit/core/doctor.py b/src/algokit/core/doctor.py index d8cb2589..fa379081 100644 --- a/src/algokit/core/doctor.py +++ b/src/algokit/core/doctor.py @@ -2,8 +2,8 @@ import logging import platform import shutil -import sys from datetime import datetime, timezone +from sys import version_info as sys_version_info from algokit.core import proc @@ -65,13 +65,17 @@ def get_brew_info() -> ProcessResult: def get_os(os_type: str) -> ProcessResult: os_version = "" + os_name = "" if os_type == "windows": + os_name = "Windows" os_version = platform.win32_ver()[0] elif os_type == "darwin": + os_name = "Mac OS X" os_version = platform.mac_ver()[0] else: + os_name = "Unix/Linux" os_version = platform.version() - return ProcessResult(f"{os_type} {os_version}", 0) + return ProcessResult(f"{os_name} {os_version}", 0) def get_docker_info() -> ProcessResult: @@ -122,7 +126,7 @@ def get_git_info(system: str) -> ProcessResult: ) else: return ProcessResult( - "None found.\nGit required to run 1algokit init`; " + "None found.\nGit required to run `algokit init`; " "install via https://github.com/git-guides/install-git", 1, ) @@ -130,8 +134,7 @@ def get_git_info(system: str) -> ProcessResult: def get_algokit_python_info() -> ProcessResult: try: - python_version = sys.version_info - return ProcessResult(f"{python_version.major}.{python_version.minor}.{python_version.micro}", 0) + return ProcessResult(f"{sys_version_info.major}.{sys_version_info.minor}.{sys_version_info.micro}", 0) except Exception: return ProcessResult("None found.", 1) @@ -187,9 +190,9 @@ def get_node_info() -> ProcessResult: def get_npm_info() -> ProcessResult: try: process_results = proc.run(["npm", "-v"]) - return ProcessResult(process_results.output, process_results.exit_code) + return ProcessResult(process_results.output.splitlines()[0], process_results.exit_code) except Exception: - return ProcessResult("None found", 1) + return ProcessResult("None found.", 1) def is_minimum_version(system_version: str, minimum_version: str) -> bool: diff --git a/tests/doctor/test_doctor.py b/tests/doctor/test_doctor.py index 76a0b549..9e36658c 100644 --- a/tests/doctor/test_doctor.py +++ b/tests/doctor/test_doctor.py @@ -1,19 +1,75 @@ +import typing from datetime import datetime, timezone +from pathlib import Path +import click import pytest +from approvaltests.scrubbers.scrubbers import Scrubber from pytest_mock import MockerFixture -from utils.approvals import verify +from utils.approvals import TokenScrubber, combine_scrubbers, verify from utils.click_invoker import invoke from utils.proc_mock import ProcMock -FAKE_NOW = datetime(2020, 3, 11, 14, 0, 0) +PARENT_DIRECTORY = Path(__file__).parent + + +class VersionInfoType(typing.NamedTuple): + major: int + minor: int + micro: int + releaselevel: str + serial: int + + +@pytest.fixture(autouse=True) +def mock_dependencies(mocker: MockerFixture) -> None: + # Mock OS.platform + mocked_os = mocker.patch("algokit.cli.doctor.platform") + mocked_os.system.return_value = "darwin" + # Mock platform + mocked_os = mocker.patch("algokit.core.doctor.platform") + mocked_os.win32_ver.return_value = ("windows_version", "", "", "") + mocked_os.mac_ver.return_value = ("mac_os_version", "", "", "") + mocked_os.version.return_value = "linux_version" + # Mock datetime + mocked_date = mocker.patch("algokit.core.doctor.datetime") + fake_now = datetime(1990, 12, 31, 10, 9, 8, tzinfo=timezone.utc).astimezone() + mocked_date.now.return_value = fake_now + # Mock shutil + mocked_shutil = mocker.patch("algokit.core.doctor.shutil") + mocked_shutil.which.return_value = "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3" + # Mock sys - Tuple[int, int, int, str, int] + mocker.patch("algokit.core.doctor.sys_version_info", VersionInfoType(3, 6, 2, "blah", 0)) @pytest.fixture(autouse=True) -def test_time_now(mocker: MockerFixture): - mock_date = mocker.patch("algokit.core.doctor.datetime") - fake_now = datetime(1990, 12, 31, 14, 0, 0, tzinfo=timezone.utc) - mock_date.now.return_value = fake_now +def mock_happy_values(proc_mock: ProcMock) -> None: + proc_mock.set_output(["pipx", "list", "--short"], ["aaa 2.3.4", "algokit 1.2.3", "copier 7.0.1\n"]) + proc_mock.set_output( + ["pipx", "environment"], + ["PIPX_SHARED_LIBS=/pipx/shared", "PIPX_LOCAL_VENVS=/pipx/venvs"], + ) + proc_mock.set_output(["choco"], ["Chocolatey v0.10.15", "Please run 'choco -?' for help"]) + proc_mock.set_output(["brew", "-v"], ["Homebrew 3.6.15", "Homebrew/homebrew-core (blah)"]) + proc_mock.set_output(["docker", "-v"], ["Docker version 20.10.21, build baeda1f"]) + proc_mock.set_output(["docker-compose", "-v"], ["Docker Compose version v2.12.2"]) + proc_mock.set_output(["git", "-v"], ["git version 2.37.1 (Apple Git-137.1)"]) + proc_mock.set_output(["python3", "--version"], ["Python 3.11.0"]) + proc_mock.set_output(["pipx", "--version"], ["1.1.0"]) + proc_mock.set_output(["poetry", "--version"], ["blah blah", "", "Poetry (version 1.2.2)"]) + proc_mock.set_output(["node", "-v"], ["v18.12.1"]) + proc_mock.set_output(["npm", "-v"], ["8.19.2"]) + + +def make_output_scrubber(**extra_tokens: str) -> Scrubber: + default_tokens = {"test_parent_directory": str(PARENT_DIRECTORY)} + tokens = default_tokens | extra_tokens + return combine_scrubbers( + click.unstyle, + TokenScrubber(tokens=tokens), + TokenScrubber(tokens={"test_parent_directory": str(PARENT_DIRECTORY).replace("\\", "/")}), + lambda t: t.replace("{test_parent_directory}\\", "{test_parent_directory}/"), + ) def test_doctor_help(mocker: MockerFixture): @@ -23,21 +79,86 @@ def test_doctor_help(mocker: MockerFixture): verify(result.output) -def test_doctor_successful(proc_mock: ProcMock, mocker: MockerFixture): - proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) - proc_mock.set_output(["choco"]) - proc_mock.set_output(["brew", "-v"]) - proc_mock.set_output(["docker", "-v"]) - proc_mock.set_output(["docker-compose", "-v"]) - proc_mock.set_output(["git", "-v"], ["AlgoKit Results"]) - proc_mock.set_output(["python", "--version"]) - proc_mock.set_output(["pipx", "--version"]) - proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) - proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) - proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) - proc_mock.set_output(["pip", "show", "AlgoKit"], ["AlgoKit Results"]) +def test_doctor_with_copy(mocker: MockerFixture): + # Mock pyclip + mocked_os = mocker.patch("algokit.cli.doctor.pyclip.copy") + result = invoke("doctor -c") + + assert result.exit_code == 0 + mocked_os.assert_called_once() + verify(result.output, scrubber=make_output_scrubber()) + +def test_doctor_successful_on_mac(): result = invoke("doctor") assert result.exit_code == 0 - verify(result.output) + verify(result.output, scrubber=make_output_scrubber()) + + +def test_doctor_successful_on_windows(mocker: MockerFixture, proc_mock: ProcMock): + mocked_os = mocker.patch("algokit.cli.doctor.platform") + mocked_os.system.return_value = "windows" + result = invoke("doctor") + + assert result.exit_code == 0 + verify(result.output, scrubber=make_output_scrubber()) + + +def test_doctor_successful_on_linux(mocker: MockerFixture, proc_mock: ProcMock): + mocked_os = mocker.patch("algokit.cli.doctor.platform") + mocked_os.system.return_value = "linux" + result = invoke("doctor") + + assert result.exit_code == 0 + verify(result.output, scrubber=make_output_scrubber()) + + +def test_doctor_with_docker_compose_warning(proc_mock: ProcMock): + proc_mock.set_output(["docker-compose", "-v"], ["Docker Compose version v2.1.3"]) + + result = invoke("doctor") + + assert result.exit_code == 1 + verify(result.output, scrubber=make_output_scrubber()) + + +def test_doctor_with_git_warning_on_mac(mocker: MockerFixture, proc_mock: ProcMock): + proc_mock.set_output(["git", "-v"], ["EMPTY"]) + + result = invoke("doctor") + + assert result.exit_code == 1 + verify(result.output, scrubber=make_output_scrubber()) + + +def test_doctor_with_git_warning_on_windows(mocker: MockerFixture, proc_mock: ProcMock): + mocked_os = mocker.patch("algokit.cli.doctor.platform") + mocked_os.system.return_value = "windows" + + proc_mock.set_output(["git", "-v"], []) + + result = invoke("doctor") + + assert result.exit_code == 1 + verify(result.output, scrubber=make_output_scrubber()) + + +def test_doctor_all_failed_on_mac(mocker: MockerFixture, proc_mock: ProcMock): + proc_mock.set_output(["pipx", "list", "--short"], []) + proc_mock.set_output(["pipx", "environment"], []) + proc_mock.set_output(["choco"], []) + proc_mock.set_output(["brew", "-v"], []) + proc_mock.set_output(["docker", "-v"], []) + proc_mock.set_output(["docker-compose", "-v"], []) + proc_mock.set_output(["git", "-v"], []) + proc_mock.set_output(["python3", "--version"], []) + proc_mock.set_output(["pipx", "--version"], []) + proc_mock.set_output(["poetry", "--version"], []) + proc_mock.set_output(["node", "-v"], []) + proc_mock.set_output(["npm", "-v"], []) + + result = invoke("doctor") + + assert result.exit_code == 1 + verify(result.output, scrubber=make_output_scrubber()) diff --git a/tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt b/tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt new file mode 100644 index 00000000..04d68ff5 --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt @@ -0,0 +1,30 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: Running 'brew -v' in '{current_working_directory}' +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: Running 'npm -v' in '{current_working_directory}' +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: None found +Brew: None found +OS: Mac OS X mac_os_version +Docker: None found. +Docker required to `run algokit sandbox` command; install via https://docs.docker.com/get-docker/ +Docker Compose: None found. +Docker Compose 2.5 required to `run algokit sandbox command`; install via https://docs.docker.com/compose/install/ +Git: None found. +Git required to run `algokit init`; install via https://github.com/git-guides/install-git +AlgoKit Python: 3.6.2 +Global Python: None found. +Pipx: None found. +Pipx is required to install Poetry; install via https://pypa.github.io/pipx/ +Poetry: None found. +Poetry is required for some Python-based templates; install via `algokit bootstrap` within project directory, or via https://python-poetry.org/docs/#installation +Node.js: None found. +Node.js is required for some Node.js-based templates; install via `algokit bootstrap` within project directory, or via https://nodejs.dev/en/learn/how-to-install-nodejs/ +Npm: None found. +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_default.approved.txt b/tests/doctor/test_doctor.test_doctor_default.approved.txt deleted file mode 100644 index 19ee914a..00000000 --- a/tests/doctor/test_doctor.test_doctor_default.approved.txt +++ /dev/null @@ -1,49 +0,0 @@ -DEBUG: Running 'pip show AlgoKit' in '{current_working_directory}' -DEBUG: pip: Name: algokit -DEBUG: pip: Version: 0.1.0 -DEBUG: pip: Summary: Algorand development kit command line interface -DEBUG: pip: Home-page: -DEBUG: pip: Author: Algorand Foundation -DEBUG: pip: Author-email: contact@algorand.foundation -DEBUG: pip: License: MIT -DEBUG: pip: Location: {current_working_directory}/.venv/lib/python3.11/site-packages -DEBUG: pip: Requires: click, copier, httpx, questionary -DEBUG: pip: Required-by: -DEBUG: Running 'brew -v' in '{current_working_directory}' -DEBUG: brew: Homebrew 3.6.14 -DEBUG: brew: Homebrew/homebrew-core (git revision d7bde1056b7; last commit 2022-12-07) -DEBUG: brew: Homebrew/homebrew-cask (git revision 6fb50d235a; last commit 2022-12-07) -DEBUG: Running 'docker -v' in '{current_working_directory}' -DEBUG: docker: Docker version 20.10.21, build baeda1f -DEBUG: Running 'docker-compose -v' in '{current_working_directory}' -DEBUG: docker-compose: Docker Compose version v2.12.2 -DEBUG: Running 'git -v' in '{current_working_directory}' -DEBUG: git: git version 2.37.1 (Apple Git-137.1) -DEBUG: Running 'python --version' in '{current_working_directory}' -DEBUG: python: Python 3.11.0 -DEBUG: Running 'pipx --version' in '{current_working_directory}' -DEBUG: pipx: 1.1.0 -DEBUG: Running 'poetry --version' in '{current_working_directory}' -DEBUG: poetry: Configuration file exists at /Users/mzaatar/Library/Application Support/pypoetry, reusing this directory. -DEBUG: poetry: -DEBUG: poetry: Consider moving configuration to /Users/mzaatar/Library/Preferences/pypoetry, as support for the legacy directory will be removed in an upcoming release. -DEBUG: poetry: Poetry (version 1.2.2) -DEBUG: Running 'node -v' in '{current_working_directory}' -DEBUG: node: v18.12.1 -DEBUG: Running 'npm -v' in '{current_working_directory}' -DEBUG: npm: 8.19.2 -Time: 1990-12-31T22:00:00+08:00 -AlgoKit: 0.1.0 {current_working_directory}/.venv/lib/python3.11/site-packages -Brew: 3.6.14 -OS: darwin 13.0.1 -Docker: 20.10.21 -Docker Compose: 2.12.2 -Git: 2.37.1 -AlgoKit Python: 3.11.0 -Global Python: [TODO] | None found -Pipx: 1.1.0 -Poetry: 1.2.2 -Node.js: 18.12.1 -Npm: 8.19.2 - -If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt b/tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt new file mode 100644 index 00000000..0c798c5d --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt @@ -0,0 +1,38 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: pipx: aaa 2.3.4 +DEBUG: pipx: algokit 1.2.3 +DEBUG: pipx: copier 7.0.1 +DEBUG: Running 'pipx environment' in '{current_working_directory}' +DEBUG: pipx: PIPX_SHARED_LIBS=/pipx/shared +DEBUG: pipx: PIPX_LOCAL_VENVS=/pipx/venvs +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.12.2 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: git: git version 2.37.1 (Apple Git-137.1) +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: python3: Python 3.11.0 +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: blah blah +DEBUG: poetry: +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: 1.2.3 /pipx/venvs/algokit +OS: Unix/Linux linux_version +Docker: 20.10.21 +Docker Compose: 2.12.2 +Git: 2.37.1 +AlgoKit Python: 3.6.2 +Global Python: 3.11.0 /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 +Pipx: 1.1.0 +Poetry: 1.2.2 +Node.js: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt b/tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt new file mode 100644 index 00000000..c6a50fe9 --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt @@ -0,0 +1,42 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: pipx: aaa 2.3.4 +DEBUG: pipx: algokit 1.2.3 +DEBUG: pipx: copier 7.0.1 +DEBUG: Running 'pipx environment' in '{current_working_directory}' +DEBUG: pipx: PIPX_SHARED_LIBS=/pipx/shared +DEBUG: pipx: PIPX_LOCAL_VENVS=/pipx/venvs +DEBUG: Running 'brew -v' in '{current_working_directory}' +DEBUG: brew: Homebrew 3.6.15 +DEBUG: brew: Homebrew/homebrew-core (blah) +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.12.2 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: git: git version 2.37.1 (Apple Git-137.1) +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: python3: Python 3.11.0 +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: blah blah +DEBUG: poetry: +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: 1.2.3 /pipx/venvs/algokit +Brew: 3.6.15 +OS: Mac OS X mac_os_version +Docker: 20.10.21 +Docker Compose: 2.12.2 +Git: 2.37.1 +AlgoKit Python: 3.6.2 +Global Python: 3.11.0 /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 +Pipx: 1.1.0 +Poetry: 1.2.2 +Node.js: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt b/tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt new file mode 100644 index 00000000..6ad58ed5 --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt @@ -0,0 +1,42 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: pipx: aaa 2.3.4 +DEBUG: pipx: algokit 1.2.3 +DEBUG: pipx: copier 7.0.1 +DEBUG: Running 'pipx environment' in '{current_working_directory}' +DEBUG: pipx: PIPX_SHARED_LIBS=/pipx/shared +DEBUG: pipx: PIPX_LOCAL_VENVS=/pipx/venvs +DEBUG: Running 'choco' in '{current_working_directory}' +DEBUG: choco: Chocolatey v0.10.15 +DEBUG: choco: Please run 'choco -?' for help +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.12.2 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: git: git version 2.37.1 (Apple Git-137.1) +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: python3: Python 3.11.0 +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: blah blah +DEBUG: poetry: +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: 1.2.3 /pipx/venvs/algokit +Chocolatey: 0.10.15 +OS: Windows windows_version +Docker: 20.10.21 +Docker Compose: 2.12.2 +Git: 2.37.1 +AlgoKit Python: 3.6.2 +Global Python: 3.11.0 /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 +Pipx: 1.1.0 +Poetry: 1.2.2 +Node.js: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt b/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt new file mode 100644 index 00000000..c6a50fe9 --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt @@ -0,0 +1,42 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: pipx: aaa 2.3.4 +DEBUG: pipx: algokit 1.2.3 +DEBUG: pipx: copier 7.0.1 +DEBUG: Running 'pipx environment' in '{current_working_directory}' +DEBUG: pipx: PIPX_SHARED_LIBS=/pipx/shared +DEBUG: pipx: PIPX_LOCAL_VENVS=/pipx/venvs +DEBUG: Running 'brew -v' in '{current_working_directory}' +DEBUG: brew: Homebrew 3.6.15 +DEBUG: brew: Homebrew/homebrew-core (blah) +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.12.2 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: git: git version 2.37.1 (Apple Git-137.1) +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: python3: Python 3.11.0 +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: blah blah +DEBUG: poetry: +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: 1.2.3 /pipx/venvs/algokit +Brew: 3.6.15 +OS: Mac OS X mac_os_version +Docker: 20.10.21 +Docker Compose: 2.12.2 +Git: 2.37.1 +AlgoKit Python: 3.6.2 +Global Python: 3.11.0 /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 +Pipx: 1.1.0 +Poetry: 1.2.2 +Node.js: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt b/tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt new file mode 100644 index 00000000..0383a75a --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt @@ -0,0 +1,43 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: pipx: aaa 2.3.4 +DEBUG: pipx: algokit 1.2.3 +DEBUG: pipx: copier 7.0.1 +DEBUG: Running 'pipx environment' in '{current_working_directory}' +DEBUG: pipx: PIPX_SHARED_LIBS=/pipx/shared +DEBUG: pipx: PIPX_LOCAL_VENVS=/pipx/venvs +DEBUG: Running 'brew -v' in '{current_working_directory}' +DEBUG: brew: Homebrew 3.6.15 +DEBUG: brew: Homebrew/homebrew-core (blah) +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.1.3 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: git: git version 2.37.1 (Apple Git-137.1) +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: python3: Python 3.11.0 +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: blah blah +DEBUG: poetry: +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: 1.2.3 /pipx/venvs/algokit +Brew: 3.6.15 +OS: Mac OS X mac_os_version +Docker: 20.10.21 +Docker Compose: 2.1.3 +Docker Compose 2.5 required to `run algokit sandbox command`; install via https://docs.docker.com/compose/install/ +Git: 2.37.1 +AlgoKit Python: 3.6.2 +Global Python: 3.11.0 /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 +Pipx: 1.1.0 +Poetry: 1.2.2 +Node.js: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt new file mode 100644 index 00000000..742ca498 --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt @@ -0,0 +1,43 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: pipx: aaa 2.3.4 +DEBUG: pipx: algokit 1.2.3 +DEBUG: pipx: copier 7.0.1 +DEBUG: Running 'pipx environment' in '{current_working_directory}' +DEBUG: pipx: PIPX_SHARED_LIBS=/pipx/shared +DEBUG: pipx: PIPX_LOCAL_VENVS=/pipx/venvs +DEBUG: Running 'brew -v' in '{current_working_directory}' +DEBUG: brew: Homebrew 3.6.15 +DEBUG: brew: Homebrew/homebrew-core (blah) +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.12.2 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: git: EMPTY +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: python3: Python 3.11.0 +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: blah blah +DEBUG: poetry: +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: 1.2.3 /pipx/venvs/algokit +Brew: 3.6.15 +OS: Mac OS X mac_os_version +Docker: 20.10.21 +Docker Compose: 2.12.2 +Git: None found. +Git required to run `algokit init`; install via https://github.com/git-guides/install-git +AlgoKit Python: 3.6.2 +Global Python: 3.11.0 /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 +Pipx: 1.1.0 +Poetry: 1.2.2 +Node.js: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` diff --git a/tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt new file mode 100644 index 00000000..464050eb --- /dev/null +++ b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt @@ -0,0 +1,42 @@ +DEBUG: Running 'pipx list --short' in '{current_working_directory}' +DEBUG: pipx: aaa 2.3.4 +DEBUG: pipx: algokit 1.2.3 +DEBUG: pipx: copier 7.0.1 +DEBUG: Running 'pipx environment' in '{current_working_directory}' +DEBUG: pipx: PIPX_SHARED_LIBS=/pipx/shared +DEBUG: pipx: PIPX_LOCAL_VENVS=/pipx/venvs +DEBUG: Running 'choco' in '{current_working_directory}' +DEBUG: choco: Chocolatey v0.10.15 +DEBUG: choco: Please run 'choco -?' for help +DEBUG: Running 'docker -v' in '{current_working_directory}' +DEBUG: docker: Docker version 20.10.21, build baeda1f +DEBUG: Running 'docker-compose -v' in '{current_working_directory}' +DEBUG: docker-compose: Docker Compose version v2.12.2 +DEBUG: Running 'git -v' in '{current_working_directory}' +DEBUG: Running 'python3 --version' in '{current_working_directory}' +DEBUG: python3: Python 3.11.0 +DEBUG: Running 'pipx --version' in '{current_working_directory}' +DEBUG: pipx: 1.1.0 +DEBUG: Running 'poetry --version' in '{current_working_directory}' +DEBUG: poetry: blah blah +DEBUG: poetry: +DEBUG: poetry: Poetry (version 1.2.2) +DEBUG: Running 'node -v' in '{current_working_directory}' +DEBUG: node: v18.12.1 +DEBUG: Running 'npm -v' in '{current_working_directory}' +DEBUG: npm: 8.19.2 +Time: 1990-12-31T18:09:08+08:00 +AlgoKit: 1.2.3 /pipx/venvs/algokit +Chocolatey: 0.10.15 +OS: Windows windows_version +Docker: 20.10.21 +Docker Compose: 2.12.2 +Git: None found. +Git required to `run algokit init`; install via `choco install git` if using Chocolatey or via https://github.com/git-guides/install-git#install-git-on-windows +AlgoKit Python: 3.6.2 +Global Python: 3.11.0 /Library/Frameworks/Python.framework/Versions/3.11/bin/python3 +Pipx: 1.1.0 +Poetry: 1.2.2 +Node.js: 18.12.1 +Npm: 8.19.2 +If you are experiencing a problem with algokit, feel free to submit an issue via https://github.com/algorandfoundation/algokit-cli/issues/new; please include this output, if you want to populate this message in your clipboard, run `algokit doctor -c` From d9fe303934f3c093d7548228fce74c83286fa1f2 Mon Sep 17 00:00:00 2001 From: Mo Zaatar Date: Thu, 15 Dec 2022 15:25:30 +0800 Subject: [PATCH 7/7] feat(doctor): fix timezone in tests --- src/algokit/core/doctor.py | 2 +- tests/doctor/test_doctor.py | 5 ++--- .../test_doctor.test_doctor_all_failed_on_mac.approved.txt | 2 +- .../test_doctor.test_doctor_successful_on_linux.approved.txt | 2 +- .../test_doctor.test_doctor_successful_on_mac.approved.txt | 2 +- ...est_doctor.test_doctor_successful_on_windows.approved.txt | 2 +- tests/doctor/test_doctor.test_doctor_with_copy.approved.txt | 2 +- ...ctor.test_doctor_with_docker_compose_warning.approved.txt | 2 +- ...t_doctor.test_doctor_with_git_warning_on_mac.approved.txt | 2 +- ...ctor.test_doctor_with_git_warning_on_windows.approved.txt | 2 +- 10 files changed, 11 insertions(+), 12 deletions(-) diff --git a/src/algokit/core/doctor.py b/src/algokit/core/doctor.py index fa379081..e3f43fc8 100644 --- a/src/algokit/core/doctor.py +++ b/src/algokit/core/doctor.py @@ -24,7 +24,7 @@ class ProcessResult: def get_date() -> ProcessResult: - return ProcessResult(format(datetime.now(timezone.utc).astimezone().isoformat()), 0) + return ProcessResult(format(datetime.now(timezone.utc).isoformat()), 0) def get_algokit_info() -> ProcessResult: diff --git a/tests/doctor/test_doctor.py b/tests/doctor/test_doctor.py index 9e36658c..3a97b83e 100644 --- a/tests/doctor/test_doctor.py +++ b/tests/doctor/test_doctor.py @@ -1,5 +1,5 @@ import typing -from datetime import datetime, timezone +from datetime import datetime from pathlib import Path import click @@ -33,8 +33,7 @@ def mock_dependencies(mocker: MockerFixture) -> None: mocked_os.version.return_value = "linux_version" # Mock datetime mocked_date = mocker.patch("algokit.core.doctor.datetime") - fake_now = datetime(1990, 12, 31, 10, 9, 8, tzinfo=timezone.utc).astimezone() - mocked_date.now.return_value = fake_now + mocked_date.now.return_value = datetime(1990, 12, 31, 10, 9, 8) # Mock shutil mocked_shutil = mocker.patch("algokit.core.doctor.shutil") mocked_shutil.which.return_value = "/Library/Frameworks/Python.framework/Versions/3.11/bin/python3" diff --git a/tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt b/tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt index 04d68ff5..6d822121 100644 --- a/tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_all_failed_on_mac.approved.txt @@ -8,7 +8,7 @@ DEBUG: Running 'pipx --version' in '{current_working_directory}' DEBUG: Running 'poetry --version' in '{current_working_directory}' DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: Running 'npm -v' in '{current_working_directory}' -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: None found Brew: None found OS: Mac OS X mac_os_version diff --git a/tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt b/tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt index 0c798c5d..6e2b8325 100644 --- a/tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_successful_on_linux.approved.txt @@ -23,7 +23,7 @@ DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: 1.2.3 /pipx/venvs/algokit OS: Unix/Linux linux_version Docker: 20.10.21 diff --git a/tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt b/tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt index c6a50fe9..2f0329dd 100644 --- a/tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_successful_on_mac.approved.txt @@ -26,7 +26,7 @@ DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: 1.2.3 /pipx/venvs/algokit Brew: 3.6.15 OS: Mac OS X mac_os_version diff --git a/tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt b/tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt index 6ad58ed5..8d790389 100644 --- a/tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_successful_on_windows.approved.txt @@ -26,7 +26,7 @@ DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: 1.2.3 /pipx/venvs/algokit Chocolatey: 0.10.15 OS: Windows windows_version diff --git a/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt b/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt index c6a50fe9..2f0329dd 100644 --- a/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_copy.approved.txt @@ -26,7 +26,7 @@ DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: 1.2.3 /pipx/venvs/algokit Brew: 3.6.15 OS: Mac OS X mac_os_version diff --git a/tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt b/tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt index 0383a75a..e37e6254 100644 --- a/tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_docker_compose_warning.approved.txt @@ -26,7 +26,7 @@ DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: 1.2.3 /pipx/venvs/algokit Brew: 3.6.15 OS: Mac OS X mac_os_version diff --git a/tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt index 742ca498..3d4aefeb 100644 --- a/tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_mac.approved.txt @@ -26,7 +26,7 @@ DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: 1.2.3 /pipx/venvs/algokit Brew: 3.6.15 OS: Mac OS X mac_os_version diff --git a/tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt index 464050eb..54fdab78 100644 --- a/tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt +++ b/tests/doctor/test_doctor.test_doctor_with_git_warning_on_windows.approved.txt @@ -25,7 +25,7 @@ DEBUG: Running 'node -v' in '{current_working_directory}' DEBUG: node: v18.12.1 DEBUG: Running 'npm -v' in '{current_working_directory}' DEBUG: npm: 8.19.2 -Time: 1990-12-31T18:09:08+08:00 +Time: 1990-12-31T10:09:08 AlgoKit: 1.2.3 /pipx/venvs/algokit Chocolatey: 0.10.15 OS: Windows windows_version