from collections import OrderedDict
from frank.frank import parse_yaml, ordered_load, run_action
from frank.frank import Shell

test_yaml = """
    commands:
     - test
     - build_sphinx
     - publish

    test:
     shell:
      - pip install -e .
      - python setup.py test

    build_sphinx:
      shell:
       cwd: docs
       cmd: make html
    """


def mk_yaml():
    with open('.frank.yaml', 'w') as f:
        f.write(test_yaml)

mk_yaml()


def test_parse_yaml():
    y = parse_yaml('.')
    assert isinstance(y, dict)


def test_ordered_load():
    ans = ordered_load("""
    commands:
     - test
     - build_sphinx
     - publish""")

    assert isinstance(ans['commands'], list)
    ans = ordered_load("""
    commands:
     - test
     - build_sphinx
     - publish

    test:
     shell:
      - pip install -e .
      - python setup.py test
     """)
    assert isinstance(ans['test'], OrderedDict)
    assert isinstance(ans['test']['shell'], list)

    # If 'shell' is a list run the commands as ordered

    ans = ordered_load("""
    commands:
     - test
     - build_sphinx
     - publish

    test:
     shell:
      - pip install -e .
      - python setup.py test

    build_sphinx:
      shell:
       cwd: docs
       cmd: make html
    """)
    assert isinstance(ans['test']['shell'], list)
    assert isinstance(ans['build_sphinx'], OrderedDict)
    assert isinstance(ans['build_sphinx']['shell'], OrderedDict)
    # If 'shell' is an OrderedDict run the command with the keywords given


def test_Shell_run():
    sh = Shell()
    sh.run('ls -l', cwd='/tmp/')
    assert not sh.code
    assert isinstance(sh.output(), list)
    sh = Shell()
    sh.run('ls -l', cwd='/no-such-directory/')
    assert sh.pid is None
    assert isinstance(sh.exception, OSError)


def test_run_action_shell():
    # test shell commands
    axn = ['shell', 'touch /tmp/testaxn', 'touch /tmp/testaxn2',
           'rm /tmp/testaxn']
    results = run_action(axn)

    # all these commands should have succeeded
    assert not any([result.code for result in results])
    axn = ['shell', 'touch /nosuchdir/testaxn', 'touch /tmp/testaxn2',
           'rm /tmp/testaxn']
    results = run_action(axn)
    assert len(results) == 1
    assert results[0].code == 1
    axn = ['shell', 'touch /tmp/works', 'touch /nosuchdir/fails',
           'touch /tmp/testaxn2', 'rm /tmp/testaxn']
    results = run_action(axn)
    assert len(results) == 2
    assert results[0].code == 0
    assert results[1].code == 1


def test_run_action_shell_with_kwargs():
    # test shell commands
    axn = OrderedDict([('shell', OrderedDict([('cwd', 'tmp'),
                      ('cmd', 'touch foo')]))])
    results = run_action(axn)
    assert len(results) == 1
    assert results[0].code == 0
    axn = OrderedDict([('shell', OrderedDict([('cwd', 'nosuchdir'),
                      ('cmd', 'touch foo')]))])
    results = run_action(axn)
    assert len(results) == 1
    assert isinstance(results[0].exception, OSError)
    axn = OrderedDict([('shell', OrderedDict([('cwd', '/tmp'),
        ('cmd', 'touch /nosuchdir/foo')]))])
    results = run_action(axn)
    assert len(results) == 1
    assert results[0].code == 1
    # missing arguments to touch
    axn = OrderedDict([('shell', OrderedDict([('cwd', '/tmp'),
        ('cmd', 'touch')]))])
    assert len(results) == 1
    assert results[0].code == 1
    assert ['touch: missing file operand',
            "Try 'touch --help' for more information."] == \
                 results[0].errors()

def test_run_python_code():
    import sys
    import os
    sys.path.insert(0, os.path.dirname(__file__))
    od = ordered_load("""
    run_function_python:
      python:
        - dummy_code:do_something
        - dummy_code:do_something_else
    """)
    results = run_action(od['run_function_python'])
    assert len(results) == 2
    assert isinstance(results[-1].code, AttributeError)