Last minute refactoring

This commit is contained in:
Thomas Krijnen
2026-08-08 07:42:45 +02:00
parent 8870ffb018
commit af58eaf79f
300 changed files with 5230 additions and 5150 deletions
+76 -70
View File
@@ -51,13 +51,13 @@
%ignore ifcopenshell::instance_streamer<ifcopenshell::file_reader<ifcopenshell::full_buffer_impl>>::read_instance;
%ignore ifcopenshell::instance_streamer<ifcopenshell::file_reader<ifcopenshell::full_buffer_impl>>::steal_instances;
%ignore express::Entity;
%ignore express::Select;
%ignore express::DeclaredType;
%ignore express::entity;
%ignore express::select;
%ignore express::declared_type;
// operator< takes a reference, so SWIG's auto __lt__ crashes on None.
// entity_instance_mixin already has a safe __lt__; let it inherit through.
%ignore express::Base::operator<;
%ignore express::base::operator<;
%ignore in_memory_file_storage;
%ignore rocks_db_file_storage;
@@ -93,17 +93,17 @@
%ignore ifcopenshell::file::type_iterator;
%ignore express::Base::is;
%ignore express::Base::operator==;
%ignore express::Base::operator!=;
%ignore express::Base::Base(std::nullopt_t);
%ignore express::base::is;
%ignore express::base::operator==;
%ignore express::base::operator!=;
%ignore express::base::base(std::nullopt_t);
%rename("by_id") instance_by_id;
%rename("by_guid") instance_by_guid;
%rename("_by_type") instances_by_type;
%rename("_by_type_excl_subtypes") instances_by_type_excl_subtypes;
%rename("get_inverses_by_declaration") get_inverse;
%rename("entity_instance") express::Base;
%rename("entity_instance") express::base;
%rename("file") file;
// _add() because mixin defined add which adds transaction logic
%rename("_add") add_entity;
@@ -191,7 +191,7 @@ static const std::string& helper_fn_declaration_get_name(const ifcopenshell::dec
return decl->name();
}
static ifcopenshell::argument_type helper_fn_attribute_type(const express::Base* instp, unsigned i) {
static ifcopenshell::argument_type helper_fn_attribute_type(const express::base* instp, unsigned i) {
const auto& inst = *instp;
const ifcopenshell::parameter_type* pt = 0;
if (inst.declaration().as_entity()) {
@@ -295,22 +295,22 @@ private:
return new ifcopenshell::file(ifcopenshell::uninitialized_tag{}, logger_or_root(logger));
}
std::vector<express::Base> _get_inverse(const express::Base& e) {
if (auto e_ = e.as<express::Entity>()) {
return cast_vector<express::Base>($self->get_inverse(e_.id(), 0, -1));
std::vector<express::base> _get_inverse(const express::base& e) {
if (auto e_ = e.as<express::entity>()) {
return cast_vector<express::base>($self->get_inverse(e_.id(), 0, -1));
}
throw ifcopenshell::exception("Only entities with ids are supported for get_inverse. Provided entity: '" + e.declaration().name() + "'.");
}
std::vector<int> _get_inverse_indices(const express::Base& e) {
if (auto e_ = e.as<express::Entity>()) {
std::vector<int> _get_inverse_indices(const express::base& e) {
if (auto e_ = e.as<express::entity>()) {
return $self->get_inverse_indices_by_id(e_.id());
}
throw ifcopenshell::exception("Only entities with ids are supported for get_inverse_indices. Provided entity: '" + e.declaration().name() + "'.");
}
int get_total_inverses(const express::Base& e) {
if (auto e_ = e.as<express::Entity>()) {
int get_total_inverses(const express::base& e) {
if (auto e_ = e.as<express::entity>()) {
return $self->get_inverse_indices_by_id(e_.id()).size();
}
throw ifcopenshell::exception("Only entities with ids are supported for get_total_inverses. Provided entity: '" + e.declaration().name() + "'.");
@@ -329,7 +329,7 @@ private:
return s.str();
}
express::Base create(const std::string& entity_name, int id=-1) {
express::base create(const std::string& entity_name, int id=-1) {
const ifcopenshell::declaration* decl = $self->schema()->declaration_by_name(entity_name);
if (!decl || !(decl->as_entity() || decl->as_type_declaration())) {
throw ifcopenshell::exception("No such entity or type declaration: '" + entity_name + "' in schema '" + $self->schema()->name());
@@ -433,7 +433,7 @@ private:
%}
}
%extend express::Base {
%extend express::base {
// 0 = not found
// 1 = regular forward attribute
@@ -478,8 +478,8 @@ private:
// to expose it to the Python wrapper it is simply duplicated here.
// Same applies to the two methods reimplemented below.
int id() const {
return $self->as<express::Base>() != nullptr
? $self->as<express::Base>()->id()
return $self->as<express::base>() != nullptr
? $self->as<express::base>()->id()
: 0;
}
*/
@@ -583,9 +583,9 @@ private:
}
}
std::vector<express::Base> _get_inverse(const std::string& a) {
std::vector<express::base> _get_inverse(const std::string& a) {
if ($self->declaration().as_entity()) {
return cast_vector<express::Base>($self->as<express::Entity>().get_inverse(a));
return cast_vector<express::base>($self->as<express::entity>().get_inverse(a));
} else {
throw ifcopenshell::exception(a + " not found on " + $self->declaration().name());
}
@@ -596,7 +596,15 @@ private:
}
const char* const attribute_type(const std::string& name) const {
return ifcopenshell::argument_type_to_string(helper_fn_attribute_type($self, express_Base_get_argument_index($self, name)));
unsigned int index;
if ($self->declaration().as_entity()) {
index = $self->declaration().as_entity()->attribute_index(name);
} else if (name == "wrappedValue") {
index = 0;
} else {
throw ifcopenshell::exception(name + " not found on " + $self->declaration().name());
}
return ifcopenshell::argument_type_to_string(helper_fn_attribute_type($self, index));
}
const std::string& attribute_name(unsigned int i) const {
@@ -734,35 +742,35 @@ private:
return out;
};
auto to_base = [&](PyObject* o) -> express::Base {
auto to_base = [&](PyObject* o) -> express::base {
void* vp = nullptr;
// Try non-const pointer first
if (swig_type_info* ti = SWIG_TypeQuery("express::Base *")) {
if (swig_type_info* ti = SWIG_TypeQuery("express::base *")) {
int res = SWIG_ConvertPtr(o, &vp, ti, 0);
if (res >= 0 && vp) {
return *static_cast<express::Base*>(vp);
return *static_cast<express::base*>(vp);
}
}
// Then try const pointer
vp = nullptr;
if (swig_type_info* ti = SWIG_TypeQuery("express::Base const *")) {
if (swig_type_info* ti = SWIG_TypeQuery("express::base const *")) {
int res = SWIG_ConvertPtr(o, &vp, ti, 0);
if (res >= 0 && vp) {
return *static_cast<const express::Base*>(vp);
return *static_cast<const express::base*>(vp);
}
}
throw ifcopenshell::exception("Attribute not set");
};
auto to_vec_base = [&](PyObject* o) -> std::vector<express::Base> {
auto to_vec_base = [&](PyObject* o) -> std::vector<express::base> {
PyObject* fast = seq_fast(o);
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
PyObject** items = PySequence_Fast_ITEMS(fast);
std::vector<express::Base> out;
std::vector<express::base> out;
out.reserve(static_cast<size_t>(n));
for (Py_ssize_t k = 0; k < n; ++k) {
out.push_back(to_base(items[k]));
@@ -802,12 +810,12 @@ private:
return out;
};
auto to_vec_vec_base = [&](PyObject* o) -> std::vector<std::vector<express::Base>> {
auto to_vec_vec_base = [&](PyObject* o) -> std::vector<std::vector<express::base>> {
PyObject* fast = seq_fast(o);
Py_ssize_t n = PySequence_Fast_GET_SIZE(fast);
PyObject** items = PySequence_Fast_ITEMS(fast);
std::vector<std::vector<express::Base>> out;
std::vector<std::vector<express::base>> out;
out.reserve(static_cast<size_t>(n));
for (Py_ssize_t k = 0; k < n; ++k) {
out.push_back(to_vec_base(items[k]));
@@ -936,13 +944,13 @@ private:
%extend ifcopenshell::spf_header {
// Upcast to header instances for SWIG, because
// it has no idea about the schema definitions.
express::Base file_description_py() {
express::base file_description_py() {
return $self->file_description();
}
express::Base file_name_py() {
express::base file_name_py() {
return $self->file_name();
}
express::Base file_schema_py() {
express::base file_schema_py() {
return $self->file_schema();
}
@@ -969,7 +977,7 @@ from .file import file_mixin as file_mixin
%pythoncode %{
from .entity_instance import entity_instance_mixin
%}
%feature("python:abc", "entity_instance_mixin") express::Base;
%feature("python:abc", "entity_instance_mixin") express::base;
%include "../ifcparse/express.h"
@@ -1011,7 +1019,7 @@ from .entity_instance import entity_instance_mixin
return IFCOPENSHELL_VERSION;
}
express::Base new_IfcBaseClass(ifcopenshell::file& file, const std::string& name) {
express::base new_IfcBaseClass(ifcopenshell::file& file, const std::string& name) {
return file.create(file.schema()->declaration_by_name(name));
}
%}
@@ -1171,29 +1179,29 @@ from .entity_instance import entity_instance_mixin
%}
%{
PyObject* get_info_cpp(const express::Base& v, bool recursive, bool include_identifier);
PyObject* get_info_cpp(const express::base& v, bool recursive, bool include_identifier);
// @todo refactor this to remove duplication with the typemap.
// except this is calls the above function in case of instances.
PyObject* convert_cpp_attribute_to_python(const express::Base& instance, size_t attribute_index, bool recursive, bool include_identifier) {
PyObject* convert_cpp_attribute_to_python(const express::base& instance, size_t attribute_index, bool recursive, bool include_identifier) {
return instance.get_attribute_value(attribute_index).apply_visitor([recursive, include_identifier](const auto& v){
using U = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<U, enumeration_reference>) {
using u = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<u, enumeration_reference>) {
return pythonize(std::string(v.value()));
} else if constexpr (std::is_same_v<U, derived>) {
} else if constexpr (std::is_same_v<u, derived>) {
if (feature_use_attribute_value_derived) {
return SWIG_NewPointerObj(new attribute_value_derived, SWIGTYPE_p_attribute_value_derived, SWIG_POINTER_OWN);
} else {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
}
} else if constexpr (std::is_same_v<U, express::Base>) {
} else if constexpr (std::is_same_v<u, express::base>) {
if (recursive) {
return get_info_cpp(v, recursive, include_identifier);
} else {
return pythonize(v);
}
} else if constexpr (std::is_same_v<U, std::vector<express::Base>>) {
} else if constexpr (std::is_same_v<u, std::vector<express::base>>) {
if (recursive) {
PyObject* t = PyTuple_New(v.size());
for (size_t i = 0; i < v.size(); ++i) {
@@ -1204,7 +1212,7 @@ from .entity_instance import entity_instance_mixin
} else {
return pythonize_vector(v);
}
} else if constexpr (std::is_same_v<U, std::vector<std::vector<express::Base>>>) {
} else if constexpr (std::is_same_v<u, std::vector<std::vector<express::base>>>) {
if (recursive) {
PyObject* outer = PyTuple_New(v.size());
for (size_t i = 0; i < v.size(); ++i) {
@@ -1220,10 +1228,10 @@ from .entity_instance import entity_instance_mixin
} else {
return pythonize_vector(v);
}
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, blank>) {
} else if constexpr (std::is_same_v<u, empty_aggregate_t> || std::is_same_v<u, empty_aggregate_of_aggregate_t> || std::is_same_v<u, blank>) {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
} else if constexpr (is_std_vector_v<U>) {
} else if constexpr (is_std_vector_v<u>) {
// only for non-entity-instance vectors
return pythonize_vector(v);
} else {
@@ -1233,7 +1241,7 @@ from .entity_instance import entity_instance_mixin
}
%}
%inline %{
PyObject* get_info_cpp(const express::Base& v, bool recursive, bool include_identifier) {
PyObject* get_info_cpp(const express::base& v, bool recursive, bool include_identifier) {
PyObject *d = PyDict_New();
if (v.declaration().as_entity()) {
@@ -1273,24 +1281,24 @@ from .entity_instance import entity_instance_mixin
%extend ifcopenshell::instance_streamer<ifcopenshell::file_reader<ifcopenshell::full_buffer_impl>> {
PyObject* read_instance_py(bool type_as_declaration_instance=false) {
auto simply_type_to_dictionary = [&](const express::Base& t) -> PyObject* {
auto simply_type_to_dictionary = [&](const express::base& t) -> PyObject* {
const auto& nm = t.declaration().name();
auto ifc_val = t.get_attribute_value(0);
auto attribute_val_py = ifc_val.apply_visitor([&](const auto& t) {
using U = std::decay_t<decltype(t)>;
using u = std::decay_t<decltype(t)>;
if constexpr (is_std_vector_v<U>) {
if constexpr (is_std_vector_v<u>) {
return pythonize_vector(t);
} else if constexpr (std::is_same_v<U, enumeration_reference>) {
} else if constexpr (std::is_same_v<u, enumeration_reference>) {
return pythonize(std::string(t.value()));
} else if constexpr (std::is_same_v<U, derived>) {
} else if constexpr (std::is_same_v<u, derived>) {
if (feature_use_attribute_value_derived) {
return SWIG_NewPointerObj(new attribute_value_derived, SWIGTYPE_p_attribute_value_derived, SWIG_POINTER_OWN);
} else {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
}
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, blank>) {
} else if constexpr (std::is_same_v<u, empty_aggregate_t> || std::is_same_v<u, empty_aggregate_of_aggregate_t> || std::is_same_v<u, blank>) {
Py_INCREF(Py_None);
return static_cast<PyObject*>(Py_None);
} else {
@@ -1370,25 +1378,23 @@ from .entity_instance import entity_instance_mixin
// sets dict member, returns void
val.apply_visitor([&](const auto& t) -> void {
using T = std::decay_t<decltype(t)>;
using value_type = std::decay_t<decltype(t)>;
PyObject* attribute_val_py;
if constexpr (std::is_same_v<T, express::Base>) {
if constexpr (std::is_same_v<value_type, express::base>) {
attribute_val_py = simply_type_to_dictionary(t);
} else {
using U = std::decay_t<decltype(t)>;
if constexpr (is_std_vector_v<U>) {
if constexpr (is_std_vector_v<value_type>) {
attribute_val_py = pythonize_vector(t);
} else if constexpr (std::is_same_v<U, enumeration_reference>) {
} else if constexpr (std::is_same_v<value_type, enumeration_reference>) {
attribute_val_py = pythonize(std::string(t.value()));
} else if constexpr (std::is_same_v<U, derived>) {
} else if constexpr (std::is_same_v<value_type, derived>) {
if (feature_use_attribute_value_derived) {
attribute_val_py = SWIG_NewPointerObj(new attribute_value_derived, SWIGTYPE_p_attribute_value_derived, SWIG_POINTER_OWN);
} else {
Py_INCREF(Py_None);
attribute_val_py = static_cast<PyObject*>(Py_None);
}
} else if constexpr (std::is_same_v<U, empty_aggregate_t> || std::is_same_v<U, empty_aggregate_of_aggregate_t> || std::is_same_v<U, blank>) {
} else if constexpr (std::is_same_v<value_type, empty_aggregate_t> || std::is_same_v<value_type, empty_aggregate_of_aggregate_t> || std::is_same_v<value_type, blank>) {
Py_INCREF(Py_None);
attribute_val_py = static_cast<PyObject*>(Py_None);
} else {
@@ -1411,32 +1417,32 @@ from .entity_instance import entity_instance_mixin
std::visit([&](const auto& v) -> void {
PyObject* attribute_val_py = nullptr;
using T = std::decay_t<decltype(v)>;
using t = std::decay_t<decltype(v)>;
if constexpr (std::is_same_v<T, ifcopenshell::reference_or_simple_type>) {
if (auto* inst = std::get_if<express::Base>(&v)) {
if constexpr (std::is_same_v<t, ifcopenshell::reference_or_simple_type>) {
if (auto* inst = std::get_if<express::base>(&v)) {
// So this never happens?
} else if (auto* name = std::get_if<ifcopenshell::instance_reference>(&v)) {
attribute_val_py = instance_reference_to_dict(*name);
}
} else if constexpr (std::is_same_v<T, std::vector<ifcopenshell::reference_or_simple_type>>) {
} else if constexpr (std::is_same_v<t, std::vector<ifcopenshell::reference_or_simple_type>>) {
attribute_val_py = PyTuple_New(v.size());
size_t idx = 0;
for (auto const& inner : v) {
if (auto* inst = std::get_if<express::Base>(&inner)) {
if (auto* inst = std::get_if<express::base>(&inner)) {
PyTuple_SetItem(attribute_val_py, idx++, simply_type_to_dictionary(*inst));
} else if (auto* name = std::get_if<ifcopenshell::instance_reference>(&inner)) {
PyTuple_SetItem(attribute_val_py, idx++, instance_reference_to_dict(*name));
}
}
} else if constexpr (std::is_same_v<T, std::vector<std::vector<ifcopenshell::reference_or_simple_type>>>) {
} else if constexpr (std::is_same_v<t, std::vector<std::vector<ifcopenshell::reference_or_simple_type>>>) {
attribute_val_py = PyTuple_New(v.size());
size_t outer_idx = 0;
for (auto const& inner : v) {
PyObject* inner_py = PyTuple_New(inner.size());
size_t idx = 0;
for (auto const& innermost : inner) {
if (auto* inst = std::get_if<express::Base>(&innermost)) {
if (auto* inst = std::get_if<express::base>(&innermost)) {
PyTuple_SetItem(inner_py, idx++, simply_type_to_dictionary(*inst));
} else if (auto* name = std::get_if<ifcopenshell::instance_reference>(&innermost)) {
PyTuple_SetItem(inner_py, idx++, instance_reference_to_dict(*name));