diff --git a/src/ifcopenshell-python/ifcopenshell/entity_instance.py b/src/ifcopenshell-python/ifcopenshell/entity_instance.py index ea58268322..2b5015cb85 100644 --- a/src/ifcopenshell-python/ifcopenshell/entity_instance.py +++ b/src/ifcopenshell-python/ifcopenshell/entity_instance.py @@ -152,6 +152,8 @@ class entity_instance(object): idx, entity_instance.unwrap_value(value) ) except BaseException as e: + import traceback + traceback.print_exc() valid = False if not valid: diff --git a/src/ifcparse/IfcParse.cpp b/src/ifcparse/IfcParse.cpp index 1ce886a0fb..b8074cb1b6 100644 --- a/src/ifcparse/IfcParse.cpp +++ b/src/ifcparse/IfcParse.cpp @@ -1212,6 +1212,11 @@ void IfcEntityInstanceData::setArgument(size_t i, Argument* a, IfcUtil::Argument case IfcUtil::Argument_BOOL: copy->set(static_cast(*a)); break; + case IfcUtil::Argument_LOGICAL: { + boost::logic::tribool tb = *a; + copy->set(tb); + break; + } case IfcUtil::Argument_DOUBLE: copy->set(static_cast(*a)); break; diff --git a/src/ifcparse/IfcWrite.cpp b/src/ifcparse/IfcWrite.cpp index 6fa3ac7dd3..4ff08eec48 100644 --- a/src/ifcparse/IfcWrite.cpp +++ b/src/ifcparse/IfcWrite.cpp @@ -229,6 +229,7 @@ void StringBuilderVisitor::operator()(const std::vector< std::vector >& IfcWriteArgument::operator int() const { return as(); } IfcWriteArgument::operator bool() const { return as(); } +IfcWriteArgument::operator boost::logic::tribool() const { return as(); } IfcWriteArgument::operator double() const { return as(); } IfcWriteArgument::operator std::string() const { if (type() == IfcUtil::Argument_ENUMERATION) { diff --git a/src/ifcparse/IfcWrite.h b/src/ifcparse/IfcWrite.h index c9300df91e..502ec21f1e 100644 --- a/src/ifcparse/IfcWrite.h +++ b/src/ifcparse/IfcWrite.h @@ -145,6 +145,8 @@ namespace IfcWrite { operator int() const; operator bool() const; + operator boost::logic::tribool() const; + operator double() const; operator std::string() const; operator boost::dynamic_bitset<>() const; diff --git a/src/ifcwrap/IfcParseWrapper.i b/src/ifcwrap/IfcParseWrapper.i index 8c88abb0ec..49e3cf20c5 100644 --- a/src/ifcwrap/IfcParseWrapper.i +++ b/src/ifcwrap/IfcParseWrapper.i @@ -326,6 +326,17 @@ static IfcUtil::ArgumentType helper_fn_attribute_type(const IfcUtil::IfcBaseClas } } + void setArgumentAsLogical(unsigned int i, boost::logic::tribool v) { + IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); + if (arg_type == IfcUtil::Argument_LOGICAL) { + IfcWrite::IfcWriteArgument* arg = new IfcWrite::IfcWriteArgument(); + arg->set(v); + self->data().setArgument(i, arg); + } else { + throw IfcParse::IfcException("Attribute not set"); + } + } + void setArgumentAsDouble(unsigned int i, double v) { IfcUtil::ArgumentType arg_type = helper_fn_attribute_type($self, i); if (arg_type == IfcUtil::Argument_DOUBLE) { diff --git a/src/ifcwrap/utils/type_conversion.i b/src/ifcwrap/utils/type_conversion.i index 91355cdf8c..14a4f5c86c 100644 --- a/src/ifcwrap/utils/type_conversion.i +++ b/src/ifcwrap/utils/type_conversion.i @@ -123,6 +123,7 @@ PyObject* pythonize(const int& t) { return PyInt_FromLong(t); } PyObject* pythonize(const unsigned int& t) { return PyInt_FromLong(t); } PyObject* pythonize(const bool& t) { return PyBool_FromLong(t); } + PyObject* pythonize(const boost::logic::tribool& t) { return boost::logic::indeterminate(t) ? PyUnicode_FromString("UNKNOWN") : PyBool_FromLong((bool)t) ;} PyObject* pythonize(const double& t) { return PyFloat_FromDouble(t); } PyObject* pythonize(const std::string& t) { return PyUnicode_FromString(t.c_str()); } PyObject* pythonize(const IfcUtil::IfcBaseClass* t) { return SWIG_NewPointerObj(SWIG_as_voidptr(t), SWIGTYPE_p_IfcUtil__IfcBaseClass, 0); } diff --git a/src/ifcwrap/utils/typemaps_in.i b/src/ifcwrap/utils/typemaps_in.i index 03289a17f5..19588c1584 100644 --- a/src/ifcwrap/utils/typemaps_in.i +++ b/src/ifcwrap/utils/typemaps_in.i @@ -241,6 +241,28 @@ CREATE_VECTOR_TYPEMAP_IN(std::string, STRING, str) $1 = check_aggregate_of_aggregate_of_type($input, get_python_type()); } +%typemap(in) boost::logic::tribool { + if (PyBool_Check($input)) { + $1 = $input == Py_True; + } else if (PyUnicode_Check($input)) { + // we already checked the value of the string in the typecheck typemap + $1 = boost::logic::indeterminate; + } else { + SWIG_exception(SWIG_TypeError, "Logical needs boolean or \"UNKOWN\""); + } +} + +%typemap(typecheck, precedence=SWIG_TYPECHECK_INTEGER) boost::logic::tribool { + $1 = PyBool_Check($input); + if (!$1 && PyUnicode_Check($input)) { + PyObject * ascii = PyUnicode_AsEncodedString(result, "UTF-8", "strict"); + if (ascii) { + $1 = strcmp(PyBytes_AS_STRING(ascii), "UNKNOWN") == 0; + Py_DECREF(ascii); + } + } +} + %define CREATE_OPTIONAL_TYPEMAP_IN(template_type, express_name, python_name) %typemap(in) const boost::optional& { diff --git a/src/ifcwrap/utils/typemaps_out.i b/src/ifcwrap/utils/typemaps_out.i index 8243cba33f..07f07a1bcc 100644 --- a/src/ifcwrap/utils/typemaps_out.i +++ b/src/ifcwrap/utils/typemaps_out.i @@ -51,6 +51,10 @@ bool v = arg; $result = pythonize(v); break; } + case IfcUtil::Argument_LOGICAL: { + boost::logic::tribool v = arg; + $result = pythonize(v); + break; } case IfcUtil::Argument_DOUBLE: { double v = arg; $result = pythonize(v);