Exemple #1
0
 def set_document(
     self,
     document: Drawing,
     auditor: Auditor,
     *,
     layout: str = "Model",
     overall_scaling_factor: float = 1.0,
 ):
     error_count = len(auditor.errors)
     if error_count > 0:
         ret = qw.QMessageBox.question(
             self,
             "Found DXF Errors",
             f'Found {error_count} errors in file "{document.filename}"\n'
             f"Load file anyway? ",
         )
         if ret == qw.QMessageBox.No:
             auditor.print_error_report(auditor.errors)
             return
     self.doc = document
     self._render_context = RenderContext(document)
     self._reset_backend(scale=overall_scaling_factor)
     self._visible_layers = None
     self._current_layout = None
     self._populate_layouts()
     self._populate_layer_list()
     self.draw_layout(layout)
     self.setWindowTitle("CAD Viewer - " + str(document.filename))
Exemple #2
0
 def test_audit_invalid_major_axis(self, msp):
     ellipse = msp.add_ellipse((0, 0), (1, 0))
     # can only happen for loaded DXF files
     ellipse.dxf.__dict__["major_axis"] = Vec3(0, 0, 0)  # hack
     auditor = Auditor(ellipse.doc)
     ellipse.audit(auditor)
     auditor.empty_trashcan()
     assert len(auditor.fixes) == 1
     assert ellipse.is_alive is False, "invalid ellipse should be deleted"
def test_audit_fix_invalid_root_dict_owner():
    doc = ezdxf.new()
    rootdict = doc.rootdict
    auditor = Auditor(doc)

    rootdict.dxf.owner = "FF"  # set invalid owner
    auditor.run()
    assert len(auditor.fixes) == 1
    assert auditor.fixes[0].code == AuditError.INVALID_OWNER_HANDLE
    assert rootdict.dxf.owner == "0"
Exemple #4
0
    def audit(self) -> Auditor:
        """Checks document integrity and fixes all fixable problems, not
        fixable problems are stored in :attr:`Auditor.errors`.

        If you are messing around with internal structures, call this method
        before saving to be sure to export valid DXF documents, but be aware
        this is a long running task.

        """
        auditor = Auditor(self)
        auditor.run()
        return auditor
Exemple #5
0
 def _fix_entry_handles(self, auditor: Auditor):
     # Why: see duplicate handle issue #604
     entitydb = self.entitydb
     for entry in self:
         entity = entitydb.get(entry.dxf.handle)
         if entity is not entry:  # duplicate handle usage
             # This can break entities referring to this entity, but at
             # least the DXF readable
             entry.dxf.handle = entitydb.next_handle()
             self.entitydb.add(entry)
             auditor.fixed_error(
                 code=AuditError.INVALID_TABLE_HANDLE,
                 message=f"Fixed invalid table entry handle in {entry}",
             )
Exemple #6
0
def run(start):
    if start > 0:
        start -= 1
    names = list(chain(glob.glob(DIR1), glob.glob(DIR2)))
    names = names[start:]
    count = 0
    for filename in names:
        count += 1
        print("processing: {}/{} file: {}".format(count+start, len(names)+start, filename))
        doc = ezdxf.readfile(filename, legacy_mode=LEGACY_MODE)

        auditor = Auditor(doc)
        if len(auditor):
            auditor.print_error_report(auditor.errors)
Exemple #7
0
def read(stream: BinaryIO,
         errors: str = 'surrogateescape') -> Tuple['Drawing', 'Auditor']:
    """ Read a DXF document from a binary-stream similar to :func:`ezdxf.read`,
    but this function will detect the text encoding automatically and repair
    as much flaws as possible, runs the required audit process afterwards
    and returns the DXF document and the :class:`Auditor`.

    Args:
        stream: data stream to load in binary read mode
        errors: specify decoding error handler

            - "surrogateescape" to preserve possible binary data (default)
            - "ignore" to use the replacement char U+FFFD "\ufffd" for invalid data
            - "strict" to raise an :class:`UnicodeDecodeError` exception for invalid data

    Raises:
        DXFStructureError: for invalid or corrupted DXF structures
        UnicodeDecodeError: if `errors` is "strict" and a decoding error occurs

    """
    from ezdxf.document import Drawing
    recover_tool = Recover.run(stream, errors=errors)
    doc = Drawing()
    doc._load_section_dict(recover_tool.section_dict)

    auditor = Auditor(doc)
    for code, msg in recover_tool.errors:
        auditor.add_error(code, msg)
    for code, msg in recover_tool.fixes:
        auditor.fixed_error(code, msg)
    auditor.run()
    return doc, auditor
