14from zipfile
import ZipInfo
16from .compat
import sysconfig, detect_encoding, ZipFile
17from .resources
import finder
18from .util
import (FileOperator, get_export_entry, convert_path,
19 get_executable, get_platform, in_venv)
23_DEFAULT_MANIFEST =
'''
24<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
25<assembly xmlns="urn:schemas-microsoft-com:asm.v1" manifestVersion="1.0">
26 <assemblyIdentity version="1.0.0.0"
27 processorArchitecture="X86"
31 <!-- Identify the application security requirements. -->
32 <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3">
35 <requestedExecutionLevel level="asInvoker" uiAccess="false"/>
36 </requestedPrivileges>
42FIRST_LINE_RE =
re.compile(b
'^#!.*pythonw?[0-9.]*([ \t].*)?$')
43SCRIPT_TEMPLATE =
r'''# -*- coding: utf-8 -*-
46from %(module)s import %(import_name)s
47if __name__ == '__main__':
48 sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
62 executable =
'%s "%s"' % (env, _executable)
65 executable =
'"%s"' % executable
69_enquote_executable = enquote_executable
73 A class to copy or create scripts from source scripts or callable
76 script_template = SCRIPT_TEMPLATE
80 def __init__(self, source_dir, target_dir, add_launchers=True,
81 dry_run=False, fileop=None):
107 Determine if the specified executable is a script
111 with open(executable)
as fp:
113 except (OSError, IOError):
127 return '/usr/bin/env %s' % executable
131 Build a shebang line. In the simple case (on Windows, or a shebang line
132 which is not too long or contains spaces) use a simple formulation for
133 the shebang. Otherwise, use /bin/sh as the executable, with a contrived
134 shebang which allows the script to run either under Python or sh, using
135 suitable quoting. Thanks to Harald Nordgren for his input.
137 See also: http://www.in-ulm.de/~mascheck/various/shebang/#length
138 https://hg.mozilla.org/mozilla-central/file/tip/mach
141 simple_shebang =
True
144 shebang_length =
len(executable) +
len(post_interp) + 3
146 max_shebang_length = 512
148 max_shebang_length = 127
149 simple_shebang = ((b
' ' not in executable)
and
150 (shebang_length <= max_shebang_length))
153 result = b
'#!' + executable + post_interp + b
'\n'
155 result = b
'#!/bin/sh\n'
156 result += b
"'''exec' " + executable + post_interp + b
' "$0" "$@"\n'
166 executable = get_executable()
203 if (
sys.platform ==
'cli' and '-X:Frames' not in post_interp
204 and '-X:FullFrames' not in post_interp):
205 post_interp += b
' -X:Frames'
214 except UnicodeDecodeError:
216 'The shebang (%r) is not decodable from utf-8' % shebang)
220 if encoding !=
'utf-8':
223 except UnicodeDecodeError:
225 'The shebang (%r) is not decodable '
226 'from the script encoding (%r)' % (shebang, encoding))
234 manifest = _DEFAULT_MANIFEST
246 script_bytes = shebang + script_bytes
253 with ZipFile(stream,
'w')
as zf:
255 if source_date_epoch:
256 date_time =
time.gmtime(int(source_date_epoch))[:6]
257 zinfo = ZipInfo(filename=
'__main__.py', date_time=date_time)
262 script_bytes = launcher + shebang + zip_data
269 outname =
'%s.exe' % outname
271 self.
_fileop.write_binary_file(outname, script_bytes)
275 'use .deleteme logic')
276 dfname =
'%s.deleteme' % outname
280 self.
_fileop.write_binary_file(outname, script_bytes)
289 outname =
'%s.%s' % (outname, ext)
293 self.
_fileop.write_binary_file(outname, script_bytes)
295 self.
_fileop.set_executable_mode([outname])
298 variant_separator =
'-'
316 args =
' %s' %
' '.join(args)
318 shebang = self.
_get_shebang(
'utf-8', post_interp, options=options)
325 self.
_write_script(scriptnames, shebang, script, filenames, ext)
331 if not self.
force and not self.
_fileop.newer(script, outname):
339 f = open(script,
'rb')
358 self.
_fileop.copy_file(script, outname)
360 self.
_fileop.set_executable_mode([outname])
363 logger.info(
'copying and adjusting %s -> %s', script,
369 if b
'pythonw' in first_line:
395 platform_suffix =
'-arm' if get_platform() ==
'win-arm64' else ''
396 name =
'%s%s%s.exe' % (kind, bits, platform_suffix)
400 resource = finder(distlib_package).find(name)
402 msg = (
'Unable to find resource %s in package %s' % (name,
404 raise ValueError(msg)
409 def make(self, specification, options=None):
413 :param specification: The specification, which is either a valid export
414 entry specification (to make a script from a
415 callable) or a filename (to make a script by
416 copying from a source location).
417 :param options: A dictionary of options controlling script generation.
418 :return: A list of all absolute pathnames written to.
421 entry = get_export_entry(specification)
430 Take a list of specifications and make scripts from them,
431 :param specifications: A list of specifications.
432 :return: A list of all absolute pathnames written to,
435 for specification
in specifications:
get_manifest(self, exename)
_build_shebang(self, executable, post_interp)
_is_shell(self, executable)
_get_launcher(self, kind)
_get_shebang(self, encoding, post_interp=b'', options=None)
_write_script(self, names, shebang, script_bytes, filenames, ext)
_get_script_text(self, entry)
make_multiple(self, specifications, options=None)
_get_alternate_executable(self, executable, options)
_fix_jython_executable(self, executable)
_copy_script(self, script, filenames)
_make_script(self, entry, filenames, options=None)
__init__(self, source_dir, target_dir, add_launchers=True, dry_run=False, fileop=None)
get_script_filenames(self, name)
make(self, specification, options=None)
enquote_executable(executable)