[Bf-blender-cvs] SVN commit: /data/svn/bf-blender [25550] trunk/blender: update rna_info and rna_rna for better introspection

Campbell Barton ideasman42 at gmail.com
Fri Dec 25 15:42:00 CET 2009


Revision: 25550
          http://projects.blender.org/plugins/scmsvn/viewcvs.php?view=rev&root=bf-blender&revision=25550
Author:   campbellbarton
Date:     2009-12-25 15:42:00 +0100 (Fri, 25 Dec 2009)

Log Message:
-----------
update rna_info and rna_rna for better introspection

Modified Paths:
--------------
    trunk/blender/release/scripts/modules/bpy_types.py
    trunk/blender/release/scripts/modules/rna_info.py
    trunk/blender/source/blender/makesrna/intern/rna_rna.c
    trunk/blender/source/blender/python/epy_doc_gen.py

Modified: trunk/blender/release/scripts/modules/bpy_types.py
===================================================================
--- trunk/blender/release/scripts/modules/bpy_types.py	2009-12-25 09:01:23 UTC (rev 25549)
+++ trunk/blender/release/scripts/modules/bpy_types.py	2009-12-25 14:42:00 UTC (rev 25550)
@@ -42,25 +42,27 @@
 
     @property
     def children(self):
+        """All the children of this object"""
         import bpy
         return [child for child in bpy.data.objects if child.parent == self]
 
 
 class _GenericBone:
-    '''
+    """
     functions for bones, common between Armature/Pose/Edit bones.
     internal subclassing use only.
-    '''
+    """
     __slots__ = ()
 
     def translate(self, vec):
+        """Utility function to add *vec* to the head and tail of this bone."""
         self.head += vec
         self.tail += vec
 
     def parent_index(self, parent_test):
-        '''
+        """
         The same as 'bone in other_bone.parent_recursive' but saved generating a list.
-        '''
+        """
         # use the name so different types can be tested.
         name = parent_test.name
 
@@ -76,11 +78,13 @@
 
     @property
     def basename(self):
+        """The name of this bone before any '.' character"""
         #return self.name.rsplit(".", 1)[0]
         return self.name.split(".")[0]
 
     @property
     def parent_recursive(self):
+        """A list of parents, starting with the immediate parent"""
         parent_list = []
         parent = self.parent
 
@@ -94,23 +98,26 @@
 
     @property
     def length(self):
+        """The distance from head to tail, when set the head is moved to fit the length."""
         return self.vector.length
 
     @length.setter
     def length(self, value):
-        """The distance from head to tail"""
         self.tail = self.head + ((self.tail - self.head).normalize() * value)
 
     @property
     def vector(self):
+        """The direction this bone is pointing. Utility function for (tail - head)"""
         return (self.tail - self.head)
 
     @property
     def children(self):
+        """A list of all the bones children."""
         return [child for child in self._other_bones if child.parent == self]
 
     @property
     def children_recursive(self):
+        """a list of all children from this bone."""
         bones_children = []
         for bone in self._other_bones:
             index = bone.parent_index(self)
@@ -123,10 +130,11 @@
 
     @property
     def children_recursive_basename(self):
-        '''
+        """
         Returns a chain of children with the same base name as this bone
-        Only direct chains are supported, forks caused by multiple children with matching basenames will.
-        '''
+        Only direct chains are supported, forks caused by multiple children with matching basenames will
+        terminate the function and not be returned.
+        """
         basename = self.basename
         chain = []
 
@@ -177,10 +185,10 @@
     __slots__ = ()
 
     def align_orientation(self, other):
-        '''
+        """
         Align this bone to another by moving its tail and settings its roll
         the length of the other bone is not used.
-        '''
+        """
         vec = other.vector.normalize() * self.length
         self.tail = self.head + vec
         self.roll = other.roll
@@ -196,10 +204,10 @@
     __slots__ = ()
 
     def from_pydata(self, verts, edges, faces):
-        '''
+        """
         Make a mesh from a list of verts/edges/faces
         Until we have a nicer way to make geometry, use this.
-        '''
+        """
         self.add_geometry(len(verts), len(edges), len(faces))
 
         verts_flat = [f for v in verts for f in v]
@@ -244,7 +252,7 @@
         return [edge_face_count_dict.get(ed.key, 0) for ed in mesh.edges]
 
     def edge_loops(self, faces=None, seams=()):
-        '''
+        """
         Edge loops defined by faces
 
         Takes me.faces or a list of faces and returns the edge loops
@@ -255,7 +263,7 @@
         [ [(0,1), (4, 8), (3,8)], ...]
 
         optionaly, seams are edge keys that will be removed
-        '''
+        """
 
         OTHER_INDEX = 2,3,0,1 # opposite face index
 
@@ -396,9 +404,9 @@
             layout.operator(operator, text=bpy.utils.display_name(f)).path = path
 
     def draw_preset(self, context):
