#!/usr/bin/env python
"""
Generates a bash script, that executes py.test or nosetest on each file
individually.

Usage and help:

    $ bin/test_isolated -h

and read the instructions.
"""

from __future__ import print_function

from os import chmod, getcwd
from glob import glob
from optparse import OptionParser
from stat import S_IREAD, S_IWRITE, S_IXUSR, S_IRGRP, S_IROTH, S_IXGRP, S_IXOTH

filemode = S_IREAD | S_IWRITE | S_IXUSR | S_IRGRP | S_IROTH | S_IXGRP | S_IXOTH


def get_paths(level=6):
    """
    Generates a set of paths for testfiles searching.

    Example:
    >>> get_paths(2)
    ['sympy/test_*.py', 'sympy/*/test_*.py', 'sympy/*/*/test_*.py']
    >>> get_paths(6)
    ['sympy/test_*.py', 'sympy/*/test_*.py', 'sympy/*/*/test_*.py',
    'sympy/*/*/*/test_*.py', 'sympy/*/*/*/*/test_*.py',
    'sympy/*/*/*/*/*/test_*.py', 'sympy/*/*/*/*/*/*/test_*.py']
    """
    wildcards = ["/"]
    for i in range(level):
        wildcards.append(wildcards[-1] + "*/")
    my_dir = getcwd()
    p = [my_dir + "/sympy" + x + "test_*.py" for x in wildcards]
    return p


def generate_test_script1(testlib="py.test"):
    """Generates a bash script for doing the test.

    "testlib" is the name of the executable, that is going to execute the test,
    for example "py.test" or "nosetests".
    """
    g = []
    for x in get_paths(10):
        g.extend(glob(x))
    with open("/tmp/test_sympy.sh", "w") as f:
        f.write("#! /bin/sh\n")
        f.write("# Autogenerated script for a reliable test of SymPy.\n")
        f.write("# Execute with 'sh test_sympy.sh' (in any directory).\n\n")
        for x in g:
            f.write(testlib + " " + x + "\n")
        chmod(f.name, filemode)


def generate_test_script2(testlib="nosetests"):
    """Generates a bash script for doing the test.

    "testlib" is the name of the executable, that is going to execute the test,
    for example "py.test" or "nosetests".
    """
    g = []
    for x in get_paths(10):
        g.extend(glob(x))
    with open("/tmp/test_sympy.sh", "w") as f:
        f.write("#! /bin/sh\n")
        f.write("# Autogenerated script for a reliable test of SymPy.\n")
        f.write("# Execute with 'sh test_sympy.sh' (in any directory).\n\n")
        for x in g:
            f.write(testlib + " " + x + " && \\\n")
        f.write("echo 'all tests passed, ok to commit'")
        chmod(f.name, filemode)

usage = """%prog [options]

Generates a bash script, that executes py.test or nosetest on each file
individually.

Usage:

    $ bin/test_isolated
    Generating py.test isolated testsuite...
    Done. Run (search for 'COMMIT' in the less environment):
    /tmp/test_sympy.sh | less
    $ /tmp/test_sympy.sh | less

Let the tests run and then search if any test failed (it will write DO NOT
COMMIT), so search for COMMIT."""


def main():
    parser = OptionParser(usage=usage)
    parser.add_option("-p", "--py.test", action="store_false", dest="nosetests",
            help="Use py.test (default)")
    parser.add_option("-n", "--nosetests", action="store_true", dest="nosetests",
            help="Use nosetests")
    parser.add_option("-q", "--quiet", action="store_false", dest="verbose")
    parser.set_defaults(nosetests=False, verbose=True)

    options, args = parser.parse_args()
    if len(args) != 0:
        parser.error("too many arguments")
    if options.nosetests:
        if options.verbose:
            print("Generating nosetests isolated testsuite...")
        generate_test_script2("nosetests")
    else:
        if options.verbose:
            print("Generating py.test isolated testsuite...")
        generate_test_script1("py.test")
    if options.verbose:
        print("Done. Run (search for 'COMMIT' in the less environment):")
        print("/tmp/test_sympy.sh | less")

if __name__ == "__main__":
    main()
