Skip to content

Commit

Permalink
fix: adjust how we run npx, so it supports all windows versions (#454)
Browse files Browse the repository at this point in the history
* fix: adjust how we run npx, so it supports all windows versions
* chore: make client generator snapshots platform specific
  • Loading branch information
neilcampbell authored Mar 13, 2024
1 parent 0ab21bc commit a997953
Show file tree
Hide file tree
Showing 24 changed files with 95 additions and 32 deletions.
3 changes: 2 additions & 1 deletion src/algokit/cli/doctor.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
DOCKER_COMPOSE_MINIMUM_VERSION,
DOCKER_COMPOSE_VERSION_COMMAND,
)
from algokit.core.utils import is_windows as get_is_windows
from algokit.core.version_prompt import get_latest_github_version

logger = logging.getLogger(__name__)
Expand Down Expand Up @@ -40,7 +41,7 @@ def doctor_command(*, copy_to_clipboard: bool) -> None:
Will search the system for AlgoKit dependencies and show their versions, as well as identifying any
potential issues."""
os_type = platform.system()
is_windows = os_type == "Windows"
is_windows = get_is_windows()
service_outputs = {
"timestamp": DoctorResult(ok=True, output=dt.datetime.now(dt.timezone.utc).replace(microsecond=0).isoformat()),
"AlgoKit": _get_algokit_version_output(),
Expand Down
6 changes: 2 additions & 4 deletions src/algokit/core/bootstrap.py
Original file line number Diff line number Diff line change
@@ -1,14 +1,13 @@
import logging
import os
import platform
from pathlib import Path

import click
from packaging import version

from algokit.core import proc, questionary_extensions
from algokit.core.conf import ALGOKIT_CONFIG, get_algokit_config, get_current_package_version
from algokit.core.utils import find_valid_pipx_command
from algokit.core.utils import find_valid_pipx_command, is_windows

ENV_TEMPLATE_PATTERN = ".env*.template"
MAX_BOOTSTRAP_DEPTH = 2
Expand Down Expand Up @@ -162,8 +161,7 @@ def bootstrap_npm(project_dir: Path) -> None:
logger.info(f"{package_json_path} doesn't exist; nothing to do here, skipping bootstrap of npm")
else:
logger.info("Installing npm dependencies")
is_windows = platform.system() == "Windows"
cmd = ["npm" if not is_windows else "npm.cmd", "install"]
cmd = ["npm" if not is_windows() else "npm.cmd", "install"]
try:
proc.run(
cmd,
Expand Down
4 changes: 2 additions & 2 deletions src/algokit/core/typed_client_generation.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import click

from algokit.core import proc
from algokit.core.utils import is_windows

logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -96,11 +97,10 @@ def __init__(self) -> None:
npx_path = shutil.which("npx")
if not npx_path:
raise click.ClickException("Typescript generator requires Node.js and npx to be installed.")
self._npx_path = npx_path

def generate(self, app_spec: Path, output: Path) -> None:
cmd = [
self._npx_path,
"npx" if not is_windows() else "npx.cmd",
"--yes",
TYPESCRIPT_NPX_PACKAGE,
"generate",
Expand Down
7 changes: 5 additions & 2 deletions src/algokit/core/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -141,10 +141,9 @@ def get_base_python_path() -> str | None:
# this will be the value of `home = <path>` in pyvenv.cfg if it exists
if base_home := getattr(sys, "_home", None):
base_home_path = Path(base_home)
is_windows = platform.system() == "Windows"
for name in ("python", "python3", f"python3.{sys.version_info.minor}"):
candidate_path = base_home_path / name
if is_windows:
if is_windows():
candidate_path = candidate_path.with_suffix(".exe")
if candidate_path.is_file():
return str(candidate_path)
Expand All @@ -158,3 +157,7 @@ def is_binary_mode() -> bool:
return: True if running in a native binary frozen environment, False otherwise.
"""
return getattr(sys, "frozen", False) and hasattr(sys, "_MEIPASS")


