]>
jfr.im git - dlqueue.git/blob - venv/lib/python3.11/site-packages/setuptools/_distutils/command/build_scripts.py
1 """distutils.command.build_scripts
3 Implements the Distutils 'build_scripts' command."""
7 from stat
import ST_MODE
8 from distutils
import sysconfig
9 from ..core
import Command
10 from ..dep_util
import newer
11 from ..util
import convert_path
12 from distutils
._log
import log
15 shebang_pattern
= re
.compile('^#!.*python[0-9.]*([ \t].*)?$')
17 Pattern matching a Python interpreter indicated in first line of a script.
20 # for Setuptools compatibility
21 first_line_re
= shebang_pattern
24 class build_scripts(Command
):
25 description
= "\"build\" scripts (copy and fixup #! line)"
28 ('build-dir=', 'd', "directory to \"build\" (copy) to"),
29 ('force', 'f', "forcibly build everything (ignore file timestamps"),
30 ('executable=', 'e', "specify final destination interpreter path"),
33 boolean_options
= ['force']
35 def initialize_options(self
):
39 self
.executable
= None
41 def finalize_options(self
):
42 self
.set_undefined_options(
44 ('build_scripts', 'build_dir'),
46 ('executable', 'executable'),
48 self
.scripts
= self
.distribution
.scripts
50 def get_source_files(self
):
58 def copy_scripts(self
):
60 Copy each script listed in ``self.scripts``.
62 If a script is marked as a Python script (first line matches
63 'shebang_pattern', i.e. starts with ``#!`` and contains
64 "python"), then adjust in the copy the first line to refer to
65 the current Python interpreter.
67 self
.mkpath(self
.build_dir
)
70 for script
in self
.scripts
:
71 self
._copy
_script
(script
, outfiles
, updated_files
)
73 self
._change
_modes
(outfiles
)
75 return outfiles
, updated_files
77 def _copy_script(self
, script
, outfiles
, updated_files
): # noqa: C901
79 script
= convert_path(script
)
80 outfile
= os
.path
.join(self
.build_dir
, os
.path
.basename(script
))
81 outfiles
.append(outfile
)
83 if not self
.force
and not newer(script
, outfile
):
84 log
.debug("not copying %s (up-to-date)", script
)
87 # Always open the file, but ignore failures in dry-run mode
88 # in order to attempt to copy directly.
90 f
= tokenize
.open(script
)
96 first_line
= f
.readline()
98 self
.warn("%s is an empty file (skipping)" % script
)
101 shebang_match
= shebang_pattern
.match(first_line
)
103 updated_files
.append(outfile
)
105 log
.info("copying and adjusting %s -> %s", script
, self
.build_dir
)
107 if not sysconfig
.python_build
:
108 executable
= self
.executable
110 executable
= os
.path
.join(
111 sysconfig
.get_config_var("BINDIR"),
114 sysconfig
.get_config_var("VERSION"),
115 sysconfig
.get_config_var("EXE"),
118 post_interp
= shebang_match
.group(1) or ''
119 shebang
= "#!" + executable
+ post_interp
+ "\n"
120 self
._validate
_shebang
(shebang
, f
.encoding
)
121 with open(outfile
, "w", encoding
=f
.encoding
) as outf
:
123 outf
.writelines(f
.readlines())
129 self
.copy_file(script
, outfile
)
131 def _change_modes(self
, outfiles
):
132 if os
.name
!= 'posix':
135 for file in outfiles
:
136 self
._change
_mode
(file)
138 def _change_mode(self
, file):
140 log
.info("changing mode of %s", file)
143 oldmode
= os
.stat(file)[ST_MODE
] & 0o7777
144 newmode
= (oldmode |
0o555) & 0o7777
145 if newmode
!= oldmode
:
146 log
.info("changing mode of %s from %o to %o", file, oldmode
, newmode
)
147 os
.chmod(file, newmode
)
150 def _validate_shebang(shebang
, encoding
):
151 # Python parser starts to read a script using UTF-8 until
152 # it gets a #coding:xxx cookie. The shebang has to be the
153 # first line of a file, the #coding:xxx cookie cannot be
154 # written before. So the shebang has to be encodable to
157 shebang
.encode('utf-8')
158 except UnicodeEncodeError:
160 "The shebang ({!r}) is not encodable " "to utf-8".format(shebang
)
163 # If the script is encoded to a custom encoding (use a
164 # #coding:xxx cookie), the shebang has to be encodable to
165 # the script encoding too.
167 shebang
.encode(encoding
)
168 except UnicodeEncodeError:
170 "The shebang ({!r}) is not encodable "
171 "to the script encoding ({})".format(shebang
, encoding
)