diff options
author | Christian Tismer <tismer@stackless.com> | 2021-05-26 19:23:32 +0200 |
---|---|---|
committer | Qt Cherry-pick Bot <cherrypick_bot@qt-project.org> | 2021-06-10 20:18:48 +0000 |
commit | 0695cf877bab98bc654bc264538e3a5f876fa48f (patch) | |
tree | adf5f8522df52fa4e8140bde01b66ee5ecbf8e47 | |
parent | e5dc26940adbe28013e540bfee7395a6a3617cce (diff) |
PyClassProperty: Correct the decorator and publish the class
PyClassProperty is now correctly published as a QtCore class
and existing as an import.
As a side effect, a bug was fixed where a syntax error
occurred because of a missing signature count.
Task-number: PYSIDE-1019
Fixes: PYSIDE-1593
Change-Id: Iae733280d9f9c23244e83a356011104bf527c329
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
(cherry picked from commit 6acc53a4e426fee336a8577581f579d6c173c7bc)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
11 files changed, 66 insertions, 42 deletions
diff --git a/sources/pyside6/libpyside/class_property.cpp b/sources/pyside6/libpyside/class_property.cpp index 35375d0f3..63850be07 100644 --- a/sources/pyside6/libpyside/class_property.cpp +++ b/sources/pyside6/libpyside/class_property.cpp @@ -92,7 +92,7 @@ static PyType_Slot PyClassProperty_slots[] = { }; static PyType_Spec PyClassProperty_spec = { - "PySide6.PyClassProperty", + "PySide6.QtCore.PyClassProperty", sizeof(propertyobject), 0, Py_TPFLAGS_DEFAULT|Py_TPFLAGS_BASETYPE, @@ -148,11 +148,30 @@ static int SbkObjectType_meta_setattro(PyObject *obj, PyObject *name, PyObject * */ namespace PySide { namespace ClassProperty { -void init() +static const char *PyClassProperty_SignatureStrings[] = { + "PySide6.QtCore.PyClassProperty(cls," + "fget:typing.Optional[typing.Callable[[typing.Any],typing.Any]]=None," + "fset:typing.Optional[typing.Callable[[typing.Any,typing.Any],None]]=None," + "fdel:typing.Optional[typing.Callable[[typing.Any],None]]=None," + "doc:typing.Optional[str]=None)" + "->PySide6.QtCore.PyClassProperty", + "PySide6.QtCore.PyClassProperty.getter(cls,fget:typing.Callable[[typing.Any],typing.Any])->PySide6.QtCore.PyClassProperty", + "PySide6.QtCore.PyClassProperty.setter(cls,fset:typing.Callable[[typing.Any,typing.Any],None])->PySide6.QtCore.PyClassProperty", + "PySide6.QtCore.PyClassProperty.deleter(cls,fdel:typing.Callable[[typing.Any],None])->PySide6.QtCore.PyClassProperty", + nullptr}; // Sentinel + +void init(PyObject *module) { PyTypeObject *type = SbkObjectType_TypeF(); type->tp_setattro = SbkObjectType_meta_setattro; Py_TYPE(PyClassPropertyTypeF()) = type; + + if (InitSignatureStrings(PyClassPropertyTypeF(), PyClassProperty_SignatureStrings) < 0) + return; + + Py_INCREF(PyClassPropertyTypeF()); + auto classproptype = reinterpret_cast<PyObject *>(PyClassPropertyTypeF()); + PyModule_AddObject(module, "PyClassProperty", classproptype); } } // namespace ClassProperty diff --git a/sources/pyside6/libpyside/class_property.h b/sources/pyside6/libpyside/class_property.h index f94fdde31..2bf7334a2 100644 --- a/sources/pyside6/libpyside/class_property.h +++ b/sources/pyside6/libpyside/class_property.h @@ -61,7 +61,7 @@ PYSIDE_API PyTypeObject *PyClassPropertyTypeF(); namespace PySide { namespace ClassProperty { -PYSIDE_API void init(); +PYSIDE_API void init(PyObject *module); } // namespace ClassProperty } // namespace PySide diff --git a/sources/pyside6/libpyside/feature_select.cpp b/sources/pyside6/libpyside/feature_select.cpp index 443296f0e..4c80c4ffe 100644 --- a/sources/pyside6/libpyside/feature_select.cpp +++ b/sources/pyside6/libpyside/feature_select.cpp @@ -465,7 +465,6 @@ void init() initSelectableFeature(SelectFeatureSet); registerCleanupFunction(finalize); patch_property_impl(); - PySide::ClassProperty::init(); is_initialized = true; } // Reset the cache. This is called at any "from __feature__ import". diff --git a/sources/pyside6/libpyside/pyside.cpp b/sources/pyside6/libpyside/pyside.cpp index 7efe49b68..a78e4e9eb 100644 --- a/sources/pyside6/libpyside/pyside.cpp +++ b/sources/pyside6/libpyside/pyside.cpp @@ -43,6 +43,7 @@ #include "signalmanager.h" #include "pysideclassinfo_p.h" #include "pysideproperty_p.h" +#include "class_property.h" #include "pysideproperty.h" #include "pysidesignal.h" #include "pysidesignal_p.h" @@ -92,6 +93,7 @@ void init(PyObject *module) Signal::init(module); Slot::init(module); Property::init(module); + ClassProperty::init(module); MetaFunction::init(module); // Init signal manager, so it will register some meta types used by QVariant. SignalManager::instance(); diff --git a/sources/pyside6/libpyside/pysideproperty.cpp b/sources/pyside6/libpyside/pysideproperty.cpp index 6d9769a7e..ea0fba7e5 100644 --- a/sources/pyside6/libpyside/pysideproperty.cpp +++ b/sources/pyside6/libpyside/pysideproperty.cpp @@ -453,15 +453,11 @@ static const char *Property_SignatureStrings[] = { "notify:typing.Callable=None,designable:bool=True,scriptable:bool=True," "stored:bool=True,user:bool=False,constant:bool=False,final:bool=False)" "->PySide6.QtCore.Property", - "PySide6.QtCore.Property.deleter(self,func:typing.Callable)", - "PySide6.QtCore.Property.fdel(self)->typing.Callable", - "PySide6.QtCore.Property.fget(self)->typing.Callable", - "PySide6.QtCore.Property.freset(self)->typing.Callable", - "PySide6.QtCore.Property.fset(self)->typing.Callable", - "PySide6.QtCore.Property.getter(self,func:typing.Callable)", - "PySide6.QtCore.Property.read(self,func:typing.Callable)", - "PySide6.QtCore.Property.setter(self,func:typing.Callable)", - "PySide6.QtCore.Property.write(self,func:typing.Callable)", + "PySide6.QtCore.Property.deleter(self,fdel:typing.Callable)->PySide6.QtCore.Property", + "PySide6.QtCore.Property.getter(self,fget:typing.Callable)->PySide6.QtCore.Property", + "PySide6.QtCore.Property.read(self,fget:typing.Callable)->PySide6.QtCore.Property", + "PySide6.QtCore.Property.setter(self,fset:typing.Callable)->PySide6.QtCore.Property", + "PySide6.QtCore.Property.write(self,fset:typing.Callable)->PySide6.QtCore.Property", nullptr}; // Sentinel void init(PyObject *module) diff --git a/sources/shiboken6/shibokenmodule/Shiboken.pyi b/sources/shiboken6/shibokenmodule/Shiboken.pyi index 84b907aa0..e312f6912 100644 --- a/sources/shiboken6/shibokenmodule/Shiboken.pyi +++ b/sources/shiboken6/shibokenmodule/Shiboken.pyi @@ -47,21 +47,14 @@ Shiboken, except for defaults which are replaced by "...". # Module `Shiboken` -import typing -from typing import Any, Callable, Dict, List, Optional, Tuple, Union from shiboken6 import Shiboken -from shibokensupport.signature.mapping import ( - Virtual, Missing, Invalid, Default, Instance) -class Enum(object): - - def __init__(self, itemValue: int = ...) -> None: ... - class Object(object): def __init__(self) -> None: ... + class VoidPtr(object): ... diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py index cb28874fb..2fd2b6c4f 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py @@ -236,7 +236,7 @@ def create_signature(props, key): # parser. pass else: - if "self" in varnames[:1]: + if varnames[0] in ("self", "cls"): varnames = varnames[1:] # calculate the modifications @@ -256,7 +256,7 @@ def create_signature(props, key): elif name.startswith("*"): kind = _VAR_POSITIONAL ann = annotations.get(name, _empty) - if ann == "self": + if ann in ("self", "cls"): ann = _empty name = name.lstrip("*") defpos = idx - len(varnames) + len(defaults) diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py index c94dd94bb..28898deb1 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py @@ -119,7 +119,7 @@ class ExactEnumerator(object): bases_list = [] for base in klass.__bases__: name = base.__name__ - if name not in ("object", "type"): + if name not in ("object", "property", "type"): name = base.__module__ + "." + name bases_list.append(name) bases_str = ', '.join(bases_list) @@ -147,21 +147,26 @@ class ExactEnumerator(object): init_signature = getattr(klass, "__signature__", None) enums.sort(key=lambda tup: tup[1 : 3]) # sort by class then enum value - self.fmt.have_body = bool(subclasses or functions or enums or init_signature) # We want to handle functions and properties together. func_prop = sorted(functions + properties, key=lambda tup: tup[0]) + # find out how many functions create a signature + sigs = list(_ for _ in functions if hasattr(_[1], "__signature__") and _[1].__signature__) + self.fmt.have_body = bool(subclasses or sigs or properties or enums or init_signature) + with self.fmt.klass(class_name, class_str): self.fmt.level += 1 self.fmt.class_name = class_name if hasattr(self.fmt, "enum"): # this is an optional feature + if len(enums): + self.section() for enum_name, enum_class_name, value in enums: with self.fmt.enum(enum_class_name, enum_name, int(value)): pass - if len(enums): - self.section() + if len(subclasses): + self.section() for subclass_name, subclass in subclasses: ret.update(self.klass(subclass_name, subclass)) self.fmt.class_name = class_name @@ -253,11 +258,12 @@ class HintingEnumerator(ExactEnumerator): # Class properties don't have signature support (yet). # In that case, produce a fake one. sig = get_sig(func, "hintingstub") - if decorator and not sig: - if decorator.endswith(".setter"): - sig = self.setter_sig - elif decorator.endswith(".deleter"): - sig = self.deleter_sig - else: - sig = self.getter_sig + if not sig: + if decorator: + if decorator.endswith(".setter"): + sig = self.setter_sig + elif decorator.endswith(".deleter"): + sig = self.deleter_sig + else: + sig = self.getter_sig return sig 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 f81e738b2..3c4efebda 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 @@ -146,7 +146,6 @@ class Formatter(Writer): from shiboken6 import Shiboken - import typing <<IMPORTS>> """ self.print(dedent(txt)) @@ -158,7 +157,6 @@ class Formatter(Writer): while "." in class_name: class_name = class_name.split(".", 1)[-1] class_str = class_str.split(".", 1)[-1] - here = self.outfile.tell() if self.have_body: self.print(f"{spaces}class {class_str}:") else: @@ -173,7 +171,7 @@ class Formatter(Writer): spaces = indent * self.level if isinstance(signature, list): for sig in signature: - self.print(f'{spaces}@typing.overload') + self.print(f'{spaces}@overload') self._function(func_name, sig, spaces) else: self._function(func_name, signature, spaces, decorator) @@ -183,8 +181,9 @@ class Formatter(Writer): def _function(self, func_name, signature, spaces, decorator=None): if decorator: + # In case of a PyClassProperty the classmethod decorator is not used. self.print(f'{spaces}@{decorator}') - if self.is_method() and "self" not in signature.parameters: + elif self.is_method() and "self" not in signature.parameters: kind = "class" if "cls" in signature.parameters else "static" self.print(f'{spaces}@{kind}method') signature = self.optional_replacer(signature) @@ -211,8 +210,8 @@ def find_imports(text): FROM_IMPORTS = [ - ("typing", "Any Callable Dict List Optional Tuple Union".split()), - ("PySide6", ["PyClassProperty"]), + ("typing", "Any Callable Dict List Optional overload Tuple Union".split()), + ("PySide6.QtCore", ["PyClassProperty"]), ] def filter_from_imports(from_struct, text): diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py index af78ed309..be96a7689 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py @@ -352,9 +352,19 @@ type_map.update({ "QStringList*" : ResultVariable(StringList), }) + +type_map.update({ + # Hack, until improving the parser: + "[typing.Any]" : [typing.Any], + "[typing.Any,typing.Any]" : [typing.Any, typing.Any], + "None" : None, + }) + + # PYSIDE-1328: We need to handle "self" explicitly. type_map.update({ - "self" : "self", + "self" : "self", + "cls" : "cls", }) # PYSIDE-1538: We need to treat "std::optional" accordingly. diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py index 047ce6c4b..788aaaa0d 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py @@ -113,7 +113,7 @@ def _parse_line(line): for idx, arg in enumerate(arglist): tokens = arg.split(":") if len(tokens) < 2: - if idx == 0 and tokens[0] == "self": + if idx == 0 and tokens[0] in ("self", "cls"): tokens = 2 * tokens # "self: self" else: # This should never happen again (but who knows?) |