Thu, 31 Oct 2024 17:44:46 +0100
Added code to ensure, that compiled form files get recreated before they are written to the plugin archive.
--- a/docs/changelog.md Thu Oct 31 14:39:04 2024 +0100 +++ b/docs/changelog.md Thu Oct 31 17:44:46 2024 +0100 @@ -2,6 +2,9 @@ ### Version 24.12 - bug fixes +- Project Type 'Eric7 Plugin' + - Added code to ensure, that compiled form files get recreated before + they are written to the plugin archive. ### Version 24.11 **Note:** As Python 3.8 is EOL this eric-ide release will be the last one
--- a/src/eric7/APIs/Python3/eric7.api Thu Oct 31 14:39:04 2024 +0100 +++ b/src/eric7/APIs/Python3/eric7.api Thu Oct 31 17:44:46 2024 +0100 @@ -11413,6 +11413,7 @@ eric7.Utilities.rxIndex?4(rx, txt) eric7.Utilities.slash?4(txt) eric7.Utilities.supportedCodecs?7 +eric7.Utilities.uic.compileOneUi?4(ui_path, mapFunc=None, execute=False, indent=4, uiheadername="") eric7.Utilities.uic.compileUiFiles?4(directory, recurse=False) eric7.Utilities.unslash?4(txt) eric7.Utilities.writeEncodedFile?4(filename, text, origEncoding, forcedEncoding="")
--- a/src/eric7/Documentation/Help/source.qhp Thu Oct 31 14:39:04 2024 +0100 +++ b/src/eric7/Documentation/Help/source.qhp Thu Oct 31 17:44:46 2024 +0100 @@ -20103,6 +20103,7 @@ <keyword name="_Unparser.write_key_value_pair" id="_Unparser.write_key_value_pair" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.ast_unparse.html#_Unparser.write_key_value_pair" /> <keyword name="__checkCodeStyle" id="__checkCodeStyle" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleChecker.html#__checkCodeStyle" /> <keyword name="__checkSyntax" id="__checkSyntax" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.CodeStyleChecker.html#__checkSyntax" /> + <keyword name="__compileUi" id="__compileUi" ref="eric7.Utilities.uic.html#__compileUi" /> <keyword name="__getMainPassword" id="__getMainPassword" ref="eric7.EricUtilities.crypto.__init__.html#__getMainPassword" /> <keyword name="__getPygmentsLexer" id="__getPygmentsLexer" ref="eric7.QScintilla.Lexers.__init__.html#__getPygmentsLexer" /> <keyword name="__initChannelModesDict" id="__initChannelModesDict" ref="eric7.Network.IRC.IrcUtilities.html#__initChannelModesDict" /> @@ -20263,6 +20264,7 @@ <keyword name="comparison_negative" id="comparison_negative" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#comparison_negative" /> <keyword name="comparison_to_singleton" id="comparison_to_singleton" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#comparison_to_singleton" /> <keyword name="comparison_type" id="comparison_type" ref="eric7.Plugins.CheckerPlugins.CodeStyleChecker.pycodestyle.html#comparison_type" /> + <keyword name="compileOneUi" id="compileOneUi" ref="eric7.Utilities.uic.html#compileOneUi" /> <keyword name="compileRegExp" id="compileRegExp" ref="eric7.CodeFormatting.BlackUtilities.html#compileRegExp" /> <keyword name="compileUiFiles" id="compileUiFiles" ref="eric7.Utilities.uic.html#compileUiFiles" /> <keyword name="completeFormData" id="completeFormData" ref="eric7.WebBrowser.Tools.Scripts.html#completeFormData" />
--- a/src/eric7/Documentation/Source/eric7.Utilities.uic.html Thu Oct 31 14:39:04 2024 +0100 +++ b/src/eric7/Documentation/Source/eric7.Utilities.uic.html Thu Oct 31 17:44:46 2024 +0100 @@ -25,10 +25,18 @@ <h3>Functions</h3> <table> <tr> +<td><a href="#__compileUi">__compileUi</a></td> +<td>Function to create a Python module from a Qt Designer .ui file.</td> +</tr> +<tr> <td><a href="#__pyName">__pyName</a></td> <td>Local function to create the Python source file name for the compiled .ui file.</td> </tr> <tr> +<td><a href="#compileOneUi">compileOneUi</a></td> +<td>Function to compile a single form file to Python code.</td> +</tr> +<tr> <td><a href="#compileUiFiles">compileUiFiles</a></td> <td>Module function to compile the .ui files of a directory tree to Python sources.</td> </tr> @@ -36,6 +44,41 @@ <hr /> <hr /> +<a NAME="__compileUi" ID="__compileUi"></a> +<h2>__compileUi</h2> +<b>__compileUi</b>(<i>uifile, pyfile, execute=False, indent=4, uiheadername=""</i>) +<p> + Function to create a Python module from a Qt Designer .ui file. +</p> + +<dl> + +<dt><i>uifile</i> (str or file)</dt> +<dd> +file name or file-like object containing the .ui file +</dd> +<dt><i>pyfile</i> (file)</dt> +<dd> +file-like object to which the Python code will be written to +</dd> +<dt><i>execute</i> (bool (optional))</dt> +<dd> +flag indicating to generate extra Python code that allows the + code to be run as a standalone application (defaults to False) +</dd> +<dt><i>indent</i> (int (optional))</dt> +<dd> +indentation width using spaces. If it is 0 then a tab is used. + (defaults to 4) +</dd> +<dt><i>uiheadername</i> (str ((optional))</dt> +<dd> +UI file name to be placed in the header (defaults to "") +</dd> +</dl> +<div align="right"><a href="#top">Up</a></div> +<hr /> +<hr /> <a NAME="__pyName" ID="__pyName"></a> <h2>__pyName</h2> <b>__pyName</b>(<i>py_dir, py_file</i>) @@ -70,6 +113,41 @@ <div align="right"><a href="#top">Up</a></div> <hr /> <hr /> +<a NAME="compileOneUi" ID="compileOneUi"></a> +<h2>compileOneUi</h2> +<b>compileOneUi</b>(<i>ui_path, mapFunc=None, execute=False, indent=4, uiheadername=""</i>) +<p> + Function to compile a single form file to Python code. +</p> + +<dl> + +<dt><i>ui_path</i> (str)</dt> +<dd> +path of the Qt form file +</dd> +<dt><i>mapFunc</i> (func (optional))</dt> +<dd> +function to change directory and/or name of the resulting Python file + (defaults to None) +</dd> +<dt><i>execute</i> (bool (optional))</dt> +<dd> +flag indicating to generate code to execute the form in standalone + mode (defaults to False) +</dd> +<dt><i>indent</i> (int (optional))</dt> +<dd> +indentation width using spaces (defaults to 4) +</dd> +<dt><i>uiheadername</i> (str ((optional))</dt> +<dd> +UI file name to be placed in the header (defaults to "") +</dd> +</dl> +<div align="right"><a href="#top">Up</a></div> +<hr /> +<hr /> <a NAME="compileUiFiles" ID="compileUiFiles"></a> <h2>compileUiFiles</h2> <b>compileUiFiles</b>(<i>directory, recurse=False</i>)
--- a/src/eric7/Project/Project.py Thu Oct 31 14:39:04 2024 +0100 +++ b/src/eric7/Project/Project.py Thu Oct 31 17:44:46 2024 +0100 @@ -54,6 +54,7 @@ ) from eric7.Tasks.TasksFile import TasksFile from eric7.UI.NotificationWidget import NotificationTypes +from eric7.Utilities.uic import compileOneUi from eric7.VCS.VersionControl import VersionControlState from .DebuggerPropertiesFile import DebuggerPropertiesFile @@ -7157,6 +7158,20 @@ errors += 1 continue + # recompile all included compiled forms + for name in names: + nameList = os.path.split(name) + if nameList[1].startswith("Ui_") and nameList[1].endswith(".py"): + # It is a compiled form file. + formPath = os.path.join( + nameList[0], + nameList[1].replace("Ui_", "").replace(".py", ".ui"), + ) + compileOneUi( + os.path.join(self.ppath, formPath), uiheadername=formPath + ) + + # create the plugin archive for name in names: if name: try:
--- a/src/eric7/Utilities/uic.py Thu Oct 31 14:39:04 2024 +0100 +++ b/src/eric7/Utilities/uic.py Thu Oct 31 17:44:46 2024 +0100 @@ -8,6 +8,8 @@ directory or directory tree. """ +import os + from PyQt6.uic import compileUiDir @@ -36,4 +38,85 @@ @param recurse flag indicating to recurse into subdirectories @type boolean) """ - compileUiDir(directory, recurse, __pyName) + compileUiDir(directory, recurse=recurse, map=__pyName) + + +def compileOneUi(ui_path, mapFunc=None, execute=False, indent=4, uiheadername=""): + """ + Function to compile a single form file to Python code. + + @param ui_path path of the Qt form file + @type str + @param mapFunc function to change directory and/or name of the resulting Python file + (defaults to None) + @type func (optional) + @param execute flag indicating to generate code to execute the form in standalone + mode (defaults to False) + @type bool (optional) + @param indent indentation width using spaces (defaults to 4) + @type int (optional) + @param uiheadername UI file name to be placed in the header (defaults to "") + @type str ((optional) + """ + py_dir, py_file = os.path.split(ui_path[:-3] + ".py") + + # Allow the caller to change the name of the .py file or generate + # it in a different directory. + if mapFunc is None: + py_dir, py_file = __pyName(py_dir, py_file) + else: + py_dir, py_file = mapFunc(py_dir, py_file) + + # Make sure the destination directory exists. + os.makedirs(py_dir, exist_ok=True) + + py_path = os.path.join(py_dir, py_file) + + with open(py_path, "w", encoding="utf-8") as py_file: + __compileUi( + ui_path, py_file, execute=execute, indent=indent, uiheadername=uiheadername + ) + + +################################################################################ +## Below is a modified compileUi() of PyQt6 +################################################################################ + + +def __compileUi(uifile, pyfile, execute=False, indent=4, uiheadername=""): + """ + Function to create a Python module from a Qt Designer .ui file. + + @param uifile file name or file-like object containing the .ui file + @type str or file + @param pyfile file-like object to which the Python code will be written to + @type file + @param execute flag indicating to generate extra Python code that allows the + code to be run as a standalone application (defaults to False) + @type bool (optional) + @param indent indentation width using spaces. If it is 0 then a tab is used. + (defaults to 4) + @type int (optional) + @param uiheadername UI file name to be placed in the header (defaults to "") + @type str ((optional) + """ + from PyQt6.QtCore import PYQT_VERSION_STR # noqa: I102 + from PyQt6.uic.compile_ui import _display_code, _header # noqa: I102 + from PyQt6.uic.Compiler import compiler, indenter # noqa: I102 + + if uiheadername: + uifname = uiheadername + else: + try: + uifname = uifile.name + except AttributeError: + uifname = uifile + + indenter.indentwidth = indent + + pyfile.write(_header.format(uifname, PYQT_VERSION_STR)) + + winfo = compiler.UICompiler().compileUi(uifile, pyfile) + + if execute: + indenter.write_code(_display_code % winfo)