mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-06 07:51:47 +00:00
Bonsai - fix missing Bonsai Fatal Error UI
Since we added more data to debug info in fcf5614 Fatal Error itself started to fail and was never displayed due some props being inaccessible during load, should be fixed now.
Possible error that were fixed:
```
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 328, in <module>
print(format_debug_info(get_debug_info()))
~~~~~~~~~~~~~~^^
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 117, in get_debug_info
if bpy.data.is_saved:
^^^^^^^^^^^^^^^^^
AttributeError: '_RestrictData' object has no attribute 'is_saved'
Traceback (most recent call last):
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 366, in draw
info = get_debug_info()
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 152, in get_debug_info
bim_props = tool.Blender.get_bim_props()
^^^^
NameError: name 'tool' is not defined. Did you mean: 'bool'?
Traceback (most recent call last):
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 366, in draw
info = get_debug_info()
File "\Blender\5.1\extensions\raw_githubusercontent_com\bonsai\__init__.py", line 141, in get_debug_info
import bonsai.tool as tool
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\__init__.py", line 355, in <module>
print(format_debug_info(get_debug_info()))
~~~~~~~~~~~~~~^^
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\__init__.py", line 141, in get_debug_info
import bonsai.tool as tool
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\__init__.py", line 23, in <module>
from bonsai.tool.attribute import Attribute
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\attribute.py", line 31, in <module>
import bonsai.bim.helper as helper
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\__init__.py", line 28, in <module>
from . import handler, operator, prop, ui
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\handler.py", line 36, in <module>
from bonsai.bim.module.aggregate.decorator import AggregateDecorator
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\module\aggregate\__init__.py", line 21, in <module>
from . import operator, prop, ui
File "\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\bim\module\aggregate\operator.py", line 32, in <module>
class BIM_OT_aggregate_assign_object(bpy.types.Operator, tool.Ifc.Operator):
^^^^^^^^
AttributeError: partially initialized module 'bonsai.tool' from '\Blender\5.1\extensions\.local\lib\python3.13\site-packages\bonsai\tool\__init__.py' has no attribute 'Ifc' (most likely due to a circular import)
```
This commit is contained in:
@@ -40,7 +40,7 @@ import webbrowser
|
||||
from collections import deque
|
||||
from collections.abc import Generator
|
||||
from pathlib import Path
|
||||
from typing import Any, Union
|
||||
from typing import TYPE_CHECKING, Any, Union
|
||||
|
||||
last_commit_hash = "8888888"
|
||||
last_commit_date = "9999999"
|
||||
@@ -72,6 +72,21 @@ REINSTALLED_BBIM_VERSION: Union[str, None] = None
|
||||
REGISTERED_BBIM_PACKAGE: str
|
||||
|
||||
|
||||
def is_registering() -> bool:
|
||||
"""
|
||||
During addon registration ``bpy.context`` and ``bpy.data`` are restricted
|
||||
and you can't access their properties.
|
||||
"""
|
||||
import bpy
|
||||
|
||||
if TYPE_CHECKING or bpy.app.version >= (5, 0, 0):
|
||||
import _bpy_restrict_state as bpy_restrict_state
|
||||
else:
|
||||
import bpy_restrict_state
|
||||
|
||||
return isinstance(bpy.context, bpy_restrict_state._RestrictContext)
|
||||
|
||||
|
||||
def initialize_bbim_semver():
|
||||
"""Initialize `bbim_semver` dictionary.
|
||||
|
||||
@@ -93,9 +108,13 @@ def initialize_bbim_semver():
|
||||
bbim_semver["version"] = version_str
|
||||
|
||||
|
||||
def get_debug_info():
|
||||
def get_debug_info(*, bonsai_failed_to_load: bool = False) -> dict[str, Any]:
|
||||
import bpy
|
||||
|
||||
bbim_version = bbim_semver["version"]
|
||||
|
||||
# All data here should be gettable even in case of `bpy.context` and `bpy.data` being inaccessible
|
||||
# and Bonsai completely failed to load.
|
||||
debug_info = {
|
||||
"os": platform.system(),
|
||||
"os_version": platform.version(),
|
||||
@@ -111,6 +130,14 @@ def get_debug_info():
|
||||
"last_error": last_error,
|
||||
}
|
||||
|
||||
# Can't access blend data or context during registration.
|
||||
# If Bonsai failed to load we cannot safely access any of its properties or its tools
|
||||
# as they may not be registered yet and acessing them will break Bonsai Fatal Error UI.
|
||||
if is_registering() or bonsai_failed_to_load:
|
||||
return debug_info
|
||||
|
||||
import bonsai.tool as tool
|
||||
|
||||
# Add .blend file save information
|
||||
if bpy.data.is_saved:
|
||||
debug_info["blend_file_path"] = bpy.data.filepath
|
||||
@@ -131,7 +158,7 @@ def get_debug_info():
|
||||
return debug_info
|
||||
|
||||
|
||||
def format_debug_info(info: dict):
|
||||
def format_debug_info(info: dict[str, Any]) -> str:
|
||||
last_actions = ""
|
||||
for action in info["last_actions"]:
|
||||
last_actions += f"\n# {action['type']}: {action['name']}"
|
||||
@@ -205,6 +232,8 @@ def clean_up_dlls_safe_links() -> None:
|
||||
|
||||
|
||||
if IN_BLENDER:
|
||||
import bpy
|
||||
|
||||
initialize_bbim_semver()
|
||||
|
||||
def get_binary_info() -> dict[str, Any]:
|
||||
@@ -333,7 +362,7 @@ if IN_BLENDER:
|
||||
bl_context = "scene"
|
||||
|
||||
def draw(self, context):
|
||||
info = get_debug_info()
|
||||
info = get_debug_info(bonsai_failed_to_load=True)
|
||||
|
||||
layout = self.layout
|
||||
layout.alert = True
|
||||
@@ -409,7 +438,7 @@ if IN_BLENDER:
|
||||
bl_description = "Copies debugging information to your clipboard for use in bugreports"
|
||||
|
||||
def execute(self, context):
|
||||
info = get_debug_info()
|
||||
info = get_debug_info(bonsai_failed_to_load=True)
|
||||
info.update(get_binary_info())
|
||||
info = format_debug_info(info)
|
||||
context.window_manager.clipboard = info
|
||||
|
||||
@@ -16,19 +16,12 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with Bonsai. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import ifcopenshell.util.pset
|
||||
|
||||
import bonsai
|
||||
import bonsai.tool as tool
|
||||
|
||||
if TYPE_CHECKING or bpy.app.version >= (5, 0, 0):
|
||||
import _bpy_restrict_state as bpy_restrict_state
|
||||
else:
|
||||
import bpy_restrict_state
|
||||
|
||||
|
||||
class IfcSchema:
|
||||
data_dir: str
|
||||
@@ -62,7 +55,7 @@ class IfcSchema:
|
||||
self.psetqto.get_by_name.cache_clear()
|
||||
|
||||
# During register we cannot access the context either way.
|
||||
if isinstance(bpy.context, bpy_restrict_state._RestrictContext):
|
||||
if bonsai.is_registering():
|
||||
return
|
||||
for path in tool.Blender.get_data_dir_paths("pset", "*.ifc"):
|
||||
self.psetqto.templates.append(ifcopenshell.open(path))
|
||||
|
||||
@@ -24,6 +24,7 @@ import bpy
|
||||
import ifcopenshell
|
||||
import pytest
|
||||
|
||||
import bonsai
|
||||
import bonsai.core.tool
|
||||
import bonsai.tool as tool
|
||||
from bonsai.tool.blender import Blender as subject
|
||||
@@ -144,3 +145,25 @@ class TestGetSelectedFiles(NewFile):
|
||||
assert subject.get_selected_files(Path(g.name).parent, [file], use_relative_path=True) == [
|
||||
Path(g.name).name
|
||||
]
|
||||
|
||||
|
||||
class TestGetDebugInfo(NewFile):
|
||||
# Only keys that are safe to set if Bonsai fails to load.
|
||||
EXPECTED_KEYS = {
|
||||
"os",
|
||||
"os_version",
|
||||
"python_version",
|
||||
"architecture",
|
||||
"machine",
|
||||
"processor",
|
||||
"blender_version",
|
||||
"bonsai_version",
|
||||
"bonsai_commit_hash",
|
||||
"bonsai_commit_date",
|
||||
"last_actions",
|
||||
"last_error",
|
||||
}
|
||||
|
||||
def test_failed_to_load_returns_only_base_keys(self):
|
||||
info = bonsai.get_debug_info(bonsai_failed_to_load=True)
|
||||
assert set(info.keys()) == self.EXPECTED_KEYS
|
||||
|
||||
Reference in New Issue
Block a user