[Bf-extensions-cvs] [e529809c] master: development_edit_operator: returned to release: T63750 c983a2472846 T68541

meta-androcto noreply at git.blender.org
Mon Sep 2 13:32:02 CEST 2019


Commit: e529809cf6513748776a878338109ecf960d1326
Author: meta-androcto
Date:   Mon Sep 2 21:31:44 2019 +1000
Branches: master
https://developer.blender.org/rBAe529809cf6513748776a878338109ecf960d1326

development_edit_operator: returned to release: T63750 c983a2472846 T68541

===================================================================

A	development_edit_operator.py

===================================================================

diff --git a/development_edit_operator.py b/development_edit_operator.py
new file mode 100644
index 00000000..08e91d87
--- /dev/null
+++ b/development_edit_operator.py
@@ -0,0 +1,337 @@
+# ##### BEGIN GPL LICENSE BLOCK #####
+#
+#  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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+#
+# ##### END GPL LICENSE BLOCK #####
+
+
+bl_info = {
+    "name": "Edit Operator Source",
+    "author": "scorpion81",
+    "version": (1, 2, 2),
+    "blender": (2, 80, 0),
+    "location": "Text Editor > Edit > Edit Operator",
+    "description": "Opens source file of chosen operator or call locations, if source not available",
+    "warning": "",
+    "wiki_url": "https://wiki.blender.org/index.php/Extensions:2.6/"
+                "Py/Scripts/Development/Edit_Operator_Source",
+    "category": "Development"}
+
+import bpy
+import sys
+import os
+import inspect
+from bpy.types import (
+        Operator,
+        Panel,
+        Header,
+        Menu,
+        PropertyGroup
+        )
+from bpy.props import ( 
+        EnumProperty,
+        StringProperty,
+        IntProperty
+        )
+
+def stdlib_excludes():
+    #need a handy list of modules to avoid walking into
+    import distutils.sysconfig as sysconfig
+    excludes = []
+    std_lib = sysconfig.get_python_lib(standard_lib=True)
+    for top, dirs, files in os.walk(std_lib):
+        for nm in files:
+            if nm != '__init__.py' and nm[-3:] == '.py':
+                excludes.append(os.path.join(top, nm)[len(std_lib)+1:-3].replace('\\','.'))
+    
+    return excludes
+
+def make_loc(prefix, c):
+    #too long and not helpful... omitting for now
+    space = ""
+    #if hasattr(c, "bl_space_type"):
+    #    space = c.bl_space_type
+        
+    region = ""
+    #if hasattr(c, "bl_region_type"):
+    #   region = c.bl_region_type
+        
+    label = ""
+    if hasattr(c, "bl_label"):
+        label = c.bl_label
+    
+    return prefix+": " + space + " " + region + " " + label
+
+def walk_module(opname, mod, calls=[], exclude=[]):
+    
+    for name, m in inspect.getmembers(mod):
+        if inspect.ismodule(m):
+            if m.__name__ not in exclude:
+                #print(name, m.__name__)
+                walk_module(opname, m, calls, exclude)
+        elif inspect.isclass(m):
+            if (issubclass(m, Panel) or \
+                issubclass(m, Header) or \
+                issubclass(m, Menu)) and mod.__name__ != "bl_ui":
+                if hasattr(m, "draw"):
+                    loc = ""
+                    file = ""
+                    line = -1
+                    src, n = inspect.getsourcelines(m.draw)
+                    for i, s in enumerate(src):
+                        if opname in s:
+                            file = mod.__file__
+                            line = n + i
+                        
+                            if issubclass(m, Panel) and name != "Panel":
+                                loc = make_loc("Panel", m)
+                                calls.append([opname, loc, file, line])
+                            if issubclass(m, Header) and name != "Header":
+                                loc = make_loc("Header", m)
+                                calls.append([opname, loc, file, line])
+                            if issubclass(m, Menu) and name != "Menu":
+                                loc = make_loc("Menu", m)
+                                calls.append([opname, loc, file, line])
+
+
+def getclazz(opname):
+    opid = opname.split(".")
+    opmod = getattr(bpy.ops, opid[0])
+    op = getattr(opmod, opid[1])
+    id = op.get_rna_type().bl_rna.identifier
+    try:
+        clazz = getattr(bpy.types, id)
+        return clazz
+    except AttributeError:
+        return None
+
+
+def getmodule(opname):
+    addon = True
+    clazz = getclazz(opname)
+    
+    if clazz is None:
+        return  "", -1, False
+    
+    modn = clazz.__module__
+
+    try:
+        line = inspect.getsourcelines(clazz)[1]
+    except IOError:
+        line = -1
+    except TypeError:
+        line = -1
+
+    if modn == 'bpy.types':
+        mod = 'C operator'
+        addon = False
+    elif modn != '__main__':
+        mod = sys.modules[modn].__file__
+    else:
+        addon = False
+        mod = modn
+
+    return mod, line, addon
+
+
+def get_ops():
+    allops = []
+    opsdir = dir(bpy.ops)
+    for opmodname in opsdir:
+        opmod = getattr(bpy.ops, opmodname)
+        opmoddir = dir(opmod)
+        for o in opmoddir:
+            name = opmodname + "." + o
+            clazz = getclazz(name)
+            #if (clazz is not None) :# and clazz.__module__ != 'bpy.types'):
+            allops.append(name)
+        del opmoddir
+
+    # add own operator name too, since its not loaded yet when this is called
+    allops.append("text.edit_operator")
+    l = sorted(allops)
+    del allops
+    del opsdir
+
+    return [(y, y, "", x) for x, y in enumerate(l)]
+
+class OperatorEntry(PropertyGroup):
+    
+    label : StringProperty(
+            name="Label",
+            description="",
+            default=""
+            )
+             
+    path : StringProperty(
+            name="Path",
+            description="",
+            default=""
+            )
+            
+    line : IntProperty(
+            name="Line",
+            description="",
+            default=-1
+            ) 
+
+class TEXT_OT_EditOperator(Operator):
+    bl_idname = "text.edit_operator"
+    bl_label = "Edit Operator"
+    bl_description = "Opens the source file of operators chosen from Menu"
+    bl_property = "op"
+
+    items = get_ops()
+
+    op : EnumProperty(
+            name="Op",
+            description="",
+            items=items
+            )
+            
+    path : StringProperty(
+            name="Path",
+            description="",
+            default=""
+            )
+            
+    line : IntProperty(
+            name="Line",
+            description="",
+            default=-1
+            )
+            
+    def show_text(self, context, path, line):
+        found = False
+        
+        for t in bpy.data.texts:
+            if t.filepath == path:
+                #switch to the wanted text first
+                context.space_data.text = t
+                ctx = context.copy()
+                ctx['edit_text'] = t
+                bpy.ops.text.jump(ctx, line=line)
+                found = True
+                break
+
+        if (found is False):
+            self.report({'INFO'},
+                        "Opened file: " + path)
+            bpy.ops.text.open(filepath=path)
+            bpy.ops.text.jump(line=line)
+            
+    def show_calls(self, context):
+        import bl_ui
+        import addon_utils
+        
+        exclude = stdlib_excludes()
+        exclude.append("bpy")
+        exclude.append("sys")
+        
+        calls = []
+        walk_module(self.op, bl_ui, calls, exclude)
+        
+        for m in addon_utils.modules():
+            try:
+                mod = sys.modules[m.__name__]
+                walk_module(self.op, mod, calls, exclude)
+            except KeyError:
+                continue
+            
+        for c in calls:
+            cl = context.scene.calls.add()
+            cl.name = c[0]
+            cl.label = c[1]
+            cl.path = c[2]
+            cl.line = c[3]
+
+    def invoke(self, context, event):
+        context.window_manager.invoke_search_popup(self)
+        return {'PASS_THROUGH'}
+
+    def execute(self, context):
+        if self.path != "" and self.line != -1:
+            #invocation of one of the "found" locations
+            self.show_text(context, self.path, self.line)
+            return {'FINISHED'} 
+        else:
+            context.scene.calls.clear()
+            path, line, addon = getmodule(self.op)
+            
+            if addon:
+                self.show_text(context, path, line)
+                
+                #add convenient "source" button, to toggle back from calls to source
+                c = context.scene.calls.add()
+                c.name = self.op
+                c.label = "Source"
+                c.path = path
+                c.line = line
+                
+                self.show_calls(context)
+                context.area.tag_redraw()
+                
+                return {'FINISHED'}
+            else:
+                
+                self.report({'WARNING'},
+                            "Found no source file for " + self.op)
+                            
+                self.show_calls(context)
+                context.area.tag_redraw()
+               
+                return {'FINISHED'}
+
+
+class TEXT_PT_EditOperatorPanel(Panel):
+    bl_space_type = 'TEXT_EDITOR'
+    bl_region_type = 'UI'
+    bl_label = "Edit Operator"
+    bl_category = "Text"
+
+    def draw(self, context):
+        layout = self.layout
+        op = layout.operator("text.edit_operator")
+        op.path = ""
+        op.line = -1
+        
+        if len(context.scene.calls) > 0:
+            box = layout.box()
+            box.label(text="Calls of: " + context.scene.calls[0].name)
+            box.operator_context = 'EXEC_DEFAULT'
+            for c in context.scene.calls:
+                op = box.operator("text.edit_operator", text=c.label)
+                op.path = c.path
+                op.line = c.line
+                op.op = c.name
+
+
+def register():
+    bpy.utils.register_class(OperatorEntry)
+    bpy.types.Scene.calls = bpy.props.CollectionProperty(name

@@ Diff output truncated at 10240 characters. @@



More information about the Bf-extensions-cvs mailing list