def is_windows() -> bool:
return platform.system() == "Windows"
27 changes: 23 additions & 4 deletions tests/generate/test_generate_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,9 @@
import pytest
from _pytest.tmpdir import TempPathFactory
from algokit.core.typed_client_generation import TYPESCRIPT_NPX_PACKAGE, _snake_case
from algokit.core.utils import is_windows
from approvaltests.namer import NamerFactory
from approvaltests.pytest.py_test_namer import PyTestNamer
from pytest_mock import MockerFixture

from tests.utils.approvals import verify
Expand All @@ -20,6 +22,10 @@ def _normalize_output(output: str) -> str:
return output.replace("\\", "/").replace(TYPESCRIPT_NPX_PACKAGE, "{typed_client_package}")


def _get_npx_command() -> str:
return "npx" if not is_windows() else "npx.cmd"


@pytest.fixture()
def cwd(tmp_path_factory: TempPathFactory) -> Path:
return tmp_path_factory.mktemp("cwd")
Expand Down Expand Up @@ -102,6 +108,7 @@ def test_generate_client_python_arc32_filename(arc32_json: Path, options: str, e
assert (arc32_json.parent / expected_output_path).read_text()


@pytest.mark.usefixtures("mock_platform_system")
@pytest.mark.parametrize(
("options", "expected_output_path"),
[
Expand All @@ -116,17 +123,20 @@ def test_generate_client_typescript(
application_json: Path,
options: str,
expected_output_path: Path,
request: pytest.FixtureRequest,
) -> None:
result = invoke(f"generate client {options} {application_json.name}", cwd=application_json.parent)
assert result.exit_code == 0
verify(
_normalize_output(result.output),
namer=PyTestNamer(request),
options=NamerFactory.with_parameters(*options.split()),
)
npx = _get_npx_command()
assert len(proc_mock.called) == 1
assert (
proc_mock.called[0].command
== f"/bin/npx --yes {TYPESCRIPT_NPX_PACKAGE} generate -a {application_json} -o {expected_output_path}".split()
== f"{npx} --yes {TYPESCRIPT_NPX_PACKAGE} generate -a {application_json} -o {expected_output_path}".split()
)


Expand All @@ -138,12 +148,21 @@ def test_npx_missing(application_json: Path, which_mock: WhichMock) -> None:
verify(_normalize_output(result.output))


def test_npx_failed(proc_mock: ProcMock, application_json: Path) -> None:
proc_mock.should_bad_exit_on(f"/bin/npx --yes {TYPESCRIPT_NPX_PACKAGE} generate -a {application_json} -o client.ts")
@pytest.mark.usefixtures("mock_platform_system")
def test_npx_failed(
proc_mock: ProcMock,
application_json: Path,
request: pytest.FixtureRequest,
) -> None:
npx = _get_npx_command()
proc_mock.should_bad_exit_on(f"{npx} --yes {TYPESCRIPT_NPX_PACKAGE} generate -a {application_json} -o client.ts")
result = invoke(f"generate client -o client.ts {application_json.name}", cwd=application_json.parent)

assert result.exit_code == 1
verify(_normalize_output(result.output))
verify(
_normalize_output(result.output),
namer=PyTestNamer(request),
)


def test_generate_client_recursive(cwd: Path, dir_with_app_spec_factory: DirWithAppSpecFactory) -> None:
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to HelloWorldApp.ts
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o HelloWorldApp.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to HelloWorldAppClient.ts
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o HelloWorldAppClient.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.py
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.ts
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to HelloWorldApp.ts
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o HelloWorldApp.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to HelloWorldAppClient.ts
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o HelloWorldAppClient.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.py
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.ts
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to HelloWorldApp.ts
DEBUG: Running 'npx.cmd --yes {typed_client_package} generate -a {current_working_directory}/application.json -o HelloWorldApp.ts' in '{current_working_directory}'
DEBUG: npx.cmd: STDOUT
DEBUG: npx.cmd: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to HelloWorldAppClient.ts
DEBUG: Running 'npx.cmd --yes {typed_client_package} generate -a {current_working_directory}/application.json -o HelloWorldAppClient.ts' in '{current_working_directory}'
DEBUG: npx.cmd: STDOUT
DEBUG: npx.cmd: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.py
DEBUG: Running 'npx.cmd --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.py' in '{current_working_directory}'
DEBUG: npx.cmd: STDOUT
DEBUG: npx.cmd: STDERR
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.ts
DEBUG: Running 'npx.cmd --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}'
DEBUG: npx.cmd: STDOUT
DEBUG: npx.cmd: STDERR
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.ts
DEBUG: Running '/bin/npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}'
DEBUG: /bin/npx: STDOUT
DEBUG: /bin/npx: STDERR
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Error: Client generation failed for {current_working_directory}/application.json.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.ts
DEBUG: Running 'npx --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}'
DEBUG: npx: STDOUT
DEBUG: npx: STDERR
Error: Client generation failed for {current_working_directory}/application.json.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
Generating TypeScript client code for application specified in {current_working_directory}/application.json and writing to client.ts
DEBUG: Running 'npx.cmd --yes {typed_client_package} generate -a {current_working_directory}/application.json -o client.ts' in '{current_working_directory}'
DEBUG: npx.cmd: STDOUT
DEBUG: npx.cmd: STDERR
Error: Client generation failed for {current_working_directory}/application.json.

1 comment on commit a997953

@github-actions
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Coverage

Coverage Report
FileStmtsMissCoverMissing
src/algokit
   __init__.py15753%6–13, 17–24, 32–34
   __main__.py440%1–7
src/algokit/cli
   completions.py108298%83, 98
   deploy.py72790%44, 46, 92–94, 158, 182
   dispenser.py121199%77
   doctor.py49394%143–145
   explore.py501276%34–39, 41–46
   generate.py67396%74–75, 140
   goal.py44198%71
   init.py2752591%384–385, 440, 443–445, 456, 460, 516, 542, 571, 604, 613–615, 618–623, 636, 653, 665–666, 683–686
   localnet.py1191587%74–78, 111, 123, 138–148, 161, 206, 227–228
   task.py34391%25–28
src/algokit/cli/common
   utils.py26292%120, 123
src/algokit/cli/tasks
   analyze.py81199%81
   assets.py821384%65–66, 72, 74–75, 105, 119, 125–126, 132, 134, 136–137
   ipfs.py51884%52, 80, 92, 94–95, 105–107
   mint.py66494%48, 70, 91, 250
   send_transaction.py651085%52–53, 57, 89, 158, 170–174
   sign_transaction.py59886%21, 28–30, 71–72, 109, 123
   transfer.py39392%26, 90, 117
   utils.py994555%26–34, 40–43, 75–76, 100–101, 125–133, 152–162, 209, 258–259, 279–290, 297–299
   vanity_address.py561082%41, 45–48, 112, 114, 121–123
   wallet.py79495%21, 66, 136, 162
src/algokit/core
   bootstrap.py1171191%41, 105–106, 128, 155, 183–188
   conf.py661577%12, 24, 28, 36, 38, 72–74, 92–100
   deploy.py691184%61–64, 73–75, 79, 84, 91–93
   dispenser.py2022687%91, 123–124, 141–149, 191–192, 198–200, 218–219, 259–260, 318, 332–334, 345–346, 356, 369, 384
   doctor.py65789%67–69, 92–94, 134
   generate.py48394%44, 81, 99
   goal.py60395%30–31, 41
   init.py39685%59, 63–68, 76
   log_handlers.py68790%50–51, 63, 112–116, 125
   proc.py45198%98
   sandbox.py2181892%62, 73–75, 96, 142–149, 160, 457, 473, 498, 506
   typed_client_generation.py80594%56–58, 71, 76
   utils.py1073072%44–45, 49–68, 129, 132, 138–151
   version_prompt.py921485%37–38, 68, 87–90, 108, 118–125, 148
src/algokit/core/compile
   python.py31584%19–20, 25, 48–49
src/algokit/core/tasks
   analyze.py93397%105–112, 187
   ipfs.py63789%58–64, 140, 144, 146, 152
   nfd.py491373%25, 31, 34–41, 70–72, 99–101
   vanity_address.py903462%49–50, 54, 59–75, 92–108, 128–131
   wallet.py71593%37, 129, 155–157
src/algokit/core/tasks/mint
   mint.py781087%123–133, 187
   models.py901188%50, 52, 57, 71–74, 85–88
TOTAL368843688% 

Tests Skipped Failures Errors Time
428 0 💤 0 ❌ 0 🔥 27.586s ⏱️

Please sign in to comment.