<s> from io import BytesIO <EOL> import logging <EOL> import os <EOL> import re <EOL> import struct <EOL> import sys <EOL> from . compat import sysconfig , detect_encoding , ZipFile <EOL> from . resources import finder <EOL> from . util import ( FileOperator , get_export_entry , convert_path , <EOL> get_executable , in_venv ) <EOL> logger = logging . getLogger ( __name__ ) <EOL> _DEFAULT_MANIFEST = '''<STR_LIT>''' . strip ( ) <EOL> FIRST_LINE_RE = re . compile ( b'<STR_LIT>' ) <EOL> SCRIPT_TEMPLATE = '''<STR_LIT>''' <EOL> def _enquote_executable ( executable ) : <EOL> if '<STR_LIT:U+0020>' in executable : <EOL> if executable . startswith ( '<STR_LIT>' ) : <EOL> env , _executable = executable . split ( '<STR_LIT:U+0020>' , <NUM_LIT:1> ) <EOL> if '<STR_LIT:U+0020>' in _executable and not _executable . startswith ( '<STR_LIT:">' ) : <EOL> executable = '<STR_LIT>' % ( env , _executable ) <EOL> else : <EOL> if not executable . startswith ( '<STR_LIT:">' ) : <EOL> executable = '<STR_LIT>' % executable <EOL> return executable <EOL> class ScriptMaker ( object ) : <EOL> """<STR_LIT>""" <EOL> script_template = SCRIPT_TEMPLATE <EOL> executable = None <EOL> def __init__ ( self , source_dir , target_dir , add_launchers = True , <EOL> dry_run = False , fileop = None ) : <EOL> self . source_dir = source_dir <EOL> self . target_dir = target_dir <EOL> self . add_launchers = add_launchers <EOL> self . force = False <EOL> self . clobber = False <EOL> self . set_mode = ( os . name == '<STR_LIT>' ) or ( os . name == '<STR_LIT>' and <EOL> os . _name == '<STR_LIT>' ) <EOL> self . variants = set ( ( '<STR_LIT>' , '<STR_LIT>' ) ) <EOL> self . _fileop = fileop or FileOperator ( dry_run ) <EOL> self . _is_nt = os . name == '<STR_LIT>' or ( <EOL> os . name == '<STR_LIT>' and os . _name == '<STR_LIT>' ) <EOL> def _get_alternate_executable ( self , executable , options ) : <EOL> if options . get ( '<STR_LIT>' , False ) and self . _is_nt : <EOL> dn , fn = os . path . split ( executable ) <EOL> fn = fn . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> executable = os . path . join ( dn , fn ) <EOL> return executable <EOL> if sys . platform . startswith ( '<STR_LIT>' ) : <EOL> def _is_shell ( self , executable ) : <EOL> """<STR_LIT>""" <EOL> try : <EOL> with open ( executable ) as fp : <EOL> return fp . read ( <NUM_LIT:2> ) == '<STR_LIT>' <EOL> except ( OSError , IOError ) : <EOL> logger . warning ( '<STR_LIT>' , executable ) <EOL> return False <EOL> def _fix_jython_executable ( self , executable ) : <EOL> if self . _is_shell ( executable ) : <EOL> import java <EOL> if java . lang . System . getProperty ( '<STR_LIT>' ) == '<STR_LIT>' : <EOL> return executable <EOL> elif executable . lower ( ) . endswith ( '<STR_LIT>' ) : <EOL> return executable <EOL> return '<STR_LIT>' % executable <EOL> def _get_shebang ( self , encoding , post_interp = b'<STR_LIT>' , options = None ) : <EOL> enquote = True <EOL> if self . executable : <EOL> executable = self . executable <EOL> enquote = False <EOL> elif not sysconfig . is_python_build ( ) : <EOL> executable = get_executable ( ) <EOL> elif in_venv ( ) : <EOL> executable = os . path . join ( sysconfig . get_path ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' % sysconfig . get_config_var ( '<STR_LIT>' ) ) <EOL> else : <EOL> executable = os . path . join ( <EOL> sysconfig . get_config_var ( '<STR_LIT>' ) , <EOL> '<STR_LIT>' % ( sysconfig . get_config_var ( '<STR_LIT>' ) , <EOL> sysconfig . get_config_var ( '<STR_LIT>' ) ) ) <EOL> if options : <EOL> executable = self . _get_alternate_executable ( executable , options ) <EOL> if sys . platform . startswith ( '<STR_LIT>' ) : <EOL> executable = self . _fix_jython_executable ( executable ) <EOL> executable = os . path . normcase ( executable ) <EOL> if enquote : <EOL> executable = _enquote_executable ( executable ) <EOL> executable = executable . encode ( '<STR_LIT:utf-8>' ) <EOL> if ( sys . platform == '<STR_LIT>' and '<STR_LIT>' not in post_interp <EOL> and '<STR_LIT>' not in post_interp ) : <EOL> post_interp += b'<STR_LIT>' <EOL> shebang = b'<STR_LIT>' + executable + post_interp + b'<STR_LIT:\n>' <EOL> try : <EOL> shebang . decode ( '<STR_LIT:utf-8>' ) <EOL> except UnicodeDecodeError : <EOL> raise ValueError ( <EOL> '<STR_LIT>' % shebang ) <EOL> if encoding != '<STR_LIT:utf-8>' : <EOL> try : <EOL> shebang . decode ( encoding ) <EOL> except UnicodeDecodeError : <EOL> raise ValueError ( <EOL> '<STR_LIT>' <EOL> '<STR_LIT>' % ( shebang , encoding ) ) <EOL> return shebang <EOL> def _get_script_text ( self , entry ) : <EOL> return self . script_template % dict ( module = entry . prefix , <EOL> func = entry . suffix ) <EOL> manifest = _DEFAULT_MANIFEST <EOL> def get_manifest ( self , exename ) : <EOL> base = os . path . basename ( exename ) <EOL> return self . manifest % base <EOL> def _write_script ( self , names , shebang , script_bytes , filenames , ext ) : <EOL> use_launcher = self . add_launchers and self . _is_nt <EOL> linesep = os . linesep . encode ( '<STR_LIT:utf-8>' ) <EOL> if not use_launcher : <EOL> script_bytes = shebang + linesep + script_bytes <EOL> else : <EOL> if ext == '<STR_LIT>' : <EOL> launcher = self . _get_launcher ( '<STR_LIT:t>' ) <EOL> else : <EOL> launcher = self . _get_launcher ( '<STR_LIT:w>' ) <EOL> stream = BytesIO ( ) <EOL> with ZipFile ( stream , '<STR_LIT:w>' ) as zf : <EOL> zf . writestr ( '<STR_LIT>' , script_bytes ) <EOL> zip_data = stream . getvalue ( ) <EOL> script_bytes = launcher + shebang + linesep + zip_data <EOL> for name in names : <EOL> outname = os . path . join ( self . target_dir , name ) <EOL> if use_launcher : <EOL> n , e = os . path . splitext ( outname ) <EOL> if e . startswith ( '<STR_LIT>' ) : <EOL> outname = n <EOL> outname = '<STR_LIT>' % outname <EOL> try : <EOL> self . _fileop . write_binary_file ( outname , script_bytes ) <EOL> except Exception : <EOL> logger . warning ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> dfname = '<STR_LIT>' % outname <EOL> if os . path . exists ( dfname ) : <EOL> os . remove ( dfname ) <EOL> os . rename ( outname , dfname ) <EOL> self . _fileop . write_binary_file ( outname , script_bytes ) <EOL> logger . debug ( '<STR_LIT>' <EOL> '<STR_LIT>' ) <EOL> try : <EOL> os . remove ( dfname ) <EOL> except Exception : <EOL> pass <EOL> else : <EOL> if self . _is_nt and not outname . endswith ( '<STR_LIT:.>' + ext ) : <EOL> outname = '<STR_LIT>' % ( outname , ext ) <EOL> if os . path . exists ( outname ) and not self . clobber : <EOL> logger . warning ( '<STR_LIT>' , outname ) <EOL> continue <EOL> self . _fileop . write_binary_file ( outname , script_bytes ) <EOL> if self . set_mode : <EOL> self . _fileop . set_executable_mode ( [ outname ] ) <EOL> filenames . append ( outname ) <EOL> def _make_script ( self , entry , filenames , options = None ) : <EOL> post_interp = b'<STR_LIT>' <EOL> if options : <EOL> args = options . get ( '<STR_LIT>' , [ ] ) <EOL> if args : <EOL> args = '<STR_LIT>' % '<STR_LIT:U+0020>' . join ( args ) <EOL> post_interp = args . encode ( '<STR_LIT:utf-8>' ) <EOL> shebang = self . _get_shebang ( '<STR_LIT:utf-8>' , post_interp , options = options ) <EOL> script = self . _get_script_text ( entry ) . encode ( '<STR_LIT:utf-8>' ) <EOL> name = entry . name <EOL> scriptnames = set ( ) <EOL> if '<STR_LIT>' in self . variants : <EOL> scriptnames . add ( name ) <EOL> if '<STR_LIT:X>' in self . variants : <EOL> scriptnames . add ( '<STR_LIT>' % ( name , sys . version [ <NUM_LIT:0> ] ) ) <EOL> if '<STR_LIT>' in self . variants : <EOL> scriptnames . add ( '<STR_LIT>' % ( name , sys . version [ : <NUM_LIT:3> ] ) ) <EOL> if options and options . get ( '<STR_LIT>' , False ) : <EOL> ext = '<STR_LIT>' <EOL> else : <EOL> ext = '<STR_LIT>' <EOL> self . _write_script ( scriptnames , shebang , script , filenames , ext ) <EOL> def _copy_script ( self , script , filenames ) : <EOL> adjust = False <EOL> script = os . path . join ( self . source_dir , convert_path ( script ) ) <EOL> outname = os . path . join ( self . target_dir , os . path . basename ( script ) ) <EOL> if not self . force and not self . _fileop . newer ( script , outname ) : <EOL> logger . debug ( '<STR_LIT>' , script ) <EOL> return <EOL> try : <EOL> f = open ( script , '<STR_LIT:rb>' ) <EOL> except IOError : <EOL> if not self . dry_run : <EOL> raise <EOL> f = None <EOL> else : <EOL> first_line = f . readline ( ) <EOL> if not first_line : <EOL> logger . warning ( '<STR_LIT>' , <EOL> self . get_command_name ( ) , script ) <EOL> return <EOL> match = FIRST_LINE_RE . match ( first_line . replace ( b'<STR_LIT:\r\n>' , b'<STR_LIT:\n>' ) ) <EOL> if match : <EOL> adjust = True <EOL> post_interp = match . group ( <NUM_LIT:1> ) or b'<STR_LIT>' <EOL> if not adjust : <EOL> if f : <EOL> f . close ( ) <EOL> self . _fileop . copy_file ( script , outname ) <EOL> if self . set_mode : <EOL> self . _fileop . set_executable_mode ( [ outname ] ) <EOL> filenames . append ( outname ) <EOL> else : <EOL> logger . info ( '<STR_LIT>' , script , <EOL> self . target_dir ) <EOL> if not self . _fileop . dry_run : <EOL> encoding , lines = detect_encoding ( f . readline ) <EOL> f . seek ( <NUM_LIT:0> ) <EOL> shebang = self . _get_shebang ( encoding , post_interp ) <EOL> if b'<STR_LIT>' in first_line : <EOL> ext = '<STR_LIT>' <EOL> else : <EOL> ext = '<STR_LIT>' <EOL> n = os . path . basename ( outname ) <EOL> self . _write_script ( [ n ] , shebang , f . read ( ) , filenames , ext ) <EOL> if f : <EOL> f . close ( ) <EOL> @ property <EOL> def dry_run ( self ) : <EOL> return self . _fileop . dry_run <EOL> @ dry_run . setter <EOL> def dry_run ( self , value ) : <EOL> self . _fileop . dry_run = value <EOL> if os . name == '<STR_LIT>' or ( os . name == '<STR_LIT>' and os . _name == '<STR_LIT>' ) : <EOL> def _get_launcher ( self , kind ) : <EOL> if struct . calcsize ( '<STR_LIT:P>' ) == <NUM_LIT:8> : <EOL> bits = '<STR_LIT>' <EOL> else : <EOL> bits = '<STR_LIT>' <EOL> name = '<STR_LIT>' % ( kind , bits ) <EOL> distlib_package = __name__ . rsplit ( '<STR_LIT:.>' , <NUM_LIT:1> ) [ <NUM_LIT:0> ] <EOL> result = finder ( distlib_package ) . find ( name ) . bytes <EOL> return result <EOL> def make ( self , specification , options = None ) : <EOL> """<STR_LIT>""" <EOL> filenames = [ ] <EOL> entry = get_export_entry ( specification ) <EOL> if entry is None : <EOL> self . _copy_script ( specification , filenames ) <EOL> else : <EOL> self . _make_script ( entry , filenames , options = options ) <EOL> return filenames <EOL> def make_multiple ( self , specifications , options = None ) : <EOL> """<STR_LIT>""" <EOL> filenames = [ ] <EOL> for specification in specifications : <EOL> filenames . extend ( self . make ( specification , options ) ) <EOL> return filenames </s>
