mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-09 21:53:40 +00:00
Distinguish between nil and derived in validate.py
This commit is contained in:
@@ -284,7 +284,16 @@ def validate(f, logger):
|
|||||||
It is recommended to supply the path to the file, so that internal C++ errors reported during the parse stage
|
It is recommended to supply the path to the file, so that internal C++ errors reported during the parse stage
|
||||||
are also captured.
|
are also captured.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
# Originally there was no way in Python to distinguish on an entity instance attribute value whether the
|
||||||
|
# value supplied in the model was NIL ($) or 'missing because derived in subtype' (*). For validation this
|
||||||
|
# however this may be important, and hence a feature switch has been implemented to return *-values as
|
||||||
|
# instances of a dedicated type `ifcopenshell.ifcopenshell_wrapper.attribute_value_derived`.
|
||||||
|
attribute_value_derived_org = ifcopenshell.ifcopenshell_wrapper.get_feature('use_attribute_value_derived')
|
||||||
|
ifcopenshell.ifcopenshell_wrapper.set_feature('use_attribute_value_derived', True)
|
||||||
|
|
||||||
filename = None
|
filename = None
|
||||||
|
|
||||||
if not isinstance(f, ifcopenshell.file):
|
if not isinstance(f, ifcopenshell.file):
|
||||||
|
|
||||||
# get_log() clears log existing output
|
# get_log() clears log existing output
|
||||||
@@ -335,7 +344,18 @@ def validate(f, logger):
|
|||||||
zip(attrs, values, entity.derived())
|
zip(attrs, values, entity.derived())
|
||||||
):
|
):
|
||||||
|
|
||||||
if val is None and not (is_derived or attr.optional()):
|
if is_derived and not isinstance(val, ifcopenshell.ifcopenshell_wrapper.attribute_value_derived):
|
||||||
|
if hasattr(logger, "set_instance"):
|
||||||
|
logger.error("Attribute %s.%s is derived in subtype", entity, attr)
|
||||||
|
else:
|
||||||
|
logger.error(
|
||||||
|
"For instance:\n %s\n %s\nWith attribute:\n %s\nDerived in subtype\n",
|
||||||
|
inst,
|
||||||
|
annotate_inst_attr_pos(inst, i),
|
||||||
|
attr,
|
||||||
|
)
|
||||||
|
|
||||||
|
if val is None and not attr.optional() and not is_derived:
|
||||||
if hasattr(logger, "set_instance"):
|
if hasattr(logger, "set_instance"):
|
||||||
logger.error("Attribute %s.%s not optional", entity, attr)
|
logger.error("Attribute %s.%s not optional", entity, attr)
|
||||||
else:
|
else:
|
||||||
@@ -346,7 +366,7 @@ def validate(f, logger):
|
|||||||
attr,
|
attr,
|
||||||
)
|
)
|
||||||
|
|
||||||
if val is not None:
|
if val is not None and not is_derived:
|
||||||
attr_type = attr.type_of_attribute()
|
attr_type = attr.type_of_attribute()
|
||||||
try:
|
try:
|
||||||
assert_valid(attr_type, val, schema, attr=attr)
|
assert_valid(attr_type, val, schema, attr=attr)
|
||||||
@@ -379,6 +399,8 @@ def validate(f, logger):
|
|||||||
# are verified.
|
# are verified.
|
||||||
log_internal_cpp_errors(filename, logger)
|
log_internal_cpp_errors(filename, logger)
|
||||||
|
|
||||||
|
# Restore the original value for 'use_attribute_value_derived'
|
||||||
|
ifcopenshell.ifcopenshell_wrapper.set_feature('use_attribute_value_derived', attribute_value_derived_org)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
import sys
|
import sys
|
||||||
|
|||||||
@@ -54,7 +54,41 @@ private:
|
|||||||
%rename("add") addEntity;
|
%rename("add") addEntity;
|
||||||
%rename("remove") removeEntity;
|
%rename("remove") removeEntity;
|
||||||
|
|
||||||
|
class attribute_value_derived {};
|
||||||
%{
|
%{
|
||||||
|
class attribute_value_derived {};
|
||||||
|
%}
|
||||||
|
|
||||||
|
%extend attribute_value_derived {
|
||||||
|
%pythoncode %{
|
||||||
|
def __bool__(self): return False
|
||||||
|
def __repr__(self): return '*'
|
||||||
|
%}
|
||||||
|
}
|
||||||
|
|
||||||
|
%inline %{
|
||||||
|
static bool feature_use_attribute_value_derived = false;
|
||||||
|
|
||||||
|
void set_feature(const std::string& x, PyObject* v) {
|
||||||
|
if (PyBool_Check(v) && x == "use_attribute_value_derived") {
|
||||||
|
feature_use_attribute_value_derived = v == Py_True;
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Invalid feature specification");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
PyObject* get_feature(const std::string& x) {
|
||||||
|
if (x == "use_attribute_value_derived") {
|
||||||
|
return PyBool_FromLong(feature_use_attribute_value_derived);
|
||||||
|
} else {
|
||||||
|
throw std::runtime_error("Invalid feature specification");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
%}
|
||||||
|
|
||||||
|
%{
|
||||||
|
|
||||||
static const std::string& helper_fn_declaration_get_name(const IfcParse::declaration* decl) {
|
static const std::string& helper_fn_declaration_get_name(const IfcParse::declaration* decl) {
|
||||||
return decl->name();
|
return decl->name();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,9 +38,16 @@
|
|||||||
try {
|
try {
|
||||||
const Argument& arg = *($1.second);
|
const Argument& arg = *($1.second);
|
||||||
const IfcUtil::ArgumentType type = $1.first;
|
const IfcUtil::ArgumentType type = $1.first;
|
||||||
if (arg.isNull() || type == IfcUtil::Argument_DERIVED) {
|
if (arg.isNull()) {
|
||||||
Py_INCREF(Py_None);
|
Py_INCREF(Py_None);
|
||||||
$result = Py_None;
|
$result = Py_None;
|
||||||
|
} else if (type == IfcUtil::Argument_DERIVED) {
|
||||||
|
if (feature_use_attribute_value_derived) {
|
||||||
|
$result = SWIG_NewPointerObj(new attribute_value_derived, SWIGTYPE_p_attribute_value_derived, SWIG_POINTER_OWN);
|
||||||
|
} else {
|
||||||
|
Py_INCREF(Py_None);
|
||||||
|
$result = Py_None;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
switch(type) {
|
switch(type) {
|
||||||
case IfcUtil::Argument_INT: {
|
case IfcUtil::Argument_INT: {
|
||||||
|
|||||||
Reference in New Issue
Block a user