Misc. changes, including documenting the ability to specify a class attribute in...
[python.git] / Lib / posixfile.py
blob763c605c95f04a6c2de9e10ecb7bbc96d2f4b7f7
1 """Extended file operations available in POSIX.
3 f = posixfile.open(filename, [mode, [bufsize]])
4 will create a new posixfile object
6 f = posixfile.fileopen(fileobject)
7 will create a posixfile object from a builtin file object
9 f.file()
10 will return the original builtin file object
12 f.dup()
13 will return a new file object based on a new filedescriptor
15 f.dup2(fd)
16 will return a new file object based on the given filedescriptor
18 f.flags(mode)
19 will turn on the associated flag (merge)
20 mode can contain the following characters:
22 (character representing a flag)
23 a append only flag
24 c close on exec flag
25 n no delay flag
26 s synchronization flag
27 (modifiers)
28 ! turn flags 'off' instead of default 'on'
29 = copy flags 'as is' instead of default 'merge'
30 ? return a string in which the characters represent the flags
31 that are set
33 note: - the '!' and '=' modifiers are mutually exclusive.
34 - the '?' modifier will return the status of the flags after they
35 have been changed by other characters in the mode string
37 f.lock(mode [, len [, start [, whence]]])
38 will (un)lock a region
39 mode can contain the following characters:
41 (character representing type of lock)
42 u unlock
43 r read lock
44 w write lock
45 (modifiers)
46 | wait until the lock can be granted
47 ? return the first lock conflicting with the requested lock
48 or 'None' if there is no conflict. The lock returned is in the
49 format (mode, len, start, whence, pid) where mode is a
50 character representing the type of lock ('r' or 'w')
52 note: - the '?' modifier prevents a region from being locked; it is
53 query only
54 """
57 class _posixfile_:
58 """File wrapper class that provides extra POSIX file routines."""
60 states = ['open', 'closed']
63 # Internal routines
65 def __repr__(self):
66 file = self._file_
67 return "<%s posixfile '%s', mode '%s' at %s>" % \
68 (self.states[file.closed], file.name, file.mode, \
69 hex(id(self))[2:])
72 # Initialization routines
74 def open(self, name, mode='r', bufsize=-1):
75 import __builtin__
76 return self.fileopen(__builtin__.open(name, mode, bufsize))
78 def fileopen(self, file):
79 import types
80 if repr(type(file)) != "<type 'file'>":
81 raise TypeError, 'posixfile.fileopen() arg must be file object'
82 self._file_ = file
83 # Copy basic file methods
84 for maybemethod in dir(file):
85 if not maybemethod.startswith('_'):
86 attr = getattr(file, maybemethod)
87 if isinstance(attr, types.BuiltinMethodType):
88 setattr(self, maybemethod, attr)
89 return self
92 # New methods
94 def file(self):
95 return self._file_
97 def dup(self):
98 import posix
100 if not hasattr(posix, 'fdopen'):
101 raise AttributeError, 'dup() method unavailable'
103 return posix.fdopen(posix.dup(self._file_.fileno()), self._file_.mode)
105 def dup2(self, fd):
106 import posix
108 if not hasattr(posix, 'fdopen'):
109 raise AttributeError, 'dup() method unavailable'
111 posix.dup2(self._file_.fileno(), fd)
112 return posix.fdopen(fd, self._file_.mode)
114 def flags(self, *which):
115 import fcntl, os
117 if which:
118 if len(which) > 1:
119 raise TypeError, 'Too many arguments'
120 which = which[0]
121 else: which = '?'
123 l_flags = 0
124 if 'n' in which: l_flags = l_flags | os.O_NDELAY
125 if 'a' in which: l_flags = l_flags | os.O_APPEND
126 if 's' in which: l_flags = l_flags | os.O_SYNC
128 file = self._file_
130 if '=' not in which:
131 cur_fl = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
132 if '!' in which: l_flags = cur_fl & ~ l_flags
133 else: l_flags = cur_fl | l_flags
135 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFL, l_flags)
137 if 'c' in which:
138 arg = ('!' not in which) # 0 is don't, 1 is do close on exec
139 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_SETFD, arg)
141 if '?' in which:
142 which = '' # Return current flags
143 l_flags = fcntl.fcntl(file.fileno(), fcntl.F_GETFL, 0)
144 if os.O_APPEND & l_flags: which = which + 'a'
145 if fcntl.fcntl(file.fileno(), fcntl.F_GETFD, 0) & 1:
146 which = which + 'c'
147 if os.O_NDELAY & l_flags: which = which + 'n'
148 if os.O_SYNC & l_flags: which = which + 's'
149 return which
151 def lock(self, how, *args):
152 import struct, fcntl
154 if 'w' in how: l_type = fcntl.F_WRLCK
155 elif 'r' in how: l_type = fcntl.F_RDLCK
156 elif 'u' in how: l_type = fcntl.F_UNLCK
157 else: raise TypeError, 'no type of lock specified'
159 if '|' in how: cmd = fcntl.F_SETLKW
160 elif '?' in how: cmd = fcntl.F_GETLK
161 else: cmd = fcntl.F_SETLK
163 l_whence = 0
164 l_start = 0
165 l_len = 0
167 if len(args) == 1:
168 l_len = args[0]
169 elif len(args) == 2:
170 l_len, l_start = args
171 elif len(args) == 3:
172 l_len, l_start, l_whence = args
173 elif len(args) > 3:
174 raise TypeError, 'too many arguments'
176 # Hack by davem@magnet.com to get locking to go on freebsd;
177 # additions for AIX by Vladimir.Marangozov@imag.fr
178 import sys, os
179 if sys.platform in ('netbsd1',
180 'openbsd2',
181 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
182 'freebsd6', 'freebsd7',
183 'bsdos2', 'bsdos3', 'bsdos4'):
184 flock = struct.pack('lxxxxlxxxxlhh', \
185 l_start, l_len, os.getpid(), l_type, l_whence)
186 elif sys.platform in ('aix3', 'aix4'):
187 flock = struct.pack('hhlllii', \
188 l_type, l_whence, l_start, l_len, 0, 0, 0)
189 else:
190 flock = struct.pack('hhllhh', \
191 l_type, l_whence, l_start, l_len, 0, 0)
193 flock = fcntl.fcntl(self._file_.fileno(), cmd, flock)
195 if '?' in how:
196 if sys.platform in ('netbsd1',
197 'openbsd2',
198 'freebsd2', 'freebsd3', 'freebsd4', 'freebsd5',
199 'bsdos2', 'bsdos3', 'bsdos4'):
200 l_start, l_len, l_pid, l_type, l_whence = \
201 struct.unpack('lxxxxlxxxxlhh', flock)
202 elif sys.platform in ('aix3', 'aix4'):
203 l_type, l_whence, l_start, l_len, l_sysid, l_pid, l_vfs = \
204 struct.unpack('hhlllii', flock)
205 elif sys.platform == "linux2":
206 l_type, l_whence, l_start, l_len, l_pid, l_sysid = \
207 struct.unpack('hhllhh', flock)
208 else:
209 l_type, l_whence, l_start, l_len, l_sysid, l_pid = \
210 struct.unpack('hhllhh', flock)
212 if l_type != fcntl.F_UNLCK:
213 if l_type == fcntl.F_RDLCK:
214 return 'r', l_len, l_start, l_whence, l_pid
215 else:
216 return 'w', l_len, l_start, l_whence, l_pid
218 def open(name, mode='r', bufsize=-1):
219 """Public routine to open a file as a posixfile object."""
220 return _posixfile_().open(name, mode, bufsize)
222 def fileopen(file):
223 """Public routine to get a posixfile object from a Python file object."""
224 return _posixfile_().fileopen(file)
227 # Constants
229 SEEK_SET = 0
230 SEEK_CUR = 1
231 SEEK_END = 2
234 # End of posixfile.py