diff --git a/lib/galaxy/tool_util/linters/command.py b/lib/galaxy/tool_util/linters/command.py
index 482fe4ac70f..231cd6a5a0c 100644
--- a/lib/galaxy/tool_util/linters/command.py
+++ b/lib/galaxy/tool_util/linters/command.py
@@ -24,7 +24,9 @@ def lint_command(tool_xml, lint_ctx):
return
command = get_command(tool_xml)
- if "TODO" in command:
+ if command.text is None:
+ lint_ctx.error("Command is empty.", line=root_line, xpath=root_path)
+ elif "TODO" in command.text:
lint_ctx.warn("Command template contains TODO text.", line=command.sourceline, xpath=tool_xml.getpath(command))
command_attrib = command.attrib
@@ -41,7 +43,7 @@ def lint_command(tool_xml, lint_ctx):
if interpreter_type:
interpreter_info = f" with interpreter of type [{interpreter_type}]"
if interpreter_type:
- lint_ctx.info("Command uses deprecated 'interpreter' attribute.", line=command.sourceline, xpath=tool_xml.getpath(command))
+ lint_ctx.warn("Command uses deprecated 'interpreter' attribute.", line=command.sourceline, xpath=tool_xml.getpath(command))
lint_ctx.info(f"Tool contains a command{interpreter_info}.", line=command.sourceline, xpath=tool_xml.getpath(command))
diff --git a/test/unit/tool_util/test_tool_linters.py b/test/unit/tool_util/test_tool_linters.py
index a6b6cb1bda4..5360017b0ff 100644
--- a/test/unit/tool_util/test_tool_linters.py
+++ b/test/unit/tool_util/test_tool_linters.py
@@ -5,6 +5,7 @@ import pytest
from galaxy.tool_util.lint import LintContext
from galaxy.tool_util.linters import (
citations,
+ command,
general,
help,
inputs,
@@ -45,6 +46,31 @@ CITATIONS_VALID = """
"""
+
+# tests tool xml for command linter
+COMMAND_MULTIPLE = """
+
+
+
+
+"""
+COMMAND_MISSING = """
+
+"""
+COMMAND_TODO = """
+
+
+ ## TODO
+
+
+"""
+COMMAND_DETECT_ERRORS_INTERPRETER = """
+
+
+
+"""
+
+
# tests tool xml for general linter
GENERAL_MISSING_TOOL_ID_NAME_VERSION = """
@@ -513,6 +539,34 @@ TESTS = [
'Found 1 likely valid citations.' in x.valid_messages
and len(x.info_messages) == 0 and len(x.valid_messages) == 1 and len(x.warn_messages) == 0 and len(x.error_messages) == 0
),
+ (
+ COMMAND_MULTIPLE, command.lint_command,
+ lambda x:
+ 'More than one command tag found, behavior undefined.' in x.error_messages
+ and len(x.info_messages) == 0 and len(x.valid_messages) == 0 and len(x.warn_messages) == 0 and len(x.error_messages) == 1
+ ),
+ (
+ COMMAND_MISSING, command.lint_command,
+ lambda x:
+ 'No command tag found, must specify a command template to execute.' in x.error_messages
+ and len(x.info_messages) == 0 and len(x.valid_messages) == 0 and len(x.warn_messages) == 0 and len(x.error_messages) == 1
+ ),
+ (
+ COMMAND_TODO, command.lint_command,
+ lambda x:
+ 'Tool contains a command.' in x.info_messages
+ and 'Command template contains TODO text.' in x.warn_messages
+ and len(x.info_messages) == 1 and len(x.valid_messages) == 0 and len(x.warn_messages) == 1 and len(x.error_messages) == 0
+ ),
+ (
+ COMMAND_DETECT_ERRORS_INTERPRETER, command.lint_command,
+ lambda x:
+ "Command uses deprecated 'interpreter' attribute." in x.warn_messages
+ and 'Tool contains a command with interpreter of type [python].' in x.info_messages
+ and 'Unknown detect_errors attribute [nonsense]' in x.warn_messages
+ and 'Command is empty.' in x.error_messages
+ and len(x.info_messages) == 1 and len(x.valid_messages) == 0 and len(x.warn_messages) == 2 and len(x.error_messages) == 1
+ ),
(
GENERAL_MISSING_TOOL_ID_NAME_VERSION, general.lint_general,
lambda x:
@@ -794,6 +848,10 @@ TEST_IDS = [
'citations: absent',
'citations: errors',
'citations: valid',
+ 'command: multiple',
+ 'command: missing',
+ 'command: todo',
+ 'command: detect_errors and interpreter',
'general: missing tool id, name, version; invalid profile',
'general: whitespace in version, id, name',
'general: requirement without version',