~ubuntu-branches/ubuntu/maverick/python3.1/maverick

« back to all changes in this revision

Viewing changes to Demo/pdist/FSProxy.py

  • Committer: Bazaar Package Importer
  • Author(s): Matthias Klose
  • Date: 2009-03-23 00:01:27 UTC
  • Revision ID: james.westby@ubuntu.com-20090323000127-5fstfxju4ufrhthq
Tags: upstream-3.1~a1+20090322
ImportĀ upstreamĀ versionĀ 3.1~a1+20090322

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
"""File System Proxy.
 
2
 
 
3
Provide an OS-neutral view on a file system, locally or remotely.
 
4
The functionality is geared towards implementing some sort of
 
5
rdist-like utility between a Mac and a UNIX system.
 
6
 
 
7
The module defines three classes:
 
8
 
 
9
FSProxyLocal  -- used for local access
 
10
FSProxyServer -- used on the server side of remote access
 
11
FSProxyClient -- used on the client side of remote access
 
12
 
 
13
The remote classes are instantiated with an IP address and an optional
 
14
verbosity flag.
 
15
"""
 
16
 
 
17
import server
 
18
import client
 
19
import md5
 
20
import os
 
21
import fnmatch
 
22
from stat import *
 
23
import time
 
24
import fnmatch
 
25
 
 
26
if os.name == 'mac':
 
27
    import macfs
 
28
    maxnamelen = 31
 
29
else:
 
30
    macfs = None
 
31
    maxnamelen = 255
 
32
 
 
33
skipnames = (os.curdir, os.pardir)
 
34
 
 
35
 
 
36
class FSProxyLocal:
 
37
 
 
38
    def __init__(self):
 
39
        self._dirstack = []
 
40
        self._ignore = ['*.pyc'] + self._readignore()
 
41
 
 
42
    def _close(self):
 
43
        while self._dirstack:
 
44
            self.back()
 
45
 
 
46
    def _readignore(self):
 
47
        file = self._hide('ignore')
 
48
        try:
 
49
            f = open(file)
 
50
        except IOError:
 
51
            file = self._hide('synctree.ignorefiles')
 
52
            try:
 
53
                f = open(file)
 
54
            except IOError:
 
55
                return []
 
56
        ignore = []
 
57
        while 1:
 
58
            line = f.readline()
 
59
            if not line: break
 
60
            if line[-1] == '\n': line = line[:-1]
 
61
            ignore.append(line)
 
62
        f.close()
 
63
        return ignore
 
64
 
 
65
    def _hidden(self, name):
 
66
        if os.name == 'mac':
 
67
            return name[0] == '(' and name[-1] == ')'
 
68
        else:
 
69
            return name[0] == '.'
 
70
 
 
71
    def _hide(self, name):
 
72
        if os.name == 'mac':
 
73
            return '(%s)' % name
 
74
        else:
 
75
            return '.%s' % name
 
76
 
 
77
    def visible(self, name):
 
78
        if len(name) > maxnamelen: return 0
 
79
        if name[-1] == '~': return 0
 
80
        if name in skipnames: return 0
 
81
        if self._hidden(name): return 0
 
82
        head, tail = os.path.split(name)
 
83
        if head or not tail: return 0
 
84
        if macfs:
 
85
            if os.path.exists(name) and not os.path.isdir(name):
 
86
                try:
 
87
                    fs = macfs.FSSpec(name)
 
88
                    c, t = fs.GetCreatorType()
 
89
                    if t != 'TEXT': return 0
 
90
                except macfs.error as msg:
 
91
                    print("***", name, msg)
 
92
                    return 0
 
93
        else:
 
94
            if os.path.islink(name): return 0
 
95
            if '\0' in open(name, 'rb').read(512): return 0
 
96
        for ign in self._ignore:
 
97
            if fnmatch.fnmatch(name, ign): return 0
 
98
        return 1
 
99
 
 
100
    def check(self, name):
 
