Package logilab-common-0 :: Package 36 :: Package 1 :: Module shellutils
[frames] | no frames]

Source Code for Module logilab-common-0.36.1.shellutils

  1  """shell/term utilities, useful to write some python scripts instead of shell 
  2  scripts. 
  3   
  4  :author:    Logilab 
  5  :copyright: 2000-2008 LOGILAB S.A. (Paris, FRANCE), all rights reserved. 
  6  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr 
  7  :license: General Public License version 2 - http://www.gnu.org/licenses 
  8  """ 
  9  __docformat__ = "restructuredtext en" 
 10   
 11  import os 
 12  import glob 
 13  import shutil 
 14  import sys 
 15  import tempfile 
 16  import time 
 17  import fnmatch 
 18  from os.path import exists, isdir, islink, basename, join, walk 
 19   
 20  from logilab.common import STD_BLACKLIST 
 21   
 22   
23 -def chown(path, login=None, group=None):
24 """Same as `os.chown` function but accepting user login or group name as 25 argument. If login or group is omitted, it's left unchanged. 26 27 Note: you must own the file to chown it (or be root). Otherwise OSError is raised. 28 """ 29 if login is None: 30 uid = -1 31 else: 32 try: 33 uid = int(login) 34 except ValueError: 35 import pwd 36 uid = pwd.getpwnam(login).pw_uid 37 if group is None: 38 gid = -1 39 else: 40 try: 41 gid = int(group) 42 except ValueError: 43 import grp 44 gid = grp.getgrname(group).gr_gid 45 os.chown(path, uid, gid)
46 47
48 -def mv(source, destination, _action=shutil.move):
49 """A shell-like mv, supporting wildcards. 50 """ 51 sources = glob.glob(source) 52 if len(sources) > 1: 53 assert isdir(destination) 54 for filename in sources: 55 _action(filename, join(destination, basename(filename))) 56 else: 57 try: 58 source = sources[0] 59 except IndexError: 60 raise OSError('No file matching %s' % source) 61 if isdir(destination) and exists(destination): 62 destination = join(destination, basename(source)) 63 try: 64 _action(source, destination) 65 except OSError, ex: 66 raise OSError('Unable to move %r to %r (%s)' % ( 67 source, destination, ex))
68
69 -def rm(*files):
70 """A shell-like rm, supporting wildcards. 71 """ 72 for wfile in files: 73 for filename in glob.glob(wfile): 74 if islink(filename): 75 os.remove(filename) 76 elif isdir(filename): 77 shutil.rmtree(filename) 78 else: 79 os.remove(filename)
80
81 -def cp(source, destination):
82 """A shell-like cp, supporting wildcards. 83 """ 84 mv(source, destination, _action=shutil.copy)
85 86
87 -def find(directory, exts, exclude=False, blacklist=STD_BLACKLIST):
88 """Recursivly find files ending with the given extensions from the directory. 89 90 :type directory: str 91 :param directory: 92 directory where the search should start 93 94 :type exts: basestring or list or tuple 95 :param exts: 96 extensions or lists or extensions to search 97 98 :type exclude: boolean 99 :param exts: 100 if this argument is True, returning files NOT ending with the given 101 extensions 102 103 :type blacklist: list or tuple 104 :param blacklist: 105 optional list of files or directory to ignore, default to the value of 106 `logilab.common.STD_BLACKLIST` 107 108 :rtype: list 109 :return: 110 the list of all matching files 111 """ 112 if isinstance(exts, basestring): 113 exts = (exts,) 114 if exclude: 115 def match(filename, exts): 116 for ext in exts: 117 if filename.endswith(ext): 118 return False 119 return True
120 else: 121 def match(filename, exts): 122 for ext in exts: 123 if filename.endswith(ext): 124 return True 125 return False 126 def func(files, directory, fnames): 127 """walk handler""" 128 # remove files/directories in the black list 129 for norecurs in blacklist: 130 try: 131 fnames.remove(norecurs) 132 except ValueError: 133 continue 134 for filename in fnames: 135 src = join(directory, filename) 136 if isdir(src): 137 continue 138 if match(filename, exts): 139 files.append(src) 140 files = [] 141 walk(directory, func, files) 142 return files 143 144
145 -def globfind(directory, pattern, blacklist=STD_BLACKLIST):
146 """Recursively finds files matching glob `pattern` under `directory`. 147 148 This is an alternative to `logilab.common.shellutils.find`. 149 150 :type directory: str 151 :param directory: 152 directory where the search should start 153 154 :type pattern: basestring 155 :param pattern: 156 the glob pattern (e.g *.py, foo*.py, etc.) 157 158 :type blacklist: list or tuple 159 :param blacklist: 160 optional list of files or directory to ignore, default to the value of 161 `logilab.common.STD_BLACKLIST` 162 163 :rtype: iterator 164 :return: 165 iterator over the list of all matching files 166 """ 167 for curdir, dirnames, filenames in os.walk(directory): 168 for fname in fnmatch.filter(filenames, pattern): 169 yield join(curdir, fname) 170 for skipped in blacklist: 171 if skipped in dirnames: 172 dirnames.remove(skipped)
173
174 -def unzip(archive, destdir):
175 import zipfile 176 if not exists(destdir): 177 os.mkdir(destdir) 178 zfobj = zipfile.ZipFile(archive) 179 for name in zfobj.namelist(): 180 if name.endswith('/'): 181 os.mkdir(join(destdir, name)) 182 else: 183 outfile = open(join(destdir, name), 'wb') 184 outfile.write(zfobj.read(name)) 185 outfile.close()
186
187 -class Execute:
188 """This is a deadlock safe version of popen2 (no stdin), that returns 189 an object with errorlevel, out and err. 190 """ 191
192 - def __init__(self, command):
193 outfile = tempfile.mktemp() 194 errfile = tempfile.mktemp() 195 self.status = os.system("( %s ) >%s 2>%s" % 196 (command, outfile, errfile)) >> 8 197 self.out = open(outfile,"r").read() 198 self.err = open(errfile,"r").read() 199 os.remove(outfile) 200 os.remove(errfile)
201 202
203 -def acquire_lock(lock_file, max_try=10, delay=10):
204 """Acquire a lock represented by a file on the file system.""" 205 count = 0 206 while max_try <= 0 or count < max_try: 207 if not exists(lock_file): 208 break 209 count += 1 210 time.sleep(delay) 211 else: 212 raise Exception('Unable to acquire %s' % lock_file) 213 stream = open(lock_file, 'w') 214 stream.write(str(os.getpid())) 215 stream.close()
216
217 -def release_lock(lock_file):
218 """Release a lock represented by a file on the file system.""" 219 os.remove(lock_file)
220 221
222 -class ProgressBar(object):
223 """A simple text progression bar.""" 224
225 - def __init__(self, nbops, size=20, stream=sys.stdout):
226 self._fstr = '\r[%%-%ss]' % int(size) 227 self._stream = stream 228 self._total = nbops 229 self._size = size 230 self._current = 0 231 self._progress = 0
232
233 - def update(self):
234 """Update the progression bar.""" 235 self._current += 1 236 progress = int((float(self._current)/float(self._total))*self._size) 237 if progress > self._progress: 238 self._progress = progress 239 self.refresh()
240
241 - def refresh(self):
242 """Refresh the progression bar display.""" 243 self._stream.write(self._fstr % ('.' * min(self._progress, self._size)) ) 244 self._stream.flush()
245