mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-28 19:27:10 +00:00
Log and validate invalid attribute counts
This commit is contained in:
@@ -256,11 +256,12 @@ def assert_valid(
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def log_internal_cpp_errors(filename: str, logger: Logger) -> None:
|
def log_internal_cpp_errors(f: ifcopenshell.file, filename: str, logger: Logger) -> None:
|
||||||
import re
|
import re
|
||||||
import bisect
|
import bisect
|
||||||
|
|
||||||
chr_offset_re = re.compile(r"at offset (\d+)\s*")
|
chr_offset_re = re.compile(r"at offset (\d+)\s*")
|
||||||
|
for_instance_re = re.compile(r"\s*for instance #(\d+)\s*")
|
||||||
|
|
||||||
log = ifcopenshell.get_log()
|
log = ifcopenshell.get_log()
|
||||||
msgs = list(map(json.loads, filter(None, log.split("\n"))))
|
msgs = list(map(json.loads, filter(None, log.split("\n"))))
|
||||||
@@ -286,6 +287,23 @@ def log_internal_cpp_errors(filename: str, logger: Logger) -> None:
|
|||||||
else:
|
else:
|
||||||
logger.error("For instance:\n %s\n%s", line, m)
|
logger.error("For instance:\n %s\n%s", line, m)
|
||||||
|
|
||||||
|
instance_messages = [for_instance_re.findall(m["message"]) for m in msgs]
|
||||||
|
if instance_messages:
|
||||||
|
for instid, msg in zip(instance_messages, msgs):
|
||||||
|
if instid:
|
||||||
|
m = for_instance_re.sub("", msg["message"])
|
||||||
|
try:
|
||||||
|
inst = f[int(instid[0])]
|
||||||
|
except:
|
||||||
|
inst = None
|
||||||
|
if hasattr(logger, "set_state"):
|
||||||
|
logger.set_state("instance", inst)
|
||||||
|
logger.set_state("attribute", None)
|
||||||
|
logger.error(m)
|
||||||
|
elif inst:
|
||||||
|
logger.error("For instance:\n %s\n%s", inst, m)
|
||||||
|
else:
|
||||||
|
logger.error(m)
|
||||||
|
|
||||||
entity_attribute_map: dict[tuple[str, str], tuple[entity_type, tuple[attribute]]] = {}
|
entity_attribute_map: dict[tuple[str, str], tuple[entity_type, tuple[attribute]]] = {}
|
||||||
|
|
||||||
@@ -368,7 +386,7 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
|||||||
logger.error(f"Unsupported schema: {schema_name}")
|
logger.error(f"Unsupported schema: {schema_name}")
|
||||||
return
|
return
|
||||||
|
|
||||||
log_internal_cpp_errors(filename, logger)
|
log_internal_cpp_errors(f, filename, logger)
|
||||||
|
|
||||||
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(f.schema_identifier)
|
schema = ifcopenshell.ifcopenshell_wrapper.schema_by_name(f.schema_identifier)
|
||||||
used_guids: dict[str, ifcopenshell.entity_instance] = dict()
|
used_guids: dict[str, ifcopenshell.entity_instance] = dict()
|
||||||
@@ -490,7 +508,7 @@ def validate(f: Union[ifcopenshell.file, str], logger: Logger, express_rules=Fal
|
|||||||
# Re capturing the log when validate() is finished
|
# Re capturing the log when validate() is finished
|
||||||
# iterating over every instance so that all attribute counts
|
# iterating over every instance so that all attribute counts
|
||||||
# are verified.
|
# are verified.
|
||||||
log_internal_cpp_errors(filename, logger)
|
log_internal_cpp_errors(f, filename, logger)
|
||||||
|
|
||||||
# Restore the original value for 'use_attribute_value_derived'
|
# Restore the original value for 'use_attribute_value_derived'
|
||||||
ifcopenshell.ifcopenshell_wrapper.set_feature("use_attribute_value_derived", attribute_value_derived_org)
|
ifcopenshell.ifcopenshell_wrapper.set_feature("use_attribute_value_derived", attribute_value_derived_org)
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ namespace {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl) {
|
IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size) {
|
||||||
std::vector<const IfcParse::parameter_type*> parameter_types;
|
std::vector<const IfcParse::parameter_type*> parameter_types;
|
||||||
|
|
||||||
if ((decl != nullptr) && (decl->as_type_declaration() != nullptr)) {
|
if ((decl != nullptr) && (decl->as_type_declaration() != nullptr)) {
|
||||||
@@ -197,8 +197,11 @@ IfcEntityInstanceData IfcParse::parse_context::construct(int name, unresolved_re
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((decl != nullptr) && (tokens_.size() != parameter_types.size())) {
|
if (((decl != nullptr) && (tokens_.size() != parameter_types.size())) ||
|
||||||
// warning
|
expected_size && *expected_size != tokens_.size())
|
||||||
|
{
|
||||||
|
size_t expected = expected_size ? *expected_size : parameter_types.size();
|
||||||
|
Logger::Warning("Expected " + std::to_string(expected) + " attribute values, found " + std::to_string(tokens_.size()) + " for instance #" + std::to_string(name));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (tokens_.empty()) {
|
if (tokens_.empty()) {
|
||||||
|
|||||||
@@ -91,7 +91,7 @@ struct parse_context {
|
|||||||
|
|
||||||
void push(IfcUtil::IfcBaseClass* inst);
|
void push(IfcUtil::IfcBaseClass* inst);
|
||||||
|
|
||||||
IfcEntityInstanceData construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl);
|
IfcEntityInstanceData construct(int name, unresolved_references& references_to_resolve, const IfcParse::declaration* decl, boost::optional<size_t> expected_size);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class provides several static convenience functions and variables
|
/// This class provides several static convenience functions and variables
|
||||||
|
|||||||
@@ -719,7 +719,7 @@ void IfcParse::IfcFile::load(unsigned entity_instance_name, const IfcParse::enti
|
|||||||
tokens->Next();
|
tokens->Next();
|
||||||
load(0, nullptr, ps, -1);
|
load(0, nullptr, ps, -1);
|
||||||
const auto *decl = schema_->declaration_by_name(TokenFunc::asStringRef(next));
|
const auto *decl = schema_->declaration_by_name(TokenFunc::asStringRef(next));
|
||||||
auto* simple_type_instance = schema_->instantiate(decl, ps.construct(-1, references_to_resolve, decl));
|
auto* simple_type_instance = schema_->instantiate(decl, ps.construct(-1, references_to_resolve, decl, boost::none));
|
||||||
//@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity));
|
//@todo decide addEntity(((IfcUtil::IfcBaseClass*)*entity));
|
||||||
context.push(simple_type_instance);
|
context.push(simple_type_instance);
|
||||||
simple_type_instance->file_ = this;
|
simple_type_instance->file_ = this;
|
||||||
@@ -748,7 +748,7 @@ IfcEntityInstanceData IfcParse::read(unsigned int i, IfcFile* f) {
|
|||||||
parse_context pc;
|
parse_context pc;
|
||||||
f->tokens->Next();
|
f->tokens->Next();
|
||||||
f->load(i, ty->as_entity(), pc, -1);
|
f->load(i, ty->as_entity(), pc, -1);
|
||||||
return IfcEntityInstanceData(pc.construct(i, f->references_to_resolve, ty));
|
return IfcEntityInstanceData(pc.construct(i, f->references_to_resolve, ty, boost::none));
|
||||||
}
|
}
|
||||||
|
|
||||||
void IfcParse::IfcFile::try_read_semicolon() const {
|
void IfcParse::IfcFile::try_read_semicolon() const {
|
||||||
@@ -1300,7 +1300,7 @@ void IfcFile::initialize_(IfcParse::IfcSpfStream* s) {
|
|||||||
parse_context ps;
|
parse_context ps;
|
||||||
tokens->Next();
|
tokens->Next();
|
||||||
load(current_id, entity_type->as_entity(), ps, -1);
|
load(current_id, entity_type->as_entity(), ps, -1);
|
||||||
instance = schema_->instantiate(entity_type, ps.construct(current_id, references_to_resolve, entity_type));
|
instance = schema_->instantiate(entity_type, ps.construct(current_id, references_to_resolve, entity_type, boost::none));
|
||||||
instance->file_ = this;
|
instance->file_ = this;
|
||||||
instance->id_ = current_id;
|
instance->id_ = current_id;
|
||||||
|
|
||||||
|
|||||||
@@ -41,12 +41,7 @@ namespace {
|
|||||||
parse_context pc;
|
parse_context pc;
|
||||||
f->tokens->Next();
|
f->tokens->Next();
|
||||||
f->load(-1, nullptr, pc, -1);
|
f->load(-1, nullptr, pc, -1);
|
||||||
return pc.construct(-1, f->references_to_resolve, nullptr);
|
return pc.construct(-1, f->references_to_resolve, nullptr, s);
|
||||||
/*std::ostringstream oss;
|
|
||||||
ent.toString(oss);
|
|
||||||
auto osss = oss.str();
|
|
||||||
std::wcout << osss.c_str() << std::endl;*/
|
|
||||||
// return ent;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user