Exemple #8
0
    def audit(self, auditor: Auditor) -> None:
        """Audit and repair BLOCKS section.

        .. important::

            Do not delete entities while auditing process, because this
            would alter the entity database while iterating, instead use::

                auditor.trash(entity)

            to delete invalid entities after auditing automatically.

        """
        assert self.doc is auditor.doc, "Auditor for different DXF document."

        for block_record in self.block_records:
            assert isinstance(block_record, BlockRecord)
            for entity in block_record.entity_space:
                if not is_graphic_entity(entity):
                    auditor.fixed_error(
                        code=AuditError.REMOVED_INVALID_GRAPHIC_ENTITY,
                        message=f"Removed invalid DXF entity {str(entity)} from"
                        f" BLOCK '{block_record.dxf.name}'.",
                    )
                    auditor.trash(entity)
                elif isinstance(entity, Attrib):
                    # ATTRIB can only exist as an attached entity of the INSERT
                    # entity!
                    auditor.fixed_error(
                        code=AuditError.REMOVED_STANDALONE_ATTRIB_ENTITY,
                        message=f"Removed standalone {str(entity)} entity from"
                        f" BLOCK '{block_record.dxf.name}'.",
                    )
                    auditor.trash(entity)
def test_audit_restores_deleted_owner_tag():
    doc = ezdxf.new()
    d = doc.objects.add_dictionary()
    d.dxf.discard("owner")
    auditor = Auditor(doc)
    d.audit(auditor)
    assert d.dxf.owner == doc.rootdict.dxf.handle, "assign to root dict"
Exemple #10
0
 def test_audit_fixes_invalid_text_style_handle(self, doc, new_style):
     new_style.dxf.text_style_handle = "ABBA"
     auditor = Auditor(doc)
     new_style.audit(auditor)
     assert len(auditor.fixes) == 1
     text_style = doc.entitydb.get(new_style.dxf.text_style_handle)
     assert text_style.dxf.name == "Standard"
Exemple #11
0
 def test_audit_max_ratio(self, msp):
     ellipse = msp.add_ellipse((0, 0), (1, 0))
     # can only happen for loaded DXF files
     ellipse.dxf.__dict__["ratio"] = 2.0  # hack
     auditor = Auditor(ellipse.doc)
     ellipse.audit(auditor)
     assert len(auditor.fixes) == 1
     assert ellipse.dxf.ratio == 0.5
     assert ellipse.dxf.major_axis.isclose((0.0, 2.0))
Exemple #12
0
 def test_audit_min_ratio(self, msp):
     ellipse = msp.add_ellipse((0, 0), (1, 0))
     # can only happen for loaded DXF files
     ellipse.dxf.__dict__["ratio"] = 1e-9  # hack
     auditor = Auditor(ellipse.doc)
     ellipse.audit(auditor)
     assert len(auditor.fixes) == 1
     assert ellipse.dxf.ratio == 1e-6
     assert ellipse.dxf.major_axis.isclose((1.0, 0.0)), "should not changed"
 def test_create_place_holder_for_invalid_default_vaue(self):
     doc = ezdxf.new()
     d = doc.objects.add_dictionary_with_default(
         owner=doc.rootdict.dxf.handle, default="0")
     auditor = Auditor(doc)
     d.audit(auditor)
     default = d.get("xxx")
     assert default.is_alive is True
     assert default.dxftype() == "ACDBPLACEHOLDER"
