[Bf-blender-cvs] [79840abf6d5] master: PyAPI: use real modules for bpy.ops

Campbell Barton noreply at git.blender.org
Thu Oct 8 08:47:36 CEST 2020


Commit: 79840abf6d58af1dab801f4e5718bca0df4ad1a9
Author: Campbell Barton
Date:   Thu Oct 8 17:43:08 2020 +1100
Branches: master
https://developer.blender.org/rB79840abf6d58af1dab801f4e5718bca0df4ad1a9

PyAPI: use real modules for bpy.ops

Python 3.7x added support for module `__getattr__` & `__dir__`.

Make use of this for operator access,
previously these were module like classes.

No functional changes, this is mostly to use a type which is expected,
rather than faking the type with a class instance.

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

M	release/scripts/modules/bpy/__init__.py
M	release/scripts/modules/bpy/ops.py

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

diff --git a/release/scripts/modules/bpy/__init__.py b/release/scripts/modules/bpy/__init__.py
index a80135a59e1..3fc5f54b77b 100644
--- a/release/scripts/modules/bpy/__init__.py
+++ b/release/scripts/modules/bpy/__init__.py
@@ -46,13 +46,11 @@ from _bpy import (
 
 # python modules
 from . import (
+    ops,
     path,
     utils,
 )
 
-# fake operator module
-from .ops import ops_fake_module as ops
-
 
 def main():
     import sys
diff --git a/release/scripts/modules/bpy/ops.py b/release/scripts/modules/bpy/ops.py
index c2245d908b5..39540ac08df 100644
--- a/release/scripts/modules/bpy/ops.py
+++ b/release/scripts/modules/bpy/ops.py
@@ -29,81 +29,11 @@ op_as_string = ops_module.as_string
 op_get_rna_type = ops_module.get_rna_type
 op_get_bl_options = ops_module.get_bl_options
 
+_ModuleType = type(ops_module)
 
-class BPyOps:
-    """
-    Fake module like class.
-
-     bpy.ops
-    """
-    __slots__ = ()
-
-    def __getattr__(self, module):
-        """
-        gets a bpy.ops submodule
-        """
-        if module.startswith('__'):
-            raise AttributeError(module)
-        return BPyOpsSubMod(module)
-
-    def __dir__(self):
-
-        submodules = set()
-
-        # add this classes functions
-        for id_name in dir(self.__class__):
-            if not id_name.startswith('__'):
-                submodules.add(id_name)
-
-        for id_name in op_dir():
-            id_split = id_name.split('_OT_', 1)
-
-            if len(id_split) == 2:
-                submodules.add(id_split[0].lower())
-            else:
-                submodules.add(id_split[0])
-
-        return list(submodules)
-
-    def __repr__(self):
-        return "<module like class 'bpy.ops'>"
-
-
-class BPyOpsSubMod:
-    """
-    Utility class to fake submodules.
-
-    eg. bpy.ops.object
-    """
-    __slots__ = ("_module",)
-
-    def __init__(self, module):
-        self._module = module
-
-    def __getattr__(self, func):
-        """
-        gets a bpy.ops.submodule function
-        """
-        if func.startswith('__'):
-            raise AttributeError(func)
-        return BPyOpsSubModOp(self._module, func)
-
-    def __dir__(self):
-
-        functions = set()
-
-        module_upper = self._module.upper()
-
-        for id_name in op_dir():
-            id_split = id_name.split('_OT_', 1)
-            if len(id_split) == 2 and module_upper == id_split[0]:
-                functions.add(id_split[1])
-
-        return list(functions)
-
-    def __repr__(self):
-        return "<module like class 'bpy.ops.%s'>" % self._module
 
+# -----------------------------------------------------------------------------
+# Callable Operator Wrapper
 
 class BPyOpsSubModOp:
     """
@@ -223,4 +153,53 @@ class BPyOpsSubModOp:
                 (self._module, self._func, id(self)))
 
 
-ops_fake_module = BPyOps()
+# -----------------------------------------------------------------------------
+# Sub-Module Access
+
+def _bpy_ops_submodule__getattr__(module, func):
+    # Return a value from `bpy.ops.{module}.{func}`
+    if func.startswith("__"):
+        raise AttributeError(func)
+    return BPyOpsSubModOp(module, func)
+
+
+def _bpy_ops_submodule__dir__(module):
+    functions = set()
+    module_upper = module.upper()
+
+    for id_name in op_dir():
+        id_split = id_name.split("_OT_", 1)
+        if len(id_split) == 2 and module_upper == id_split[0]:
+            functions.add(id_split[1])
+
+    return list(functions)
+
+
+def _bpy_ops_submodule(module):
+    result = _ModuleType("bpy.ops." + module)
+    result.__getattr__ = lambda func: _bpy_ops_submodule__getattr__(module, func)
+    result.__dir__ = lambda: _bpy_ops_submodule__dir__(module)
+    return result
+
+
+# -----------------------------------------------------------------------------
+# Module Access
+
+def __getattr__(module):
+    # Return a value from `bpy.ops.{module}`.
+    if module.startswith("__"):
+        raise AttributeError(module)
+    return _bpy_ops_submodule(module)
+
+
+def __dir__():
+    submodules = set()
+    for id_name in op_dir():
+        id_split = id_name.split("_OT_", 1)
+
+        if len(id_split) == 2:
+            submodules.add(id_split[0].lower())
+        else:
+            submodules.add(id_split[0])
+
+    return list(submodules)



More information about the Bf-blender-cvs mailing list