Beispiel #1
0
def test_custom_extension_array():
    import array

    class ArrayExtension(bsdf.Extension):
        name = 'array'
        cls = array.array

        def encode(self, s, arr):
            return dict(typecode=str(arr.typecode), data=arr.tostring())

        def decode(self, s, d):
            a = array.array(d['typecode'])
            a.fromstring(d['data'])
            return a

    extensions = [ArrayExtension]

    a1 = [1, 2, array.array('b', [1, 2, 42])]
    a2 = [1, 2, array.array('b', [1, 2, 42] * 1000)]
    a3 = [1, 2, array.array('b', [4, 2, 42] * 1000)]
    bb1 = bsdf.encode(a1, extensions)
    bb2 = bsdf.encode(a2, extensions, compression=0)
    bb3 = bsdf.encode(a3, extensions, compression=1)

    assert len(bb2) > len(bb1) * 10
    assert len(bb2) > len(bb3) * 10

    b1 = bsdf.decode(bb1, extensions)
    b2 = bsdf.decode(bb2, extensions)
    b3 = bsdf.decode(bb3, extensions)

    assert a1 == b1
    assert a2 == b2
    assert a3 == b3
Beispiel #2
0
def test_blob_writing1():

    # Use blob to specify bytes
    blob = bsdf.Blob(b'xxxx')
    bb1 = bsdf.encode([2, 3, blob, 5])

    # Again, with extra size
    blob = bsdf.Blob(b'xxxx', extra_size=100)
    bb2 = bsdf.encode([2, 3, blob, 5])

    # Again, with checksum
    blob = bsdf.Blob(b'xxxx', use_checksum=True)
    bb3 = bsdf.encode([2, 3, blob, 5])

    assert len(bb2) == len(bb1) + 100
    assert len(bb3) == len(bb1) + 16

    assert bsdf.decode(bb1) == [2, 3, b'xxxx', 5]
    assert bsdf.decode(bb2) == [2, 3, b'xxxx', 5]
    assert bsdf.decode(bb3) == [2, 3, b'xxxx', 5]

    # Fail
    with raises(TypeError):
        bsdf.Blob([1, 2, 3])
    with raises(RuntimeError):
        blob.tell()
    with raises(RuntimeError):
        blob.seek(0)
    with raises(RuntimeError):
        blob.read(1)
    with raises(RuntimeError):
        blob.write(b'xx')
Beispiel #3
0
def test_standard_extensions_ndarray():

    try:
        import numpy as np
    except ImportError:
        skip('need numpy')

    extensions = None

    a1 = [1, 2, np.array([1, 2, 3, 4]).reshape((2, 2))]
    a2 = [1, 2, np.array([1, 2, 42] * 1000)]
    a3 = [1, 2, np.array([4, 2, 42] * 1000)]
    b1 = bsdf.encode(a1, extensions)
    b2 = bsdf.encode(a2, extensions, compression=0)
    b3 = bsdf.encode(a3, extensions, compression=1)

    assert len(b2) > len(b1) * 10
    assert len(b2) > len(b3) * 10

    c1 = bsdf.decode(b1, extensions)
    c2 = bsdf.decode(b2, extensions)
    c3 = bsdf.decode(b3, extensions)

    assert np.all(a1[2] == c1[2])
    assert np.all(a2[2] == c2[2])
    assert np.all(a3[2] == c3[2])
Beispiel #4
0
def test_blob_reading1():

    blob = bsdf.Blob(b'xxxx')
    bb1 = bsdf.encode([2, 3, blob, 5])

    res1 = bsdf.decode(bb1)
    assert isinstance(res1[2], bytes)

    res1 = bsdf.decode(bb1, lazy_blob=True)
    assert not isinstance(res1[2], bytes) and isinstance(res1[2], bsdf.Blob)

    res1[2].get_bytes() == b'xxxx'
