def parse_functions(code): """ Parses code and returns a list of functions. Usage: For this function to work properly input code needs to be prepared first, function prepare_for_parsing(code) has to be called to pre-process the code first. Input arguments: code -- code from which we are parsing functions Output: List of functions. Each function has: type -- type of function (located from beginnig to ' ') name -- name of function (located between ' ' and '(') arguments -- list of arguments (located between '(' and ')' and separated by comma) Each argument has: type -- type of the argument name -- name of the argument array -- array lenght of argument (optional) Example: >>> code = '''actarray_t* actarray_init( ... file_t *file, ... int nb_actions); ... ... actarray_t* mixed_actarray_init( ... file_t **files, ... int nb_actions); ... ... typedef enum mode { ... NEVER = 0, ... ALWAYS = 2 ... } mode_t;''' >>> code = prepare_for_parsing(code) >>> print code actarray_t* actarray_init(file_t* file,int nb_actions); actarray_t* mixed_actarray_init(file_t** files,int nb_actions); typedef enum mode {NEVER = 0,ALWAYS = 2}mode_t; >>> print parse_functions(code) [{'type': 'actarray_t*', 'name': 'actarray_init', 'arguments': [{'type': 'file_t*', 'name': 'file'}, {'type': 'int', 'name': ' nb_actions'}]}, {'type': 'actarray_t*', 'name': 'mixed_actarray _init', 'arguments': [{'type': 'file_t**', 'name': 'files'}, {' type': 'int', 'name': 'nb_actions}]}] """ def parse_arguments(arguments): """ Parses arguments and returns a list of arguments Input arguments: arguments -- arguments which we are parsing Output: A list of arguments. Each argument has: type -- type of the argument name -- name of the argument array -- array lenght of argument (optional) Example: >>> arguments = 'file_t* file,int nb_actions' >>> print parse_element(element) [{'type': 'file_t*', 'name': 'file'}, {'type': 'int', 'name ': 'nb_actions'}] """ return [({ 'type': argument[:argument.rfind(' ')], 'name': argument[argument.rfind(' ') + 1:] } if ' ' in argument else { 'type': argument }) if '[' not in argument else { 'type': argument[:argument[:argument.find('[')].rfind(' ')], 'name': argument[argument[:argument.find('[')].rfind(' ') + 1:argument.find('[')], 'array': argument[argument.find('[') + 1:argument.find(']')] } for argument in arguments.split(',') if argument != ''] # remove same lines from code lines = remove_duplicates(code.splitlines()) return [ { 'type': line[:line[:line.find('(')].rfind(' ')], 'name': line[line[:line.find('(')].rfind(' ') + 1:line.find('(')], 'arguments': parse_arguments(line[line.find('(') + 1:line.find(')')]) } for line in lines if '(' in line # if 'typedef' not in line # line is a function if '{' not in line # if 'INIT_NAME' not in line # INIT_NAME not supported TODO if 'bindresvport6' not in line # bindresvport6 not supported TODO if 'cb_func' not in line # cb_func not supported TODO if '*__func' not in line # *__func not supported TODO if '_IO' not in line # _IO not supported TODO if '...' not in line ] # ... not supported TODO
def test_remove_duplicates_4(self): """remove_duplicates Unit test 4: Removing mixed duplicates""" input4 = ['a', 'a', '1', '1'] output4 = ['a', '1'] self.assertEqual(remove_duplicates(input4), output4)
def test_remove_duplicates_3(self): """remove_duplicates Unit test 3: No duplicates""" input3 = ['a', 'b', 'c'] output3 = ['a', 'b', 'c'] self.assertEqual(remove_duplicates(input3), output3)
def test_remove_duplicates_2(self): """remove_duplicates Unit test 2: Removing string duplicates""" input2 = ['a', 'b', 'c', 'c'] output2 = ['a', 'b', 'c'] self.assertEqual(remove_duplicates(input2), output2)
def test_remove_duplicates_1(self): """remove_duplicates Unit test 1: Removing int duplicates""" input1 = [1, 2, 2, 6, 4, 6, 1] output1 = [1, 2, 6, 4] self.assertEqual(remove_duplicates(input1), output1)
def parse_functions(code): """ Parses code and returns a list of functions. Usage: For this function to work properly input code needs to be prepared first, function prepare_for_parsing(code) has to be called to pre-process the code first. Input arguments: code -- code from which we are parsing functions Output: List of functions. Each function has: type -- type of function (located from beginnig to ' ') name -- name of function (located between ' ' and '(') arguments -- list of arguments (located between '(' and ')' and separated by comma) Each argument has: type -- type of the argument name -- name of the argument array -- array lenght of argument (optional) Example: >>> code = '''actarray_t* actarray_init( ... file_t *file, ... int nb_actions); ... ... actarray_t* mixed_actarray_init( ... file_t **files, ... int nb_actions); ... ... typedef enum mode { ... NEVER = 0, ... ALWAYS = 2 ... } mode_t;''' >>> code = prepare_for_parsing(code) >>> print code actarray_t* actarray_init(file_t* file,int nb_actions); actarray_t* mixed_actarray_init(file_t** files,int nb_actions); typedef enum mode {NEVER = 0,ALWAYS = 2}mode_t; >>> print parse_functions(code) [{'type': 'actarray_t*', 'name': 'actarray_init', 'arguments': [{'type': 'file_t*', 'name': 'file'}, {'type': 'int', 'name': ' nb_actions'}]}, {'type': 'actarray_t*', 'name': 'mixed_actarray _init', 'arguments': [{'type': 'file_t**', 'name': 'files'}, {' type': 'int', 'name': 'nb_actions}]}] """ def parse_arguments(arguments): """ Parses arguments and returns a list of arguments Input arguments: arguments -- arguments which we are parsing Output: A list of arguments. Each argument has: type -- type of the argument name -- name of the argument array -- array lenght of argument (optional) Example: >>> arguments = 'file_t* file,int nb_actions' >>> print parse_element(element) [{'type': 'file_t*', 'name': 'file'}, {'type': 'int', 'name ': 'nb_actions'}] """ return [({'type': argument[ : argument.rfind(' ')], 'name': argument[argument.rfind(' ') + 1 : ]} if ' ' in argument else {'type': argument}) if '[' not in argument else {'type': argument[ : argument[:argument.find('[')].rfind(' ')], 'name': argument[argument[:argument.find('[')].rfind(' ') + 1: argument.find('[')], 'array': argument[argument.find('[') + 1 : argument.find(']')]} for argument in arguments.split(',') if argument != ''] # remove same lines from code lines = remove_duplicates(code.splitlines()) return [{'type': line[ : line[ : line.find('(')].rfind(' ')], 'name': line[line[ : line.find('(')].rfind(' ') + 1 : line.find('(')], 'arguments': parse_arguments(line[line.find('(') + 1 : line.find(')')])} for line in lines if '(' in line # if 'typedef' not in line # line is a function if '{' not in line # if 'INIT_NAME' not in line # INIT_NAME not supported TODO if 'bindresvport6' not in line # bindresvport6 not supported TODO if 'cb_func' not in line # cb_func not supported TODO if '*__func' not in line # *__func not supported TODO if '_IO' not in line # _IO not supported TODO if '...' not in line] # ... not supported TODO