def test_init(): tag = DXFBinaryTag.from_string(310, 'FFFF') assert tag == (310, b"\xff\xff") tag = DXFBinaryTag(310, b"\xff\xff") assert tag == (310, b"\xff\xff") tag2 = DXFBinaryTag.from_string(code=310, value='FFFF') assert tag2 == (310, b"\xff\xff")
def test_hexstr_to_bytes(): import array s = "".join("%0.2X" % byte for byte in range(256)) assert len(s) == 512 bytes_ = unhexlify(s) assert len(bytes_) == 256 for x, y in zip(array.array("B", bytes_), range(256)): assert x == y tag = DXFBinaryTag(310, bytes_) assert tag.tostring() == s
def test_hexstr_to_bytes(): import array s = ''.join('%0.2X' % byte for byte in range(256)) assert len(s) == 512 bytes_ = unhexlify(s) assert len(bytes_) == 256 # works in Python 2.7 & Python 3 for x, y in zip(array.array('B', bytes_), range(256)): assert x == y tag = DXFBinaryTag(310, bytes_) assert tag.tostring() == s
def test_long_string(): tag = DXFBinaryTag.from_string( 310, "414349532042696E61727946696C652855000000000000020000000C00000007104175746F6465736B204175746F434144071841534D203231392E302E302E3536303020556E6B6E6F776E071853756E204D61792020342031353A34373A3233203230313406000000000000F03F068DEDB5A0F7C6B03E06BBBDD7D9DF7CDB", ) assert len(tag.value) == 127 clone = tag.clone() assert tag.value == clone.value
def set_data(self, byte_data): self.clear() vba_tags = self.AcDbVbaProject start = 0 count = 0 while start < len(byte_data): vba_tags.append(DXFBinaryTag(310, byte_data[start:start+254])) count += 1 start += 254 self.dxf.count = count
def test_dxf_str(): assert DXFBinaryTag.from_string(310, 'FFFF').tostring() == "FFFF" assert DXFBinaryTag.from_string(310, 'FFFF').dxfstr() == "310\nFFFF\n"
def test_index_able(): tag = DXFBinaryTag.from_string(310, 'FFFF') assert tag[0] == 310 assert tag[1] == b"\xff\xff"
def export_data(self, tagwriter: 'TagWriter'): data = self.data while data: tagwriter.write_tag(DXFBinaryTag(310, data[:127])) data = data[127:]
def byte_tag_compiler( tags: Iterable[DXFTag], encoding=const.DEFAULT_ENCODING, messages: List = None, errors: str = 'surrogateescape', ) -> Iterable[DXFTag]: """ Compiles DXF tag values imported by bytes_loader() into Python types. Raises DXFStructureError() for invalid float values and invalid coordinate values. Expects DXF coordinates written in x, y[, z] order, see function :func:`safe_tag_loader` for usage with applied repair filters. Args: tags: DXF tag generator, yielding tag values as bytes like bytes_loader() encoding: text encoding messages: list to store error messages 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: Found invalid DXF tag or unexpected coordinate order. """ def error_msg(tag): code = tag.code value = tag.value.decode(encoding) return f'Invalid tag ({code}, "{value}") near line: {line}.' if messages is None: messages = [] tags = iter(tags) undo_tag = None line = 0 while True: try: if undo_tag is not None: x = undo_tag undo_tag = None else: x = next(tags) line += 2 code = x.code if code in POINT_CODES: y = next(tags) # y coordinate is mandatory line += 2 # e.g. y-code for x-code=10 is 20 if y.code != code + 10: raise const.DXFStructureError( f"Missing required y-coordinate near line: {line}.") # optional z coordinate z = next(tags) line += 2 try: # is it a z-coordinate like (30, 0.0) for base x-code=10 if z.code == code + 20: try: point = (float(x.value), float(y.value), float(z.value)) except ValueError: # search for any float values point = (_search_float(x.value), _search_float(y.value), _search_float(z.value)) else: try: point = (float(x.value), float(y.value)) except ValueError: # seach for any float values point = ( _search_float(x.value), _search_float(y.value), ) undo_tag = z except ValueError: raise const.DXFStructureError( f'Invalid floating point values near line: {line}.') yield DXFVertex(code, point) elif code in BINARY_DATA: # maybe pre compiled in low level tagger (binary DXF) if isinstance(x, DXFBinaryTag): tag = x else: try: tag = DXFBinaryTag.from_string(code, x.value) except ValueError: raise const.DXFStructureError( f'Invalid binary data near line: {line}.') yield tag else: # just a single tag type_ = TYPE_TABLE.get(code, str) value: bytes = x.value if type_ is str: if code == 0: # remove white space from structure tags value = x.value.strip().upper() try: # 2 stages to document decoding errors str_ = value.decode(encoding, errors='strict') except UnicodeDecodeError: str_ = value.decode(encoding, errors=errors) messages.append( (AuditError.DECODING_ERROR, f'Fixed unicode decoding error near line {line}')) # Convert DXF unicode notation "\U+xxxx" to unicode, # but exclude structure tags (code>0): if code and has_dxf_unicode(str_): str_ = decode_dxf_unicode(str_) yield DXFTag(code, str_) else: try: # fast path for int and float yield DXFTag(code, type_(value)) except ValueError: # slow path - e.g. ProE stores int values as floats :(( if type_ is int: try: yield DXFTag(code, _search_int(x.value)) except ValueError: raise const.DXFStructureError(error_msg(x)) elif type_ is float: try: yield DXFTag(code, _search_float(x.value)) except ValueError: raise const.DXFStructureError(error_msg(x)) else: raise const.DXFStructureError(error_msg(x)) except StopIteration: return
def byte_tag_compiler(tags: Iterable[DXFTag], encoding=const.DEFAULT_ENCODING) -> Iterable[DXFTag]: """ Compiles DXF tag values imported by bytes_loader() into Python types. Raises DXFStructureError() for invalid float values and invalid coordinate values. Expects DXF coordinates written in x, y[, z] order, see function :func:`safe_tag_loader` for usage with applied repair filters. Args: tags: DXF tag generator, yielding tag values as bytes like bytes_loader() encoding: text encoding Raises: DXFStructureError: Found invalid DXF tag or unexpected coordinate order. """ def error_msg(tag): code = tag.code value = tag.value.decode(encoding) return f'Invalid tag ({code}, "{value}") near line: {line}.' tags = iter(tags) undo_tag = None line = 0 while True: try: if undo_tag is not None: x = undo_tag undo_tag = None else: x = next(tags) line += 2 code = x.code if code in POINT_CODES: y = next(tags) # y coordinate is mandatory line += 2 # e.g. y-code for x-code=10 is 20 if y.code != code + 10: raise const.DXFStructureError( f"Missing required y-coordinate near line: {line}.") # optional z coordinate z = next(tags) line += 2 try: # is it a z-coordinate like (30, 0.0) for base x-code=10 if z.code == code + 20: point = (float(x.value), float(y.value), float(z.value)) else: point = (float(x.value), float(y.value)) undo_tag = z except ValueError: raise const.DXFStructureError( f'Invalid floating point values near line: {line}.') yield DXFVertex(code, point) elif code in BINARY_DATA: # maybe pre compiled in low level tagger (binary DXF) if isinstance(x, DXFBinaryTag): tag = x else: try: tag = DXFBinaryTag.from_string(code, x.value) except ValueError: raise const.DXFStructureError( f'Invalid binary data near line: {line}.') yield tag else: # just a single tag type_ = TYPE_TABLE.get(code, str) value: bytes = x.value if type_ is str: if code == 0: # remove white space from structure tags value = x.value.strip() yield DXFTag(code, value.decode(encoding)) else: try: # fast path for int and float yield DXFTag(code, type_(value)) except ValueError: # slow path - ProE stores int values as floats :(( if type_ is int: try: yield DXFTag(code, int(float(x.value))) except ValueError: raise const.DXFStructureError(error_msg(x)) else: raise const.DXFStructureError(error_msg(x)) except StopIteration: return