This file is indexed.

/usr/lib/python2.7/dist-packages/versuchung/files.py is in python-versuchung 1.1-3.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
# This file is part of versuchung.
# 
# versuchung is free software: you can redistribute it and/or modify it under the
# terms of the GNU General Public License as published by the Free Software
# Foundation, either version 3 of the License, or (at your option) any later
# version.
# 
# versuchung is distributed in the hope that it will be useful, but WITHOUT ANY
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
# PARTICULAR PURPOSE.  See the GNU General Public License for more details.
# 
# You should have received a copy of the GNU General Public License along with
# versuchung.  If not, see <http://www.gnu.org/licenses/>.


from versuchung.types import InputParameter, OutputParameter, Type
from versuchung.tools import before
from cStringIO import StringIO
import shutil
import csv
import os, stat
import hashlib

class FilesystemObject(InputParameter, OutputParameter, Type):
    def __init__(self, default_name=""):
        InputParameter.__init__(self)
        OutputParameter.__init__(self)
        Type.__init__(self)
        self.__object_name = default_name
        self.__enclosing_directory = os.path.abspath(os.curdir)
        self.__force_enclosing_directory = False

    def inp_setup_cmdline_parser(self, parser):
        self.inp_parser_add(parser, None, self.__object_name)

    def inp_extract_cmdline_parser(self, opts, args):
        self.__object_name = self.inp_parser_extract(opts, None)

    def inp_metadata(self):
        return {self.name: self.__object_name}

    @property
    def path(self):
        """:return: string -- path to the file/directory"""
        if not self.__force_enclosing_directory:
            if self.parameter_type == "input":
                if self.static_experiment == self.dynamic_experiment:
                    self.__enclosing_directory = os.path.abspath(os.curdir)
                else:
                    self.__enclosing_directory = self.static_experiment.base_directory
            elif self.parameter_type == "output":
                assert self.static_experiment == self.dynamic_experiment
                self.__enclosing_directory = self.dynamic_experiment.base_directory
            else:
                self.__enclosing_directory = os.path.abspath(os.curdir)
        return os.path.join(self.__enclosing_directory, self.__object_name)

    @property
    def basename(self):
        return os.path.basename(self.path)

    @property
    def dirname(self):
        return os.path.basename(self.path)

    def set_path(self, base_directory, object_name):
        assert base_directory[0] == "/"
        self.__force_enclosing_directory = True
        self.__enclosing_directory = base_directory
        self.__object_name         = object_name

class File(FilesystemObject):
    """Can be used as: **input parameter** and **output parameter**

    The File type represents the content of a single file. Its contents
    can be read and written most easily with the :attr:`value` property.

    Alternatively, the method :meth:`write` appends new content if the
    parameter `append` is set to `True`.

    NB: The content of the file is flushed only after the experiment
    finishes.  Use :meth:`flush` to force writing the buffered data to
    disk before the experiment finishes.
    """

    def __init__(self, default_filename=""):
        FilesystemObject.__init__(self, default_filename)
        self.__value = None

    @property
    def value(self):
        """This attribute can be read and written and represent the
        content of the specified file"""
        if not self.__value:
            try:
                with open(self.path) as fd:
                    self.__value = self.after_read(fd.read())
            except IOError:
                # File couldn't be read
                self.__value = self.after_read("")
        return self.__value

    @value.setter
    def value(self, value):
        self.__value = value

    def write(self, content, append = False):
        """Similar to the :attr:`value` property. If the parameter
        `append` is `False`, then the property :attr:`value` is reset
        (i.e., overwritten), otherwise the content is appendend"""
        if append:
            self.value += content
        else:
            self.value = content

    def after_experiment_run(self, parameter_type):
        FilesystemObject.after_experiment_run(self, parameter_type)
        assert parameter_type in ["input", "output"]
        if parameter_type == "output":
            self.flush()

    def flush(self):
        """Flush the cached content of the file to disk"""
        if not self.__value:
            return
        with open(self.path, "w+") as fd:
            v = self.before_write(self.value)
            if v is None:
                v = ""
            fd.write(v)

    def copy_contents(self, filename):
        """Read the given file and replace the current .value with the
        files content.

        Flushes automatically afterwards."""
        with open(filename) as fd:
            self.value = self.after_read(fd.read())
        self.flush()

    def make_executable(self):
        """makes a file exectuable (chmod +x $file)"""
        st = os.stat(self.path)
        os.chmod(self.path, st.st_mode | stat.S_IEXEC)

    def after_read(self, value):
        """To provide filtering of file contents in subclasses, overrwrite this method.
        It is gets the file content as a string and returns the value()"""
        return value

    def before_write(self, value):
        """To provide filtering of file contents in subclasses, overrwrite this method.
        This method gets the value() and returns a string, when the file is written to disk"""
        return value

