2 A helper module that can work with paths
3 that can refer to data inside a zipfile
5 XXX: Need to determine if isdir("zipfile.zip")
6 should return True or False. Currently returns
7 True, but that might do the wrong thing with
8 data-files that are zipfiles.
11 import zipfile
as _zipfile
12 import errno
as _errno
33 if _sys
.version_info
[0] == 2:
34 from StringIO
import StringIO
as _BaseStringIO
35 from StringIO
import StringIO
as _BaseBytesIO
37 class _StringIO (_BaseStringIO
):
41 def __exit__(self
, exc_type
, exc_value
, traceback
):
45 class _BytesIO (_BaseBytesIO
):
49 def __exit__(self
, exc_type
, exc_value
, traceback
):
54 from io
import StringIO
as _StringIO
55 from io
import BytesIO
as _BytesIO
62 if _os
.path
.exists(path
):
67 root
= _os
.path
.splitdrive(path
)
68 while path
and path
!= root
:
69 path
, bn
= _os
.path
.split(path
)
71 if _os
.path
.exists(path
):
76 _errno
.ENOENT
, full_path
,
77 "No such file or directory")
79 if not _os
.path
.isfile(path
):
81 _errno
.ENOENT
, full_path
,
82 "No such file or directory")
85 return path
, '/'.join(rest
).strip('/')
88 def open(path
, mode
='r'):
89 if 'w' in mode
or 'a' in mode
:
91 _errno
.EINVAL
, path
, "Write access not supported")
94 _errno
.EINVAL
, path
, "Write access not supported")
97 path
, rest
= _locate(path
)
99 return _open(path
, mode
)
103 zf
= _zipfile
.ZipFile(path
, 'r')
105 except _zipfile
.error
:
107 _errno
.ENOENT
, full_path
,
108 "No such file or directory")
112 except (_zipfile
.error
, KeyError):
115 _errno
.ENOENT
, full_path
,
116 "No such file or directory")
120 return _BytesIO(data
)
123 if _sys
.version_info
[0] == 3:
124 data
= data
.decode('ascii')
126 return _StringIO(data
)
130 path
, rest
= _locate(path
)
131 if not rest
and not _os
.path
.isfile(path
):
132 return _os
.listdir(path
)
136 zf
= _zipfile
.ZipFile(path
, 'r')
138 except _zipfile
.error
:
140 _errno
.ENOENT
, full_path
,
141 "No such file or directory")
146 for nm
in zf
.namelist():
149 value
= nm
.split('/')[0]
153 elif nm
.startswith(rest
):
158 elif nm
[len(rest
)] == '/':
160 value
= nm
[len(rest
)+1:].split('/')[0]
166 except _zipfile
.error
:
169 _errno
.ENOENT
, full_path
,
170 "No such file or directory")
176 _errno
.ENOENT
, full_path
,
177 "No such file or directory")
183 path
, rest
= _locate(path
)
185 ok
= _os
.path
.isfile(path
)
188 zf
= _zipfile
.ZipFile(path
, 'r')
190 except (_zipfile
.error
, IOError):
196 zf
= _zipfile
.ZipFile(path
, 'r')
197 info
= zf
.getinfo(rest
)
200 except (KeyError, _zipfile
.error
):
204 # Check if this is a directory
206 info
= zf
.getinfo(rest
+ '/')
213 for nm
in zf
.namelist():
214 if nm
.startswith(rest
):
218 # No trace in zipfile
220 _errno
.ENOENT
, full_path
,
221 "No such file or directory")
228 path
, rest
= _locate(path
)
230 ok
= _os
.path
.isdir(path
)
233 zf
= _zipfile
.ZipFile(path
, 'r')
234 except (_zipfile
.error
, IOError):
242 zf
= _zipfile
.ZipFile(path
)
243 except _zipfile
.error
:
245 _errno
.ENOENT
, full_path
,
246 "No such file or directory")
249 info
= zf
.getinfo(rest
)
258 info
= zf
.getinfo(rest
)
262 # Directory entry found
265 for nm
in zf
.namelist():
266 if nm
.startswith(rest
):
270 _errno
.ENOENT
, full_path
,
271 "No such file or directory")
279 path
, rest
= _locate(path
)
281 return _os
.path
.islink(path
)
284 zf
= _zipfile
.ZipFile(path
)
285 except _zipfile
.error
:
287 _errno
.ENOENT
, full_path
,
288 "No such file or directory")
293 info
= zf
.getinfo(rest
)
302 info
= zf
.getinfo(rest
)
309 for nm
in zf
.namelist():
310 if nm
.startswith(rest
):
311 # Directory without listing
315 _errno
.ENOENT
, full_path
,
316 "No such file or directory")
324 path
, rest
= _locate(path
)
326 # No symlinks inside zipfiles
328 _errno
.ENOENT
, full_path
,
329 "No such file or directory")
331 return _os
.readlink(path
)
335 path
, rest
= _locate(path
)
337 return _os
.stat(path
).st_mode
341 zf
= _zipfile
.ZipFile(path
)
345 info
= zf
.getinfo(rest
)
351 info
= zf
.getinfo(rest
+ '/')
357 for nm
in zf
.namelist():
358 if nm
.startswith(rest
):
362 _errno
.ENOENT
, full_path
,
363 "No such file or directory")
365 # Directory exists, but has no entry of its own.
366 return _DFLT_DIR_MODE
368 # The mode is stored without file-type in external_attr.
369 if (info
.external_attr
>> 16) != 0:
370 return _stat
.S_IFREG |
(info
.external_attr
>> 16)
372 return _DFLT_FILE_MODE
379 _errno
.ENOENT
, full_path
,
380 "No such file or directory")
384 path
, rest
= _locate(path
)
386 return _os
.path
.getmtime(path
)
390 zf
= _zipfile
.ZipFile(path
)
394 info
= zf
.getinfo(rest
)
400 info
= zf
.getinfo(rest
+ '/')
406 for nm
in zf
.namelist():
407 if nm
.startswith(rest
):
411 _errno
.ENOENT
, full_path
,
412 "No such file or directory")
414 # Directory exists, but has no entry of its
415 # own, fake mtime by using the timestamp of
416 # the zipfile itself.
417 return _os
.path
.getmtime(path
)
419 return _time
.mktime(info
.date_time
+ (0, 0, -1))
425 _errno
.ENOENT
, full_path
,
426 "No such file or directory")