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:
2012-12-20 03:56:22 +00:00
parent e4728bf910
commit 423994bf39
3 changed files with 92 additions and 45 deletions

View File

@@ -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:

View File

@@ -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)

View 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