Exemple #14
0
 def set_document(self, document: Drawing, auditor: Auditor):
     error_count = len(auditor.errors)
     if error_count > 0:
         ret = qw.QMessageBox.question(
             self, 'Found DXF Errors',
             f'Found {error_count} errors in file "{document.filename}"\nLoad file anyway? '
         )
         if ret == qw.QMessageBox.No:
             auditor.print_error_report(auditor.errors)
             return
     self.doc = document
     self._render_context = RenderContext(document)
     self._reset_backend()  # clear caches
     self._visible_layers = None
     self._current_layout = None
     self._populate_layouts()
     self._populate_layer_list()
     self.draw_layout('Model')
     self.setWindowTitle('CAD Viewer - ' + str(document.filename))
Exemple #15
0
def test_fix_invalid_transparency():
    doc = ezdxf.new()
    msp = doc.modelspace()
    line = msp.add_line((0, 0), (1, 0))
    # transparency value requires 0x02000000 bit set
    line.dxf.unprotected_set("transparency", 0x10000000)
    auditor = Auditor(doc)
    line.audit(auditor)
    assert line.dxf.hasattr("transparency") is False
    assert len(auditor.fixes) == 1
Exemple #16
0
def _load_and_audit_document(recover_tool) -> Tuple['Drawing', 'Auditor']:
    from ezdxf.document import Drawing

    doc = Drawing()
    doc._load_section_dict(recover_tool.section_dict)

    auditor = Auditor(doc)
    for code, msg in recover_tool.errors:
        auditor.add_error(code, msg)
    for code, msg in recover_tool.fixes:
        auditor.fixed_error(code, msg)
    auditor.run()
    return doc, auditor
Exemple #17
0
def test_audit_ok():
    doc = ezdxf.new()
    auditor = Auditor(doc)

    rootdict = doc.rootdict
    assert 'TEST_VAR_1' not in rootdict
    new_var = rootdict.add_dict_var('TEST_VAR_1', 'Hallo')
    assert new_var.dxftype() == 'DICTIONARYVAR'

    rootdict.audit(auditor)
    assert len(auditor) == 0
def test_audit_invalid_pointer():
    doc = ezdxf.new()
    auditor = Auditor(doc)

    d = doc.rootdict.add_new_dict("TEST_AUDIT_2")
    entry = d.add_dict_var("TEST_VAR_2", "Hallo")
    entry.dxf.handle = "ABBA"
    d.audit(auditor)
    assert len(auditor.fixes) == 1
    e = auditor.fixes[0]
    assert e.code == AuditError.INVALID_DICTIONARY_ENTRY
def test_audit_ok():
    doc = ezdxf.new()
    auditor = Auditor(doc)

    rootdict = doc.rootdict
    assert "TEST_VAR_1" not in rootdict
    new_var = rootdict.add_dict_var("TEST_VAR_1", "Hallo")
    assert new_var.dxftype() == "DICTIONARYVAR"

    rootdict.audit(auditor)
    assert len(auditor) == 0
Exemple #20
0
def test_block_cycle_detector_setup():
    doc = ezdxf.new()
    a = doc.blocks.new('a')
    b = doc.blocks.new('b')
    c = doc.blocks.new('c')
    a.add_blockref('b', (0, 0))
    a.add_blockref('c', (0, 0))
    b.add_blockref('c', (0, 0))
    c.add_blockref('a', (0, 0))  # cycle

    detector = BlockCycleDetector(doc)
    assert detector.has_cycle('a') is True
    assert detector.has_cycle('b') is True
    assert detector.has_cycle('c') is True

    auditor = Auditor(doc)
    auditor.check_block_reference_cycles()
    assert len(auditor.errors) == 3  # one entry for each involved block: 'a', 'b', 'c'
    assert auditor.errors[0].code == AuditError.INVALID_BLOCK_REFERENCE_CYCLE
    assert auditor.errors[1].code == AuditError.INVALID_BLOCK_REFERENCE_CYCLE
    assert auditor.errors[2].code == AuditError.INVALID_BLOCK_REFERENCE_CYCLE
Exemple #21
0
    def audit(self, auditor: Auditor) -> None:
        """Audit and repair OBJECTS section.

        .. important::

            Do not delete entities while auditing process, because this
            would alter the entity database while iterating, instead use::

                auditor.trash(entity)

            to delete invalid entities after auditing automatically.

        """
        assert self.doc is auditor.doc, "Auditor for different DXF document."
        for entity in self._entity_space:
            if not is_dxf_object(entity):
                auditor.fixed_error(
                    code=AuditError.REMOVED_INVALID_DXF_OBJECT,
                    message=f"Removed invalid DXF entity {str(entity)} "
                    f"from OBJECTS section.",
                )
                auditor.trash(entity)
