generate_pyi.py 3.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495
  1. # Copyright (C) 2022 The Qt Company Ltd.
  2. # SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
  3. from __future__ import annotations
  4. """
  5. generate_pyi.py
  6. This script generates the .pyi files for all PySide modules.
  7. """
  8. # mypy: disable-error-code="import-not-found"
  9. import argparse
  10. import inspect # noqa: F401
  11. import logging
  12. import os
  13. import sys
  14. import typing # noqa: F401
  15. from pathlib import Path
  16. from types import SimpleNamespace # noqa: F401
  17. # Can we use forward references?
  18. USE_PEP563 = sys.version_info[:2] >= (3, 7)
  19. def generate_all_pyi(outpath, options):
  20. ps = os.pathsep
  21. if options.sys_path:
  22. # make sure to propagate the paths from sys_path to subprocesses
  23. normpath = lambda x: os.fspath(Path(x).resolve()) # noqa: E731
  24. sys_path = [normpath(_) for _ in options.sys_path]
  25. sys.path[0:0] = sys_path
  26. pypath = ps.join(sys_path)
  27. os.environ["PYTHONPATH"] = pypath
  28. # now we can import
  29. global PySide6, inspect, typing, HintingEnumerator, build_brace_pattern
  30. import PySide6
  31. from PySide6.support.signature.lib.enum_sig import HintingEnumerator
  32. from PySide6.support.signature.lib.tool import build_brace_pattern
  33. from PySide6.support.signature.lib.pyi_generator import generate_pyi
  34. # propagate USE_PEP563 to the mapping module.
  35. # Perhaps this can be automated?
  36. PySide6.support.signature.mapping.USE_PEP563 = USE_PEP563
  37. outpath = Path(outpath) if outpath and os.fspath(outpath) else Path(PySide6.__file__).parent
  38. name_list = PySide6.__all__ if options.modules == ["all"] else options.modules
  39. errors = ", ".join(set(name_list) - set(PySide6.__all__))
  40. if errors:
  41. raise ImportError(f"The module(s) '{errors}' do not exist")
  42. for mod_name in name_list:
  43. import_name = "PySide6." + mod_name
  44. if hasattr(sys, "pypy_version_info"):
  45. # PYSIDE-535: We cannot use __feature__ yet in PyPy
  46. generate_pyi(import_name, outpath, options)
  47. else:
  48. from PySide6.support import feature
  49. feature_id = feature.get_select_id(options.feature)
  50. with feature.force_selection(feature_id, import_name):
  51. generate_pyi(import_name, outpath, options)
  52. if __name__ == "__main__":
  53. parser = argparse.ArgumentParser(
  54. description="This script generates the .pyi file for all PySide modules.")
  55. parser.add_argument("modules", nargs="+",
  56. help="'all' or the names of modules to build (QtCore QtGui etc.)")
  57. parser.add_argument("--quiet", action="store_true", help="Run quietly")
  58. parser.add_argument("--outpath",
  59. help="the output directory (default = binary location)")
  60. parser.add_argument("--sys-path", nargs="+",
  61. help="a list of strings prepended to sys.path")
  62. parser.add_argument("--feature", nargs="+", choices=["snake_case", "true_property"], default=[],
  63. help="""a list of feature names. """
  64. """Example: `--feature snake_case true_property`. """
  65. """Currently not available for PyPy.""")
  66. options = parser.parse_args()
  67. qtest_env = os.environ.get("QTEST_ENVIRONMENT", "")
  68. log_level = logging.DEBUG if qtest_env else logging.INFO
  69. if options.quiet:
  70. log_level = logging.WARNING
  71. logging.basicConfig(level=log_level)
  72. logger = logging.getLogger("generate_pyi")
  73. outpath = options.outpath
  74. if outpath and not Path(outpath).exists():
  75. os.makedirs(outpath)
  76. logger.info(f"+++ Created path {outpath}")
  77. options._pyside_call = True
  78. options.logger = logger
  79. options.is_ci = qtest_env == "ci"
  80. generate_all_pyi(outpath, options=options)
  81. # eof