101
        if not self.visible(name):
 
102
            raise os.error("protected name %s" % repr(name))
 
103
 
 
104
    def checkfile(self, name):
 
105
        self.check(name)
 
106
        if not os.path.isfile(name):
 
107
            raise os.error("not a plain file %s" % repr(name))
 
108
 
 
109
    def pwd(self):
 
110
        return os.getcwd()
 
111
 
 
112
    def cd(self, name):
 
113
        self.check(name)
 
114
        save = os.getcwd(), self._ignore
 
115
        os.chdir(name)
 
116
        self._dirstack.append(save)
 
117
        self._ignore = self._ignore + self._readignore()
 
118
 
 
119
    def back(self):
 
120
        if not self._dirstack:
 
121
            raise os.error("empty directory stack")
 
122
        dir, ignore = self._dirstack[-1]
 
123
        os.chdir(dir)
 
124
        del self._dirstack[-1]
 
125
        self._ignore = ignore
 
126
 
 
127
    def _filter(self, files, pat = None):
 
128
        if pat:
 
129
            def keep(name, pat = pat):
 
130
                return fnmatch.fnmatch(name, pat)
 
131
            files = list(filter(keep, files))
 
132
        files = list(filter(self.visible, files))
 
133
        files.sort()
 
134
        return files
 
135
 
 
136
    def list(self, pat = None):
 
137
        files = os.listdir(os.curdir)
 
138
        return self._filter(files, pat)
 
139
 
 
140
    def listfiles(self, pat = None):
 
141
        files = os.listdir(os.curdir)
 
142
        files = list(filter(os.path.isfile, files))
 
143
        return self._filter(files, pat)
 
144
 
 
145
    def listsubdirs(self, pat = None):
 
146
        files = os.listdir(os.curdir)
 
147
        files = list(filter(os.path.isdir, files))
 
148
        return self._filter(files, pat)
 
149
 
 
150
    def exists(self, name):
 
151
        return self.visible(name) and os.path.exists(name)
 
152
 
 
153
    def isdir(self, name):
 
154
        return self.visible(name) and os.path.isdir(name)
 
155
 
 
156
    def islink(self, name):
 
157
        return self.visible(name) and os.path.islink(name)
 
158
 
 
159
    def isfile(self, name):
 
160
        return self.visible(name) and os.path.isfile(name)
 
161
 
 
162
    def sum(self, name):
 
163
        self.checkfile(name)
 
164
        BUFFERSIZE = 1024*8
 
165
        f = open(name)
 
166
        sum = md5.new()
 
167
        while 1:
 
168
            buffer = f.read(BUFFERSIZE)
 
169
            if not buffer:
 
170
                break
 
171
            sum.update(buffer)
 
172
        return sum.digest()
 
173
 
 
174
    def size(self, name):
 
175
        self.checkfile(name)
 
176
        return os.stat(name)[ST_SIZE]
 
177
 
 
178
    def mtime(self, name):
 
179
        self.checkfile(name)
 
180
        return time.localtime(os.stat(name)[ST_MTIME])
 
181
 
 
182
    def stat(self, name):
 
183
        self.checkfile(name)
 
184
        size = os.stat(name)[ST_SIZE]
 
185
        mtime = time.localtime(os.stat(name)[ST_MTIME])
 
186
        return size, mtime
 
187
 
 
188
    def info(self, name):
 
189
        sum = self.sum(name)
 
190
        size = os.stat(name)[ST_SIZE]
 
191
        mtime = time.localtime(os.stat(name)[ST_MTIME])
 
192
        return sum, size, mtime
 
193
 
 
194
    def _list(self, function, list):
 
195
        if list is None:
 
196
            list = self.listfiles()
 
197
        res = []
 
198
        for name in list:
 
199
            try:
 
200
                res.append((name, function(name)))
 
201
            except (os.error, IOError):
 
202
                res.append((name, None))
 
203
        return res
 
