Last active
October 19, 2015 02:53
-
-
Save internetimagery/ec5da479e09c1e350ad9 to your computer and use it in GitHub Desktop.
Dict - like interface for zipfile
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import shutil | |
import os.path | |
import zipfile | |
import collections | |
try: | |
import zlib | |
compress = zipfile.ZIP_DEFLATED | |
except ImportError: | |
compress = zipfile.ZIP_STORED | |
class Archive(collections.MutableMapping): | |
def __init__(s, path): | |
s._depth = 0 | |
s._mode = "r" | |
s._path = path | |
s._dirty = False | |
if os.path.isfile(path): | |
with s: s._data = dict((a, file) for a in s.z.namelist()) | |
else: | |
s._data = {} | |
s._mode = "w" | |
with s: pass | |
def __enter__(s): | |
if not s._depth: | |
s.z = zipfile.ZipFile(s._path, s._mode, compress) | |
s._depth += 1 | |
return s | |
def __exit__(s, *err): | |
s._depth -= 1 | |
s._mode = "r" | |
if not s._depth: | |
if s._dirty and not err[0]: | |
s._dirty = False | |
dirty = set(a for a, b in s._data.items() if b is not file) | |
n = set(s.z.namelist()) | |
if dirty - n and not dirty & n: | |
s.z.close() | |
s._mode = "a" | |
with s: | |
for k in dirty: | |
s.z.writestr(k, s._data[k]) | |
else: | |
read = s.z | |
s._mode = "w" | |
path, s._path = s._path, "%s.incomplete" % s._path | |
try: | |
with s: | |
s.z.comment = read.comment | |
for k in s._data: | |
if k in dirty: | |
s.z.writestr(k, s._data[k]) | |
else: | |
s.z.writestr(k, read.read(k)) | |
read.close() | |
shutil.move(s._path, path) | |
finally: | |
s._path = path | |
s._data = dict((a, file) for a in s.z.namelist()) | |
else: | |
s.z.close() | |
def __iter__(s): return iter(s._data) | |
def __repr__(s): return repr(s._data) | |
def __len__(s): return len(s._data) | |
def __getitem__(s, k): | |
with s: return s.z.read(k) | |
def __setitem__(s, k, v): | |
with s: | |
s._data[k] = v | |
s._dirty = True | |
def __delitem__(s, k): | |
with s: | |
del s._data[k] | |
s._dirty = True |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment