Shell Commands ============== lint ---- TPV config files can be checked for linting errors using the ``tpv lint`` command. .. code-block:: console tpv lint If linting is successful, a lint successful message will be displayed with an exit code of zero. If the linting fails, a lint failed message with the relevant error will be displayed with an exit code of 1. For example: .. code-block:: console $ cat >good.yml <bad.yml < $ tpv -vv lint --preserve-temp-code tests/fixtures/linter/linter-types-undefined-variable.yml WARNING: tpv.commands.linter: T103: /var/folders/0j/l_xj28m94cb7fq5nnk03m7p80000gs/T/tmpym33_1uz.py:64: error: Incompatible return value type (got "set[Any]", expected "int | float | str | None") [return-value] WARNING: tpv.commands.linter: T103: /var/folders/0j/l_xj28m94cb7fq5nnk03m7p80000gs/T/tmpym33_1uz.py:64: error: Name "something" is not defined [name-defined] WARNING: tpv.commands.linter: T103: /var/folders/0j/l_xj28m94cb7fq5nnk03m7p80000gs/T/tmpym33_1uz.py:68: error: Name "mem2" is not defined [name-defined] WARNING: tpv.commands.linter: T104: Unexpected field '.destinations.local.unknown' - make sure the field is nested correctly or manually silence warning WARNING: tpv.commands.linter: T104: Unexpected field '.destinations.local.if' - make sure the field is nested correctly or manually silence warning INFO : tpv.commands.shell: lint successful. Note the use of the `-vv` flag, which has a single hypen, and each repeated occurrence of `v` increases verbosity level. Note also the use of the `--preserve-temp-code` flag. This flag will retain the generated python code so that the line numbers indicated in the error can be inspected. In the generated file, each code block is enclosed in a dedicated function, and the function name can be used to infer the affected code block. .. code-block:: console cat /var/folders/0j/l_xj28m94cb7fq5nnk03m7p80000gs/T/tmpym33_1uz.py will reveal the code that was type checked, and you can find the line numbers pinpointed by mypy: .. code-block:: python # This file was autogenerated by TPVConfigLinter for mypy checks. import logging from typing import Annotated, Any, ClassVar, Iterable from galaxy.app import UniverseApplication from galaxy.jobs import JobWrapper from galaxy.model import Job, User from galaxy.tools import Tool as GalaxyTool from tpv.core import helpers from tpv.core.entities import Destination, Entity, SchedulingTags from tpv.core.mapper import EntityToDestinationMapper log = logging.getLogger(__name__) # --- 1. Declare global "context" variables --- app: UniverseApplication tool: GalaxyTool user: User | None job: Job job_wrapper: JobWrapper | None resource_params: dict[str, Any] | None workflow_invocation_uuid: str | None mapper: EntityToDestinationMapper entity: Entity # --- 2. Declare evaluation time "context" variables --- cores: int | float | str | None mem: int | float | str | None gpus: int | str | None min_cores: int | float | str | None min_mem: int | float | str | None min_gpus: int | str | None max_cores: int | float | str | None max_mem: int | float | str | None max_gpus: int | str | None max_accepted_cores: int | float | None max_accepted_mem: int | float | None max_accepted_gpus: int | None min_accepted_cores: int | float | None min_accepted_mem: int | float | None min_accepted_gpus: int | None env: list[dict[str, str]] | None params: dict[str, Any] | None resubmit: dict[str, dict[str, str | int | float | None]] | None rank: str | None context: dict[str, Any] | None handler_tags: SchedulingTags | None candidate_destinations: list[Destination] dest_name: str | None input_size: float # --- 3. Declare user defined "context" variables --- # --- 4. User defined, evaluable entity fields --- def tool_default_cores() -> int | float | str | None: return 2 def tool_default_mem() -> int | float | str | None: return {something} def tool_default_params_native_spec() -> str: return f'''--mem {mem2}''' dry-run ------- You can test that your TPV configuration returns the expected destination for a given tool and/or user using the ``tpv dry-run`` command. .. code-block:: console tpv dry-run --job-conf [--tool ] \ [--user ] [--input-size ] \ [tpv_config_file ...] If no TPV config files are specified on the command line, they will be read from the ``tpv_dispatcher`` execution environment (destination) definition in the specified Galaxy job configuration file. For example: .. code-block:: console $ tpv dry-run --job-conf /srv/galaxy/config/job_conf.yml !!python/object:galaxy.jobs.JobDestination converted: false env: - {name: LC_ALL, value: C} id: slurm legacy: false params: {native_specification: --nodes=1 --ntasks=1 --ntasks-per-node=1 --mem=3994 --partition=normal, outputs_to_working_directory: true, tmp_dir: true} resubmit: [] runner: slurm shell: null tags: null url: null .. code-block:: console $ tpv dry-run --job-conf /srv/galaxy/config/job_conf.yml --tool trinity --input-size 40 *.yml !!python/object:galaxy.jobs.JobDestination converted: false env: - {name: LC_ALL, value: C} - {name: TERM, value: vt100} - {execute: ulimit -c 0} - {execute: ulimit -u 16384} id: pulsar legacy: false params: default_file_action: remote_transfer dependency_resolution: remote jobs_directory: /scratch/pulsar/staging outputs_to_working_directory: false remote_metadata: false rewrite_parameters: true submit_native_specification: --nodes=1 --ntasks=20 --ntasks-per-node=20 --partition=xlarge transport: curl resubmit: [] runner: pulsar shell: null tags: null url: null **Explain mode** The ``--explain`` flag provides a detailed decision trace showing how TPV arrived at its scheduling result. This is useful for debugging why a particular tool was routed to a specific destination, or why a mapping failed. .. code-block:: console tpv dry-run --job-conf --tool --explain \ [--user ] [--input-size ] \ [--output-format text|yaml] [tpv_config_file ...] The trace is written to stderr (so it can be separated from the destination YAML on stdout) and includes the following phases: - **Configuration Loading** -- which config files were loaded - **Entity Matching** -- which tool, user, and role entities were matched - **Entity Combining** -- how matched entities were merged - **Rule Evaluation** -- which rules matched or did not match, and how they modified the entity - **Destination Matching** -- which candidate destinations matched or were rejected - **Destination Ranking** -- how candidates were scored and ordered - **Destination Evaluation** -- final evaluation of the selected destination - **Final Result** -- the chosen destination, or the reason for failure For example: .. code-block:: console $ tpv dry-run --job-conf /srv/galaxy/config/job_conf.yml --tool bwa --input-size 40 --explain ======================================================================== TPV SCHEDULING DECISION TRACE ======================================================================== --- Configuration Loading --- [1] Loaded config: /srv/galaxy/config/tpv_rules.yml --- Entity Matching --- [2] Tool 'bwa': matched entity 'bwa' ... --- Final Result --- [10] Selected destination: pulsar (score=2) ======================================================================== If the mapping fails (e.g. no destinations can accept the job), the trace still shows all steps up to the failure, making it easy to diagnose the issue. To get the trace as YAML instead of text, use ``--output-format yaml``: .. code-block:: console $ tpv dry-run --job-conf /srv/galaxy/config/job_conf.yml --tool bwa --explain --output-format yaml dump ---- The ``tpv dump`` command loads one or more TPV configuration files, merges them, and outputs the fully resolved configuration. This is useful for inspecting the final merged state when multiple config files override each other. .. code-block:: console tpv dump [--job-conf ] \ [--output-format text|yaml] [tpv_config_file ...] If no TPV config files are specified on the command line, they will be discovered from the ``tpv_dispatcher`` destination definition in the Galaxy job configuration file specified via ``--job-conf``. The text output shows all non-default fields for each entity, including resource requirements, scheduling tags, environment variables, parameters, and full rule details. Simple rule conditions appear inline, while multiline code blocks are rendered with YAML-style ``|`` block syntax. For example: .. code-block:: console $ tpv dump config1.yml config2.yml ======================================================================== TPV MERGED CONFIGURATION Sources (in load order): 1. config1.yml 2. config2.yml ======================================================================== --- Global --- default_inherits: default --- Tools --- default: cores: 2 mem: cores * 3 env: [{'name': 'GALAXY_SLOTS', 'value': '{cores}'}] params: {'native_spec': '--mem {mem} --cores {cores}'} scheduling: prefer=['general'], reject=['pulsar'] rules: fail_small_data [if: input_size < 5] fail: Data size too small bwa: scheduling: require=['pulsar'] rules: medium_resources [if: input_size <= 10] cores: 4 mem: cores * 4 large_resources [if: input_size > 10 and input_size < 20] scheduling: {'require': ['highmem']} reject_huge [if: input_size >= 20] fail: Too much data, shouldn't run --- Users --- default: rules: training_destination_rule if: | any([r for r in user.all_roles() if (not r.deleted and r.name.startswith('training'))]) scheduling: {'require': ['training']} --- Destinations --- local: runner: local max_accepted_cores: 4 max_accepted_mem: 16 scheduling: prefer=['general'] k8s_environment: runner: k8s max_accepted_cores: 16 max_accepted_mem: 64 max_accepted_gpus: 2 scheduling: prefer=['pulsar'] ======================================================================== To dump the merged configuration as YAML: .. code-block:: console $ tpv dump --output-format yaml config1.yml config2.yml To discover config files from a Galaxy job configuration: .. code-block:: console $ tpv dump --job-conf /srv/galaxy/config/job_conf.yml