From fea11ec4048383e5650489c3b99fc04fb70d2d5b Mon Sep 17 00:00:00 2001 From: chriskiehl Date: Thu, 24 Dec 2015 16:48:51 -0500 Subject: [PATCH] Removed outdated files --- gooey/python_bindings/code_prep.py | 61 --- gooey/python_bindings/codegen.py | 578 ------------------------- gooey/python_bindings/source_parser.py | 171 -------- gooey/tests/code_prep_unittest.py | 55 --- 4 files changed, 865 deletions(-) delete mode 100644 gooey/python_bindings/code_prep.py delete mode 100644 gooey/python_bindings/codegen.py delete mode 100644 gooey/python_bindings/source_parser.py delete mode 100644 gooey/tests/code_prep_unittest.py diff --git a/gooey/python_bindings/code_prep.py b/gooey/python_bindings/code_prep.py deleted file mode 100644 index 34b13ef..0000000 --- a/gooey/python_bindings/code_prep.py +++ /dev/null @@ -1,61 +0,0 @@ -__author__ = 'Chris' - -""" -Preps the extracted Python code so that it can be evaled by the -monkey_parser -""" - -from itertools import * - -source = ''' -import sys -import os -import doctest -import cProfile -import pstats -from argparse import ArgumentParser -from argparse import RawDescriptionHelpFormatter -from gooey import Gooey -parser = ArgumentParser(description='Example Argparse Program', formatter_class=RawDescriptionHelpFormatter) -parser.add_argument('filename', help='filename') -parser.add_argument('-r', '--recursive', dest='recurse', action='store_true', help='recurse into subfolders [default: %(default)s]') -parser.add_argument('-v', '--verbose', dest='verbose', action='count', help='set verbosity level [default: %(default)s]') -parser.add_argument('-i', '--include', action='append', help='only include paths matching this regex pattern. Note: exclude is given preference over include. [default: %(default)s]', metavar='RE') -parser.add_argument('-m', '--mycoolargument', help='mycoolargument') -parser.add_argument('-e', '--exclude', dest='exclude', help='exclude paths matching this regex pattern. [default: %(default)s]', metavar='RE') -parser.add_argument('-V', '--version', action='version') -parser.add_argument('-T', '--tester', choices=['yes', 'no']) -parser.add_argument(dest='paths', help='paths to folder(s) with source file(s) [default: %(default)s]', metavar='path', nargs='+') -''' - -def take_imports(code): - return takewhile(lambda line: 'import' in line, code) - -def drop_imports(code): - return dropwhile(lambda line: 'import' in line, code) - -def split_line(line): - # splits an assignment statement into varname and command strings - # in: "parser = ArgumentParser(description='Example Argparse Program')" - # out: "parser", "ArgumentParser(description='Example Argparse Program" - variable, instruction = line.split('=', 1) - return variable.strip(), instruction.strip() - -def update_parser_varname(new_varname, code): - # lines = source.split('\n')[1:] - lines = filter(lambda x: x != '', code) - - argparse_code = dropwhile(lambda line: 'import' in line, lines) - old_argparser_varname, _ = split_line(argparse_code.next()) - - updated_code = [line.replace(old_argparser_varname, new_varname) - for line in lines] - return updated_code - -if __name__ == '__main__': - pass - - - - - diff --git a/gooey/python_bindings/codegen.py b/gooey/python_bindings/codegen.py deleted file mode 100644 index a9f1ab4..0000000 --- a/gooey/python_bindings/codegen.py +++ /dev/null @@ -1,578 +0,0 @@ -# -*- coding: utf-8 -*- -""" - codegen - ~~~~~~~ - - Extension to ast that allow ast -> python code generation. - - :copyright: Copyright 2008 by Armin Ronacher. - :license: BSD. -""" -from ast import * - - -BOOLOP_SYMBOLS = { - And: 'and', - Or: 'or' -} - -BINOP_SYMBOLS = { - Add: '+', - Sub: '-', - Mult: '*', - Div: '/', - FloorDiv: '//', - Mod: '%', - LShift: '<<', - RShift: '>>', - BitOr: '|', - BitAnd: '&', - BitXor: '^' -} - -CMPOP_SYMBOLS = { - Eq: '==', - Gt: '>', - GtE: '>=', - In: 'in', - Is: 'is', - IsNot: 'is not', - Lt: '<', - LtE: '<=', - NotEq: '!=', - NotIn: 'not in' -} - -UNARYOP_SYMBOLS = { - Invert: '~', - Not: 'not', - UAdd: '+', - USub: '-' -} - -ALL_SYMBOLS = {} -ALL_SYMBOLS.update(BOOLOP_SYMBOLS) -ALL_SYMBOLS.update(BINOP_SYMBOLS) -ALL_SYMBOLS.update(CMPOP_SYMBOLS) -ALL_SYMBOLS.update(UNARYOP_SYMBOLS) - - -def to_source(node, indent_with=' ' * 4, add_line_information=False): - """This function can convert a node tree back into python sourcecode. - This is useful for debugging purposes, especially if you're dealing with - custom asts not generated by python itself. - - It could be that the sourcecode is evaluable when the AST itself is not - compilable / evaluable. The reason for this is that the AST contains some - more data than regular sourcecode does, which is dropped during - conversion. - - Each level of indentation is replaced with `indent_with`. Per default this - parameter is equal to four spaces as suggested by PEP 8, but it might be - adjusted to match the application's styleguide. - - If `add_line_information` is set to `True` comments for the line numbers - of the nodes are added to the output. This can be used to spot wrong line - number information of statement nodes. - """ - generator = SourceGenerator(indent_with, add_line_information) - generator.visit(node) - return ''.join(str(s) for s in generator.result) - - -class SourceGenerator(NodeVisitor): - """This visitor is able to transform a well formed syntax tree into python - sourcecode. For more details have a look at the docstring of the - `node_to_source` function. - """ - - def __init__(self, indent_with, add_line_information=False): - self.result = [] - self.indent_with = indent_with - self.add_line_information = add_line_information - self.indentation = 0 - self.new_lines = 0 - - def write(self, x): - if self.new_lines: - if self.result: - self.result.append('\n' * self.new_lines) - self.result.append(self.indent_with * self.indentation) - self.new_lines = 0 - self.result.append(x) - - def newline(self, node=None, extra=0): - self.new_lines = max(self.new_lines, 1 + extra) - if node is not None and self.add_line_information: - self.write('# line: %s' % node.lineno) - self.new_lines = 1 - - def body(self, statements): - self.new_line = True - self.indentation += 1 - for stmt in statements: - self.visit(stmt) - self.indentation -= 1 - - def body_or_else(self, node): - self.body(node.body) - if node.orelse: - self.newline() - self.write('else:') - self.body(node.orelse) - - def signature(self, node): - want_comma = [] - - def write_comma(): - if want_comma: - self.write(', ') - else: - want_comma.append(True) - - padding = [None] * (len(node.args) - len(node.defaults)) - for arg, default in zip(node.args, padding + node.defaults): - write_comma() - self.visit(arg) - if default is not None: - self.write('=') - self.visit(default) - if node.vararg is not None: - write_comma() - self.write('*' + node.vararg) - if node.kwarg is not None: - write_comma() - self.write('**' + node.kwarg) - - def decorators(self, node): - for decorator in node.decorator_list: - self.newline(decorator) - self.write('@') - self.visit(decorator) - - # Statements - - def visit_Assign(self, node): - self.newline(node) - for idx, target in enumerate(node.targets): - if idx: - self.write(', ') - self.visit(target) - self.write(' = ') - self.visit(node.value) - - def visit_AugAssign(self, node): - self.newline(node) - self.visit(node.target) - self.write(BINOP_SYMBOLS[type(node.op)] + '=') - self.visit(node.value) - - def visit_ImportFrom(self, node): - self.newline(node) - self.write('from %s%s import ' % ('.' * node.level, node.module)) - for idx, item in enumerate(node.names): - if idx: - self.write(', ') - self.write(item.name) - - def visit_Import(self, node): - self.newline(node) - for item in node.names: - self.write('import ') - self.visit(item) - - def visit_Expr(self, node): - self.newline(node) - self.generic_visit(node) - - def visit_FunctionDef(self, node): - self.newline(extra=1) - self.decorators(node) - self.newline(node) - self.write('def %s(' % node.name) - self.signature(node.args) - self.write('):') - self.body(node.body) - - def visit_ClassDef(self, node): - have_args = [] - - def paren_or_comma(): - if have_args: - self.write(', ') - else: - have_args.append(True) - self.write('(') - - self.newline(extra=2) - self.decorators(node) - self.newline(node) - self.write('class %s' % node.name) - for base in node.bases: - paren_or_comma() - self.visit(base) - # XXX: the if here is used to keep this module compatible - # with python 2.6. - if hasattr(node, 'keywords'): - for keyword in node.keywords: - paren_or_comma() - self.write(keyword.arg + '=') - self.visit(keyword.value) - if node.starargs is not None: - paren_or_comma() - self.write('*') - self.visit(node.starargs) - if node.kwargs is not None: - paren_or_comma() - self.write('**') - self.visit(node.kwargs) - self.write(have_args and '):' or ':') - self.body(node.body) - - def visit_If(self, node): - self.newline(node) - self.write('if ') - self.visit(node.test) - self.write(':') - self.body(node.body) - while True: - else_ = node.orelse - if len(else_) == 1 and isinstance(else_[0], If): - node = else_[0] - self.newline() - self.write('elif ') - self.visit(node.test) - self.write(':') - self.body(node.body) - else: - self.newline() - self.write('else:') - self.body(else_) - break - - def visit_For(self, node): - self.newline(node) - self.write('for ') - self.visit(node.target) - self.write(' in ') - self.visit(node.iter) - self.write(':') - self.body_or_else(node) - - def visit_While(self, node): - self.newline(node) - self.write('while ') - self.visit(node.test) - self.write(':') - self.body_or_else(node) - - def visit_With(self, node): - self.newline(node) - self.write('with ') - self.visit(node.context_expr) - if node.optional_vars is not None: - self.write(' as ') - self.visit(node.optional_vars) - self.write(':') - self.body(node.body) - - def visit_Pass(self, node): - self.newline(node) - self.write('pass') - - def visit_Print(self, node): - # XXX: python 2.6 only - self.newline(node) - self.write('print ') - want_comma = False - if node.dest is not None: - self.write(' >> ') - self.visit(node.dest) - want_comma = True - for value in node.values: - if want_comma: - self.write(', ') - self.visit(value) - want_comma = True - if not node.nl: - self.write(',') - - def visit_Delete(self, node): - self.newline(node) - self.write('del ') - for idx, target in enumerate(node): - if idx: - self.write(', ') - self.visit(target) - - def visit_TryExcept(self, node): - self.newline(node) - self.write('try:') - self.body(node.body) - for handler in node.handlers: - self.visit(handler) - - def visit_TryFinally(self, node): - self.newline(node) - self.write('try:') - self.body(node.body) - self.newline(node) - self.write('finally:') - self.body(node.finalbody) - - def visit_Global(self, node): - self.newline(node) - self.write('global ' + ', '.join(node.names)) - - def visit_Nonlocal(self, node): - self.newline(node) - self.write('nonlocal ' + ', '.join(node.names)) - - def visit_Return(self, node): - self.newline(node) - if node.value: - self.write('return ') - self.visit(node.value) - else: - self.write('return') - - def visit_Break(self, node): - self.newline(node) - self.write('break') - - def visit_Continue(self, node): - self.newline(node) - self.write('continue') - - def visit_Raise(self, node): - # XXX: Python 2.6 / 3.0 compatibility - self.newline(node) - self.write('raise') - if hasattr(node, 'exc') and node.exc is not None: - self.write(' ') - self.visit(node.exc) - if node.cause is not None: - self.write(' from ') - self.visit(node.cause) - elif hasattr(node, 'type') and node.type is not None: - self.visit(node.type) - if node.inst is not None: - self.write(', ') - self.visit(node.inst) - if node.tback is not None: - self.write(', ') - self.visit(node.tback) - - # Expressions - - def visit_Attribute(self, node): - self.visit(node.value) - self.write('.' + node.attr) - - def visit_Call(self, node): - want_comma = [] - - def write_comma(): - if want_comma: - self.write(', ') - else: - want_comma.append(True) - - self.visit(node.func) - self.write('(') - for arg in node.args: - write_comma() - self.visit(arg) - for keyword in node.keywords: - write_comma() - self.write(keyword.arg + '=') - self.visit(keyword.value) - if node.starargs is not None: - write_comma() - self.write('*') - self.visit(node.starargs) - if node.kwargs is not None: - write_comma() - self.write('**') - self.visit(node.kwargs) - self.write(')') - - def visit_Name(self, node): - self.write(node.id) - - def visit_Str(self, node): - self.write(repr(node.s)) - - def visit_Bytes(self, node): - self.write(repr(node.s)) - - def visit_Num(self, node): - self.write(repr(node.n)) - - def visit_Tuple(self, node): - self.write('(') - idx = -1 - for idx, item in enumerate(node.elts): - if idx: - self.write(', ') - self.visit(item) - self.write(idx and ')' or ',)') - - def sequence_visit(left, right): - def visit(self, node): - self.write(left) - for idx, item in enumerate(node.elts): - if idx: - self.write(', ') - self.visit(item) - self.write(right) - return visit - - visit_List = sequence_visit('[', ']') - visit_Set = sequence_visit('{', '}') - del sequence_visit - - def visit_Dict(self, node): - self.write('{') - for idx, (key, value) in enumerate(zip(node.keys, node.values)): - if idx: - self.write(', ') - self.visit(key) - self.write(': ') - self.visit(value) - self.write('}') - - def visit_BinOp(self, node): - self.visit(node.left) - self.write(' %s ' % BINOP_SYMBOLS[type(node.op)]) - self.visit(node.right) - - def visit_BoolOp(self, node): - self.write('(') - for idx, value in enumerate(node.values): - if idx: - self.write(' %s ' % BOOLOP_SYMBOLS[type(node.op)]) - self.visit(value) - self.write(')') - - def visit_Compare(self, node): - self.write('(') - self.write(node.left) - for op, right in zip(node.ops, node.comparators): - self.write(' %s %%' % CMPOP_SYMBOLS[type(op)]) - self.visit(right) - self.write(')') - - def visit_UnaryOp(self, node): - self.write('(') - op = UNARYOP_SYMBOLS[type(node.op)] - self.write(op) - if op == 'not': - self.write(' ') - self.visit(node.operand) - self.write(')') - - def visit_Subscript(self, node): - self.visit(node.value) - self.write('[') - self.visit(node.slice) - self.write(']') - - def visit_Slice(self, node): - if node.lower is not None: - self.visit(node.lower) - self.write(':') - if node.upper is not None: - self.visit(node.upper) - if node.step is not None: - self.write(':') - if not (isinstance(node.step, Name) and node.step.id == 'None'): - self.visit(node.step) - - def visit_ExtSlice(self, node): - for idx, item in node.dims: - if idx: - self.write(', ') - self.visit(item) - - def visit_Yield(self, node): - self.write('yield ') - self.visit(node.value) - - def visit_Lambda(self, node): - self.write('lambda ') - self.signature(node.args) - self.write(': ') - self.visit(node.body) - - def visit_Ellipsis(self, node): - self.write('Ellipsis') - - def generator_visit(left, right): - def visit(self, node): - self.write(left) - self.visit(node.elt) - for comprehension in node.generators: - self.visit(comprehension) - self.write(right) - return visit - - visit_ListComp = generator_visit('[', ']') - visit_GeneratorExp = generator_visit('(', ')') - visit_SetComp = generator_visit('{', '}') - del generator_visit - - def visit_DictComp(self, node): - self.write('{') - self.visit(node.key) - self.write(': ') - self.visit(node.value) - for comprehension in node.generators: - self.visit(comprehension) - self.write('}') - - def visit_IfExp(self, node): - self.visit(node.body) - self.write(' if ') - self.visit(node.test) - self.write(' else ') - self.visit(node.orelse) - - def visit_Starred(self, node): - self.write('*') - self.visit(node.value) - - def visit_Repr(self, node): - # XXX: python 2.6 only - self.write('`') - self.visit(node.value) - self.write('`') - - # Helper Nodes - - def visit_alias(self, node): - self.write(node.name) - if node.asname is not None: - self.write(' as ' + node.asname) - - def visit_comprehension(self, node): - self.write(' for ') - self.visit(node.target) - self.write(' in ') - self.visit(node.iter) - if node.ifs: - for if_ in node.ifs: - self.write(' if ') - self.visit(if_) - - def visit_excepthandler(self, node): - self.newline(node) - self.write('except') - if node.type is not None: - self.write(' ') - self.visit(node.type) - if node.name is not None: - self.write(' as ') - self.visit(node.name) - self.write(':') - self.body(node.body) \ No newline at end of file diff --git a/gooey/python_bindings/source_parser.py b/gooey/python_bindings/source_parser.py deleted file mode 100644 index 351378f..0000000 --- a/gooey/python_bindings/source_parser.py +++ /dev/null @@ -1,171 +0,0 @@ -''' -Created on Dec 11, 2013 - -@author: Chris - -Collection of functions for extracting argparse related statements from the -client code. -''' - -import re -import os -import ast -import _ast -from itertools import * - -from gooey.python_bindings import codegen, modules - - -def parse_source_file(file_name): - """ - Parses the AST of Python file for lines containing - references to the argparse module. - - returns the collection of ast objects found. - - Example client code: - - 1. parser = ArgumentParser(desc="My help Message") - 2. parser.add_argument('filename', help="Name of the file to load") - 3. parser.add_argument('-f', '--format', help='Format of output \nOptions: ['md', 'html'] - 4. args = parser.parse_args() - - Variables: - * nodes Primary syntax tree object - * argparse_assignments The assignment of the ArgumentParser (line 1 in example code) - * add_arg_assignments Calls to add_argument() (lines 2-3 in example code) - * parser_var_name The instance variable of the ArgumentParser (line 1 in example code) - * ast_source The curated collection of all parser related nodes in the client code - """ - - nodes = ast.parse(_openfile(file_name)) - - module_imports = get_nodes_by_instance_type(nodes, _ast.Import) - specific_imports = get_nodes_by_instance_type(nodes, _ast.ImportFrom) - - assignment_objs = get_nodes_by_instance_type(nodes, _ast.Assign) - call_objects = get_nodes_by_instance_type(nodes, _ast.Call) - - argparse_assignments = get_nodes_by_containing_attr(assignment_objs, 'ArgumentParser') - add_arg_assignments = get_nodes_by_containing_attr(call_objects, 'add_argument') - parse_args_assignment = get_nodes_by_containing_attr(call_objects, 'parse_args') - - ast_argparse_source = chain( - module_imports, - specific_imports, - argparse_assignments, - add_arg_assignments - # parse_args_assignment - ) - return ast_argparse_source - -def _openfile(file_name): - with open(file_name, 'rb') as f: - return f.read() - -def read_client_module(filename): - with open(filename, 'r') as f: - return f.readlines() - -def get_nodes_by_instance_type(nodes, object_type): - return [node for node in walk_tree(nodes) if isinstance(node, object_type)] - -def get_nodes_by_containing_attr(nodes, attr): - return [node for node in nodes if attr in walk_tree(node)] - -def walk_tree(node): - yield node - d = node.__dict__ - for key, value in d.iteritems(): - if isinstance(value, list): - for val in value: - for _ in walk_tree(val): yield _ - elif 'ast' in str(type(value)): - for _ in walk_tree(value): yield _ - else: - yield value - - -def convert_to_python(ast_source): - """ - Converts the ast objects back into human readable Python code - """ - return map(codegen.to_source, ast_source) - -def get_assignment_name(lines): - nodes = ast.parse(''.join(lines)) - assignments = get_nodes_by_instance_type(nodes, _ast.Assign) - argparse_var = get_nodes_by_containing_attr(assignments, 'parse_args') - return argparse_var[0].value.func.value.id - - -def lines_indented(line): - unindented = re.compile("^[a-zA-Z0-9_@]+") - return unindented.match(line) is None - -def not_at_main(line): - return 'def main' not in line - -def not_at_parse_args(line): - return 'parse_args(' not in line - -def get_indent(line): - indent = re.compile("(\t|\s)") - return ''.join(takewhile(lambda char: indent.match(char) is not None, line)) - -def format_source_to_return_parser(source, cutoff_line, restart_line, col_offset, parser_name): - top = source[:cutoff_line - 1] - bottom = source[restart_line:] - indentation = source[cutoff_line - 1][:col_offset] - return_statement = ['{}return {}\n\n'.format(indentation, parser_name)] - - # stitch it all back together excluding the Gooey decorator - new_source = (line for line in chain(top, return_statement, bottom) - if '@gooey' not in line.lower()) - - return ''.join(new_source) - -def extract_parser(modulepath, func_with_argparse): - source = read_client_module(modulepath) - - nodes = ast.parse(''.join(source)) - funcs = get_nodes_by_instance_type(nodes, _ast.FunctionDef) - assignment_objs = get_nodes_by_instance_type(nodes, _ast.Assign) - - main_func = get_nodes_by_containing_attr(funcs, func_with_argparse)[0] - parse_args_assignment = get_nodes_by_containing_attr(main_func.body, 'parse_args')[0] - - # ast reports the line no of a block structure as the start of the structure, - # not the end, so we look for the line no of the next node after main() - # and use that as the end of the main() function. - try: - restart_line = nodes.body[nodes.body.index(main_func)+1].lineno - 1 - except IndexError: - restart_line = len(source) - - module_source = format_source_to_return_parser( - source, - cutoff_line=parse_args_assignment.lineno, - restart_line=restart_line, - col_offset=parse_args_assignment.col_offset, - parser_name=parse_args_assignment.value.func.value.id - ) - client_module = modules.load(module_source) - return getattr(client_module, func_with_argparse)() - - -def has_argparse(source): - return any(['.parse_args(' in line.lower() for line in source.split('\n')]) - -if __name__ == '__main__': - filepath = os.path.join(os.path.dirname(__file__), - 'examples', - 'example_argparse_souce_in_main.py') - - nodes = ast.parse(_openfile(filepath)) - # - ast_source = parse_source_file(filepath) - python_code = convert_to_python(list(ast_source)) - - - diff --git a/gooey/tests/code_prep_unittest.py b/gooey/tests/code_prep_unittest.py deleted file mode 100644 index 2aae0d8..0000000 --- a/gooey/tests/code_prep_unittest.py +++ /dev/null @@ -1,55 +0,0 @@ -__author__ = 'Chris' - -import unittest -from gooey.python_bindings import code_prep - - -def test_split_line(): - line = "parser = ArgumentParser(description='Example Argparse Program')" - assert "parser" == code_prep.split_line(line)[0] - assert "ArgumentParser(description='Example Argparse Program')" == code_prep.split_line(line)[1] - - -def test_update_parser_varname_assigns_new_name_to_parser_var(): - line = ["parser = ArgumentParser(description='Example Argparse Program')"] - expected = "jarser = ArgumentParser(description='Example Argparse Program')" - result = code_prep.update_parser_varname('jarser', line)[0] - assert result == expected - -def test_update_parser_varname_assigns_new_name_to_parser_var__multiline(): - lines = ''' -import argparse -from argparse import ArgumentParser -parser = ArgumentParser(description='Example Argparse Program') -parser.parse_args() - '''.split('\n') - - line = "jarser = ArgumentParser(description='Example Argparse Program')" - result = code_prep.update_parser_varname('jarser', lines)[2] - assert line == result - - -def test_take_imports_drops_all_non_imports_statements(): - lines = ''' -import argparse -from argparse import ArgumentParser -parser = ArgumentParser(description='Example Argparse Program') -parser.parse_args() - '''.split('\n')[1:] - - assert 2 == len(list(code_prep.take_imports(lines))) - assert 'import argparse' == list(code_prep.take_imports(lines))[0] - - -def test_drop_imports_excludes_all_imports_statements(): - lines = ''' -import argparse -from argparse import ArgumentParser -parser = ArgumentParser(description='Example Argparse Program') -parser.parse_args() - '''.split('\n')[1:] - - assert 2 == len(list(code_prep.take_imports(lines))) - assert 'parser.parse_args()' == list(code_prep.drop_imports(lines))[1] - -