def test_low_level_tagger_not_skip_comments(): tags = list( ascii_tags_loader(StringIO("999\ncomment\n0\nEOF\n"), skip_comments=False)) assert (999, "comment") == tags[0] assert (0, "EOF") == tags[1] assert len(tags) == 2
def test_write_R12_without_handles(filename, tmpdir): dwg = ezdxf.readfile(filename) dwg.header["$HANDLING"] = 0 export_path = str(tmpdir.join("dxf_r12_without_handles.dxf")) dwg.saveas(export_path) # can't check with ezdxf.readfile(), because handles automatically enabled with open(export_path) as f: tagger = ascii_tags_loader(f) sections = load_dxf_structure(tagger) for entity in sections["ENTITIES"]: with pytest.raises(ezdxf.DXFValueError): # has no handles entity.get_handle() for entity in sections["TABLES"]: if entity[0] != (0, "DIMSTYLE"): with pytest.raises(ezdxf.DXFValueError): # has no handles entity.get_handle() else: # special DIMSTYLE entity assert ( len(entity.find_all(105)) == 0 ), "remove handle group code 105" assert ( len(entity.find_all(5)) == 1 ), "do not remove group code 5"
def test_low_level_tagger_not_skip_comments(): tags = list( ascii_tags_loader(StringIO('999\ncomment\n0\nEOF\n'), skip_comments=False)) assert (999, 'comment') == tags[0] assert (0, 'EOF') == tags[1] assert len(tags) == 2
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_fix_line_coordinate_order(): tags = list(ascii_tags_loader(StringIO(TEST_LINE1))) ordered_tags = list(fix_coordinate_order(tags, codes=(10, 11))) assert ordered_tags[0] == (0, "LINE") assert ordered_tags[-6] == (10, "1000.") assert ordered_tags[-5] == (20, "2000.") assert ordered_tags[-4] == (11, "1100.") assert ordered_tags[-3] == (21, "2100.") assert ordered_tags[-2] == (1000, "ExtData") assert ordered_tags[-1] == (0, "EOF")
def test_fix_line_coordinate_order(): tags = list(ascii_tags_loader(StringIO(TEST_LINE1))) ordered_tags = list(fix_coordinate_order(tags, codes=(10, 11))) assert ordered_tags[0] == (0, 'LINE') assert ordered_tags[-6] == (10, '1000.') assert ordered_tags[-5] == (20, '2000.') assert ordered_tags[-4] == (11, '1100.') assert ordered_tags[-3] == (21, '2100.') assert ordered_tags[-2] == (1000, 'ExtData') assert ordered_tags[-1] == (0, 'EOF')
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 get_tag_loader(filename: Union[str, Path], errors: str = "ignore") -> Iterable[DXFTag]: filename = str(filename) if not is_dxf_file(filename): raise IOError(f"File '{filename}' is not an ASCII DXF file.") info = dxf_file_info(filename) with open(filename, mode="rt", encoding=info.encoding, errors=errors) as fp: # type: ignore return list(ascii_tags_loader(fp, skip_comments=True)) # type: ignore
def from_stream(stream: TextIO, codes: Set[int] = None) -> Iterable['DXFTag']: """ Yields comment tags from text `stream` as :class:`~ezdxf.lldxf.types.DXFTag` objects. Args: stream: input text stream codes: set of group codes to yield additional DXF tags e.g. {5, 0} to also yield handle and structure tags """ codes = codes or set() codes.add(999) return (tag for tag in ascii_tags_loader(stream, skip_comments=False) if tag.code in codes)
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 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 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 test_low_level_tagger(): tags = list(ascii_tags_loader(StringIO(TEST_LINE1))) assert len(tags) == 14
def test_low_level_tagger_skip_comments(): tags = list(ascii_tags_loader(StringIO('999\ncomment\n0\nEOF\n'))) assert (0, 'EOF') == tags[0] assert len(tags) == 1
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 string_reorder_tagger(s): return tag_reorder_layer(ascii_tags_loader(StringIO(s)))
def load_ascii(): with open(BIG_FILE, 'rt') as fp: list(ascii_tags_loader(fp))
def txt2tags(s: str) -> Tags: return Tags(ascii_tags_loader(StringIO(s), skip_comments=False))
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))