Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-kaitaistruct for 
openSUSE:Factory checked in at 2022-12-19 14:07:55
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-kaitaistruct (Old)
 and      /work/SRC/openSUSE:Factory/.python-kaitaistruct.new.1835 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-kaitaistruct"

Mon Dec 19 14:07:55 2022 rev:5 rq:1043186 version:0.10

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-kaitaistruct/python-kaitaistruct.changes  
2020-10-20 16:17:17.154205139 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-kaitaistruct.new.1835/python-kaitaistruct.changes
        2022-12-19 14:07:56.810565691 +0100
@@ -1,0 +2,5 @@
+Thu Dec 15 16:59:33 UTC 2022 - Daniel Garcia <daniel.gar...@suse.com>
+
+- Update to version 0.10 (no changelog supplied)
+
+-------------------------------------------------------------------

Old:
----
  kaitaistruct-0.9.tar.gz

New:
----
  kaitaistruct-0.10.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-kaitaistruct.spec ++++++
--- /var/tmp/diff_new_pack.HSjUw3/_old  2022-12-19 14:07:57.330568385 +0100
+++ /var/tmp/diff_new_pack.HSjUw3/_new  2022-12-19 14:07:57.338568427 +0100
@@ -1,7 +1,7 @@
 #
 # spec file for package python-kaitaistruct
 #
-# Copyright (c) 2020 SUSE LLC
+# Copyright (c) 2022 SUSE LLC
 #
 # All modifications and additions to the file contributed by third parties
 # remain the property of their copyright owners, unless otherwise agreed
@@ -16,15 +16,16 @@
 #
 
 
-%{?!python_module:%define python_module() python-%{**} python3-%{**}}
 Name:           python-kaitaistruct
-Version:        0.9
+Version:        0.10
 Release:        0
 Summary:        Python library for kaitaistruct
 License:        MIT
 URL:            https://kaitai.io
 Source:         
https://files.pythonhosted.org/packages/source/k/kaitaistruct/kaitaistruct-%{version}.tar.gz
+BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module setuptools}
+BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
 BuildArch:      noarch
@@ -44,19 +45,20 @@
 
 %prep
 %setup -q -n kaitaistruct-%{version}
-rm -rf kaitaistruct.egg-info
 
 %build
-%python_build
+%pyproject_wheel
 
 %install
-%python_install
+%pyproject_install
 %python_expand %fdupes %{buildroot}%{$python_sitelib}
 
 %files %{python_files}
-%doc README.rst
+%defattr(0644,root,root,-)
+%doc README.md
+%license LICENSE
 %pycache_only %{python_sitelib}/__pycache__
 %{python_sitelib}/kaitaistruct.py*
-%{python_sitelib}/kaitaistruct-%{version}-py%{python_version}.egg-info
+%{python_sitelib}/kaitaistruct-%{version}*-info
 
 %changelog

