<commit_before>#!/usr/bin/env python
#
# Test major functions.
#
# In The following fields should be defined under the init() function of each test script:
#   param_test.list_fname_gt     list containing the relative file name for ground truth data. See test_sct_propseg
#
# Authors: <NAME>, <NAME>, <NAME>

# TODO: list functions to test in help (do a search in testing folder)
# TODO: find a way to be able to have list of arguments and loop across list elements.
# TODO: do something about this ugly 'output.nii.gz'

import sys, io, os, time, random, copy, shlex, importlib, multiprocessing

from pandas import DataFrame

from msct_parser import Parser
import sct_utils as sct

# get path of SCT
path_script = os.path.dirname(__file__)
path_sct = os.path.dirname(path_script)
sys.path.append(os.path.join(path_sct, 'testing'))


# Parameters
class Param:
    def __init__(self):
        self.download = 0
        self.path_data = 'sct_testing_data'  # path to the testing data
        self.path_output = []  # list of output folders
        self.function_to_test = None
        self.remove_tmp_file = 0
        self.verbose = 1
        self.path_tmp = None
        self.args = []  # list of input arguments to the function
        self.args_with_path = ''  # input arguments to the function, with path
        # self.list_fname_gt = []  # list of fname for ground truth data
        self.contrast = ''  # folder containing the data and corresponding to the contrast. Could be t2, t1, t2s, etc.
        self.output = ''  # output string
        self.results = ''  # results in Panda DataFrame
        self.redirect_stdout = True  # for debugging, set to 0. Otherwise set to 1.
        self.fname_log = None


# define nice colors
class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'


# PARSER
# ==========================================================================================
def get_parser():
    # initialize default param
    param_default = Param()
    # Initialize the parser
    parser = Parser(__file__)
    parser.usage.set_description(
        'Crash and integrity testing for functions of the Spinal Cord Toolbox. Internet connection is required for downloading testing data.')
    parser.add_option(name="-f",
                      type_value="str",
                      description="Test this specific script (do not add extension).",
                      mandatory=False,
                      example='sct_propseg')
    parser.add_option(name="-d",
                      type_value="multiple_choice",
                      description="Download testing data.",
                      mandatory=False,
                      default_value=param_default.download,
                      example=['0', '1'])
    parser.add_option(name="-p",
                      type_value="folder",
                      description='Path to testing data. NB: no need to set if using "-d 1"',
                      mandatory=False,
                      default_value=param_default.path_data)
    parser.add_option(name="-r",
                      type_value="multiple_choice",
                      description='Remove temporary files.',
                      mandatory=False,
                      default_value='1',
                      example=['0', '1'])
    parser.add_option(name="-j",
                      type_value="int",
                      description="# of simultaneous tests to run (jobs). -1 means # of cores",
                      mandatory=False,
                      default_value='1',
                      )
    return parser


def process_function(fname, param):
    """
    """
    param.function_to_test = fname
    # display script name
    # load modules of function to test
    module_testing = importlib.import_module('test_' + fname)
    # initialize default parameters of function to test
    param.args = []
    # param.list_fname_gt = []
    # param.fname_groundtruth = ''
    param = module_testing.init(param)
    # loop over parameters to test
    list_status_function = []
    list_output = []
    for i in range(0, len(param.args)):
        param_test = copy.deepcopy(param)
        param_test.default_args = param.args
        param_test.args = param.args[i]
        param_test.test_integrity = True
        # if list_fname_gt is not empty, assign it
        # if param_test.list_fname_gt:
        #     param_test.fname_gt = param_test.list_fname_gt[i]
        # test function
        try:
            param_test = test_function(param_test)
        except Exception as e:
            list_status_function.append(1)
            list_output.append("TODO exception: %s" % e)
        else:
            list_status_function.append(param_test.status)
            list_output.append(param_test.output)

    return list_output, list_status_function

# Main
# ==========================================================================================
def main(args=None):

    # initializations
    list_status = []
    param = Param()

    # check user arguments
    if args is None:
        args = sys.argv[1:]

    # get parser info
    parser = get_parser()
    arguments = parser.parse(args)
    if '-d' in arguments:
        param.download = int(arguments['-d'])
    if '-p' in arguments:
        param.path_data = arguments['-p']
    if '-f' in arguments:
        param.function_to_test = arguments['-f']
    if '-r' in arguments:
        param.remove_tmp_file = int(arguments['-r'])

    jobs = int(arguments.get("-j", 1))
    if jobs > 0:
        pass
    elif jobs == -1:
        jobs = None
    else:
        sct.log("Command-line usage error: -j takes a value >= -1", type="error")

    # path_data = param.path_data
    function_to_test = param.function_to_test

    start_time = time.time()

    # get absolute path and add slash at the end
    param.path_data = os.path.abspath(param.path_data)

    # check existence of testing data folder
    if not os.path.isdir(param.path_data) or param.download:
        downloaddata(param)

    # display path to data
    sct.printv('\nPath to testing data: ' + param.path_data, param.verbose)

    # create temp folder that will have all results and go in it
    param.path_tmp = sct.tmp_create(verbose=0)
    curdir = os.getcwd()
    os.chdir(param.path_tmp)

    # get list of all scripts to test
    list_functions = fill_functions()
    if function_to_test:
        if function_to_test in list_functions:
            # overwrite variable to include only the function to test
            list_functions = [function_to_test]
        else:
            sct.printv('ERROR: Function "%s" is not part of the list of testing functions' % function_to_test, type='error')<commit_msg>sct_testing: use argparse<commit_after>#!/usr/bin/env python
