Import: DXF backend/frontend, report more unsupported features info

Now for unsupported features we report on line numbers and on the entity
handle, in case that unsupported feature is a DXF entity. To avoid
flooding the output, only a maximum of 5 instances are reported with
details. The rest simply add up to the global count and are ellipsized
in the report.

Report output is now in sentence case.
This commit is contained in:
Furgo
2025-06-23 23:01:39 +02:00
parent f8b0ceaac5
commit 7764ed5173
4 changed files with 49 additions and 22 deletions

View File

@@ -4228,38 +4228,38 @@ class DxfImportReporter:
Formats the statistics into a human-readable string for console output.
"""
if not self.stats:
return "DXF Import: No statistics were returned from the importer.\n"
return "DXF Import: no statistics were returned from the importer.\n"
lines = ["\n--- DXF Import Summary ---"]
lines = ["\n--- DXF import summary ---"]
# General info
lines.append(f"DXF Version: {self.stats.get('dxfVersion', 'Unknown')}")
lines.append(f"File Encoding: {self.stats.get('dxfEncoding', 'Unknown')}")
lines.append(f"DXF version: {self.stats.get('dxfVersion', 'Unknown')}")
lines.append(f"File encoding: {self.stats.get('dxfEncoding', 'Unknown')}")
# Scaling info
file_units = self.stats.get('fileUnits', 'Not specified')
source = self.stats.get('scalingSource', '')
if source:
lines.append(f"File Units: {file_units} (from {source})")
lines.append(f"File units: {file_units} (from {source})")
else:
lines.append(f"File Units: {file_units}")
lines.append(f"File units: {file_units}")
manual_scaling = self.stats.get('importSettings', {}).get('Manual scaling factor', '1.0')
lines.append(f"Manual Scaling Factor: {manual_scaling}")
lines.append(f"Manual scaling factor: {manual_scaling}")
final_scaling = self.stats.get('finalScalingFactor', 1.0)
lines.append(f"Final Scaling: 1 DXF unit = {final_scaling:.4f} mm")
lines.append(f"Final scaling: 1 DXF unit = {final_scaling:.4f} mm")
lines.append("")
# Timing
lines.append("Performance:")
cpp_time = self.stats.get('importTimeSeconds', 0.0)
lines.append(f" - C++ Import Time: {cpp_time:.4f} seconds")
lines.append(f" - Total Import Time: {self.total_time:.4f} seconds")
lines.append(f" - C++ import time: {cpp_time:.4f} seconds")
lines.append(f" - Total import time: {self.total_time:.4f} seconds")
lines.append("")
# Settings
lines.append("Import Settings:")
lines.append("Import settings:")
settings = self.stats.get('importSettings', {})
if settings:
for key, value in sorted(settings.items()):
@@ -4269,7 +4269,7 @@ class DxfImportReporter:
lines.append("")
# Counts
lines.append("Entity Counts:")
lines.append("Entity counts:")
total_read = 0
entities = self.stats.get('entityCounts', {})
if entities:
@@ -4283,15 +4283,31 @@ class DxfImportReporter:
lines.append(f"FreeCAD objects created: {self.stats.get('totalEntitiesCreated', 0)}")
lines.append("")
lines.append("Unsupported Features:")
lines.append("Import issues and unsupported features:")
unsupported = self.stats.get('unsupportedFeatures', {})
if unsupported:
for key, value in sorted(unsupported.items()):
lines.append(f" - {key}: {value} time(s)")
else:
lines.append(" (None)")
for key, occurrences in sorted(unsupported.items()):
count = len(occurrences)
max_details_to_show = 5
lines.append("--- End of Summary ---\n")
details_list = []
for i, (line, handle) in enumerate(occurrences):
if i >= max_details_to_show:
break
if handle:
details_list.append(f"line {line} (handle {handle})")
else:
details_list.append(f"line {line} (no handle available)")
details_str = ", ".join(details_list)
if count > max_details_to_show:
lines.append(f" - {key}: {count} time(s). Examples: {details_str}, ...")
else:
lines.append(f" - {key}: {count} time(s) at {details_str}")
else:
lines.append(" (none)")
lines.append("--- End of summary ---\n")
return "\n".join(lines)
def report_to_console(self):

View File

@@ -1404,7 +1404,14 @@ Py::Object ImpExpDxfRead::getStatsAsPyObject()
// Create a nested dictionary for any unsupported DXF features encountered.
Py::Dict unsupportedFeaturesDict;
for (const auto& pair : m_stats.unsupportedFeatures) {
unsupportedFeaturesDict.setItem(pair.first.c_str(), Py::Long(pair.second));
Py::List occurrencesList;
for (const auto& occurrence : pair.second) {
Py::Tuple infoTuple(2);
infoTuple.setItem(0, Py::Long(occurrence.first));
infoTuple.setItem(1, Py::String(occurrence.second));
occurrencesList.append(infoTuple);
}
unsupportedFeaturesDict.setItem(pair.first.c_str(), occurrencesList);
}
statsDict.setItem("unsupportedFeatures", unsupportedFeaturesDict);

View File

@@ -2342,8 +2342,8 @@ bool CDxfRead::ReadDimension()
bool CDxfRead::ReadUnknownEntity()
{
UnsupportedFeature("Entity type '%s'", m_record_data);
ProcessAllEntityAttributes();
UnsupportedFeature("Entity type '%s'", m_record_data);
return true;
}
@@ -2403,7 +2403,7 @@ void CDxfRead::UnsupportedFeature(const char* format, args&&... argValuess)
{
// NOLINTNEXTLINE(runtime/printf)
std::string formattedMessage = fmt::sprintf(format, std::forward<args>(argValuess)...);
m_stats.unsupportedFeatures[formattedMessage]++;
m_stats.unsupportedFeatures[formattedMessage].emplace_back(m_line, m_current_entity_handle);
}
bool CDxfRead::get_next_record()
@@ -2798,6 +2798,8 @@ bool CDxfRead::ReadEntity()
{
InitializeAttributes();
m_entityAttributes.SetDefaults();
m_current_entity_handle.clear();
SetupStringAttribute(eHandle, m_current_entity_handle);
EntityNormalVector.Set(0, 0, 1);
Setup3DVectorAttribute(eExtrusionDirection, EntityNormalVector);
SetupStringAttribute(eLinetypeName, m_entityAttributes.m_LineType);

View File

@@ -187,7 +187,7 @@ struct DxfImportStats
double finalScalingFactor = 1.0;
std::map<std::string, int> entityCounts;
std::map<std::string, std::string> importSettings;
std::map<std::string, int> unsupportedFeatures;
std::map<std::string, std::vector<std::pair<int, std::string>>> unsupportedFeatures;
int totalEntitiesCreated = 0;
};
@@ -200,6 +200,7 @@ enum eDXFGroupCode_t
ePrimaryText = 1,
eName = 2,
eExtraText = 3,
eHandle = 5,
eLinetypeName = 6,
eTextStyleName = 7,
eLayerName = 8,
@@ -462,6 +463,7 @@ private:
bool m_not_eof = true;
int m_line = 0;
bool m_repeat_last_record = false;
std::string m_current_entity_handle;
// The scaling from DXF units to millimetres.
// This does not include the dxfScaling option