diff options
Diffstat (limited to 'sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py')
-rw-r--r-- | sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py | 47 |
1 files changed, 33 insertions, 14 deletions
diff --git a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py index bbca35fbd..ce12dd6c8 100644 --- a/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py +++ b/sources/shiboken6/shibokenmodule/files.dir/shibokensupport/signature/lib/pyi_generator.py @@ -3,6 +3,8 @@ LICENSE_TEXT = """ # 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 @@ -21,7 +23,6 @@ from pathlib import Path from contextlib import contextmanager from textwrap import dedent -from shiboken6 import Shiboken from shibokensupport.signature.lib.enum_sig import HintingEnumerator from shibokensupport.signature.lib.tool import build_brace_pattern @@ -59,6 +60,7 @@ class Formatter(Writer): 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: @@ -74,8 +76,12 @@ class Formatter(Writer): """ def _typevar__repr__(self): return f"typing.{self.__name__}" - typing.TypeVar.__repr__ = _typevar__repr__ - + # 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. @@ -84,6 +90,7 @@ class Formatter(Writer): 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 @@ -152,6 +159,12 @@ class Formatter(Writer): 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}") @@ -165,12 +178,14 @@ def find_imports(text): FROM_IMPORTS = [ (None, ["builtins"]), (None, ["os"]), - (None, ["enum"] if sys.pyside63_option_python_enum else []), + (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 @@ -180,8 +195,15 @@ def filter_from_imports(from_struct, text): lis = [] nfs.append((mod, lis)) for each in imports: - if re.search(rf"(\b|@){each}\b([^\s\(:]|\n)", text): - lis.append(each) + # 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 @@ -220,12 +242,10 @@ def generate_pyi(import_name, outpath, options): 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}`") - module = sys.modules[import_name] outfile = io.StringIO() fmt = Formatter(outfile, options) fmt.print(LICENSE_TEXT.strip()) - need_imports = options._pyside_call and not USE_PEP563 if USE_PEP563: fmt.print("from __future__ import annotations") fmt.print() @@ -267,13 +287,12 @@ def generate_pyi(import_name, outpath, options): 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}") - # PYSIDE-1735: .pyi files are no longer compatible with Python, because - # enum classes contain ellipsis which a Python enum forbids. - # We will implement tests with Mypy, instead. def main(): @@ -288,11 +307,10 @@ def main(): 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)") + 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("--check", action="store_true", help="Test the output") parser.add_argument("--outpath", - help="the output directory (default = location of module binary)") + help="the output directory (default = location of module binary)") # noqa E:128 options = parser.parse_args() module = options.module outpath = options.outpath @@ -310,6 +328,7 @@ def main(): options.logger = logger generate_pyi(module, outpath, options=options) + if __name__ == "__main__": main() # eof |