From 9c14eb873b5d8029a2d221a09852ef824f3be726 Mon Sep 17 00:00:00 2001 From: Florian Apolloner Date: Mon, 11 Mar 2024 13:16:05 +0100 Subject: [PATCH 1/3] Implement Python 3.12 compatible loader. Fixes #130. --- src/qrc_importer.py | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/src/qrc_importer.py b/src/qrc_importer.py index 1a4a123..db42fbd 100644 --- a/src/qrc_importer.py +++ b/src/qrc_importer.py @@ -16,11 +16,33 @@ # import sys +from importlib import abc +from importlib.util import spec_from_loader + import pyotherside -from importlib import abc + +class PyOtherSideQtRCLoader(abc.Loader): + def __init__(self, filepath): + self.filepath = filepath + + def create_module(self, spec): + return + + def exec_module(self, module): + data = pyotherside.qrc_get_file_contents(self.filepath[len('qrc:') :]) + code = compile(data, self.filepath, 'exec') + exec(code, module.__dict__) + class PyOtherSideQtRCImporter(abc.MetaPathFinder, abc.SourceLoader): + def find_spec(self, fullname, path, target=None): + if path is None: + fname = self.get_filename(fullname) + if fname: + return spec_from_loader(fullname, PyOtherSideQtRCLoader(fname)) + return + def find_module(self, fullname, path): if path is None or all(x.startswith('qrc:') for x in path): if self.get_filename(fullname): From 5d6580c1a3869effecc35bc61abe83bedb8e761b Mon Sep 17 00:00:00 2001 From: Florian Apolloner Date: Tue, 12 Mar 2024 09:19:53 +0100 Subject: [PATCH 2/3] Address review comments. --- .github/workflows/build.yaml | 2 +- README.md | 4 ++-- docs/index.rst | 6 ++++-- src/qrc_importer.py | 17 +++-------------- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/.github/workflows/build.yaml b/.github/workflows/build.yaml index 2f180c8..066a5dd 100644 --- a/.github/workflows/build.yaml +++ b/.github/workflows/build.yaml @@ -28,7 +28,7 @@ jobs: - name: Install dependencies (macOS) if: matrix.os == 'macos-latest' run: | - brew install qt@5 python@3.8 + brew install qt@5 python@3.12 echo PATH=/usr/local/opt/qt@5/bin:$PATH >> ${GITHUB_ENV} - run: qmake - run: make diff --git a/README.md b/README.md index fdaeaf8..b92a771 100644 --- a/README.md +++ b/README.md @@ -11,7 +11,7 @@ Requirements ------------ * Qt 5.1.0 or newer (Qt 6.x also supported) -* Python 3.3.0 or newer +* Python 3.8.0 or newer Building @@ -28,7 +28,7 @@ make install To build against a specific Python version, use: ``` -qmake PYTHON_CONFIG=python3.3-config # use "qmake6" for Qt 6 +qmake PYTHON_CONFIG=python3.8-config # use "qmake6" for Qt 6 make make install ``` diff --git a/docs/index.rst b/docs/index.rst index 6b901b0..06f0d43 100644 --- a/docs/index.rst +++ b/docs/index.rst @@ -1169,7 +1169,7 @@ Building PyOtherSide The following build requirements have to be satisfied to build PyOtherSide: * Qt 5.1.0 or newer (Qt 6.x also supported) -* Python 3.3.0 or newer +* Python 3.8.0 or newer If you have the required build-dependencies installed, building and installing the PyOtherSide plugin should be as simple as: @@ -1185,7 +1185,7 @@ pass a suitable ``python-config`` to ``qmake`` at configure time: .. code-block:: sh - qmake PYTHON_CONFIG=python3.3-config # For Qt 6, use "qmake6" + qmake PYTHON_CONFIG=python3.8-config # For Qt 6, use "qmake6" make make install @@ -1199,6 +1199,8 @@ ChangeLog Version UNRELEASED (YYYY-MM-DD) ------------------------------- +* Dropped support for Python < 3.8 (PR#131) +* Added support for Python 3.12 (PR#131) * Support for Qt 6.5 and newer (backwards-incompatible ``Q_RETURN_ARG()`` change) (fixes #128) Version 1.6.0 (2022-08-05) diff --git a/src/qrc_importer.py b/src/qrc_importer.py index db42fbd..2aa2132 100644 --- a/src/qrc_importer.py +++ b/src/qrc_importer.py @@ -27,7 +27,7 @@ def __init__(self, filepath): self.filepath = filepath def create_module(self, spec): - return + return None def exec_module(self, module): data = pyotherside.qrc_get_file_contents(self.filepath[len('qrc:') :]) @@ -35,18 +35,13 @@ def exec_module(self, module): exec(code, module.__dict__) -class PyOtherSideQtRCImporter(abc.MetaPathFinder, abc.SourceLoader): +class PyOtherSideQtRCImporter(abc.MetaPathFinder): def find_spec(self, fullname, path, target=None): if path is None: fname = self.get_filename(fullname) if fname: return spec_from_loader(fullname, PyOtherSideQtRCLoader(fname)) - return - - def find_module(self, fullname, path): - if path is None or all(x.startswith('qrc:') for x in path): - if self.get_filename(fullname): - return self + return None def get_filename(self, fullname): basename = fullname.replace('.', '/') @@ -60,10 +55,4 @@ def get_filename(self, fullname): if pyotherside.qrc_is_file(filename[len('qrc:'):]): return filename - def get_data(self, path): - return pyotherside.qrc_get_file_contents(path[len('qrc:'):]) - - def module_repr(self, m): - return "".format(m.__name__, m.__file__) - sys.meta_path.append(PyOtherSideQtRCImporter()) From fbd40d4e882fe70fe072f07bb5b9b7c49fb67ea4 Mon Sep 17 00:00:00 2001 From: Florian Apolloner Date: Tue, 12 Mar 2024 09:36:55 +0100 Subject: [PATCH 3/3] Simplify code. --- src/qrc_importer.py | 38 +++++++++++++++++++------------------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/src/qrc_importer.py b/src/qrc_importer.py index 2aa2132..af51a98 100644 --- a/src/qrc_importer.py +++ b/src/qrc_importer.py @@ -22,37 +22,37 @@ import pyotherside -class PyOtherSideQtRCLoader(abc.Loader): +def get_filename(fullname): + basename = fullname.replace(".", "/") + + for import_path in sys.path: + if not import_path.startswith("qrc:"): + continue + + for candidate in ("{}/{}.py", "{}/{}/__init__.py"): + filename = candidate.format(import_path, basename) + if pyotherside.qrc_is_file(filename[len("qrc:") :]): + return filename + + +class PyOtherSideQtRCLoader(abc.SourceLoader): def __init__(self, filepath): self.filepath = filepath - def create_module(self, spec): - return None + def get_data(self, path): + return pyotherside.qrc_get_file_contents(self.filepath[len("qrc:") :]) - def exec_module(self, module): - data = pyotherside.qrc_get_file_contents(self.filepath[len('qrc:') :]) - code = compile(data, self.filepath, 'exec') - exec(code, module.__dict__) + def get_filename(self, fullname): + return get_filename(fullname) class PyOtherSideQtRCImporter(abc.MetaPathFinder): def find_spec(self, fullname, path, target=None): if path is None: - fname = self.get_filename(fullname) + fname = get_filename(fullname) if fname: return spec_from_loader(fullname, PyOtherSideQtRCLoader(fname)) return None - def get_filename(self, fullname): - basename = fullname.replace('.', '/') - - for import_path in sys.path: - if not import_path.startswith('qrc:'): - continue - - for candidate in ('{}/{}.py', '{}/{}/__init__.py'): - filename = candidate.format(import_path, basename) - if pyotherside.qrc_is_file(filename[len('qrc:'):]): - return filename sys.meta_path.append(PyOtherSideQtRCImporter())