hook-tkinterdnd2.py 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. # ------------------------------------------------------------------
  2. # Copyright (c) 2025 PyInstaller Development Team.
  3. #
  4. # This file is distributed under the terms of the GNU General Public
  5. # License (version 2.0 or later).
  6. #
  7. # The full license is available in LICENSE, distributed with
  8. # this software.
  9. #
  10. # SPDX-License-Identifier: GPL-2.0-or-later
  11. # ------------------------------------------------------------------
  12. import os
  13. import pathlib
  14. import platform
  15. from PyInstaller.utils.hooks import get_package_paths, logger
  16. # tkinterdnd2 contains a tkdnd sub-directory which contains platform-specific directories with shared library and .tcl
  17. # files. Collect only the relevant directory, by matching the decision logic from:
  18. # https://github.com/Eliav2/tkinterdnd2/blob/9a55907e430234bf8ab72ea614f84af9cc89598c/tkinterdnd2/TkinterDnD.py#L33-L51
  19. def _collect_platform_subdir(system, machine):
  20. datas = []
  21. binaries = []
  22. # Under Windows, `platform.machine()` returns the identifier of the *host* architecture, which does not necessarily
  23. # match the architecture of the running process (for example, when running x86 process under x64 Windows, or when
  24. # running either x86 or x64 process under arm64 Windows). The architecture of the running process can be obtained
  25. # from the `PROCESSOR_ARCHITECTURE` environment variable, which is automatically set by Windows / WOW64 subsystem.
  26. #
  27. # NOTE: at the time of writing (tkinterdnd2 v0.4.2), tkinterdnd2 does not account for this, and attempts to load
  28. # the shared library from incorrect directory; as this fails due to architecture mismatch, there is no point in
  29. # us trying to collect that (incorrect) directory.
  30. if system == "Windows":
  31. machine = os.environ.get("PROCESSOR_ARCHITECTURE", machine)
  32. # Resolve the platform-specific sub-directory name and shared library suffix.
  33. DIR_NAMES = {
  34. "Darwin": {
  35. "arm64": "osx-arm64",
  36. "x86_64": "osx-x64",
  37. },
  38. "Linux": {
  39. "aarch64": "linux-arm64",
  40. "x86_64": "linux-x64",
  41. },
  42. "Windows": {
  43. "ARM64": "win-arm64",
  44. "AMD64": "win-x64",
  45. "x86": "win-x86",
  46. }
  47. }
  48. dir_name = DIR_NAMES.get(system, {}).get(machine, None)
  49. LIB_SUFFICES = {
  50. "Darwin": "*.dylib",
  51. "Linux": "*.so",
  52. "Windows": "*.dll",
  53. }
  54. lib_suffix = LIB_SUFFICES.get(system, None)
  55. if dir_name is None or lib_suffix is None:
  56. logger.warning(
  57. "hook-tkinterdnd2: unsupported platform (%s, %s)! Platform-specific directory will not be collected!",
  58. system, machine
  59. )
  60. return datas, binaries
  61. pkg_base, pkg_dir = get_package_paths("tkinterdnd2")
  62. dest_dir = os.path.join("tkinterdnd2", "tkdnd", dir_name)
  63. src_path = pathlib.Path(pkg_dir) / "tkdnd" / dir_name
  64. if not src_path.is_dir():
  65. logger.warning("hook-tkinterdnd2: platform-specific sub-directory %r does not exist!", str(src_path))
  66. return datas, binaries
  67. # Collect the shared library.
  68. for entry in src_path.glob(lib_suffix):
  69. binaries.append((str(entry), dest_dir))
  70. # Collect the .tcl files.
  71. for entry in src_path.glob("*.tcl"):
  72. datas.append((str(entry), dest_dir))
  73. return datas, binaries
  74. datas, binaries = _collect_platform_subdir(platform.system(), platform.machine())