astor-0.5/0000775000175000017500000000000012514552465013267 5ustar berkerberker00000000000000astor-0.5/setuputils.py0000664000175000017500000000100212361472705016051 0ustar berkerberker00000000000000import codecs import os.path import re def read(*parts): file_path = os.path.join(os.path.dirname(__file__), *parts) with codecs.open(file_path, 'r') as fobj: content = fobj.read() return content def find_version(*parts): version_file = read(*parts) version_match = re.search(r'^__version__ = [\'"]([^\'"]*)[\'"]', version_file, re.M) if version_match: return version_match.group(1) raise RuntimeError('Unable to find version string.') astor-0.5/astor/0000775000175000017500000000000012514552465014417 5ustar berkerberker00000000000000astor-0.5/astor/treewalk.py0000664000175000017500000001204512361472705016607 0ustar berkerberker00000000000000# -*- coding: utf-8 -*- """ Part of the astor library for Python AST manipulation. License: 3-clause BSD Copyright 2012 (c) Patrick Maupin Copyright 2013 (c) Berker Peksag """ from .misc import MetaFlatten, iter_node class TreeWalk(MetaFlatten): """The TreeWalk class can be used as a superclass in order to walk an AST or similar tree. Unlike other treewalkers, this class can walk a tree either recursively or non-recursively. Subclasses can define methods with the following signatures:: def pre_xxx(self): pass def post_xxx(self): pass def init_xxx(self): pass Where 'xxx' is one of: - A class name - An attribute member name concatenated with '_name' For example, 'pre_targets_name' will process nodes that are referenced by the name 'targets' in their parent's node. - An attribute member name concatenated with '_item' For example, 'pre_targets_item' will process nodes that are in a list that is the targets attribute of some node. pre_xxx will process a node before processing any of its subnodes. if the return value from pre_xxx evalates to true, then walk will not process any of the subnodes. Those can be manually processed, if desired, by calling self.walk(node) on the subnodes before returning True. post_xxx will process a node after processing all its subnodes. init_xxx methods can decorate the class instance with subclass-specific information. A single init_whatever method could be written, but to make it easy to keep initialization with use, any number of init_xxx methods can be written. They will be called in alphabetical order. """ nodestack = None def __init__(self, node=None): self.setup() if node is not None: self.walk(node) def setup(self): """All the node-specific handlers are setup at object initialization time. """ self.pre_handlers = pre_handlers = {} self.post_handlers = post_handlers = {} for name in sorted(vars(type(self))): if name.startswith('init_'): getattr(self, name)() elif name.startswith('pre_'): pre_handlers[name[4:]] = getattr(self, name) elif name.startswith('post_'): post_handlers[name[5:]] = getattr(self, name) def walk(self, node, name='', list=list, len=len, type=type): """Walk the tree starting at a given node. Maintain a stack of nodes. """ pre_handlers = self.pre_handlers.get post_handlers = self.post_handlers.get oldstack = self.nodestack self.nodestack = nodestack = [] append, pop = nodestack.append, nodestack.pop append([node, name, list(iter_node(node, name + '_item')), -1]) while nodestack: node, name, subnodes, index = nodestack[-1] if index >= len(subnodes): handler = (post_handlers(type(node).__name__) or post_handlers(name + '_name')) if handler is None: pop() continue self.cur_node = node self.cur_name = name handler() current = nodestack and nodestack[-1] popstack = current and current[0] is node if popstack and current[-1] >= len(current[-2]): pop() continue nodestack[-1][-1] = index + 1 if index < 0: handler = (pre_handlers(type(node).__name__) or pre_handlers(name + '_name')) if handler is not None: self.cur_node = node self.cur_name = name if handler(): pop() else: node, name = subnodes[index] append([node, name, list(iter_node(node, name + '_item')), -1]) self.nodestack = oldstack @property def parent(self): """Return the parent node of the current node.""" nodestack = self.nodestack if len(nodestack) < 2: return None return nodestack[-2][0] @property def parent_name(self): """Return the parent node and name.""" nodestack = self.nodestack if len(nodestack) < 2: return None return nodestack[-2][:2] def replace(self, new_node): """Replace a node after first checking integrity of node stack.""" cur_node = self.cur_node nodestack = self.nodestack cur = nodestack.pop() prev = nodestack[-1] index = prev[-1] - 1 oldnode, name = prev[-2][index] assert cur[0] is cur_node is oldnode, (cur[0], cur_node, prev[-2], index) parent = prev[0] if isinstance(parent, list): parent[index] = new_node else: setattr(parent, name, new_node) astor-0.5/astor/codegen.py0000664000175000017500000003705312501062164016371 0ustar berkerberker00000000000000# -*- coding: utf-8 -*- """ This module converts an AST into Python source code. Original code copyright (c) 2008 by Armin Ronacher and is distributed under the 3-clause BSD license. It was derived from a modified version found here: https://gist.github.com/1250562 """ import ast from .misc import (ExplicitNodeVisitor, get_boolop, get_binop, get_cmpop, get_unaryop) 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) def enclose(enclosure): def decorator(func): def newfunc(self, node): self.write(enclosure[0]) func(self, node) self.write(enclosure[-1]) return newfunc return decorator class SourceGenerator(ExplicitNodeVisitor): """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, *params): for item in params: if isinstance(item, ast.AST): self.visit(item) elif hasattr(item, '__call__'): item() elif item == '\n': self.newline() else: 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(item) def conditional_write(self, *stuff): if stuff[-1] is not None: self.write(*stuff) 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.indentation += 1 for stmt in statements: self.visit(stmt) self.indentation -= 1 def else_body(self, elsewhat): if elsewhat: self.write('\n', 'else:') self.body(elsewhat) def body_or_else(self, node): self.body(node.body) self.else_body(node.orelse) def signature(self, node): want_comma = [] def write_comma(): if want_comma: self.write(', ') else: want_comma.append(True) def loop_args(args, defaults): padding = [None] * (len(args) - len(defaults)) for arg, default in zip(args, padding + defaults): self.write(write_comma, arg) self.conditional_write('=', default) loop_args(node.args, node.defaults) self.conditional_write(write_comma, '*', node.vararg) self.conditional_write(write_comma, '**', node.kwarg) kwonlyargs = getattr(node, 'kwonlyargs', None) if kwonlyargs: if node.vararg is None: self.write(write_comma, '*') loop_args(kwonlyargs, node.kw_defaults) def statement(self, node, *params, **kw): self.newline(node) self.write(*params) def decorators(self, node, extra): self.newline(extra=extra) for decorator in node.decorator_list: self.statement(decorator, '@', decorator) def comma_list(self, items, trailing=False): for idx, item in enumerate(items): if idx: self.write(', ') self.visit(item) if trailing: self.write(',') # Statements def visit_Assign(self, node): self.newline(node) for target in node.targets: self.write(target, ' = ') self.visit(node.value) def visit_AugAssign(self, node): self.statement(node, node.target, get_binop(node.op, ' %s= '), node.value) def visit_ImportFrom(self, node): if node.module: self.statement(node, 'from ', node.level * '.', node.module, ' import ') else: self.statement(node, 'from ', node.level * '. import ') self.comma_list(node.names) def visit_Import(self, node): self.statement(node, 'import ') self.comma_list(node.names) def visit_Expr(self, node): self.statement(node) self.generic_visit(node) def visit_FunctionDef(self, node): self.decorators(node, 1) self.statement(node, 'def %s(' % node.name) self.signature(node.args) self.write(')') if getattr(node, 'returns', None) is not None: self.write(' ->', node.returns) 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.decorators(node, 2) self.statement(node, 'class %s' % node.name) for base in node.bases: self.write(paren_or_comma, 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: self.write(paren_or_comma, keyword.arg, '=', keyword.value) self.conditional_write(paren_or_comma, '*', node.starargs) self.conditional_write(paren_or_comma, '**', node.kwargs) self.write(have_args and '):' or ':') self.body(node.body) def visit_If(self, node): self.statement(node, 'if ', node.test, ':') self.body(node.body) while True: else_ = node.orelse if len(else_) == 1 and isinstance(else_[0], ast.If): node = else_[0] self.write('\n', 'elif ', node.test, ':') self.body(node.body) else: self.else_body(else_) break def visit_For(self, node): self.statement(node, 'for ', node.target, ' in ', node.iter, ':') self.body_or_else(node) def visit_While(self, node): self.statement(node, 'while ', node.test, ':') self.body_or_else(node) def visit_With(self, node): if hasattr(node, "context_expr"): # Python < 3.3 self.statement(node, 'with ', node.context_expr) self.conditional_write(' as ', node.optional_vars) self.write(':') else: # Python >= 3.3 self.statement(node, 'with ') count = 0 for item in node.items: if count > 0: self.write(" , ") self.visit(item) count += 1 self.write(':') self.body(node.body) # new for Python 3.3 def visit_withitem(self, node): self.write(node.context_expr) self.conditional_write(' as ', node.optional_vars) def visit_NameConstant(self, node): self.write(node.value) def visit_Pass(self, node): self.statement(node, 'pass') def visit_Print(self, node): # XXX: python 2.6 only self.statement(node, 'print ') values = node.values if node.dest is not None: self.write(' >> ') values = [node.dest] + node.values self.comma_list(values, not node.nl) def visit_Delete(self, node): self.statement(node, 'del ') self.comma_list(node.targets) def visit_TryExcept(self, node): self.statement(node, 'try:') self.body(node.body) for handler in node.handlers: self.visit(handler) self.else_body(node.orelse) # new for Python 3.3 def visit_Try(self, node): self.statement(node, 'try:') self.body(node.body) for handler in node.handlers: self.visit(handler) if node.finalbody: self.statement(node, 'finally:') self.body(node.finalbody) self.else_body(node.orelse) def visit_ExceptHandler(self, node): self.statement(node, 'except') if node.type is not None: self.write(' ', node.type) self.conditional_write(' as ', node.name) self.write(':') self.body(node.body) def visit_TryFinally(self, node): self.statement(node, 'try:') self.body(node.body) self.statement(node, 'finally:') self.body(node.finalbody) def visit_Exec(self, node): dicts = node.globals, node.locals dicts = dicts[::-1] if dicts[0] is None else dicts self.statement(node, 'exec ', node.body) self.conditional_write(' in ', dicts[0]) self.conditional_write(', ', dicts[1]) def visit_Assert(self, node): self.statement(node, 'assert ', node.test) self.conditional_write(', ', node.msg) def visit_Global(self, node): self.statement(node, 'global ', ', '.join(node.names)) def visit_Nonlocal(self, node): self.statement(node, 'nonlocal ', ', '.join(node.names)) def visit_Return(self, node): self.statement(node, 'return') self.conditional_write(' ', node.value) def visit_Break(self, node): self.statement(node, 'break') def visit_Continue(self, node): self.statement(node, 'continue') def visit_Raise(self, node): # XXX: Python 2.6 / 3.0 compatibility self.statement(node, 'raise') if hasattr(node, 'exc') and node.exc is not None: self.write(' ', node.exc) self.conditional_write(' from ', node.cause) elif hasattr(node, 'type') and node.type is not None: self.write(' ', node.type) self.conditional_write(', ', node.inst) self.conditional_write(', ', node.tback) # Expressions def visit_Attribute(self, node): self.write(node.value, '.', 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: self.write(write_comma, arg) for keyword in node.keywords: self.write(write_comma, keyword.arg, '=', keyword.value) self.conditional_write(write_comma, '*', node.starargs) self.conditional_write(write_comma, '**', 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): # Hack because ** binds more closely than '-' s = repr(node.n) if s.startswith('-'): s = '(%s)' % s self.write(s) @enclose('()') def visit_Tuple(self, node): self.comma_list(node.elts, len(node.elts) == 1) @enclose('[]') def visit_List(self, node): self.comma_list(node.elts) @enclose('{}') def visit_Set(self, node): self.comma_list(node.elts) @enclose('{}') def visit_Dict(self, node): for key, value in zip(node.keys, node.values): self.write(key, ': ', value, ', ') @enclose('()') def visit_BinOp(self, node): self.write(node.left, get_binop(node.op, ' %s '), node.right) @enclose('()') def visit_BoolOp(self, node): op = get_boolop(node.op, ' %s ') for idx, value in enumerate(node.values): self.write(idx and op or '', value) @enclose('()') def visit_Compare(self, node): self.visit(node.left) for op, right in zip(node.ops, node.comparators): self.write(get_cmpop(op, ' %s '), right) @enclose('()') def visit_UnaryOp(self, node): self.write(get_unaryop(node.op), ' ', node.operand) def visit_Subscript(self, node): self.write(node.value, '[', node.slice, ']') def visit_Slice(self, node): self.conditional_write(node.lower) self.write(':') self.conditional_write(node.upper) if node.step is not None: self.write(':') if not (isinstance(node.step, ast.Name) and node.step.id == 'None'): self.visit(node.step) def visit_Index(self, node): self.visit(node.value) def visit_ExtSlice(self, node): self.comma_list(node.dims, len(node.dims) == 1) def visit_Yield(self, node): self.write('yield') self.conditional_write(' ', node.value) # new for Python 3.3 def visit_YieldFrom(self, node): self.write('yield from ') self.visit(node.value) @enclose('()') def visit_Lambda(self, node): self.write('lambda ') self.signature(node.args) self.write(': ', node.body) def visit_Ellipsis(self, node): self.write('...') def generator_visit(left, right): def visit(self, node): self.write(left, 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 @enclose('{}') def visit_DictComp(self, node): self.write(node.key, ': ', node.value) for comprehension in node.generators: self.visit(comprehension) @enclose('()') def visit_IfExp(self, node): self.write(node.body, ' if ', node.test, ' else ', node.orelse) def visit_Starred(self, node): self.write('*', node.value) @enclose('``') def visit_Repr(self, node): # XXX: python 2.6 only self.visit(node.value) def visit_Module(self, node): for stmt in node.body: self.visit(stmt) # Helper Nodes def visit_arg(self, node): self.write(node.arg) self.conditional_write(': ', node.annotation) def visit_alias(self, node): self.write(node.name) self.conditional_write(' as ', node.asname) def visit_comprehension(self, node): self.write(' for ', node.target, ' in ', node.iter) if node.ifs: for if_ in node.ifs: self.write(' if ', if_) def visit_arguments(self, node): self.signature(node) astor-0.5/astor/__init__.py0000664000175000017500000000101112514547553016523 0ustar berkerberker00000000000000# -*- coding: utf-8 -*- """ Part of the astor library for Python AST manipulation. License: 3-clause BSD Copyright 2012 (c) Patrick Maupin Copyright 2013 (c) Berker Peksag """ __version__ = '0.5' from .codegen import to_source # NOQA from .misc import iter_node, dump, all_symbols, get_anyop # NOQA from .misc import get_boolop, get_binop, get_cmpop, get_unaryop # NOQA from .misc import ExplicitNodeVisitor # NOQA from .misc import parsefile, CodeToAst, codetoast # NOQA from .treewalk import TreeWalk # NOQA astor-0.5/astor/misc.py0000664000175000017500000001364412514547525015735 0ustar berkerberker00000000000000# -*- coding: utf-8 -*- """ Part of the astor library for Python AST manipulation. License: 3-clause BSD Copyright 2012 (c) Patrick Maupin Copyright 2013 (c) Berker Peksag """ import ast import sys class NonExistent(object): pass def iter_node(node, name='', list=list, getattr=getattr, isinstance=isinstance, enumerate=enumerate, missing=NonExistent): """Iterates over an object: - If the object has a _fields attribute, it gets attributes in the order of this and returns name, value pairs. - Otherwise, if the object is a list instance, it returns name, value pairs for each item in the list, where the name is passed into this function (defaults to blank). """ fields = getattr(node, '_fields', None) if fields is not None: for name in fields: value = getattr(node, name, missing) if value is not missing: yield value, name elif isinstance(node, list): for value in node: yield value, name def dump(node, name=None, initial_indent='', indentation=' ', maxline=120, maxmerged=80, iter_node=iter_node, special=ast.AST, list=list, isinstance=isinstance, type=type, len=len): """Dumps an AST or similar structure: - Pretty-prints with indentation - Doesn't print line/column/ctx info """ def dump(node, name=None, indent=''): level = indent + indentation name = name and name + '=' or '' values = list(iter_node(node)) if isinstance(node, list): prefix, suffix = '%s[' % name, ']' elif values: prefix, suffix = '%s%s(' % (name, type(node).__name__), ')' elif isinstance(node, special): prefix, suffix = name + type(node).__name__, '' else: return '%s%s' % (name, repr(node)) node = [dump(a, b, level) for a, b in values if b != 'ctx'] oneline = '%s%s%s' % (prefix, ', '.join(node), suffix) if len(oneline) + len(indent) < maxline: return '%s' % oneline if node and len(prefix) + len(node[0]) < maxmerged: prefix = '%s%s,' % (prefix, node.pop(0)) node = (',\n%s' % level).join(node).lstrip() return '%s\n%s%s%s' % (prefix, level, node, suffix) return dump(node, name, initial_indent) class MetaFlatten(type): """This metaclass is used to flatten classes to remove class hierarchy. This makes it easier to manipulate classes (find attributes in a single dict, etc.) """ def __new__(clstype, name, bases, clsdict): newbases = (object,) newdict = {} for base in reversed(bases): if base not in newbases: newdict.update(vars(base)) newdict.update(clsdict) # Delegate the real work to type return type.__new__(clstype, name, newbases, newdict) MetaFlatten = MetaFlatten('MetaFlatten', (object, ), {}) def _getsymbol(mapping, map_dict=None, type=type): """This function returns a closure that will map a class type to its corresponding symbol, by looking up the class name of an object. """ if isinstance(mapping, str): mapping = mapping.split() mapping = list(zip(mapping[0::2], (x.replace('_', ' ') for x in mapping[1::2]))) mapping = dict(((getattr(ast, x), y) for x, y in mapping)) if map_dict is not None: map_dict.update(mapping) def getsymbol(obj, fmt='%s'): return fmt % mapping[type(obj)] return getsymbol all_symbols = {} get_boolop = _getsymbol(""" And and Or or """, all_symbols) binops = """ Add + Mult * LShift << BitAnd & Sub - Div / RShift >> BitOr | Mod % BitXor ^ FloorDiv // Pow ** """ if sys.version_info >= (3, 5): binops += "MatMult @" get_binop = _getsymbol(binops, all_symbols) get_cmpop = _getsymbol(""" Eq == Gt > GtE >= In in Is is NotEq != Lt < LtE <= NotIn not_in IsNot is_not """, all_symbols) get_unaryop = _getsymbol(""" UAdd + USub - Invert ~ Not not """, all_symbols) get_anyop = _getsymbol(all_symbols) class ExplicitNodeVisitor(ast.NodeVisitor): """This expands on the ast module's NodeVisitor class to remove any implicit visits. """ def abort_visit(node): # XXX: self? msg = 'No defined handler for node of type %s' raise AttributeError(msg % node.__class__.__name__) def visit(self, node, abort=abort_visit): """Visit a node.""" method = 'visit_' + node.__class__.__name__ visitor = getattr(self, method, abort) return visitor(node) def parsefile(fname): with open(fname, 'r') as f: fstr = f.read() fstr = fstr.replace('\r\n', '\n').replace('\r', '\n') if not fstr.endswith('\n'): fstr += '\n' return ast.parse(fstr, filename=fname) class CodeToAst(object): """Given a module, or a function that was compiled as part of a module, re-compile the module into an AST and extract the sub-AST for the function. Allow caching to reduce number of compiles. """ def __init__(self, cache=None): self.cache = cache or {} def __call__(self, codeobj): cache = self.cache fname = getattr(codeobj, '__file__', None) if fname is None: func_code = codeobj.__code__ fname = func_code.co_filename linenum = func_code.co_firstlineno key = fname, linenum else: fname = key = fname.replace('.pyc', '.py') result = cache.get(key) if result is not None: return result cache[fname] = mod_ast = parsefile(fname) for obj in mod_ast.body: if not isinstance(obj, ast.FunctionDef): continue cache[(fname, obj.lineno)] = obj return cache[key] codetoast = CodeToAst() astor-0.5/AUTHORS0000664000175000017500000000061612514547643014344 0ustar berkerberker00000000000000Original author of astor/codegen.py: * Armin Ronacher And with some modifications based on Armin's code: * Paul Dubs * Berker Peksag * Patrick Maupin * Abhishek L * Bob Tolbert * Whyzgeek * Zack M. Davis astor-0.5/setup.py0000775000175000017500000000270412514552351015001 0ustar berkerberker00000000000000#!/usr/bin/env python from setuptools import setup, find_packages from setuputils import find_version, read setup( name='astor', version=find_version('astor/__init__.py'), description='Read/rewrite/write Python ASTs', long_description=read('README.rst'), author='Patrick Maupin', author_email='pmaupin@gmail.com', platforms='Independent', url='https://github.com/berkerpeksag/astor', packages=find_packages(exclude=['tests']), py_modules=['setuputils'], classifiers=[ 'Development Status :: 5 - Production/Stable', 'Environment :: Console', 'Intended Audience :: Developers', 'License :: OSI Approved :: BSD License', 'Operating System :: OS Independent', 'Programming Language :: Python', 'Programming Language :: Python :: 2', 'Programming Language :: Python :: 2.6', 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', 'Programming Language :: Python :: 3.2', 'Programming Language :: Python :: 3.3', 'Programming Language :: Python :: 3.4', 'Programming Language :: Python :: Implementation', 'Programming Language :: Python :: Implementation :: CPython', 'Programming Language :: Python :: Implementation :: PyPy', 'Topic :: Software Development :: Code Generators', 'Topic :: Software Development :: Compilers', ], keywords='ast, codegen', ) astor-0.5/CHANGES0000664000175000017500000000114312514547740014261 0ustar berkerberker000000000000000.1 -- Initial release 0.2 -- Added Python 3 support 0.2.1 -- Modified TreeWalk to add '_name' suffix for functions that work on attribute names 0.3 -- Added support for Python 3.3. Added YieldFrom and updated Try and With. Also, fixed a packaging bug on Python 3. See pull requests #1 and #2 for more information. 0.4 -- Added a visitor for NameConstant. Added initial test suite and documentation. 0.4.1 -- Added missing SourceGenerator.visit_arguments() 0.5 -- Added support for Python 3.5 infix matrix multiplication astor-0.5/astor.egg-info/0000775000175000017500000000000012514552465016111 5ustar berkerberker00000000000000astor-0.5/astor.egg-info/SOURCES.txt0000664000175000017500000000040612514552465017775 0ustar berkerberker00000000000000AUTHORS CHANGES LICENSE MANIFEST.in README.rst setup.cfg setup.py setuputils.py astor/__init__.py astor/codegen.py astor/misc.py astor/treewalk.py astor.egg-info/PKG-INFO astor.egg-info/SOURCES.txt astor.egg-info/dependency_links.txt astor.egg-info/top_level.txtastor-0.5/astor.egg-info/PKG-INFO0000664000175000017500000000620612514552464017211 0ustar berkerberker00000000000000Metadata-Version: 1.1 Name: astor Version: 0.5 Summary: Read/rewrite/write Python ASTs Home-page: https://github.com/berkerpeksag/astor Author: Patrick Maupin Author-email: pmaupin@gmail.com License: UNKNOWN Description: ============================= astor -- AST observe/rewrite ============================= :PyPI: https://pypi.python.org/pypi/astor :Documentation: http://astor.rtfd.org/ :Source: https://github.com/berkerpeksag/astor :License: 3-clause BSD :Build status: .. image:: https://secure.travis-ci.org/berkerpeksag/astor.png :alt: Travis CI :target: http://travis-ci.org/berkerpeksag/astor/ astor is designed to allow easy manipulation of Python source via the AST. There are some other similar libraries, but astor focuses on the following areas: - Round-trip back to Python via Armin Ronacher's codegen.py module: - Modified AST doesn't need linenumbers, ctx, etc. or otherwise be directly compileable - Easy to read generated code as, well, code - Dump pretty-printing of AST - Harder to read than round-tripped code, but more accurate to figure out what is going on. - Easier to read than dump from built-in AST module - Non-recursive treewalk - Sometimes you want a recursive treewalk (and astor supports that, starting at any node on the tree), but sometimes you don't need to do that. astor doesn't require you to explicitly visit sub-nodes unless you want to: - You can add code that executes before a node's children are visited, and/or - You can add code that executes after a node's children are visited, and/or - You can add code that executes and keeps the node's children from being visited (and optionally visit them yourself via a recursive call) - Write functions to access the tree based on object names and/or attribute names - Enjoy easy access to parent node(s) for tree rewriting Keywords: ast,codegen Platform: Independent Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: Implementation Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Code Generators Classifier: Topic :: Software Development :: Compilers astor-0.5/astor.egg-info/dependency_links.txt0000664000175000017500000000000112514552464022156 0ustar berkerberker00000000000000 astor-0.5/astor.egg-info/top_level.txt0000664000175000017500000000002112514552464020633 0ustar berkerberker00000000000000setuputils astor astor-0.5/README.rst0000664000175000017500000000320012361472705014747 0ustar berkerberker00000000000000============================= astor -- AST observe/rewrite ============================= :PyPI: https://pypi.python.org/pypi/astor :Documentation: http://astor.rtfd.org/ :Source: https://github.com/berkerpeksag/astor :License: 3-clause BSD :Build status: .. image:: https://secure.travis-ci.org/berkerpeksag/astor.png :alt: Travis CI :target: http://travis-ci.org/berkerpeksag/astor/ astor is designed to allow easy manipulation of Python source via the AST. There are some other similar libraries, but astor focuses on the following areas: - Round-trip back to Python via Armin Ronacher's codegen.py module: - Modified AST doesn't need linenumbers, ctx, etc. or otherwise be directly compileable - Easy to read generated code as, well, code - Dump pretty-printing of AST - Harder to read than round-tripped code, but more accurate to figure out what is going on. - Easier to read than dump from built-in AST module - Non-recursive treewalk - Sometimes you want a recursive treewalk (and astor supports that, starting at any node on the tree), but sometimes you don't need to do that. astor doesn't require you to explicitly visit sub-nodes unless you want to: - You can add code that executes before a node's children are visited, and/or - You can add code that executes after a node's children are visited, and/or - You can add code that executes and keeps the node's children from being visited (and optionally visit them yourself via a recursive call) - Write functions to access the tree based on object names and/or attribute names - Enjoy easy access to parent node(s) for tree rewriting astor-0.5/PKG-INFO0000664000175000017500000000620612514552465014370 0ustar berkerberker00000000000000Metadata-Version: 1.1 Name: astor Version: 0.5 Summary: Read/rewrite/write Python ASTs Home-page: https://github.com/berkerpeksag/astor Author: Patrick Maupin Author-email: pmaupin@gmail.com License: UNKNOWN Description: ============================= astor -- AST observe/rewrite ============================= :PyPI: https://pypi.python.org/pypi/astor :Documentation: http://astor.rtfd.org/ :Source: https://github.com/berkerpeksag/astor :License: 3-clause BSD :Build status: .. image:: https://secure.travis-ci.org/berkerpeksag/astor.png :alt: Travis CI :target: http://travis-ci.org/berkerpeksag/astor/ astor is designed to allow easy manipulation of Python source via the AST. There are some other similar libraries, but astor focuses on the following areas: - Round-trip back to Python via Armin Ronacher's codegen.py module: - Modified AST doesn't need linenumbers, ctx, etc. or otherwise be directly compileable - Easy to read generated code as, well, code - Dump pretty-printing of AST - Harder to read than round-tripped code, but more accurate to figure out what is going on. - Easier to read than dump from built-in AST module - Non-recursive treewalk - Sometimes you want a recursive treewalk (and astor supports that, starting at any node on the tree), but sometimes you don't need to do that. astor doesn't require you to explicitly visit sub-nodes unless you want to: - You can add code that executes before a node's children are visited, and/or - You can add code that executes after a node's children are visited, and/or - You can add code that executes and keeps the node's children from being visited (and optionally visit them yourself via a recursive call) - Write functions to access the tree based on object names and/or attribute names - Enjoy easy access to parent node(s) for tree rewriting Keywords: ast,codegen Platform: Independent Classifier: Development Status :: 5 - Production/Stable Classifier: Environment :: Console Classifier: Intended Audience :: Developers Classifier: License :: OSI Approved :: BSD License Classifier: Operating System :: OS Independent Classifier: Programming Language :: Python Classifier: Programming Language :: Python :: 2 Classifier: Programming Language :: Python :: 2.6 Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 Classifier: Programming Language :: Python :: 3.2 Classifier: Programming Language :: Python :: 3.3 Classifier: Programming Language :: Python :: 3.4 Classifier: Programming Language :: Python :: Implementation Classifier: Programming Language :: Python :: Implementation :: CPython Classifier: Programming Language :: Python :: Implementation :: PyPy Classifier: Topic :: Software Development :: Code Generators Classifier: Topic :: Software Development :: Compilers astor-0.5/MANIFEST.in0000664000175000017500000000005312361472705015021 0ustar berkerberker00000000000000include README.rst AUTHORS LICENSE CHANGES astor-0.5/setup.cfg0000664000175000017500000000012212514552465015103 0ustar berkerberker00000000000000[wheel] universal = 1 [egg_info] tag_build = tag_date = 0 tag_svn_revision = 0 astor-0.5/LICENSE0000664000175000017500000000302212361472705014267 0ustar berkerberker00000000000000Copyright (c) 2012, Patrick Maupin Copyright (c) 2013, Berker Peksag Copyright (c) 2008, Armin Ronacher All rights reserved. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: 1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. 2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. 3. Neither the name of the copyright holder nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.