Tutorial:How to make your snakefiles self-documenting
2
7
Entering edit mode
8.1 years ago
Botond Sipos ★ 1.7k

I wrote a gist about how to make snakefiles self-documenting:

# This snippet add the "self-documenting" feature to snakemake files. 
# It is inspired by the Makefile in https://github.com/audreyr/cookiecutter-pypackage

# Add the follwing to your snakefile or include: "self_document.snake"

import re
def generate_help(sfile):
    """Parse out target and help message from file."""
    handler = open(sfile, "r")
    for line in handler:
        match = re.match(r'^rule\s+([a-zA-Z_-]+):.*?## (.*)$$', line)
        if match:
            target, help = match.groups()
            print("%-20s %s" % (target, help))

rule help: ## print list of all targets with help
    input:
        workflow.included
    run:
        print("--------------------------------------------")
        [generate_help(sfile) for sfile in input]
        print("--------------------------------------------")

# Then simply add a comment to your rule line preceded by '##'. Invoking snakemake help will print all targets and their descriptions.
snakemake • 6.8k views
ADD COMMENT
7
Entering edit mode
8.1 years ago
Eric Lim ★ 2.2k

Thanks for posting. This can also be accomplished using native snakemake's objects, workflow and rule with docstring.

rule help:
  """
  Print list of all targets with help.
  """
  run:
    for rule in workflow.rules:
      print( rule.name )
      print( rule.docstring )

rule do_something:
  """
  Do something.
  """
  run:
    pass

You can then write a function to prettify the outputs.

ADD COMMENT
1
Entering edit mode

Yeah, this might be a better way to do it :)

ADD REPLY
1
Entering edit mode
7.8 years ago
Eric Lim ★ 2.2k

Not sure if this is a newly added functionality, but I just realized one can simply do snakemake -l or snakemake --lt to display docstrings for each rule.

This is better than what I've been doing:

rule print_help:
"""Print help menu.
"""
run:
    tbl = PrettyTable(['Rules', 'Description'])
    tbl.align = 'l'
    for rule in workflow.rules:
        if not rule.name.startswith('_'):
            tbl.add_row([rule.name, rule.docstring.splitlines()[0]])
    print(tbl)
ADD COMMENT

Login before adding your answer.

Traffic: 2331 users visited in the last hour
Help About
FAQ
Access RSS
API
Stats

Use of this site constitutes acceptance of our User Agreement and Privacy Policy.

Powered by the version 2.3.6