diff options
| author | Cristián Maureira-Fredes <Cristian.Maureira-Fredes@qt.io> | 2024-08-09 16:09:37 +0200 |
|---|---|---|
| committer | Cristián Maureira-Fredes <Cristian.Maureira-Fredes@qt.io> | 2024-08-16 17:13:01 +0200 |
| commit | 141d596d1bcf32314802d4269781d2f005ec2278 (patch) | |
| tree | 2811dbe4ef762a99fd7dd1120fe512f7c2beb5a2 | |
| parent | 1e9ab846e7b59f98b57bd22c17840472619fa85e (diff) | |
pyi: improve findChild/findChildren type hints
Add a TypeVar that's bound to QObject in order to use
it as a generic QObject-based for the returns of
both findChild and findChildren.
Fixes: PYSIDE-2517
Pick-to: 6.7 6.5 6.2
Change-Id: I165cdc391bd7b57df95247202170d6fa9d2aa824
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
4 files changed, 32 insertions, 5 deletions
diff --git a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml index f4559fbfd..2fc68f005 100644 --- a/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml +++ b/sources/pyside6/PySide6/QtCore/typesystem_core_common.xml @@ -1845,7 +1845,7 @@ </inject-documentation> <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-findchild-2"/> - <modify-argument index="return"> + <modify-argument index="return" pyi-type="Optional[PlaceHolderType]"> <parent index="this" action="add"/> </modify-argument> </add-function> @@ -1855,14 +1855,14 @@ Like the method *findChild*, the first parameter should be the child's type. </inject-documentation> <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-findchildren"/> - <modify-argument index="return"> + <modify-argument index="return" pyi-type="Iterable[PlaceHolderType]"> <parent index="this" action="add"/> </modify-argument> </add-function> <add-function signature="findChildren(PyTypeObject*@type@,const QRegularExpression&@pattern@,Qt::FindChildOptions@options@=Qt::FindChildrenRecursively)" return-type="PySequence*" > <inject-code class="target" position="beginning" file="../glue/qtcore.cpp" snippet="qobject-findchildren"/> - <modify-argument index="return"> + <modify-argument index="return" pyi-type="Iterable[PlaceHolderType]"> <parent index="this" action="add"/> </modify-argument> </add-function> diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py index 91ab3ed37..883b85fcd 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py @@ -90,6 +90,11 @@ class Formatter(Writer): optional_searcher = re.compile(pattern, flags=re.VERBOSE) def optional_replacer(source): + # PYSIDE-2517: findChild/findChildren type hints: + # PlaceHolderType fix to avoid the '~' from TypeVar.__repr__ + if "~PlaceHolderType" in str(source): + source = str(source).replace("~PlaceHolderType", "PlaceHolderType") + return optional_searcher.sub(replace, str(source)) self.optional_replacer = optional_replacer # self.level is maintained by enum_sig.py @@ -274,15 +279,23 @@ def generate_pyi(import_name, outpath, options): wr.print("import " + imp) wr.print() for mod, imports in filter_from_imports(FROM_IMPORTS, text): - import_args = ', '.join(imports) + # Sorting, and getting uniques to avoid duplications + # on "Iterable" having a couple of entries. + import_args = ', '.join(sorted(set(imports))) if mod is None: # special case, a normal import wr.print(f"import {import_args}") else: wr.print(f"from {mod} import {import_args}") + # Adding extra typing import for types that are used in + # the followed generated lines + wr.print("from typing import TypeAlias, TypeVar") wr.print() wr.print() wr.print("NoneType: TypeAlias = type[None]") + # We use it only in QtCore at the moment, but this + # could be extended to other modules. + wr.print("PlaceHolderType = TypeVar(\"PlaceHolderType\", bound=QObject)") wr.print() else: wr.print(line) diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py index 3bdd4c1d2..0e94c2bfc 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py @@ -38,6 +38,11 @@ QImageCleanupFunction = typing.Callable # Until we can force it to create Optional[t] again, we use this. NoneType = type(None) +# PYSIDE-2517: findChild/findChildren type hints: +# Placeholder so it does not trigger an UNDEFINED error while building. +# Later it will be bound to a QObject, within the QtCore types extensions +PlaceHolderType = TypeVar("PlaceHolderType") + _S = TypeVar("_S") MultiMap = typing.DefaultDict[str, typing.List[str]] @@ -207,6 +212,7 @@ type_map.update({ "int": int, "List": ArrayLikeVariable, "Optional": typing.Optional, + "Iterable": typing.Iterable, "long": int, "long long": int, "nullptr": None, @@ -463,7 +469,7 @@ def init_smart(): # The PySide Part def init_PySide6_QtCore(): - from PySide6.QtCore import Qt, QUrl, QDir, QKeyCombination + from PySide6.QtCore import Qt, QUrl, QDir, QKeyCombination, QObject from PySide6.QtCore import QRect, QRectF, QSize, QPoint, QLocale, QByteArray from PySide6.QtCore import QMarginsF # 5.9 from PySide6.QtCore import SignalInstance @@ -472,6 +478,7 @@ def init_PySide6_QtCore(): from PySide6.QtCore import Connection except ImportError: pass + type_map.update({ "' '": " ", "'%'": "%", @@ -486,6 +493,8 @@ def init_PySide6_QtCore(): "size_t": int, "NULL": None, # 5.6, MSVC "nullptr": None, # 5.9 + # PYSIDE-2517: findChild/findChildren type hints: + "PlaceHolderType": typing.TypeVar("PlaceHolderType", bound=QObject), "PyBuffer": typing.Union[bytes, bytearray, memoryview], "PyByteArray": bytearray, "PyBytes": typing.Union[bytes, bytearray, memoryview], diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py index 6071dd92c..f3cf6ed51 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py @@ -297,6 +297,11 @@ def to_string(thing): # i.e. it must be an idempotent mapping. if isinstance(thing, str): return thing + # PYSIDE-2517: findChild/findChildren type hints: + # TypeVar doesn't have a __qualname__ attribute, + # so we fall back to use __name__ before the next condition. + if isinstance(thing, typing.TypeVar): + return get_name(thing) if hasattr(thing, "__name__") and thing.__module__ != "typing": m = thing.__module__ dot = "." in str(thing) or m not in (thing.__qualname__, "builtins") |
