2 Create a dist_info directory
3 As defined in the wheel specification
11 from contextlib
import contextmanager
12 from inspect
import cleandoc
13 from pathlib
import Path
15 from distutils
.core
import Command
16 from distutils
import log
17 from setuptools
.extern
import packaging
18 from setuptools
._deprecation
_warning
import SetuptoolsDeprecationWarning
21 class dist_info(Command
):
23 description
= 'create a .dist-info directory'
26 ('egg-base=', 'e', "directory containing .egg-info directories"
27 " (default: top of the source tree)"
28 " DEPRECATED: use --output-dir."),
29 ('output-dir=', 'o', "directory inside of which the .dist-info will be"
30 "created (default: top of the source tree)"),
31 ('tag-date', 'd', "Add date stamp (e.g. 20050528) to version number"),
32 ('tag-build=', 'b', "Specify explicit tag to add to version number"),
33 ('no-date', 'D', "Don't include date stamp [default]"),
34 ('keep-egg-info', None, "*TRANSITIONAL* will be removed in the future"),
37 boolean_options
= ['tag-date', 'keep-egg-info']
38 negative_opt
= {'no-date': 'tag-date'}
40 def initialize_options(self
):
42 self
.output_dir
= None
44 self
.dist_info_dir
= None
47 self
.keep_egg_info
= False
49 def finalize_options(self
):
51 msg
= "--egg-base is deprecated for dist_info command. Use --output-dir."
52 warnings
.warn(msg
, SetuptoolsDeprecationWarning
)
53 self
.output_dir
= self
.egg_base
or self
.output_dir
55 dist
= self
.distribution
56 project_dir
= dist
.src_root
or os
.curdir
57 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
)
63 egg_info
.tag_date
= self
.tag_date
65 self
.tag_date
= egg_info
.tag_date
68 egg_info
.tag_build
= self
.tag_build
70 self
.tag_build
= egg_info
.tag_build
72 egg_info
.finalize_options()
73 self
.egg_info
= egg_info
75 name
= _safe(dist
.get_name())
76 version
= _version(dist
.get_version())
77 self
.name
= f
"{name}-{version}"
78 self
.dist_info_dir
= os
.path
.join(self
.output_dir
, f
"{self.name}.dist-info")
81 def _maybe_bkp_dir(self
, dir_path
: str, requires_bkp
: bool):
83 bkp_name
= f
"{dir_path}.__bkp__"
84 _rm(bkp_name
, ignore_errors
=True)
85 _copy(dir_path
, bkp_name
, dirs_exist_ok
=True, symlinks
=True)
89 _rm(dir_path
, ignore_errors
=True)
90 shutil
.move(bkp_name
, dir_path
)
95 self
.output_dir
.mkdir(parents
=True, exist_ok
=True)
97 egg_info_dir
= self
.egg_info
.egg_info
98 assert os
.path
.isdir(egg_info_dir
), ".egg-info dir should have been created"
100 log
.info("creating '{}'".format(os
.path
.abspath(self
.dist_info_dir
)))
101 bdist_wheel
= self
.get_finalized_command('bdist_wheel')
103 # TODO: if bdist_wheel if merged into setuptools, just add "keep_egg_info" there
104 with self
._maybe
_bkp
_dir
(egg_info_dir
, self
.keep_egg_info
):
105 bdist_wheel
.egg2dist(egg_info_dir
, self
.dist_info_dir
)
108 def _safe(component
: str) -> str:
109 """Escape a component used to form a wheel name according to PEP 491"""
110 return re
.sub(r
"[^\w\d.]+", "_", component
)
113 def _version(version
: str) -> str:
114 """Convert an arbitrary string to a version string."""
115 v
= version
.replace(' ', '.')
117 return str(packaging
.version
.Version(v
)).replace("-", "_")
118 except packaging
.version
.InvalidVersion
:
119 msg
= f
"""Invalid version: {version!r}.
124 {version!r} is not valid according to PEP 440.\n
125 Please make sure specify a valid version for your package.
126 Also note that future releases of setuptools may halt the build process
127 if an invalid version is given.
130 warnings
.warn(cleandoc(msg
))
131 return _safe(v
).strip("_")
134 def _rm(dir_name
, **opts
):
135 if os
.path
.isdir(dir_name
):
136 shutil
.rmtree(dir_name
, **opts
)
139 def _copy(src
, dst
, **opts
):
140 if sys
.version_info
< (3, 8):
141 opts
.pop("dirs_exist_ok", None)
142 shutil
.copytree(src
, dst
, **opts
)