Ui file encoding issue: PyQt5.uic.compileUiDir() uses local default text encoding for all UI files, instead of utf-8 (PyQt5 5.15.7)

Phil Thompson phil at riverbankcomputing.com
Fri Oct 28 02:58:57 BST 2022


On 19/10/2022 20:17, Thomas Hess wrote:
> Hello list,
> 
> I think I found a file-encoding related bug in 
> PyQt5.uic.compileUiDir():
> 
> It internally open()s the input UI file and output Python file without
> specifying the encoding, thus using the system-default encoding for 
> text files.
> 
> For my Windows VMs, the default encoding is cp1252. Compiling my UI 
> files
> causes a UnicodeDecodeError on utf-8 encoded UI files that contain 
> characters
> invalid in said default encoding, which crashes the ui compilation 
> step.
> 
> Additionally, the generated file header explicitly mentions that the 
> output is
> using utf-8, which is currently simply not true, because compileUiDir()
> doesn’t always write using utf-8.
> 
> I propose this patch (released as Public Domain) to solve both points 
> (which
> is also attached):
> 
> 
> --- a/PyQt5/uic/__init__.py
> +++ b/PyQt5/uic/__init__.py
> @@ -111,13 +111,11 @@ def compileUiDir(dir, recurse=False, map=None,
> **compileUi_args):
>              ui_path = os.path.join(ui_dir, ui_file)
>              py_path = os.path.join(py_dir, py_file)
> 
> -            ui_file = open(ui_path, 'r')
> -            py_file = open(py_path, 'w')
> +            py_file = open(py_path, 'w',  encoding='utf-8')
> 
>              try:
> -                compileUi(ui_file, py_file, **compileUi_args)
> +                compileUi(ui_path, py_file, **compileUi_args)
>              finally:
> -                ui_file.close()
>                  py_file.close()
> 
> For the output side, the patched code explicitly specifies utf-8 as the 
> output
> encoding, according to the header defined starting with line 46.
> 
> The input encoding issue is solved by not opening the UI file here at 
> all,
> instead passing the file path to compileUi(), which can handle file 
> paths
> according to the docstring. The compileUi-internal file handling logic 
> then
> handles the utf-8 input files properly.
> 
> The attached UI file contains a minimal crashing example. Place mce.ui 
> into the
> the current directory.
> Compiling via compileUi is successful:
>>>> with open("mce.py", "w", encoding="utf-8") as f: compileUi("mce.ui", 
>>>> f)
> 
> Compiling via compileUiDir fails:
>>>> compileUiDir(".")
> [snip]
> UnicodeDecodeError: 'charmap' codec can't decode byte 0x9d in position 
> 161:
> character maps to <undefined>

Applied with a slight change for Python v2.

Thanks,
Phil


More information about the PyQt mailing list