root / logilab.pylintinstaller / logilab / common / shellutils.py

Revision 202:d67e86292521, 6.3 kB (checked in by tziade@…, 9 months ago)

added logilab.pylintinstaller

Line 
1# This program is free software; you can redistribute it and/or modify it under
2# the terms of the GNU General Public License as published by the Free Software
3# Foundation; either version 2 of the License, or (at your option) any later
4# version.
5#
6# This program is distributed in the hope that it will be useful, but WITHOUT
7# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
8# FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
9#
10# You should have received a copy of the GNU General Public License along with
11# this program; if not, write to the Free Software Foundation, Inc.,
12# 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
13"""
14Some shell/term utilities, useful to write some python scripts instead of shell
15scripts
16
17:author:    Logilab
18:copyright: 2003-2008 LOGILAB S.A. (Paris, FRANCE)
19:contact:   http://www.logilab.fr/ -- mailto:python-projects@logilab.org
20"""
21__docformat__ = "restructuredtext en"
22
23import os       
24import glob
25import shutil
26import sys
27import tempfile
28import time
29from os.path import exists, isdir, islink, basename, join, walk
30
31from logilab.common import STD_BLACKLIST
32
33
34def chown(path, login=None, group=None):
35    """same as `os.chown` function but accepting user login or group name as
36    argument. If login or group is omitted, it's left unchanged.
37
38    Note: you must own the file to chown it (or be root). Otherwise OSError is raised.
39    """
40    if login is None:
41        uid = -1
42    else:
43        try:
44            uid = int(login)
45        except ValueError:
46            import pwd
47            uid = pwd.getpwname(login).pw_uid
48    if group is None:
49        gid = -1
50    else:
51        try:
52            gid = int(group)
53        except ValueError:
54            import grp
55            gid = grp.getgrname(group).gr_gid
56    os.chown(path, uid, gid)
57       
58
59def mv(source, destination, _action=shutil.move):
60    """a shell like mv, supporting wildcards
61    """
62    sources = glob.glob(source)
63    if len(sources) > 1:
64        assert isdir(destination)
65        for filename in sources:
66            _action(filename, join(destination, basename(filename)))
67    else:
68        try:
69            source = sources[0]
70        except IndexError:
71            raise OSError('No file matching %s' % source)
72        if isdir(destination) and exists(destination):
73            destination = join(destination, basename(source))
74        try:
75            _action(source, destination)
76        except OSError, ex:
77            raise OSError('Unable to move %r to %r (%s)' % (
78                source, destination, ex))
79       
80def rm(*files):
81    """a shell like rm, supporting wildcards
82    """
83    for wfile in files:
84        for filename in glob.glob(wfile):
85            if islink(filename):
86                os.remove(filename)
87            elif isdir(filename):
88                shutil.rmtree(filename)
89            else:
90                os.remove(filename)
91   
92def cp(source, destination):
93    """a shell like cp, supporting wildcards
94    """
95    mv(source, destination, _action=shutil.copy)
96
97
98def find(directory, exts, exclude=False, blacklist=STD_BLACKLIST):
99    """recursivly find files ending with the given extensions from the directory
100
101    :type directory: str
102    :param directory:
103      directory where the search should start
104
105    :type exts: basestring or list or tuple
106    :param exts:
107      extensions or lists or extensions to search
108
109    :type exclude: boolean
110    :param exts:
111      if this argument is True, returning files NOT ending with the given
112      extensions
113
114    :type blacklist: list or tuple
115    :param blacklist:
116      optional list of files or directory to ignore, default to the value of
117      `logilab.common.STD_BLACKLIST`
118
119    :rtype: list
120    :return:
121      the list of all matching files
122    """
123    if isinstance(exts, basestring):
124        exts = (exts,)
125    if exclude:
126        def match(filename, exts):
127            for ext in exts:
128                if filename.endswith(ext):
129                    return False
130            return True
131    else:
132        def match(filename, exts):
133            for ext in exts:
134                if filename.endswith(ext):
135                    return True
136            return False
137    def func(files, directory, fnames):
138        """walk handler"""
139        # remove files/directories in the black list
140        for norecurs in blacklist:
141            try:
142                fnames.remove(norecurs)
143            except ValueError:
144                continue
145        for filename in fnames:
146            src = join(directory, filename)
147            if isdir(src):
148                continue
149            if match(filename, exts):
150                files.append(src)
151    files = []
152    walk(directory, func, files)
153    return files
154
155
156class Execute:
157    """This is a deadlock safe version of popen2 (no stdin), that returns
158    an object with errorlevel, out and err
159    """
160   
161    def __init__(self, command):
162        outfile = tempfile.mktemp()
163        errfile = tempfile.mktemp()
164        self.status = os.system("( %s ) >%s 2>%s" %
165                                (command, outfile, errfile)) >> 8
166        self.out = open(outfile,"r").read()
167        self.err = open(errfile,"r").read()
168        os.remove(outfile)
169        os.remove(errfile)
170
171
172def acquire_lock(lock_file, max_try=10, delay=10):
173    """acquire a lock represented by a file on the file system"""
174    count = 0
175    while max_try <= 0 or count < max_try:
176        if not exists(lock_file):
177            break
178        count += 1
179        time.sleep(delay)
180    else:
181        raise Exception('Unable to acquire %s' % lock_file)
182    stream = open(lock_file, 'w')
183    stream.write(str(os.getpid()))
184    stream.close()
185   
186def release_lock(lock_file):
187    """release a lock represented by a file on the file system"""
188    os.remove(lock_file)
189
190
191class ProgressBar(object):
192    """a simple text progression bar"""
193   
194    def __init__(self, nbops, size=20., stream=sys.stdout):
195        self._dotevery = max(nbops / size, 1)
196        self._fstr = '\r[%-20s]'
197        self._dotcount, self._dots = 1, []
198        self._stream = stream
199
200    def update(self):
201        """update the progression bar"""
202        self._dotcount += 1
203        if self._dotcount >= self._dotevery:
204            self._dotcount = 1
205            self._dots.append('.')
206            self._stream.write(self._fstr % ''.join(self._dots))
207            self._stream.flush()
Note: See TracBrowser for help on using the browser.