aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
diff options
context:
space:
mode:
Diffstat (limited to 'sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py')
-rw-r--r--sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py150
1 files changed, 150 insertions, 0 deletions
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
new file mode 100644
index 000000000..c2a19efef
--- /dev/null
+++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/errorhandler.py
@@ -0,0 +1,150 @@
+# 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
+
+This module handles the TypeError messages which were previously
+produced by the generated C code.
+
+This version is at least consistent with the signatures, which
+are created by the same module.
+
+Experimentally, we are trying to guess those errors which are
+just the wrong number of elements in an iterator.
+At the moment, it is unclear whether the information given is
+enough to produce a useful ValueError.
+
+This matter will be improved in a later version.
+"""
+
+import collections.abc
+import typing
+
+from shibokensupport.signature import get_signature
+from shibokensupport.signature.mapping import namespace
+from textwrap import dedent
+
+
+def qt_isinstance(inst, the_type):
+ if the_type == 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(f"FIXME qt_isinstance({inst}, {the_type}):", e)
+ return False
+
+
+def matched_type(args, sigs):
+ for sig in sigs:
+ params = list(sig.parameters.values())
+ if len(args) > len(params):
+ continue
+ if len(args) < len(params):
+ k = len(args)
+ if params[k].default is params[k].empty:
+ # this is a necessary parameter, so it fails.
+ continue
+ if all(qt_isinstance(arg, param.annotation) for arg, param in zip(args, params)):
+ return sig
+ return None
+
+
+def seterror_argument(args, func_name, info):
+ func = None
+ try:
+ func = eval(func_name, namespace)
+ except Exception as e:
+ 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():
+ msg = f"{func_name}(): got multiple values for keyword argument '{info}'"
+ else:
+ 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
+ sigs = get_signature(func, "typeerror")
+ if not sigs:
+ msg = f"{func_name}({args}) is wrong (missing signature)"
+ return TypeError, msg
+ if type(sigs) != list:
+ sigs = [sigs]
+ if type(args) != tuple:
+ args = (args,)
+ # temp!
+ found = matched_type(args, sigs)
+ if found:
+ msg = dedent(f"""
+ {func_name!r} called with wrong argument values:
+ {func_name}{args}
+ Found signature:
+ {func_name}{found}
+ """).strip()
+ return ValueError, msg
+ type_str = ", ".join(type(arg).__name__ for arg in args)
+ msg = dedent(f"""
+ {func_name!r} called with wrong argument types:
+ {func_name}({type_str})
+ Supported signatures:
+ """).strip()
+ for sig in sigs:
+ msg += f"\n {func_name}{sig}"
+ # We don't raise the error here, to avoid the loader in the traceback.
+ return TypeError, msg
+
+
+def check_string_type(s):
+ return isinstance(s, str)
+
+
+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
+ if type(sigs) != list:
+ sigs = [sigs]
+ try:
+ func_name = func.__name__
+ except AttributeError:
+ func_name = func.__func__.__name__
+ sigtext = "\n".join(func_name + str(sig) for sig in sigs)
+ msg = f"{sigtext}\n\n{existing_doc}" if check_string_type(existing_doc) else sigtext
+ return msg
+
+# end of file