Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package python-cstruct for openSUSE:Factory checked in at 2022-12-06 14:24:14 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-cstruct (Old) and /work/SRC/openSUSE:Factory/.python-cstruct.new.1835 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-cstruct" Tue Dec 6 14:24:14 2022 rev:6 rq:1040543 version:5.2 Changes: -------- --- /work/SRC/openSUSE:Factory/python-cstruct/python-cstruct.changes 2022-11-14 14:29:14.487041278 +0100 +++ /work/SRC/openSUSE:Factory/.python-cstruct.new.1835/python-cstruct.changes 2022-12-06 14:24:29.658199196 +0100 @@ -1,0 +2,17 @@ +Tue Dec 6 01:00:29 UTC 2022 - Yogalakshmi Arunachalam <yarunacha...@suse.com> + +- Update to version 5.2 + Fix + - nested struct unpack fix + - nested anonymous union offset fix + - inspect offset for nested struct/union fix + +- Update to version 5.1 + Improved + * Support unpack from ctype pointers + Added + * Add support for char constants + * Add native type test + * dir.py example + +------------------------------------------------------------------- Old: ---- python-cstruct-5.0.tar.gz New: ---- python-cstruct-5.2.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-cstruct.spec ++++++ --- /var/tmp/diff_new_pack.ToxJw9/_old 2022-12-06 14:24:30.138203289 +0100 +++ /var/tmp/diff_new_pack.ToxJw9/_new 2022-12-06 14:24:30.142203323 +0100 @@ -18,7 +18,7 @@ Name: python-cstruct -Version: 5.0 +Version: 5.2 Release: 0 Summary: C-style structs for Python License: MIT ++++++ python-cstruct-5.0.tar.gz -> python-cstruct-5.2.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/README.md new/python-cstruct-5.2/README.md --- old/python-cstruct-5.0/README.md 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/README.md 2022-11-23 12:08:50.000000000 +0100 @@ -36,6 +36,7 @@ * [Read the DOS-type (MBR) partition table](https://python-cstruct.readthedocs.io/en/latest/examples/fdisk/) * [Print information about logged uses](https://python-cstruct.readthedocs.io/en/latest/examples/who/) * [Flexible Array Member (FAM)](https://python-cstruct.readthedocs.io/en/latest/examples/flexible_array/) +* [libc integration (using ctypes)](https://python-cstruct.readthedocs.io/en/latest/examples/dir/) Features @@ -129,6 +130,8 @@ enum Type_A a; // externally defined using CEnum enum Type_B {A, B, C} b; enum {A, B, C} c; +enum Type_D : short {A, B, C} d; // specify the underlying type +enum Direction { left = 'l', right = 'r' }; ``` ### Nested structs/unions @@ -334,3 +337,6 @@ 000001f0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 aa |..............U.| ``` +Links +----- +* [C/C++ reference](https://en.cppreference.com/) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/changelog.txt new/python-cstruct-5.2/changelog.txt --- old/python-cstruct-5.0/changelog.txt 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/changelog.txt 2022-11-23 12:08:50.000000000 +0100 @@ -190,3 +190,27 @@ - Documentation and examples - Restructure setup + +## 5.1 + +2022-11-20 + +### Improved + +- Support unpack from ctype pointers + +### Added + +- Add support for char constants +- Add native type test +- dir.py example + +## 5.2 + +2022-11-23 + +### Fix + +- nested struct unpack fix +- nested anonymous union offset fix +- inspect offset for nested struct/union fix diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/cstruct/__init__.py new/python-cstruct-5.2/cstruct/__init__.py --- old/python-cstruct-5.0/cstruct/__init__.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/cstruct/__init__.py 2022-11-23 12:08:50.000000000 +0100 @@ -24,7 +24,7 @@ __author__ = "Andrea Bonomi <andrea.bon...@gmail.com>" __license__ = "MIT" -__version__ = "5.0" +__version__ = "5.2" __date__ = "15 August 2013" from typing import Any, Dict, Optional, Type, Union diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/cstruct/abstract.py new/python-cstruct-5.2/cstruct/abstract.py --- old/python-cstruct-5.0/cstruct/abstract.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/cstruct/abstract.py 2022-11-23 12:08:50.000000000 +0100 @@ -238,18 +238,25 @@ """ buffer = StringIO() if hasattr(self, "__mem__"): - mem = self.__mem__ + mem = self.__mem__[self.__base__ :] else: mem = self.pack() - for i in range(start_addr or 0, end_addr or self.size, 16): - row = mem[i : i + 16] + if end_addr is None: + end_addr = self.size + for i in range(start_addr or 0, end_addr, 16): + row = mem[i : min(i + 16, end_addr)] buffer.write(f"{i:08x} ") for j, c in enumerate(row): separator = " " if j == 7 else "" buffer.write(f" {c:02x}{separator}") + for j in range(len(row) - 1, 15): + separator = " " if j == 7 else "" + buffer.write(f" {separator}") buffer.write(" |") for c in row: buffer.write(chr(c) if c >= 32 and c < 127 else ".") + for j in range(len(row) - 1, 15): + buffer.write(" ") buffer.write("|") buffer.write("\n") buffer.seek(0, 0) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/cstruct/c_expr.py new/python-cstruct-5.2/cstruct/c_expr.py --- old/python-cstruct-5.0/cstruct/c_expr.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/cstruct/c_expr.py 2022-11-23 12:08:50.000000000 +0100 @@ -58,6 +58,8 @@ try: expr = expr.replace("!", " not ").replace("&&", " and ").replace("||", " or ") return eval_node(ast.parse(expr.strip()).body[0]) + except EvalError: + raise except Exception: raise EvalError @@ -67,6 +69,11 @@ result = handler(node) if isinstance(result, bool): # convert bool to int return 1 if result else 0 + elif isinstance(result, str): # convert char to int + if len(result) != 1: + raise EvalError("Multi-character constant") + else: + return ord(result) return result @@ -119,6 +126,7 @@ ast.Name: eval_get, ast.Call: eval_call, Constant: lambda node: node.value, + ast.Str: lambda node: node.s, # python < 3.8 # and/or ast.BoolOp: lambda node: OPS[type(node.op)](node), # and/or operator ast.And: lambda node: all(eval_node(x) for x in node.values), # && operator diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/cstruct/c_parser.py new/python-cstruct-5.2/cstruct/c_parser.py --- old/python-cstruct-5.0/cstruct/c_parser.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/cstruct/c_parser.py 2022-11-23 12:08:50.000000000 +0100 @@ -426,6 +426,10 @@ for nested_field_name, nested_field_type in field_type.ref.__fields_types__.items(): if nested_field_name in fields_types: raise ParserError(f"Duplicate member `{nested_field_name}`") + # set the corret offset + nested_field_type = nested_field_type.copy() + nested_field_type.base_offset = offset + nested_field_type.base_offset + nested_field_type.offset = offset + nested_field_type.offset fields_types[nested_field_name] = nested_field_type vname = f"__anonymous{anonymous}" anonymous += 1 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/cstruct/mem_cstruct.py new/python-cstruct-5.2/cstruct/mem_cstruct.py --- old/python-cstruct-5.0/cstruct/mem_cstruct.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/cstruct/mem_cstruct.py 2022-11-23 12:08:50.000000000 +0100 @@ -56,6 +56,7 @@ """ __mem__ = None + __base__ = 0 def unpack_from(self, buffer: Optional[bytes], offset: int = 0, flexible_array_length: Optional[int] = None) -> bool: """ @@ -73,6 +74,9 @@ self.__mem__ = ctypes.create_string_buffer(self.size + 1) elif isinstance(buffer, ctypes.Array): self.__mem__ = buffer + elif isinstance(buffer, int): + # buffer is a pointer + self.__mem__ = ctypes.cast(buffer, ctypes.POINTER(ctypes.c_char * self.size)).contents else: self.__mem__ = ctypes.create_string_buffer(buffer) for field, field_type in self.__fields_types__.items(): @@ -98,7 +102,7 @@ Returns: bytes: The packed structure """ - return self.__mem__.raw[:-1] # the buffer is one item larger than its size and the last element is NUL + return self.__mem__.raw[self.__base__ : self.__base__ + self.size] def set_flexible_array_length(self, flexible_array_length: Optional[int]) -> None: """ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/docs/examples/dir.md new/python-cstruct-5.2/docs/examples/dir.md --- old/python-cstruct-5.0/docs/examples/dir.md 1970-01-01 01:00:00.000000000 +0100 +++ new/python-cstruct-5.2/docs/examples/dir.md 2022-11-23 12:08:50.000000000 +0100 @@ -0,0 +1,6 @@ +The following program prints the names of the files in a directory, +calling the libc functions `getcwd`, `opendir`, `readdir`, and `closedir`: + +``` +{!examples/dir.py!} +``` diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/examples/dir.c new/python-cstruct-5.2/examples/dir.c --- old/python-cstruct-5.0/examples/dir.c 1970-01-01 01:00:00.000000000 +0100 +++ new/python-cstruct-5.2/examples/dir.c 2022-11-23 12:08:50.000000000 +0100 @@ -0,0 +1,22 @@ +/* https://www.gnu.org/software/libc/manual/html_mono/libc.html#Simple-Directory-Lister */ + +#include <stdio.h> +#include <sys/types.h> +#include <dirent.h> + +int main (void) { + DIR *dp; + struct dirent *ep; + + dp = opendir("."); + if (dp != NULL) { + while (ep = readdir (dp)) { + puts(ep->d_name); + } + closedir(dp); + } else { + perror("Couldn't open the directory"); + } + + return 0; +} diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/examples/dir.py new/python-cstruct-5.2/examples/dir.py --- old/python-cstruct-5.0/examples/dir.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-cstruct-5.2/examples/dir.py 2022-11-23 12:08:50.000000000 +0100 @@ -0,0 +1,94 @@ +#!/usr/bin/env python +import cstruct +import ctypes +import sys + +libc = ctypes.cdll.LoadLibrary("libc.so.6") +# opendir +libc.opendir.argtypes = [ctypes.c_char_p] +libc.opendir.restype = ctypes.c_void_p +# readdir +libc.readdir.argtypes = [ctypes.c_void_p] +libc.readdir.restype = ctypes.c_void_p +# closedir +libc.closedir.argtypes = [ctypes.c_void_p] +libc.closedir.restype = ctypes.c_int + + +class DType(cstruct.CEnum): + __size__ = 1 + __def__ = """ + enum d_type { + DT_UNKNOWN = 0x0, + DT_FIFO = 0x1, + DT_CHR = 0x2, + DT_DIR = 0x4, + DT_BLK = 0x6, + DT_REG = 0x8, + DT_LNK = 0xa, + DT_SOCK = 0xc + }; + """ + + def __str__(self): + return { + DType.DT_UNKNOWN: "<unknown>", + DType.DT_FIFO: "<fifo>", + DType.DT_CHR: "<char>", + DType.DT_DIR: "<dir>", + DType.DT_BLK: "<block>", + DType.DT_REG: "<regular>", + DType.DT_LNK: "<link>", + DType.DT_SOCK: "<socket>", + }[self] + + +class Dirent(cstruct.MemCStruct): + __def__ = """ + #define PATH_MAX 4096 + + typedef long ino_t; + typedef long off_t; + + struct dirent { + ino_t d_ino; /* Inode number */ + off_t d_off; /* Not an offset */ + unsigned short d_reclen; /* Length of this record */ + unsigned char d_type; /* Type of file; not supported + by all filesystem types */ + char d_name[256]; /* Null-terminated filename */ + }; + """ + + @property + def name(self): + return ctypes.c_char_p(self.d_name).value.decode("ascii") + + @property + def type(self): + return DType(self.d_type) + + +def main(): + if len(sys.argv) > 1: + cwd = ctypes.create_string_buffer(sys.argv[1].encode("ascii")) + else: + # Get current dir + cwd = ctypes.create_string_buffer(cstruct.getdef("PATH_MAX") + 1) + assert libc.getcwd(cwd, ctypes.sizeof(cwd)) != 0 + # Open dir + dp = libc.opendir(cwd) + assert dp != 0 + # Read dir entries + ep = libc.readdir(dp) + while ep: + contents = ctypes.cast(ep, ctypes.POINTER(ctypes.c_char * Dirent.size)).contents + dirent = Dirent(contents) + print(f"{dirent.d_ino:8} {dirent.type:10} {dirent.name}") + ep = libc.readdir(dp) + # Close dir + libc.closedir(dp) + + +if __name__ == "__main__": + main() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/examples/dir.sh new/python-cstruct-5.2/examples/dir.sh --- old/python-cstruct-5.0/examples/dir.sh 1970-01-01 01:00:00.000000000 +0100 +++ new/python-cstruct-5.2/examples/dir.sh 2022-11-23 12:08:50.000000000 +0100 @@ -0,0 +1,3 @@ +#!/usr/bin/env sh +cd "$(dirname "$0")/.." || exit +python -m examples.dir $* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/mkdocs.yml new/python-cstruct-5.2/mkdocs.yml --- old/python-cstruct-5.0/mkdocs.yml 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/mkdocs.yml 2022-11-23 12:08:50.000000000 +0100 @@ -20,6 +20,7 @@ - Code of Conduct: CODE_OF_CONDUCT.md - Source Code Repository: "https://github.com/andreax79/python-cstruct" - Examples: + - "dir.py": examples/dir.md - "fdisk.py": examples/fdisk.md - "flexible_array.py": examples/flexible_array.md - "who.py": examples/who.md diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/tests/test_c_expr.py new/python-cstruct-5.2/tests/test_c_expr.py --- old/python-cstruct-5.0/tests/test_c_expr.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/tests/test_c_expr.py 2022-11-23 12:08:50.000000000 +0100 @@ -78,3 +78,8 @@ assert c_eval("3 <= 30") == 1 define("A10", 10) assert c_eval("((A10 < 6) || (A10>10))") == 0 + + +def test_c_expr_char(): + assert c_eval("'A'") == 65 + assert c_eval("'B'") == 66 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/tests/test_cenum.py new/python-cstruct-5.2/tests/test_cenum.py --- old/python-cstruct-5.0/tests/test_cenum.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/tests/test_cenum.py 2022-11-23 12:08:50.000000000 +0100 @@ -104,3 +104,9 @@ color = cstruct.parse("enum Color : unsigned short { red, green, blue };") assert color.__size__ == 2 assert cstruct.sizeof("enum Color") == 2 + + +def test_char(): + direction = cstruct.parse("enum Direction { left = 'l', right = 'r' };") + assert direction.__size__ == 4 + assert cstruct.sizeof("enum Direction") == 4 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/tests/test_native_types.py new/python-cstruct-5.2/tests/test_native_types.py --- old/python-cstruct-5.0/tests/test_native_types.py 1970-01-01 01:00:00.000000000 +0100 +++ new/python-cstruct-5.2/tests/test_native_types.py 2022-11-23 12:08:50.000000000 +0100 @@ -0,0 +1,59 @@ +#!/usr/bin/env python +# ***************************************************************************** +# +# Copyright (c) 2013-2019 Andrea Bonomi <andrea.bon...@gmail.com> +# +# Published under the terms of the MIT license. +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to +# deal in the Software without restriction, including without limitation the +# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or +# sell copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS +# IN THE SOFTWARE. +# +# ***************************************************************************** + +from cstruct import MemCStruct, sizeof +from cstruct.base import TYPEDEFS +from cstruct.native_types import AbstractNativeType + + +class SizeT(AbstractNativeType): + type_name = "size_t" + native_format = "Q" + + +class StructWithSizeT(MemCStruct): + __def__ = """ + typedef size_t size; + typedef unsigned long long ull; + + struct StructWithSizeT { + ull a; + size_t b; + size c; + } + """ + + +def test_typedef(): + assert TYPEDEFS["size"] == "size_t" + assert TYPEDEFS["ull"] == "unsigned long long" + + +def test_sizeof_custom_native_type(): + assert sizeof("size_t") == 8 + assert sizeof("ull") == 8 + assert sizeof("struct StructWithSizeT") == 8 * 3 diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/python-cstruct-5.0/tests/test_nested.py new/python-cstruct-5.2/tests/test_nested.py --- old/python-cstruct-5.0/tests/test_nested.py 2022-11-12 09:02:29.000000000 +0100 +++ new/python-cstruct-5.2/tests/test_nested.py 2022-11-23 12:08:50.000000000 +0100 @@ -210,3 +210,125 @@ assert o1.format1.field1 == 11 assert o1.format1.field2 == 12 assert o1.format1.field3 == 13 + + +def test_nested_struct_offset(): + cstruct.parse( + """ + struct op_a { + int a; + }; + + struct op_b { + char a; + char b; + char c; + }; + """, + __byte_order__=cstruct.LITTLE_ENDIAN, + ) + + Op = cstruct.parse( + """ + struct op { + char preamble[10]; + uint64_t magic; + union { + struct op_a a_op; + struct op_b b_op; + } u1; + struct op_a aaa; + }; + """, + __byte_order__=cstruct.LITTLE_ENDIAN, + ) + + o = Op() + o.preamble = b'ciao_ciao' + o.magic = 3771778641802345472 + o.u1.a_op.a = 2022 + o.aaa.a = 0x33333333 + assert o.u1.b_op.a == b'\xe6' + assert o.u1.b_op.b == b'\x07' + assert o.u1.b_op.c == b'\x00' + assert o.__base__ == 0 + assert o.u1.__base__ >= 10 + assert o.u1.__base__ == o.u1.a_op.__base__ + assert o.u1.__base__ == o.u1.b_op.__base__ + assert o.aaa.__base__ > o.u1.__base__ + assert o.pack() == b'ciao_ciao\x00\x00\xbc\x08\xe4\xb0\x0cX4\xe6\x07\x00\x003333' + assert o.u1.pack() == b'\xe6\x07\x00\x00' + assert o.aaa.pack() == b'3333' + assert o.u1.a_op.inspect() == "00000000 e6 07 00 00 |.... |\n" + assert o.u1.b_op.inspect() == "00000000 e6 07 00 |... |\n" + + +def test_nested_anonymous_struct_offset(): + cstruct.parse( + """ + struct op_a1 { + int a; + }; + + struct op_b1 { + char a; + char b; + char c; + }; + """, + __byte_order__=cstruct.LITTLE_ENDIAN, + ) + + Opu = cstruct.parse( + """ + struct opu { + char preamble[10]; + uint64_t magic; + union { + struct op_a1 a_op; + struct op_b1 b_op; + }; + struct op_a aaa; + }; + """, + __byte_order__=cstruct.LITTLE_ENDIAN, + ) + + o = Opu() + o.preamble = b'ciao_ciao' + o.magic = 3771778641802345472 + o.__anonymous0.a_op.a = 2022 + o.aaa.a = 0x33333333 + assert o.__anonymous0.b_op.a == b'\xe6' + assert o.__anonymous0.b_op.b == b'\x07' + assert o.__anonymous0.b_op.c == b'\x00' + assert o.__base__ == 0 + assert o.__anonymous0.__base__ >= 10 + assert o.__anonymous0.__base__ == o.__anonymous0.a_op.__base__ + assert o.__anonymous0.__base__ == o.__anonymous0.b_op.__base__ + assert o.aaa.__base__ > o.__anonymous0.__base__ + assert o.pack() == b'ciao_ciao\x00\x00\xbc\x08\xe4\xb0\x0cX4\xe6\x07\x00\x003333' + assert o.__anonymous0.pack() == b'\xe6\x07\x00\x00' + assert o.aaa.pack() == b'3333' + assert o.__anonymous0.inspect() == "00000000 e6 07 00 00 |.... |\n" + assert o.__anonymous0.a_op.inspect() == "00000000 e6 07 00 00 |.... |\n" + assert o.__anonymous0.b_op.inspect() == "00000000 e6 07 00 |... |\n" + + o = Opu() + o.preamble = b'ciao_ciao' + o.magic = 3771778641802345472 + o.a_op.a = 2022 + o.aaa.a = 0x33333333 + assert o.b_op.a == b'\xe6' + assert o.b_op.b == b'\x07' + assert o.b_op.c == b'\x00' + assert o.__base__ == 0 + assert o.__anonymous0.__base__ >= 10 + assert o.__anonymous0.__base__ == o.a_op.__base__ + assert o.__anonymous0.__base__ == o.b_op.__base__ + assert o.aaa.__base__ > o.__base__ + assert o.pack() == b'ciao_ciao\x00\x00\xbc\x08\xe4\xb0\x0cX4\xe6\x07\x00\x003333' + assert o.a_op.pack() == b'\xe6\x07\x00\x00' + assert o.aaa.pack() == b'3333' + assert o.a_op.inspect() == "00000000 e6 07 00 00 |.... |\n" + assert o.b_op.inspect() == "00000000 e6 07 00 |... |\n"