__init__.py 6.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144
  1. import os
  2. import sys
  3. from pathlib import Path
  4. from types import ModuleType
  5. # mypy: disable-error-code="name-defined"
  6. # __all__ is computed below.
  7. __pre_all__ = ["QtCore", "QtGui", "QtWidgets", "QtPrintSupport", "QtSql", "QtNetwork", "QtTest", "QtConcurrent", "QtDBus", "QtDesigner", "QtXml", "QtHelp", "QtMultimedia", "QtMultimediaWidgets", "QtOpenGL", "QtOpenGLWidgets", "QtPdf", "QtPdfWidgets", "QtPositioning", "QtLocation", "QtNetworkAuth", "QtNfc", "QtQml", "QtQuick", "QtQuick3D", "QtQuickControls2", "QtQuickTest", "QtQuickWidgets", "QtRemoteObjects", "QtScxml", "QtSensors", "QtSerialPort", "QtSerialBus", "QtStateMachine", "QtTextToSpeech", "QtCharts", "QtSpatialAudio", "QtSvg", "QtSvgWidgets", "QtDataVisualization", "QtGraphs", "QtGraphsWidgets", "QtBluetooth", "QtUiTools", "QtAxContainer", "QtWebChannel", "QtWebEngineCore", "QtWebEngineWidgets", "QtWebEngineQuick", "QtWebSockets", "QtHttpServer", "QtWebView", "Qt3DCore", "Qt3DRender", "Qt3DInput", "Qt3DLogic", "Qt3DAnimation", "Qt3DExtras"]
  8. __version__ = "6.10.1"
  9. __version_info__ = (6, 10, 1, "", "")
  10. SKIP_MYPY_TEST = bool("")
  11. def _additional_dll_directories(package_dir):
  12. # Find shiboken6 relative to the package directory.
  13. root = Path(package_dir).parent
  14. # Check for a flat .zip as deployed by cx_free(PYSIDE-1257)
  15. if root.suffix == '.zip':
  16. return []
  17. shiboken6 = root / 'shiboken6'
  18. if shiboken6.is_dir(): # Standard case, only shiboken6 is needed
  19. return [shiboken6]
  20. # The below code is for the build process when generate_pyi.py
  21. # is executed in the build directory. We need libpyside and Qt in addition.
  22. shiboken6 = Path(root).parent / 'shiboken6' / 'libshiboken'
  23. if not shiboken6.is_dir():
  24. raise ImportError(str(shiboken6) + ' does not exist')
  25. result = [shiboken6, root / 'libpyside']
  26. libpysideqml = root / 'libpysideqml'
  27. if libpysideqml.is_dir():
  28. result.append(libpysideqml)
  29. for path in os.environ.get('PATH').split(';'):
  30. if path:
  31. if (Path(path) / 'qmake.exe').exists():
  32. result.append(path)
  33. break
  34. return result
  35. def _setupQtDirectories():
  36. # On Windows we need to explicitly import the shiboken6 module so
  37. # that the libshiboken.dll dependency is loaded by the time a
  38. # Qt module is imported. Otherwise due to PATH not containing
  39. # the shiboken6 module path, the Qt module import would fail
  40. # due to the missing libshiboken dll.
  41. # In addition, as of Python 3.8, the shiboken package directory
  42. # must be added to the DLL search paths so that shiboken6.dll
  43. # is found.
  44. # We need to do the same on Linux and macOS, because we do not
  45. # embed rpaths into the PySide6 libraries that would point to
  46. # the libshiboken library location. Importing the module
  47. # loads the libraries into the process memory beforehand, and
  48. # thus takes care of it for us.
  49. pyside_package_dir = Path(__file__).parent.resolve()
  50. if sys.platform == 'win32':
  51. for dir in _additional_dll_directories(pyside_package_dir):
  52. os.add_dll_directory(os.fspath(dir))
  53. try:
  54. # PYSIDE-1497: we use the build dir or install dir or site-packages, whatever the path
  55. # setting dictates. There is no longer a difference in path structure.
  56. global Shiboken
  57. from shiboken6 import Shiboken
  58. except Exception as e:
  59. paths = ', '.join(sys.path)
  60. print(f"PySide6/__init__.py: Unable to import Shiboken from {paths}: {e}",
  61. file=sys.stderr)
  62. raise
  63. if sys.platform == 'win32':
  64. # PATH has to contain the package directory, otherwise plugins
  65. # won't be able to find their required Qt libraries (e.g. the
  66. # svg image plugin won't find Qt5Svg.dll).
  67. os.environ['PATH'] = os.fspath(pyside_package_dir) + os.pathsep + os.environ['PATH']
  68. # On Windows, add the PySide6\openssl folder (created by setup.py's
  69. # --openssl option) to the PATH so that the SSL DLLs can be found
  70. # when Qt tries to dynamically load them. Tell Qt to load them and
  71. # then reset the PATH.
  72. openssl_dir = pyside_package_dir / 'openssl'
  73. if openssl_dir.exists():
  74. path = os.environ['PATH']
  75. try:
  76. os.environ['PATH'] = os.fspath(openssl_dir) + os.pathsep + path
  77. try:
  78. from . import QtNetwork
  79. except ImportError:
  80. pass
  81. else:
  82. QtNetwork.QSslSocket.supportsSsl()
  83. finally:
  84. os.environ['PATH'] = path
  85. def _find_all_qt_modules():
  86. # Since the wheel split, the __all__ variable cannot be computed statically,
  87. # because we don't know all modules in advance.
  88. # Instead, we use __getattr__ which is supported since Python 3.7
  89. # and create the __all__ list on demand when needed.
  90. unordered = set()
  91. pattern = "Qt*.pyd" if sys.platform == "win32" else "Qt*.so"
  92. for module in Path(__file__).resolve().parent.glob(pattern):
  93. name = module.name[:module.name.find(".")]
  94. if name.endswith("_d"): # Windows debug suffix?
  95. name = name[:-2]
  96. unordered.add(name)
  97. ordered_part = __pre_all__
  98. result = []
  99. for name in ordered_part:
  100. if name in unordered:
  101. result.append(name)
  102. unordered.remove(name)
  103. result.extend(unordered)
  104. return result
  105. # Provide the __all__ variable only on access.
  106. def __getattr__(name: str) -> list[str]:
  107. if name == "__all__":
  108. global __all__
  109. __all__ = _find_all_qt_modules()
  110. return __all__
  111. raise AttributeError(f"module '{__name__}' has no attribute '{name}' :)")
  112. # Be prepared that people can access the module dict instead.
  113. class ModuleDict(dict):
  114. def __missing__(self, key):
  115. if key == "__all__":
  116. self[key] = __all__ if "__all__" in globals() else __getattr__("__all__")
  117. return __all__
  118. raise KeyError(f"dict of module '{__name__}' has no key '{key}' :)")
  119. class SubModule(ModuleType):
  120. pass
  121. _setupQtDirectories()
  122. Shiboken.replaceModuleDict(sys.modules["PySide6"], SubModule, ModuleDict(globals()))