Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

Improve how trogon is calling the command with arguments #107

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ classifiers = [
python = "^3.9.1"
textual = ">=0.61.0"
click = ">=8.0.0"
oslex = ">=0.1.3"
typer = {version = ">=0.9.0", optional = true}

[tool.poetry.extras]
Expand Down
19 changes: 16 additions & 3 deletions trogon/detect_run_string.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
from __future__ import annotations

import os
import shlex
import sys
from types import ModuleType

import oslex


def get_orig_argv() -> list[str]:
"""Polyfil for orig_argv"""
Expand All @@ -22,7 +23,11 @@ def get_orig_argv() -> list[str]:


def detect_run_string(_main: ModuleType = sys.modules["__main__"]) -> str:
"""This is a slightly modified version of a function from Click."""
"""Determine the command used to run the program, for use in preview text only.

This doesn't try to be too precise.
This is a slightly modified version of a function from Click.
"""
path = sys.argv[0]

# The value of __package__ indicates how Python was called. It may
Expand All @@ -35,7 +40,7 @@ def detect_run_string(_main: ModuleType = sys.modules["__main__"]) -> str:
and os.path.exists(f"{path}.exe")
):
# Executed a file, like "python app.py".
file_path = shlex.quote(os.path.basename(path))
file_path = oslex.quote(os.path.basename(path))
argv = get_orig_argv()
if argv[0] == "python":
prefix = f"{argv[0]} "
Expand All @@ -54,3 +59,11 @@ def detect_run_string(_main: ModuleType = sys.modules["__main__"]) -> str:
py_module = f"{py_module}.{name}"

return f"python -m {py_module.lstrip('.')}"


def exact_run_commands() -> list[str]:
"""Get the calling command to re-execute it as it was called originally."""
num_of_script_args = len(sys.argv) - 1
# sys.orig_argv is nearly perfect, just contain a wrong interpreter in case of a venv
calling_command_args = get_orig_argv()[1:-num_of_script_args]
return [sys.executable, *calling_command_args]
6 changes: 3 additions & 3 deletions trogon/run_command.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
from __future__ import annotations

import itertools
import shlex
from collections import defaultdict
from dataclasses import dataclass, field
from typing import Any, List, Optional

import oslex
from rich.text import Text

from trogon.introspect import (
Expand Down Expand Up @@ -84,7 +84,7 @@ def to_cli_args(self, include_root_command: bool = False) -> list[str]:
Returns:
A list of strings that can be passed to subprocess.run to execute the command.
"""
cli_args = self._to_cli_args()
cli_args = list(str(arg) for arg in self._to_cli_args())
if not include_root_command:
cli_args = cli_args[1:]

Expand Down Expand Up @@ -231,7 +231,7 @@ def to_cli_string(self, include_root_command: bool = False) -> Text:
text_renderables: list[Text] = []
for arg in args:
text_renderables.append(
Text(shlex.quote(str(arg)))
Text(oslex.quote(str(arg)))
if arg != ValueNotSupplied()
else Text("???", style="bold black on red")
)
Expand Down
20 changes: 12 additions & 8 deletions trogon/trogon.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,15 @@
from __future__ import annotations

import os
import shlex
import subprocess
import sys
from importlib import metadata # type: ignore
from pathlib import Path
from typing import Any
from webbrowser import open as open_url

import click
import oslex
from rich.console import Console
from rich.highlighter import ReprHighlighter
from rich.text import Text
Expand All @@ -26,7 +28,7 @@
)
from textual.widgets.tree import TreeNode

from trogon.detect_run_string import detect_run_string
from trogon.detect_run_string import detect_run_string, exact_run_commands
from trogon.introspect import (
introspect_click_app,
CommandSchema,
Expand Down Expand Up @@ -247,14 +249,16 @@ def run(
if self.post_run_command:
console = Console()
if self.post_run_command and self.execute_on_exit:
run_commands = exact_run_commands()
program_path = run_commands[0]
full_commands = [*run_commands, *self.post_run_command]
console.print(
f"Running [b cyan]{self.app_name} {' '.join(shlex.quote(s) for s in self.post_run_command)}[/]"
f"Running [b cyan]{' '.join(oslex.quote(s) for s in full_commands)}[/]"
)

split_app_name = shlex.split(self.app_name)
program_name = shlex.split(self.app_name)[0]
arguments = [*split_app_name, *self.post_run_command]
os.execvp(program_name, arguments)
if sys.platform == "win32":
sys.exit(subprocess.call(full_commands, shell=True))
else:
os.execv(program_path, full_commands)

@on(CommandForm.Changed)
def update_command_to_run(self, event: CommandForm.Changed):
Expand Down