diff options
| -rw-r--r-- | sources/pyside6/PySide6/__init__.py.in | 17 | ||||
| -rw-r--r-- | sources/pyside6/tests/pysidetest/all_modules_load_test.py | 12 | ||||
| -rw-r--r-- | sources/shiboken6/libshiboken/sbkmodule.cpp | 25 | ||||
| -rw-r--r-- | sources/shiboken6/libshiboken/sbkmodule.h | 5 | ||||
| -rw-r--r-- | sources/shiboken6/shibokenmodule/shibokenmodule.cpp | 5 | ||||
| -rw-r--r-- | sources/shiboken6/shibokenmodule/typesystem_shiboken.xml | 4 |
6 files changed, 66 insertions, 2 deletions
diff --git a/sources/pyside6/PySide6/__init__.py.in b/sources/pyside6/PySide6/__init__.py.in index 5dc80c7aa..ca3b7fc6a 100644 --- a/sources/pyside6/PySide6/__init__.py.in +++ b/sources/pyside6/PySide6/__init__.py.in @@ -1,6 +1,8 @@ import os import sys from pathlib import Path +from types import ModuleType +# mypy: disable-error-code="name-defined" # __all__ is computed below. __pre_all__ = [@init_modules@] @@ -60,6 +62,7 @@ def _setupQtDirectories(): try: # PYSIDE-1497: we use the build dir or install dir or site-packages, whatever the path # setting dictates. There is no longer a difference in path structure. + global Shiboken from shiboken6 import Shiboken except Exception: paths = ', '.join(sys.path) @@ -121,4 +124,18 @@ def __getattr__(name: str) -> list[str]: raise AttributeError(f"module '{__name__}' has no attribute '{name}' :)") +# Be prepared that people can access the module dict instead. +class ModuleDict(dict): + def __missing__(self, key): + if key == "__all__": + self[key] = __all__ if "__all__" in globals() else __getattr__("__all__") + return __all__ + raise KeyError(f"dict of module '{__name__}' has no key '{key}' :)") + + +class SubModule(ModuleType): + pass + + _setupQtDirectories() +Shiboken.replaceModuleDict(sys.modules["PySide6"], SubModule, ModuleDict(globals())) diff --git a/sources/pyside6/tests/pysidetest/all_modules_load_test.py b/sources/pyside6/tests/pysidetest/all_modules_load_test.py index 16f2369a7..6b3ebe732 100644 --- a/sources/pyside6/tests/pysidetest/all_modules_load_test.py +++ b/sources/pyside6/tests/pysidetest/all_modules_load_test.py @@ -13,18 +13,26 @@ init_test_paths(False) import PySide6 + # Note: # "from PySide6 import *" can only be used at module level. # It is also really not recommended to use. But for testing, # the "__all__" variable is a great feature! - - class AllModulesImportTest(unittest.TestCase): def testAllModulesCanImport(self): # would also work: exec("from PySide6 import *") for name in PySide6.__all__: exec(f"import PySide6.{name}") + def testAllReappearsAfterDel(self): + # This is the only incompatibility that remains: + # After __all__ is deleted, it will re-appear. + PySide6.__all__ = 42 + self.assertEqual(PySide6.__dict__["__all__"], 42) + del PySide6.__all__ + self.assertTrue(PySide6.__dict__["__all__"]) + self.assertNotEqual(PySide6.__dict__["__all__"], 42) + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken6/libshiboken/sbkmodule.cpp b/sources/shiboken6/libshiboken/sbkmodule.cpp index 202bd27bd..f254cdfd1 100644 --- a/sources/shiboken6/libshiboken/sbkmodule.cpp +++ b/sources/shiboken6/libshiboken/sbkmodule.cpp @@ -539,4 +539,29 @@ SbkConverter **getTypeConverters(PyObject *module) return (iter == moduleConverters.end()) ? 0 : iter->second; } +// Replace the dictionary of a module by a different dict. +// The dict should be filled with the content of the old dict, before. +// Reason: Creating a module dict with __missing__ support. +typedef struct { + PyObject_HEAD + PyObject *md_dict; +} StartOf_PyModuleObject; + +bool replaceModuleDict(PyObject *module, PyObject *modClass, PyObject *dict) +{ + if (!(PyModule_Check(module) && PyType_Check(modClass) && PyDict_Check(dict))) + return false; + auto *modict = PyModule_GetDict(module); + auto *modIntern = reinterpret_cast<StartOf_PyModuleObject *>(module); + if (modict != modIntern->md_dict) + Py_FatalError("The layout of modules is incompatible"); + auto *hold = modIntern->md_dict; + modIntern->md_dict = dict; + Py_INCREF(dict); + Py_DECREF(hold); + Py_INCREF(modClass); + module->ob_type = reinterpret_cast<PyTypeObject *>(modClass); + return true; +} + } } // namespace Shiboken::Module diff --git a/sources/shiboken6/libshiboken/sbkmodule.h b/sources/shiboken6/libshiboken/sbkmodule.h index 2c407e09d..ac77604b8 100644 --- a/sources/shiboken6/libshiboken/sbkmodule.h +++ b/sources/shiboken6/libshiboken/sbkmodule.h @@ -84,6 +84,11 @@ LIBSHIBOKEN_API void registerTypeConverters(PyObject *module, SbkConverter **con */ LIBSHIBOKEN_API SbkConverter **getTypeConverters(PyObject *module); +/** + * Replace the dictionary of a module. This allows to use `__missing__`. + */ +LIBSHIBOKEN_API bool replaceModuleDict(PyObject *module, PyObject *modClass, PyObject *dict); + } // namespace Shiboken::Module #endif // SBK_MODULE_H diff --git a/sources/shiboken6/shibokenmodule/shibokenmodule.cpp b/sources/shiboken6/shibokenmodule/shibokenmodule.cpp index 5c6219885..16cb0fcd3 100644 --- a/sources/shiboken6/shibokenmodule/shibokenmodule.cpp +++ b/sources/shiboken6/shibokenmodule/shibokenmodule.cpp @@ -75,6 +75,11 @@ if (!Shiboken::Object::checkType(%1)) { } // @snippet dump +// @snippet replacemoduledict +const bool ok = Shiboken::Module::replaceModuleDict(%1, %2, %3); +%PYARG_0 = %CONVERTTOPYTHON[bool](ok); +// @snippet replacemoduledict + // @snippet getallvalidwrappers const auto setAll = Shiboken::BindingManager::instance().getAllPyObjects(); PyObject* listAll = PyList_New(0); diff --git a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml index acb522ecc..851f4ef61 100644 --- a/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml +++ b/sources/shiboken6/shibokenmodule/typesystem_shiboken.xml @@ -41,6 +41,10 @@ <inject-code file="shibokenmodule.cpp" snippet="disassembleframe"/> </add-function> + <add-function signature="replaceModuleDict(PyObject*, PyObject*, PyObject*)" return-type="bool"> + <inject-code file="shibokenmodule.cpp" snippet="replacemoduledict"/> + </add-function> + <add-function signature="dump(PyObject*)" return-type="const char *"> <inject-code file="shibokenmodule.cpp" snippet="dump"/> </add-function> |
