1. Brett Daniel
  2. explain

Source

explain / test_explain.py

# By Brett Daniel <http://www.brettdaniel.com>
# November 2009

import io
from nose.tools import *

import explain

SIMPLE_MAN = """\
NAME
       fake - this is a fake command

SYNOPSIS
       fake [OPTION]

DESCRIPTION
       Some text describing the command
       this description has a 
       -a flag at the beginning of a line, 
       which could cause parsing problems.

OPTIONS
       Some more text describing the command

       -a
              the a option

       -b, --big, --even-bigger
              an option with synonyms

       -c value
              an option with a value

       -d     an option with inline description and
              multiple lines.

       -e val a value then an inline description

       -f --full
              commaless synonyms
       
       -g
       --giant
              multiple line synonyms

       --ignored
              not explained

       --repeated
              explained once

       --repeated
              explained twice

       --something
              Something starting with "something"

       --something-else
              Something else starting with "something"

       -long
              A long, single-dash flag

       -l 
              A short flag that starts with the same thing as a long one

       --space-after-flag

              Documentation after a space

       More text describing the command
       And even more
""".splitlines()

def test_parse_description():
    expl = explain.parse(SIMPLE_MAN, "fake", [])
    assert_equal("fake", expl.name)
    assert_equal("this is a fake command", expl.description)

def test_parse_simple_option():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-a"])
    arg = expl.arg_for("-a")
    assert_equal("the a option", arg.description)

def test_parse_synonyms():
    expl = explain.parse(SIMPLE_MAN, "fake", ["--big"])
    arg = expl.arg_for("--big")
    assert_equal("an option with synonyms", arg.description)

def test_parse_with_value():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-c"])
    arg = expl.arg_for("-c")
    assert_equal("an option with a value", arg.description)

def test_parse_inline_multiline():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-d"])
    arg = expl.arg_for("-d")
    assert_equal(
        "an option with inline description and\nmultiple lines.", 
        arg.description)

def test_parse_value_inline():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-e"])
    arg = expl.arg_for("-e")
    assert_equal("a value then an inline description", arg.description)

def test_parse_commaless_synonyms():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-f"])
    arg = expl.arg_for("-f")
    assert_equal("commaless synonyms", arg.description)
    
def test_parse_multiline_synonyms():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-g"])
    arg = expl.arg_for("-g")
    assert_equal("multiple line synonyms", arg.description)
    assert_equal([("-g", None), ("--giant", None)], arg.synonyms)

def test_parse_multiline_synonyms2():
    expl = explain.parse(SIMPLE_MAN, "fake", ["--giant"])
    arg = expl.arg_for("--giant")
    assert_equal("multiple line synonyms", arg.description)
    assert_equal([("-g", None), ("--giant", None)], arg.synonyms)
    
def test_parse_nonexistent():
    expl = explain.parse(SIMPLE_MAN, "fake", ["--not-in-man"])
    arg = expl.arg_for("--not-in-man")
    assert_equal("", arg.description)
        
def test_parse_repeated():
    expl = explain.parse(SIMPLE_MAN, "fake", ["--repeated"])
    arg = expl.arg_for("--repeated")
    assert_equal([("--repeated", None)], arg.synonyms)
    assert_equal("explained twice", arg.description)

def test_compacted():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-abc"])
    aarg = expl.arg_for("-a")
    assert_true(aarg is not None)
    barg = expl.arg_for("-b")
    assert_true(barg is not None)
    carg = expl.arg_for("-c")
    assert_true(carg is not None)

def test_start_same():
    expl = explain.parse(SIMPLE_MAN, "fake", ["--something"])
    arg = expl.arg_for("--something")
    assert_equal([("--something", None)], arg.synonyms)
    assert_equal('Something starting with "something"', arg.description)

def test_start_same2():
    expl = explain.parse(SIMPLE_MAN, "fake", ["--something-else"])
    arg = expl.arg_for("--something-else")
    assert_equal([("--something-else", None)], arg.synonyms)
    assert_equal('Something else starting with "something"', arg.description)

def test_parse_long_single_dash():
    expl = explain.parse(SIMPLE_MAN, "fake", ["-long"])
    arg = expl.arg_for("-long")
    assert_equal([("-long", None)], arg.synonyms)
    assert_equal("A long, single-dash flag", arg.description)

def test_parse_space_after_flag():
    expl = explain.parse(SIMPLE_MAN, "fake", ["--space-after-flag"])
    arg = expl.arg_for("--space-after-flag")
    assert_equal("Documentation after a space", arg.description)

#### Real commands

def test_cp():
    _assert_explanation("cp -R -v -b src dest", """\
cp - copy files and directories
    -R, -r, --recursive
        copy directories recursively
    -v, --verbose
        explain what is being done
    -b
        like --backup but does not accept an argument
""")

def _assert_explanation(command_string, explanation):
    """Utility function that tests that the given command string
    produces the expected explanation"""
    argv = command_string.split(" ")
    out = io.StringIO()
    explain.explain(argv[0], argv[1:], out)
    assert_equal(explanation, out.getvalue())