204
 
 
205
    def sumlist(self, list = None):
 
206
        return self._list(self.sum, list)
 
207
 
 
208
    def statlist(self, list = None):
 
209
        return self._list(self.stat, list)
 
210
 
 
211
    def mtimelist(self, list = None):
 
212
        return self._list(self.mtime, list)
 
213
 
 
214
    def sizelist(self, list = None):
 
215
        return self._list(self.size, list)
 
216
 
 
217
    def infolist(self, list = None):
 
218
        return self._list(self.info, list)
 
219
 
 
220
    def _dict(self, function, list):
 
221
        if list is None:
 
222
            list = self.listfiles()
 
223
        dict = {}
 
224
        for name in list:
 
225
            try:
 
226
                dict[name] = function(name)
 
227
            except (os.error, IOError):
 
228
                pass
 
229
        return dict
 
230
 
 
231
    def sumdict(self, list = None):
 
232
        return self.dict(self.sum, list)
 
233
 
 
234
    def sizedict(self, list = None):
 
235
        return self.dict(self.size, list)
 
236
 
 
237
    def mtimedict(self, list = None):
 
238
        return self.dict(self.mtime, list)
 
239
 
 
240
    def statdict(self, list = None):
 
241
        return self.dict(self.stat, list)
 
242
 
 
243
    def infodict(self, list = None):
 
244
        return self._dict(self.info, list)
 
245
 
 
246
    def read(self, name, offset = 0, length = -1):
 
247
        self.checkfile(name)
 
248
        f = open(name)
 
249
        f.seek(offset)
 
250
        if length == 0:
 
251
            data = ''
 
252
        elif length < 0:
 
253
            data = f.read()
 
254
        else:
 
255
            data = f.read(length)
 
256
        f.close()
 
257
        return data
 
258
 
 
259
    def create(self, name):
 
260
        self.check(name)
 
261
        if os.path.exists(name):
 
262
            self.checkfile(name)
 
263
            bname = name + '~'
 
264
            try:
 
265
                os.unlink(bname)
 
266
            except os.error:
 
267
                pass
 
268
            os.rename(name, bname)
 
269
        f = open(name, 'w')
 
270
        f.close()
 
271
 
 
272
    def write(self, name, data, offset = 0):
 
273
        self.checkfile(name)
 
274
        f = open(name, 'r+')
 
275
        f.seek(offset)
 
276
        f.write(data)
 
277
        f.close()
 
278
 
 
279
    def mkdir(self, name):
 
280
        self.check(name)
 
281
        os.mkdir(name, 0o777)
 
282
 
 
283
    def rmdir(self, name):
 
284
        self.check(name)
 
285
        os.rmdir(name)
 
286
 
 
287
 
 
288
class FSProxyServer(FSProxyLocal, server.Server):
 
289
 
 
290
    def __init__(self, address, verbose = server.VERBOSE):
 
291
        FSProxyLocal.__init__(self)
 
292
        server.Server.__init__(self, address, verbose)
 
293
 
 
294
    def _close(self):
 
295
        server.Server._close(self)
 
296
        FSProxyLocal._close(self)
 
297
 
 
298
    def _serve(self):
 
299
        server.Server._serve(self)
 
300
        # Retreat into start directory
 
301
        while self._dirstack: self.back()
 
302
 
 
303
 
 
304
class FSProxyClient(client.Client):
 
305
 
 
306
    def __init__(self, address, verbose = client.VERBOSE):
 
307
        client.Client.__init__(self, address, verbose)
 
308
 
 
309
 
 
310
def test():
 
311
    import string
 
312
    import sys
 
313
    if sys.argv[1:]:
 
314
        port = string.atoi(sys.argv[1])
 
315
    else:
 
316
        port = 4127
 
317
    proxy = FSProxyServer(('', port))
 
318
    proxy._serverloop()
 
319
 
 
320
 
 
321
if __name__ == '__main__':
 
322
    test()