Beispiel #5
0
def test_streaming_closing123():
    """ Writing a streamed list, closing the stream. """
    for iter in range(4):

        f = io.BytesIO()

        thelist = bsdf.ListStream()
        bsdf.save(f, thelist)

        thelist.append('hi')

        # closing here will write the length of the stream, marking the stream as closed
        if iter in (1, 2):
            thelist.close()

        for i in range(3):
            thelist.append(i)

        if iter == 2:
            thelist.close()
        if iter == 3:
            thelist.close(True)

        assert thelist.count == 4
        assert thelist.index == thelist.count

        bb = f.getvalue()
        b1 = bsdf.decode(bb)
        b2 = bsdf.decode(bb, load_streaming=True)

        if iter in (0, 1, 2):
            assert isinstance(b2, bsdf.ListStream) and not isinstance(b2, list)
        else:
            assert not isinstance(b2, bsdf.ListStream) and isinstance(b2, list)

        if iter == 0:
            # Not closed
            assert b1 == ['hi', 0, 1, 2]
            assert list(b2) == ['hi', 0, 1, 2]
        elif iter == 1:
            # Closed, and elements added later
            assert b1 == ['hi']
            assert list(b2) == ['hi']
        elif iter == 2:
            # Closed twice
            assert b1 == ['hi', 0, 1, 2]
            assert list(b2) == ['hi', 0, 1, 2]
        elif iter == 3:
            # Closed twice
            assert b1 == ['hi', 0, 1, 2]
            assert list(b2) == ['hi', 0, 1, 2]
        else:
            assert False
Beispiel #6
0
def test_liststreaming_reading1():
    """ Reading a streamed list. """
    f = io.BytesIO()

    thelist = bsdf.ListStream()
    a = [3, 4, thelist]

    bsdf.save(f, a)

    thelist.append('hi')
    for i in range(3):
        thelist.append(i)

    bb = f.getvalue()
    b = bsdf.decode(bb, load_streaming=True)

    x = b[-1]
    assert isinstance(x, bsdf.ListStream)

    assert x.next() == 'hi'
    assert x.next() == 0
    assert x.next() == 1
    assert x.next() == 2
    with raises(StopIteration):
        x.next()

    # Support iteration
    b = bsdf.decode(bb, load_streaming=True)
    x = b[-1]
    xx = [i for i in x]
    assert xx == ['hi', 0, 1, 2]

    # Cannot read after file is closed
    f = io.BytesIO(bb)
    b = bsdf.load(f, load_streaming=True)
    x = b[-1]
    f.close()
    with raises(IOError):
        x.next()

    # Cannot read when in read-mode
    ls = bsdf.ListStream()
    with raises(IOError):
        ls.next()
    with raises(IOError):
        list(ls)

    # mmm, this would never happen, I guess, but need associated file!
    ls = bsdf.ListStream('r')
    with raises(IOError):
        ls.next()
Beispiel #7
0
def test_float32():

    # Using float32 makes smaller files
    data = [2.0, 3.1, 5.1]
    b1 = bsdf.encode(data, float64=False)
    b2 = bsdf.encode(data, float64=True)
    assert len(b1) < len(b2)
    #
    assert bsdf.decode(b1) != data
    assert bsdf.decode(b2) == data
    assert all(abs(i1 - i2) < 0.01 for i1, i2 in zip(bsdf.decode(b1), data))
    assert all(abs(i1 - i2) < 0.001 for i1, i2 in zip(bsdf.decode(b2), data))

    # Does not affect ints
    data = [2, 3, 5]
    b1 = bsdf.encode(data, float64=False)
    b2 = bsdf.encode(data, float64=True)
    assert len(b1) == len(b2)
    #
    assert bsdf.decode(b1) == data
    assert bsdf.decode(b2) == data

    # Ints are auto-scaled
    b1 = bsdf.encode([3, 4, 5, 300, 400, 500])
    b2 = bsdf.encode([300000, 400000, 500000, 3000000, 4000000, 5000000])
    assert len(b1) < len(b2)
    #
    assert bsdf.decode(b1) == [3, 4, 5, 300, 400, 500]
    assert bsdf.decode(b2) == [
        300000, 400000, 500000, 3000000, 4000000, 5000000
    ]
Beispiel #8
0
def test_loaders_and_savers():

    # load and save is already tested above and in many other places

    s1 = dict(foo=42, bar=[1, 2.1, False, 'spam', b'eggs'])

    # In-memory
    bb = bsdf.encode(s1)
    s2 = bsdf.decode(bb)
    assert s1 == s2

    # Using a filename
    bsdf.save(tempfilename, s1)
    s2 = bsdf.load(tempfilename)
    assert s1 == s2

    # Using a file object
    with open(tempfilename, 'wb') as f:
        bsdf.save(f, s1)
    with open(tempfilename, 'rb') as f:
        s2 = bsdf.load(f)
    assert s1 == s2

    # Using a very strict file object
    with open(tempfilename, 'wb') as f:
        bsdf.save(StrictWriteFile(f), s1)
    with open(tempfilename, 'rb') as f:
        s2 = bsdf.load(StrictReadFile(f))
    assert s1 == s2
