~mterry/duplicity/gdrive

« back to all changes in this revision

Viewing changes to duplicity/dup_temp.py

  • Committer: bescoto
  • Date: 2002-10-29 01:49:46 UTC
  • Revision ID: vcs-imports@canonical.com-20021029014946-3m4rmm5plom7pl6q
Initial checkin

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
# Copyright 2002 Ben Escoto
 
2
#
 
3
# This file is part of duplicity.
 
4
#
 
5
# duplicity is free software; you can redistribute it and/or modify it
 
6
# under the terms of the GNU General Public License as published by
 
7
# the Free Software Foundation, Inc., 675 Mass Ave, Cambridge MA
 
8
# 02139, USA; either version 2 of the License, or (at your option) any
 
9
# later version; incorporated herein by reference.
 
10
 
 
11
"""Manage temporary files"""
 
12
 
 
13
import tempfile
 
14
import log, path, file_naming
 
15
 
 
16
tempfile_names = []
 
17
 
 
18
def register_filename(filename):
 
19
        """Add filename to tempfile list"""
 
20
        assert not filename in tempfile_names
 
21
        tempfile_names.append(filename)
 
22
 
 
23
def unregister_filename(filename):
 
24
        """Remove filename from tempfile list"""
 
25
        try: index = tempfile_names.index(filename)
 
26
        except ValueError: log.Log("Warning, %s is not a registered tempfile" %
 
27
                                                           filename)
 
28
        else: del tempfile_names[index]
 
29
 
 
30
def cleanup():
 
31
        """Delete all existing tempfiles"""
 
32
        for filename in tempfile_names:
 
33
                log.Warn("%s still in tempfile list, deleting" % (filename,))
 
34
                p = path.Path(filename)
 
35
                if p.exists(): p.delete()
 
36
 
 
37
 
 
38
def new_temppath():
 
39
        """Return a new TempPath"""
 
40
        filename = tempfile.mktemp()
 
41
        register_filename(filename)
 
42
        return TempPath(filename)
 
43
 
 
44
class TempPath(path.Path):
 
45
        """Path object used as a temporary file"""
 
46
        def delete(self):
 
47
                """Unregister and delete"""
 
48
                path.Path.delete(self)
 
49
                unregister_filename(self.name)
 
50
 
 
51
        def open_with_delete(self, mode):
 
52
                """Returns a fileobj.  When that is closed, delete file"""
 
53
                fh = FileobjHooked(path.Path.open(self, mode))
 
54
                fh.addhook(self.delete)
 
55
                return fh
 
56
 
 
57
 
 
58
def get_fileobj_duppath(dirpath, filename):
 
59
        """Return a file object open for writing, will write to filename
 
60
 
 
61
        Data will be processed and written to a temporary file.  When the
 
62
        return fileobject is closed, rename to final position.  filename
 
63
        must be a recognizable duplicity data file.
 
64
 
 
65
        """
 
66
        oldtempdir = tempfile.tempdir
 
67
        tempfile.tempdir = dirpath.name
 
68
        tdp = new_tempduppath(file_naming.parse(filename))
 
69
        tempfile.tempdir = oldtempdir
 
70
        fh = FileobjHooked(tdp.filtered_open("wb"))
 
71
        fh.addhook(lambda: tdp.rename(dirpath.append(filename)))
 
72
        return fh
 
73
 
 
74
def new_tempduppath(parseresults):
 
75
        """Return a new TempDupPath, using settings from parseresults"""
 
76
        filename = tempfile.mktemp()
 
77
        register_filename(filename)
 
78
        return TempDupPath(filename, parseresults = parseresults)
 
79
 
 
80
class TempDupPath(path.DupPath):
 
81
        """Like TempPath, but build around DupPath"""
 
82
        def delete(self):
 
83
                """Unregister and delete"""
 
84
                path.DupPath.delete(self)
 
85
                unregister_filename(self.name)
 
86
 
 
87
        def filtered_open_with_delete(self, mode):
 
88
                """Returns a filtered fileobj.  When that is closed, delete file"""
 
89
                fh = FileobjHooked(path.DupPath.filtered_open(self, mode))
 
90
                fh.addhook(self.delete)
 
91
                return fh
 
92
 
 
93
        def open_with_delete(self, mode = "rb"):
 
94
                """Returns a fileobj.  When that is closed, delete file"""
 
95
                assert mode == "rb" # Why write a file and then close it immediately?
 
96
                fh = FileobjHooked(path.DupPath.open(self, mode))
 
97
                fh.addhook(self.delete)
 
98
                return fh
 
99
 
 
100
class FileobjHooked:
 
101
        """Simulate a file, but add hook on close"""
 
102
        def __init__(self, fileobj):
 
103
                """Initializer.  fileobj is the file object to simulate"""
 
104
                self.fileobj = fileobj
 
105
                self.closed = None
 
106
                self.hooklist = [] # fill later with thunks to run on close
 
107
 
 
108
        def write(self, buf): return self.fileobj.write(buf)
 
109
        def read(self, length = -1): return self.fileobj.read(length)
 
110
 
 
111
        def close(self):
 
112
                """Close fileobj, running hooks right afterwards"""
 
113
                assert not self.fileobj.close()
 
114
                for hook in self.hooklist: hook()
 
115
 
 
116
        def addhook(self, hook):
 
117
                """Add hook (function taking no arguments) to run upon closing"""
 
118
                self.hooklist.append(hook)
 
119