You can now load the active IFC file into a BIMTester audit. Rapid auditing go go go!

This commit is contained in:
Dion Moult
2021-02-02 20:45:56 +11:00
parent c3f7410f76
commit 5a722a792a
5 changed files with 108 additions and 156 deletions
@@ -18,56 +18,37 @@ def before_all(context):
if context.config.lang:
switch_locale(userdata.get("localedir"), context.config.lang)
context.ifc_path = userdata["ifc"]
context.ifc_basename = os.path.basename(
os.path.splitext(context.ifc_path)[0]
)
continue_after_failed = userdata.getbool(
"runner.continue_after_failed_step", True
)
continue_after_failed = userdata.getbool("runner.continue_after_failed_step", True)
Scenario.continue_after_failed_step = continue_after_failed
# keep out path
context.outpath = os.path.join(this_path, "..")
# TODO: refactor smart view support into a decoupled module
# context.ifc_path = userdata.get("ifc", "")
# context.ifc_basename = os.path.basename(
# os.path.splitext(context.ifc_path)[0]
# )
# since bimtesterfc directory in tmp is removed on every run
# neither log file nor sm file does need to be explicit removed first
# context.outpath = os.path.join(this_path, "..")
# set up log file
context.thelogfile = os.path.join(
context.outpath,
context.ifc_basename + ".log"
)
create_logfile(
context.thelogfile,
context.ifc_basename,
)
# context.thelogfile = os.path.join(context.outpath, context.ifc_basename + ".log")
# create_logfile(
# context.thelogfile,
# context.ifc_basename,
# )
# set up smart view file
context.smview_file = os.path.join(
context.outpath,
context.ifc_basename + ".bcsv"
)
create_zoom_smartview(
context.smview_file,
context.ifc_basename,
)
# # set up smart view file
# context.smview_file = os.path.join(context.outpath, context.ifc_basename + ".bcsv")
# create_zoom_smartview(
# context.smview_file,
# context.ifc_basename,
# )
def after_step(context, step):
if step.status == "failed":
# append log file
append_logfile(context, step)
# extend smart view
if hasattr(context, "falseguids"):
# print(context.falseguids)
append_zoom_smartview(
context.smview_file,
step.name,
context.falseguids
)
pass
# TODO: refactor smart view support into a decoupled module
#if step.status == "failed":
# # append log file
# append_logfile(context, step)
# # extend smart view
# if hasattr(context, "falseguids"):
# append_zoom_smartview(context.smview_file, step.name, context.falseguids)
@@ -4,7 +4,8 @@ from . import ui, prop, operator
classes = (
operator.ExecuteBIMTester,
operator.BIMTesterPurge,
operator.SelectFeaturesDir,
operator.SelectFeature,
operator.SelectBIMTesterIfcFile,
operator.RejectElement,
operator.ApproveClass,
operator.RejectClass,
@@ -1,10 +1,11 @@
import os
import bpy
import tempfile
import webbrowser
import ifcopenshell
import bimtester
import bimtester.run
import bimtester.reports
import os
import webbrowser
from pathlib import Path
from itertools import cycle
from blenderbim.bim.ifc import IfcStore
@@ -15,33 +16,26 @@ class ExecuteBIMTester(bpy.types.Operator):
bl_label = "Execute BIMTester"
def execute(self, context):
props = context.scene.BimTesterProperties
filename = os.path.join(
bpy.context.scene.BimTesterProperties.features_dir,
bpy.context.scene.BimTesterProperties.features_file + ".feature",
)
cwd = os.getcwd()
os.chdir(bpy.context.scene.BimTesterProperties.features_dir)
bimtester.run.run_tests({
"advanced_arguments": "",
"console": False,
"featuresdir": "",
"feature": filename,
"gui": False,
"ifcfile": "",
"purge": False,
"path": "",
})
bimtester.reports.generate_report()
webbrowser.open(
"file://"
+ os.path.join(
bpy.context.scene.BimTesterProperties.features_dir,
"report",
bpy.context.scene.BimTesterProperties.features_file + ".feature.html",
)
)
os.chdir(cwd)
with tempfile.TemporaryDirectory() as dirpath:
report = os.path.join(dirpath, "{}.html".format(props.feature))
args = {
"action": "run",
"advanced_arguments": "",
"console": False,
"feature": props.feature,
"ifc": props.ifc_file,
"path": "",
"report": report,
"schema": "",
"lang": "en"
}
use_stored_ifc = props.should_load_from_memory and IfcStore.get_file()
runner = bimtester.run.TestRunner(args["ifc"], ifc=IfcStore.get_file() if use_stored_ifc else None)
report_json = runner.run(args)
bimtester.reports.ReportGenerator().generate(report_json, args["report"])
webbrowser.open("file://" + report)
return {"FINISHED"}
@@ -50,7 +44,6 @@ class BIMTesterPurge(bpy.types.Operator):
bl_label = "Purge Tests"
def execute(self, context):
filename = os.path.join(
bpy.context.scene.BimTesterProperties.features_dir,
bpy.context.scene.BimTesterProperties.features_file + ".feature",
@@ -62,15 +55,31 @@ class BIMTesterPurge(bpy.types.Operator):
return {"FINISHED"}
class SelectFeaturesDir(bpy.types.Operator):
bl_idname = "bim.select_features_dir"
bl_label = "Select Features Directory"
class SelectFeature(bpy.types.Operator):
bl_idname = "bim.select_feature"
bl_label = "Select Feature"
filename_ext = ".feature"
filter_glob: bpy.props.StringProperty(default="*.feature", options={"HIDDEN"})
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
def execute(self, context):
bpy.context.scene.BimTesterProperties.features_dir = (
os.path.dirname(os.path.abspath(self.filepath)) if "." in self.filepath else self.filepath
)
bpy.context.scene.BimTesterProperties.feature = self.filepath
return {"FINISHED"}
def invoke(self, context, event):
context.window_manager.fileselect_add(self)
return {"RUNNING_MODAL"}
class SelectBIMTesterIfcFile(bpy.types.Operator):
bl_idname = "bim.select_bimtester_ifc_file"
bl_label = "Select BIMTester IFC File"
filename_ext = ".ifc"
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
def execute(self, context):
context.scene.BimTesterProperties.ifc_file = self.filepath
return {"FINISHED"}
def invoke(self, context, event):
@@ -2,6 +2,7 @@ import os
from pathlib import Path
from blenderbim.bim.ifc import IfcStore
from blenderbim.bim.prop import StrProperty
from blenderbim.bim.module.root.prop import getIfcClasses
from bpy.types import PropertyGroup
from bpy.props import (
PointerProperty,
@@ -15,53 +16,16 @@ from bpy.props import (
)
scenarios_enum = []
featuresfiles_enum = []
classes_enum = []
def getIfcClasses(self, context): # This is a copy of the one in bim.prop (as it is used in other modules, can be refactored later)
global classes_enum
file = IfcStore.get_file()
if len(classes_enum) < 1 and file:
declaration = IfcStore.get_schema().declaration_by_name(self.ifc_product)
def get_classes(declaration):
results = []
if not declaration.is_abstract():
results.append(declaration.name())
for subtype in declaration.subtypes():
results.extend(get_classes(subtype))
return results
classes = get_classes(declaration)
classes_enum.extend([(c, c, "") for c in sorted(classes)])
return classes_enum
def getFeaturesFiles(self, context):
global featuresfiles_enum
if len(featuresfiles_enum) < 1:
featuresfiles_enum.clear()
for filename in Path(context.scene.BimTesterProperties.features_dir).glob("*.feature"):
f = str(filename.stem)
featuresfiles_enum.append((f, f, ""))
return featuresfiles_enum
def refreshFeaturesFiles(self, context):
global featuresfiles_enum
featuresfiles_enum.clear()
getFeaturesFiles(self, context)
def getScenarios(self, context):
global scenarios_enum
if len(scenarios_enum) < 1:
scenarios_enum.clear()
if context.scene.BimTesterProperties.features_file != '': # To handle the error when no .feature file exists in the folder
filename = os.path.join(
context.scene.BimTesterProperties.features_dir, context.scene.BimTesterProperties.features_file + ".feature"
)
with open(filename, "r") as feature_file:
if context.scene.BimTesterProperties.feature != "":
with open(context.scene.BimTesterProperties.feature, "r") as feature_file:
lines = feature_file.readlines()
for line in lines:
if "Scenario:" in line:
@@ -77,13 +41,9 @@ def refreshScenarios(self, context):
class BimTesterProperties(PropertyGroup):
features_dir: StringProperty(default="", name="Features Directory", update=refreshFeaturesFiles)
features_file: EnumProperty(items=getFeaturesFiles, name="Features File", update=refreshScenarios)
feature: StringProperty(default="", name="Feature File", update=refreshScenarios)
ifc_file: StringProperty(default="", name="IFC File")
audit_ifc_class: EnumProperty(items=getIfcClasses, name="Audit Class")
qa_reject_element_reason: StringProperty(name="Element Rejection Reason")
scenario: EnumProperty(items=getScenarios, name="Scenario")
# should_load_from_memory: BoolProperty(default=False, name="Load from Memory") # can be added later to mimic the functionality in the CSV Module
should_load_from_memory: BoolProperty(default=False, name="Load from Memory")
@@ -1,5 +1,5 @@
import bpy
from bpy.types import Panel
from blenderbim.bim.ifc import IfcStore
class BIM_PT_qa(Panel):
@@ -11,47 +11,48 @@ class BIM_PT_qa(Panel):
bl_context = "scene"
def draw(self, context):
layout = self.layout
layout.use_property_split = True
self.layout.use_property_split = True
scene = context.scene
bimtester_properties = bpy.context.scene.BimTesterProperties
props = context.scene.BimTesterProperties
layout.label(text="Gherkin Setup:")
if IfcStore.get_file():
row = self.layout.row()
row.prop(props, "should_load_from_memory")
row = layout.row(align=True)
row.prop(bimtester_properties, "features_dir")
row.operator("bim.select_features_dir", icon="FILE_FOLDER", text="")
if not IfcStore.get_file() or not props.should_load_from_memory:
row = self.layout.row(align=True)
row.prop(props, "ifc_file")
row.operator("bim.select_bimtester_ifc_file", icon="FILE_FOLDER", text="")
if bimtester_properties.features_dir:
row = layout.row(align=True)
row.prop(bimtester_properties, "features_file")
row = self.layout.row(align=True)
row.prop(props, "feature")
row.operator("bim.select_feature", icon="FILE_FOLDER", text="")
row = layout.row(align=True)
row.prop(bimtester_properties, "scenario")
else:
return
has_ifc_file = (IfcStore.get_file() and props.should_load_from_memory) or (
props.ifc_file and not props.should_load_from_memory
)
if str(context.scene.BimTesterProperties.features_file) != '': # To handle the error when no .feature file exists in the folder
row = layout.row()
row.operator("bim.execute_bim_tester")
row = self.layout.row(align=True)
row.operator("bim.execute_bim_tester")
row.operator("bim.bim_tester_purge")
row = layout.row()
row.operator("bim.bim_tester_purge")
if props.feature and has_ifc_file:
self.layout.label(text="Scenario Authoring:")
layout.label(text="Quality Auditing:")
row = self.layout.row(align=True)
row.prop(props, "scenario")
row = layout.row()
row.prop(bimtester_properties, "qa_reject_element_reason")
row = layout.row()
row = self.layout.row()
row.prop(props, "qa_reject_element_reason")
row = self.layout.row()
row.operator("bim.reject_element")
row = layout.row()
row.prop(bimtester_properties, "audit_ifc_class")
row = self.layout.row()
row.prop(props, "audit_ifc_class")
row = layout.row(align=True)
row = self.layout.row(align=True)
row.operator("bim.approve_class")
row.operator("bim.reject_class")
row = layout.row()
row = self.layout.row()
row.operator("bim.select_audited")