mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-24 21:39:59 +00:00
#1349 result formatting
This commit is contained in:
@@ -10,6 +10,22 @@ def error(msg):
|
|||||||
raise exception(msg)
|
raise exception(msg)
|
||||||
|
|
||||||
|
|
||||||
|
class facet_evaluation:
|
||||||
|
"""
|
||||||
|
The evaluation of a facet with data from IFC. Converts to bool and has a human readable string format.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self, success, str):
|
||||||
|
self.success = success
|
||||||
|
self.str = str
|
||||||
|
|
||||||
|
def __bool__(self):
|
||||||
|
return self.success
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.str
|
||||||
|
|
||||||
|
|
||||||
class meta_facet(type):
|
class meta_facet(type):
|
||||||
"""
|
"""
|
||||||
A metaclass for automatically registering facets in a map to be instantiated based on XML tagnames.
|
A metaclass for automatically registering facets in a map to be instantiated based on XML tagnames.
|
||||||
@@ -41,17 +57,30 @@ class facet(metaclass=meta_facet):
|
|||||||
else:
|
else:
|
||||||
return v.firstChild.nodeValue.strip()
|
return v.firstChild.nodeValue.strip()
|
||||||
|
|
||||||
|
def __iter__(self):
|
||||||
|
for k in self.parameters:
|
||||||
|
yield k, getattr(self, k)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.message % dict(list(self))
|
||||||
|
|
||||||
|
|
||||||
class entity(facet):
|
class entity(facet):
|
||||||
"""
|
"""
|
||||||
The IDS entity facet currently *with* inheritance
|
The IDS entity facet currently *with* inheritance
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
parameters = ["name"]
|
||||||
|
message = "an entity name '%(name)s'"
|
||||||
|
|
||||||
def __call__(self, inst, logger):
|
def __call__(self, inst, logger):
|
||||||
logger.debug("Testing %s == %s", inst.is_a(), self.name)
|
logger.debug("Testing %s == %s", inst.is_a(), self.name)
|
||||||
# @nb with inheritance
|
# @nb with inheritance
|
||||||
# return inst.is_a() == self.name
|
# return inst.is_a() == self.name
|
||||||
return inst.is_a(self.name)
|
return facet_evaluation(
|
||||||
|
inst.is_a(self.name),
|
||||||
|
self.message % {'name':inst.is_a()}
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class classification(facet):
|
class classification(facet):
|
||||||
@@ -59,6 +88,9 @@ class classification(facet):
|
|||||||
The IDS classification facet by traversing the HasAssociations inverse attribute
|
The IDS classification facet by traversing the HasAssociations inverse attribute
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
parameters = ["system", "value"]
|
||||||
|
message = "a classification reference to '%(value)s' from '%(system)s'"
|
||||||
|
|
||||||
def __call__(self, inst, logger):
|
def __call__(self, inst, logger):
|
||||||
refs = []
|
refs = []
|
||||||
for association in inst.HasAssociations:
|
for association in inst.HasAssociations:
|
||||||
@@ -66,7 +98,12 @@ class classification(facet):
|
|||||||
cref = association.RelatingClassification
|
cref = association.RelatingClassification
|
||||||
refs.append((cref.ReferencedSource, cref.Name))
|
refs.append((cref.ReferencedSource, cref.Name))
|
||||||
|
|
||||||
return (self.system, self.value) in refs
|
return facet_evaluation(
|
||||||
|
(self.system, self.value) in refs,
|
||||||
|
# @todo
|
||||||
|
''
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class property(facet):
|
class property(facet):
|
||||||
@@ -74,11 +111,33 @@ class property(facet):
|
|||||||
The IDS property facet implenented using `ifcopenshell.util.element`
|
The IDS property facet implenented using `ifcopenshell.util.element`
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
parameters = ["property", "propertyset", "value"]
|
||||||
|
message = "a property '%(property)s' in '%(propertyset)s' with value '%(value)s'"
|
||||||
|
|
||||||
def __call__(self, inst, logger):
|
def __call__(self, inst, logger):
|
||||||
props = ifcopenshell.util.element.get_psets(inst)
|
props = ifcopenshell.util.element.get_psets(inst)
|
||||||
val = props.get(self.propertyset, {}).get(self.property)
|
pset = props.get(self.propertyset)
|
||||||
|
val = pset.get(self.property) if pset else None
|
||||||
logger.debug("Testing %s == %s", val, self.value)
|
logger.debug("Testing %s == %s", val, self.value)
|
||||||
return val == self.value
|
|
||||||
|
di = {
|
||||||
|
'property': self.property,
|
||||||
|
'propertyset': self.propertyset,
|
||||||
|
'value': val
|
||||||
|
}
|
||||||
|
|
||||||
|
if val is not None:
|
||||||
|
msg = self.message % di
|
||||||
|
else:
|
||||||
|
if pset:
|
||||||
|
msg = "a set '%(propertyset)s', but no property '%(property)'" % di
|
||||||
|
else:
|
||||||
|
msg = "no set '%(propertyset)s'" % di
|
||||||
|
|
||||||
|
return facet_evaluation(
|
||||||
|
val == self.value,
|
||||||
|
msg
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class boolean_logic:
|
class boolean_logic:
|
||||||
@@ -90,7 +149,15 @@ class boolean_logic:
|
|||||||
self.terms = terms
|
self.terms = terms
|
||||||
|
|
||||||
def __call__(self, *args):
|
def __call__(self, *args):
|
||||||
return self.fold(t(*args) for t in self.terms)
|
eval = [t(*args) for t in self.terms]
|
||||||
|
join = [" and ", " or "][self.fold == any]
|
||||||
|
return facet_evaluation(
|
||||||
|
self.fold(eval),
|
||||||
|
join.join(map(str, eval))
|
||||||
|
)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return [" and ", " or "][self.fold == any].join(map(str, self.terms))
|
||||||
|
|
||||||
|
|
||||||
class boolean_and(boolean_logic):
|
class boolean_and(boolean_logic):
|
||||||
@@ -117,7 +184,7 @@ class restriction:
|
|||||||
return other in self.options
|
return other in self.options
|
||||||
|
|
||||||
def __repr__(self):
|
def __repr__(self):
|
||||||
return "|".join(self.options)
|
return " or ".join(self.options)
|
||||||
|
|
||||||
|
|
||||||
class specification:
|
class specification:
|
||||||
@@ -144,10 +211,14 @@ class specification:
|
|||||||
|
|
||||||
def __call__(self, inst, logger):
|
def __call__(self, inst, logger):
|
||||||
if self.applicabiliy(inst, logger):
|
if self.applicabiliy(inst, logger):
|
||||||
if self.requirements(inst, logger):
|
valid = self.requirements(inst, logger)
|
||||||
logger.info("%s is compliant", inst)
|
if valid:
|
||||||
|
logger.info(str(self) + "\n%s has" % inst + " " + str(valid) + " so is compliant")
|
||||||
else:
|
else:
|
||||||
logger.error("%s not compliant", inst)
|
logger.error(str(self) + "\n%s has" % inst + " " + str(valid) + " so is not compliant")
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return "Given an instance with %(applicabiliy)s\nWe expect %(requirements)s" % self.__dict__
|
||||||
|
|
||||||
|
|
||||||
class ids:
|
class ids:
|
||||||
@@ -167,8 +238,8 @@ class ids:
|
|||||||
]
|
]
|
||||||
|
|
||||||
def validate(self, ifc_file, logger):
|
def validate(self, ifc_file, logger):
|
||||||
for elem in ifc_file.by_type("IfcObject"):
|
for spec in self.specifications:
|
||||||
for spec in self.specifications:
|
for elem in ifc_file.by_type("IfcObject"):
|
||||||
spec(elem, logger)
|
spec(elem, logger)
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user