def test_duplicate_handle_loading_error(doc):
    msp = doc.modelspace()
    p1 = msp.add_point((0, 0))
    p2 = msp.add_point((0, 0))
    count = len(msp)
    # Simulate loading error with same handle for two entities!
    p2.dxf.handle = p1.dxf.handle
    auditor = Auditor(doc)
    block_record = doc.block_records.get("*Model_Space")
    block_record.audit(auditor)
    assert len(auditor.fixes) == 1
    assert len(msp) == count-1
    assert p2.is_alive, "entity should not be destroyed"
def test_audit_filters_invalid_entities(doc):
    group = doc.groups.new("test6")
    msp = doc.modelspace()
    block = doc.blocks.new("Block6")
    point1 = block.add_point((0, 0))  # invalid BLOCK entity
    point2 = msp.add_point((0, 0))  # valid model space entity ...
    point2.destroy()  # ... but destroyed
    layer = doc.layers.get("0")  # invalid table entry

    group.extend([point1, point2, layer])
    auditor = Auditor(doc)
    group.audit(auditor)
    assert len(group) == 0
def test_audit_fix_invalid_pointer():
    doc = ezdxf.new()
    auditor = Auditor(doc)

    d = doc.rootdict.add_new_dict("TEST_AUDIT_3")
    entry = d.add_dict_var("TEST_VAR_3", "Hallo")
    entry.dxf.handle = "ABBA"
    d.audit(auditor)
    assert len(auditor) == 0, "should return count of unfixed errors"
    assert len(auditor.errors) == 0
    assert len(auditor.fixes) == 1
    fix = auditor.fixes[0]
    assert fix.code == AuditError.INVALID_DICTIONARY_ENTRY

    # test if invalid entry was removed
    assert len(d) == 0
    assert "TEST_VAR_3" not in d
Exemple #25
0
def test_auditor_fixes_invalid_crease_count(msp):
    mesh = msp.add_mesh()
    with mesh.edit_data() as mesh_data:
        mesh_data.add_face([(0, 0, 0), (1, 0, 0), (1, 1, 0), (0, 1, 0)])
        mesh_data.add_edge_crease(v1=0, v2=1, crease=1.0)

    auditor = Auditor(msp.doc)
    mesh.audit(auditor)
    assert len(auditor.fixes) == 0
    assert len(auditor.errors) == 0

    auditor.reset()
    mesh.creases = [1, 1]  # too much crease values for only one edge
    mesh.audit(auditor)
    assert len(auditor.fixes) == 1
    assert list(mesh.creases) == [1.0]

    auditor.reset()
    mesh.creases = []  # too few crease values for only one edge
    mesh.audit(auditor)
    assert len(auditor.fixes) == 1
    assert list(mesh.creases) == [0.0]
Exemple #26
0
def auditor(dxf):
    return Auditor(dxf)
def auditor(doc):
    return Auditor(doc)
Exemple #28
0
 def audit(self, auditor: Auditor):
     """ Validity check. """
     super().audit(auditor)
     auditor.check_text_style(self)
# Copyright (c) 2011-2020, Manfred Moitzi
# License: MIT License
import pytest
from ezdxf.entitydb import EntityDB
from ezdxf.entities.dxfentity import DXFEntity
from ezdxf.audit import Auditor

ENTITY = DXFEntity.new(handle='FFFF')
auditor = Auditor(None)


@pytest.fixture
def db():
    db = EntityDB()
    db['FEFE'] = ENTITY
    return db


def test_get_value(db):
    assert ENTITY is db['FEFE']


def test_set_value(db):
    new_entity = DXFEntity.new(handle='FEFE')
    db['FEFE'] = new_entity
    assert new_entity is db['FEFE']


def test_del_value(db):
    del db['FEFE']
    with pytest.raises(KeyError):
Exemple #30
0
 def auditor(self, doc):
     return Auditor(doc)