-        '''Define these on the subclass
+        """Define these on the subclass
          - preset_operator
          - preset_subdir
-        '''
+        """
         import bpy
         self.path_menu(bpy.utils.preset_paths(self.preset_subdir), self.preset_operator)

Modified: trunk/blender/release/scripts/modules/rna_info.py
===================================================================
--- trunk/blender/release/scripts/modules/rna_info.py	2009-12-25 09:01:23 UTC (rev 25549)
+++ trunk/blender/release/scripts/modules/rna_info.py	2009-12-25 14:42:00 UTC (rev 25550)
@@ -20,6 +20,9 @@
 
 import bpy
 
+# use to strip python paths
+script_paths = bpy.utils.script_paths()
+
 def range_str(val):
     if val < -10000000:	return '-inf'
     if val >  10000000:	return 'inf'
@@ -28,6 +31,12 @@
     else:
         return str(val)
 
+def float_as_string(f):
+    val_str = "%g" % f
+    if '.' not in val_str and '-' not in val_str: # value could be 1e-05
+        val_str += '.0'
+    return val_str
+
 class InfoStructRNA:
     global_lookup = {}
     def __init__(self, rna_type):
@@ -73,6 +82,31 @@
 
         return ls
 
+    def _get_py_visible_attrs(self):
+        attrs = []
+        py_class = getattr(bpy.types, self.identifier)
+        for attr_str in dir(py_class):
+            if attr_str.startswith("_"):
+                continue                
+            attrs.append((attr_str, getattr(py_class, attr_str)))
+        return attrs
+        
+
+    def get_py_properties(self):
+        properties = []
+        for identifier, attr in self._get_py_visible_attrs():
+            if type(attr) is property:
+                properties.append((identifier, attr))
+        return properties
+    
+    def get_py_functions(self):
+        import types
+        functions = []
+        for identifier, attr in self._get_py_visible_attrs():
+            if type(attr) is types.FunctionType:
+                functions.append((identifier, attr))
+        return functions
+    
     def __repr__(self):
 
         txt = ''
@@ -106,6 +140,10 @@
         self.min = getattr(rna_prop, "hard_min", -1)
         self.max = getattr(rna_prop, "hard_max", -1)
         self.array_length = getattr(rna_prop, "array_length", 0)
+        self.collection_type = GetInfoStructRNA(rna_prop.srna)
+        self.is_required = rna_prop.is_required
+        self.is_readonly = rna_prop.is_readonly
+        self.is_never_none = rna_prop.is_never_none
 
         self.type = rna_prop.type.lower()
         fixed_type = getattr(rna_prop, "fixed_type", "")
@@ -118,12 +156,43 @@
             self.enum_items[:] = rna_prop.items.keys()
 
         if self.array_length:
-            self.default_str = str(getattr(rna_prop, "default_array", ""))
+            self.default = tuple(getattr(rna_prop, "default_array", ()))
+            self.default_str = ''
+            # special case for floats
+            if len(self.default) > 0:
+                if type(self.default[0]) is float:
+                    self.default_str = "(%s)" % ", ".join([float_as_string(f) for f in self.default])
+            if not self.default_str:
+                self.default_str = str(self.default)
         else:
-            self.default_str = str(getattr(rna_prop, "default", ""))
+            self.default = getattr(rna_prop, "default", "")
+            if type(self.default) is float:
+                self.default_str = float_as_string(self.default)
+            else:
+                self.default_str = str(self.default)
 
         self.srna = GetInfoStructRNA(rna_prop.srna) # valid for pointer/collections
+    
+    def get_default_string(self):
+        # pointer has no default, just set as None
+        if self.type == "pointer":
+           return "None"
+        elif self.type == "string":
+           return '"' + self.default_str + '"'
+        elif self.type == "enum":
+            if self.default_str:
+               return "'" + self.default_str + "'"
+            else:
+                return ""
 
+        return self.default_str
+    
+    def get_arg_default(self, force=True):
+        default = self.get_default_string()
+        if default and (force or self.is_required == False):
+            return "%s=%s" % (self.identifier, default)
+        return self.identifier
+    
     def __repr__(self):
         txt = ''
         txt += ' * ' + self.identifier + ': ' + self.description
@@ -162,6 +231,65 @@
         return txt
 
 
+class InfoOperatorRNA:
+    global_lookup = {}
+    def __init__(self, rna_op):
+        self.bl_op = rna_op
+        self.identifier = rna_op.identifier
+        
+        mod, name = self.identifier.split("_OT_", 1)
+        self.module_name = mod.lower()
+        self.func_name = name
+        
+        # self.name = rna_func.name # functions have no name!
+        self.description = rna_op.description.strip()
+
+        self.args = []
+
+    def build(self):
+        rna_op = self.bl_op
+        parent_id = self.identifier
+        for rna_id, rna_prop in rna_op.properties.items():
+            if rna_id == "rna_type":
+                continue
+            
+            prop = GetInfoPropertyRNA(rna_prop, parent_id)
+            self.args.append(prop)
+
+    def get_location(self):
+        op_class = getattr(bpy.types, self.identifier)
+        op_func = getattr(op_class, "execute", None)
+        if op_func is None:
+            op_func = getattr(op_class, "invoke", None)
+        if op_func is None:
+            op_func = getattr(op_class, "poll", None)
+
+        if op_func:
+            op_code = op_func.__code__
+            source_path = op_code.co_filename
+
+            # clear the prefix
+            for p in script_paths:
+                source_path = source_path.split(p)[-1]
+            
+            if source_path[0] in "/\\":
+                source_path= source_path[1:]
+            
+            return source_path, op_code.co_firstlineno
+        else:
+            return None, None
+
+'''
+    def __repr__(self):
+        txt = ''
+        txt += ' * ' + self.identifier + '('
+
+        for arg in self.args:
+            txt += arg.identifier + ', '

@@ Diff output truncated at 10240 characters. @@




More information about the Bf-blender-cvs mailing list