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")
Example #2
0
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
Example #4
0
def test_long_string():
    tag = DXFBinaryTag.from_string(
        310,
        "414349532042696E61727946696C652855000000000000020000000C00000007104175746F6465736B204175746F434144071841534D203231392E302E302E3536303020556E6B6E6F776E071853756E204D61792020342031353A34373A3233203230313406000000000000F03F068DEDB5A0F7C6B03E06BBBDD7D9DF7CDB",
    )
    assert len(tag.value) == 127
    clone = tag.clone()
    assert tag.value == clone.value
Example #5
0
 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"
Example #8
0
 def export_data(self, tagwriter: 'TagWriter'):
     data = self.data
     while data:
         tagwriter.write_tag(DXFBinaryTag(310, data[:127]))
         data = data[127:]
Example #9
0
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
Example #10
0
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