Beispiel #9
0
def test_all_types_simple():

    s1 = dict(
        v1=None,
        v2=False,
        v3=True,
        v4=3,
        v5=3.2,
        v6=u'a',  # u-prefix is needed in Legacy Python to not be bytes
        v7=u'aa',
        v8=(1, 2),
        v9=[3, 4],
        v10={
            'a': 0,
            'b': 1
        },
        v11=b'b',
        v12=b'bb',
    )

    bb = bsdf.encode(s1)
    s2 = bsdf.decode(bb)

    # Correction - tuples become lists
    assert isinstance(s2['v8'], list)
    s2['v8'] = tuple(s2['v8'])

    assert bb.startswith(b'BSDF')
    assert s1 == s2
    for key in s1:
        assert type(s1[key]) == type(s2[key])
Beispiel #10
0
def load_bsdf(filename, decode=True):
    ''' load object from a BSDF file. automatically decode if in bytes. '''
    object = bsdf.load(filename)
    if decode and (type(object) is bytes):
        return bsdf.decode(object)
    else:
        return object
Beispiel #11
0
def test_blob_modding2():  # with checksum

    bb = bsdf.encode(bsdf.Blob(b'xxyyzz', extra_size=2, use_checksum=True))
    f = io.BytesIO(bb)
    blob = bsdf.load(f, lazy_blob=True)

    blob.seek(4)
    blob.write(b'aa')
    blob.update_checksum()
    assert bsdf.decode(f.getvalue()) == b'xxyyaa'
Beispiel #12
0
def test_extension_recurse():
    class MyExt1(bsdf.Extension):
        name = 'myob1'
        cls = MyObject1

        def encode(self, s, v):
            return v.val

        def decode(self, s, v):
            return MyObject1(v)

    class MyExt2(bsdf.Extension):
        name = 'myob2'
        cls = MyObject2

        def encode(self, s, v):
            # encode a MyObject2 as MyObject1
            return MyObject1(v.val)

        def decode(self, s, v):
            # decode a MyObject2 from MyObject1
            return MyObject2(v.val)

    class MyExt3(bsdf.Extension):
        name = 'myob2'
        cls = MyObject2

        def encode(self, s, v):
            # encode a MyObject2 as [MyObject1]
            return [MyObject1(v.val)]

        def decode(self, s, v):
            # decode a MyObject2 from MyObject1
            return MyObject2(v[0].val)

    a = MyObject2(14)
    with raises(ValueError):
        b = bsdf.encode(a, [MyExt1, MyExt2])

    b = bsdf.encode(a, [MyExt1, MyExt3])
    c = bsdf.decode(b, [MyExt1, MyExt3])
    assert repr(a) == repr(c)
Beispiel #13
0
def test_liststreaming1():
    """ Writing a streamed list. """
    f = io.BytesIO()

    thelist = bsdf.ListStream()
    a = [3, 4, thelist]

    bsdf.save(f, a)

    thelist.append('hi')
    for i in range(10):
        thelist.append(i * 101)
    thelist.append((4, 2))

    thelist.close()
    bb = f.getvalue()
    b = bsdf.decode(bb)

    assert b[-1] == [
        'hi', 0, 101, 202, 303, 404, 505, 606, 707, 808, 909, [4, 2]
    ]
Beispiel #14
0
def test_extension_default_notimplemented():
    class MyExt1(bsdf.Extension):
        name = 'myob1'
        cls = MyObject1

    class MyExt2(bsdf.Extension):
        name = 'myob1'
        cls = MyObject1

        def encode(self, s, v):
            return v.val

    assert 'myob1' in repr(MyExt1()) and 'BSDF extension' in repr(MyExt1())

    a = MyObject1(7)

    with raises(NotImplementedError):
        bsdf.encode(a, [MyExt1])

    b = bsdf.encode(a, [MyExt2])
    with raises(NotImplementedError):
        c = bsdf.decode(b, [MyExt2])
