### Install comrun using uv Source: https://github.com/jgroxz/comrun/blob/develop/README.md This command installs the comrun package into your Python project using the uv package manager. Ensure you have uv installed and configured for your project. ```bash uv add comrun ``` -------------------------------- ### Derive a Runner with New Options Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Shows how to create a new CommandRunner instance that inherits settings from a base runner but overrides specific options. This allows for flexible configuration by building upon existing runner setups. ```python base = CommandRunner(check=True, quiet=True) verbose = base.with_options(quiet=False) verbose("echo loud") # (1)! base("echo silent") # (2)! # 1. Inherits base settings, but prints live output because `quiet=False`. # 2. Uses the quiet base runner. ``` -------------------------------- ### Install comrun using Package Managers Source: https://github.com/jgroxz/comrun/blob/develop/docs/index.md Instructions for installing the comrun package using different Python package managers: uv, poetry, and pip. These commands add the comrun library to your project's dependencies. ```bash uv add comrun ``` ```bash poetry add comrun ``` ```bash pip install comrun ``` -------------------------------- ### Async Command Execution with run_async in Python Source: https://context7.com/jgroxz/comrun/llms.txt Demonstrates asynchronous command execution using `CommandRunner.run_async`. This method integrates with `asyncio.to_thread` for non-blocking operations. The example shows running multiple commands concurrently using `asyncio.gather` and handling timeouts with `asyncio.wait_for`. ```python import asyncio from comrun import CommandRunner runner = CommandRunner(quiet=True) async def run_multiple_commands(): # Run commands concurrently results = await asyncio.gather( runner.run_async("sleep 1 && echo 'Task 1 done'"), runner.run_async("sleep 1 && echo 'Task 2 done'"), runner.run_async("sleep 1 && echo 'Task 3 done'"), ) for i, result in enumerate(results, 1): print(f"Task {i}: {result.stdout.stripped}") async def run_with_timeout(): try: result = await asyncio.wait_for( runner.run_async("sleep 10"), timeout=2.0 ) print(f"Completed: {result.exit_code}") except asyncio.TimeoutError: print("Command timed out!") asyncio.run(run_multiple_commands()) asyncio.run(run_with_timeout()) ``` -------------------------------- ### Configure CommandRunner using with_options Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Shows how to create a new `CommandRunner` instance with modified options from an existing runner using the `.with_options()` method. This allows for creating specialized runners without altering the original instance. ```python base_runner = CommandRunner(quiet=True, check=True) loud_runner = base_runner.with_options(quiet=False) ``` -------------------------------- ### Configure CommandRunner Options (Python) Source: https://context7.com/jgroxz/comrun/llms.txt Illustrates various ways to configure CommandRunner, including constructor arguments, deriving new runners with `with_options()`, and per-call overrides. Covers options like working directory, environment variables, output suppression, error checking, and WSL integration. ```Python import os from comrun import CommandRunner, CommandError # Configure via constructor runner = CommandRunner( cwd="/path/to/project", env={**os.environ, "NODE_ENV": "production"}, quiet=False, # Stream output to console (default) check=True, # Raise CommandError on non-zero exit encoding="utf-8" ) # Derive a new runner with modified options quiet_runner = runner.with_options(quiet=True) permissive_runner = runner.with_options(check=False) # Per-call overrides result = runner("pytest -q", quiet=True, check=False) # Windows WSL configuration windows_runner = CommandRunner(wsl=False) # Run native Windows commands windows_runner(["cmd", "/c", "dir"]) ``` -------------------------------- ### Configure CommandRunner via constructor Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Demonstrates initializing a `CommandRunner` with specific options directly in the constructor. This sets default behaviors for the runner instance, such as silencing output or raising exceptions on failures. ```python base_runner = CommandRunner(quiet=True, check=True) ``` -------------------------------- ### Log Command Execution with Start/Finish Hooks (Python) Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_advanced.md Implement 'on_start' and 'on_finish' callbacks to log information before and after a command runs. This is useful for integrating comrun into larger applications and tracking execution status. It requires the 'comrun' library. ```python from comrun import CommandContext, CommandResult, CommandRunner def on_start(ctx: CommandContext): print(f"Running: {ctx.command}") def on_finish(result: CommandResult, ctx: CommandContext): print(f"Done ({result.exit_code})") runner = CommandRunner(on_start=on_start, on_finish=on_finish) runner("ls") ``` -------------------------------- ### Run a command synchronously with CommandRunner Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Demonstrates how to instantiate and use the CommandRunner class to execute a shell command synchronously. The output of the command is printed to standard output. ```python from comrun import CommandRunner runner = CommandRunner() runner.run('echo "The cake is a lie."') ``` -------------------------------- ### Execution Details Source: https://github.com/jgroxz/comrun/blob/develop/docs/reference.md Information regarding command execution nuances like quoting, shell usage, and output handling. ```APIDOC ## Execution Details ### Quoting Prefer using argument lists (e.g., `["git", "status"]`) to avoid shell quoting issues. String commands are split using `shlex.split`. ### Shell Built-ins Comrun executes commands with `shell=False`. On Windows, shell built-ins can be run via `["cmd", "/c", "dir"]` when `wsl=False`. ### WSL Integration When running on Windows and `wsl=True`, commands are prefixed with `wsl `. ### Output Handling Stdout and stderr are streamed via the `on_line` hook (unless `quiet=True`) and also buffered in memory. For very large outputs, it is recommended to process lines within the `on_line` hook to prevent excessive memory consumption. ### Truthiness A `CommandResult` object evaluates to `True` if the command was successful (exit code 0). If `check=True`, a non-zero exit code will raise a `CommandError` instead of returning a falsy `CommandResult`. ``` -------------------------------- ### Add Environment Variables and Working Directory Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Demonstrates how to set environment variables and specify a working directory for commands executed by CommandRunner. This is crucial for applications that rely on specific configurations or file paths. ```python import os from comrun import CommandRunner env = {**os.environ, "APP_ENV": "dev"} runner = CommandRunner(cwd="examples", env=env) runner("python main.py") ``` -------------------------------- ### Access Captured Output with CommandOutput (Python) Source: https://context7.com/jgroxz/comrun/llms.txt Details how to access captured stdout, stderr, and combined output using `CommandOutput` objects. Demonstrates different access patterns like lines, text, stripped text, and nullable values, as well as iterating over lines. ```Python from comrun import CommandRunner runner = CommandRunner(quiet=True) # Suppress live output result = runner("git log --oneline -3") # Access stdout, stderr, or combined output stdout = result.stdout # Only stdout stderr = result.stderr # Only stderr output = result.output # Combined stdout + stderr chronologically # Different access patterns for CommandOutput print(stdout.lines) # ('commit1', 'commit2', 'commit3') print(stdout.text) # "commit1\ncommit2\ncommit3" print(stdout.stripped) # Same as text but without leading/trailing whitespace print(stdout.value) # Same as stripped, but None if empty # Iterate over lines for line in result.stdout.lines: print(f"Line: {line}") # Check if command produced output if result.stdout.value is not None: print("Command produced output!") # CommandOutput converts to string via .text print(result.stdout) # Same as print(result.stdout.text) ``` -------------------------------- ### Running commands with string or argv list Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Explains that commands can be provided to `CommandRunner` either as a single string or as a list of arguments (argv). String commands are internally split using `shlex.split`. ```python runner = CommandRunner() runner.run('git status') runner.run(['git', 'status']) ``` -------------------------------- ### Lifecycle Hooks for Command Execution in Python Source: https://context7.com/jgroxz/comrun/llms.txt Illustrates the use of lifecycle hooks (`on_start`, `on_line`, `on_finish`) with `CommandRunner`. `on_start` executes before the command, `on_line` processes each output line in real-time, and `on_finish` runs after completion. The `on_line` hook is skipped if `quiet=True`. ```python import logging from comrun import CommandRunner, CommandContext, CommandResult, StreamName log = logging.getLogger(__name__) def on_start(ctx: CommandContext): """Called before command execution.""" print(f"[START] Running: {ctx.command}") print(f" Working dir: {ctx.cwd}") print(f" Check mode: {ctx.check}") def on_line(line: str, stream: StreamName, ctx: CommandContext): """Called for each output line. StreamName is 'stdout' or 'stderr'.""" prefix = "ERR" if stream == "stderr" else "OUT" log.info("%s | %s | %s", prefix, ctx.command, line) def on_finish(result: CommandResult, ctx: CommandContext): """Called after command completes.""" status = "SUCCESS" if result.success else f"FAILED ({result.exit_code})" print(f"[FINISH] {ctx.command}: {status}") runner = CommandRunner( on_start=on_start, on_line=on_line, on_finish=on_finish ) runner("echo 'Hello from comrun!'") # [START] Running: echo 'Hello from comrun!' # Working dir: None # Check mode: False # INFO:__main__:OUT | echo 'Hello from comrun!' | Hello from comrun! # [FINISH] echo 'Hello from comrun!': SUCCESS ``` -------------------------------- ### Execute Shell Commands with CommandRunner (Python) Source: https://context7.com/jgroxz/comrun/llms.txt Demonstrates basic usage of the CommandRunner class to execute shell commands, including reusable runner instances, using argv lists, and asynchronous execution. ```Python from comrun import CommandRunner, CommandError # Basic usage - create runner and execute commands runner = CommandRunner() result = runner('echo "Hello, World!"') # Output: Hello, World! # Runner is reusable for multiple commands runner("ls -la") runner("git status") # Using argv list instead of string (avoids shell quoting issues) result = runner(["git", "log", "--oneline", "-5"]) # Async execution async def run_commands(): result = await runner.run_async("npm install") return result ``` -------------------------------- ### Run a command asynchronously with CommandRunner Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Shows how to execute a shell command asynchronously using the `run_async` method of the CommandRunner. This is useful for non-blocking command execution within async applications. ```python async def some_coroutine(): runner = CommandRunner() await runner.run_async('echo "This cake is an async lie."') ``` -------------------------------- ### Override configuration for individual command runs Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Illustrates how to pass specific options directly to the `.run()` or `.run_async()` methods to temporarily override the runner's default configuration for a single command execution. ```python loud_runner = CommandRunner(quiet=False, check=True) loud_runner.run("echo 'Hello, World!'", check=False) ``` -------------------------------- ### CommandRunner Class Source: https://github.com/jgroxz/comrun/blob/develop/docs/reference.md Details about the CommandRunner class, its options, and methods for executing commands. ```APIDOC ## CommandRunner Class ### Description Manages the execution of shell commands with various configuration options. ### Options | Option | Default | Description | | --- | --- | --- | | `cwd` | `None` | Working directory for the subprocess. | | `env` | `None` | Environment overrides. If set, replaces the env; merge with `os.environ` to add keys. | | `quiet` | `False` | Suppress live output (still captured). | | `check` | `False` | Raise `CommandError` on non-zero exit. | | `wsl` | `True` (Windows) | Prefix with `wsl` on Windows; ignored on POSIX. | | `encoding` | `locale.getpreferredencoding(False)` | Decoding for stdout/stderr. | | `on_line` | Rich printer | Hook for each line `(line, stream, ctx)`. Skipped when `quiet=True`. | | `on_start` | `None` | Hook before launch `(ctx)`. | | `on_finish` | `None` | Hook after completion `(result, ctx)`. | ### Methods - `run(command, **options) -> CommandResult`: Executes synchronously. Strings are split with `shlex.split`; lists bypass splitting. Shell is always `False`. - `__call__(...)`: Alias for `run`. - `run_async(command, **options) -> CommandResult`: Runs `run` in a worker thread via `asyncio.to_thread` (same semantics as `run`). ### Hooks and Context - `on_line(line: str, stream: Literal["stdout", "stderr"], ctx: CommandContext)`: Called from reader threads; avoid blocking. - `on_start(ctx: CommandContext)`: Called just before starting the process. - `on_finish(result: CommandResult, ctx: CommandContext)`: Called after the process completes. - `CommandContext` fields: `command`, `cwd`, `env`, `quiet`, `check`, `wsl`, `encoding`. ``` -------------------------------- ### Error Handling with CommandError in Python Source: https://context7.com/jgroxz/comrun/llms.txt Demonstrates how to use `CommandRunner` with `check=True` to raise `CommandError` on non-zero exit codes. It shows how to catch the exception and access command details, exit code, and full command results. Also illustrates handling failures without exceptions using `check=False`. ```python from comrun import CommandRunner, CommandError # Strict mode - raises on non-zero exit runner = CommandRunner(check=True, quiet=True) try: runner("exit 1") except CommandError as err: print(f"Command: {err.command}") # "exit 1" print(f"Exit code: {err.exit_code}") # 1 # Access full result for debugging print(f"Stdout: {err.result.stdout.text}") print(f"Stderr: {err.result.stderr.text}") # Alternative: handle failures without exceptions permissive = CommandRunner(check=False) result = permissive("exit 1") if result.failure: print(f"Command failed with exit code: {result.exit_code}") ``` -------------------------------- ### Using CommandRunner as a callable Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Highlights that `CommandRunner` instances are callable, allowing commands to be executed by directly calling the runner instance, which forwards the call to the `.run()` method. ```python runner = CommandRunner() runner("ls -la") ``` -------------------------------- ### Run external commands with CommandRunner in Python Source: https://github.com/jgroxz/comrun/blob/develop/README.md Demonstrates how to use the CommandRunner class from the comrun library to execute external shell commands. It shows initializing the runner and calling it with a command string. The output of the command is captured and can be further processed. ```python from comrun import CommandRunner runner = CommandRunner() # Run your command – instance is callable result = runner('echo "The cake is a lie."') # (prints "The cake is a lie." to the console) ``` -------------------------------- ### Run on Windows Without WSL Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Configures CommandRunner to execute commands directly on Windows without using the Windows Subsystem for Linux (WSL). This is necessary when running native Windows commands or applications. ```python from comrun import CommandRunner windows_runner = CommandRunner(wsl=False) windows_runner(["cmd", "/c", "dir"]) # (1)! # 1. Executes `dir` in the native **cmd.exe** instead of WSL. # !!! note # comrun uses `shell=False`, so shell built-ins like `dir` must be invoked via `cmd /c ...` (or `powershell -Command ...`). ``` -------------------------------- ### Access captured command output with CommandResult Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Explains how to retrieve captured standard output (stdout), standard error (stderr), and combined output from a `CommandResult` object. It details accessing output as lines, full text, or stripped text. ```python result = runner.run("ls") print(result.stdout) print(result.stderr) print(result.output) for line in result.stdout.lines: print(line) print(result.stdout.text) print(result.stdout.stripped) if result.stdout.value is not None: print("Command produced some output!") ``` -------------------------------- ### Access Command Execution Results with CommandResult (Python) Source: https://context7.com/jgroxz/comrun/llms.txt Explains how to access the results of a command execution using the `CommandResult` object. Shows how to retrieve the exit code, check success/failure status, and use the result object in conditional statements. ```Python from comrun import CommandRunner runner = CommandRunner() result = runner("ls -la") # Check exit status print(result.exit_code) # 0 for success print(result.success) # True when exit_code == 0 print(result.failure) # True when exit_code != 0 # Use result in conditionals (truthy on success) if result: print("Command succeeded!") else: print(f"Command failed with exit code: {result.exit_code}") # String representation includes command and exit info print(result) # "Command 'ls -la' finished with exit status 0." ``` -------------------------------- ### Log Each Line with a Prefix Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Customizes CommandRunner to log each line of command output with a prefix indicating the stream (stdout/stderr) and the command being executed. This enhances visibility into command execution, especially for debugging. ```python import logging from comrun import CommandContext, CommandRunner log = logging.getLogger(__name__) def log_lines(line: str, stream: str, ctx: CommandContext): # log each line with stream name, command info and its output log.info("%s | %s | %s", stream.upper(), ctx.command, line) runner = CommandRunner(on_line=log_lines) runner("git status") ``` -------------------------------- ### Check command exit status with CommandResult Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Illustrates how to access the exit status of a command from the `CommandResult` object. It shows how to check the raw exit code, success status, and failure status. ```python result = runner.run("ls") print(result.exit_code) print(result.success) print(result.failure) ``` -------------------------------- ### Control WSL Usage on Windows with wsl in Python Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Control whether commands are prefixed with `wsl` on Windows using the `wsl` option. Setting `wsl=False` forces the use of the native Windows shell instead of the Windows Subsystem for Linux. This option is ignored on POSIX systems. ```python windows_runner = CommandRunner(wsl=False) ``` -------------------------------- ### Process Command Output Lines with Custom Callback (Python) Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_advanced.md Customize how command output lines are handled by providing an 'on_line' callback. This allows for custom processing, logging, or filtering of stdout and stderr. It requires the 'comrun' library and uses Rich for console output by default. The callback receives the line, stream name (stdout/stderr), and context. Keep the callback non-blocking and thread-safe as it runs on reader threads. ```python from comrun import CommandContext, CommandRunner, StreamName def print_line_with_stream_name( line: str, stream: StreamName, ctx: CommandContext ): print(f"{stream.upper()} | {line}") runner = CommandRunner(on_line=print_line_with_stream_name) runner('echo "For science!"') ``` -------------------------------- ### CommandError Class Source: https://github.com/jgroxz/comrun/blob/develop/docs/reference.md Exception raised when a command fails and `check=True`. ```APIDOC ## CommandError Class ### Description Raised when `check=True` and the command exits with a non-zero status code. ### Attributes - `command` / `cmd`: the command string - `result`: the `CommandResult` object - `exit_code`: the process exit code ``` -------------------------------- ### CommandResult Class Source: https://github.com/jgroxz/comrun/blob/develop/docs/reference.md Represents the outcome of a command execution. ```APIDOC ## CommandResult Class ### Description Holds the results of a command execution, including exit code, output, and success status. ### Fields | Field | Type | Notes | | --- | --- | --- | | `command` | `str` | Command string that was executed. | | `exit_code` | `int` | Raw process exit code. | | `success` | `bool` | `True` when `exit_code == 0`. | | `failure` | `bool` | `True` when `exit_code != 0`. | | `stdout` | `CommandOutput` | Captured stdout. | | `stderr` | `CommandOutput` | Captured stderr. | | `output` | `CommandOutput` | Stdout and stderr merged chronologically. | ### CommandOutput Properties - `lines`: tuple of lines - `text`: joined lines as a single string (also used by `str(output)`) - `stripped`: `text` without leading/trailing whitespace and newlines - `value`: same as `stripped`, but returns `None` if empty ``` -------------------------------- ### Run Quietly with Fast Failure Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Configures CommandRunner to run commands quietly and fail fast if the command returns a non-zero exit code. This is useful for ensuring that errors are immediately apparent without excessive output. ```python from comrun import CommandRunner runner = CommandRunner(check=True, quiet=True) result = runner("pytest -q") ``` -------------------------------- ### Set Working Directory with cwd in Python Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Configure the working directory for commands executed by CommandRunner. Commands run via this runner will execute with the specified path as their working directory. This is useful for ensuring commands operate in the correct context. ```python runner = CommandRunner(cwd="/path/to/dir") ``` -------------------------------- ### Catch Exceptions with Strict Mode Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Configures CommandRunner with `check=True` to raise a `CommandError` when a command returns a non-zero exit code. This enables robust error handling using try-except blocks. ```python from comrun import CommandError, CommandRunner runner = CommandRunner(check=True) try: runner("exit 1") # (1)! except CommandError as err: print(f"Command failed: {err.exit_code}") # Access captured output if needed: err.result.stdout / stderr / output # 1. `check=True` raises `CommandError` on non-zero exit. ``` -------------------------------- ### Set Output Encoding with encoding in Python Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Override the default system encoding for decoding command output by specifying the `encoding` option. This ensures consistent output handling across different systems or when dealing with specific character sets like UTF-8. ```python runner = CommandRunner(encoding="utf-8") ``` -------------------------------- ### Add an Asyncio Timeout Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Integrates CommandRunner with asyncio to execute commands asynchronously and enforce a timeout. If the command exceeds the specified timeout, an `asyncio.TimeoutError` is raised. ```python import asyncio from comrun import CommandRunner runner = CommandRunner() async def main(): try: result = await asyncio.wait_for( runner.run_async("sleep 5"), # (1)! timeout=2.0, # (2)! ) print(result.exit_code) except asyncio.TimeoutError: print("Timed out") asyncio.run(main()) # 1. `run_async` executes `run` in a worker thread (same semantics as sync). # 2. `asyncio.wait_for` enforces the timeout; on timeout, the coroutine is cancelled but the subprocess is not killed—wrap the process in your own timeout/termination logic if needed. ``` -------------------------------- ### Raise Exceptions on Failures with check in Python Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Enable exception handling for command failures by passing `check=True`. By default, non-zero exit codes are quietly handled. With `check=True`, a non-zero exit code will raise a `CommandError`, allowing for explicit error management. ```python result = runner("exit 1") try: runner("exit 1", check=True) except CommandError as exc: print(exc) ``` -------------------------------- ### Branch on Failure Without Raising Exceptions Source: https://github.com/jgroxz/comrun/blob/develop/docs/cookbook.md Configures CommandRunner with `check=False` to prevent it from raising exceptions on non-zero exit codes. This allows for manual handling of command failures by inspecting the result object. ```python from comrun import CommandRunner runner = CommandRunner(check=False) result = runner("exit 1") # (1)! if result.failure: # Handle non-zero exit here print(f"Command failed with {result.exit_code}") # 1. `check=False` keeps exceptions off; use `failure`/`exit_code` to branch. ``` -------------------------------- ### Silence Command Output with quiet in Python Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Disable the default behavior of printing command output to the console as it appears by setting `quiet=True`. Captured output is still available in `result.stdout`. This is useful for cleaner execution logs when output is not needed in real-time. ```python runner('echo "Potato."') runner('echo "POTATO!", quiet=True) ``` -------------------------------- ### Override Environment Variables with env in Python Source: https://github.com/jgroxz/comrun/blob/develop/docs/usage_general.md Override environment variables for commands executed by CommandRunner. The `env` parameter takes a dictionary to set specific environment variables. Note that this replaces the entire environment; to merge, use `os.environ`. ```python runner = CommandRunner(env={"MY_VAR": "value"}) # To merge with existing environment variables: # CommandRunner(env={**os.environ, "MY_VAR": "value"}) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.