diff --git a/client/galaxy/scripts/components/Markdown/Markdown.vue b/client/galaxy/scripts/components/Markdown/Markdown.vue index 03a43e27969..5d49d1fcac4 100644 --- a/client/galaxy/scripts/components/Markdown/Markdown.vue +++ b/client/galaxy/scripts/components/Markdown/Markdown.vue @@ -17,16 +17,12 @@ import JOB_STATES_MODEL from "mvc/history/job-states-model"; import HDCAModel from "mvc/history/hdca-model"; import HDCAListItemEdit from "mvc/history/hdca-li-edit"; -const galaxy_blocks = /{galaxy_(\w+)(.*)}/; +const FUNCTION_CALL_LINE_TEMPLATE = /\s*(\w+)\s*\((\s*\w+\s*=\s*\w+\s*)\)\s*/m; const md = MarkdownIt(); const default_fence = md.renderer.rules.fence; -function render_fenced_div(action, args, content) { - return `
${content}

\n`; -} - const RENDER_FUNCTIONS = { history_dataset_display: (action, args, content) => { const history_dataset_id = args.history_dataset_id; @@ -82,10 +78,22 @@ const RENDER_FUNCTIONS = { const history_dataset_id = args.history_dataset_id; return ``; }, - history_dataset_peek: render_fenced_div, - history_dataset_info: render_fenced_div, - tool_stdout: render_fenced_div, - tool_stderr: render_fenced_div, + history_dataset_peek: (action, args, content) => { + const history_dataset_id = args.history_dataset_id; + return `
`; + }, + history_dataset_info: (action, args, content) => { + const history_dataset_id = args.history_dataset_id; + return `
`; + }, + tool_stdout: (action, args, content) => { + const jobId = args.job_id; + return `
`; + }, + tool_stderr: (action, args, content) => { + const jobId = args.job_id; + return `
`; + }, job_metrics: (action, args, content) => { const jobId = args.job_id; return `
`; @@ -100,8 +108,8 @@ md.renderer.rules.fence = function(tokens, idx, options, env, slf) { const token = tokens[idx], info = token.info ? token.info.trim() : "", content = token.content; - const arr = galaxy_blocks.exec(info); - if (arr) { + if (info == "galaxy") { + const arr = FUNCTION_CALL_LINE_TEMPLATE.exec(content); const action = arr[1]; const arguments_str = arr[2].trim(); const args = {}; @@ -109,7 +117,7 @@ md.renderer.rules.fence = function(tokens, idx, options, env, slf) { const parts = arguments_str.split(/(\s+)/); for (const part of parts) { const [key, val] = part.split("="); - args[key] = val; + args[key.trim()] = val.trim(); } } return RENDER_FUNCTIONS[action](action, args, content); @@ -118,6 +126,16 @@ md.renderer.rules.fence = function(tokens, idx, options, env, slf) { } }; +function render_fenced_output(tag, objects, idAttr, metadataKey) { + $("." + tag).each((i, el) => { + const objectId = $(el).attr(idAttr); + const meta = objects[objectId][metadataKey]; + $(el) + .find("code") + .text(meta); + }); +} + export default { props: { markdownConfig: { @@ -129,7 +147,8 @@ export default { markdownRendered: "", historyDatasets: {}, historyDatasetCollections: {}, - workflows: {} + workflows: {}, + jobs: {} }; }, watch: { @@ -139,6 +158,7 @@ export default { this.historyDatasets = mConfig.history_datasets || {}; this.historyDatasetCollections = mConfig.history_dataset_collections || {}; this.workflows = mConfig.workflows || {}; + this.jobs = mConfig.jobs || {}; this.$nextTick(() => { render_embedded_items(); @@ -155,6 +175,11 @@ export default { } }); + render_fenced_output("tool-stdout", this.jobs, "job_id", "tool_stdout"); + render_fenced_output("tool-stderr", this.jobs, "job_id", "tool_stderr"); + render_fenced_output("dataset-peek", this.historyDatasets, "history_dataset_id", "peek"); + render_fenced_output("dataset-info", this.historyDatasets, "history_dataset_id", "info"); + $(".dataset-collection").each((i, el) => { const Galaxy = getGalaxyInstance(); const hdcaId = $(el).attr("history_dataset_collection_id"); diff --git a/client/galaxy/scripts/mvc/workflow/workflow-manager.js b/client/galaxy/scripts/mvc/workflow/workflow-manager.js index 9391a564bb5..67eb4b87625 100644 --- a/client/galaxy/scripts/mvc/workflow/workflow-manager.js +++ b/client/galaxy/scripts/mvc/workflow/workflow-manager.js @@ -9,16 +9,19 @@ const DEFAULT_INVOCATION_REPORT = ` # Workflow Execution Report ## Workflow Inputs -::: invocation_inputs -::: +\`\`\`galaxy +invocation_inputs() +\`\`\` ## Workflow Outputs -::: invocation_outputs -::: +\`\`\`galaxy +invocation_outputs() +\`\`\` ## Workflow -::: workflow_display -::: +\`\`\`galaxy +workflow_display() +\`\`\` `; class Workflow { diff --git a/lib/galaxy/managers/markdown_util.py b/lib/galaxy/managers/markdown_util.py index 6ce369994ba..be4144804e8 100644 --- a/lib/galaxy/managers/markdown_util.py +++ b/lib/galaxy/managers/markdown_util.py @@ -37,8 +37,12 @@ INVOCATION_SECTIONS = [ "invocation_inputs", "invocation_outputs", ] -GALAXY_FLAVORED_MARKDOWN_CONTAINER_REGEX = "(%s)" % "|".join(GALAXY_FLAVORED_MARKDOWN_CONTAINERS) -INVOCATION_SECTION_MARKDOWN_CONTAINER_REGEX = "(%s)" % "|".join(INVOCATION_SECTIONS) +ALL_CONTAINER_TYPES = GALAXY_FLAVORED_MARKDOWN_CONTAINERS + INVOCATION_SECTIONS +GALAXY_FLAVORED_MARKDOWN_CONTAINER_REGEX = "(%s)" % "|".join(ALL_CONTAINER_TYPES) + +FUNCTION_ARG = r'\s*\w+\s*=\s*\w+\s*' +FUNCTION_CALL_LINE_TEMPLATE = r'\s*%s\s*\((?:' + FUNCTION_ARG + r')?\)\s*' +GALAXY_MARKDOWN_FUNCTION_CALL_LINE = re.compile(FUNCTION_CALL_LINE_TEMPLATE % GALAXY_FLAVORED_MARKDOWN_CONTAINER_REGEX) BLOCK_FENCE_START = re.compile(r'```.*') BLOCK_FENCE_END = re.compile(r'```[\s]*') @@ -49,14 +53,12 @@ INPUT_LABEL_PATTERN = re.compile(r'input=([\w_\-]+)') STEP_LABEL_PATTERN = re.compile(r'step=([\w_\-]+)') ID_PATTERN = re.compile(r'(workflow_id|history_dataset_id|history_dataset_collection_id|job_id)=([\d]+)') GALAXY_FLAVORED_MARKDOWN_CONTAINER_LINE_PATTERN = re.compile( - r"```\s*\{galaxy_%s.*\}\s*" % GALAXY_FLAVORED_MARKDOWN_CONTAINER_REGEX -) -FENCED_MARKDOWN_CONTAINER_LINE_PATTERN = re.compile( - r"```\s*\{.*" + r"```\s*galaxy\s*" ) INVOCATION_SECTION_MARKDOWN_CONTAINER_LINE_PATTERN = re.compile( - r"```\s*\{galaxy_%s.*\}\s*" % INVOCATION_SECTION_MARKDOWN_CONTAINER_REGEX + r"```\s*galaxy\s*" ) +GALAXY_FENCED_BLOCK = re.compile(r'^```\s*galaxy\s*(.*?)^```', re.MULTILINE ^ re.DOTALL) VALID_CONTAINER_START_PATTERN = re.compile(r"^```\s+[\w]+.*$") VALID_CONTAINER_END_PATTERN = re.compile(r"^```\s*$") WHITE_SPACE_ONLY_PATTERN = re.compile(r"^[\s]+$") @@ -75,7 +77,6 @@ def ready_galaxy_markdown_for_export(trans, internal_galaxy_markdown): extra_rendering_data = {} def _remap(container, line): - remap_lines = [] id_match = re.search(ID_PATTERN, line) object_id = None encoded_id = None @@ -83,44 +84,37 @@ def ready_galaxy_markdown_for_export(trans, internal_galaxy_markdown): object_id = int(id_match.group(2)) encoded_id = trans.security.encode_id(object_id) line = line.replace(id_match.group(), "%s=%s" % (id_match.group(1), encoded_id)) - remap_lines.append(line) - def remap_with_fenced_output(output, default): - if output: - for line in output.splitlines(True): - if not line.endswith("\n"): - line += "\n" - remap_lines.append(line) - else: - # TODO: handle this better... shouldn't be part of code block - # ideally. - remap_lines.append("%s\n" % default) + def ensure_rendering_data_for(object_type, encoded_id): + if object_type not in extra_rendering_data: + extra_rendering_data[object_type] = {} + object_type_data = extra_rendering_data[object_type] + if encoded_id not in object_type_data: + object_type_data[encoded_id] = {} + return object_type_data[encoded_id] + + def extend_history_dataset_rendering_data(key, val, default_val): + ensure_rendering_data_for("history_datasets", encoded_id)[key] = val or default_val if container == "history_dataset_display": assert object_id is not None hda = hdas_manager.get_accessible(object_id, trans.user) if "history_datasets" not in extra_rendering_data: extra_rendering_data["history_datasets"] = {} - extra_rendering_data["history_datasets"][encoded_id] = { - "name": hda.name, - } + extend_history_dataset_rendering_data("name", hda.name, "") elif container == "history_dataset_peek": assert object_id is not None hda = hdas_manager.get_accessible(object_id, trans.user) peek = hda.peek - remap_with_fenced_output(peek, "*No Dataset Peek Available*") + extend_history_dataset_rendering_data("peek", peek, "*No Dataset Peek Available*") elif container == "history_dataset_info": hda = hdas_manager.get_accessible(object_id, trans.user) info = hda.info - remap_with_fenced_output(info, "*No Dataset Info Available*") + extend_history_dataset_rendering_data("info", info, "*No Dataset Peek Available*") elif container == "workflow_display": # TODO: should be workflow id... stored_workflow = workflows_manager.get_stored_accessible_workflow(trans, encoded_id) - if "workflows" not in extra_rendering_data: - extra_rendering_data["workflows"] = {} - extra_rendering_data["workflows"][encoded_id] = { - "name": stored_workflow.name, - } + ensure_rendering_data_for("workflows", encoded_id)["name"] = stored_workflow.name elif container == "history_dataset_collection_display": collection_manager = DatasetCollectionManager(trans.app) hdca = collection_manager.get_dataset_collection_instance(trans, "history", encoded_id) @@ -130,18 +124,18 @@ def ready_galaxy_markdown_for_export(trans, internal_galaxy_markdown): ) if "history_dataset_collections" not in extra_rendering_data: extra_rendering_data["history_dataset_collections"] = {} - extra_rendering_data["history_dataset_collections"][encoded_id] = hdca_view + ensure_rendering_data_for("history_dataset_collections", encoded_id).update(hdca_view) elif container == "tool_stdout": job_manager = JobManager(trans.app) job = job_manager.get_accessible_job(trans, object_id) - remap_with_fenced_output(job.tool_stdout, "*No Standard Output Available*") + ensure_rendering_data_for("jobs", encoded_id)["tool_stdout"] = job.tool_stdout or "*No Standard Output Available*" elif container == "tool_stderr": job_manager = JobManager(trans.app) job = job_manager.get_accessible_job(trans, object_id) - remap_with_fenced_output(job.tool_stderr, "*No Standard Error Available*") - return remap_lines + ensure_rendering_data_for("jobs", encoded_id)["tool_stderr"] = job.tool_stderr or "*No Standard Error Available*" + return (line, False) - export_markdown = _remap_galaxy_markdown_containers(_remap, internal_galaxy_markdown) + export_markdown = _remap_galaxy_markdown_calls(_remap, internal_galaxy_markdown) return export_markdown, extra_rendering_data @@ -171,12 +165,14 @@ def resolve_invocation_markdown(trans, invocation, workflow_markdown): if output_assoc.history_content_type == "dataset": section_markdown += """#### Output Dataset: %s -```{galaxy_history_dataset_display output=%s} +```galaxy +history_dataset_display(output=%s) ``` """ % (output_assoc.workflow_output.label, output_assoc.workflow_output.label) else: section_markdown += """#### Output Dataset Collection: %s -```{galaxy_history_dataset_collection_display output=%s} +```galaxy +history_dataset_collection_display(output=%s) ``` """ % (output_assoc.workflow_output.label) elif container == "invocation_inputs": @@ -186,21 +182,25 @@ def resolve_invocation_markdown(trans, invocation, workflow_markdown): if input_assoc.history_content_type == "dataset": section_markdown += """#### Input Dataset: %s -```{galaxy_history_dataset_display input=%s} +```galaxy +history_dataset_display(input=%s) ``` """ % (input_assoc.workflow_step.label, input_assoc.workflow_step.label) else: section_markdown += """#### Input Dataset Collection: %s -```{galaxy_history_dataset_collection_display input=%s} +```galaxy +history_dataset_collection_display(input=%s) ``` """ % (input_assoc.workflow_step.label, input_assoc.workflow_step.label) - return section_markdown + else: + return line, False + return section_markdown, True def _remap(container, line): if container == "workflow_display": # TODO: this really should be workflow id not stored workflow id but the API # it consumes wants the stored id. - return "```{galaxy_workflow_display workflow_id=%s}\n" % invocation.workflow.stored_workflow.id + return ("workflow_display(workflow_id=%s)\n" % invocation.workflow.stored_workflow.id, False) ref_object_type = None output_match = re.search(OUTPUT_LABEL_PATTERN, line) input_match = re.search(INPUT_LABEL_PATTERN, line) @@ -228,16 +228,14 @@ def resolve_invocation_markdown(trans, invocation, workflow_markdown): else: ref_object_type = "history_dataset_collection" line = line.replace(target_match.group(), "%s_id=%s" % (ref_object_type, ref_object.id)) - return line + return (line, False) log.debug("workflow markdown is \n%s" % workflow_markdown) - workflow_markdown = _remap_galaxy_markdown_containers( + workflow_markdown = _remap_galaxy_markdown_calls( _section_remap, workflow_markdown, - container_pattern=INVOCATION_SECTION_MARKDOWN_CONTAINER_LINE_PATTERN, - replace_whole_container=True ) - galaxy_markdown = _remap_galaxy_markdown_containers(_remap, workflow_markdown) + galaxy_markdown = _remap_galaxy_markdown_calls(_remap, workflow_markdown) log.debug("galaxy markdown is \n%s" % galaxy_markdown) return galaxy_markdown @@ -245,6 +243,7 @@ def resolve_invocation_markdown(trans, invocation, workflow_markdown): def validate_galaxy_markdown(galaxy_markdown, internal=True): expecting_container_close_for = None last_line_no = 0 + function_calls = 0 for (line, fenced, open_fence, line_no) in _split_markdown_lines(galaxy_markdown): last_line_no = line_no @@ -261,7 +260,7 @@ def validate_galaxy_markdown(galaxy_markdown, internal=True): continue elif fenced and expecting_container_close and BLOCK_FENCE_END.match(line): expecting_container_close_for = None - elif open_fence and FENCED_MARKDOWN_CONTAINER_LINE_PATTERN.match(line): + elif open_fence and GALAXY_FLAVORED_MARKDOWN_CONTAINER_LINE_PATTERN.match(line): if expecting_container_close: if not VALID_CONTAINER_END_PATTERN.match(line): invalid_line("Invalid command close line [{line}] for [{expected_for}]", line=line, expected_for=expecting_container_close_for) @@ -269,11 +268,16 @@ def validate_galaxy_markdown(galaxy_markdown, internal=True): expecting_container_close_for = None continue - if not GALAXY_FLAVORED_MARKDOWN_CONTAINER_LINE_PATTERN.match(line): - invalid_line("Invalid markdown command line [{line}]", line=line) - # TODO: check IDs and attributes and stuff... expecting_container_close_for = line continue + elif fenced and line and expecting_container_close_for: + if GALAXY_MARKDOWN_FUNCTION_CALL_LINE.match(line): + function_calls += 1 + if function_calls > 1: + invalid_line("Only one Galaxy directive is allowed per fenced Galaxy block (```galaxy)") + continue + else: + invalid_line("Invalid embedded Galaxy markup line [{line}]", line=line) # Markdown unrelated to Galaxy object containers. continue @@ -282,26 +286,47 @@ def validate_galaxy_markdown(galaxy_markdown, internal=True): raise Exception("Invalid line %d: %s" % (last_line_no, "close of block for [{expected_for}] expected".format(expected_for=expecting_container_close_for))) -def _remap_galaxy_markdown_containers(func, markdown, container_pattern=GALAXY_FLAVORED_MARKDOWN_CONTAINER_LINE_PATTERN, replace_whole_container=False): - remapped_lines = [] - replaced_container = False - for (line, fenced, open_fence, _) in _split_markdown_lines(markdown): - if replaced_container: - # Replaced whole container, no need to keep container close. - assert line.startswith("```") - replaced_container = False - continue - container_match = container_pattern.match(line) - if container_match: - remap_line = func(container_match.group(1), line) - if not isinstance(remap_line, list): - remap_line = [remap_line] - remapped_lines.extend(remap_line) - replaced_container = replace_whole_container +def _remap_galaxy_markdown_containers(func, markdown): + new_markdown = markdown + + searching_from = 0 + while True: + from_markdown = new_markdown[searching_from:] + match = re.search(GALAXY_FENCED_BLOCK, from_markdown) + if match is not None: + (replacement, whole_block) = func(match.group(1)) + if whole_block: + start_pos = match.start() + end_pos = match.end() + else: + start_pos = match.start(1) + end_pos = match.end(1) + start_pos = start_pos + searching_from + end_pos = end_pos + searching_from + + new_markdown = new_markdown[:start_pos] + replacement + new_markdown[end_pos:] + searching_from = end_pos else: - remapped_lines.append(line) - rval = "".join(remapped_lines) - return rval + break + + return new_markdown + + +def _remap_galaxy_markdown_calls(func, markdown): + + def _remap_container(container): + matching_line = None + for line in container.splitlines(): + if GALAXY_MARKDOWN_FUNCTION_CALL_LINE.match(line): + assert matching_line is None + matching_line = line + + assert matching_line, "Failed to find func call line in [%s]" % container + match = GALAXY_MARKDOWN_FUNCTION_CALL_LINE.match(line) + + return func(match.group(1), matching_line + "\n") + + return _remap_galaxy_markdown_containers(_remap_container, markdown) def _split_markdown_lines(markdown): diff --git a/lib/galaxy/workflow/reports/generators/markdown.py b/lib/galaxy/workflow/reports/generators/markdown.py index a17466cecdf..4f735274d43 100644 --- a/lib/galaxy/workflow/reports/generators/markdown.py +++ b/lib/galaxy/workflow/reports/generators/markdown.py @@ -11,16 +11,19 @@ DEFAULT_MARKDOWN = """ # ${title} ## Workflow Inputs -::: invocation_inputs -::: +```galaxy +invocation_inputs() +``` ## Workflow Outputs -::: invocation_outputs -::: +```galaxy +invocation_outputs() +``` ## Workflow -::: workflow_display -::: +```galaxy +workflow_display() +``` """ diff --git a/test/api/test_workflows.py b/test/api/test_workflows.py index a4ad8069be8..e1a063278e8 100644 --- a/test/api/test_workflows.py +++ b/test/api/test_workflows.py @@ -1284,7 +1284,7 @@ steps: assert report_json["render_format"] == "markdown" markdown_content = report_json["markdown"] assert "## Workflow Outputs" in markdown_content - assert "\n```{galaxy_history_dataset_display history_dataset_id=" in markdown_content + assert "\n```galaxy\nhistory_dataset_display(history_dataset_id=" in markdown_content assert "## Workflow Inputs" in markdown_content assert "## About This Report" in markdown_content diff --git a/test/base/workflow_fixtures.py b/test/base/workflow_fixtures.py index 941f5813477..55de9ccc7e7 100644 --- a/test/base/workflow_fixtures.py +++ b/test/base/workflow_fixtures.py @@ -500,19 +500,23 @@ report: in the default workflow invocation report template. ## Workflow Inputs - ```{galaxy_invocation_inputs} + ```galaxy + invocation_inputs() ``` ## Workflow Outputs - ```{galaxy_invocation_outputs} + ```galaxy + invocation_outputs() ``` ## Workflow Inputs - ```{galaxy_invocation_inputs} + ```galaxy + invocation_inputs() ``` ## Workflow Outputs - ```{galaxy_invocation_outputs} + ```galaxy + invocation_outputs() ``` The auto-generated sections could be hand-crafted from workflow markdown also, @@ -530,28 +534,34 @@ report: Once can reference an output and embed a display of it as follows: - ```{galaxy_history_dataset_display output=output_1} + ```galaxy + history_dataset_display(output=output_1) ``` - ```{galaxy_history_dataset_display output=output_1} + ```galaxy + history_dataset_display(output=output_1) ``` Inputs can be referenced and displayed the same way: - ```{galaxy_history_dataset_display input=input_1} + ```galaxy + history_dataset_display(input=input_1) ``` - ```{galaxy_history_dataset_display input=input_1} + ```galaxy + history_dataset_display(input=input_1) ``` --- Images can be embedded directly into the report as follows: - ```{galaxy_history_dataset_as_image output=output_image} + ```galaxy + history_dataset_as_image(output=output_image) ``` - ```{galaxy_history_dataset_as_image output=output_image} + ```galaxy + history_dataset_as_image(output=output_image) ``` --- @@ -559,30 +569,36 @@ report: Dataset peek content can be displayed to quickly provided an embedded summary of an input or output: - ```{galaxy_history_dataset_peek output=output_1} + ```galaxy + history_dataset_peek(output=output_1) ``` - ```{galaxy_history_dataset_peek output=output_1} + ```galaxy + history_dataset_peek(output=output_1) ``` --- Dataset "info" content can be displayed as well: - ```{galaxy_history_dataset_info input=input_1} + ```galaxy + history_dataset_info(input=input_1) ``` - ```{galaxy_history_dataset_info input=input_1} + ```galaxy + history_dataset_info(input=input_1) ``` --- Collections can be displayed: - ```{galaxy_history_dataset_collection_display input=input_list} + ```galaxy + history_dataset_collection_display(input=input_list) ``` - ```{galaxy_history_dataset_collection_display input=input_list} + ```galaxy + history_dataset_collection_display(input=input_list) ``` --- @@ -590,46 +606,56 @@ report: The whole workflow can be embedded to provide some context and display annotations and steps. - ```{galaxy_workflow_display} + ```galaxy + workflow_display() ``` - ```{galaxy_workflow_display} + ```galaxy + workflow_display() ``` --- Job parameters can be summarized: - ```{galaxy_job_parameters step=qc_step} + ```galaxy + job_parameters(step=qc_step) ``` - ```{galaxy_job_parameters step=qc_step} + ```galaxy + job_parameters(step=qc_step) ``` --- Job metrics can be summarized as well: - ```{galaxy_job_metrics step=image_cat} + ```galaxy + job_metrics(step=image_cat) ``` - ```{galaxy_job_metrics step=image_cat} + ```galaxy + job_metrics(step=image_cat) ``` --- Tool standard out and error are also available for steps. - ```{galaxy_tool_stdout step=qc_step} + ```galaxy + tool_stdout(step=qc_step) ``` - ```{galaxy_tool_stdout step=qc_step} + ```galaxy + tool_stdout(step=qc_step) ``` - ```{galaxy_tool_stderr step=qc_step} + ```galaxy + tool_stderr(step=qc_step) ``` - ```{galaxy_tool_stderr step=qc_step} + ```galaxy + tool_stderr(step=qc_step) ``` --- diff --git a/test/unit/test_markdown_validate.py b/test/unit/test_markdown_validate.py index 681fb163eac..1dc5561bf4b 100644 --- a/test/unit/test_markdown_validate.py +++ b/test/unit/test_markdown_validate.py @@ -32,26 +32,40 @@ printf('hello') """) # assert valid container is fine. assert_markdown_valid(""" -```{galaxy_job_metrics job_id=THISFAKEID} +```galaxy +job_metrics(job_id=THISFAKEID) ``` """) - # assert valid container is fine. + # assert valid container is fine at end of document. assert_markdown_valid(""" -```{galaxy_job_metrics job_id=THISFAKEID} +```galaxy +job_metrics(job_id=THISFAKEID) ```""") # assert valid containers require container close assert_markdown_invalid(""" -```{galaxy_job_metrics job_id=THISFAKEID} -foo +```galaxy +job_metrics(job_id=THISFAKEID) """, at_line=1) # assert valid containers require container close, even at end... assert_markdown_invalid(""" -```{galaxy_job_metrics job_id=THISFAKEID""") - - # assert valid containers require container close, even at end... +```galaxy +job_metrics(job_id=THISFAKEID)""") + # assert only one command allowed assert_markdown_invalid(""" -```{galaxy_not_a_command} -```""") +```galaxy +job_metrics(job_id=THISFAKEID) +job_metrics(job_id=THISFAKEID2) +``` +""") + # assert command paren is closed assert_markdown_invalid(""" -```{not_a_command} -```""") +```galaxy +job_metrics(job_id=THISFAKEID +``` +""") + # assert command arg is named. + assert_markdown_invalid(""" +```galaxy +job_metrics(THISFAKEID) +``` +""") diff --git a/test/unit/workflows/test_workflow_markdown.py b/test/unit/workflows/test_workflow_markdown.py index f286731450c..742d557b451 100644 --- a/test/unit/workflows/test_workflow_markdown.py +++ b/test/unit/workflows/test_workflow_markdown.py @@ -1,5 +1,5 @@ from galaxy import model -from galaxy.managers.markdown_util import resolve_invocation_markdown +from galaxy.managers.markdown_util import resolve_invocation_markdown, validate_galaxy_markdown from .test_workflow_progress import TEST_WORKFLOW_YAML from .workflow_support import MockTrans, yaml_to_model @@ -7,63 +7,69 @@ from .workflow_support import MockTrans, yaml_to_model def test_workflow_section_expansion(): workflow_markdown = """ ## Workflow -```{galaxy_workflow_display} +```galaxy +workflow_display() ``` """ galaxy_markdown = resolved_markdown(workflow_markdown) assert "## Workflow\n" in galaxy_markdown - assert "```{galaxy_workflow_display workflow_id=342}\n```\n" in galaxy_markdown + assert "```galaxy\nworkflow_display(workflow_id=342)\n```\n" in galaxy_markdown def test_inputs_section_expansion(): workflow_markdown = """ ## Workflow Inputs -```{galaxy_invocation_inputs} +```galaxy +invocation_inputs() ``` """ galaxy_markdown = resolved_markdown(workflow_markdown) assert "## Workflow Inputs" in galaxy_markdown - assert "```{galaxy_history_dataset_display history_dataset_id=567}" in galaxy_markdown + assert "```galaxy\nhistory_dataset_display(history_dataset_id=567)\n" in galaxy_markdown assert len(galaxy_markdown.split("```")) == 3 def test_outputs_section_expansion(): workflow_markdown = """ ## Workflow Outputs -```{galaxy_invocation_outputs} +```galaxy +invocation_outputs() ``` """ galaxy_markdown = resolved_markdown(workflow_markdown) assert "## Workflow Outputs" in galaxy_markdown - assert "```{galaxy_history_dataset_display history_dataset_id=563}" in galaxy_markdown + assert "```galaxy\nhistory_dataset_display(history_dataset_id=563)" in galaxy_markdown def test_input_reference_mapping(): workflow_markdown = """ And outputs... -```{galaxy_history_dataset_peek input=input1} +```galaxy +history_dataset_peek(input=input1) ``` """ galaxy_markdown = resolved_markdown(workflow_markdown) - assert "```{galaxy_history_dataset_peek history_dataset_id=567}\n```" in galaxy_markdown + assert "```galaxy\nhistory_dataset_peek(history_dataset_id=567)\n```" in galaxy_markdown def test_output_reference_mapping(): workflow_markdown = """ And outputs... -```{galaxy_history_dataset_as_image output=output_label} +```galaxy +history_dataset_as_image(output=output_label) ``` """ galaxy_markdown = resolved_markdown(workflow_markdown) - assert "```{galaxy_history_dataset_as_image history_dataset_id=563}" in galaxy_markdown + assert "```galaxy\nhistory_dataset_as_image(history_dataset_id=563)\n```" in galaxy_markdown def resolved_markdown(workflow_markdown): # Convert workflow markdown to internal Galaxy markdown with object id references # and with sections expanded. trans = MockTrans() + validate_galaxy_markdown(workflow_markdown) galaxy_markdown = resolve_invocation_markdown(trans, example_invocation(trans), workflow_markdown) return galaxy_markdown