def raw_pretty_print(filename, nocompile=True, legacy_mode=False): try: info = dxf_file_info(str(filename)) except IOError: print("Unable to read DXF file '{}'.".format(filename)) sys.exit(1) except DXFError as e: print(str(e)) sys.exit(2) with io.open(filename, mode='rt', encoding=info.encoding, errors='ignore') as dxf: tagger = low_level_tagger(dxf) if legacy_mode: tagger = tag_reorder_layer(tagger) if nocompile is False: tagger = tag_compiler(tagger) html_filename = filename.parent / (filename.stem + '.html') try: with io.open(html_filename, mode='wt', encoding='utf-8') as html: html.write(rawpp(tagger, str(filename))) except IOError: print("IOError: can not write file '{}'.".format(html_filename)) except DXFStructureError as e: print("DXFStructureError: {}".format(str(e))) return html_filename
def test_safe_tag_loader(filename01): with open(filename01, 'rt', encoding='cp1252') as fp: expected = list(tag_compiler(iter(ascii_tags_loader(fp)))) with open(filename01, 'rb') as fp: tags = list(recover.safe_tag_loader(fp)) assert len(tags) == len(expected) assert tags[:100] == tags[:100]
def test_safe_tag_loader(): filename = fullpath(RECOVER1) with open(filename, "rt", encoding="cp1252") as fp: expected = list(tag_compiler(iter(ascii_tags_loader(fp)))) with open(filename, "rb") as fp: tags = list(recover.safe_tag_loader(fp)) assert len(tags) == len(expected) assert tags[:100] == tags[:100]
def entity_tags(entities: Iterable[Tags], handle: str) -> Optional[Tags]: def get_handle(tags: Tags): try: return tags.get_handle() except ValueError: return "0" for e in entities: if get_handle(e) == handle: return Tags(tag_compiler(iter(e))) return None
def readfile(filename: str, legacy_mode: bool = False, compile_tags=True) -> Iterable[DXFTag]: from ezdxf.lldxf.validator import is_dxf_file if not is_dxf_file(filename): raise IOError("File '{}' is not a DXF file.".format(filename)) info = dxf_file_info(filename) fp = open(filename, mode='rt', encoding=info.encoding, errors='ignore') tagger = low_level_tagger(fp) if legacy_mode: tagger = tag_reorder_layer(tagger) if compile_tags: tagger = tag_compiler(tagger) return tagger
def modelspace(filename: str, 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 = low_level_tagger(fp) queued: Optional[DXFEntity] = None tags: List[DXFTag] = [] factory = EntityFactory() linked_entity = entity_linker() for tag in tag_compiler(tagger): 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.entity(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
def modelspace(self) -> Iterable[DXFGraphic]: """ Returns an iterator for all supported DXF entities in the modelspace. These entities are regular :class:`~ezdxf.entities.DXFGraphic` objects but without a valid document assigned. It is **not** possible to add these entities to other `ezdxf` documents. It is only possible to recreate the objects by factory functions base on attributes of the source entity. For MESH, POLYMESH and POLYFACE it is possible to use the :class:`~ezdxf.render.MeshTransformer` class to render (recreate) this objects as new entities in another document. """ if self._fp_entities_section is None: self._fp_entities_section = self._seek_to_section('ENTITIES') self.file.seek(self._fp_entities_section) tags = [] factory = EntityFactory() polyline: Optional[Polyline] = None for tag in tag_compiler(low_level_tagger(self.file)): if tag.code == 0: # start new entity if len(tags): xtags = ExtendedTags(tags) dxftype = xtags.dxftype() if dxftype in SUPPORTED_DXF_TYPES: entity = factory.entity(xtags) if dxftype == 'SEQEND': if polyline is not None: polyline.seqend = entity yield polyline polyline = None # suppress all other SEQEND entities -> ATTRIB elif dxftype == 'VERTEX' and polyline is not None: # vertices without POLYLINE are DXF structure errors, but here just ignore it. polyline.vertices.append(entity) elif dxftype == 'POLYLINE': polyline = entity else: # POLYLINE without SEQEND is a DXF structure error, but here just ignore it. # By using this add-on be sure to get valid DXF files. polyline = None yield entity if tag == (0, 'ENDSEC'): break tags = [tag] else: tags.append(tag)
def readfile(filename: str, legacy_mode: bool = False, compile_tags=True, is_binary_dxf=False) -> Iterable[DXFTag]: if is_binary_dxf: with open(filename, mode='rb') as fp: data = fp.read() tagger = binary_tags_loader(data) else: info = dxf_file_info(filename) fp = open(filename, mode='rt', encoding=info.encoding, errors='ignore') tagger = ascii_tags_loader(fp) if legacy_mode: tagger = tag_reorder_layer(tagger) if compile_tags: tagger = tag_compiler(iter(tagger)) return tagger
def external_tag_compiler(text): return tag_compiler(low_level_tagger(StringIO(text)))
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 load_ascii(): with open(BIG_FILE, 'rt') as fp: list(tag_compiler(iter(ascii_tags_loader(fp))))
def external_tag_compiler(text): return tag_compiler(ascii_tags_loader(StringIO(text)))
def test_polyline_with_xdata(): tags = list(tag_compiler(ascii_tags_loader(StringIO(POLYLINE_WITH_XDATA)))) assert len(tags) == 49
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] = [] factory = EntityFactory() 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.entity(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
def read(stream): """Open an existing drawing.""" from ezdxf.lldxf.tagger import ascii_tags_loader, tag_compiler tagger = list(ascii_tags_loader(stream)) return tag_compiler(iter(tagger))
def test_polyline_with_xdata(): tags = list(tag_compiler(low_level_tagger(StringIO(POLYLINE_WITH_XDATA)))) assert len(tags) == 49
def read(stream): """ Open an existing drawing. """ from ezdxf.lldxf.tagger import low_level_tagger, tag_compiler tagger = list(low_level_tagger(stream)) return tag_compiler(iter(tagger))