++++++ kaitaistruct-0.9.tar.gz -> kaitaistruct-0.10.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/LICENSE 
new/kaitaistruct-0.10/LICENSE
--- old/kaitaistruct-0.9/LICENSE        1970-01-01 01:00:00.000000000 +0100
+++ new/kaitaistruct-0.10/LICENSE       2022-04-15 22:10:15.000000000 +0200
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2015-2022 Kaitai Project
+
+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.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/MANIFEST.in 
new/kaitaistruct-0.10/MANIFEST.in
--- old/kaitaistruct-0.9/MANIFEST.in    2019-10-19 20:07:48.000000000 +0200
+++ new/kaitaistruct-0.10/MANIFEST.in   1970-01-01 01:00:00.000000000 +0100
@@ -1 +0,0 @@
-include README.rst
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/PKG-INFO 
new/kaitaistruct-0.10/PKG-INFO
--- old/kaitaistruct-0.9/PKG-INFO       2020-10-16 01:34:07.574351800 +0200
+++ new/kaitaistruct-0.10/PKG-INFO      2022-07-09 02:26:54.262237000 +0200
@@ -1,44 +1,50 @@
-Metadata-Version: 1.2
-Name: kaitaistruct
-Version: 0.9
-Summary: Kaitai Struct declarative parser generator for binary data: runtime 
library for Python
-Home-page: http://kaitai.io
-Author: Kaitai Project
-Author-email: grey...@kaitai.io
-License: MIT
-Description: Kaitai Struct: runtime library for Python
-        ===========================================
-        
-        This library implements Kaitai Struct API for Python.
-        
-        `Kaitai Struct <http://kaitai.io>`_ is a declarative language used for
-        describe various binary data structures, laid out in files or in 
memory:
-        i.e. binary file formats, network stream packet formats, etc.
-        
-        It is similar to `Python's Construct 2.9 
<http://construct.readthedocs.org/>`_ but it is
-        language-agnostic. The format description is done in YAML-based .ksy
-        format, which then can be compiled into a wide range of target 
languages.
-        
-        Further reading:
-        
-        * `About Kaitai Struct <http://kaitai.io/>`_
-        * `About API implemented in this library 
<http://doc.kaitai.io/stream_api.html>`_
-        * `Python-specific notes <http://doc.kaitai.io/lang_python.html>`_ in 
KS
-          documentation discuss installation and usage of this runtime
-        
-Keywords: kaitai,struct,construct,ksy,declarative,data structure,data 
format,file format,packet format,binary,parser,parsing,unpack,development
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: Topic :: Software Development :: Build Tools
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: Implementation :: CPython
-Classifier: Programming Language :: Python :: Implementation :: PyPy
-Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
+Metadata-Version: 2.1
+Name: kaitaistruct
+Version: 0.10
+Summary: Kaitai Struct declarative parser generator for binary data: runtime 
library for Python
+Home-page: https://kaitai.io
+Author: Kaitai Project
+Author-email: grey...@kaitai.io
+License: MIT
+Keywords: kaitai,struct,construct,ksy,declarative,data structure,data 
format,file format,packet format,binary,parser,parsing,unpack,development
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: Topic :: Software Development :: Build Tools
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7
+Description-Content-Type: text/markdown
+License-File: LICENSE
+
+# Kaitai Struct: runtime library for Python
+
+[![PyPI](https://img.shields.io/pypi/v/kaitaistruct)](https://pypi.org/project/kaitaistruct/)
+[![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/kaitaistruct)](https://pypi.org/project/kaitaistruct/#:~:text=Programming%20Language)
+
+This library implements Kaitai Struct API for Python.
+
+[Kaitai Struct](https://kaitai.io/) is a declarative language used for
+describe various binary data structures, laid out in files or in memory:
+i.e. binary file formats, network stream packet formats, etc.
+
+It is similar to [Python's Construct 
2.10](https://construct.readthedocs.io/en/latest/)
+but it is language-agnostic. The format description is done in YAML-based .ksy
+format, which then can be compiled into a wide range of target languages.
+
+Further reading:
+
+* [About Kaitai Struct](https://kaitai.io/)
+* [About API implemented in this 
library](https://doc.kaitai.io/stream_api.html)
+* [Python-specific notes](https://doc.kaitai.io/lang_python.html) in KS
+  documentation discuss installation and usage of this runtime
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/README.md 
new/kaitaistruct-0.10/README.md
--- old/kaitaistruct-0.9/README.md      1970-01-01 01:00:00.000000000 +0100
+++ new/kaitaistruct-0.10/README.md     2022-04-15 10:32:27.000000000 +0200
@@ -0,0 +1,21 @@
+# Kaitai Struct: runtime library for Python
+
+[![PyPI](https://img.shields.io/pypi/v/kaitaistruct)](https://pypi.org/project/kaitaistruct/)
+[![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/kaitaistruct)](https://pypi.org/project/kaitaistruct/#:~:text=Programming%20Language)
+
+This library implements Kaitai Struct API for Python.
+
+[Kaitai Struct](https://kaitai.io/) is a declarative language used for
+describe various binary data structures, laid out in files or in memory:
+i.e. binary file formats, network stream packet formats, etc.
+
+It is similar to [Python's Construct 
2.10](https://construct.readthedocs.io/en/latest/)
+but it is language-agnostic. The format description is done in YAML-based .ksy
+format, which then can be compiled into a wide range of target languages.
+
+Further reading:
+
+* [About Kaitai Struct](https://kaitai.io/)
+* [About API implemented in this 
library](https://doc.kaitai.io/stream_api.html)
+* [Python-specific notes](https://doc.kaitai.io/lang_python.html) in KS
+  documentation discuss installation and usage of this runtime
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/README.rst 
new/kaitaistruct-0.10/README.rst
--- old/kaitaistruct-0.9/README.rst     2020-02-14 19:12:41.000000000 +0100
+++ new/kaitaistruct-0.10/README.rst    1970-01-01 01:00:00.000000000 +0100
@@ -1,19 +0,0 @@
-Kaitai Struct: runtime library for Python
-===========================================
-
-This library implements Kaitai Struct API for Python.
-
-`Kaitai Struct <http://kaitai.io>`_ is a declarative language used for
-describe various binary data structures, laid out in files or in memory:
-i.e. binary file formats, network stream packet formats, etc.
-
-It is similar to `Python's Construct 2.9 <http://construct.readthedocs.org/>`_ 
but it is
-language-agnostic. The format description is done in YAML-based .ksy
-format, which then can be compiled into a wide range of target languages.
-
-Further reading:
-
-* `About Kaitai Struct <http://kaitai.io/>`_
-* `About API implemented in this library 
<http://doc.kaitai.io/stream_api.html>`_
-* `Python-specific notes <http://doc.kaitai.io/lang_python.html>`_ in KS
-  documentation discuss installation and usage of this runtime
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/kaitaistruct.egg-info/PKG-INFO 
new/kaitaistruct-0.10/kaitaistruct.egg-info/PKG-INFO
--- old/kaitaistruct-0.9/kaitaistruct.egg-info/PKG-INFO 2020-10-16 
01:34:07.000000000 +0200
+++ new/kaitaistruct-0.10/kaitaistruct.egg-info/PKG-INFO        2022-07-09 
02:26:53.000000000 +0200
@@ -1,44 +1,50 @@
-Metadata-Version: 1.2
-Name: kaitaistruct
-Version: 0.9
-Summary: Kaitai Struct declarative parser generator for binary data: runtime 
library for Python
-Home-page: http://kaitai.io
-Author: Kaitai Project
-Author-email: grey...@kaitai.io
-License: MIT
-Description: Kaitai Struct: runtime library for Python
-        ===========================================
-        
-        This library implements Kaitai Struct API for Python.
-        
-        `Kaitai Struct <http://kaitai.io>`_ is a declarative language used for
-        describe various binary data structures, laid out in files or in 
memory:
-        i.e. binary file formats, network stream packet formats, etc.
-        
-        It is similar to `Python's Construct 2.9 
<http://construct.readthedocs.org/>`_ but it is
-        language-agnostic. The format description is done in YAML-based .ksy
-        format, which then can be compiled into a wide range of target 
languages.
-        
-        Further reading:
-        
-        * `About Kaitai Struct <http://kaitai.io/>`_
-        * `About API implemented in this library 
<http://doc.kaitai.io/stream_api.html>`_
-        * `Python-specific notes <http://doc.kaitai.io/lang_python.html>`_ in 
KS
-          documentation discuss installation and usage of this runtime
-        
-Keywords: kaitai,struct,construct,ksy,declarative,data structure,data 
format,file format,packet format,binary,parser,parsing,unpack,development
-Platform: UNKNOWN
-Classifier: Development Status :: 4 - Beta
-Classifier: Intended Audience :: Developers
-Classifier: Topic :: Software Development :: Build Tools
-Classifier: License :: OSI Approved :: MIT License
-Classifier: Programming Language :: Python :: 2
-Classifier: Programming Language :: Python :: 2.7
-Classifier: Programming Language :: Python :: 3
-Classifier: Programming Language :: Python :: 3.4
-Classifier: Programming Language :: Python :: 3.5
-Classifier: Programming Language :: Python :: 3.6
-Classifier: Programming Language :: Python :: 3.7
-Classifier: Programming Language :: Python :: Implementation :: CPython
-Classifier: Programming Language :: Python :: Implementation :: PyPy
-Requires-Python: >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
+Metadata-Version: 2.1
+Name: kaitaistruct
+Version: 0.10
+Summary: Kaitai Struct declarative parser generator for binary data: runtime 
library for Python
+Home-page: https://kaitai.io
+Author: Kaitai Project
+Author-email: grey...@kaitai.io
+License: MIT
+Keywords: kaitai,struct,construct,ksy,declarative,data structure,data 
format,file format,packet format,binary,parser,parsing,unpack,development
+Classifier: Development Status :: 4 - Beta
+Classifier: Intended Audience :: Developers
+Classifier: Topic :: Software Development :: Build Tools
+Classifier: License :: OSI Approved :: MIT License
+Classifier: Programming Language :: Python :: 2
+Classifier: Programming Language :: Python :: 2.7
+Classifier: Programming Language :: Python :: 3
+Classifier: Programming Language :: Python :: 3.4
+Classifier: Programming Language :: Python :: 3.5
+Classifier: Programming Language :: Python :: 3.6
+Classifier: Programming Language :: Python :: 3.7
+Classifier: Programming Language :: Python :: 3.8
+Classifier: Programming Language :: Python :: 3.9
+Classifier: Programming Language :: Python :: 3.10
+Classifier: Programming Language :: Python :: Implementation :: CPython
+Classifier: Programming Language :: Python :: Implementation :: PyPy
+Requires-Python: !=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,>=2.7
+Description-Content-Type: text/markdown
+License-File: LICENSE
+
+# Kaitai Struct: runtime library for Python
+
+[![PyPI](https://img.shields.io/pypi/v/kaitaistruct)](https://pypi.org/project/kaitaistruct/)
+[![PyPI - Python 
Version](https://img.shields.io/pypi/pyversions/kaitaistruct)](https://pypi.org/project/kaitaistruct/#:~:text=Programming%20Language)
+
+This library implements Kaitai Struct API for Python.
+
+[Kaitai Struct](https://kaitai.io/) is a declarative language used for
+describe various binary data structures, laid out in files or in memory:
+i.e. binary file formats, network stream packet formats, etc.
+
+It is similar to [Python's Construct 
2.10](https://construct.readthedocs.io/en/latest/)
+but it is language-agnostic. The format description is done in YAML-based .ksy
+format, which then can be compiled into a wide range of target languages.
+
+Further reading:
+
+* [About Kaitai Struct](https://kaitai.io/)
+* [About API implemented in this 
library](https://doc.kaitai.io/stream_api.html)
+* [Python-specific notes](https://doc.kaitai.io/lang_python.html) in KS
+  documentation discuss installation and usage of this runtime
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/kaitaistruct.egg-info/SOURCES.txt 
new/kaitaistruct-0.10/kaitaistruct.egg-info/SOURCES.txt
--- old/kaitaistruct-0.9/kaitaistruct.egg-info/SOURCES.txt      2020-10-16 
01:34:07.000000000 +0200
+++ new/kaitaistruct-0.10/kaitaistruct.egg-info/SOURCES.txt     2022-07-09 
02:26:54.000000000 +0200
@@ -1,10 +1,12 @@
-MANIFEST.in
-README.rst
+LICENSE
+README.md
 kaitaistruct.py
+pyproject.toml
 setup.cfg
 setup.py
 kaitaistruct.egg-info/PKG-INFO
 kaitaistruct.egg-info/SOURCES.txt
 kaitaistruct.egg-info/dependency_links.txt
+kaitaistruct.egg-info/requires.txt
 kaitaistruct.egg-info/top_level.txt
 kaitaistruct.egg-info/zip-safe
\ No newline at end of file
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/kaitaistruct.egg-info/requires.txt 
new/kaitaistruct-0.10/kaitaistruct.egg-info/requires.txt
--- old/kaitaistruct-0.9/kaitaistruct.egg-info/requires.txt     1970-01-01 
01:00:00.000000000 +0100
+++ new/kaitaistruct-0.10/kaitaistruct.egg-info/requires.txt    2022-07-09 
02:26:54.000000000 +0200
@@ -0,0 +1,3 @@
+
+[:python_version < "3.4"]
+enum34
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/kaitaistruct.egg-info/zip-safe 
new/kaitaistruct-0.10/kaitaistruct.egg-info/zip-safe
--- old/kaitaistruct-0.9/kaitaistruct.egg-info/zip-safe 2020-10-16 
00:59:29.000000000 +0200
+++ new/kaitaistruct-0.10/kaitaistruct.egg-info/zip-safe        2022-07-09 
02:26:53.000000000 +0200
@@ -1 +1 @@
-
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/kaitaistruct.py 
new/kaitaistruct-0.10/kaitaistruct.py
--- old/kaitaistruct-0.9/kaitaistruct.py        2020-05-22 00:11:16.000000000 
+0200
+++ new/kaitaistruct-0.10/kaitaistruct.py       2022-07-07 12:16:50.000000000 
+0200
@@ -1,498 +1,521 @@
-import itertools
-import sys
-import struct
-from io import open, BytesIO, SEEK_CUR, SEEK_END  # noqa
-
-PY2 = sys.version_info[0] == 2
-
-# Kaitai Struct runtime streaming API version, defined as per PEP-0396
-# standard. Used for two purposes:
-#
-# * .py files generated by ksc from .ksy check that they import proper
-#   KS runtime library by this version number;
-# * distribution utils (setup.py) use this when packaging for PyPI
-#
-__version__ = '0.9'
-
-
-class KaitaiStruct(object):
-    def __init__(self, stream):
-        self._io = stream
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, *args, **kwargs):
-        self.close()
-
-    def close(self):
-        self._io.close()
-
-    @classmethod
-    def from_file(cls, filename):
-        f = open(filename, 'rb')
-        try:
-            return cls(KaitaiStream(f))
-        except Exception:
-            # close file descriptor, then reraise the exception
-            f.close()
-            raise
-
-    @classmethod
-    def from_bytes(cls, buf):
-        return cls(KaitaiStream(BytesIO(buf)))
-
-    @classmethod
-    def from_io(cls, io):
-        return cls(KaitaiStream(io))
-
-
-class KaitaiStream(object):
-    def __init__(self, io):
-        self._io = io
-        self.align_to_byte()
-
-    def __enter__(self):
-        return self
-
-    def __exit__(self, *args, **kwargs):
-        self.close()
-
-    def close(self):
-        self._io.close()
-
-    # ========================================================================
-    # Stream positioning
-    # ========================================================================
-
-    def is_eof(self):
-        if self.bits_left > 0:
-            return False
-
-        io = self._io
-        t = io.read(1)
-        if t == b'':
-            return True
-        else:
-            io.seek(-1, SEEK_CUR)
-            return False
-
-    def seek(self, n):
-        self._io.seek(n)
-
-    def pos(self):
-        return self._io.tell()
-
-    def size(self):
-        # Python has no internal File object API function to get
-        # current file / StringIO size, thus we use the following
-        # trick.
-        io = self._io
-        # Remember our current position
-        cur_pos = io.tell()
-        # Seek to the end of the File object
-        io.seek(0, SEEK_END)
-        # Remember position, which is equal to the full length
-        full_size = io.tell()
-        # Seek back to the current position
-        io.seek(cur_pos)
-        return full_size
-
-    # ========================================================================
-    # Integer numbers
-    # ========================================================================
-
-    packer_s1 = struct.Struct('b')
-    packer_s2be = struct.Struct('>h')
-    packer_s4be = struct.Struct('>i')
-    packer_s8be = struct.Struct('>q')
-    packer_s2le = struct.Struct('<h')
-    packer_s4le = struct.Struct('<i')
-    packer_s8le = struct.Struct('<q')
-
-    packer_u1 = struct.Struct('B')
-    packer_u2be = struct.Struct('>H')
-    packer_u4be = struct.Struct('>I')
-    packer_u8be = struct.Struct('>Q')
-    packer_u2le = struct.Struct('<H')
-    packer_u4le = struct.Struct('<I')
-    packer_u8le = struct.Struct('<Q')
-
-    # ------------------------------------------------------------------------
-    # Signed
-    # ------------------------------------------------------------------------
-
-    def read_s1(self):
-        return KaitaiStream.packer_s1.unpack(self.read_bytes(1))[0]
-
-    # ........................................................................
-    # Big-endian
-    # ........................................................................
-
-    def read_s2be(self):
-        return KaitaiStream.packer_s2be.unpack(self.read_bytes(2))[0]
-
-    def read_s4be(self):
-        return KaitaiStream.packer_s4be.unpack(self.read_bytes(4))[0]
-
-    def read_s8be(self):
-        return KaitaiStream.packer_s8be.unpack(self.read_bytes(8))[0]
-
-    # ........................................................................
-    # Little-endian
-    # ........................................................................
-
-    def read_s2le(self):
-        return KaitaiStream.packer_s2le.unpack(self.read_bytes(2))[0]
-
-    def read_s4le(self):
-        return KaitaiStream.packer_s4le.unpack(self.read_bytes(4))[0]
-
-    def read_s8le(self):
-        return KaitaiStream.packer_s8le.unpack(self.read_bytes(8))[0]
-
-    # ------------------------------------------------------------------------
-    # Unsigned
-    # ------------------------------------------------------------------------
-
-    def read_u1(self):
-        return KaitaiStream.packer_u1.unpack(self.read_bytes(1))[0]
-
-    # ........................................................................
-    # Big-endian
-    # ........................................................................
-
-    def read_u2be(self):
-        return KaitaiStream.packer_u2be.unpack(self.read_bytes(2))[0]
-
-    def read_u4be(self):
-        return KaitaiStream.packer_u4be.unpack(self.read_bytes(4))[0]
-
-    def read_u8be(self):
-        return KaitaiStream.packer_u8be.unpack(self.read_bytes(8))[0]
-
-    # ........................................................................
-    # Little-endian
-    # ........................................................................
-
-    def read_u2le(self):
-        return KaitaiStream.packer_u2le.unpack(self.read_bytes(2))[0]
-
-    def read_u4le(self):
-        return KaitaiStream.packer_u4le.unpack(self.read_bytes(4))[0]
-
-    def read_u8le(self):
-        return KaitaiStream.packer_u8le.unpack(self.read_bytes(8))[0]
-
-    # ========================================================================
-    # Floating point numbers
-    # ========================================================================
-
-    packer_f4be = struct.Struct('>f')
-    packer_f8be = struct.Struct('>d')
-    packer_f4le = struct.Struct('<f')
-    packer_f8le = struct.Struct('<d')
-
-    # ........................................................................
-    # Big-endian
-    # ........................................................................
-
-    def read_f4be(self):
-        return KaitaiStream.packer_f4be.unpack(self.read_bytes(4))[0]
-
-    def read_f8be(self):
-        return KaitaiStream.packer_f8be.unpack(self.read_bytes(8))[0]
-
-    # ........................................................................
-    # Little-endian
-    # ........................................................................
-
-    def read_f4le(self):
-        return KaitaiStream.packer_f4le.unpack(self.read_bytes(4))[0]
-
-    def read_f8le(self):
-        return KaitaiStream.packer_f8le.unpack(self.read_bytes(8))[0]
-
-    # ========================================================================
-    # Unaligned bit values
-    # ========================================================================
-
-    def align_to_byte(self):
-        self.bits = 0
-        self.bits_left = 0
-
-    def read_bits_int_be(self, n):
-        bits_needed = n - self.bits_left
-        if bits_needed > 0:
-            # 1 bit  => 1 byte
-            # 8 bits => 1 byte
-            # 9 bits => 2 bytes
-            bytes_needed = ((bits_needed - 1) // 8) + 1
-            buf = self.read_bytes(bytes_needed)
-            for byte in buf:
-                byte = KaitaiStream.int_from_byte(byte)
-                self.bits <<= 8
-                self.bits |= byte
-                self.bits_left += 8
-
-        # raw mask with required number of 1s, starting from lowest bit
-        mask = (1 << n) - 1
-        # shift self.bits to align the highest bits with the mask & derive 
reading result
-        shift_bits = self.bits_left - n
-        res = (self.bits >> shift_bits) & mask
-        # clear top bits that we've just read => AND with 1s
-        self.bits_left -= n
-        mask = (1 << self.bits_left) - 1
-        self.bits &= mask
-
-        return res
-
-    # Unused since Kaitai Struct Compiler v0.9+ - compatibility with
-    # older versions.
-    def read_bits_int(self, n):
-        return self.read_bits_int_be(n)
-
-    def read_bits_int_le(self, n):
-        bits_needed = n - self.bits_left
-        if bits_needed > 0:
-            # 1 bit  => 1 byte
-            # 8 bits => 1 byte
-            # 9 bits => 2 bytes
-            bytes_needed = ((bits_needed - 1) // 8) + 1
-            buf = self.read_bytes(bytes_needed)
-            for byte in buf:
-                byte = KaitaiStream.int_from_byte(byte)
-                self.bits |= (byte << self.bits_left)
-                self.bits_left += 8
-
-        # raw mask with required number of 1s, starting from lowest bit
-        mask = (1 << n) - 1
-        # derive reading result
-        res = self.bits & mask
-        # remove bottom bits that we've just read by shifting
-        self.bits >>= n
-        self.bits_left -= n
-
-        return res
-
-    # ========================================================================
-    # Byte arrays
-    # ========================================================================
-
-    def read_bytes(self, n):
-        if n < 0:
-            raise ValueError(
-                "requested invalid %d amount of bytes" %
-                (n,)
-            )
-        r = self._io.read(n)
-        if len(r) < n:
-            raise EOFError(
-                "requested %d bytes, but got only %d bytes" %
-                (n, len(r))
-            )
-        return r
-
-    def read_bytes_full(self):
-        return self._io.read()
-
-    def read_bytes_term(self, term, include_term, consume_term, eos_error):
-        r = b''
-        while True:
-            c = self._io.read(1)
-            if c == b'':
-                if eos_error:
-                    raise Exception(
-                        "end of stream reached, but no terminator %d found" %
-                        (term,)
-                    )
-                else:
-                    return r
-            elif ord(c) == term:
-                if include_term:
-                    r += c
-                if not consume_term:
-                    self._io.seek(-1, SEEK_CUR)
-                return r
-            else:
-                r += c
-
-    def ensure_fixed_contents(self, expected):
-        actual = self._io.read(len(expected))
-        if actual != expected:
-            raise Exception(
-                "unexpected fixed contents: got %r, was waiting for %r" %
-                (actual, expected)
-            )
-        return actual
-
-    @staticmethod
-    def bytes_strip_right(data, pad_byte):
-        new_len = len(data)
-        if PY2:
-            # data[...] must yield an integer, to compare with integer pad_byte
-            data = bytearray(data)
-
-        while new_len > 0 and data[new_len - 1] == pad_byte:
-            new_len -= 1
-
-        return data[:new_len]
-
-    @staticmethod
-    def bytes_terminate(data, term, include_term):
-        new_len = 0
-        max_len = len(data)
-        if PY2:
-            # data[...] must yield an integer, to compare with integer term
-            data = bytearray(data)
-
-        while new_len < max_len and data[new_len] != term:
-            new_len += 1
-
-        if include_term and new_len < max_len:
-            new_len += 1
-
-        return data[:new_len]
-
-    # ========================================================================
-    # Byte array processing
-    # ========================================================================
-
-    @staticmethod
-    def process_xor_one(data, key):
-        if PY2:
-            return bytes(bytearray(v ^ key for v in bytearray(data)))
-        else:
-            return bytes(v ^ key for v in data)
-
-    @staticmethod
-    def process_xor_many(data, key):
-        if PY2:
-            return bytes(bytearray(a ^ b for a, b in zip(bytearray(data), 
itertools.cycle(bytearray(key)))))
-        else:
-            return bytes(a ^ b for a, b in zip(data, itertools.cycle(key)))
-
-    @staticmethod
-    def process_rotate_left(data, amount, group_size):
-        if group_size != 1:
-            raise Exception(
-                "unable to rotate group of %d bytes yet" %
-                (group_size,)
-            )
-
-        mask = group_size * 8 - 1
-        anti_amount = -amount & mask
-
-        r = bytearray(data)
-        for i in range(len(r)):
-            r[i] = (r[i] << amount) & 0xff | (r[i] >> anti_amount)
-        return bytes(r)
-
-    # ========================================================================
-    # Misc
-    # ========================================================================
-
-    @staticmethod
-    def int_from_byte(v):
-        if PY2:
-            return ord(v)
-        return v
-
-    @staticmethod
-    def byte_array_index(data, i):
-        return KaitaiStream.int_from_byte(data[i])
-
-    @staticmethod
-    def byte_array_min(b):
-        return KaitaiStream.int_from_byte(min(b))
-
-    @staticmethod
-    def byte_array_max(b):
-        return KaitaiStream.int_from_byte(max(b))
-
-    @staticmethod
-    def resolve_enum(enum_obj, value):
-        """Resolves value using enum: if the value is not found in the map,
-        we'll just use literal value per se. Works around problem with Python
-        enums throwing an exception when encountering unknown value.
-        """
-        try:
-            return enum_obj(value)
-        except ValueError:
-            return value
-
-
-class KaitaiStructError(BaseException):
-    """Common ancestor for all error originating from Kaitai Struct usage.
-    Stores KSY source path, pointing to an element supposedly guilty of
-    an error.
-    """
-    def __init__(self, msg, src_path):
-        super(KaitaiStructError, self).__init__("%s: %s" % (src_path, msg))
-        self.src_path = src_path
-
-
-class UndecidedEndiannessError(KaitaiStructError):
-    """Error that occurs when default endianness should be decided with
-    switch, but nothing matches (although using endianness expression
-    implies that there should be some positive result).
-    """
-    def __init__(self, src_path):
-        super(KaitaiStructError, self).__init__("unable to decide on 
endianness for a type", src_path)
-
-
-class ValidationFailedError(KaitaiStructError):
-    """Common ancestor for all validation failures. Stores pointer to
-    KaitaiStream IO object which was involved in an error.
-    """
-    def __init__(self, msg, io, src_path):
-        super(ValidationFailedError, self).__init__("at pos %d: validation 
failed: %s" % (io.pos(), msg), src_path)
-        self.io = io
-
-
-class ValidationNotEqualError(ValidationFailedError):
-    """Signals validation failure: we required "actual" value to be equal to
-    "expected", but it turned out that it's not.
-    """
-    def __init__(self, expected, actual, io, src_path):
-        super(ValidationNotEqualError, self).__init__("not equal, expected %s, 
but got %s" % (repr(expected), repr(actual)), io, src_path)
-        self.expected = expected
-        self.actual = actual
-
-
-class ValidationLessThanError(ValidationFailedError):
-    """Signals validation failure: we required "actual" value to be
-    greater than or equal to "min", but it turned out that it's not.
-    """
-    def __init__(self, min, actual, io, src_path):
-        super(ValidationLessThanError, self).__init__("not in range, min %s, 
but got %s" % (repr(min), repr(actual)), io, src_path)
-        self.min = min
-        self.actual = actual
-
-
-class ValidationGreaterThanError(ValidationFailedError):
-    """Signals validation failure: we required "actual" value to be
-    less than or equal to "max", but it turned out that it's not.
-    """
-    def __init__(self, max, actual, io, src_path):
-        super(ValidationGreaterThanError, self).__init__("not in range, max 
%s, but got %s" % (repr(max), repr(actual)), io, src_path)
-        self.max = max
-        self.actual = actual
-
-
-class ValidationNotAnyOfError(ValidationFailedError):
-    """Signals validation failure: we required "actual" value to be
-    from the list, but it turned out that it's not.
-    """
-    def __init__(self, actual, io, src_path):
-        super(ValidationNotAnyOfError, self).__init__("not any of the list, 
got %s" % (repr(actual)), io, src_path)
-        self.actual = actual
-
-
-class ValidationExprError(ValidationFailedError):
-    """Signals validation failure: we required "actual" value to match
-    the expression, but it turned out that it doesn't.
-    """
-    def __init__(self, actual, io, src_path):
-        super(ValidationExprError, self).__init__("not matching the 
expression, got %s" % (repr(actual)), io, src_path)
-        self.actual = actual
+import itertools
+import sys
+import struct
+from io import open, BytesIO, SEEK_CUR, SEEK_END  # noqa
+
+PY2 = sys.version_info[0] == 2
+
+# Kaitai Struct runtime version, in the format defined by PEP 440.
+# Used by our setup.cfg to set the version number in
+# packaging/distribution metadata.
+# Also used in Python code generated by older ksc versions (0.7 through 0.9)
+# to check that the imported runtime is compatible with the generated code.
+# Since ksc 0.10, the compatibility check instead uses the API_VERSION 
constant,
+# so that the version string does not need to be parsed at runtime
+# (see https://github.com/kaitai-io/kaitai_struct/issues/804).
+__version__ = '0.10'
+
+# Kaitai Struct runtime API version, as a tuple of ints.
+# Used in generated Python code (since ksc 0.10) to check that the imported
+# runtime is compatible with the generated code.
+API_VERSION = (0, 10)
+
+# pylint: disable=invalid-name,missing-docstring,too-many-public-methods
+# pylint: 
disable=useless-object-inheritance,super-with-arguments,consider-using-f-string
+
+
+class KaitaiStruct(object):
+    def __init__(self, stream):
+        self._io = stream
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args, **kwargs):
+        self.close()
+
+    def close(self):
+        self._io.close()
+
+    @classmethod
+    def from_file(cls, filename):
+        f = open(filename, 'rb')
+        try:
+            return cls(KaitaiStream(f))
+        except Exception:
+            # close file descriptor, then reraise the exception
+            f.close()
+            raise
+
+    @classmethod
+    def from_bytes(cls, buf):
+        return cls(KaitaiStream(BytesIO(buf)))
+
+    @classmethod
+    def from_io(cls, io):
+        return cls(KaitaiStream(io))
+
+
+class KaitaiStream(object):
+    def __init__(self, io):
+        self._io = io
+        self.align_to_byte()
+
+    def __enter__(self):
+        return self
+
+    def __exit__(self, *args, **kwargs):
+        self.close()
+
+    def close(self):
+        self._io.close()
+
+    # ========================================================================
+    # Stream positioning
+    # ========================================================================
+
+    def is_eof(self):
+        if self.bits_left > 0:
+            return False
+
+        io = self._io
+        t = io.read(1)
+        if t == b'':
+            return True
+
+        io.seek(-1, SEEK_CUR)
+        return False
+
+    def seek(self, n):
+        self._io.seek(n)
+
+    def pos(self):
+        return self._io.tell()
+
+    def size(self):
+        # Python has no internal File object API function to get
+        # current file / StringIO size, thus we use the following
+        # trick.
+        io = self._io
+        # Remember our current position
+        cur_pos = io.tell()
+        # Seek to the end of the stream and remember the full length
+        full_size = io.seek(0, SEEK_END)
+        # Seek back to the current position
+        io.seek(cur_pos)
+        return full_size
+
+    # ========================================================================
+    # Integer numbers
+    # ========================================================================
+
+    packer_s1 = struct.Struct('b')
+    packer_s2be = struct.Struct('>h')
+    packer_s4be = struct.Struct('>i')
+    packer_s8be = struct.Struct('>q')
+    packer_s2le = struct.Struct('<h')
+    packer_s4le = struct.Struct('<i')
+    packer_s8le = struct.Struct('<q')
+
+    packer_u1 = struct.Struct('B')
+    packer_u2be = struct.Struct('>H')
+    packer_u4be = struct.Struct('>I')
+    packer_u8be = struct.Struct('>Q')
+    packer_u2le = struct.Struct('<H')
+    packer_u4le = struct.Struct('<I')
+    packer_u8le = struct.Struct('<Q')
+
+    # ------------------------------------------------------------------------
+    # Signed
+    # ------------------------------------------------------------------------
+
+    def read_s1(self):
+        return KaitaiStream.packer_s1.unpack(self.read_bytes(1))[0]
+
+    # ........................................................................
+    # Big-endian
+    # ........................................................................
+
+    def read_s2be(self):
+        return KaitaiStream.packer_s2be.unpack(self.read_bytes(2))[0]
+
+    def read_s4be(self):
+        return KaitaiStream.packer_s4be.unpack(self.read_bytes(4))[0]
+
+    def read_s8be(self):
+        return KaitaiStream.packer_s8be.unpack(self.read_bytes(8))[0]
+
+    # ........................................................................
+    # Little-endian
+    # ........................................................................
+
+    def read_s2le(self):
+        return KaitaiStream.packer_s2le.unpack(self.read_bytes(2))[0]
+
+    def read_s4le(self):
+        return KaitaiStream.packer_s4le.unpack(self.read_bytes(4))[0]
+
+    def read_s8le(self):
+        return KaitaiStream.packer_s8le.unpack(self.read_bytes(8))[0]
+
+    # ------------------------------------------------------------------------
+    # Unsigned
+    # ------------------------------------------------------------------------
+
+    def read_u1(self):
+        return KaitaiStream.packer_u1.unpack(self.read_bytes(1))[0]
+
+    # ........................................................................
+    # Big-endian
+    # ........................................................................
+
+    def read_u2be(self):
+        return KaitaiStream.packer_u2be.unpack(self.read_bytes(2))[0]
+
+    def read_u4be(self):
+        return KaitaiStream.packer_u4be.unpack(self.read_bytes(4))[0]
+
+    def read_u8be(self):
+        return KaitaiStream.packer_u8be.unpack(self.read_bytes(8))[0]
+
+    # ........................................................................
+    # Little-endian
+    # ........................................................................
+
+    def read_u2le(self):
+        return KaitaiStream.packer_u2le.unpack(self.read_bytes(2))[0]
+
+    def read_u4le(self):
+        return KaitaiStream.packer_u4le.unpack(self.read_bytes(4))[0]
+
+    def read_u8le(self):
+        return KaitaiStream.packer_u8le.unpack(self.read_bytes(8))[0]
+
+    # ========================================================================
+    # Floating point numbers
+    # ========================================================================
+
+    packer_f4be = struct.Struct('>f')
+    packer_f8be = struct.Struct('>d')
+    packer_f4le = struct.Struct('<f')
+    packer_f8le = struct.Struct('<d')
+
+    # ........................................................................
+    # Big-endian
+    # ........................................................................
+
+    def read_f4be(self):
+        return KaitaiStream.packer_f4be.unpack(self.read_bytes(4))[0]
+
+    def read_f8be(self):
+        return KaitaiStream.packer_f8be.unpack(self.read_bytes(8))[0]
+
+    # ........................................................................
+    # Little-endian
+    # ........................................................................
+
+    def read_f4le(self):
+        return KaitaiStream.packer_f4le.unpack(self.read_bytes(4))[0]
+
+    def read_f8le(self):
+        return KaitaiStream.packer_f8le.unpack(self.read_bytes(8))[0]
+
+    # ========================================================================
+    # Unaligned bit values
+    # ========================================================================
+
+    def align_to_byte(self):
+        self.bits_left = 0
+        self.bits = 0
+
+    def read_bits_int_be(self, n):
+        res = 0
+
+        bits_needed = n - self.bits_left
+        self.bits_left = -bits_needed % 8
+
+        if bits_needed > 0:
+            # 1 bit  => 1 byte
+            # 8 bits => 1 byte
+            # 9 bits => 2 bytes
+            bytes_needed = ((bits_needed - 1) // 8) + 1  # `ceil(bits_needed / 
8)`
+            buf = self.read_bytes(bytes_needed)
+            if PY2:
+                buf = bytearray(buf)
+            for byte in buf:
+                res = res << 8 | byte
+
+            new_bits = res
+            res = res >> self.bits_left | self.bits << bits_needed
+            self.bits = new_bits  # will be masked at the end of the function
+        else:
+            res = self.bits >> -bits_needed  # shift unneeded bits out
+
+        mask = (1 << self.bits_left) - 1  # `bits_left` is in range 0..7
+        self.bits &= mask
+
+        return res
+
+    # Unused since Kaitai Struct Compiler v0.9+ - compatibility with
+    # older versions.
+    def read_bits_int(self, n):
+        return self.read_bits_int_be(n)
+
+    def read_bits_int_le(self, n):
+        res = 0
+        bits_needed = n - self.bits_left
+
+        if bits_needed > 0:
+            # 1 bit  => 1 byte
+            # 8 bits => 1 byte
+            # 9 bits => 2 bytes
+            bytes_needed = ((bits_needed - 1) // 8) + 1  # `ceil(bits_needed / 
8)`
+            buf = self.read_bytes(bytes_needed)
+            if PY2:
+                buf = bytearray(buf)
+            for i, byte in enumerate(buf):
+                res |= byte << (i * 8)
+
+            new_bits = res >> bits_needed
+            res = res << self.bits_left | self.bits
+            self.bits = new_bits
+        else:
+            res = self.bits
+            self.bits >>= n
+
+        self.bits_left = -bits_needed % 8
+
+        mask = (1 << n) - 1  # no problem with this in Python (arbitrary 
precision integers)
+        res &= mask
+        return res
+
+    # ========================================================================
+    # Byte arrays
+    # ========================================================================
+
+    def read_bytes(self, n):
+        if n < 0:
+            raise ValueError(
+                "requested invalid %d amount of bytes" %
+                (n,)
+            )
+
+        is_satisfiable = True
+        # When a large number of bytes is requested, try to check first
+        # that there is indeed enough data left in the stream.
+        # This avoids reading large amounts of data only to notice afterwards
+        # that it's not long enough. For smaller amounts of data, it's faster 
to
+        # first read the data unconditionally and check the length afterwards.
+        if (
+            n >= 8*1024*1024  # = 8 MiB
+            # in Python 2, there is a common error ['file' object has no
+            # attribute 'seekable'], so we need to make sure that seekable() 
exists
+            and callable(getattr(self._io, 'seekable', None))
+            and self._io.seekable()
+        ):
+            num_bytes_available = self.size() - self.pos()
+            is_satisfiable = (n <= num_bytes_available)
+
+        if is_satisfiable:
+            r = self._io.read(n)
+            num_bytes_available = len(r)
+            is_satisfiable = (n <= num_bytes_available)
+
+        if not is_satisfiable:
+            # noinspection PyUnboundLocalVariable
+            raise EOFError(
+                "requested %d bytes, but only %d bytes available" %
+                (n, num_bytes_available)
+            )
+
+        # noinspection PyUnboundLocalVariable
+        return r
+
+    def read_bytes_full(self):
+        return self._io.read()
+
+    def read_bytes_term(self, term, include_term, consume_term, eos_error):
+        r = b''
+        while True:
+            c = self._io.read(1)
+            if c == b'':
+                if eos_error:
+                    raise Exception(
+                        "end of stream reached, but no terminator %d found" %
+                        (term,)
+                    )
+
+                return r
+
+            if ord(c) == term:
+                if include_term:
+                    r += c
+                if not consume_term:
+                    self._io.seek(-1, SEEK_CUR)
+                return r
+
+            r += c
+
+    def ensure_fixed_contents(self, expected):
+        actual = self._io.read(len(expected))
+        if actual != expected:
+            raise Exception(
+                "unexpected fixed contents: got %r, was waiting for %r" %
+                (actual, expected)
+            )
+        return actual
+
+    @staticmethod
+    def bytes_strip_right(data, pad_byte):
+        return data.rstrip(KaitaiStream.byte_from_int(pad_byte))
+
+    @staticmethod
+    def bytes_terminate(data, term, include_term):
+        new_data, term_byte, _ = 
data.partition(KaitaiStream.byte_from_int(term))
+        if include_term:
+            new_data += term_byte
+        return new_data
+
+    # ========================================================================
+    # Byte array processing
+    # ========================================================================
+
+    @staticmethod
+    def process_xor_one(data, key):
+        if PY2:
+            return bytes(bytearray(v ^ key for v in bytearray(data)))
+
+        return bytes(v ^ key for v in data)
+
+    @staticmethod
+    def process_xor_many(data, key):
+        if PY2:
+            return bytes(bytearray(a ^ b for a, b in zip(bytearray(data), 
itertools.cycle(bytearray(key)))))
+
+        return bytes(a ^ b for a, b in zip(data, itertools.cycle(key)))
+
+    @staticmethod
+    def process_rotate_left(data, amount, group_size):
+        if group_size != 1:
+            raise Exception(
+                "unable to rotate group of %d bytes yet" %
+                (group_size,)
+            )
+
+        anti_amount = -amount % (group_size * 8)
+
+        r = bytearray(data)
+        for i, byte in enumerate(r):
+            r[i] = (byte << amount) & 0xff | (byte >> anti_amount)
+        return bytes(r)
+
+    # ========================================================================
+    # Misc
+    # ========================================================================
+
+    @staticmethod
+    def int_from_byte(v):
+        return ord(v) if PY2 else v
+
+    @staticmethod
+    def byte_from_int(i):
+        return chr(i) if PY2 else bytes((i,))
+
+    @staticmethod
+    def byte_array_index(data, i):
+        return KaitaiStream.int_from_byte(data[i])
+
+    @staticmethod
+    def byte_array_min(b):
+        return KaitaiStream.int_from_byte(min(b))
+
+    @staticmethod
+    def byte_array_max(b):
+        return KaitaiStream.int_from_byte(max(b))
+
+    @staticmethod
+    def resolve_enum(enum_obj, value):
+        """Resolves value using enum: if the value is not found in the map,
+        we'll just use literal value per se. Works around problem with Python
+        enums throwing an exception when encountering unknown value.
+        """
+        try:
+            return enum_obj(value)
+        except ValueError:
+            return value
+
+
+class KaitaiStructError(Exception):
+    """Common ancestor for all error originating from Kaitai Struct usage.
+    Stores KSY source path, pointing to an element supposedly guilty of
+    an error.
+    """
+    def __init__(self, msg, src_path):
+        super(KaitaiStructError, self).__init__("%s: %s" % (src_path, msg))
+        self.src_path = src_path
+
+
+class UndecidedEndiannessError(KaitaiStructError):
+    """Error that occurs when default endianness should be decided with
+    switch, but nothing matches (although using endianness expression
+    implies that there should be some positive result).
+    """
+    def __init__(self, src_path):
+        super(UndecidedEndiannessError, self).__init__("unable to decide on 
endianness for a type", src_path)
+
+
+class ValidationFailedError(KaitaiStructError):
+    """Common ancestor for all validation failures. Stores pointer to
+    KaitaiStream IO object which was involved in an error.
+    """
+    def __init__(self, msg, io, src_path):
+        super(ValidationFailedError, self).__init__("at pos %d: validation 
failed: %s" % (io.pos(), msg), src_path)
+        self.io = io
+
+
+class ValidationNotEqualError(ValidationFailedError):
+    """Signals validation failure: we required "actual" value to be equal to
+    "expected", but it turned out that it's not.
+    """
+    def __init__(self, expected, actual, io, src_path):
+        super(ValidationNotEqualError, self).__init__("not equal, expected %s, 
but got %s" % (repr(expected), repr(actual)), io, src_path)
+        self.expected = expected
+        self.actual = actual
+
+
+class ValidationLessThanError(ValidationFailedError):
+    """Signals validation failure: we required "actual" value to be
+    greater than or equal to "min", but it turned out that it's not.
+    """
+    def __init__(self, min_bound, actual, io, src_path):
+        super(ValidationLessThanError, self).__init__("not in range, min %s, 
but got %s" % (repr(min_bound), repr(actual)), io, src_path)
+        self.min = min_bound
+        self.actual = actual
+
+
+class ValidationGreaterThanError(ValidationFailedError):
+    """Signals validation failure: we required "actual" value to be
+    less than or equal to "max", but it turned out that it's not.
+    """
+    def __init__(self, max_bound, actual, io, src_path):
+        super(ValidationGreaterThanError, self).__init__("not in range, max 
%s, but got %s" % (repr(max_bound), repr(actual)), io, src_path)
+        self.max = max_bound
+        self.actual = actual
+
+
+class ValidationNotAnyOfError(ValidationFailedError):
+    """Signals validation failure: we required "actual" value to be
+    from the list, but it turned out that it's not.
+    """
+    def __init__(self, actual, io, src_path):
+        super(ValidationNotAnyOfError, self).__init__("not any of the list, 
got %s" % (repr(actual)), io, src_path)
+        self.actual = actual
+
+
+class ValidationExprError(ValidationFailedError):
+    """Signals validation failure: we required "actual" value to match
+    the expression, but it turned out that it doesn't.
+    """
+    def __init__(self, actual, io, src_path):
+        super(ValidationExprError, self).__init__("not matching the 
expression, got %s" % (repr(actual)), io, src_path)
+        self.actual = actual
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/pyproject.toml 
new/kaitaistruct-0.10/pyproject.toml
--- old/kaitaistruct-0.9/pyproject.toml 1970-01-01 01:00:00.000000000 +0100
+++ new/kaitaistruct-0.10/pyproject.toml        2022-04-15 10:06:08.000000000 
+0200
@@ -0,0 +1,3 @@
+[build-system]
+requires = ["setuptools >= 38.6.0", "wheel >= 0.23.0"]
+build-backend = "setuptools.build_meta"
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/setup.cfg 
new/kaitaistruct-0.10/setup.cfg
--- old/kaitaistruct-0.9/setup.cfg      2020-10-16 01:34:07.576354000 +0200
+++ new/kaitaistruct-0.10/setup.cfg     2022-07-09 02:26:54.262237000 +0200
@@ -1,45 +1,51 @@
-[metadata]
-name = kaitaistruct
-version = attr: kaitaistruct.__version__
-author = Kaitai Project
-author_email = grey...@kaitai.io
-url = http://kaitai.io
-description = Kaitai Struct declarative parser generator for binary data: 
runtime library for Python
-long_description = file: README.rst
-license = MIT
-keywords = kaitai, struct, construct, ksy, declarative, data structure, data 
format, file format, packet format, binary, parser, parsing, unpack, development
-classifiers = 
-       Development Status :: 4 - Beta
-       Intended Audience :: Developers
-       Topic :: Software Development :: Build Tools
-       License :: OSI Approved :: MIT License
-       Programming Language :: Python :: 2
-       Programming Language :: Python :: 2.7
-       Programming Language :: Python :: 3
-       Programming Language :: Python :: 3.4
-       Programming Language :: Python :: 3.5
-       Programming Language :: Python :: 3.6
-       Programming Language :: Python :: 3.7
-       Programming Language :: Python :: Implementation :: CPython
-       Programming Language :: Python :: Implementation :: PyPy
-
-[options]
-zip_safe = True
-include_package_data = True
-py_modules = kaitaistruct
-python_requires = >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
-
-[bdist_wheel]
-universal = 1
-
-[build-system]
-requires = ["setuptools", "wheel"]
-
-[pycodestyle]
-max-line-length = 140
-statistics = True
-
-[egg_info]
-tag_build = 
-tag_date = 0
-
+[metadata]
+name = kaitaistruct
+version = attr: kaitaistruct.__version__
+author = Kaitai Project
+author_email = grey...@kaitai.io
+url = https://kaitai.io
+description = Kaitai Struct declarative parser generator for binary data: 
runtime library for Python
+long_description = file: README.md
+long_description_content_type = text/markdown
+license = MIT
+keywords = kaitai, struct, construct, ksy, declarative, data structure, data 
format, file format, packet format, binary, parser, parsing, unpack, development
+classifiers = 
+       Development Status :: 4 - Beta
+       Intended Audience :: Developers
+       Topic :: Software Development :: Build Tools
+       License :: OSI Approved :: MIT License
+       Programming Language :: Python :: 2
+       Programming Language :: Python :: 2.7
+       Programming Language :: Python :: 3
+       Programming Language :: Python :: 3.4
+       Programming Language :: Python :: 3.5
+       Programming Language :: Python :: 3.6
+       Programming Language :: Python :: 3.7
+       Programming Language :: Python :: 3.8
+       Programming Language :: Python :: 3.9
+       Programming Language :: Python :: 3.10
+       Programming Language :: Python :: Implementation :: CPython
+       Programming Language :: Python :: Implementation :: PyPy
+
+[options]
+zip_safe = True
+include_package_data = True
+py_modules = kaitaistruct
+python_requires = >=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*
+install_requires = 
+       enum34; python_version < "3.4"
+setup_requires = 
+       setuptools >= 38.6.0
+       wheel >= 0.23.0
+
+[bdist_wheel]
+universal = 1
+
+[pycodestyle]
+max-line-length = 140
+statistics = True
+
+[egg_info]
+tag_build = 
+tag_date = 0
+
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/kaitaistruct-0.9/setup.py 
new/kaitaistruct-0.10/setup.py
--- old/kaitaistruct-0.9/setup.py       2020-05-17 00:14:19.000000000 +0200
+++ new/kaitaistruct-0.10/setup.py      2021-08-14 11:42:27.000000000 +0200
@@ -1,3 +1,3 @@
-from setuptools import setup
-
-setup()
+from setuptools import setup
+
+setup()

Reply via email to