py api: add restrict state context manager (thats python's context not blenders context),
which restricts bpy.context and bpy.data. enable this for loading scripts in 'startup' too.
This commit is contained in:
@@ -31,14 +31,6 @@ __all__ = (
|
|||||||
import bpy as _bpy
|
import bpy as _bpy
|
||||||
_user_preferences = _bpy.context.user_preferences
|
_user_preferences = _bpy.context.user_preferences
|
||||||
|
|
||||||
class _RestrictedContext():
|
|
||||||
__slots__ = ()
|
|
||||||
@property
|
|
||||||
def window_manager(self):
|
|
||||||
return _bpy.data.window_managers[0]
|
|
||||||
_ctx_restricted = _RestrictedContext()
|
|
||||||
|
|
||||||
|
|
||||||
error_duplicates = False
|
error_duplicates = False
|
||||||
error_encoding = False
|
error_encoding = False
|
||||||
addons_fake_modules = {}
|
addons_fake_modules = {}
|
||||||
@@ -240,6 +232,7 @@ def enable(module_name, default_set=True, persistent=False):
|
|||||||
|
|
||||||
import os
|
import os
|
||||||
import sys
|
import sys
|
||||||
|
from bpy_restrict_state import RestrictBlend
|
||||||
|
|
||||||
def handle_error():
|
def handle_error():
|
||||||
import traceback
|
import traceback
|
||||||
@@ -267,37 +260,31 @@ def enable(module_name, default_set=True, persistent=False):
|
|||||||
# Split registering up into 3 steps so we can undo
|
# Split registering up into 3 steps so we can undo
|
||||||
# if it fails par way through.
|
# if it fails par way through.
|
||||||
|
|
||||||
# first disable the context, using the context at all is
|
# disable the context, using the context at all is
|
||||||
# really bad while loading an addon, don't do it!
|
# really bad while loading an addon, don't do it!
|
||||||
ctx = _bpy.context
|
with RestrictBlend():
|
||||||
_bpy.context = _ctx_restricted
|
|
||||||
|
|
||||||
# 1) try import
|
# 1) try import
|
||||||
try:
|
try:
|
||||||
mod = __import__(module_name)
|
mod = __import__(module_name)
|
||||||
mod.__time__ = os.path.getmtime(mod.__file__)
|
mod.__time__ = os.path.getmtime(mod.__file__)
|
||||||
mod.__addon_enabled__ = False
|
mod.__addon_enabled__ = False
|
||||||
except:
|
except:
|
||||||
handle_error()
|
handle_error()
|
||||||
_bpy.context = ctx
|
return None
|
||||||
return None
|
|
||||||
|
|
||||||
# 2) try register collected modules
|
# 2) try register collected modules
|
||||||
# removed, addons need to handle own registration now.
|
# removed, addons need to handle own registration now.
|
||||||
|
|
||||||
# 3) try run the modules register function
|
# 3) try run the modules register function
|
||||||
try:
|
try:
|
||||||
mod.register()
|
mod.register()
|
||||||
except:
|
except:
|
||||||
print("Exception in module register(): %r" %
|
print("Exception in module register(): %r" %
|
||||||
getattr(mod, "__file__", module_name))
|
getattr(mod, "__file__", module_name))
|
||||||
handle_error()
|
handle_error()
|
||||||
del sys.modules[module_name]
|
del sys.modules[module_name]
|
||||||
_bpy.context = ctx
|
return None
|
||||||
return None
|
|
||||||
|
|
||||||
# finally restore the context
|
|
||||||
_bpy.context = ctx
|
|
||||||
|
|
||||||
# * OK loaded successfully! *
|
# * OK loaded successfully! *
|
||||||
if default_set:
|
if default_set:
|
||||||
|
|||||||
@@ -217,18 +217,21 @@ def load_scripts(reload_scripts=False, refresh_scripts=False):
|
|||||||
|
|
||||||
del _global_loaded_modules[:]
|
del _global_loaded_modules[:]
|
||||||
|
|
||||||
for base_path in script_paths():
|
from bpy_restrict_state import RestrictBlend
|
||||||
for path_subdir in _script_module_dirs:
|
|
||||||
path = _os.path.join(base_path, path_subdir)
|
|
||||||
if _os.path.isdir(path):
|
|
||||||
_sys_path_ensure(path)
|
|
||||||
|
|
||||||
# only add this to sys.modules, don't run
|
with RestrictBlend():
|
||||||
if path_subdir == "modules":
|
for base_path in script_paths():
|
||||||
continue
|
for path_subdir in _script_module_dirs:
|
||||||
|
path = _os.path.join(base_path, path_subdir)
|
||||||
|
if _os.path.isdir(path):
|
||||||
|
_sys_path_ensure(path)
|
||||||
|
|
||||||
for mod in modules_from_path(path, loaded_modules):
|
# only add this to sys.modules, don't run
|
||||||
test_register(mod)
|
if path_subdir == "modules":
|
||||||
|
continue
|
||||||
|
|
||||||
|
for mod in modules_from_path(path, loaded_modules):
|
||||||
|
test_register(mod)
|
||||||
|
|
||||||
# deal with addons separately
|
# deal with addons separately
|
||||||
_addon_utils.reset_all(reload_scripts)
|
_addon_utils.reset_all(reload_scripts)
|
||||||
|
|||||||
57
release/scripts/modules/bpy_restrict_state.py
Normal file
57
release/scripts/modules/bpy_restrict_state.py
Normal file
@@ -0,0 +1,57 @@
|
|||||||
|
# ##### 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 #####
|
||||||
|
|
||||||
|
# <pep8-80 compliant>
|
||||||
|
|
||||||
|
"""
|
||||||
|
This module contains RestrictBlend context manager.
|
||||||
|
"""
|
||||||
|
|
||||||
|
__all__ = (
|
||||||
|
"RestrictBlend",
|
||||||
|
)
|
||||||
|
|
||||||
|
import bpy as _bpy
|
||||||
|
|
||||||
|
class _RestrictContext():
|
||||||
|
__slots__ = ()
|
||||||
|
_real_data = _bpy.data
|
||||||
|
@property
|
||||||
|
def window_manager(self):
|
||||||
|
return self._real_data.window_managers[0]
|
||||||
|
|
||||||
|
|
||||||
|
class _RestrictData():
|
||||||
|
__slots__ = ()
|
||||||
|
|
||||||
|
|
||||||
|
_context_restrict = _RestrictContext()
|
||||||
|
_data_restrict = _RestrictData()
|
||||||
|
|
||||||
|
|
||||||
|
class RestrictBlend():
|
||||||
|
__slots__ = ("context", "data")
|
||||||
|
def __enter__(self):
|
||||||
|
self.data = _bpy.data
|
||||||
|
self.context = _bpy.context
|
||||||
|
_bpy.data = _data_restrict
|
||||||
|
_bpy.context = _context_restrict
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
_bpy.data = self.data
|
||||||
|
_bpy.context = self.context
|
||||||
Reference in New Issue
Block a user