data.py 5.22 KB
Newer Older
Jerome Mariette's avatar
Jerome Mariette committed
1
2
3
4
5
6
7
# Copyright (c) 2010- The University of Notre Dame.
# This software is distributed under the GNU General Public License.
# See the file COPYING for details.

""" Weaver data module """

from weaver.logger  import D_DATA, debug
Jerome Mariette's avatar
Jerome Mariette committed
8
from weaver.stack   import CurrentNest, CurrentScript
Jerome Mariette's avatar
Jerome Mariette committed
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
from weaver.util    import iterable, normalize_path, parse_object_list, \
                           parse_string_list, WeaverError

import os


# File classes

class File(object):
    """ Weaver base File class. """

    STATS = {
        'uid'  : lambda p: os.stat(p).st_uid,
        'gid'  : lambda p: os.stat(p).st_gid,
        'size' : lambda p: os.stat(p).st_size,
        'atime': lambda p: os.stat(p).st_atime,
        'mtime': lambda p: os.stat(p).st_mtime,
    }

    def __init__(self, path, nest=None):
        self.path = str(path)   # __str__ method returns path to file
        self.nest = nest or CurrentNest()
        debug(D_DATA, 'Created File: {0}'.format(self.path))

    def __getattr__(self, name):
        try:
            value = self.STATS[name](self.path)
            setattr(self, name, value)
            return value
        except KeyError:
            raise AttributeError

    def __lt__(self, other):
        return str(self) < str(other)

    def __cmp__(self, other):
        return cmp(str(self), str(other))

    def __str__(self):
        return normalize_path(self.path, self.nest.work_dir)


MakeFileCache = {}

def MakeFile(object_or_path, nest=None):
    if isinstance(object_or_path, File):
        return object_or_path
    else:
        if nest is None:
            nest = CurrentNest()
        try:
            key = (object_or_path, nest)
            return MakeFileCache[key]
        except KeyError:
            value = File(object_or_path, nest)
            MakeFileCache[key] = value
            return value


# File argument parsers

def parse_input_list(input_list=None):
    """ Return an :func:`~weaver.util.iterable` object of input files.

    This just uses :func:`~weaver.util.parse_string_list` to parse the input
    and casts all the objects to :class:`File`.

    This means that `input_list` must be one of the following:

    1. ``None`` or ``[]`` for an empty list.
    2. A string object.
    3. An :func:`~weaver.util.iterable` object (ex. list, iterator, etc.).

    Where each individual element must represent an :class:`File`.
    """
    debug(D_DATA, 'Parsing input list')
    return [MakeFile(i) for i in parse_object_list(input_list)]


def parse_output_list(output_list=None, input_list=None):
    """ Return an :func:`~weaver.util.iterable` object of output files.

    If `output_list` is ``None``, then return ``[]``.  If `output_list` is a
    string template, then use it to generate a list of :class:`File`
    objects.  If `output_list` is already an :func:`~weaver.util.iterable`,
    then map :class:`File` to `output_list` and return it.

    This means that `output_list` must be one of the following:

    1. ``None`` to leave it to the caller to generate an output file object.
    2. A string object to be used as a template.
    3. An :func:`~weaver.util.iterable` object (ex. list, iterator, etc.).

    If `output_list` is a string template, then it may have the following
    fields:

    - `{fullpath}`, `{FULL}`         -- Full input file path.
    - `{basename}`, `{BASE}`         -- Base input file name.
    - `{fullpath_woext}`, `{FULLWE}` -- Full input file path without extension
    - `{basename_woext}`, `{BASEWE}` -- Base input file name without extension

    """
    debug(D_DATA, 'Parsing output list')
    if output_list is None:
        return []

    if isinstance(output_list, str) or isinstance(output_list, File):
        # If input list is empty or output list is not a format string, then
        # return list of single output file.
        # TODO: support single {stash}
        if not input_list or not '{' in str(output_list):
            return [MakeFile(output_list)]

        nest = CurrentNest()
        return [MakeFile(str(output_list).format(
                    fullpath       = input,
                    FULL           = input,
                    i              = '{0:05X}'.format(i),
                    NUMBER         = '{0:05X}'.format(i),
                    stash          = next(nest.stash) if '{stash}' in output_list else '',
                    fullpath_woext = os.path.splitext(input)[0],
                    FULL_WOEXT     = os.path.splitext(input)[0],
                    basename       = os.path.basename(input),
                    BASE           = os.path.basename(input),
                    basename_woext = os.path.splitext(os.path.basename(input))[0] if os.path.splitext(os.path.basename(input))[1] != ".gz" else os.path.splitext(os.path.splitext(os.path.basename(input))[0])[0],
                    BASE_WOEXT     = os.path.splitext(os.path.basename(input))[0] if os.path.splitext(os.path.basename(input))[1] != ".gz" else os.path.splitext(os.path.splitext(os.path.basename(input))[0])[0]))
                for i, input in enumerate(parse_string_list(input_list))]

    if iterable(output_list):
        return [MakeFile(o) for o in parse_object_list(output_list)]

    raise WeaverError(D_DATA,
        'Could not parse output argument: {0}'.format(output_list))

Jerome Mariette's avatar
Jerome Mariette committed
143
# vim: set sts=4 sw=4 ts=8 expandtab ft=python: