dist_info.py 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. """
  2. Create a dist_info directory
  3. As defined in the wheel specification
  4. """
  5. import os
  6. import shutil
  7. import sys
  8. from contextlib import contextmanager
  9. from distutils import log
  10. from distutils.core import Command
  11. from pathlib import Path
  12. from .. import _normalization
  13. from ..warnings import SetuptoolsDeprecationWarning
  14. class dist_info(Command):
  15. """
  16. This command is private and reserved for internal use of setuptools,
  17. users should rely on ``setuptools.build_meta`` APIs.
  18. """
  19. description = "DO NOT CALL DIRECTLY, INTERNAL ONLY: create .dist-info directory"
  20. user_options = [
  21. (
  22. 'egg-base=',
  23. 'e',
  24. "directory containing .egg-info directories"
  25. " (default: top of the source tree)"
  26. " DEPRECATED: use --output-dir.",
  27. ),
  28. (
  29. 'output-dir=',
  30. 'o',
  31. "directory inside of which the .dist-info will be"
  32. "created (default: top of the source tree)",
  33. ),
  34. ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"),
  35. ('tag-build=', 'b', "Specify explicit tag to add to version number"),
  36. ('no-date', 'D', "Don't include date stamp [default]"),
  37. ('keep-egg-info', None, "*TRANSITIONAL* will be removed in the future"),
  38. ]
  39. boolean_options = ['tag-date', 'keep-egg-info']
  40. negative_opt = {'no-date': 'tag-date'}
  41. def initialize_options(self):
  42. self.egg_base = None
  43. self.output_dir = None
  44. self.name = None
  45. self.dist_info_dir = None
  46. self.tag_date = None
  47. self.tag_build = None
  48. self.keep_egg_info = False
  49. def finalize_options(self):
  50. if self.egg_base:
  51. msg = "--egg-base is deprecated for dist_info command. Use --output-dir."
  52. SetuptoolsDeprecationWarning.emit(msg, due_date=(2023, 9, 26))
  53. # This command is internal to setuptools, therefore it should be safe
  54. # to remove the deprecated support soon.
  55. self.output_dir = self.egg_base or self.output_dir
  56. dist = self.distribution
  57. project_dir = dist.src_root or os.curdir
  58. self.output_dir = Path(self.output_dir or project_dir)
  59. egg_info = self.reinitialize_command("egg_info")
  60. egg_info.egg_base = str(self.output_dir)
  61. if self.tag_date:
  62. egg_info.tag_date = self.tag_date
  63. else:
  64. self.tag_date = egg_info.tag_date
  65. if self.tag_build:
  66. egg_info.tag_build = self.tag_build
  67. else:
  68. self.tag_build = egg_info.tag_build
  69. egg_info.finalize_options()
  70. self.egg_info = egg_info
  71. name = _normalization.safer_name(dist.get_name())
  72. version = _normalization.safer_best_effort_version(dist.get_version())
  73. self.name = f"{name}-{version}"
  74. self.dist_info_dir = os.path.join(self.output_dir, f"{self.name}.dist-info")
  75. @contextmanager
  76. def _maybe_bkp_dir(self, dir_path: str, requires_bkp: bool):
  77. if requires_bkp:
  78. bkp_name = f"{dir_path}.__bkp__"
  79. _rm(bkp_name, ignore_errors=True)
  80. _copy(dir_path, bkp_name, dirs_exist_ok=True, symlinks=True)
  81. try:
  82. yield
  83. finally:
  84. _rm(dir_path, ignore_errors=True)
  85. shutil.move(bkp_name, dir_path)
  86. else:
  87. yield
  88. def run(self):
  89. self.output_dir.mkdir(parents=True, exist_ok=True)
  90. self.egg_info.run()
  91. egg_info_dir = self.egg_info.egg_info
  92. assert os.path.isdir(egg_info_dir), ".egg-info dir should have been created"
  93. log.info("creating '{}'".format(os.path.abspath(self.dist_info_dir)))
  94. bdist_wheel = self.get_finalized_command('bdist_wheel')
  95. # TODO: if bdist_wheel if merged into setuptools, just add "keep_egg_info" there
  96. with self._maybe_bkp_dir(egg_info_dir, self.keep_egg_info):
  97. bdist_wheel.egg2dist(egg_info_dir, self.dist_info_dir)
  98. def _rm(dir_name, **opts):
  99. if os.path.isdir(dir_name):
  100. shutil.rmtree(dir_name, **opts)
  101. def _copy(src, dst, **opts):
  102. if sys.version_info < (3, 8):
  103. opts.pop("dirs_exist_ok", None)
  104. shutil.copytree(src, dst, **opts)