class Executable(File):
    """Can be used as: **input parameter**

    An executable is a :class:`versuchung.files.File` that only
    references an executable. It checksums the executable and puts the
    checksum into the metadata. The executable is never changed.

    """
    def __init__(self, default_filename):
        File.__init__(self, default_filename)

    @property
    def value(self):
        raise NotImplemented

    @value.setter
    def value(self, value):
        raise NotImplementedError

    def write(self, content, append = False):
        raise NotImplementedError

    def after_experiment_run(self, parameter_type):
        pass

    def flush(self):
        raise NotImplementedError

    def copy_contents(self, filename):
        raise NotImplementedError

    def make_executable(self):
        raise NotImplementedError

    def inp_metadata(self):
        return {self.name + "-md5": hashlib.md5(open(self.path).read()).hexdigest()}

    def execute(self, cmdline, *args):
        """Does start the executable with meth:`versuchung.execute.shell` and
        args, which is of type list, as arguments."""
        from versuchung.execute import shell

        shell(self.path + " " + cmdline, *args)

class Directory_op_with:
    def __init__(self):
        self.__olddir = []
    def __enter__(self):
        self.__olddir.append(os.path.abspath(os.curdir))
        os.chdir(self.path)
        return self.path
    def __exit__(self, *excinfo):
        path = self.__olddir[-1]
        del self.__olddir[-1]
        os.chdir(path)


class Directory(FilesystemObject, Directory_op_with):
    """Can be used as: **input parameter** and **output parameter**

    Represents the contents of directory. It can also be used with the
    **with**-keyword to change the current working directory temporarily to this
    directory::

       with directory as dir:
          # Do something with adjusted current working directory
          print os.curdir
    """

    def __init__(self, default_filename=""):
        FilesystemObject.__init__(self, default_filename)
        Directory_op_with.__init__(self)
        self.__value = None
        self.__new_files = []

    def ___ensure_dir_exists(self):
        if not os.path.exists(self.path):
            os.mkdir(self.path)

    # Ensure dir exists DECORATOR
    __ensure_dir_exists = before(___ensure_dir_exists)

    @property
    def value(self):
        """:return: list -- directories and files in given directory"""
        if not self.__value:
            self.__value = os.listdir(self.path)
        return self.__value

    def __iter__(self):
        for name in self.value:
            p = os.path.join(self.path, name)
            if os.path.isdir(p):
                d = Directory(name)
                d.set_path(self.path, p)
                self.subobjects[name] = d
                yield d
            else:
                f = File(name)
                f.set_path(self.path, p)
                self.subobjects[name] = f
                yield f

    def before_experiment_run(self, parameter_type):
        FilesystemObject.before_experiment_run(self, parameter_type)
        if parameter_type == "output":
            self.___ensure_dir_exists()

    @__ensure_dir_exists
    def new_file(self, name):
        """Generate a new :class:`~versuchung.files.File` in the
        directory. It will be flushed automatically if the experiment
        is over."""
        f = File(name)
        f.set_path(self.path, name)
        self.subobjects[name] = f
        return f

    @__ensure_dir_exists
    def new_directory(self, name):
        """Generate a new :class:`~versuchung.files.Directory` in the
        directory. The directory <name> must not be present before"""
        f = Directory(name)
        f.set_path(self.path, name)
        os.mkdir(f.path)
        self.subobjects[name] = f
        return f


    @__ensure_dir_exists
    def mirror_directory(self, path, include_closure = None):
        """Copies the contents of the given directory to this
        directory.

        The include closure is a function, which checks for every
        (absolute) path in the origin directory, if it is mirrored. If
        it is None, all files are included."""

        if not include_closure:
            include_closure = lambda arg: True

        if not os.path.exists(path) and os.path.isdir(path):
            raise RuntimeError("Argument is no directory")

        path = os.path.abspath(path)

        for root, dirs, files in os.walk(path):
            root = root[len(path)+1:]
            for d in dirs:
                src = os.path.join(path, root, d)
                if not include_closure(src):
                    continue
                dst = os.path.join(self.path, root, d)
                if not os.path.isdir(dst):
                    os.mkdir(dst)
            for f in files:
                src = os.path.join(path, root, f)
                if not include_closure(src):
                    continue
                dst = os.path.join(self.path, root, f)
                shutil.copyfile(src,dst)

        self.__value = None

class CSV_File(File):
    """Can be used as: **input parameter** and **output parameter**

    It is a normal :class:`~versuchung.files.File` but the content of the file is
    interpreted as a csv file. It is parsed before the value is
    exposed to the user. And formatted before the content is written
    to disk.

    Internally the :mod:`csv` is used, so all arguments to
    ``csv.reader`` and ``csv.writer`` can be given in *csv_args*."""

    value = File.value
    """Other than a normal CSV_File the value of a CSV_File is a list
    of lists, which represents the structure of the csv file. This
    value can be manipulated by the user.

    >>> CSV_File("csv_output").value
    [["1", "2", "3"]]"""

    def __init__(self, default_filename = "", **csv_args):
        File.__init__(self, default_filename)
        self.csv_args = csv_args

    def after_read(self, value):
        fd = StringIO(value)
        reader = csv.reader(fd, self.csv_args)
        return list(reader)
    def before_write(self, value):
        fd = StringIO()
        writer = csv.writer(fd, self.csv_args)
        writer.writerows(value)
        return fd.getvalue()

    def write(self):
        raise NotImplemented

    def append(self, row):
        """Append a row to the csv file

        It is just a shorthand for

        >>> csv_file.value.append([1,2,3])

        :param row: row to append
        :type row: list."""
        if type(row) != list:
            raise TypeError("list of values required")
        self.value.append(row)