def write_script(path, entry_pt, egg_name): """ Write an entry point script to path. """ if verbose: print 'Creating script: %s' % path assert entry_pt.count(':') == 1 module, func = entry_pt.strip().split(':') python = executable if on_win: if path.endswith('pyw'): p = re.compile('python\.exe$', re.I) python = p.sub('pythonw.exe', python) python = '"%s"' % python rm_rf(path) fo = open(path, 'w') fo.write('''\ #!%(python)s # This script was created by egginst when installing: # # %(egg_name)s # if __name__ == '__main__': import sys from %(module)s import %(func)s sys.exit(%(func)s()) ''' % locals()) fo.close() os.chmod(path, 0755)
def create_proxies(egg): # This function is called on Windows only if not isdir(egg.bin_dir): os.makedirs(egg.bin_dir) for line in egg.lines_from_arcname('EGG-INFO/inst/files_to_install.txt'): arcname, action = line.split() if verbose: print "arcname=%r action=%r" % (arcname, action) if action == 'PROXY': ei = 'EGG-INFO/' if arcname.startswith(ei): src = abspath(join(egg.meta_dir, arcname[len(ei):])) else: src = abspath(join(egg.prefix, arcname)) if verbose: print " src: %r" % src egg.files.extend(create_proxy(src, egg.bin_dir)) else: data = egg.z.read(arcname) dst = abspath(join(egg.prefix, action, basename(arcname))) if verbose: print " dst: %r" % dst rm_rf(dst) fo = open(dst, 'wb') fo.write(data) fo.close() egg.files.append(dst)
def write_exe(dst, script_type='console_scripts'): """ This function is only used on Windows. It either writes cli.exe or gui.exe to the destination specified, depending on script_type. The binary content of these files are read from the module exe_data, which may be generated by the following small script (run from the setuptools directory which contains the file cli.exe and gui.exe: fo = open('exe_data.py', 'w') for name in ['cli', 'gui']: data = open('%s.exe' % name, 'rb').read() fo.write('%s = %r\n' % (name, data)) fo.close() """ if script_type == 'console_scripts': from exe_data import cli as data elif script_type == 'gui_scripts': from exe_data import gui as data else: raise Exception("Did not except script_type=%r" % script_type) rm_rf(dst) try: open(dst, 'wb').write(data) except IOError: # When bootstrapping, the file egginst.exe is in use and can therefore # not be rewritten, which is OK since its content is always the same. pass os.chmod(dst, 0755)
def remove(self): rm_rf(self.entry_path) for fn in os.listdir(appdir): if fn.startswith(self.name_): # found one shortcut, so don't remove the name from menu return self._remove_this_menu()
def write_exe(dst, script_type='console_scripts'): """ This function is only used on Windows. It either writes cli.exe or gui.exe to the destination specified, depending on script_type. The binary content of these files are read from the module exe_data, which may be generated by the following small script (run from the setuptools directory which contains the file cli.exe and gui.exe: fo = open('exe_data.py', 'w') for name in ['cli', 'gui']: data = open('%s.exe' % name, 'rb').read() fo.write('%s = %r\n' % (name, data)) fo.close() """ if script_type == 'console_scripts': from exe_data import cli as data elif script_type == 'gui_scripts': from exe_data import gui as data else: raise Exception("Did not except script_type=%r" % script_type) rm_rf(dst) try: with open(dst, 'wb') as fp: fp.write(data) except IOError: # When bootstrapping, the file egginst.exe is in use and can therefore # not be rewritten, which is OK since its content is always the same. pass os.chmod(dst, 0755)
def create_proxies(egg, pythonexe=sys.executable): """ Create so-called 'proxy' files on windows. Proxies are essentially entry points, which redirect to actual executables in locations not in %PATH%. """ # This function is called on Windows only makedirs(egg.scriptsdir) for line in egg.iter_files_to_install(): arcname, action = line.split() logger.info("arcname=%r action=%r", arcname, action) if action == 'PROXY': ei = 'EGG-INFO/' if arcname.startswith(ei): src = abspath(join(egg.meta_dir, arcname[len(ei):])) else: src = abspath(join(egg.prefix, arcname)) logger.info(" src: %r", src) egg.files.extend(_create_proxy(src, egg.scriptsdir, pythonexe)) else: data = egg.z.read(arcname) dst = abspath(join(egg.prefix, action, basename(arcname))) logger.info(" dst: %r", dst) rm_rf(dst) with open(dst, 'wb') as fo: fo.write(data) egg.files.append(dst)
def create_proxies(egg): # This function is called on Windows only if not isdir(egg.bin_dir): os.makedirs(egg.bin_dir) for line in egg.iter_files_to_install(): arcname, action = line.split() logger.info("arcname=%r action=%r", arcname, action) if action == 'PROXY': ei = 'EGG-INFO/' if arcname.startswith(ei): src = abspath(join(egg.meta_dir, arcname[len(ei):])) else: src = abspath(join(egg.prefix, arcname)) logger.info(" src: %r", src) egg.files.extend(create_proxy(src, egg.bin_dir)) else: data = egg.z.read(arcname) dst = abspath(join(egg.prefix, action, basename(arcname))) logger.info(" dst: %r", dst) rm_rf(dst) with open(dst, 'wb') as fo: fo.write(data) egg.files.append(dst)
def _create_proxy(src, bin_dir, executable=sys.executable): """ create a proxy of src in bin_dir (Windows only) """ logger.info("Creating proxy executable to: %r", src) assert src.endswith('.exe') dst_name = basename(src) if dst_name.startswith('epd-'): dst_name = dst_name[4:] dst = join(bin_dir, dst_name) _write_exe(dst) dst_script = dst[:-4] + '-script.py' rm_rf(dst_script) with open(dst_script, 'w') as fo: fo.write('''\ #!"%(python)s" # This proxy was created by egginst from an egg with special instructions # import sys import subprocess src = %(src)r sys.exit(subprocess.call([src] + sys.argv[1:])) ''' % dict(python=_get_executable(executable), src=src)) return dst, dst_script
def create_proxy(src, bin_dir): """ create a proxy of src in bin_dir (Windows only) """ if verbose: print "Creating proxy executable to: %r" % src assert src.endswith('.exe') dst_name = basename(src) if dst_name.startswith('epd-'): dst_name = dst_name[4:] dst = join(bin_dir, dst_name) write_exe(dst) dst_script = dst[:-4] + '-script.py' rm_rf(dst_script) fo = open(dst_script, 'w') fo.write('''\ #!"%(python)s" # This proxy was created by egginst from an egg with special instructions # import sys import subprocess src = %(src)r sys.exit(subprocess.call([src] + sys.argv[1:])) ''' % dict(python=get_executable(), src=src)) fo.close() return dst, dst_script
def write_arcname(self, arcname): if arcname.endswith('/') or arcname.startswith('.unused'): return m = self.py_pat.match(arcname) if m and (m.group(1) + self.py_obj) in self.arcnames: # .py, .pyc, .pyo next to .so are not written return path = self.get_dst(arcname) dn, fn = os.path.split(path) data = self.z.read(arcname) if fn in ['__init__.py', '__init__.pyc']: tmp = arcname.rstrip('c') if tmp in self.arcnames and NS_PKG_PAT.match(self.z.read(tmp)): if fn == '__init__.py': data = '' if fn == '__init__.pyc': return self.files.append(path) if not isdir(dn): os.makedirs(dn) rm_rf(path) fo = open(path, 'wb') fo.write(data) fo.close() if (arcname.startswith(('EGG-INFO/usr/bin/', 'EGG-INFO/scripts/')) or fn.endswith(('.dylib', '.pyd', '.so')) or (arcname.startswith('EGG-INFO/usr/lib/') and self.so_pat.match(fn))): os.chmod(path, 0755)
def write_script(path, entry_pt, egg_name): """ Write an entry point script to path. """ if verbose: print 'Creating script: %s' % path assert entry_pt.count(':') == 1 module, func = entry_pt.strip().split(':') rm_rf(path) fo = open(path, 'w') fo.write('''\ #!%(python)s # This script was created by egginst when installing: # # %(egg_name)s # if __name__ == '__main__': import sys from %(module)s import %(func)s sys.exit(%(func)s()) ''' % dict(python=get_executable(pythonw=path.endswith('.pyw'), with_quotes=on_win), egg_name=egg_name, module=module, func=func)) fo.close() os.chmod(path, 0755)
def fetch(self, key, execution_aborted=None): """ Fetch the given key. execution_aborted: a threading.Event object which signals when the execution needs to be aborted, or None, if we don't want to abort the fetching at all. """ path = self.path(key) fi, info = self.remote.get(key) size = info['size'] md5 = info.get('md5') if self.evt_mgr: from encore.events.api import ProgressManager else: from egginst.console import ProgressManager progress = ProgressManager( self.evt_mgr, source=self, operation_id=uuid4(), message="fetching", steps=size, # --- progress_type="fetching", filename=basename(path), disp_amount=human_bytes(size), super_id=getattr(self, 'super_id', None)) n = 0 h = hashlib.new('md5') if size < 256: buffsize = 1 else: buffsize = 2 ** int(math.log(size / 256.0) / math.log(2.0) + 1) pp = path + '.part' if sys.platform == 'win32': rm_rf(pp) with progress: with open(pp, 'wb') as fo: while True: if execution_aborted is not None and execution_aborted.is_set(): close_file_or_response(fi) return chunk = fi.read(buffsize) if not chunk: break fo.write(chunk) if md5: h.update(chunk) n += len(chunk) progress(step=n) close_file_or_response(fi) if md5 and h.hexdigest() != md5: raise ValueError("received data MD5 sums mismatch") if sys.platform == 'win32': rm_rf(path) os.rename(pp, path)
def write_script(path, entry_pt, egg_name): """ Write an entry point script to path. """ if verbose: print 'Creating script: %s' % path assert entry_pt.count(':') == 1 module, func = entry_pt.strip().split(':') python = '"%s"' % executable rm_rf(path) fo = open(path, 'w') fo.write('''\ #!%(python)s # This script was created by egginst when installing: # # %(egg_name)s # if __name__ == '__main__': import sys from %(module)s import %(func)s sys.exit(%(func)s()) ''' % locals()) fo.close() os.chmod(path, 0755)
def write_exe(dst): from exe_data import cli as data rm_rf(dst) try: open(dst, 'wb').write(data) except IOError: # When bootstrapping, the file egginst.exe is in use and can therefore # not be rewritten, which is OK since its content is always the same. pass os.chmod(dst, 0755)
def create(self): if self.tp == 'app': Application(self.path, self.shortcut).create() elif self.tp == 'link': src = self.cmd[0] if src.startswith('{{'): src = self.cmd[1] rm_rf(self.path) os.symlink(src, self.path)
def fetch(self, key): path = self.path(key) fi, info = self.remote.get(key) size = info['size'] md5 = info.get('md5') if self.evt_mgr: from encore.events.api import ProgressManager else: from egginst.console import ProgressManager progress = ProgressManager( self.evt_mgr, source=self, operation_id=uuid4(), message="fetching", steps=size, # --- progress_type="fetching", filename=basename(path), disp_amount=human_bytes(size), super_id=getattr(self, 'super_id', None)) n = 0 h = hashlib.new('md5') if size < 256: buffsize = 1 else: buffsize = 2 ** int(math.log(size / 256.0) / math.log(2.0) + 1) pp = path + '.part' if sys.platform == 'win32': rm_rf(pp) with progress: with open(pp, 'wb') as fo: while True: chunk = fi.read(buffsize) if not chunk: break fo.write(chunk) if md5: h.update(chunk) n += len(chunk) progress(step=n) fi.close() if md5 and h.hexdigest() != md5: raise ValueError("received data MD5 sums mismatch") if sys.platform == 'win32': rm_rf(path) os.rename(pp, path)
def create_link(arcname, link, prefix): usr = '******' assert arcname.startswith(usr), arcname dst = join(prefix, arcname[len(usr):]) # Create the destination directory if it does not exist. In most cases # it will exist, but you never know. if not isdir(dirname(dst)): os.makedirs(dirname(dst)) rm_rf(dst) logger.info("Creating: %s (link to %s)", dst, link) os.symlink(link, dst) return dst
def fetch_dist(self, dist, fetch_dir, force=False, check_md5=False, dry_run=False): """ Get a distribution, i.e. copy or download the distribution into fetch_dir. force: force download or copy check_md5: when determining if a file needs to be downloaded or copied, check it's MD5. This is, of course, slower but more reliable then just checking the file-size (which is always done first). Note: * This option has nothing to do with checking the MD5 of the download. The md5 is always checked when files are downloaded (regardless of this option). * If force=True, this option is has no effect, because the file is forcefully downloaded, ignoring any existing file (as well as the MD5). """ md5 = self.index[dist].get('md5') size = self.index[dist].get('size') fn = dist_naming.filename_dist(dist) dst = join(fetch_dir, fn) # if force is not used, see if (i) the file exists (ii) its size is # the expected (iii) optionally, make sure the md5 is the expected. if (not force and isfile(dst) and getsize(dst) == size and (not check_md5 or md5_file(dst) == md5)): if self.verbose: print "Not forcing refetch, %r already exists" % dst return self.file_action_callback(fn, ('copying', 'downloading') [dist.startswith(('http://', 'https://'))]) if dry_run: return if self.verbose: print "Copying: %r" % dist print " to: %r" % dst fo = open(dst + '.part', 'wb') write_data_from_url(fo, dist, md5, size, progress_callback=self.download_progress_callback) fo.close() rm_rf(dst) os.rename(dst + '.part', dst)
def write_arcname(self, arcname): if arcname.endswith('/') or arcname.startswith('.unused'): return path = self.get_dst(arcname) dn, fn = os.path.split(path) data = self.z.read(arcname) self.files.append(path) if not isdir(dn): os.makedirs(dn) rm_rf(path) fo = open(path, 'wb') fo.write(data) fo.close() if arcname.startswith(('EGG-INFO/scripts/')) or fn.endswith('.pyd'): os.chmod(path, 0755)
def _write_script(path, entry_point, template, pythonexe): """ Write an entry point script to path. """ logger.info('Creating script: %s', path) rm_rf(path) with open(path, 'w') as fo: data = template.format( python=_get_executable( pythonexe, pythonw=path.endswith('.pyw'), with_quotes=on_win ), module=entry_point.module, func=entry_point.function ) fo.write(data) os.chmod(path, 0o755)
def remove(self): if not isdir(self.meta_dir): print "Error: Can't find meta data for:", self.cname return self.read_meta() cur = n = 0 nof = len(self.files) # number of files sys.stdout.write('%9s [' % human_bytes(self.installed_size)) self.run('pre_egguninst.py') for p in self.files: n += 1 rat = float(n) / nof if rat * 64 >= cur: sys.stdout.write('.') sys.stdout.flush() cur += 1 rm_rf(p) if p.endswith('.py') and isfile(p + 'c'): # remove the corresponding .pyc rm_rf(p + 'c') self.rmdirs() rm_rf(self.meta_dir) sys.stdout.write('.' * (65-cur) + ']\n') sys.stdout.flush()
def remove(self): if not isdir(self.meta_dir): print "Error: Can't find meta data for:", self.cname return self.read_meta() n = 0 nof = len(self.files) # number of files self.progress_callback(0, self.installed_size) self.install_app(remove=True) self.run('pre_egguninst.py') for p in self.files: n += 1 self.progress_callback(n, nof) rm_rf(p) if p.endswith('.py'): rm_rf(p + 'c') self.rm_dirs() rm_rf(self.meta_dir) if self.hook: rm_empty_dir(self.pkg_dir) else: rm_empty_dir(self.egginfo_dir)
def _repair_package_dir(source_egg_info_dir, dest_egg_info_dir, dry_run): if dry_run: _in_place_repair(source_egg_info_dir, dest_egg_info_dir, dry_run) _fix_pkg_info_file(dest_egg_info_dir, dest_egg_info_dir, dry_run) return working_dir = dest_egg_info_dir + ".wdir" temp_dir = dest_egg_info_dir + ".bak" # We do the transformation in a temporary directory we then move to the # final destination to avoid putting stalled .egg-info directories. makedirs(working_dir) try: _in_place_repair(source_egg_info_dir, working_dir, dry_run) _fix_pkg_info_file(dest_egg_info_dir, working_dir, dry_run) # Backup original egg-info file/dir os.rename(dest_egg_info_dir, temp_dir) # Move repaired egg-info file/dir to final destination os.rename(working_dir, dest_egg_info_dir) except BaseException: rm_rf(working_dir) else: rm_rf(temp_dir)
def ensure_menu_file(): # ensure any existing version is a file if exists(menu_file) and not isfile(menu_file): rm_rf(menu_file) # ensure any existing file is actually a menu file if isfile(menu_file): # make a backup of the menu file to be edited cur_time = time.strftime('%Y-%m-%d_%Hh%Mm%S') backup_menu_file = "%s.%s" % (menu_file, cur_time) shutil.copyfile(menu_file, backup_menu_file) if not is_valid_menu_file(): os.remove(menu_file) # create a new menu file if one doesn't yet exist if not isfile(menu_file): fo = open(menu_file, 'w') if mode == 'user': merge = '<MergeFile type="parent">%s</MergeFile>' % sys_menu_file else: merge = '' fo.write("<Menu><Name>Applications</Name>%s</Menu>\n" % merge) fo.close()
def remove(self): rm_rf(self.path)
def tearDown(self): rm_rf(self.prefix)
def _create_dirs(self): rm_rf(self.app_path) os.makedirs(self.resources_dir) os.makedirs(self.macos_dir)
def create(self, remove=False): # Separate the arguments to the invoked command from the command # itself. cmd = self.cmd[0] args = self.cmd[1:] executable = get_executable(self.prefix) # Handle the special '{{FILEBROWSER}}' command by using webbrowser # since using just the path name pops up a dialog asking for which # application to use. Using 'explorer.exe' picks up # c:/windows/system32/explorer.exe which does not work. Webbrowser # does the right thing. if cmd == '{{FILEBROWSER}}': cmd = executable args = ['-m', 'webbrowser'] + args # Otherwise, handle the special '{{WEBBROWSER}}' command by # invoking the Python standard lib's 'webbrowser' script. This # allows us to specify that the url(s) should be opened in new # tabs. # # If this doesn't work, see the following website for details of # the special URL shortcut file format. While split across two # lines it is one URL: # http://delphi.about.com/gi/dynamic/offsite.htm?site= \ # http://www.cyanwerks.com/file-format-url.html elif cmd == '{{WEBBROWSER}}': cmd = executable args = ['-m', 'webbrowser', '-t'] + args # The API for the call to 'wininst.create_shortcut' has 3 required # arguments:- # # path, description and filename # # and 4 optional arguments:- # # args, working_dir, icon_path and icon_index # # We always pass the args argument, but we only pass the working # directory and the icon path if given, and we never currently pass the # icon index. working_dir = quoted(self.shortcut.get('working_dir', '')) icon = self.shortcut.get('icon') if working_dir and icon: shortcut_args = [working_dir, icon] elif working_dir and not icon: shortcut_args = [working_dir] elif not working_dir and icon: shortcut_args = ['', icon] else: shortcut_args = [] # Menu link dst_dirs = [self.menu.path] # Desktop link if self.shortcut.get('desktop') and addtodesktop: dst_dirs.append(desktop_dir) # Quicklaunch link if self.shortcut.get('quicklaunch') and addtolauncher: dst_dirs.append(quicklaunch_dir) for dst_dir in dst_dirs: dst = join(dst_dir, self.shortcut['name'] + '.lnk') if remove: rm_rf(dst) else: wininst.create_shortcut( quoted(cmd), self.shortcut['comment'], dst, ' '.join(quoted(arg) for arg in args), *shortcut_args)
path = self.path if tp == 'gnome': filebrowser = 'gnome-open' path += '.desktop' elif tp == 'kde': filebrowser = 'kfmclient openURL' path += 'KDE.desktop' cmd = self.cmd if cmd[0] == '{{FILEBROWSER}}': cmd[0] = filebrowser elif cmd[0] == '{{WEBBROWSER}}': import webbrowser executable = get_executable(self.prefix) cmd[0:1] = [executable, webbrowser.__file__, '-t'] spec['cmd'] = cmd spec['path'] = path # create the shortcuts make_desktop_entry(spec) if __name__ == '__main__': rm_rf(menu_file) Menu('Foo').create() Menu('Bar').create() Menu('Foo').remove() Menu('Foo').remove()
def remove(self): for ext in ('.desktop', 'KDE.desktop'): path = self.path + ext rm_rf(path)
def create(self, remove=False): # Separate the arguments to the invoked command from the command # itself. cmd = self.cmd[0] args = self.cmd[1:] executable = get_executable(self.prefix) # Handle the special '{{FILEBROWSER}}' command by using webbrowser # since using just the path name pops up a dialog asking for which # application to use. Using 'explorer.exe' picks up # c:/windows/system32/explorer.exe which does not work. Webbrowser # does the right thing. if cmd == '{{FILEBROWSER}}': cmd = executable args = ['-m', 'webbrowser'] + args # Otherwise, handle the special '{{WEBBROWSER}}' command by # invoking the Python standard lib's 'webbrowser' script. This # allows us to specify that the url(s) should be opened in new # tabs. # # If this doesn't work, see the following website for details of # the special URL shortcut file format. While split across two # lines it is one URL: # http://delphi.about.com/gi/dynamic/offsite.htm?site= \ # http://www.cyanwerks.com/file-format-url.html elif cmd == '{{WEBBROWSER}}': cmd = executable args = ['-m', 'webbrowser', '-t'] + args # The API for the call to 'wininst.create_shortcut' has 3 required # arguments:- # # path, description and filename # # and 4 optional arguments:- # # args, working_dir, icon_path and icon_index # # We always pass the args argument, but we only pass the working # directory and the icon path if given, and we never currently pass the # icon index. working_dir = quoted(self.shortcut.get('working_dir', '')) icon = self.shortcut.get('icon') if working_dir and icon: shortcut_args = [working_dir, icon] elif working_dir and not icon: shortcut_args = [working_dir] elif not working_dir and icon: shortcut_args = ['', icon] else: shortcut_args = [] # Menu link dst_dirs = [self.menu.path] # Desktop link if self.shortcut.get('desktop') and addtodesktop: dst_dirs.append(desktop_dir) # Quicklaunch link if self.shortcut.get('quicklaunch') and addtolauncher: dst_dirs.append(quicklaunch_dir) for dst_dir in dst_dirs: dst = join(dst_dir, self.shortcut['name'] + '.lnk') if remove: rm_rf(dst) else: wininst.create_shortcut(quoted(cmd), self.shortcut['comment'], dst, ' '.join(quoted(arg) for arg in args), *shortcut_args)