memoryview of LitteleEndianStructure cause error

Create issue
Issue #3172 closed
Hiroshi Miura created an issue

When adding following test case in extra_tests/ctypes_test/test_structure.py

def test_memoryview_endian():
    class LES(LittleEndianStructure):
        _pack_ = 1
        _fields_ = [
            ('a', c_ubyte * 16),
            ('i', c_uint64)
        ]
    c_les = LES()
    mv = memoryview(c_les)

The test fails as TypeError on pypy3.6.9 -7.3.1 alpha with following log.

$ pypy3 -m pytest extra_tests/ctypes_tests/test_structures.py 
========================================================= test session starts ==========================================================
platform linux -- Python 3.6.9[pypy-7.3.1-alpha], pytest-2.9.2, py-1.4.29, pluggy-0.3.1
rootdir: /home/miurahr/projects/pypy/extra_tests, inifile: pytest.ini
collected 15 items 

extra_tests/ctypes_tests/test_structures.py ..............F

=============================================================== FAILURES ===============================================================
________________________________________________________ test_memoryview_endian ________________________________________________________

    def test_memoryview_endian():
        class LES(LittleEndianStructure):
            _pack_ = 1
            _fields_ = [
                ('a', c_ubyte * 16),
                ('i', c_uint64)
            ]
        c_les = LES()
>       mv = memoryview(c_les)

extra_tests/ctypes_tests/test_structures.py:217: 
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 
/opt/pypy3/lib_pypy/_ctypes/structure.py:309: in __buffer__
    fmt = get_format_str(self)
/opt/pypy3/lib_pypy/_ctypes/array.py:309: in get_format_str
    ch = get_format_str(obj)[1:]
_ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ 

typ = <class '_ctypes.array.c_ubyte_Array_16'>

    def get_format_str(typ):
        if hasattr(typ, '_fields_'):
            if hasattr(typ, '_swappedbytes_'):
                bo = swappedorder[sys.byteorder]
            else:
                bo = byteorder[sys.byteorder]
            flds = []
            cum_size = 0
            for name, obj in typ._fields_:
                padding = typ._ffistruct_.fieldoffset(name) - cum_size
                if padding:
                    flds.append('%dx' % padding)
                # Trim off the leading '<' or '>'
                ch = get_format_str(obj)[1:]
                if (ch) == 'B':
                    flds.append(byteorder[sys.byteorder])
                else:
                    flds.append(bo)
                flds.append(ch)
                flds.append(':')
                flds.append(name)
                flds.append(':')
                cum_size += typ._ffistruct_.fieldsize(name)
            return 'T{' + ''.join(flds) + '}'
        elif hasattr(typ, '_type_'):
            ch = typ._type_
>           return byteorder[sys.byteorder] + ch
E           TypeError: unsupported operand type(s) for +: 'str' and 'SimpleType'

/opt/pypy3/lib_pypy/_ctypes/array.py:322: TypeError
======================================== 1 failed, 14 passed, 1 pytest-warnings in 0.49 seconds ========================================
miurahr@miurahr-note:~/projects/pypy$

Environment:

Python 3.6.9 (22226b5e0778, Dec 12 2019, 22:56:14) [PyPy 7.3.1-alpha0 with GCC 7.4.0]

Linux Mint 19.3

Linux 5.3.0-46-generic #38~18.04.1-Ubuntu SMP Tue Mar 31 04:17:56 UTC 2020 x86_64 x86_64 x86_64 GNU/Linux

Comments (5)

  1. mattip

    It is not even clear what the format of this should be. PEP 3118 seems to suggest 'T{(16,)<B:a:<L:i:}', but CPython shows only B

    Anyhow, an error is definitely not the correct thing

  2. Log in to comment