#
# Test major functions.
#
# In The following fields should be defined under the init() function of each test script:
#   param_test.list_fname_gt     list containing the relative file name for ground truth data. See test_sct_propseg
#
# Authors: <NAME>, <NAME>, <NAME>

# TODO: list functions to test in help (do a search in testing folder)
# TODO: find a way to be able to have list of arguments and loop across list elements.
# TODO: do something about this ugly 'output.nii.gz'

import sys, io, os, time, random, copy, shlex, importlib, multiprocessing

from pandas import DataFrame

from msct_parser import Parser
import sct_utils as sct

# get path of SCT
path_script = os.path.dirname(__file__)
path_sct = os.path.dirname(path_script)
sys.path.append(os.path.join(path_sct, 'testing'))


# Parameters
class Param:
    def __init__(self):
        self.download = 0
        self.path_data = 'sct_testing_data'  # path to the testing data
        self.path_output = []  # list of output folders
        self.function_to_test = None
        self.remove_tmp_file = 0
        self.verbose = 1
        self.path_tmp = None
        self.args = []  # list of input arguments to the function
        self.args_with_path = ''  # input arguments to the function, with path
        # self.list_fname_gt = []  # list of fname for ground truth data
        self.contrast = ''  # folder containing the data and corresponding to the contrast. Could be t2, t1, t2s, etc.
        self.output = ''  # output string
        self.results = ''  # results in Panda DataFrame
        self.redirect_stdout = True  # for debugging, set to 0. Otherwise set to 1.
        self.fname_log = None


# define nice colors
class bcolors:
    HEADER = '\033[95m'
    OKBLUE = '\033[94m'
    OKGREEN = '\033[92m'
    WARNING = '\033[93m'
    FAIL = '\033[91m'
    ENDC = '\033[0m'


# PARSER
# ==========================================================================================
def get_parser():
    import argparse

    param_default = Param()

    parser = argparse.ArgumentParser(
     description="Crash and integrity testing for functions of the Spinal Cord Toolbox. Internet connection is required for downloading testing data.",
    )

    parser.add_argument("--function", "-f",
     help="Test this specific script (eg. 'sct_propseg').",
     nargs="+",
    )

    def arg_jobs(s):
        jobs = int(s)
        if jobs > 0:
            pass
        elif jobs == -1:
            jobs = None
        else:
            raise ValueError()
        return jobs

    parser.add_argument("--download", "-d",
     choices=("0", "1"),
     default=param_default.download,
    )
    parser.add_argument("--path", "-p",
     help='Path to testing data. NB: no need to set if using "-d 1"',
     default=param_default.path_data,
    )
    parser.add_argument("--remove-temps", "-r",
     choices=("0", "1"),
     help='Remove temporary files.',
     default=param_default.remove_tmp_file,
    )
    parser.add_argument("--jobs", "-j",
     type=arg_jobs,
     help="# of simultaneous tests to run (jobs). -1 means # of cores",
     default=arg_jobs(-1),
    )

    return parser


def process_function(fname, param):
    """
    """
    param.function_to_test = fname
    # display script name
    # load modules of function to test
    module_testing = importlib.import_module('test_' + fname)
    # initialize default parameters of function to test
    param.args = []
    # param.list_fname_gt = []
    # param.fname_groundtruth = ''
    param = module_testing.init(param)
    # loop over parameters to test
    list_status_function = []
    list_output = []
    for i in range(0, len(param.args)):
        param_test = copy.deepcopy(param)
        param_test.default_args = param.args
        param_test.args = param.args[i]
        param_test.test_integrity = True
        # if list_fname_gt is not empty, assign it
        # if param_test.list_fname_gt:
        #     param_test.fname_gt = param_test.list_fname_gt[i]
        # test function
        try:
            param_test = test_function(param_test)
        except Exception as e:
            list_status_function.append(1)
            list_output.append("TODO exception: %s" % e)
        else:
            list_status_function.append(param_test.status)
            list_output.append(param_test.output)

    return list_output, list_status_function

# Main
# ==========================================================================================
def main(args=None):

    # initializations
    list_status = []
    param = Param()

    # check user arguments
    if args is None:
        args = sys.argv[1:]

    # get parser info
    parser = get_parser()

    arguments = parser.parse_args(args)

    param.download = int(arguments.download)
    param.path_data = arguments.path
    functions_to_test = arguments.function
    param.remove_tmp_file = int(arguments.remove_temps)
    jobs = arguments.jobs

    start_time = time.time()

    # get absolute path and add slash at the end
    param.path_data = os.path.abspath(param.path_data)

    # check existence of testing data folder
    if not os.path.isdir(param.path_data) or param.download:
        downloaddata(param)

    # display path to data
    sct.printv('\nPath to testing data: ' + param.path_data, param.verbose)

    # create temp folder that will have all results and go in it
    param.path_tmp = sct.tmp_create(verbose=0)
    curdir = os.getcwd()
    os.chdir(param.path_tmp)

    # get list of all scripts to test
    list_functions = fill_functions()
    if functions_to_test:
        for f in functions_to_test:
            if f not in list_functions:
                sct.printv('Command-line usage error: Function "%s" is not part of the list of testing functions' % function_to_test, type='error')
        list_functions = functions_to_test
{'fraction_non_alphanumeric': 0.12245058666036696, 'fraction_numerical': 0.008110874872037169, 'mean_word_length': 2.532684283727399, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 15, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '884012', 'n_tokens_mistral': 3796, 'n_tokens_neox': 3638, 'n_words': 1070}