Beispiel #15
0
def test_parse_errors1():

    msgs = []

    class MyHandler(logging.Handler):
        def emit(self, record):
            msgs.append(record.getMessage())

    myHandler = MyHandler()
    logger = bsdf.logger.addHandler(myHandler)

    V = bsdf.VERSION
    assert V[0] > 0 and V[0] < 255  # or our tests will fail
    assert V[1] > 0 and V[1] < 255

    def header(*version):
        return ('BSDF' + chr(version[0]) + chr(version[1])).encode()

    assert bsdf.decode(header(*V) + b'v') == None
    assert bsdf.decode(header(*V) + b'h\x07\x00') == 7

    # Not BSDF
    with raises(RuntimeError) as err:
        assert bsdf.decode(b'BZDF\x02\x00v')
    assert ' not ' in str(err) and 'BSDF' in str(err)

    # Major version mismatch
    with raises(RuntimeError) as err1:
        assert bsdf.decode(header(V[0] - 1, V[1]) + b'v')
    with raises(RuntimeError) as err2:
        assert bsdf.decode(header(V[0] + 1, V[1]) + b'v')
    for err in (err1, err2):
        assert 'different major version' in str(err)
        assert bsdf.__version__ in str(err)

    # Smaller minor version is ok, larger minor version displays warning
    out = ''
    err = ''.join(msgs)
    msgs[:] = []
    bsdf.decode(header(V[0], V[1] - 1) + b'v')
    out = ''
    err = ''.join(msgs)
    msgs[:] = []
    assert not out and not err
    bsdf.decode(header(V[0], V[1] + 1) + b'v')
    out = ''
    err = ''.join(msgs)
    msgs[:] = []
    assert not out and 'higher minor version' in err

    # Wrong types
    with raises(RuntimeError):
        bsdf.decode(b'BSDF\x02\x00r\x07')
        #                         \ r is not a known type

    logger = bsdf.logger.removeFilter(myHandler)
Beispiel #16
0
def test_custom_extensions():
    class MyExtension(bsdf.Extension):
        name = 'myob'

        def encode(self, s, v):
            assert isinstance(s, bsdf.BsdfSerializer)
            return v.val

        def decode(self, s, v):
            assert isinstance(s, bsdf.BsdfSerializer)
            return MyObject1(v)

    class MyExtension1(MyExtension):
        cls = MyObject1

        def match(self, s, v):
            return False

    class MyExtension2(MyExtension):
        cls = MyObject1, MyObject2

        def match(self, s, v):
            return False

    class MyExtension3(MyExtension):
        cls = MyObject1
        # default: def match(self, v): return isinstance(v, self.cls)

    # Define data
    a1 = [1, MyObject1(2), 3]
    a2 = [1, MyObject1(2), MyObject2(3), 4]

    # Extension 1 can only encode MyObject1
    b1 = bsdf.encode(a1, [MyExtension1])
    c1 = bsdf.decode(b1, [MyExtension1])
    d1 = bsdf.decode(b1, [])
    assert repr(a1) == repr(c1)
    assert repr(a1) != repr(d1)
    assert d1 == [1, 2, 3]  # just has the undelying value
    #
    with raises(TypeError):
        b2 = bsdf.encode(a2, [MyExtension1])

    # Extension 2 can encode both
    b1 = bsdf.encode(a1, [MyExtension2])
    c1 = bsdf.decode(b1, [MyExtension2])
    assert repr(a1) == repr(c1)
    #
    b2 = bsdf.encode(a2, [MyExtension2])
    c2 = bsdf.decode(b2, [MyExtension2])
    assert repr(a2).replace('ct2', 'ct1') == repr(c2)

    # Extension 3 can encode both too
    b3 = bsdf.encode(a1, [MyExtension2])
    c3 = bsdf.decode(b1, [MyExtension2])
    assert repr(a1) == repr(c1)
    #
    b3 = bsdf.encode(a2, [MyExtension3])
    c3 = bsdf.decode(b2, [MyExtension3])
    assert repr(a2).replace('ct2', 'ct1') == repr(c2)

    # Overwriting works
    b3 = bsdf.encode(a2, [MyExtension1, MyExtension3])
    c3 = bsdf.decode(b2, [MyExtension1, MyExtension3])
    assert repr(a2).replace('ct2', 'ct1') == repr(c2)