aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChristian Tismer <tismer@stackless.com>2019-09-21 18:34:13 +0200
committerChristian Tismer <tismer@stackless.com>2019-09-28 00:15:57 +0200
commitb4989b9c2b33772f23dd5f9763622e6fd3cf41a8 (patch)
treefee1717e5d8bdb1267ed7f7432fc09be67c6b024
parent94023741a3d0377b5a39914646bc06b06f6fa548 (diff)
Enable the Function Registry for 5.14
The function registry was not enabled for versions greater than 5.12 . This is now needed, since the function registry will be used in the tests for the improved NumPy support. There were new cases of Python keywords touched by enums which had to be renamed. This was moved into the code generator instead of the runtime overhead. The formatting of the enums was rewritten and reports all enums now that can be found (also those which are copied into the parent class). The formatting of the function registry had not been used for a long time and had entries that showed the wrong number of subclasses. The usage of the registry was also simplified by using the full names of functions. They can now directly be accessed. Task-number: PYSIDE-795 Change-Id: I734f6811205f3c3528a911975677eb677fedd2dd Reviewed-by: Friedemann Kleint <Friedemann.Kleint@qt.io>
-rw-r--r--sources/pyside2/PySide2/support/generate_pyi.py11
-rw-r--r--sources/pyside2/tests/registry/existence_test.py14
-rw-r--r--sources/pyside2/tests/registry/init_platform.py26
-rw-r--r--sources/pyside2/tests/registry/util.py2
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp17
-rw-r--r--sources/shiboken2/libshiboken/sbkenum.cpp7
-rw-r--r--sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py63
7 files changed, 74 insertions, 66 deletions
diff --git a/sources/pyside2/PySide2/support/generate_pyi.py b/sources/pyside2/PySide2/support/generate_pyi.py
index d5bbe5d7c..e60645701 100644
--- a/sources/pyside2/PySide2/support/generate_pyi.py
+++ b/sources/pyside2/PySide2/support/generate_pyi.py
@@ -161,14 +161,11 @@ class Formatter(Writer):
if self.level == 0:
self.print()
here = self.outfile.tell()
- self.print("{spaces}class {class_str}:".format(**locals()))
- pos = self.outfile.tell()
- yield
- if pos == self.outfile.tell():
- # we have not written any function
- self.outfile.seek(here)
- self.outfile.truncate()
+ if self.have_body:
+ self.print("{spaces}class {class_str}:".format(**locals()))
+ else:
self.print("{spaces}class {class_str}: ...".format(**locals()))
+ yield
if "<" in class_name:
# This is happening in QtQuick for some reason:
## class QSharedPointer<QQuickItemGrabResult >:
diff --git a/sources/pyside2/tests/registry/existence_test.py b/sources/pyside2/tests/registry/existence_test.py
index fd81901b4..f5f614d04 100644
--- a/sources/pyside2/tests/registry/existence_test.py
+++ b/sources/pyside2/tests/registry/existence_test.py
@@ -103,8 +103,10 @@ except SyntaxError:
print("*** not a python file, removed:", shortpath)
os.unlink(effectiveRefPath)
have_refmodule = False
-if have_refmodule and not hasattr(sig_exists, "dict"):
- print("*** wrong module without 'dict', removed:", shortpath)
+dict_name = "sig_dict"
+if have_refmodule and not hasattr(sig_exists, dict_name):
+ print("*** wrong module without '{dict_name}', removed:"
+ .format(**locals()), shortpath)
os.unlink(effectiveRefPath)
have_refmodule = False
@@ -129,12 +131,12 @@ class TestSignaturesExists(unittest.TestCase):
"Actual {len_act} {actual} vs. expected {len_exp} {expect}')"
.format(**locals()))
- for key, value in sig_exists.dict.items():
+ for key, value in sig_exists.sig_dict.items():
name = key.rsplit(".", 1)[-1]
if name in ("next", "__next__"): # ignore problematic cases
continue
if key not in found_sigs:
- warn("missing key: '{}'".format(key))
+ warn("missing key: '{}'".format(key), stacklevel=3)
else:
found_val = found_sigs[key]
if type(value) is list and (
@@ -142,7 +144,7 @@ class TestSignaturesExists(unittest.TestCase):
len(found_val) < len(value)):
# We check that nothing got lost. But it is ok when an older
# registry file does not know all variants, yet!
- warn(multi_signature_msg(key, found_val, value))
+ warn(multi_signature_msg(key, found_val, value), stacklevel=3)
def test_signatures(self):
found_sigs = enum_all()
@@ -206,7 +208,7 @@ class TestSignaturesExists(unittest.TestCase):
self.assertFalse(check_warnings(), "you ignore when arity got bigger")
-tested_versions = (5, 6), (5, 9), (5, 11), (5, 12)
+tested_versions = (5, 6), (5, 9), (5, 11), (5, 12), (5, 14)
if not have_refmodule and is_ci and qt_version()[:2] in tested_versions:
class TestFor_CI_Init(unittest.TestCase):
diff --git a/sources/pyside2/tests/registry/init_platform.py b/sources/pyside2/tests/registry/init_platform.py
index 31e212287..1c4261b4b 100644
--- a/sources/pyside2/tests/registry/init_platform.py
+++ b/sources/pyside2/tests/registry/init_platform.py
@@ -1,6 +1,6 @@
#############################################################################
##
-## Copyright (C) 2018 The Qt Company Ltd.
+## Copyright (C) 2019 The Qt Company Ltd.
## Contact: https://www.qt.io/licensing/
##
## This file is part of Qt for Python.
@@ -201,39 +201,41 @@ class Formatter(object):
"""
def __init__(self, outfile):
self.outfile = outfile
+ self.last_level = 0
def print(self, *args, **kw):
print(*args, file=self.outfile, **kw) if self.outfile else None
@contextmanager
def module(self, mod_name):
- self.mod_name = mod_name
self.print("")
self.print("# Module", mod_name)
- self.print('if "{}" in sys.modules:'.format(mod_name))
- self.print(" dict.update({")
+ self.print("sig_dict.update({")
yield
- self.print(" })")
+ self.print(' }}) if "{mod_name}" in sys.modules else None'.format(**locals()))
@contextmanager
def klass(self, class_name, class_str):
- self.class_name = class_name
self.print()
- self.print(" # class {}.{}:".format(self.mod_name, class_name))
+ self.print("# class {self.mod_name}.{class_name}:".format(**locals()))
yield
@contextmanager
def function(self, func_name, signature):
- if self.class_name is None:
- key = viskey = "{}".format(func_name)
+ if self.last_level > self.level:
+ self.print()
+ self.last_level = self.level
+ class_name = self.class_name
+ if class_name is None:
+ key = viskey = "{self.mod_name}.{func_name}".format(**locals())
else:
- key = viskey = "{}.{}".format(self.class_name, func_name)
+ key = viskey = "{self.mod_name}.{class_name}.{func_name}".format(**locals())
if key.endswith("lY"):
# Some classes like PySide2.QtGui.QContextMenuEvent have functions
# globalX and the same with Y. The gerrit robot thinks that this
# is a badly written "globally". Convince it by hiding this word.
viskey = viskey[:-1] + '""Y'
- self.print(' "{}": {},'.format(viskey, signature))
+ self.print(' "{viskey}": {signature},'.format(**locals()))
yield key
@@ -268,7 +270,7 @@ def generate_all():
'''.format(module)))
fmt.print("import sys")
fmt.print("")
- fmt.print("dict = {}")
+ fmt.print("sig_dict = {}")
for mod_name in all_modules:
enu.module(mod_name)
fmt.print("# eof")
diff --git a/sources/pyside2/tests/registry/util.py b/sources/pyside2/tests/registry/util.py
index 415b8aa45..3033608e6 100644
--- a/sources/pyside2/tests/registry/util.py
+++ b/sources/pyside2/tests/registry/util.py
@@ -91,7 +91,7 @@ def check_warnings():
return True
return False
-def warn(message, category=None, stacklevel=1):
+def warn(message, category=None, stacklevel=2):
"""Issue a warning with the default 'RuntimeWarning'"""
if category is None:
category = UserWarning
diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
index a2b67b91b..85ce8f954 100644
--- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
+++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp
@@ -4611,6 +4611,15 @@ void CppGenerator::writeEnumsInitialization(QTextStream &s, AbstractMetaEnumList
}
}
+static QString mangleName(QString name)
+{
+ if ( name == QLatin1String("None")
+ || name == QLatin1String("False")
+ || name == QLatin1String("True"))
+ name += QLatin1Char('_');
+ return name;
+}
+
void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnum *cppEnum)
{
const AbstractMetaClass *enclosingClass = getProperEnclosingClassForEnum(cppEnum);
@@ -4690,7 +4699,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
Indentation indent(INDENT);
s << INDENT << "PyObject *anonEnumItem = PyInt_FromLong(" << enumValueText << ");" << endl;
s << INDENT << "if (PyDict_SetItemString(reinterpret_cast<PyTypeObject *>(reinterpret_cast<SbkObjectType *>(" << enclosingObjectVariable
- << "))->tp_dict, \"" << enumValue->name() << "\", anonEnumItem) < 0)" << endl;
+ << "))->tp_dict, \"" << mangleName(enumValue->name()) << "\", anonEnumItem) < 0)" << endl;
{
Indentation indent(INDENT);
s << INDENT << returnStatement(m_currentErrorCode) << endl;
@@ -4699,7 +4708,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
}
s << INDENT << '}' << endl;
} else {
- s << INDENT << "if (PyModule_AddIntConstant(module, \"" << enumValue->name() << "\", ";
+ s << INDENT << "if (PyModule_AddIntConstant(module, \"" << mangleName(enumValue->name()) << "\", ";
s << enumValueText << ") < 0)" << endl;
{
Indentation indent(INDENT);
@@ -4712,7 +4721,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem");
s << '(' << enumVarTypeObj << ',' << endl;
Indentation indent(INDENT);
- s << INDENT << enclosingObjectVariable << ", \"" << enumValue->name() << "\", ";
+ s << INDENT << enclosingObjectVariable << ", \"" << mangleName(enumValue->name()) << "\", ";
s << enumValueText << "))" << endl;
s << INDENT << returnStatement(m_currentErrorCode) << endl;
}
@@ -4721,7 +4730,7 @@ void CppGenerator::writeEnumInitialization(QTextStream &s, const AbstractMetaEnu
s << INDENT << "if (!Shiboken::Enum::createScopedEnumItem("
<< enumVarTypeObj << ',' << endl;
Indentation indent(INDENT);
- s << INDENT << enumVarTypeObj<< ", \"" << enumValue->name() << "\", "
+ s << INDENT << enumVarTypeObj<< ", \"" << mangleName(enumValue->name()) << "\", "
<< enumValueText << "))" << endl
<< INDENT << returnStatement(m_currentErrorCode) << endl;
}
diff --git a/sources/shiboken2/libshiboken/sbkenum.cpp b/sources/shiboken2/libshiboken/sbkenum.cpp
index 2dc785884..71fcf5f64 100644
--- a/sources/shiboken2/libshiboken/sbkenum.cpp
+++ b/sources/shiboken2/libshiboken/sbkenum.cpp
@@ -412,13 +412,6 @@ PyTypeObject *createScopedEnum(SbkObjectType *scope, const char *name, const cha
static PyObject *createEnumItem(PyTypeObject *enumType, const char *itemName, long itemValue)
{
- char mangled[20];
- if (strcmp(itemName, "None") == 0
- || strcmp(itemName, "False") == 0 || strcmp(itemName, "True") == 0) {
- strcpy(mangled, itemName);
- strcat(mangled, "_");
- itemName = mangled;
- }
PyObject *enumItem = newItem(enumType, itemValue, itemName);
if (PyDict_SetItemString(enumType->tp_dict, itemName, enumItem) < 0)
return nullptr;
diff --git a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
index b84a20e16..2e4d67186 100644
--- a/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
+++ b/sources/shiboken2/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py
@@ -84,6 +84,7 @@ class ExactEnumerator(object):
def module(self, mod_name):
__import__(mod_name)
+ self.fmt.mod_name = mod_name
with self.fmt.module(mod_name):
module = sys.modules[mod_name]
members = inspect.getmembers(module, inspect.isclass)
@@ -93,7 +94,7 @@ class ExactEnumerator(object):
for class_name, klass in members:
ret.update(self.klass(class_name, klass))
if isinstance(klass, EnumType):
- self.enum(klass)
+ raise SystemError("implement enum instances at module level")
for func_name, func in functions:
ret.update(self.function(func_name, func))
return ret
@@ -114,26 +115,41 @@ class ExactEnumerator(object):
name = modname + "." + base.__name__
bases_list.append(name)
class_str = "{}({})".format(class_name, ", ".join(bases_list))
- with self.fmt.klass(class_name, class_str):
- ret = self.result_type()
- # class_members = inspect.getmembers(klass)
- # gives us also the inherited things.
- class_members = sorted(list(klass.__dict__.items()))
- subclasses = []
- functions = []
- for thing_name, thing in class_members:
- if inspect.isclass(thing):
- subclass_name = ".".join((class_name, thing_name))
- subclasses.append((subclass_name, thing))
- elif inspect.isroutine(thing):
- func_name = thing_name.split(".")[0] # remove ".overload"
+ ret = self.result_type()
+ # class_members = inspect.getmembers(klass)
+ # gives us also the inherited things.
+ class_members = sorted(list(klass.__dict__.items()))
+ subclasses = []
+ functions = []
+ enums = []
+
+ for thing_name, thing in class_members:
+ if inspect.isclass(thing):
+ subclass_name = ".".join((class_name, thing_name))
+ subclasses.append((subclass_name, thing))
+ elif inspect.isroutine(thing):
+ func_name = thing_name.split(".")[0] # remove ".overload"
+ signature = getattr(thing, "__signature__", None)
+ if signature is not None:
functions.append((func_name, thing))
+ elif type(type(thing)) is EnumType:
+ enums.append((thing_name, thing))
+ init_signature = getattr(klass, "__signature__", None)
+ enums.sort(key=lambda tup: tup[1]) # sort by enum value
+ self.fmt.have_body = bool(subclasses or functions 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
+ for enum_name, value in enums:
+ with self.fmt.enum(class_name, enum_name, int(value)):
+ pass
for subclass_name, subclass in subclasses:
ret.update(self.klass(subclass_name, subclass))
- if isinstance(subclass, EnumType):
- self.enum(subclass)
- ret = self.function("__init__", klass)
+ self.fmt.class_name = class_name
+ ret.update(self.function("__init__", klass))
for func_name, func in functions:
func_kind = get_signature(func, "__func_kind__")
modifier = func_kind if func_kind in (
@@ -145,24 +161,13 @@ class ExactEnumerator(object):
def function(self, func_name, func, modifier=None):
self.fmt.level += 1
ret = self.result_type()
- signature = getattr(func, '__signature__', None)
+ signature = func.__signature__
if signature is not None:
with self.fmt.function(func_name, signature, modifier) as key:
ret[key] = signature
self.fmt.level -= 1
return ret
- def enum(self, subclass):
- if not hasattr(self.fmt, "enum"):
- # this is an optional feature
- return
- class_name = subclass.__name__
- for enum_name, value in subclass.__dict__.items():
- if type(type(value)) is EnumType:
- with self.fmt.enum(class_name, enum_name, int(value)):
- pass
- self._after_enum = True
-
def stringify(signature):
if isinstance(signature, list):