Package: debmutate Version: 0.71 Severity: important Tags: python3.13 The python3-debmutate package fails to handle UTF-8 encoded files when running under Python 3.13. This affects multiple Debian packaging tools including lintian-brush, making it impossible to process packages containing non-ASCII characters.
When running lintian-brush, the following error occurs: UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) This error occurs in debmutate/reformatting.py, line 223: self._orig_content = f.read() The error appears when processing both debian/copyright and debian/changelog files that contain UTF-8 characters. Setting PYTHONIOENCODING=utf8 does not resolve the issue. Steps to reproduce: 1. Have a package with non-ASCII characters in debian/copyright or debian/changelog 2. Run: lintian-brush --no-update-changelog --modern --uncertain 3. Observe the UnicodeDecodeError The error occurs with multiple lintian-brush fixers: - global-files-wildcard-not-first-paragraph-in-dep5-copyright - new-package-uses-date-based-version-number This appears to be a regression in Python 3.13 handling, as these files are valid UTF-8 and can be processed correctly by iconv and other tools. Full log of lintian-brush on package MariaDB in Debian unstable for further reference below. *************** # dpkg -l | grep -E 'debmutate|lintian' ii lintian 2.121.1 all Debian package checker ii lintian-brush 0.160+b2 amd64 automatically fix lintian problems ii python3-debmutate 0.71 all Format-preserving manipulation of Debian control files in Python # file -i debian/copyright debian/changelog debian/copyright: text/plain; charset=utf-8 debian/changelog: text/plain; charset=utf-8 # PYTHONIOENCODING=utf8 lintian-brush --no-update-changelog --modern --uncertain [ ] 154/154No changes made. Some fixer scripts failed to run: copyright-missing-upstream-info: Script failed: /usr/share/lintian-brush/fixers/copyright-missing-upstream-info.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/copyright-missing-upstream-info.py", line 80, in <module> ), CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) debian-changelog-line-too-long: Script failed: /usr/share/lintian-brush/fixers/debian-changelog-line-too-long.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/debian-changelog-line-too-long.py", line 42, in <module> with ChangelogEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) obsolete-field-in-dep5-copyright: Script failed: /usr/share/lintian-brush/fixers/obsolete-field-in-dep5-copyright.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/obsolete-field-in-dep5-copyright.py", line 47, in <module> ), CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) upstream-metadata-file: Timeout after 10s initial-upload-closes-no-bugs: Script failed: /usr/share/lintian-brush/fixers/initial-upload-closes-no-bugs.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/initial-upload-closes-no-bugs.py", line 21, in <module> with ChangelogEditor() as editor: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) ancient-maintscript-entry: Script failed: /usr/share/lintian-brush/fixers/ancient-maintscript-entry.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/ancient-maintscript-entry.py", line 52, in <module> with ChangelogEditor() as cl: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) space-in-std-shortname-in-dep5-copyright: Script failed: /usr/share/lintian-brush/fixers/space-in-std-shortname-in-dep5-copyright.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/space-in-std-shortname-in-dep5-copyright.py", line 68, in <module> ), CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) debian-changelog-has-wrong-day-of-week: Script failed: /usr/share/lintian-brush/fixers/debian-changelog-has-wrong-day-of-week.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/debian-changelog-has-wrong-day-of-week.py", line 12, in <module> with ChangelogEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) invalid-short-name-in-dep5-copyright: Script failed: /usr/share/lintian-brush/fixers/invalid-short-name-in-dep5-copyright.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/invalid-short-name-in-dep5-copyright.py", line 50, in <module> ), CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) dep5-file-paragraph-references-header-paragraph: Script failed: /usr/share/lintian-brush/fixers/dep5-file-paragraph-references-header-paragraph.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/dep5-file-paragraph-references-header-paragraph.py", line 41, in <module> with CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) out-of-date-standards-version: Script failed: /usr/share/lintian-brush/fixers/out-of-date-standards-version.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/out-of-date-standards-version.py", line 301, in <module> svs = dict(iter_standards_versions()) File "/usr/lib/python3/dist-packages/lintian_brush/standards_version.py", line 41, in iter_standards_versions data = json.load(f) File "/usr/lib/python3.13/json/__init__.py", line 293, in load return loads(fp.read(), ~~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4315: ordinal not in range(128) ) global-files-wildcard-not-first-paragraph-in-dep5-copyright: Script failed: /usr/share/lintian-brush/fixers/global-files-wildcard-not-first-paragraph-in-dep5-copyright.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/global-files-wildcard-not-first-paragraph-in-dep5-copyright.py", line 11, in <module> ), CopyrightEditor() as editor: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) common-license: Script failed: /usr/share/lintian-brush/fixers/common-license.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/common-license.py", line 271, in <module> ), CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) changelog-has-duplicate-line: Script failed: /usr/share/lintian-brush/fixers/changelog-has-duplicate-line.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/changelog-has-duplicate-line.py", line 7, in <module> with ChangelogEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) possible-missing-colon-in-closes: Script failed: /usr/share/lintian-brush/fixers/possible-missing-colon-in-closes.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/possible-missing-colon-in-closes.py", line 88, in <module> with ChangelogEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) unnecessary-team-upload: Script failed: /usr/share/lintian-brush/fixers/unnecessary-team-upload.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/unnecessary-team-upload.py", line 19, in <module> with ChangelogEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) unused-license-paragraph-in-dep5-copyright: Script failed: /usr/share/lintian-brush/fixers/unused-license-paragraph-in-dep5-copyright.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/unused-license-paragraph-in-dep5-copyright.py", line 33, in <module> with CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) copyright-refers-to-symlink-license: Script failed: /usr/share/lintian-brush/fixers/copyright-refers-to-symlink-license.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/copyright-refers-to-symlink-license.py", line 42, in <module> ), CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) debian-rules-uses-unnecessary-dh-argument: Script failed: /usr/share/lintian-brush/fixers/debian-rules-uses-unnecessary-dh-argument.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/debian-rules-uses-unnecessary-dh-argument.py", line 20, in <module> compat_version = get_debhelper_compat_level() File "/usr/lib/python3/dist-packages/debmutate/debhelper.py", line 123, in get_debhelper_compat_level control = Deb822(f) File "/usr/lib/python3/dist-packages/debian/deb822.py", line 673, in __init__ self._internal_parser(iterable, fields, strict) ~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/debian/deb822.py", line 817, in _internal_parser for linebytes in self._gpg_stripped_paragraph( ~~~~~~~~~~~~~~~~~~~~~~~~~~~~^ self._skip_useless_lines(sequence), strict): ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/debian/deb822.py", line 1184, in _gpg_stripped_paragraph return cls._split_gpg_and_payload(sequence, strict)[1] ~~~~~~~~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^ File "/usr/lib/python3/dist-packages/debian/deb822.py", line 1133, in _split_gpg_and_payload for line in sequence: ^^^^^^^^ File "/usr/lib/python3/dist-packages/debian/deb822.py", line 773, in _skip_useless_lines for line in sequence: ^^^^^^^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 152: ordinal not in range(128) ) license-file-listed-in-debian-copyright: Script failed: /usr/share/lintian-brush/fixers/license-file-listed-in-debian-copyright.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/license-file-listed-in-debian-copyright.py", line 19, in <module> with CopyrightEditor() as updater: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc2 in position 5806: ordinal not in range(128) ) invalid-standards-version: Script failed: /usr/share/lintian-brush/fixers/invalid-standards-version.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/invalid-standards-version.py", line 11, in <module> release_dates = dict(iter_standards_versions()) File "/usr/lib/python3/dist-packages/lintian_brush/standards_version.py", line 41, in iter_standards_versions data = json.load(f) File "/usr/lib/python3.13/json/__init__.py", line 293, in load return loads(fp.read(), ~~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 4315: ordinal not in range(128) ) new-package-uses-date-based-version-number: Script failed: /usr/share/lintian-brush/fixers/new-package-uses-date-based-version-number.py (exit code 1) (stderr: Traceback (most recent call last): File "/usr/share/lintian-brush/fixers/new-package-uses-date-based-version-number.py", line 11, in <module> with ChangelogEditor() as editor: ~~~~~~~~~~~~~~~^^ File "/usr/lib/python3/dist-packages/debmutate/reformatting.py", line 223, in __enter__ self._orig_content = f.read() ~~~~~~^^ File "/usr/lib/python3.13/encodings/ascii.py", line 26, in decode return codecs.ascii_decode(input, self.errors)[0] ~~~~~~~~~~~~~~~~~~~^^^^^^^^^^^^^^^^^^^^ UnicodeDecodeError: 'ascii' codec can't decode byte 0xc3 in position 705: ordinal not in range(128) ) Run with --verbose for details.