diff options
| author | Shyamnath Premnadh <Shyamnath.Premnadh@qt.io> | 2024-09-20 17:00:39 +0200 |
|---|---|---|
| committer | Shyamnath Premnadh <Shyamnath.Premnadh@qt.io> | 2024-10-07 13:54:03 +0200 |
| commit | 1e5fe140b485209a30d7dd38b3334440c58cbb05 (patch) | |
| tree | 43511980e289c57b6208ad0bf9b0c09ea58a483e /sources/pyside-tools/deploy_lib | |
| parent | 9a10caa1e22773ce7563f82680c67596293178e4 (diff) | |
Deployment: Support Design Studio projects
- new class 'DesignStudio' to handle Design Studio projects.
- Currently uses a way of monkey patching to override the 'main.py'
to use 'main_patch.py' which has the same content but with
'app_dir' set to the parent of `main.py``. The reason for doing this
is that Nuitka requires the `main.py` to be in the same directory
as other resources required for the project.
Once the corresponding patch, to alternate between evaluating
'app_dir' based on whether the application is deployed or called
through the Python interpreter, is merged then this temporary fix
of creating 'main_patch.py' can be removed.
- Add tests.
Pick-to: 6.7
Change-Id: I79e6572bdbbf4576fbdd9039a4922997a22139f8
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
Diffstat (limited to 'sources/pyside-tools/deploy_lib')
| -rw-r--r-- | sources/pyside-tools/deploy_lib/__init__.py | 1 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/config.py | 57 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/design_studio.py | 57 | ||||
| -rw-r--r-- | sources/pyside-tools/deploy_lib/nuitka_helper.py | 27 |
4 files changed, 108 insertions, 34 deletions
diff --git a/sources/pyside-tools/deploy_lib/__init__.py b/sources/pyside-tools/deploy_lib/__init__.py index 98179ecf0..3417f7a29 100644 --- a/sources/pyside-tools/deploy_lib/__init__.py +++ b/sources/pyside-tools/deploy_lib/__init__.py @@ -54,6 +54,7 @@ def get_all_pyside_modules(): return [module[2:] for module in PySide6.__all__] +from .design_studio import DesignStudio from .commands import run_command, run_qmlimportscanner from .dependency_util import find_pyside_modules, find_permission_categories, QtDependencyReader from .nuitka_helper import Nuitka diff --git a/sources/pyside-tools/deploy_lib/config.py b/sources/pyside-tools/deploy_lib/config.py index c400348ec..d34489b97 100644 --- a/sources/pyside-tools/deploy_lib/config.py +++ b/sources/pyside-tools/deploy_lib/config.py @@ -12,7 +12,7 @@ from pathlib import Path from enum import Enum from project import ProjectData -from . import (DEFAULT_APP_ICON, DEFAULT_IGNORE_DIRS, find_pyside_modules, +from . import (DEFAULT_APP_ICON, DEFAULT_IGNORE_DIRS, DesignStudio, find_pyside_modules, find_permission_categories, QtDependencyReader, run_qmlimportscanner) # Some QML plugins like QtCore are excluded from this list as they don't contribute much to @@ -165,7 +165,10 @@ class Config(BaseConfig): else: self.excluded_qml_plugins = self._find_excluded_qml_plugins() - self._generated_files_path = self.project_dir / "deployment" + if DesignStudio.isDSProject(self.source_file): + self._generated_files_path = self.project_dir / "Python" / "deployment" + else: + self._generated_files_path = self.project_dir / "deployment" self.modules = [] @@ -208,9 +211,10 @@ class Config(BaseConfig): @qml_files.setter def qml_files(self, qml_files): self._qml_files = qml_files - self.set_value("qt", "qml_files", - ",".join([str(file.absolute().relative_to(self.project_dir.absolute())) - for file in self.qml_files])) + qml_files = [str(file.absolute().relative_to(self.project_dir.absolute())) + if file.absolute().is_relative_to(self.project_dir) else str(file.absolute()) + for file in self.qml_files] + self.set_value("qt", "qml_files", ",".join(qml_files)) @property def project_dir(self): @@ -254,6 +258,11 @@ class Config(BaseConfig): @source_file.setter def source_file(self, source_file: Path): self._source_file = source_file + # FIXME: Remove when new DS is released + # for DS project, set self._source_file to main_patch.py, but don't change the value + # in the config file as main_patch.py is a temporary file + if DesignStudio.isDSProject(source_file): + self._source_file = DesignStudio(source_file).ds_source_file self.set_value("app", "input_file", str(source_file)) @property @@ -314,30 +323,28 @@ class Config(BaseConfig): qml_files.extend([self.project_dir / str(qml_file) for qml_file in ProjectData(project_file=sub_project_file).qml_files]) else: - qml_files_temp = None - if self.source_file and self.python_path: - if not self.qml_files: - # filter out files from DEFAULT_IGNORE_DIRS - qml_files_temp = [file for file in self.source_file.parent.glob("**/*.qml") - if all(part not in file.parts for part in - DEFAULT_IGNORE_DIRS)] - - if len(qml_files_temp) > 500: - warnings.warn( - "You seem to include a lot of QML files. This can lead to errors in " - "deployment." - ) - - if qml_files_temp: - extra_qml_files = [Path(file) for file in qml_files_temp] - qml_files.extend(extra_qml_files) + # Filter out files from DEFAULT_IGNORE_DIRS + qml_files = [ + file for file in self.project_dir.glob("**/*.qml") + if all(part not in file.parts for part in DEFAULT_IGNORE_DIRS) + ] + + if len(qml_files) > 500: + warnings.warn( + "You seem to include a lot of QML files from " + f"{self.project_dir}. This can lead to errors in deployment." + ) return qml_files def _find_project_dir(self) -> Path: - # there is no other way to find the project_dir than assume it is the parent directory - # of source_file - project_dir = self.source_file.parent + if DesignStudio.isDSProject(self.source_file): + ds = DesignStudio(self.source_file) + project_dir = ds.project_dir + else: + # there is no other way to find the project_dir than assume it is the parent directory + # of source_file + project_dir = self.source_file.parent return project_dir def _find_project_file(self) -> Path: diff --git a/sources/pyside-tools/deploy_lib/design_studio.py b/sources/pyside-tools/deploy_lib/design_studio.py new file mode 100644 index 000000000..1fc1a4cc8 --- /dev/null +++ b/sources/pyside-tools/deploy_lib/design_studio.py @@ -0,0 +1,57 @@ +# Copyright (C) 2024 The Qt Company Ltd. +# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +import logging +import atexit +from pathlib import Path + +# FIXME: Remove this idea of creating main_patch.py once the corresponding changes are +# made in Design Studio main.py file: +# if '__compiled__' in globals(): #nuitka +# app_dir = Path(__file__).parent +# else: +# app_dir = Path(__file__).parent.parent + + +class DesignStudio: + """ + Class to handle Design Studio projects + """ + + def __init__(self, main_file: Path): + self.ds_project_dir = main_file.parent.parent + self.current_main_file = main_file + self.new_main_file = main_file.parent / 'main_patch.py' + self._create_new_main_file() + atexit.register(self._delete_main_patch_file) + + def _create_new_main_file(self): + # read the content of main file + content = "" + with open(self.current_main_file, 'r', encoding='utf-8') as main_file: + content = main_file.read() + + # replace app_dir + content = content.replace("app_dir = Path(__file__).parent.parent", # old value + "app_dir = Path(__file__).parent") # new value + + # write the content to new main file + with open(self.new_main_file, 'w', encoding="utf-8") as main_file: + main_file.write(content) + + def _delete_main_patch_file(self): + if self.new_main_file.exists(): + logging.info(f"[DEPLOY] Removing {self.new_main_file}") + self.new_main_file.unlink() + + @staticmethod + def isDSProject(main_file: Path) -> bool: + return (main_file.parent / 'autogen/settings.py').exists() + + @property + def project_dir(self) -> str: + return self.ds_project_dir + + @property + def ds_source_file(self) -> Path: + return self.new_main_file diff --git a/sources/pyside-tools/deploy_lib/nuitka_helper.py b/sources/pyside-tools/deploy_lib/nuitka_helper.py index f0acfb720..2d46dcf8a 100644 --- a/sources/pyside-tools/deploy_lib/nuitka_helper.py +++ b/sources/pyside-tools/deploy_lib/nuitka_helper.py @@ -11,7 +11,7 @@ import shlex import sys from pathlib import Path -from . import MAJOR_VERSION, run_command +from . import MAJOR_VERSION, DesignStudio, run_command from .config import DesktopConfig @@ -104,14 +104,23 @@ class Nuitka: qml_args = [] if qml_files: - # This will generate options for each file using: - # --include-data-files=ABSOLUTE_PATH_TO_FILE=RELATIVE_PATH_TO ROOT - # for each file. This will preserve the directory structure of QML resources. - qml_args.extend( - [f"--include-data-files={qml_file.resolve()}=" - f"./{qml_file.resolve().relative_to(source_file.resolve().parent)}" - for qml_file in qml_files] - ) + if DesignStudio.isDSProject(source_file): + ds = DesignStudio(source_file) + # include all subdirectories of ds.project_directory as data directories + # this will contain all the qml files and other resources + for subdir in ds.project_dir.iterdir(): + if subdir.is_dir(): + extra_args.append(f"--include-data-dir={subdir}=" + f"./{subdir.name}") + else: + # This will generate options for each file using: + # --include-data-files=ABSOLUTE_PATH_TO_FILE=RELATIVE_PATH_TO ROOT + # for each file. This will preserve the directory structure of QML resources. + qml_args.extend( + [f"--include-data-files={qml_file.resolve()}=" + f"./{qml_file.resolve().relative_to(source_file.resolve().parent)}" + for qml_file in qml_files] + ) # add qml plugin. The `qml`` plugin name is not present in the module json files shipped # with Qt and hence not in `qt_plugins``. However, Nuitka uses the 'qml' plugin name to # include the necessary qml plugins. There we have to add it explicitly for a qml |
