def test_factory_load(): tags = ExtendedTags.from_text(POINT) e = factory.load(tags) assert e.dxftype() == 'POINT' assert e.doc is None assert e.dxf.handle == 'FEFE' assert e.dxf.owner is None assert e.is_alive is True assert e.is_virtual is True
def test_empty_section(): sec = load_section(EMPTYSEC, "CLASSES") cls_entities = [factory.load(ExtendedTags(e)) for e in sec] section = ClassesSection(None, iter(cls_entities)) stream = StringIO() section.export_dxf(TagWriter(stream)) result = stream.getvalue() stream.close() assert EMPTYSEC == result
def test_support_for_proxy_graphic_stored_in_acdb_entity(): tag_storage = factory.load(ExtendedTags.from_text(DXF_STORAGE)) assert tag_storage.dxftype() == "TAG_STORAGE" proxy = DXFGraphicProxy(tag_storage) # reusing data from test suite 252 types = [e.dxftype() for e in query_virtual_entities(proxy)] assert types == [ "POLYLINE", "POLYLINE", "ARC", "ARC", "POLYLINE", "POLYLINE", ]
def load_dxf_entities(entities: Iterable[Tags]) -> Iterable['DXFEntity']: check_tag_structure = options.check_entity_tag_structures for entity in entities: if len(entity) == 0: logger.debug('Ignore empty DXF entity.') continue code, dxftype = entity[0] if code != 0: raise DXFStructureError( f'Invalid first tag in DXF entity, group code={code}.') if check_tag_structure and (dxftype not in EXCLUDE_STRUCTURE_CHECK): entity = entity_structure_validator(entity) yield factory.load(ExtendedTags(entity))
def modelspace(filename: Filename, types: Iterable[str] = None) -> Iterable[DXFGraphic]: """ Iterate over all modelspace entities as :class:`DXFGraphic` objects of a seekable file. Use this function to 'quick' iterate over modelspace entities of a DXF file, filtering DXF types may speed up things if many entity types will be skipped. Args: filename: filename of a seekable DXF file types: DXF types like ``['LINE', '3DFACE']`` which should be returned, ``None`` returns all supported types. """ info = dxf_file_info(filename) prev_code: int = -1 prev_value: str = '' entities = False requested_types = _requested_types(types) with open(filename, mode='rt', encoding=info.encoding) as fp: tagger = ascii_tags_loader(fp) queued: Optional[DXFEntity] = None tags: List[DXFTag] = [] linked_entity = entity_linker() for tag in tag_compiler(tagger): code = tag.code value = tag.value if entities: if code == 0: if len(tags) and tags[0].value in requested_types: entity = factory.load(ExtendedTags(tags)) if not linked_entity( entity) and entity.dxf.paperspace == 0: if queued: # queue one entity for collecting linked entities (VERTEX, ATTRIB) yield queued queued = entity tags = [tag] else: tags.append(tag) if code == 0 and value == 'ENDSEC': if queued: yield queued return continue # if entities - nothing else matters elif code == 2 and prev_code == 0 and prev_value == 'SECTION': entities = (value == 'ENTITIES') prev_code = code prev_value = value
def load_entities(self, start: int, requested_types: Set[str]) -> Iterable[DXFGraphic]: def to_str(data: bytes) -> str: return data.decode(self.encoding, errors=self.errors).replace("\r\n", "\n") index = start entry = self.structure.index[index] self.file.seek(entry.location) while entry.value != "ENDSEC": index += 1 next_entry = self.structure.index[index] size = next_entry.location - entry.location data = self.file.read(size) if entry.value in requested_types: xtags = ExtendedTags.from_text(to_str(data)) yield factory.load(xtags) # type: ignore entry = next_entry
def load_entities( self, start: int, requested_types: Iterable[str] = None) -> Iterable[DXFGraphic]: def to_str(data: bytes) -> str: return data.decode(self.encoding).replace('\r\n', '\n') index = start entry = self.structure.index[index] self.file.seek(entry.location) while entry.value != 'ENDSEC': index += 1 next_entry = self.structure.index[index] size = next_entry.location - entry.location data = self.file.read(size) if entry.value in requested_types: xtags = ExtendedTags.from_text(to_str(data)) yield factory.load(xtags) entry = next_entry
def single_pass_modelspace( stream: BinaryIO, types: Iterable[str] = None, errors: str = "surrogateescape", ) -> Iterable[DXFGraphic]: """Iterate over all modelspace entities as :class:`DXFGraphic` objects in one single pass. Use this function to 'quick' iterate over modelspace entities of a **not** seekable binary DXF stream, filtering DXF types may speed up things if many entity types will be skipped. Args: stream: (not seekable) binary DXF stream types: DXF types like ``['LINE', '3DFACE']`` which should be returned, ``None`` returns all supported types. 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: Invalid or incomplete DXF file UnicodeDecodeError: if `errors` is "strict" and a decoding error occurs """ fetch_header_var: Optional[str] = None encoding = "cp1252" version = "AC1009" prev_code: int = -1 prev_value: str = "" entities = False requested_types = _requested_types(types) for code, value in binary_tagger(stream): if code == 0 and value == b"ENDSEC": break elif code == 2 and prev_code == 0 and value != b"HEADER": # (0, SECTION), (2, name) # First section is not the HEADER section entities = value == b"ENTITIES" break elif code == 9 and value == b"$DWGCODEPAGE": fetch_header_var = "ENCODING" elif code == 9 and value == b"$ACADVER": fetch_header_var = "VERSION" elif fetch_header_var == "ENCODING": encoding = toencoding(value.decode()) fetch_header_var = None elif fetch_header_var == "VERSION": version = value.decode() fetch_header_var = None prev_code = code if version >= "AC1021": encoding = "utf-8" queued: Optional[DXFGraphic] = None tags: List[DXFTag] = [] linked_entity = entity_linker() for tag in tag_compiler(binary_tagger(stream, encoding, errors)): code = tag.code value = tag.value if entities: if code == 0 and value == "ENDSEC": if queued: yield queued return if code == 0: if len(tags) and tags[0].value in requested_types: entity = cast(DXFGraphic, factory.load(ExtendedTags(tags))) if not linked_entity( entity) and entity.dxf.paperspace == 0: # queue one entity for collecting linked entities: # VERTEX, ATTRIB if queued: yield queued queued = entity tags = [tag] else: tags.append(tag) continue # if entities - nothing else matters elif code == 2 and prev_code == 0 and prev_value == "SECTION": entities = value == "ENTITIES" prev_code = code prev_value = value
def modelspace( filename: Filename, types: Iterable[str] = None, errors: str = "surrogateescape", ) -> Iterable[DXFGraphic]: """Iterate over all modelspace entities as :class:`DXFGraphic` objects of a seekable file. Use this function to iterate "quick" over modelspace entities of a DXF file, filtering DXF types may speed up things if many entity types will be skipped. Args: filename: filename of a seekable DXF file types: DXF types like ``['LINE', '3DFACE']`` which should be returned, ``None`` returns all supported types. 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: invalid or incomplete DXF file UnicodeDecodeError: if `errors` is "strict" and a decoding error occurs """ info = dxf_file_info(str(filename)) prev_code: int = -1 prev_value: Any = "" entities = False requested_types = _requested_types(types) with open(filename, mode="rt", encoding=info.encoding, errors=errors) as fp: tagger = ascii_tags_loader(fp) queued: Optional[DXFEntity] = None tags: List[DXFTag] = [] linked_entity = entity_linker() for tag in tag_compiler(tagger): code = tag.code value = tag.value if entities: if code == 0: if len(tags) and tags[0].value in requested_types: entity = factory.load(ExtendedTags(tags)) if (not linked_entity(entity) and entity.dxf.paperspace == 0): # queue one entity for collecting linked entities: # VERTEX, ATTRIB if queued: yield queued # type: ignore queued = entity tags = [tag] else: tags.append(tag) if code == 0 and value == "ENDSEC": if queued: yield queued # type: ignore return continue # if entities - nothing else matters elif code == 2 and prev_code == 0 and prev_value == "SECTION": entities = value == "ENTITIES" prev_code = code prev_value = value
def section(): sec = load_section(TESTCLASSES, "CLASSES") cls_entities = [factory.load(ExtendedTags(e)) for e in sec] return ClassesSection(None, iter(cls_entities))
def proxy() -> ACADProxyEntity: xtags = ExtendedTags.from_text(AEC_DOOR) return cast(ACADProxyEntity, factory.load(xtags, ezdxf.new("R2018")))
def load_dxf_entities(entities: Iterable[Tags]) -> Iterable['DXFEntity']: for entity in entities: yield factory.load(ExtendedTags(entity))
def load_dxf_entities(entities: Iterable[Tags], doc: "Drawing" = None) -> Iterable["DXFEntity"]: for entity in entities: yield factory.load(ExtendedTags(entity), doc)
def single_pass_modelspace(stream: BinaryIO, types: Iterable[str] = None ) -> Iterable[DXFGraphic]: """ Iterate over all modelspace entities as :class:`DXFGraphic` objects in one single pass. Use this function to 'quick' iterate over modelspace entities of a **not** seekable binary DXF stream, filtering DXF types may speed up things if many entity types will be skipped. Args: stream: (not seekable) binary DXF stream types: DXF types like ``['LINE', '3DFACE']`` which should be returned, ``None`` returns all supported types. """ fetch_header_var: Optional[str] = None encoding = 'cp1252' version = 'AC1009' prev_code: int = -1 prev_value: str = '' entities = False requested_types = _requested_types(types) for code, value in binary_tagger(stream): if code == 0 and value == b'ENDSEC': break elif code == 2 and prev_code == 0 and value != b'HEADER': # (0, SECTION), (2, name) # First section is not the HEADER section entities = (value == b'ENTITIES') break elif code == 9 and value == b'$DWGCODEPAGE': fetch_header_var = 'ENCODING' elif code == 9 and value == b'$ACADVER': fetch_header_var = 'VERSION' elif fetch_header_var == 'ENCODING': encoding = toencoding(value.decode()) fetch_header_var = None elif fetch_header_var == 'VERSION': version = value.decode() fetch_header_var = None prev_code = code if version >= 'AC1021': encoding = 'utf-8' queued: Optional[DXFEntity] = None tags: List[DXFTag] = [] linked_entity = entity_linker() for tag in tag_compiler(binary_tagger(stream, encoding)): code = tag.code value = tag.value if entities: if code == 0 and value == 'ENDSEC': if queued: yield queued return if code == 0: if len(tags) and tags[0].value in requested_types: entity = factory.load(ExtendedTags(tags)) if not linked_entity( entity) and entity.dxf.paperspace == 0: if queued: # queue one entity for collecting linked entities (VERTEX, ATTRIB) yield queued queued = entity tags = [tag] else: tags.append(tag) continue # if entities - nothing else matters elif code == 2 and prev_code == 0 and prev_value == 'SECTION': entities = (value == 'ENTITIES') prev_code = code prev_value = value