aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/shibokenmodule/files.dir/shibokensupport
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/shibokenmodule/files.dir/shibokensupport')
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__feature__.py187
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__init__.py40
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py248
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py47
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject16
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/__init__.py40
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py87
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py44
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py78
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/__init__.py40
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/enum_sig.py228
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py334
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py80
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py189
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py326
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py250
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json2
17 files changed, 1270 insertions, 966 deletions
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__feature__.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__feature__.py
deleted file mode 100644
index 0fa58d22f..000000000
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__feature__.py
+++ /dev/null
@@ -1,187 +0,0 @@
-#############################################################################
-##
-## Copyright (C) 2020 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
-
-"""
-__feature__.py
-
-This is the feature file for the Qt for Python project. There is some
-similarity to Python's `__future__` file, but also some distinction.
-
-The normal usage is like
-
- from __feature__ import <feature_name> [, ...]
- ...
-
-Alternatively, there is the `set_selection` function which uses select_id's
-and takes an optional `mod_name` parameter.
-
-The select id `-1` has the spectial meaning "ignore this module".
-"""
-
-import sys
-
-all_feature_names = [
- "snake_case",
- "true_property",
- "_feature_04",
- "_feature_08",
- "_feature_10",
- "_feature_20",
- "_feature_40",
- "_feature_80",
-]
-
-__all__ = ["all_feature_names", "set_selection", "info"] + all_feature_names
-
-snake_case = 0x01
-true_property = 0x02
-_feature_04 = 0x04
-_feature_08 = 0x08
-_feature_10 = 0x10
-_feature_20 = 0x20
-_feature_40 = 0x40
-_feature_80 = 0x80
-
-# let's remove the dummies for the normal user
-_really_all_feature_names = all_feature_names[:]
-all_feature_names = list(_ for _ in all_feature_names if not _.startswith("_"))
-
-# Install an import hook that controls the `__feature__` import.
-"""
-Note: This are two imports.
->>> import dis
->>> def test():
-... from __feature__ import snake_case
-...
->>> dis.dis(test)
- 2 0 LOAD_CONST 1 (0)
- 2 LOAD_CONST 2 (('snake_case',))
- 4 IMPORT_NAME 0 (__feature__)
- 6 IMPORT_FROM 1 (snake_case)
- 8 STORE_FAST 0 (snake_case)
- 10 POP_TOP
- 12 LOAD_CONST 0 (None)
- 14 RETURN_VALUE
-"""
-# XXX build an improved C version? I guess not.
-def _import(name, *args, **kwargs):
- # PYSIDE-1368: The `__name__` attribute does not need to exist in all modules.
- # PYSIDE-1398: sys._getframe(1) may not exist when embedding.
- calling_frame = _cf = sys._getframe().f_back
- importing_module = _cf.f_globals.get("__name__", "__main__") if _cf else "__main__"
- existing = pyside_feature_dict.get(importing_module, 0)
-
- if name == "__feature__" and args[2]:
- __init__()
-
- # This is an `import from` statement that corresponds to `IMPORT_NAME`.
- # The following `IMPORT_FROM` will handle errors. (Confusing, ofc.)
- flag = 0
- for feature in args[2]:
- if feature in _really_all_feature_names:
- flag |= globals()[feature]
- else:
- raise SyntaxError(f"PySide feature {feature} is not defined")
-
- flag |= existing & 255 if isinstance(existing, int) and existing >= 0 else 0
- pyside_feature_dict[importing_module] = flag
-
- if importing_module == "__main__":
- # We need to add all modules here which should see __feature__.
- pyside_feature_dict["rlcompleter"] = flag
-
- # Initialize feature (multiple times allowed) and clear cache.
- sys.modules["PySide6.QtCore"].__init_feature__()
- return sys.modules["__feature__"]
-
- if name.split(".")[0] == "PySide6":
- # This is a module that imports PySide6.
- flag = existing if isinstance(existing, int) else 0
- else:
- # This is some other module. Ignore it in switching.
- flag = -1
- pyside_feature_dict[importing_module] = flag
- return original_import(name, *args, **kwargs)
-
-_is_initialized = False
-
-def __init__():
- global _is_initialized
- if not _is_initialized:
- # use _one_ recursive import...
- import PySide6.QtCore
- # Initialize all prior imported modules
- for name in sys.modules:
- pyside_feature_dict.setdefault(name, -1)
-
-
-def set_selection(select_id, mod_name=None):
- """
- Internal use: Set the feature directly by Id.
- Id == -1: ignore this module in switching.
- """
- mod_name = mod_name or sys._getframe(1).f_globals['__name__']
- __init__()
- # Reset the features to the given id
- flag = 0
- if isinstance(select_id, int):
- flag = select_id & 255
- pyside_feature_dict[mod_name] = flag
- sys.modules["PySide6.QtCore"].__init_feature__()
- return _current_selection(flag)
-
-
-def info(mod_name=None):
- """
- Internal use: Return the current selection
- """
- mod_name = mod_name or sys._getframe(1).f_globals['__name__']
- flag = pyside_feature_dict.get(mod_name, 0)
- return _current_selection(flag)
-
-
-def _current_selection(flag):
- names = []
- if flag >= 0:
- for idx, name in enumerate(_really_all_feature_names):
- if (1 << idx) & flag:
- names.append(name)
- return names
-
-#eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__init__.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__init__.py
index 2d640cb89..e54bec75a 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__init__.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/__init__.py
@@ -1,40 +1,4 @@
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
# this file intentionally left blank
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py
new file mode 100644
index 000000000..7a0871ee7
--- /dev/null
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/feature.py
@@ -0,0 +1,248 @@
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+# flake8: noqa F:821
+# flake8: noqa F:401
+
+"""
+__feature__.py (renamed to feature.py)
+
+This is the feature file for the Qt for Python project. There is some
+similarity to Python's `__future__` file, but also some distinction.
+
+The normal usage is like
+
+ from __feature__ import <feature_name> [, ...]
+ ...
+
+Alternatively, there is the `set_selection` function which uses select_id's
+and takes an optional `mod_name` parameter.
+
+The select id `-1` has the special meaning "ignore this module".
+"""
+
+import inspect
+import sys
+from contextlib import contextmanager
+
+all_feature_names = [
+ "snake_case",
+ "true_property",
+ "_feature_04",
+ "_feature_08",
+ "_feature_10",
+ "_feature_20",
+ "_feature_40",
+ "_feature_80",
+]
+
+__all__ = ["all_feature_names", "info", "reset", "set_selection"] + all_feature_names
+
+snake_case = 0x01
+true_property = 0x02
+_feature_04 = 0x04
+_feature_08 = 0x08
+_feature_10 = 0x10
+_feature_20 = 0x20
+_feature_40 = 0x40
+_feature_80 = 0x80
+
+# let's remove the dummies for the normal user
+_really_all_feature_names = all_feature_names[:]
+all_feature_names = list(_ for _ in all_feature_names if not _.startswith("_"))
+
+# Install an import hook that controls the `__feature__` import.
+"""
+Note: This are two imports.
+>>> import dis
+>>> def test():
+... from __feature__ import snake_case
+...
+>>> dis.dis(test)
+ 2 0 LOAD_CONST 1 (0)
+ 2 LOAD_CONST 2 (('snake_case',))
+ 4 IMPORT_NAME 0 (__feature__)
+ 6 IMPORT_FROM 1 (snake_case)
+ 8 STORE_FAST 0 (snake_case)
+ 10 POP_TOP
+ 12 LOAD_CONST 0 (None)
+ 14 RETURN_VALUE
+"""
+
+"""
+The redirection of __import__
+-----------------------------
+
+This construction avoids irritating extra redirections in tracebacks.
+
+The normal `__import__` is replaced by C function `__feature_import__`.
+`__feature_import__` calls this `feature_import` function first, to
+see if a feature is requested. If this function does not handle it, it returns
+None to indicate that a normal import should be performed, and
+`__feature_import__` calls the original import `__orig_import__`.
+All these variables are transparently kept in module `builtins`.
+"""
+
+
+def feature_import(name, *args, **kwargs):
+ # PYSIDE-1368: The `__name__` attribute does not need to exist in all modules.
+ # PYSIDE-1398: sys._getframe(1) may not exist when embedding.
+ # PYSIDE-1338: The "1" below is the redirection in loader.py .
+ # PYSIDE-1548: Ensure that features are not affected by other imports.
+ # PYSIDE-2029: Need to always switch. The cache was wrong interpreted.
+ calling_frame = _cf = sys._getframe(1).f_back
+ importing_module = _cf.f_globals.get("__name__", "__main__") if _cf else "__main__"
+ existing = pyside_feature_dict.get(importing_module, 0)
+
+ if name == "__feature__" and args[2]:
+ __init__()
+
+ # This is an `import from` statement that corresponds to `IMPORT_NAME`.
+ # The following `IMPORT_FROM` will handle errors. (Confusing, ofc.)
+ flag = get_select_id(args[2])
+
+ flag |= existing & 255 if isinstance(existing, int) and existing >= 0 else 0
+ pyside_feature_dict[importing_module] = flag
+
+ if importing_module == "__main__":
+ # We need to add all modules here which should see __feature__.
+ pyside_feature_dict["rlcompleter"] = flag
+
+ # Initialize feature (multiple times allowed) and clear cache.
+ sys.modules["PySide6.QtCore"].__init_feature__()
+ return sys.modules["__feature__"]
+ # Redirect to the original import
+ return None
+
+
+_is_initialized = False
+
+
+def __init__():
+ global _is_initialized
+ if not _is_initialized:
+ # use _one_ recursive import...
+ import PySide6.QtCore
+ # Initialize all prior imported modules
+ for name, module in sys.modules.items():
+ if name not in pyside_feature_dict:
+ pyside_feature_dict[name] = 0 if _mod_uses_pyside(module) else -1
+ _is_initialized = True
+
+
+def feature_imported(module):
+ # PYSIDE-2029: Need to inspect imported modules for PySide usage.
+ """
+ Set the module feature default after import.
+
+ A module that uses PySide has a switching default of 0 = "no feature".
+ Otherwise the default is -1 = "ignore this module".
+ """
+
+ # PYSIDE-1368: The `__name__` attribute does not need to exist in all modules.
+ if hasattr(module, "__name__"):
+ name = module.__name__
+ if name not in pyside_feature_dict:
+ pyside_feature_dict[name] = 0 if _mod_uses_pyside(module) else -1
+
+
+def _mod_uses_pyside(module):
+ """
+ Find out if this module uses PySide.
+
+ Simple approach: Search the source code for the string "PySide6".
+ Maybe we later support source-less modules by inspecting all code objects.
+ """
+ try:
+ source = inspect.getsource(module)
+ except TypeError:
+ # this is a builtin module like sys
+ return False
+ except OSError:
+ # this is a module withot source file
+ return False
+ except SyntaxError:
+ # PYSIDE-2189: A UnicodeError happens in tokenize.py in find_cookie
+ # which is then creating a SyntaxError in inspect.
+ # This is undocumented and a Python error, seen in Python 3.10.2 on Windows,
+ # importing `pythoncom` of the win32 package.
+ return False
+ except Exception:
+ # PYSIDE-2393: pytest behaves weird when allowing any other error.
+ return False
+ return "PySide6" in source
+
+
+def set_selection(select_id, mod_name=None):
+ """
+ Internal use: Set the feature directly by Id.
+ Id == -1: ignore this module in switching.
+ """
+ mod_name = mod_name or sys._getframe(1).f_globals['__name__']
+ __init__()
+ # Reset the features to the given id
+ flag = 0
+ if isinstance(select_id, int):
+ flag = select_id & 255
+ pyside_feature_dict[mod_name] = flag
+ sys.modules["PySide6.QtCore"].__init_feature__()
+ return _current_selection(flag)
+
+
+# The set_section(0) case seems to be unsafe. We will migrate to
+# use the opaque feature.reset() call in all test cases.
+def reset():
+ set_selection(0)
+ pyside_feature_dict.clear()
+ _is_initialized = False
+
+
+def info(mod_name=None):
+ """
+ Internal use: Return the current selection
+ """
+ mod_name = mod_name or sys._getframe(1).f_globals['__name__']
+ flag = pyside_feature_dict.get(mod_name, 0)
+ return _current_selection(flag)
+
+
+def _current_selection(flag):
+ names = []
+ if flag >= 0:
+ for idx, name in enumerate(_really_all_feature_names):
+ if (1 << idx) & flag:
+ names.append(name)
+ return names
+
+
+def get_select_id(feature_names):
+ flag = 0
+ for feature in feature_names:
+ if feature in _really_all_feature_names:
+ flag |= globals()[feature]
+ else:
+ raise SyntaxError(f"PySide feature {feature} is not defined")
+ return flag
+
+
+@contextmanager
+def force_selection(select_id, mod_name):
+ """
+ This function is for generating pyi files with features.
+ The selection id is set globally after performing the unswitched
+ import.
+
+ """
+ __init__()
+ saved_feature_dict = pyside_feature_dict.copy()
+ for name in pyside_feature_dict:
+ set_selection(0, name)
+ __import__(mod_name)
+ for name in pyside_feature_dict.copy():
+ set_selection(select_id, name)
+ try:
+ yield
+ finally:
+ pyside_feature_dict.update(saved_feature_dict)
+
+#eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py
index 396f6ca4c..f7190b12f 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/fix-complaints.py
@@ -1,44 +1,5 @@
-# This Python file uses the following encoding: utf-8
-# It has been edited by fix-complaints.py .
-
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
fix-complaints.py
@@ -48,7 +9,6 @@ Run it once after copying a new version. It is idem-potent, unless
you are changing messages (what I did, of course :-) .
"""
-import os
import glob
from pathlib import Path
@@ -63,6 +23,7 @@ offending_words = {
utf8_line = "# This Python file uses the following encoding: utf-8\n"
marker_line = f"# It has been edited by {Path(__file__).name} .\n"
+
def patch_file(fname):
with fname.open() as f:
lines = f.readlines()
@@ -80,6 +41,7 @@ def patch_file(fname):
with open(fname, "w") as f:
f.write("".join(lines))
+
def doit():
dirname = Path(__file__).parent
patched_files = []
@@ -90,6 +52,7 @@ def doit():
print("Working on", fname)
patch_file(fname)
+
if __name__ == "__main__":
doit()
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
new file mode 100644
index 000000000..7147a4148
--- /dev/null
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/shibokensupport.pyproject
@@ -0,0 +1,16 @@
+{
+ "files": ["__init__.py",
+ "feature.py",
+ "fix-complaints.py",
+ "signature/__init__.py",
+ "signature/errorhandler.py",
+ "signature/importhandler.py",
+ "signature/layout.py",
+ "signature/lib/__init__.py",
+ "signature/lib/enum_sig.py",
+ "signature/lib/pyi_generator.py",
+ "signature/lib/tool.py",
+ "signature/loader.py",
+ "signature/mapping.py",
+ "signature/parser.py"]
+}
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/__init__.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/__init__.py
index 7ae0a7f18..bebf56c7e 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/__init__.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/__init__.py
@@ -1,40 +1,4 @@
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
__all__ = "get_signature layout mapping lib".split()
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
index 7af7b48b2..c2a19efef 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
@@ -1,41 +1,7 @@
-#############################################################################
-##
-## Copyright (C) 2020 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+# flake8: noqa E:721
"""
errorhandler.py
@@ -54,21 +20,33 @@ enough to produce a useful ValueError.
This matter will be improved in a later version.
"""
-import sys
+import collections.abc
+import typing
-from shibokensupport.signature import inspect
from shibokensupport.signature import get_signature
-from shibokensupport.signature.mapping import update_mapping, namespace
+from shibokensupport.signature.mapping import namespace
from textwrap import dedent
def qt_isinstance(inst, the_type):
if the_type == float:
- return isinstance(inst, int) or isinstance(int, float)
+ # Qt thinks differently about int and float - simply keep it.
+ return isinstance(inst, int) or isinstance(inst, float)
+ if the_type.__module__ == "typing":
+ if the_type is typing.Any:
+ return True
+ if the_type.__origin__ is typing.Union:
+ return any(qt_isinstance(inst, _) for _ in the_type.__args__)
+ if the_type.__origin__ in (collections.abc.Sequence,
+ collections.abc.Iterable):
+ try:
+ return all(qt_isinstance(_, the_type.__args__[0]) for _ in inst)
+ except TypeError:
+ return False
try:
return isinstance(inst, the_type)
except TypeError as e:
- print("FIXME", e)
+ print(f"FIXME qt_isinstance({inst}, {the_type}):", e)
return False
@@ -82,13 +60,7 @@ def matched_type(args, sigs):
if params[k].default is params[k].empty:
# this is a necessary parameter, so it fails.
continue
- ok = True
- for arg, param in zip(args, params):
- ann = param.annotation
- if qt_isinstance(arg, ann):
- continue
- ok = False
- if ok:
+ if all(qt_isinstance(arg, param.annotation) for arg, param in zip(args, params)):
return sig
return None
@@ -98,12 +70,15 @@ def seterror_argument(args, func_name, info):
try:
func = eval(func_name, namespace)
except Exception as e:
- msg = f"Internal error evaluating {func_name}: " + str(e)
- return TypeError, msg
+ msg = f"Error evaluating `{func_name}`: {e}"
+ return type(e), msg
if info and type(info) is str:
err = TypeError
if info == "<":
msg = f"{func_name}(): not enough arguments"
+ elif info == "0":
+ msg = (f"{func_name}(): not enough arguments. "
+ "Note: keyword arguments are only supported for optional parameters.")
elif info == ">":
msg = f"{func_name}(): too many arguments"
elif info.isalnum():
@@ -112,6 +87,12 @@ def seterror_argument(args, func_name, info):
msg = f"{func_name}(): {info}"
err = AttributeError
return err, msg
+ if isinstance(info, Exception):
+ # PYSIDE-2230: Python 3.12 seems to always do normalization.
+ err = type(info)
+ info = info.args[0]
+ msg = f"{func_name}(): {info}"
+ return err, msg
if info and type(info) is dict:
msg = f"{func_name}(): unsupported keyword '{tuple(info)[0]}'"
return AttributeError, msg
@@ -151,6 +132,8 @@ def check_string_type(s):
def make_helptext(func):
existing_doc = func.__doc__
+ if existing_doc is None and hasattr(func, "__dict__"):
+ existing_doc = func.__dict__.get("__doc__")
sigs = get_signature(func)
if not sigs:
return existing_doc
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
index b37aefbb5..bae264294 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/importhandler.py
@@ -1,41 +1,5 @@
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
importhandler.py
@@ -70,9 +34,10 @@ def finish_import(module):
except Exception as e:
name = e.__class__.__qualname__
print(72 * "*")
- print(f"Error in deprecated.py, ignored:")
+ print("Error in deprecated.py, ignored:")
print(f" {name}: {e}")
+
"""
A note for people who might think this could be written in pure Python:
@@ -98,4 +63,3 @@ module, it is *perhaps* possible to solve that. I tried for a day and then
gave up, since the solution is anyway not too nice when __import__ must
be overridden.
"""
-#eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
index c0460b332..0e781cbcb 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/layout.py
@@ -1,41 +1,5 @@
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
layout.py
@@ -53,10 +17,12 @@ It also implements them in this file. The configurations are
used literally as strings like "signature", "existence", etc.
"""
+import inspect
+import typing
+
+from types import SimpleNamespace
from textwrap import dedent
-from shibokensupport.signature import inspect, typing
from shibokensupport.signature.mapping import ellipsis
-from shibokensupport.signature.lib.tool import SimpleNamespace
class SignatureLayout(SimpleNamespace):
@@ -113,6 +79,7 @@ class SignatureLayout(SimpleNamespace):
The only allowed values are '{allowed_values}'.
"""))
+
# The following names are used literally in this module.
# This way, we avoid the dict hashing problem.
signature = SignatureLayout()
@@ -149,7 +116,7 @@ def define_nameless_parameter():
P = inspect.Parameter
newname = "NamelessParameter"
bases = P.__bases__
- body = dict(P.__dict__) # get rid of mappingproxy
+ body = dict(P.__dict__) # get rid of mappingproxy
if "__slots__" in body:
# __slots__ would create duplicates
for name in body["__slots__"]:
@@ -174,10 +141,10 @@ That information would be lost when we use the "..." convention.
Note that the typing module has the remarkable expansion
- Optional[T] is Variant[T, NoneType]
+ Optional[T] is Union[T, NoneType]
We want to avoid that when generating the .pyi file.
-This is done by a regex in generate_pyi.py .
+This is done by a regex in pyi_generator.py .
The following would work in Python 3, but this is a version-dependent
hack that also won't work in Python 2 and would be _very_ complex.
"""
@@ -201,12 +168,13 @@ def make_signature_nameless(signature):
signature.parameters[key].__class__ = NamelessParameter
-_POSITIONAL_ONLY = inspect._POSITIONAL_ONLY
-_POSITIONAL_OR_KEYWORD = inspect._POSITIONAL_OR_KEYWORD
-_VAR_POSITIONAL = inspect._VAR_POSITIONAL
-_KEYWORD_ONLY = inspect._KEYWORD_ONLY
-_VAR_KEYWORD = inspect._VAR_KEYWORD
-_empty = inspect._empty
+_POSITIONAL_ONLY = inspect._POSITIONAL_ONLY # noqa E:201
+_POSITIONAL_OR_KEYWORD = inspect._POSITIONAL_OR_KEYWORD # noqa E:201
+_VAR_POSITIONAL = inspect._VAR_POSITIONAL # noqa E:201
+_KEYWORD_ONLY = inspect._KEYWORD_ONLY # noqa E:201
+_VAR_KEYWORD = inspect._VAR_KEYWORD # noqa E:201
+_empty = inspect._empty # noqa E:201
+
def create_signature(props, key):
if not props:
@@ -217,9 +185,9 @@ def create_signature(props, key):
return list(create_signature(elem, key)
for elem in props["multi"])
if type(key) is tuple:
- sig_kind, modifier = key
+ _, modifier = key
else:
- sig_kind, modifier = key, "signature"
+ _, modifier = key, "signature"
layout = globals()[modifier] # lookup of the modifier in this module
if not isinstance(layout, SignatureLayout):
@@ -234,7 +202,7 @@ def create_signature(props, key):
# parser.
pass
else:
- if "self" in varnames[:1]:
+ if varnames and varnames[0] in ("self", "cls"):
varnames = varnames[1:]
# calculate the modifications
@@ -254,7 +222,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)
@@ -268,8 +236,8 @@ def create_signature(props, key):
if kind == _VAR_POSITIONAL:
kind = _KEYWORD_ONLY
sig = inspect.Signature(params,
- return_annotation=annotations.get('return', _empty),
- __validate_parameters__=False)
+ return_annotation=annotations.get('return', _empty),
+ __validate_parameters__=False)
# the special case of nameless parameters
if not layout.parameter_names:
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/__init__.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/__init__.py
index 2d640cb89..e54bec75a 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/__init__.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/__init__.py
@@ -1,40 +1,4 @@
-#############################################################################
-##
-## Copyright (C) 2018 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
# this file intentionally left blank
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 400c36de5..5650e2bc1 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
@@ -1,41 +1,5 @@
-#############################################################################
-##
-## Copyright (C) 2020 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
enum_sig.py
@@ -47,12 +11,35 @@ It is not easy to adhere to this protocol, but in the end, it paid off
by producing a lot of clarity.
"""
+import inspect
import sys
import types
-from shibokensupport.signature import inspect
from shibokensupport.signature import get_signature as get_sig
+"""
+PYSIDE-1599: Making sure that pyi files always are tested.
+
+A new problem popped up when supporting true properties:
+When there exists an item named "property", then we cannot use
+the builtin `property` as decorator, but need to prefix it with "builtins".
+
+We scan for such a name in a class, and if there should a property be
+declared in the same class, we use `builtins.property` in the class and
+all sub-classes. The same consideration holds for "overload".
+"""
+
+_normal_functions = (types.BuiltinFunctionType, types.FunctionType)
+if hasattr(sys, "pypy_version_info"):
+ # In PyPy, there are more types because our builtin functions
+ # are created differently in C++ and not in PyPy.
+ _normal_functions += (type(get_sig),)
+
+
+def signal_check(thing):
+ return thing and type(thing) in (Signal, SignalInstance)
+
+
class ExactEnumerator(object):
"""
ExactEnumerator enumerates all signatures in a module as they are.
@@ -63,20 +50,19 @@ class ExactEnumerator(object):
"""
def __init__(self, formatter, result_type=dict):
- global EnumMeta
+ global EnumMeta, Signal, SignalInstance
try:
# Lazy import
- from PySide6.QtCore import Qt
+ from PySide6.QtCore import Qt, Signal, SignalInstance
EnumMeta = type(Qt.Key)
except ImportError:
- EnumMeta = None
+ EnumMeta = Signal = SignalInstance = None
self.fmt = formatter
self.result_type = result_type
self.fmt.level = 0
- self.fmt.after_enum = self.after_enum
- self._after_enum = False
self.fmt.is_method = self.is_method
+ self.collision_candidates = {"property", "overload"}
def is_method(self):
"""
@@ -84,11 +70,11 @@ class ExactEnumerator(object):
We check if it is a simple function.
"""
tp = type(self.func)
- return tp not in (types.BuiltinFunctionType, types.FunctionType)
+ return tp not in _normal_functions
- def after_enum(self):
- ret = self._after_enum
- self._after_enum = False
+ def section(self):
+ if hasattr(self.fmt, "section"):
+ self.fmt.section()
def module(self, mod_name):
__import__(mod_name)
@@ -100,24 +86,31 @@ class ExactEnumerator(object):
ret = self.result_type()
self.fmt.class_name = None
for class_name, klass in members:
+ self.collision_track = set()
ret.update(self.klass(class_name, klass))
- if isinstance(klass, EnumMeta):
- raise SystemError("implement enum instances at module level")
+ if len(members):
+ self.section()
for func_name, func in functions:
ret.update(self.function(func_name, func))
+ if len(functions):
+ self.section()
return ret
def klass(self, class_name, klass):
ret = self.result_type()
+ if ("._") in class_name:
+ # This happens when introspecting enum.Enum etc. Python 3.8.8 does not
+ # like this, but we want to remove that, anyway.
+ return ret
if "<" in class_name:
# This is happening in QtQuick for some reason:
- ## class QSharedPointer<QQuickItemGrabResult >:
+ # class std::shared_ptr<QQuickItemGrabResult >:
# We simply skip over this class.
return ret
bases_list = []
for base in klass.__bases__:
- name = base.__name__
- if name not in ("object", "type"):
+ name = base.__qualname__
+ if name not in ("object", "property", "type"):
name = base.__module__ + "." + name
bases_list.append(name)
bases_str = ', '.join(bases_list)
@@ -128,60 +121,126 @@ class ExactEnumerator(object):
subclasses = []
functions = []
enums = []
+ properties = []
+ signals = []
+ attributes = {}
for thing_name, thing in class_members:
- if inspect.isclass(thing):
+ if signal_check(thing):
+ signals.append((thing_name, thing))
+ elif inspect.isclass(thing):
+ # If this is the only member of the class, it causes the stub
+ # to be printed empty without ..., as self.fmt.have_body will
+ # then be True. (Example: QtCore.QCborTag). Skip it to avoid
+ # this problem.
+ if thing_name == "_member_type_":
+ continue
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))
+ functions.append((func_name, thing))
elif type(type(thing)) is EnumMeta:
# take the real enum name, not what is in the dict
- enums.append((thing_name, type(thing).__qualname__, thing))
+ if not thing_name.startswith("_"):
+ enums.append((thing_name, type(thing).__qualname__, thing))
+ elif isinstance(thing, property):
+ properties.append((thing_name, thing))
+ # Support attributes that have PySide types as values,
+ # but we skip the 'staticMetaObject' that needs
+ # to be defined at a QObject level.
+ elif "PySide" in str(type(thing)) and "QMetaObject" not in str(type(thing)):
+ if class_name not in attributes:
+ attributes[class_name] = {}
+ attributes[class_name][thing_name] = thing
+
+ if thing_name in self.collision_candidates:
+ self.collision_track.add(thing_name)
+
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)
+ # sort by class then enum value
+ enums.sort(key=lambda tup: (tup[1], tup[2].value))
+
+ # 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 get_sig(_[1]))
+ self.fmt.have_body = bool(subclasses or sigs or properties or enums or # noqa W:504
+ init_signature or signals or attributes)
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)):
+ with self.fmt.enum(enum_class_name, enum_name, value.value):
+ pass
+ if hasattr(self.fmt, "signal"):
+ # this is an optional feature
+ if len(signals):
+ self.section()
+ for signal_name, signal in signals:
+ sig_class = type(signal)
+ sig_class_name = f"{sig_class.__qualname__}"
+ sig_str = str(signal)
+ with self.fmt.signal(sig_class_name, signal_name, sig_str):
pass
+ if hasattr(self.fmt, "attribute"):
+ if len(attributes):
+ self.section()
+ for class_name, attrs in attributes.items():
+ for attr_name, attr_value in attrs.items():
+ with self.fmt.attribute(attr_name, attr_value):
+ pass
+ if len(subclasses):
+ self.section()
for subclass_name, subclass in subclasses:
- if klass == subclass:
- # this is a side effect of the typing module for Python 2.7
- # via the "._gorg" property, which we can safely ignore.
- print(f"Warning: {class_name} points to itself via {subclass_name}, skipped!")
- continue
+ save = self.collision_track.copy()
ret.update(self.klass(subclass_name, subclass))
+ self.collision_track = save
self.fmt.class_name = class_name
+ if len(subclasses):
+ self.section()
ret.update(self.function("__init__", klass))
- for func_name, func in functions:
+ for func_name, func in func_prop:
if func_name != "__init__":
- ret.update(self.function(func_name, func))
+ if isinstance(func, property):
+ ret.update(self.fproperty(func_name, func))
+ else:
+ ret.update(self.function(func_name, func))
self.fmt.level -= 1
+ if len(func_prop):
+ self.section()
return ret
@staticmethod
def get_signature(func):
- return func.__signature__
+ return get_sig(func)
- def function(self, func_name, func):
+ def function(self, func_name, func, decorator=None):
self.func = func # for is_method()
ret = self.result_type()
- signature = self.get_signature(func)
+ if decorator in self.collision_track:
+ decorator = f"builtins.{decorator}"
+ signature = self.get_signature(func, decorator)
if signature is not None:
- with self.fmt.function(func_name, signature) as key:
+ with self.fmt.function(func_name, signature, decorator) as key:
ret[key] = signature
del self.func
return ret
+ def fproperty(self, prop_name, prop):
+ ret = self.function(prop_name, prop.fget, type(prop).__qualname__)
+ if prop.fset:
+ ret.update(self.function(prop_name, prop.fset, f"{prop_name}.setter"))
+ if prop.fdel:
+ ret.update(self.function(prop_name, prop.fdel, f"{prop_name}.deleter"))
+ return ret
+
def stringify(signature):
if isinstance(signature, list):
@@ -221,6 +280,25 @@ class HintingEnumerator(ExactEnumerator):
hinting stubs. Only default values are replaced by "...".
"""
- @staticmethod
- def get_signature(func):
- return get_sig(func, "hintingstub")
+ def __init__(self, *args, **kwds):
+ super().__init__(*args, **kwds)
+ # We need to provide default signatures for class properties.
+ cls_param = inspect.Parameter("cls", inspect._POSITIONAL_OR_KEYWORD)
+ set_param = inspect.Parameter("arg_1", inspect._POSITIONAL_OR_KEYWORD, annotation=object)
+ self.getter_sig = inspect.Signature([cls_param], return_annotation=object)
+ self.setter_sig = inspect.Signature([cls_param, set_param])
+ self.deleter_sig = inspect.Signature([cls_param])
+
+ def get_signature(self, func, decorator=None):
+ # Class properties don't have signature support (yet).
+ # In that case, produce a fake one.
+ sig = get_sig(func, "hintingstub")
+ 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
new file mode 100644
index 000000000..ce12dd6c8
--- /dev/null
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py
@@ -0,0 +1,334 @@
+LICENSE_TEXT = """
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+"""
+
+# flake8: noqa E:402
+
+"""
+pyi_generator.py
+
+This script generates .pyi files for arbitrary modules.
+"""
+
+import argparse
+import io
+import logging
+import os
+import re
+import sys
+import typing
+
+from pathlib import Path
+from contextlib import contextmanager
+from textwrap import dedent
+
+from shibokensupport.signature.lib.enum_sig import HintingEnumerator
+from shibokensupport.signature.lib.tool import build_brace_pattern
+
+# Can we use forward references?
+USE_PEP563 = sys.version_info[:2] >= (3, 7)
+
+indent = " " * 4
+
+
+class Writer(object):
+ def __init__(self, outfile, *args):
+ self.outfile = outfile
+ self.history = [True, True]
+
+ def print(self, *args, **kw):
+ # controlling too much blank lines
+ if self.outfile:
+ if args == () or args == ("",):
+ # We use that to skip too many blank lines:
+ if self.history[-2:] == [True, True]:
+ return
+ print("", file=self.outfile, **kw)
+ self.history.append(True)
+ else:
+ print(*args, file=self.outfile, **kw)
+ self.history.append(False)
+
+
+class Formatter(Writer):
+ """
+ Formatter is formatting the signature listing of an enumerator.
+
+ It is written as context managers in order to avoid many callbacks.
+ The separation in formatter and enumerator is done to keep the
+ unrelated tasks of enumeration and formatting apart.
+ """
+ def __init__(self, outfile, options, *args):
+ # XXX Find out which of these patches is still necessary!
+ self.options = options
+ Writer.__init__(self, outfile, *args)
+ # patching __repr__ to disable the __repr__ of typing.TypeVar:
+ """
+ def __repr__(self):
+ if self.__covariant__:
+ prefix = '+'
+ elif self.__contravariant__:
+ prefix = '-'
+ else:
+ prefix = '~'
+ return prefix + self.__name__
+ """
+ def _typevar__repr__(self):
+ return f"typing.{self.__name__}"
+ # This is no longer necessary for modern typing versions.
+ # Ignore therefore if the repr is read-only and cannot be changed.
+ try:
+ typing.TypeVar.__repr__ = _typevar__repr__
+ except TypeError:
+ pass
+ # Adding a pattern to substitute "Union[T, NoneType]" by "Optional[T]"
+ # I tried hard to replace typing.Optional by a simple override, but
+ # this became _way_ too much.
+ # See also the comment in layout.py .
+ brace_pat = build_brace_pattern(3, ",")
+ pattern = fr"\b Union \s* \[ \s* {brace_pat} \s*, \s* NoneType \s* \]"
+ replace = r"Optional[\1]"
+ optional_searcher = re.compile(pattern, flags=re.VERBOSE)
+
+ def optional_replacer(source):
+ return optional_searcher.sub(replace, str(source))
+ self.optional_replacer = optional_replacer
+ # self.level is maintained by enum_sig.py
+ # self.is_method() is true for non-plain functions.
+
+ def section(self):
+ if self.level == 0:
+ self.print()
+ self.print()
+
+ @contextmanager
+ def module(self, mod_name):
+ self.mod_name = mod_name
+ txt = f"""\
+ # Module `{mod_name}`
+
+ <<IMPORTS>>
+ """
+ self.print(dedent(txt))
+ yield
+
+ @contextmanager
+ def klass(self, class_name, class_str):
+ spaces = indent * self.level
+ while "." in class_name:
+ class_name = class_name.split(".", 1)[-1]
+ class_str = class_str.split(".", 1)[-1]
+ if self.have_body:
+ self.print(f"{spaces}class {class_str}:")
+ else:
+ self.print(f"{spaces}class {class_str}: ...")
+ yield
+
+ @contextmanager
+ def function(self, func_name, signature, decorator=None):
+ if func_name == "__init__":
+ self.print()
+ key = func_name
+ spaces = indent * self.level
+ if isinstance(signature, list):
+ for sig in signature:
+ self.print(f'{spaces}@overload')
+ self._function(func_name, sig, spaces)
+ else:
+ self._function(func_name, signature, spaces, decorator)
+ if func_name == "__init__":
+ self.print()
+ yield key
+
+ 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}')
+ 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)
+ self.print(f'{spaces}def {func_name}{signature}: ...')
+
+ @contextmanager
+ def enum(self, class_name, enum_name, value):
+ spaces = indent * self.level
+ hexval = hex(value)
+ self.print(f"{spaces}{enum_name:25}: {class_name} = ... # {hexval}")
+ yield
+
+ @contextmanager
+ def attribute(self, attr_name, attr_value):
+ spaces = indent * self.level
+ self.print(f"{spaces}{attr_name:25} = ... # type: {type(attr_value).__qualname__}")
+ yield
+
+ @contextmanager
+ def signal(self, class_name, sig_name, sig_str):
+ spaces = indent * self.level
+ self.print(f"{spaces}{sig_name:25}: ClassVar[{class_name}] = ... # {sig_str}")
+ yield
+
+
+def find_imports(text):
+ return [imp for imp in PySide6.__all__ if f"PySide6.{imp}." in text]
+
+
+FROM_IMPORTS = [
+ (None, ["builtins"]),
+ (None, ["os"]),
+ (None, ["enum"]),
+ ("collections.abc", ["Iterable"]),
+ ("typing", sorted(typing.__all__)),
+ ("PySide6.QtCore", ["PyClassProperty", "Signal", "SignalInstance"]),
+ ("shiboken6", ["Shiboken"]),
+ ]
+
+
+def filter_from_imports(from_struct, text):
+ """
+ Build a reduced new `from` structure (nfs) with found entries, only
+ """
+ nfs = []
+ for mod, imports in from_struct:
+ lis = []
+ nfs.append((mod, lis))
+ for each in imports:
+ # PYSIDE-1603: We search text that is a usage of the class `each`,
+ # but only if the class is not also defined here.
+ if (f"class {each}(") not in text:
+ if re.search(rf"(\b|@){each}\b([^\s\(:]|\n)", text):
+ lis.append(each)
+ # Search if a type is present in the return statement
+ # of function declarations: '... -> here:'
+ if re.search(rf"->.*{each}.*:", text):
+ lis.append(each)
+ if not lis:
+ nfs.pop()
+ return nfs
+
+
+def find_module(import_name, outpath, from_pyside):
+ """
+ Find a module either directly by import, or use the full path,
+ add the path to sys.path and import then.
+ """
+ if from_pyside:
+ # internal mode for generate_pyi.py
+ plainname = import_name.split(".")[-1]
+ outfilepath = Path(outpath) / f"{plainname}.pyi"
+ return import_name, plainname, outfilepath
+ # we are alone in external module mode
+ p = Path(import_name).resolve()
+ if not p.exists():
+ raise ValueError(f"File {p} does not exist.")
+ if not outpath:
+ outpath = p.parent
+ # temporarily add the path and do the import
+ sys.path.insert(0, os.fspath(p.parent))
+ plainname = p.name.split(".")[0]
+ __import__(plainname)
+ sys.path.pop(0)
+ return plainname, plainname, Path(outpath) / (plainname + ".pyi")
+
+
+def generate_pyi(import_name, outpath, options):
+ """
+ Generates a .pyi file.
+ """
+ import_name, plainname, outfilepath = find_module(import_name, outpath, options._pyside_call)
+ top = __import__(import_name)
+ obj = getattr(top, plainname) if import_name != plainname else top
+ if not getattr(obj, "__file__", None) or Path(obj.__file__).is_dir():
+ raise ModuleNotFoundError(f"We do not accept a namespace as module `{plainname}`")
+
+ outfile = io.StringIO()
+ fmt = Formatter(outfile, options)
+ fmt.print(LICENSE_TEXT.strip())
+ if USE_PEP563:
+ fmt.print("from __future__ import annotations")
+ fmt.print()
+ fmt.print(dedent(f'''\
+ """
+ This file contains the exact signatures for all functions in module
+ {import_name}, except for defaults which are replaced by "...".
+ """
+ '''))
+ HintingEnumerator(fmt).module(import_name)
+ fmt.print("# eof")
+ # Postprocess: resolve the imports
+ if options._pyside_call:
+ global PySide6
+ import PySide6
+ with outfilepath.open("w") as realfile:
+ wr = Writer(realfile)
+ outfile.seek(0)
+ while True:
+ line = outfile.readline()
+ if not line:
+ break
+ line = line.rstrip()
+ # we remove the "<<IMPORTS>>" marker and insert imports if needed
+ if line == "<<IMPORTS>>":
+ text = outfile.getvalue()
+ wr.print("import " + import_name)
+ for mod_name in find_imports(text):
+ imp = "PySide6." + mod_name
+ if imp != import_name:
+ wr.print("import " + imp)
+ wr.print()
+ for mod, imports in filter_from_imports(FROM_IMPORTS, text):
+ import_args = ', '.join(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}")
+ wr.print()
+ wr.print()
+ wr.print("NoneType: TypeAlias = type[None]")
+ wr.print()
+ else:
+ wr.print(line)
+ if not options.quiet:
+ options.logger.info(f"Generated: {outfilepath}")
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ description=dedent("""\
+ pyi_generator.py
+ ----------------
+
+ This script generates the .pyi file for an arbitrary module.
+ You pass in the full path of a compiled, importable module.
+ pyi_generator will try to generate an interface "<module>.pyi".
+ """))
+ parser.add_argument("module",
+ help="The full path name of an importable module binary (.pyd, .so)") # noqa E:128
+ parser.add_argument("--quiet", action="store_true", help="Run quietly")
+ parser.add_argument("--outpath",
+ help="the output directory (default = location of module binary)") # noqa E:128
+ options = parser.parse_args()
+ module = options.module
+ outpath = options.outpath
+
+ qtest_env = os.environ.get("QTEST_ENVIRONMENT", "")
+ logging.basicConfig(level=logging.DEBUG if qtest_env else logging.INFO)
+ logger = logging.getLogger("pyi_generator")
+
+ if outpath and not Path(outpath).exists():
+ os.makedirs(outpath)
+ logger.info(f"+++ Created path {outpath}")
+ options._pyside_call = False
+ options.is_ci = qtest_env == "ci"
+
+ options.logger = logger
+ generate_pyi(module, outpath, options=options)
+
+
+if __name__ == "__main__":
+ main()
+# eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
index 268142db8..979dcf4ce 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/tool.py
@@ -1,41 +1,5 @@
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
"""
tool.py
@@ -45,30 +9,11 @@ On the function with_metaclass see the answer from Martijn Pieters on
https://stackoverflow.com/questions/18513821/python-metaclass-understanding-the-with-metaclass
"""
+from inspect import currentframe
from textwrap import dedent
-class SimpleNamespace(object):
- # From types.rst, because the builtin is implemented in Python 3, only.
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
-
- def __repr__(self):
- keys = sorted(self.__dict__)
- items = (f"{k}={self.__dict__[k]!r}" for k in keys)
- items_str = ', '.join(items)
- return f"{type(self).__name__}({items_str})"
-
- def __eq__(self, other):
- return self.__dict__ == other.__dict__
-
-try:
- from types import SimpleNamespace
-except ImportError:
- pass
-
-
-def build_brace_pattern(level, separators=""):
+def build_brace_pattern(level, separators):
"""
Build a brace pattern upto a given depth
@@ -92,13 +37,15 @@ def build_brace_pattern(level, separators=""):
avoiding this problem completely. It might be considered to switch to
such an engine if the external module is not a problem.
"""
+ assert type(separators) is str
+
def escape(txt):
return "".join("\\" + c for c in txt)
ro, rc = round_ = "()"
so, sc = square = "[]"
- co, cc = curly = "CD" # we insert "{}", later...
- ao, ac = angle = "<>"
+ co, cc = curly = "CD" # noqa E:201 we insert "{}", later...
+ ao, ac = angle = "<>" # noqa E:201
q2, bs, q1 = '"', "\\", "'"
allpat = round_ + square + curly + angle
__ = " "
@@ -132,8 +79,8 @@ def build_brace_pattern(level, separators=""):
{indent} )*
""")
for idx in range(level):
- pattern = pattern.format(replacer = repeated if idx < level-1 else no_braces_q,
- indent = idx * " ", **locals())
+ pattern = pattern.format(replacer=repeated if idx < level - 1 else no_braces_q,
+ indent=idx * " ", **locals())
return pattern.replace("C", "{").replace("D", "}")
@@ -153,4 +100,11 @@ def with_metaclass(meta, *bases):
return meta.__prepare__(name, bases)
return type.__new__(metaclass, 'temporary_class', (), {})
+
+# A handy tool that shows the current line number and indents.
+def lno(level):
+ lineno = currentframe().f_back.f_lineno
+ spaces = level * " "
+ return f"{lineno}{spaces}"
+
# eof
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
index e685da166..fb4c9eeca 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/loader.py
@@ -1,44 +1,8 @@
-# This Python file uses the following encoding: utf-8
-# It has been edited by fix-complaints.py .
-
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+# flake8: noqa E:402
+# flake8: noqa F:401
"""
loader.py
@@ -64,119 +28,83 @@ import os
import traceback
import types
-# On Python 2, we only have ImportError, which is way too coarse.
-# When problems occour, please use Python 3, because it has the finer
-# ModuleNotFoundError.
-
-try:
- ModuleNotFoundError
-except NameError:
- ModuleNotFoundError = ImportError
-
-def _qualname(x):
- return getattr(x, "__qualname__", x.__name__)
-
-# patching inspect's formatting to keep the word "typing":
-def formatannotation(annotation, base_module=None):
- # if getattr(annotation, '__module__', None) == 'typing':
- # return repr(annotation).replace('typing.', '')
- if isinstance(annotation, type):
- name = _qualname(annotation)
- if annotation.__module__ in ('builtins', base_module):
- return name
- return annotation.__module__ + '.' + name
- return repr(annotation)
-
-# Note also that during the tests we have a different encoding that would
-# break the Python license decorated files without an encoding line.
# name used in signature.cpp
def pyside_type_init(type_key, sig_strings):
return parser.pyside_type_init(type_key, sig_strings)
+
# name used in signature.cpp
def create_signature(props, key):
return layout.create_signature(props, key)
+
# name used in signature.cpp
def seterror_argument(args, func_name, info):
return errorhandler.seterror_argument(args, func_name, info)
+
# name used in signature.cpp
def make_helptext(func):
return errorhandler.make_helptext(func)
+
# name used in signature.cpp
def finish_import(module):
return importhandler.finish_import(module)
+# name used in signature.cpp
+def feature_import(*args, **kwds):
+ # don't spend a stack level here for speed and compatibility
+ global feature_import
+ feature_import = feature.feature_import
+ return feature_import(*args, **kwds)
+
+
+# name used in signature.cpp
+def feature_imported(*args, **kwds):
+ # don't spend a stack level here for speed and compatibility
+ global feature_imported
+ feature_imported = feature.feature_imported
+ return feature_imported(*args, **kwds)
+
+
+import builtins
import signature_bootstrap
-from shibokensupport import signature, __feature__
+from shibokensupport import signature, feature
signature.get_signature = signature_bootstrap.get_signature
# PYSIDE-1019: Publish the __feature__ dictionary.
-__feature__.pyside_feature_dict = signature_bootstrap.pyside_feature_dict
+feature.pyside_feature_dict = signature_bootstrap.pyside_feature_dict
+builtins.__feature_import__ = signature_bootstrap.__feature_import__
del signature_bootstrap
-def _get_modname(mod):
- return mod.__spec__.name if getattr(mod, "__spec__", None) else mod.__name__
-
-def _set_modname(mod, name):
- if getattr(mod, "__spec__", None):
- mod.__spec__.name = name
- else:
- mod.__name__ = name
+is_pypy = hasattr(sys, "pypy_version_info")
def put_into_package(package, module, override=None):
# take the last component of the module name
- name = (override if override else _get_modname(module)).rsplit(".", 1)[-1]
- # allow access as {package}.typing
+ name = (override if override else module.__spec__.name).rsplit(".", 1)[-1]
+ # allow access as {package}.{name}
if package:
setattr(package, name, module)
# put into sys.modules as a package to allow all import options
- fullname = f"{_get_modname(package)}.{name}" if package else name
- _set_modname(module, fullname)
+ fullname = f"{package.__spec__.name}.{name}" if package else name
+ module.__spec__.name = fullname
# publish new dotted name in sys.modules
sys.modules[fullname] = module
-# Debug: used to inspect what each step loads
-def list_modules(message):
- ext_modules = {key:value for (key, value) in sys.modules.items()
- if hasattr(value, "__file__")}
- print("SYS.MODULES", message, len(sys.modules), len(ext_modules))
- for (name, module) in sorted(ext_modules.items()):
- print(f" {name:23}", repr(module)[:70])
-
-
-orig_typing = True
-import typing
-import inspect
-inspect.formatannotation = formatannotation
-
-# Fix the module names in typing if possible. This is important since
-# the typing names should be I/O compatible, so that typing.Dict
-# shows itself as "typing.Dict".
-for name, obj in typing.__dict__.items():
- if hasattr(obj, "__module__"):
- try:
- obj.__module__ = "typing"
- except (TypeError, AttributeError):
- pass
-
-import shibokensupport
-put_into_package(shibokensupport.signature, typing, "typing")
-put_into_package(shibokensupport.signature, inspect, "inspect")
-
-
def move_into_pyside_package():
+ import shibokensupport
import PySide6
try:
import PySide6.support
except ModuleNotFoundError:
- PySide6.support = types.ModuleType("PySide6.support")
- put_into_package(PySide6.support, __feature__)
+ # This can happen in the embedding case.
+ put_into_package(PySide6, shibokensupport, "support")
+ if not is_pypy:
+ put_into_package(PySide6.support, feature)
put_into_package(PySide6.support, signature)
put_into_package(PySide6.support.signature, mapping)
put_into_package(PySide6.support.signature, errorhandler)
@@ -185,9 +113,9 @@ def move_into_pyside_package():
put_into_package(PySide6.support.signature, parser)
put_into_package(PySide6.support.signature, importhandler)
put_into_package(PySide6.support.signature.lib, enum_sig)
+ put_into_package(PySide6.support.signature.lib, pyi_generator)
+ put_into_package(PySide6.support.signature.lib, tool)
- put_into_package(None if orig_typing else PySide6.support.signature, typing)
- put_into_package(PySide6.support.signature, inspect)
from shibokensupport.signature import mapping
from shibokensupport.signature import errorhandler
@@ -196,20 +124,35 @@ from shibokensupport.signature import lib
from shibokensupport.signature import parser
from shibokensupport.signature import importhandler
from shibokensupport.signature.lib import enum_sig
+from shibokensupport.signature.lib import pyi_generator
+from shibokensupport.signature.lib import tool
+
+import enum
+
+post_init = lambda: None # noqa E:731 default
if "PySide6" in sys.modules:
- # We publish everything under "PySide6.support.signature", again.
+ # We publish everything under "PySide6.support", again.
move_into_pyside_package()
- # PYSIDE-1019: Modify `__import__` to be `__feature__` aware.
- # __feature__ is already in sys.modules, so this is actually no import
+ # PYSIDE-1502: Make sure that support can be imported.
try:
- import PySide6.support.__feature__
- sys.modules["__feature__"] = PySide6.support.__feature__
- PySide6.support.__feature__.original_import = __builtins__["__import__"]
- __builtins__["__import__"] = PySide6.support.__feature__._import
- # Maybe we should optimize that and change `__import__` from C, instead?
+ import PySide6.support
except ModuleNotFoundError:
- print("__feature__ could not be imported. "
- "This is an unsolved PyInstaller problem.", file=sys.stderr)
+ print("PySide6.support could not be imported. "
+ "This is a serious configuration error.", file=sys.stderr)
+ raise
+
+ def post_init():
+ """
+ This function needs to be called explicitly when all function pointers are set.
+ Doing this during import has bad side-effects when preloading the loader.
+ """
+ # PYSIDE-1019: Modify `__import__` to be `__feature__` aware.
+ if not is_pypy:
+ # PYSIDE-535: Cannot enable __feature__ for various reasons.
+ import PySide6.support.feature
+ sys.modules["__feature__"] = PySide6.support.feature
+ builtins.__orig_import__ = builtins.__import__
+ builtins.__import__ = builtins.__feature_import__
# end of file
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
index 2f4104945..944a928e6 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/mapping.py
@@ -1,41 +1,7 @@
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+# flake8: noqa E:203
"""
mapping.py
@@ -47,23 +13,24 @@ The PySide modules are not loaded in advance, but only after they appear
in sys.modules. This minimizes the loading overhead.
"""
-import sys
-import struct
import os
+import struct
+import sys
+import typing
+
from pathlib import Path
+from typing import TypeVar, Generic
+from _imp import is_builtin
-from shibokensupport.signature import typing
-from shibokensupport.signature.typing import TypeVar, Generic
-from shibokensupport.signature.lib.tool import with_metaclass
class ellipsis(object):
def __repr__(self):
return "..."
+
ellipsis = ellipsis()
-Point = typing.Tuple[float, float]
+Point = typing.Tuple[int, int]
Variant = typing.Any
-ModelIndexList = typing.List[int]
QImageCleanupFunction = typing.Callable
# unfortunately, typing.Optional[t] expands to typing.Union[t, NoneType]
@@ -75,7 +42,7 @@ _S = TypeVar("_S")
MultiMap = typing.DefaultDict[str, typing.List[str]]
# ulong_max is only 32 bit on windows.
-ulong_max = 2*sys.maxsize+1 if len(struct.pack("L", 1)) != 4 else 0xffffffff
+ulong_max = 2 * sys.maxsize + 1 if len(struct.pack("L", 1)) != 4 else 0xffffffff
ushort_max = 0xffff
GL_COLOR_BUFFER_BIT = 0x00004000
@@ -111,6 +78,7 @@ class _NotCalled(str):
text = self if self.endswith(")") else self + "()"
return eval(text, namespace)
+
USE_PEP563 = False
# Note: we cannot know if this feature has been imported.
# Otherwise it would be "sys.version_info[:2] >= (3, 7)".
@@ -123,6 +91,7 @@ USE_PEP563 = False
class Virtual(_NotCalled):
pass
+
# Other types I simply could not find.
class Missing(_NotCalled):
# The string must be quoted, because the object does not exist.
@@ -135,6 +104,7 @@ class Missing(_NotCalled):
class Invalid(_NotCalled):
pass
+
# Helper types
class Default(_NotCalled):
pass
@@ -143,6 +113,7 @@ class Default(_NotCalled):
class Instance(_NotCalled):
pass
+
# Parameterized primitive variables
class _Parameterized(object):
def __init__(self, type):
@@ -152,15 +123,18 @@ class _Parameterized(object):
def __repr__(self):
return f"{type(self).__name__}({self.type.__name__})"
+
# Mark the primitive variables to be moved into the result.
class ResultVariable(_Parameterized):
pass
+
# Mark the primitive variables to become Sequence, Iterable or List
# (decided in the parser).
class ArrayLikeVariable(_Parameterized):
pass
+
StringList = ArrayLikeVariable(str)
@@ -179,7 +153,7 @@ class Reloader(object):
if getattr(mod, "__file__", None) and not Path(mod.__file__).is_dir():
ending = Path(mod.__file__).suffix
return ending not in (".py", ".pyc", ".pyo", ".pyi")
- return False
+ return bool(hasattr(mod, "__name__") and is_builtin(mod.__name__))
def update(self):
"""
@@ -217,23 +191,29 @@ def check_module(mod):
mod_name = mod.__name__
raise ImportError(f"Module '{mod_name}' is not a binary module!")
+
update_mapping = Reloader().update
type_map = {}
namespace = globals() # our module's __dict__
type_map.update({
"...": ellipsis,
+ "Any": typing.Any,
"bool": bool,
"char": int,
- "char*": str,
- "char*const": str,
"double": float,
"float": float,
"int": int,
"List": ArrayLikeVariable,
+ "Optional": typing.Optional,
"long": int,
+ "long long": int,
+ "nullptr": None,
"PyCallable": typing.Callable,
"PyObject": object,
+ "PyObject*": object,
+ "PyArrayObject": ArrayLikeVariable, # numpy
+ "PyPathLike": typing.Union[str, bytes, os.PathLike[str]],
"PySequence": typing.Iterable, # important for numpy
"PyTypeObject": type,
"QChar": str,
@@ -242,16 +222,26 @@ type_map.update({
"qint32": int,
"qint64": int,
"qint8": int,
+ "int16_t": int,
+ "int32_t": int,
+ "int64_t": int,
+ "int8_t": int,
+ "intptr_t": int,
+ "uintptr_t": int,
"qintptr": int,
"qsizetype": int,
+ "QFunctionPointer": int,
"QList": ArrayLikeVariable,
"qlonglong": int,
"QMap": typing.Dict,
+ "QMultiHash": typing.Dict,
+ "QMultiMap": typing.Dict,
"QPair": typing.Tuple,
"qptrdiff": int,
"qreal": float,
"QSet": typing.Set,
"QString": str,
+ "QLatin1String": str,
"QStringView": str,
"QStringList": StringList,
"quint16": int,
@@ -259,6 +249,11 @@ type_map.update({
"quint32": int,
"quint64": int,
"quint8": int,
+ "uint16_t": int,
+ "uint32_t": int,
+ "uint64_t": int,
+ "uint8_t": int,
+ "Union": typing.Union,
"quintptr": int,
"qulonglong": int,
"QVariant": Variant,
@@ -270,7 +265,10 @@ type_map.update({
"signed long": int,
"std.list": typing.List,
"std.map": typing.Dict,
+ "std.nullptr_t": NoneType,
"std.pair": typing.Tuple,
+ "std.string": str,
+ "std.wstring": str,
"std.vector": typing.List,
"str": str,
"true": True,
@@ -280,17 +278,17 @@ type_map.update({
"uint": int,
"ulong": int,
"ULONG_MAX": ulong_max,
- "unsigned char": int, # 5.9
+ "UINT64_MAX": 0xffffffff,
+ "unsigned char": int, # 5.9
"unsigned char*": str,
"unsigned int": int,
- "unsigned long int": int, # 5.6, RHEL 6.6
+ "unsigned long int": int, # 5.6, RHEL 6.6
"unsigned long long": int,
"unsigned long": int,
- "unsigned short int": int, # 5.6, RHEL 6.6
+ "unsigned short int": int, # 5.6, RHEL 6.6
"unsigned short": int,
- "Unspecified": None,
"ushort": int,
- "void": int, # be more specific?
+ "void": int, # be more specific?
"WId": WId,
"zero(bytes)": b"",
"zero(Char)": 0,
@@ -299,7 +297,12 @@ type_map.update({
"zero(object)": None,
"zero(str)": "",
"zero(typing.Any)": None,
- })
+ "zero(Any)": None,
+ # This can be refined by importing numpy.typing optionally, but better than nothing.
+ "numpy.ndarray": typing.List[typing.Any],
+ "std.array[int, 4]": typing.List[int],
+ "std.array[float, 4]": typing.List[float]
+})
type_map.update({
# Handling variables declared as array:
@@ -311,21 +314,29 @@ type_map.update({
"array long long*" : ArrayLikeVariable(int),
"array long*" : ArrayLikeVariable(int),
"array short*" : ArrayLikeVariable(int),
- "array signed char*" : bytes,
- "array unsigned char*" : bytes,
+ "array signed char*" : typing.Union[bytes, bytearray, memoryview],
+ "array unsigned char*" : typing.Union[bytes, bytearray, memoryview],
"array unsigned int*" : ArrayLikeVariable(int),
"array unsigned short*" : ArrayLikeVariable(int),
- })
+ # PYSIDE-1646: New macOS primitive types
+ "array int8_t*" : ArrayLikeVariable(int),
+ "array uint8_t*" : ArrayLikeVariable(int),
+ "array int16_t*" : ArrayLikeVariable(int),
+ "array uint16_t*" : ArrayLikeVariable(int),
+ "array int32_t*" : ArrayLikeVariable(int),
+ "array uint32_t*" : ArrayLikeVariable(int),
+ "array intptr_t*" : ArrayLikeVariable(int),
+})
type_map.update({
# Special cases:
- "char*" : bytes,
- "QChar*" : bytes,
+ "char*" : typing.Union[bytes, bytearray, memoryview],
+ "QChar*" : typing.Union[bytes, bytearray, memoryview],
"quint32*" : int, # only for QRandomGenerator
"quint8*" : bytearray, # only for QCborStreamReader and QCborValue
- "uchar*" : bytes,
- "unsigned char*": bytes,
- })
+ "uchar*" : typing.Union[bytes, bytearray, memoryview],
+ "unsigned char*": typing.Union[bytes, bytearray, memoryview],
+})
type_map.update({
# Handling variables that are returned, eventually as Tuples:
@@ -339,6 +350,7 @@ type_map.update({
"qint32*" : ResultVariable(int),
"qint64*" : ResultVariable(int),
"qreal*" : ResultVariable(float),
+ "qsizetype*" : ResultVariable(int),
"QString*" : ResultVariable(str),
"qintptr*" : ResultVariable(int),
"quintptr*" : ResultVariable(int),
@@ -346,11 +358,26 @@ type_map.update({
"uint*" : ResultVariable(int),
"unsigned int*" : ResultVariable(int),
"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.
+type_map.update({
+ "std.optional": typing.Optional,
})
@@ -363,6 +390,7 @@ def init_Shiboken():
})
return locals()
+
def init_minimal():
type_map.update({
"MinBool": bool,
@@ -375,16 +403,18 @@ def init_sample():
type_map.update({
"char": int,
"char**": typing.List[str],
+ "const char*": str,
"Complex": complex,
"double": float,
+ "ByteArray&": typing.Union[bytes, bytearray, memoryview],
"Foo.HANDLE": int,
"HANDLE": int,
"Null": None,
- "nullptr": None,
"ObjectType.Identifier": Missing("sample.ObjectType.Identifier"),
"OddBool": bool,
"PStr": str,
"PyDate": datetime.date,
+ "PyBuffer": typing.Union[bytes, bytearray, memoryview],
"sample.bool": bool,
"sample.char": int,
"sample.double": float,
@@ -395,6 +425,7 @@ def init_sample():
"sample.Photon.TemplateBase[Photon.IdentityType]": sample.Photon.ValueIdentity,
"sample.Point": Point,
"sample.PStr": str,
+ "SampleNamespace.InValue.ZeroIn": 0,
"sample.unsigned char": int,
"std.size_t": int,
"std.string": str,
@@ -419,6 +450,7 @@ def init_smart():
# This missing type should be defined in module smart. We cannot set it to Missing()
# because it is a container type. Therefore, we supply a surrogate:
global SharedPtr
+
class SharedPtr(Generic[_S]):
__module__ = "smart"
smart.SharedPtr = SharedPtr
@@ -430,9 +462,10 @@ def init_smart():
# The PySide Part
def init_PySide6_QtCore():
- from PySide6.QtCore import Qt, QUrl, QDir
- from PySide6.QtCore import QRect, QSize, QPoint, QLocale, QByteArray
- from PySide6.QtCore import QMarginsF # 5.9
+ from PySide6.QtCore import Qt, QUrl, QDir, QKeyCombination
+ from PySide6.QtCore import QRect, QRectF, QSize, QPoint, QLocale, QByteArray
+ from PySide6.QtCore import QMarginsF # 5.9
+ from PySide6.QtCore import SignalInstance
try:
# seems to be not generated by 5.9 ATM.
from PySide6.QtCore import Connection
@@ -442,56 +475,69 @@ def init_PySide6_QtCore():
"' '": " ",
"'%'": "%",
"'g'": "g",
- "4294967295UL": 4294967295, # 5.6, RHEL 6.6
+ "4294967295UL": 4294967295, # 5.6, RHEL 6.6
"CheckIndexOption.NoOption": Instance(
- "PySide6.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11
+ "PySide6.QtCore.QAbstractItemModel.CheckIndexOptions.NoOption"), # 5.11
"DescriptorType(-1)": int, # Native handle of QSocketDescriptor
"false": False,
"list of QAbstractAnimation": typing.List[PySide6.QtCore.QAbstractAnimation],
"long long": int,
"size_t": int,
- "NULL": None, # 5.6, MSVC
- "nullptr": None, # 5.9
+ "NULL": None, # 5.6, MSVC
+ "nullptr": None, # 5.9
+ "PyBuffer": typing.Union[bytes, bytearray, memoryview],
"PyByteArray": bytearray,
- "PyBytes": bytes,
+ "PyBytes": typing.Union[bytes, bytearray, memoryview],
+ "PyTuple": typing.Tuple,
"QDeadlineTimer(QDeadlineTimer.Forever)": Instance("PySide6.QtCore.QDeadlineTimer"),
"PySide6.QtCore.QUrl.ComponentFormattingOptions":
- PySide6.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
+ PySide6.QtCore.QUrl.ComponentFormattingOption, # mismatch option/enum, why???
"PyUnicode": typing.Text,
+ "QByteArrayView": QByteArray,
"Q_NULLPTR": None,
+ "QCalendar.Unspecified": PySide6.QtCore.QCalendar.Unspecified,
+ "QCborTag(-1)": ulong_max,
"QDir.Filters(AllEntries | NoDotAndDotDot)": Instance(
"QDir.Filters(QDir.AllEntries | QDir.NoDotAndDotDot)"),
"QDir.SortFlags(Name | IgnoreCase)": Instance(
"QDir.SortFlags(QDir.Name | QDir.IgnoreCase)"),
- "QGenericArgument((0))": ellipsis, # 5.6, RHEL 6.6. Is that ok?
+ "QEvent.Type.None": None,
+ "QGenericArgument((0))": ellipsis, # 5.6, RHEL 6.6. Is that ok?
"QGenericArgument()": ellipsis,
"QGenericArgument(0)": ellipsis,
- "QGenericArgument(NULL)": ellipsis, # 5.6, MSVC
- "QGenericArgument(nullptr)": ellipsis, # 5.10
+ "QGenericArgument(NULL)": ellipsis, # 5.6, MSVC
+ "QGenericArgument(nullptr)": ellipsis, # 5.10
"QGenericArgument(Q_NULLPTR)": ellipsis,
"QJsonObject": typing.Dict[str, PySide6.QtCore.QJsonValue],
- "QModelIndex()": Invalid("PySide6.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?!
- "QModelIndexList": ModelIndexList,
- "QModelIndexList": ModelIndexList,
+ "QModelIndex()": Invalid("PySide6.QtCore.QModelIndex"), # repr is btw. very wrong, fix it?!
+ "QModelIndexList": typing.List[PySide6.QtCore.QModelIndex],
+ "PySideSignalInstance": SignalInstance,
"QString()": "",
+ "Flag.Default": Instance("PySide6.QtCore.QStringConverterBase.Flags"),
"QStringList()": [],
"QStringRef": str,
"QStringRef": str,
- "Qt.HANDLE": int, # be more explicit with some constants?
+ "Qt.HANDLE": int, # be more explicit with some constants?
"QUrl.FormattingOptions(PrettyDecoded)": Instance(
"QUrl.FormattingOptions(QUrl.PrettyDecoded)"),
"QVariant()": Invalid(Variant),
- "QVariant.Type": type, # not so sure here...
- "QVariantMap": typing.Dict[str, Variant],
+ "QVariant.Type": type, # not so sure here...
"QVariantMap": typing.Dict[str, Variant],
+ "std.chrono.seconds{5}" : ellipsis,
})
try:
type_map.update({
- "PySide6.QtCore.QMetaObject.Connection": PySide6.QtCore.Connection, # wrong!
+ "PySide6.QtCore.QMetaObject.Connection": PySide6.QtCore.Connection, # wrong!
})
except AttributeError:
# this does not exist on 5.9 ATM.
pass
+
+ # special case - char* can either be 'bytes' or 'str'. The default is 'bytes'.
+ # Here we manually set it to map to 'str'.
+ type_map.update({("PySide6.QtCore.QObject.setProperty", "char*"): str})
+ type_map.update({("PySide6.QtCore.QObject.property", "char*"): str})
+
return locals()
@@ -506,37 +552,48 @@ def init_PySide6_QtConcurrent():
def init_PySide6_QtGui():
- from PySide6.QtGui import QPageLayout, QPageSize # 5.12 macOS
+ from PySide6.QtGui import QPageLayout, QPageSize # 5.12 macOS
type_map.update({
"0.0f": 0.0,
"1.0f": 1.0,
"GL_COLOR_BUFFER_BIT": GL_COLOR_BUFFER_BIT,
"GL_NEAREST": GL_NEAREST,
"int32_t": int,
- "QPixmap()": Default("PySide6.QtGui.QPixmap"), # can't create without qApp
- "QPlatformSurface*": int, # a handle
- "QVector< QTextLayout.FormatRange >()": [], # do we need more structure?
+ "HBITMAP": int,
+ "HICON": int,
+ "HMONITOR": int,
+ "HRGN": int,
+ "QPixmap()": Default("PySide6.QtGui.QPixmap"), # can't create without qApp
+ "QPlatformSurface*": int, # a handle
+ "QVector< QTextLayout.FormatRange >()": [], # do we need more structure?
"uint32_t": int,
"uint8_t": int,
"USHRT_MAX": ushort_max,
})
+
+ # special case - char* can either be 'bytes' or 'str'. The default is 'bytes'.
+ # Here we manually set it to map to 'str'.
+ type_map.update({("PySide6.QtGui.QPixmap.save", "char*"): str})
+
return locals()
def init_PySide6_QtWidgets():
- from PySide6.QtWidgets import QWidget, QMessageBox, QStyleOption, QStyleHintReturn, QStyleOptionComplex
- from PySide6.QtWidgets import QGraphicsItem, QStyleOptionGraphicsItem # 5.9
+ from PySide6.QtWidgets import (QWidget, QMessageBox, QStyleOption,
+ QStyleHintReturn, QStyleOptionComplex,
+ QGraphicsItem, QStyleOptionGraphicsItem)
type_map.update({
"QMessageBox.StandardButtons(Yes | No)": Instance(
"QMessageBox.StandardButtons(QMessageBox.Yes | QMessageBox.No)"),
"QWidget.RenderFlags(DrawWindowBackground | DrawChildren)": Instance(
"QWidget.RenderFlags(QWidget.DrawWindowBackground | QWidget.DrawChildren)"),
- "SH_Default": QStyleHintReturn.SH_Default,
- "SO_Complex": QStyleOptionComplex.SO_Complex,
- "SO_Default": QStyleOption.SO_Default,
"static_cast<Qt.MatchFlags>(Qt.MatchExactly|Qt.MatchCaseSensitive)": Instance(
"Qt.MatchFlags(Qt.MatchExactly | Qt.MatchCaseSensitive)"),
- "Type": PySide6.QtWidgets.QListWidgetItem.Type,
+ "static_cast<Qt.MatchFlag>(Qt.MatchExactly|Qt.MatchCaseSensitive)": Instance(
+ "Qt.MatchFlag(Qt.MatchExactly | Qt.MatchCaseSensitive)"),
+ "QListWidgetItem.ItemType.Type": PySide6.QtWidgets.QListWidgetItem.Type,
+ "QTableWidgetItem.ItemType.Type": PySide6.QtWidgets.QTableWidgetItem.Type,
+ "QTreeWidgetItem.ItemType.Type": PySide6.QtWidgets.QTreeWidgetItem.Type,
})
return locals()
@@ -544,14 +601,14 @@ def init_PySide6_QtWidgets():
def init_PySide6_QtSql():
from PySide6.QtSql import QSqlDatabase
type_map.update({
- "QLatin1String(defaultConnection)": QSqlDatabase.defaultConnection,
- "QVariant.Invalid": Invalid("Variant"), # not sure what I should create, here...
+ "QLatin1StringView(QSqlDatabase.defaultConnection)": QSqlDatabase.defaultConnection,
+ "QVariant.Invalid": Invalid("Variant"), # not sure what I should create, here...
})
return locals()
def init_PySide6_QtNetwork():
- from PySide6.QtNetwork import QNetworkRequest
+ from PySide6.QtNetwork import QNetworkRequest, QHostAddress
best_structure = typing.OrderedDict if getattr(typing, "OrderedDict", None) else typing.Dict
type_map.update({
"QMultiMap[PySide6.QtNetwork.QSsl.AlternativeNameEntryType, QString]":
@@ -565,32 +622,11 @@ def init_PySide6_QtNetwork():
return locals()
-def init_PySide6_QtXmlPatterns():
- from PySide6.QtXmlPatterns import QXmlName
- type_map.update({
- "QXmlName.NamespaceCode": Missing("PySide6.QtXmlPatterns.QXmlName.NamespaceCode"),
- "QXmlName.PrefixCode": Missing("PySide6.QtXmlPatterns.QXmlName.PrefixCode"),
- })
- return locals()
-
-
-def init_PySide6_QtMultimedia():
- import PySide6.QtMultimediaWidgets
- # Check if foreign import is valid. See mapping.py in shiboken6.
- check_module(PySide6.QtMultimediaWidgets)
- type_map.update({
- "QGraphicsVideoItem": PySide6.QtMultimediaWidgets.QGraphicsVideoItem,
- "qint64": int,
- "QVideoWidget": PySide6.QtMultimediaWidgets.QVideoWidget,
- })
- return locals()
-
-
def init_PySide6_QtOpenGL():
type_map.update({
"GLbitfield": int,
"GLenum": int,
- "GLfloat": float, # 5.6, MSVC 15
+ "GLfloat": float, # 5.6, MSVC 15
"GLint": int,
"GLuint": int,
})
@@ -599,8 +635,7 @@ def init_PySide6_QtOpenGL():
def init_PySide6_QtQml():
type_map.update({
- "QJSValueList()": [],
- "QVariantHash()": typing.Dict[str, Variant], # from 5.9
+ "VolatileBool": PySide6.QtQml.VolatileBool,
})
return locals()
@@ -609,35 +644,47 @@ def init_PySide6_QtQuick():
type_map.update({
"PySide6.QtQuick.QSharedPointer[PySide6.QtQuick.QQuickItemGrabResult]":
PySide6.QtQuick.QQuickItemGrabResult,
- "UnsignedShortType": int,
+ "QSGGeometry.Type.UnsignedShortType": int,
})
return locals()
-def init_PySide6_QtScript():
+def init_PySide6_QtTest():
+ from PySide6.QtCore import SignalInstance
type_map.update({
- "QScriptValueList()": [],
+ "PySideSignalInstance": SignalInstance,
+ "PySide6.QtTest.QTest.PySideQTouchEventSequence": PySide6.QtTest.QTest.QTouchEventSequence,
+ "PySide6.QtTest.QTouchEventSequence": PySide6.QtTest.QTest.QTouchEventSequence,
})
return locals()
-def init_PySide6_QtTest():
+# from 5.12, macOS
+def init_PySide6_QtDataVisualization():
+ from PySide6.QtDataVisualization import (QBarDataItem, QSurfaceDataItem)
+ QBarDataRow = typing.List[QBarDataItem]
+ QBarDataArray = typing.List[QBarDataRow]
+ QSurfaceDataRow = typing.List[QSurfaceDataItem]
+ QSurfaceDataArray = typing.List[QSurfaceDataRow]
type_map.update({
- "PySide6.QtTest.QTest.PySideQTouchEventSequence": PySide6.QtTest.QTest.QTouchEventSequence,
- "PySide6.QtTest.QTouchEventSequence": PySide6.QtTest.QTest.QTouchEventSequence,
+ "100.0f": 100.0,
+ "QBarDataArray": QBarDataArray,
+ "QBarDataArray*": QBarDataArray,
+ "QSurfaceDataArray": QSurfaceDataArray,
+ "QSurfaceDataArray*": QSurfaceDataArray,
})
return locals()
-# from 5.6, MSVC
-def init_PySide6_QtWinExtras():
+
+def init_PySide6_QtBluetooth():
type_map.update({
- "QList< QWinJumpListItem* >()": [],
+ "QVariant*": object,
})
return locals()
-# from 5.12, macOS
-def init_PySide6_QtDataVisualization():
- from PySide6.QtDataVisualization import (QBarDataItem, QSurfaceDataItem)
+
+def init_PySide6_QtGraphs():
+ from PySide6.QtGraphs import (QBarDataItem, QSurfaceDataItem)
QBarDataRow = typing.List[QBarDataItem]
QBarDataArray = typing.List[QBarDataRow]
QSurfaceDataRow = typing.List[QSurfaceDataItem]
@@ -652,9 +699,20 @@ def init_PySide6_QtDataVisualization():
return locals()
+def init_PySide6_QtHttpServer():
+ type_map.update({
+ "qMakePair(1u, 1u)": (1, 1),
+ })
+ return locals()
+
+
def init_testbinding():
type_map.update({
"testbinding.PySideCPP2.TestObjectWithoutNamespace": testbinding.TestObjectWithoutNamespace,
+ "testbinding.FlagsNamespace.Options": testbinding.Option,
+ "FlagsNamespace.Option.NoOptions": 0,
+ "StdIntList": typing.List[int],
+ 'Str("")': str(""),
})
return locals()
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
index d737c2a54..9b48ab442 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/parser.py
@@ -1,52 +1,19 @@
-#############################################################################
-##
-## Copyright (C) 2019 The Qt Company Ltd.
-## Contact: https://www.qt.io/licensing/
-##
-## This file is part of Qt for Python.
-##
-## $QT_BEGIN_LICENSE:LGPL$
-## Commercial License Usage
-## Licensees holding valid commercial Qt licenses may use this file in
-## accordance with the commercial license agreement provided with the
-## Software or, alternatively, in accordance with the terms contained in
-## a written agreement between you and The Qt Company. For licensing terms
-## and conditions see https://www.qt.io/terms-conditions. For further
-## information use the contact form at https://www.qt.io/contact-us.
-##
-## GNU Lesser General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU Lesser
-## General Public License version 3 as published by the Free Software
-## Foundation and appearing in the file LICENSE.LGPL3 included in the
-## packaging of this file. Please review the following information to
-## ensure the GNU Lesser General Public License version 3 requirements
-## will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-##
-## GNU General Public License Usage
-## Alternatively, this file may be used under the terms of the GNU
-## General Public License version 2.0 or (at your option) the GNU General
-## Public license version 3 or any later version approved by the KDE Free
-## Qt Foundation. The licenses are as published by the Free Software
-## Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-## included in the packaging of this file. Please review the following
-## information to ensure the GNU General Public License requirements will
-## be met: https://www.gnu.org/licenses/gpl-2.0.html and
-## https://www.gnu.org/licenses/gpl-3.0.html.
-##
-## $QT_END_LICENSE$
-##
-#############################################################################
+# Copyright (C) 2022 The Qt Company Ltd.
+# SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
-import sys
+import ast
+import enum
+import keyword
+import os
import re
+import sys
+import typing
import warnings
-import types
-import keyword
-import functools
+
+from types import SimpleNamespace
from shibokensupport.signature.mapping import (type_map, update_mapping,
- namespace, typing, _NotCalled, ResultVariable, ArrayLikeVariable)
-from shibokensupport.signature.lib.tool import (SimpleNamespace,
- build_brace_pattern)
+ namespace, _NotCalled, ResultVariable, ArrayLikeVariable) # noqa E:128
+from shibokensupport.signature.lib.tool import build_brace_pattern
_DEBUG = False
LIST_KEYWORDS = False
@@ -71,6 +38,65 @@ guesses, we provide an entry in 'type_map' that resolves it.
In effect, 'type_map' maps text to real Python objects.
"""
+
+def _get_flag_enum_option():
+ from shiboken6 import (__version_info__ as ver, # noqa F:401
+ __minimum_python_version__ as pyminver,
+ __maximum_python_version__ as pymaxver)
+
+ # PYSIDE-1735: Use the new Enums per default if version is >= 6.4
+ # This decides between delivered vs. dev versions.
+ # When 6.4 is out, the switching mode will be gone.
+ flag = ver[:2] >= (6, 4)
+ envname = "PYSIDE6_OPTION_PYTHON_ENUM"
+ sysname = envname.lower()
+ opt = os.environ.get(envname)
+ if opt:
+ opt = opt.lower()
+ if opt in ("yes", "on", "true"):
+ flag = True
+ elif opt in ("no", "off", "false"):
+ flag = False
+ else:
+ # instead of a simple int() conversion, let's allow for "0xf" or "0b1111"
+ try:
+ flag = ast.literal_eval(opt)
+ except Exception:
+ flag = False # turn a forbidden option into an error
+ elif hasattr(sys, sysname):
+ opt2 = flag = getattr(sys, sysname)
+ if not isinstance(flag, int):
+ flag = False # turn a forbidden option into an error
+ p = f"\n *** Python is at version {'.'.join(map(str, pyminver or (0,)))} now."
+ q = f"\n *** PySide is at version {'.'.join(map(str, ver[:2]))} now."
+ # _PepUnicode_AsString: Fix a broken promise
+ if pyminver and pyminver >= (3, 10):
+ warnings.warn(f"{p} _PepUnicode_AsString can now be replaced by PyUnicode_AsUTF8! ***")
+ # PYSIDE-1960: Emit a warning when we may remove bufferprocs_py37.(cpp|h)
+ if pyminver and pyminver >= (3, 11):
+ warnings.warn(f"{p} The files bufferprocs_py37.(cpp|h) should be removed ASAP! ***")
+ # PYSIDE-1735: Emit a warning when we should maybe evict forgiveness mode
+ if ver[:2] >= (7, 0):
+ warnings.warn(f"{q} Please drop Enum forgiveness mode in `mangled_type_getattro` ***")
+ # PYSIDE-2404: Emit a warning when we should drop uppercase offset constants
+ if ver[:2] >= (7, 0):
+ warnings.warn(f"{q} Please drop uppercase type offsets in `copyOffsetEnumStream` ***")
+ # normalize the sys attribute
+ setattr(sys, sysname, flag)
+ os.environ[envname] = str(flag)
+ if int(flag) == 0:
+ raise RuntimeError(f"Old Enums are no longer supported. int({opt or opt2}) evaluates to 0)")
+ return flag
+
+
+class EnumSelect(enum.Enum):
+ # PYSIDE-1735: Here we could save object.value expressions by using IntEnum.
+ # But it is nice to use just an Enum for selecting Enum version.
+ OLD = 1
+ NEW = 2
+ SELECTION = NEW if _get_flag_enum_option() else OLD
+
+
def dprint(*args, **kw):
if _DEBUG:
import pprint
@@ -81,6 +107,7 @@ def dprint(*args, **kw):
_cache = {}
+
def _parse_arglist(argstr):
# The following is a split re. The string is broken into pieces which are
# between the recognized strings. Because the re has groups, both the
@@ -103,19 +130,21 @@ def _parse_line(line):
( -> (?P<returntype> .*) )? # the optional return type
$
"""
- ret = SimpleNamespace(**re.match(line_re, line, re.VERBOSE).groupdict())
+ matches = re.match(line_re, line, re.VERBOSE)
+ if not matches:
+ raise SystemError("Error parsing line:", repr(line))
+ ret = SimpleNamespace(**matches.groupdict())
# PYSIDE-1095: Handle arbitrary default expressions
argstr = ret.arglist.replace("->", ".deref.")
arglist = _parse_arglist(argstr)
args = []
for idx, arg in enumerate(arglist):
tokens = arg.split(":")
- if len(tokens) < 2:
- if idx == 0 and tokens[0] == "self":
- tokens = 2 * tokens # "self: self"
- else:
- # This should never happen again (but who knows?)
- raise SystemError(f'Invalid argument "{arg}" in "{line}".')
+ if len(tokens) < 2 and idx == 0 and tokens[0] in ("self", "cls"):
+ tokens = 2 * tokens # "self: self"
+ if len(tokens) != 2:
+ # This should never happen again (but who knows?)
+ raise SystemError(f'Invalid argument "{arg}" in "{line}".')
name, ann = tokens
if name in keyword.kwlist:
if LIST_KEYWORDS:
@@ -138,15 +167,57 @@ def _parse_line(line):
return vars(ret)
+def _using_snake_case():
+ # Note that this function should stay here where we use snake_case.
+ if "PySide6.QtCore" not in sys.modules:
+ return False
+ from PySide6.QtCore import QDir
+ return hasattr(QDir, "cd_up")
+
+
+def _handle_instance_fixup(thing):
+ """
+ Default expressions using instance methods like
+ (...,device=QPointingDevice.primaryPointingDevice())
+ need extra handling for snake_case. These are:
+ QPointingDevice.primaryPointingDevice()
+ QInputDevice.primaryKeyboard()
+ QKeyCombination.fromCombined(0)
+ QSslConfiguration.defaultConfiguration()
+ """
+ match = re.search(r"\w+\(", thing)
+ if not match:
+ return thing
+ start, stop = match.start(), match.end() - 1
+ pre, func, args = thing[:start], thing[start:stop], thing[stop:]
+ if func[0].isupper() or func.startswith("gl") and func[2:3].isupper():
+ return thing
+ # Now convert this string to snake case.
+ snake_func = ""
+ for idx, char in enumerate(func):
+ if char.isupper():
+ if idx and func[idx - 1].isupper():
+ # two upper chars are forbidden
+ return thing
+ snake_func += f"_{char.lower()}"
+ else:
+ snake_func += char
+ return f"{pre}{snake_func}{args}"
+
+
def make_good_value(thing, valtype):
+ # PYSIDE-1019: Handle instance calls (which are really seldom)
+ if "(" in thing and _using_snake_case():
+ thing = _handle_instance_fixup(thing)
try:
if thing.endswith("()"):
thing = f'Default("{thing[:-2]}")'
else:
- ret = eval(thing, namespace)
+ # PYSIDE-1735: Use explicit globals and locals because of a bug in VsCode
+ ret = eval(thing, globals(), namespace)
if valtype and repr(ret).startswith("<"):
thing = f'Instance("{thing}")'
- return eval(thing, namespace)
+ return eval(thing, globals(), namespace)
except Exception:
pass
@@ -170,12 +241,14 @@ def try_to_guess(thing, valtype):
return ret
return None
+
def get_name(thing):
if isinstance(thing, type):
return getattr(thing, "__qualname__", thing.__name__)
else:
return thing.__name__
+
def _resolve_value(thing, valtype, line):
if thing in ("0", "None") and valtype:
if valtype.startswith("PySide6.") or valtype.startswith("typing."):
@@ -194,7 +267,7 @@ def _resolve_value(thing, valtype, line):
if res is not None:
type_map[thing] = res
return res
- warnings.warn(f"""pyside_type_init:
+ warnings.warn(f"""pyside_type_init:_resolve_value
UNRECOGNIZED: {thing!r}
OFFENDING LINE: {line!r}
@@ -218,40 +291,44 @@ def _resolve_arraytype(thing, line):
def to_string(thing):
+ # This function returns a string that creates the same object.
+ # It is absolutely crucial that str(eval(thing)) == str(thing),
+ # i.e. it must be an idempotent mapping.
if isinstance(thing, str):
return thing
- if hasattr(thing, "__name__"):
- dot = "." in str(thing)
+ if hasattr(thing, "__name__") and thing.__module__ != "typing":
+ m = thing.__module__
+ dot = "." in str(thing) or m not in (thing.__qualname__, "builtins")
name = get_name(thing)
- return thing.__module__ + "." + name if dot else name
+ ret = m + "." + name if dot else name
+ assert (eval(ret, globals(), namespace))
+ return ret
# Note: This captures things from the typing module:
return str(thing)
matrix_pattern = "PySide6.QtGui.QGenericMatrix"
+
def handle_matrix(arg):
- n, m, typstr = tuple(map(lambda x:x.strip(), arg.split(",")))
+ n, m, typstr = tuple(map(lambda x: x.strip(), arg.split(",")))
assert typstr == "float"
result = f"PySide6.QtGui.QMatrix{n}x{m}"
- return eval(result, namespace)
-
+ return eval(result, globals(), namespace)
-debugging_aid = """
-from inspect import currentframe
-
-def lno(level):
- lineno = currentframe().f_back.f_lineno
- spaces = level * " "
- return f"{lineno}{spaces}"
-"""
+def _resolve_type(thing, line, level, var_handler, func_name=None):
+ # manual set of 'str' instead of 'bytes'
+ if func_name:
+ new_thing = (func_name, thing)
+ if new_thing in type_map:
+ return type_map[new_thing]
-def _resolve_type(thing, line, level, var_handler):
# Capture total replacements, first. Happens in
# "PySide6.QtCore.QCborStreamReader.StringResult[PySide6.QtCore.QByteArray]"
if thing in type_map:
return type_map[thing]
+
# Now the nested structures are handled.
if "[" in thing:
# handle primitive arrays
@@ -262,20 +339,28 @@ def _resolve_type(thing, line, level, var_handler):
# Special case: Handle the generic matrices.
if contr == matrix_pattern:
return handle_matrix(thing)
- contr = var_handler(_resolve_type(contr, line, level+1, var_handler))
+ contr = var_handler(_resolve_type(contr, line, level + 1, var_handler))
if isinstance(contr, _NotCalled):
raise SystemError("Container types must exist:", repr(contr))
contr = to_string(contr)
pieces = []
for part in _parse_arglist(thing):
- part = var_handler(_resolve_type(part, line, level+1, var_handler))
+ part = var_handler(_resolve_type(part, line, level + 1, var_handler))
if isinstance(part, _NotCalled):
# fix the tag (i.e. "Missing") by repr
part = repr(part)
pieces.append(to_string(part))
thing = ", ".join(pieces)
result = f"{contr}[{thing}]"
- return eval(result, namespace)
+ # PYSIDE-1538: Make sure that the eval does not crash.
+ try:
+ return eval(result, globals(), namespace)
+ except Exception:
+ warnings.warn(f"""pyside_type_init:_resolve_type
+
+ UNRECOGNIZED: {result!r}
+ OFFENDING LINE: {line!r}
+ """, RuntimeWarning)
return _resolve_value(thing, None, line)
@@ -328,16 +413,20 @@ def calculate_props(line):
name, ann = tup[:2]
if ann == "...":
name = "*args" if name.startswith("arg_") else "*" + name
- # copy the pathed fields back
+ # copy the patched fields back
ann = 'nullptr' # maps to None
tup = name, ann
arglist[idx] = tup
- annotations[name] = _resolve_type(ann, line, 0, handle_argvar)
+ annotations[name] = _resolve_type(ann, line, 0, handle_argvar, parsed.funcname)
if len(tup) == 3:
default = _resolve_value(tup[2], ann, line)
_defaults.append(default)
defaults = tuple(_defaults)
returntype = parsed.returntype
+ if isinstance(returntype, str) and returntype.startswith("("):
+ # PYSIDE-1588: Simplify the handling of returned tuples for now.
+ # Later we might create named tuples, instead.
+ returntype = "Tuple"
# PYSIDE-1383: We need to handle `None` explicitly.
annotations["return"] = (_resolve_type(returntype, line, 0, handle_retvar)
if returntype is not None else None)
@@ -345,9 +434,9 @@ def calculate_props(line):
props.defaults = defaults
props.kwdefaults = {}
props.annotations = annotations
- props.varnames = varnames = tuple(tup[0] for tup in arglist)
+ props.varnames = tuple(tup[0] for tup in arglist)
funcname = parsed.funcname
- shortname = funcname[funcname.rindex(".")+1:]
+ shortname = funcname[funcname.rindex(".") + 1:]
props.name = shortname
props.multi = parsed.multi
fix_variables(props, line)
@@ -378,7 +467,9 @@ def fix_variables(props, line):
if not isinstance(ann, ResultVariable):
continue
# We move the variable to the end and remove it.
- retvars.append(ann.type)
+ # PYSIDE-1409: If the variable was the first arg, we move it to the front.
+ # XXX This algorithm should probably be replaced by more introspection.
+ retvars.insert(0 if idx == 0 else len(retvars), ann.type)
deletions.append(idx)
del annos[name]
for idx in reversed(deletions):
@@ -391,7 +482,6 @@ def fix_variables(props, line):
else:
diff -= 1
if retvars:
- rvs = []
retvars = list(handle_retvar(rv) if isinstance(rv, ArrayLikeVariable) else rv
for rv in retvars)
if len(retvars) == 1:
@@ -399,7 +489,7 @@ def fix_variables(props, line):
else:
retvars_str = ", ".join(map(to_string, retvars))
typestr = f"typing.Tuple[{retvars_str}]"
- returntype = eval(typestr, namespace)
+ returntype = eval(typestr, globals(), namespace)
props.annotations["return"] = returntype
props.varnames = tuple(varnames)
props.defaults = tuple(defaults)
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
index 4cbec4824..0f05aea8b 100644
--- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/qt_attribution.json
@@ -3,7 +3,7 @@
"Name": "Python",
"QDocModule": "QtForPython",
"QtUsage": "Used for Qt for Python in the signature extension.",
- "Description": "Qt for Python is an add-on for Python. The signature packages of PySide uses certain copied and adapted source files (backport_inspect.py, typing27.py). See the folder sources/shiboken6/files.dir/shibokensupport/signature .",
+ "Description": "Qt for Python is an add-on for Python. The signature packages of PySide uses certain copied and adapted source files. See the folder sources/shiboken6/files.dir/shibokensupport .",
"Homepage": "http://www.python.org/",
"Version": "3.7.0",
"LicenseId": "Python-2.0",