25 testpid = win32.testpid |
25 testpid = win32.testpid |
26 unlink = win32.unlink |
26 unlink = win32.unlink |
27 |
27 |
28 umask = 0o022 |
28 umask = 0o022 |
29 |
29 |
|
30 class mixedfilemodewrapper(object): |
|
31 """Wraps a file handle when it is opened in read/write mode. |
|
32 |
|
33 fopen() and fdopen() on Windows have a specific-to-Windows requirement |
|
34 that files opened with mode r+, w+, or a+ make a call to a file positioning |
|
35 function when switching between reads and writes. Without this extra call, |
|
36 Python will raise a not very intuitive "IOError: [Errno 0] Error." |
|
37 |
|
38 This class wraps posixfile instances when the file is opened in read/write |
|
39 mode and automatically adds checks or inserts appropriate file positioning |
|
40 calls when necessary. |
|
41 """ |
|
42 OPNONE = 0 |
|
43 OPREAD = 1 |
|
44 OPWRITE = 2 |
|
45 |
|
46 def __init__(self, fp): |
|
47 object.__setattr__(self, '_fp', fp) |
|
48 object.__setattr__(self, '_lastop', 0) |
|
49 |
|
50 def __getattr__(self, name): |
|
51 return getattr(self._fp, name) |
|
52 |
|
53 def __setattr__(self, name, value): |
|
54 return self._fp.__setattr__(name, value) |
|
55 |
|
56 def _noopseek(self): |
|
57 self._fp.seek(0, os.SEEK_CUR) |
|
58 |
|
59 def seek(self, *args, **kwargs): |
|
60 object.__setattr__(self, '_lastop', self.OPNONE) |
|
61 return self._fp.seek(*args, **kwargs) |
|
62 |
|
63 def write(self, d): |
|
64 if self._lastop == self.OPREAD: |
|
65 self._noopseek() |
|
66 |
|
67 object.__setattr__(self, '_lastop', self.OPWRITE) |
|
68 return self._fp.write(d) |
|
69 |
|
70 def writelines(self, *args, **kwargs): |
|
71 if self._lastop == self.OPREAD: |
|
72 self._noopeseek() |
|
73 |
|
74 object.__setattr__(self, '_lastop', self.OPWRITE) |
|
75 return self._fp.writelines(*args, **kwargs) |
|
76 |
|
77 def read(self, *args, **kwargs): |
|
78 if self._lastop == self.OPWRITE: |
|
79 self._noopseek() |
|
80 |
|
81 object.__setattr__(self, '_lastop', self.OPREAD) |
|
82 return self._fp.read(*args, **kwargs) |
|
83 |
|
84 def readline(self, *args, **kwargs): |
|
85 if self._lastop == self.OPWRITE: |
|
86 self._noopseek() |
|
87 |
|
88 object.__setattr__(self, '_lastop', self.OPREAD) |
|
89 return self._fp.readline(*args, **kwargs) |
|
90 |
|
91 def readlines(self, *args, **kwargs): |
|
92 if self._lastop == self.OPWRITE: |
|
93 self._noopseek() |
|
94 |
|
95 object.__setattr__(self, '_lastop', self.OPREAD) |
|
96 return self._fp.readlines(*args, **kwargs) |
|
97 |
30 def posixfile(name, mode='r', buffering=-1): |
98 def posixfile(name, mode='r', buffering=-1): |
31 '''Open a file with even more POSIX-like semantics''' |
99 '''Open a file with even more POSIX-like semantics''' |
32 try: |
100 try: |
33 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError |
101 fp = osutil.posixfile(name, mode, buffering) # may raise WindowsError |
34 |
102 |
35 # The position when opening in append mode is implementation defined, so |
103 # The position when opening in append mode is implementation defined, so |
36 # make it consistent with other platforms, which position at EOF. |
104 # make it consistent with other platforms, which position at EOF. |
37 if 'a' in mode: |
105 if 'a' in mode: |
38 fp.seek(0, os.SEEK_END) |
106 fp.seek(0, os.SEEK_END) |
|
107 |
|
108 if '+' in mode: |
|
109 return mixedfilemodewrapper(fp) |
39 |
110 |
40 return fp |
111 return fp |
41 except WindowsError as err: |
112 except WindowsError as err: |
42 # convert to a friendlier exception |
113 # convert to a friendlier exception |
43 raise IOError(err.errno, '%s: %s' % (name, err.strerror)) |
114 raise IOError(err.errno, '%s: %s' % (name, err.strerror)) |