root/galaxy-central/eggs/PasteScript-1.7.3-py2.6.egg/paste/script/copydir.py @ 3

リビジョン 3, 14.8 KB (コミッタ: kohda, 14 年 前)

Install Unix tools  http://hannonlab.cshl.edu/galaxy_unix_tools/galaxy.html

行番号 
1# (c) 2005 Ian Bicking and contributors; written for Paste (http://pythonpaste.org)
2# Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php
3import os
4import pkg_resources
5import sys
6if sys.version_info < (2, 4):
7    from paste.script.util import string24 as string
8else:
9    import string
10import cgi
11import urllib
12import re
13Cheetah = None
14try:
15    import subprocess
16except ImportError:
17    from paste.script.util import subprocess24 as subprocess
18import inspect
19
20class SkipTemplate(Exception):
21    """
22    Raised to indicate that the template should not be copied over.
23    Raise this exception during the substitution of your template
24    """
25
26def copy_dir(source, dest, vars, verbosity, simulate, indent=0,
27             use_cheetah=False, sub_vars=True, interactive=False,
28             svn_add=True, overwrite=True, template_renderer=None):
29    """
30    Copies the ``source`` directory to the ``dest`` directory.
31
32    ``vars``: A dictionary of variables to use in any substitutions.
33
34    ``verbosity``: Higher numbers will show more about what is happening.
35
36    ``simulate``: If true, then don't actually *do* anything.
37
38    ``indent``: Indent any messages by this amount.
39
40    ``sub_vars``: If true, variables in ``_tmpl`` files and ``+var+``
41    in filenames will be substituted.
42
43    ``use_cheetah``: If true, then any templates encountered will be
44    substituted with Cheetah.  Otherwise ``template_renderer`` or
45    ``string.Template`` will be used for templates.
46
47    ``svn_add``: If true, any files written out in directories with
48    ``.svn/`` directories will be added (via ``svn add``).
49
50    ``overwrite``: If false, then don't every overwrite anything.
51
52    ``interactive``: If you are overwriting a file and interactive is
53    true, then ask before overwriting.
54
55    ``template_renderer``: This is a function for rendering templates
56    (if you don't want to use Cheetah or string.Template).  It should
57    have the signature ``template_renderer(content_as_string,
58    vars_as_dict, filename=filename)``.
59    """
60    # This allows you to use a leading +dot+ in filenames which would
61    # otherwise be skipped because leading dots make the file hidden:
62    vars.setdefault('dot', '.')
63    vars.setdefault('plus', '+')
64    use_pkg_resources = isinstance(source, tuple)
65    if use_pkg_resources:
66        names = pkg_resources.resource_listdir(source[0], source[1])
67    else:
68        names = os.listdir(source)
69    names.sort()
70    pad = ' '*(indent*2)
71    if not os.path.exists(dest):
72        if verbosity >= 1:
73            print '%sCreating %s/' % (pad, dest)
74        if not simulate:
75            svn_makedirs(dest, svn_add=svn_add, verbosity=verbosity,
76                         pad=pad)
77    elif verbosity >= 2:
78        print '%sDirectory %s exists' % (pad, dest)
79    for name in names:
80        if use_pkg_resources:
81            full = '/'.join([source[1], name])
82        else:
83            full = os.path.join(source, name)
84        reason = should_skip_file(name)
85        if reason:
86            if verbosity >= 2:
87                reason = pad + reason % {'filename': full}
88                print reason
89            continue
90        if sub_vars:
91            dest_full = os.path.join(dest, substitute_filename(name, vars))
92        sub_file = False
93        if dest_full.endswith('_tmpl'):
94            dest_full = dest_full[:-5]
95            sub_file = sub_vars
96        if use_pkg_resources and pkg_resources.resource_isdir(source[0], full):
97            if verbosity:
98                print '%sRecursing into %s' % (pad, os.path.basename(full))
99            copy_dir((source[0], full), dest_full, vars, verbosity, simulate,
100                     indent=indent+1, use_cheetah=use_cheetah,
101                     sub_vars=sub_vars, interactive=interactive,
102                     svn_add=svn_add, template_renderer=template_renderer)
103            continue
104        elif not use_pkg_resources and os.path.isdir(full):
105            if verbosity:
106                print '%sRecursing into %s' % (pad, os.path.basename(full))
107            copy_dir(full, dest_full, vars, verbosity, simulate,
108                     indent=indent+1, use_cheetah=use_cheetah,
109                     sub_vars=sub_vars, interactive=interactive,
110                     svn_add=svn_add, template_renderer=template_renderer)
111            continue
112        elif use_pkg_resources:
113            content = pkg_resources.resource_string(source[0], full)
114        else:
115            f = open(full, 'rb')
116            content = f.read()
117            f.close()
118        if sub_file:
119            try:
120                content = substitute_content(content, vars, filename=full,
121                                             use_cheetah=use_cheetah,
122                                             template_renderer=template_renderer)
123            except SkipTemplate:
124                continue
125            if content is None:
126                continue
127        already_exists = os.path.exists(dest_full)
128        if already_exists:
129            f = open(dest_full, 'rb')
130            old_content = f.read()
131            f.close()
132            if old_content == content:
133                if verbosity:
134                    print '%s%s already exists (same content)' % (pad, dest_full)
135                continue
136            if interactive:
137                if not query_interactive(
138                    full, dest_full, content, old_content,
139                    simulate=simulate):
140                    continue
141            elif not overwrite:
142                continue
143        if verbosity and use_pkg_resources:
144            print '%sCopying %s to %s' % (pad, full, dest_full)
145        elif verbosity:
146            print '%sCopying %s to %s' % (pad, os.path.basename(full), dest_full)
147        if not simulate:
148            f = open(dest_full, 'wb')
149            f.write(content)
150            f.close()
151        if svn_add and not already_exists:
152            if not os.path.exists(os.path.join(os.path.dirname(os.path.abspath(dest_full)), '.svn')):
153                if verbosity > 1:
154                    print '%s.svn/ does not exist; cannot add file' % pad
155            else:
156                cmd = ['svn', 'add', dest_full]
157                if verbosity > 1:
158                    print '%sRunning: %s' % (pad, ' '.join(cmd))
159                if not simulate:
160                    # @@: Should
161                    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
162                    stdout, stderr = proc.communicate()
163                    if verbosity > 1 and stdout:
164                        print 'Script output:'
165                        print stdout
166        elif svn_add and already_exists and verbosity > 1:
167            print '%sFile already exists (not doing svn add)' % pad
168
169def should_skip_file(name):
170    """
171    Checks if a file should be skipped based on its name.
172
173    If it should be skipped, returns the reason, otherwise returns
174    None.
175    """
176    if name.startswith('.'):
177        return 'Skipping hidden file %(filename)s'
178    if name.endswith('~') or name.endswith('.bak'):
179        return 'Skipping backup file %(filename)s'
180    if name.endswith('.pyc'):
181        return 'Skipping .pyc file %(filename)s'
182    if name.endswith('$py.class'):
183        return 'Skipping $py.class file %(filename)s'
184    if name in ('CVS', '_darcs'):
185        return 'Skipping version control directory %(filename)s'
186    return None
187
188# Overridden on user's request:
189all_answer = None
190
191def query_interactive(src_fn, dest_fn, src_content, dest_content,
192                      simulate):
193    global all_answer
194    from difflib import unified_diff, context_diff
195    u_diff = list(unified_diff(
196        dest_content.splitlines(),
197        src_content.splitlines(),
198        dest_fn, src_fn))
199    c_diff = list(context_diff(
200        dest_content.splitlines(),
201        src_content.splitlines(),
202        dest_fn, src_fn))
203    added = len([l for l in u_diff if l.startswith('+')
204                   and not l.startswith('+++')])
205    removed = len([l for l in u_diff if l.startswith('-')
206                   and not l.startswith('---')])
207    if added > removed:
208        msg = '; %i lines added' % (added-removed)
209    elif removed > added:
210        msg = '; %i lines removed' % (removed-added)
211    else:
212        msg = ''
213    print 'Replace %i bytes with %i bytes (%i/%i lines changed%s)' % (
214        len(dest_content), len(src_content),
215        removed, len(dest_content.splitlines()), msg)
216    prompt = 'Overwrite %s [y/n/d/B/?] ' % dest_fn
217    while 1:
218        if all_answer is None:
219            response = raw_input(prompt).strip().lower()
220        else:
221            response = all_answer
222        if not response or response[0] == 'b':
223            import shutil
224            new_dest_fn = dest_fn + '.bak'
225            n = 0
226            while os.path.exists(new_dest_fn):
227                n += 1
228                new_dest_fn = dest_fn + '.bak' + str(n)
229            print 'Backing up %s to %s' % (dest_fn, new_dest_fn)
230            if not simulate:
231                shutil.copyfile(dest_fn, new_dest_fn)
232            return True
233        elif response.startswith('all '):
234            rest = response[4:].strip()
235            if not rest or rest[0] not in ('y', 'n', 'b'):
236                print query_usage
237                continue
238            response = all_answer = rest[0]
239        if response[0] == 'y':
240            return True
241        elif response[0] == 'n':
242            return False
243        elif response == 'dc':
244            print '\n'.join(c_diff)
245        elif response[0] == 'd':
246            print '\n'.join(u_diff)
247        else:
248            print query_usage
249
250query_usage = """\
251Responses:
252  Y(es):    Overwrite the file with the new content.
253  N(o):     Do not overwrite the file.
254  D(iff):   Show a unified diff of the proposed changes (dc=context diff)
255  B(ackup): Save the current file contents to a .bak file
256            (and overwrite)
257  Type "all Y/N/B" to use Y/N/B for answer to all future questions
258"""
259
260def svn_makedirs(dir, svn_add, verbosity, pad):
261    parent = os.path.dirname(os.path.abspath(dir))
262    if not os.path.exists(parent):
263        svn_makedirs(parent, svn_add, verbosity, pad)
264    os.mkdir(dir)
265    if not svn_add:
266        return
267    if not os.path.exists(os.path.join(parent, '.svn')):
268        if verbosity > 1:
269            print '%s.svn/ does not exist; cannot add directory' % pad
270        return
271    cmd = ['svn', 'add', dir]
272    if verbosity > 1:
273        print '%sRunning: %s' % (pad, ' '.join(cmd))
274    proc = subprocess.Popen(cmd, stdout=subprocess.PIPE)
275    stdout, stderr = proc.communicate()
276    if verbosity > 1 and stdout:
277        print 'Script output:'
278        print stdout
279
280def substitute_filename(fn, vars):
281    for var, value in vars.items():
282        fn = fn.replace('+%s+' % var, str(value))
283    return fn
284
285def substitute_content(content, vars, filename='<string>',
286                       use_cheetah=False, template_renderer=None):
287    global Cheetah
288    v = standard_vars.copy()
289    v.update(vars)
290    vars = v
291    if template_renderer is not None:
292        return template_renderer(content, vars, filename=filename)
293    if not use_cheetah:
294        tmpl = LaxTemplate(content)
295        try:
296            return tmpl.substitute(TypeMapper(v))
297        except Exception, e:
298            _add_except(e, ' in file %s' % filename)
299            raise
300    if Cheetah is None:
301        import Cheetah.Template
302    tmpl = Cheetah.Template.Template(source=content,
303                                     searchList=[vars])
304    return careful_sub(tmpl, vars, filename)
305
306def careful_sub(cheetah_template, vars, filename):
307    """
308    Substitutes the template with the variables, using the
309    .body() method if it exists.  It assumes that the variables
310    were also passed in via the searchList.
311    """
312    if not hasattr(cheetah_template, 'body'):
313        return sub_catcher(filename, vars, str, cheetah_template)
314    body = cheetah_template.body
315    args, varargs, varkw, defaults = inspect.getargspec(body)
316    call_vars = {}
317    for arg in args:
318        if arg in vars:
319            call_vars[arg] = vars[arg]
320    return sub_catcher(filename, vars, body, **call_vars)
321
322def sub_catcher(filename, vars, func, *args, **kw):
323    """
324    Run a substitution, returning the value.  If an error occurs, show
325    the filename.  If the error is a NameError, show the variables.
326    """
327    try:
328        return func(*args, **kw)
329    except SkipTemplate, e:
330        print 'Skipping file %s' % filename
331        if str(e):
332            print str(e)
333        raise
334    except Exception, e:
335        print 'Error in file %s:' % filename
336        if isinstance(e, NameError):
337            items = vars.items()
338            items.sort()
339            for name, value in items:
340                print '%s = %r' % (name, value)
341        raise
342
343def html_quote(s):
344    if s is None:
345        return ''
346    return cgi.escape(str(s), 1)
347
348def url_quote(s):
349    if s is None:
350        return ''
351    return urllib.quote(str(s))
352
353def test(conf, true_cond, false_cond=None):
354    if conf:
355        return true_cond
356    else:
357        return false_cond
358
359def skip_template(condition=True, *args):
360    """
361    Raise SkipTemplate, which causes copydir to skip the template
362    being processed.  If you pass in a condition, only raise if that
363    condition is true (allows you to use this with string.Template)
364
365    If you pass any additional arguments, they will be used to
366    instantiate SkipTemplate (generally use like
367    ``skip_template(license=='GPL', 'Skipping file; not using GPL')``)
368    """
369    if condition:
370        raise SkipTemplate(*args)
371
372def _add_except(exc, info):
373    if not hasattr(exc, 'args') or exc.args is None:
374        return
375    args = list(exc.args)
376    if args:
377        args[0] += ' ' + info
378    else:
379        args = [info]
380    exc.args = tuple(args)
381    return
382   
383
384standard_vars = {
385    'nothing': None,
386    'html_quote': html_quote,
387    'url_quote': url_quote,
388    'empty': '""',
389    'test': test,
390    'repr': repr,
391    'str': str,
392    'bool': bool,
393    'SkipTemplate': SkipTemplate,
394    'skip_template': skip_template,
395    }
396
397class TypeMapper(dict):
398
399    def __getitem__(self, item):
400        options = item.split('|')
401        for op in options[:-1]:
402            try:
403                value = eval_with_catch(op, dict(self.items()))
404                break
405            except (NameError, KeyError):
406                pass
407        else:
408            value = eval(options[-1], dict(self.items()))
409        if value is None:
410            return ''
411        else:
412            return str(value)
413
414def eval_with_catch(expr, vars):
415    try:
416        return eval(expr, vars)
417    except Exception, e:
418        _add_except(e, 'in expression %r' % expr)
419        raise
420       
421class LaxTemplate(string.Template):
422    # This change of pattern allows for anything in braces, but
423    # only identifiers outside of braces:
424    pattern = r"""
425    \$(?:
426      (?P<escaped>\$)             |   # Escape sequence of two delimiters
427      (?P<named>[_a-z][_a-z0-9]*) |   # delimiter and a Python identifier
428      {(?P<braced>.*?)}           |   # delimiter and a braced identifier
429      (?P<invalid>)                   # Other ill-formed delimiter exprs
430    )
431    """
Note: リポジトリブラウザについてのヘルプは TracBrowser を参照してください。