dist_info.py 3.4 KB

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