summaryrefslogtreecommitdiff
path: root/raw_building.py
diff options
context:
space:
mode:
authorroot <none@none>2006-04-26 10:48:09 +0000
committerroot <none@none>2006-04-26 10:48:09 +0000
commit85529cfcb8e870333d7292cb493f54d7f3fd92cf (patch)
treeab1c5d7f169245ebf38ec6c8dba5065cbd48ec9f /raw_building.py
downloadastroid-git-85529cfcb8e870333d7292cb493f54d7f3fd92cf.tar.gz
forget the past.
forget the past.
Diffstat (limited to 'raw_building.py')
-rw-r--r--raw_building.py214
1 files changed, 214 insertions, 0 deletions
diff --git a/raw_building.py b/raw_building.py
new file mode 100644
index 00000000..d00fdfb1
--- /dev/null
+++ b/raw_building.py
@@ -0,0 +1,214 @@
+# This program is free software; you can redistribute it and/or modify it under
+# the terms of the GNU General Public License as published by the Free Software
+# Foundation; either version 2 of the License, or (at your option) any later
+# version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License along with
+# this program; if not, write to the Free Software Foundation, Inc.,
+# 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+"""this module contains a set of functions to create astng trees from scratch
+(build_* functions) or from living object (object_build_* functions)
+
+:version: $Revision: 1.12 $
+:author: Sylvain Thenault
+:copyright: 2003-2005 LOGILAB S.A. (Paris, FRANCE)
+:contact: http://www.logilab.fr/ -- mailto:python-projects@logilab.org
+:copyright: 2003-2005 Sylvain Thenault
+:contact: mailto:thenault@gmail.com
+"""
+
+__revision__ = "$Id: raw_building.py,v 1.12 2006-03-05 14:44:15 syt Exp $"
+__doctype__ = "restructuredtext en"
+
+import sys
+from inspect import getargspec
+
+from logilab.astng import nodes
+
+def attach___dict__(node):
+ """attach the __dict__ attribute to Class and Module objects"""
+ dictn = nodes.Dict([])
+ dictn.parent = node
+ node.locals['__dict__'] = [dictn]
+
+def attach_dummy_node(node, name):
+ """create a dummy node and register it in the locals of the given
+ node with the specified name
+ """
+ _attach_local_node(node, nodes.EmptyNode(), name)
+
+def attach_const_node(node, name, value):
+ """create a Const node and register it in the locals of the given
+ node with the specified name
+ """
+ _attach_local_node(node, nodes.Const(value), name)
+
+def attach_import_node(node, modname, membername):
+ """create a From node and register it in the locals of the given
+ node with the specified name
+ """
+ _attach_local_node(node, nodes.From(modname, ( (membername, None), ) ),
+ membername)
+
+def _attach_local_node(parent, node, name):
+ node.name = name # needed by add_local_node
+ node.parent = parent
+ node.lineno = 1
+ parent.add_local_node(node)
+
+
+def build_module(name, doc=None):
+ """create and initialize a astng Module node"""
+ node = nodes.Module(doc, nodes.Stmt([]))
+ node.node.parent = node
+ node.name = name
+ node.pure_python = False
+ node.package = False
+ node.parent = None
+ node.globals = node.locals = {}
+ return node
+
+def build_class(name, basenames=None, doc=None):
+ """create and initialize a astng Class node"""
+ klass = nodes.Class(name, [], doc, nodes.Stmt([]))
+ bases = [nodes.Name(base) for base in basenames]
+ for base in bases:
+ base.parent = klass
+ klass.basenames = basenames
+ klass.bases = bases
+ klass.code.parent = klass
+ klass.locals = {}
+ klass.instance_attrs = {}
+ for name, value in ( ('__name__', name),
+ #('__module__', node.root().name),
+ ):
+ const = nodes.Const(value)
+ const.parent = klass
+ klass.locals[name] = [const]
+ return klass
+
+# introduction of decorators has changed the Function initializer arguments
+if sys.version_info >= (2, 4):
+ try:
+ from compiler.ast import Decorators as BaseDecorators
+ class Decorators(BaseDecorators):
+ def __init__(self):
+ BaseDecorators.__init__(self, [], 0)
+ except ImportError:
+ Decorators = list
+
+ def build_function(name, args=None, defaults=None, flag=0, doc=None):
+ """create and initialize a astng Function node"""
+ args, defaults = args or [], defaults or []
+ # first argument is now a list of decorators
+ func = nodes.Function(Decorators(), name, args, defaults, flag, doc,
+ nodes.Stmt([]))
+ func.code.parent = func
+ func.locals = {}
+ if args:
+ register_arguments(func, args)
+ return func
+
+else:
+ def build_function(name, args=None, defaults=None, flag=0, doc=None):
+ """create and initialize a astng Function node"""
+ args, defaults = args or [], defaults or []
+ func = nodes.Function(name, args, defaults, flag, doc, nodes.Stmt([]))
+ func.code.parent = func
+ func.locals = {}
+ if args:
+ register_arguments(func, args)
+ return func
+
+
+def build_name_assign(name, value):
+ """create and initialize an astng Assign for a name assignment"""
+ return nodes.Assign([nodes.AssName(name, 'OP_ASSIGN')], nodes.Const(value))
+
+def build_attr_assign(name, value, attr='self'):
+ """create and initialize an astng Assign for an attribute assignment"""
+ return nodes.Assign([nodes.AssAttr(nodes.Name(attr), name, 'OP_ASSIGN')],
+ nodes.Const(value))
+
+def build_from_import(fromname, names):
+ """create and intialize an astng From import statement"""
+ return nodes.From(fromname, [(name, None) for name in names])
+
+def register_arguments(node, args):
+ """add given arguments to local
+
+ args is a list that may contains nested lists
+ (i.e. def func(a, (b, c, d)): ...)
+ """
+ for arg in args:
+ if type(arg) is type(''):
+ node.set_local(arg, node)
+ else:
+ register_arguments(node, arg)
+
+
+def object_build_class(node, member):
+ """create astng for a living class object"""
+ basenames = [base.__name__ for base in member.__bases__]
+ return _base_class_object_build(node, member, basenames)
+
+def object_build_function(node, member):
+ """create astng for a living function object"""
+ args, varargs, varkw, defaults = getargspec(member)
+ if varargs is not None:
+ args.append(varargs)
+ if varkw is not None:
+ args.append(varkw)
+ func = build_function(member.__name__, args, defaults,
+ member.func_code.co_flags, member.__doc__)
+ node.add_local_node(func)
+
+def object_build_datadescriptor(node, member, name):
+ """create astng for a living data descriptor object"""
+ return _base_class_object_build(node, member, [], name)
+
+def object_build_methoddescriptor(node, member):
+ """create astng for a living method descriptor object"""
+ # FIXME get arguments ?
+ func = build_function(member.__name__, doc=member.__doc__)
+ # set argnames to None to notice that we have no information, not
+ # and empty argument list
+ func.argnames = None
+ node.add_local_node(func)
+
+def _base_class_object_build(node, member, basenames, name=None):
+ """create astng for a living class object, with a given set of base names
+ (e.g. ancestors)
+ """
+ klass = build_class(name or member.__name__, basenames, member.__doc__)
+ klass._newstyle = isinstance(member, type)
+ node.add_local_node(klass)
+ try:
+ # limit the instantiation trick since it's too dangerous
+ # (such as infinite test execution...)
+ # this at least resolves common case such as Exception.args,
+ # OSError.errno
+ if issubclass(member, Exception):
+ instdict = member().__dict__
+ else:
+ raise TypeError
+ except:
+ pass
+ else:
+ for name in instdict.keys():
+ valnode = nodes.EmptyNode()
+ valnode.parent = klass
+ valnode.lineno = 1
+ klass.instance_attrs[name] = [valnode]
+ return klass
+
+
+__all__ = ('register_arguments', 'build_module',
+ 'object_build_class', 'object_build_function',
+ 'object_build_datadescriptor', 'object_build_methoddescriptor',
+ 'attach___dict__', 'attach_dummy_node',
+ 'attach_const_node', 'attach_import_node')