X-Git-Url: http://dolda2000.com/gitweb/?a=blobdiff_plain;f=manga%2Fprofile.py;h=cc0a4a1dc69e618a2648662ce7165f9f557bca77;hb=HEAD;hp=2620a9853fb9ee7768af3a81a97067e28ff9d5d9;hpb=434236682e0d553965b2912d1d307e3b1473c491;p=automanga.git diff --git a/manga/profile.py b/manga/profile.py index 2620a98..2b7a15a 100644 --- a/manga/profile.py +++ b/manga/profile.py @@ -4,16 +4,49 @@ pj = os.path.join home = os.getenv("HOME") if home is None or not os.path.isdir(home): raise Exception("Could not find home directory for profile keeping") -basedir = pj(home, ".manga", "profiles") +confdir = pj(home, ".manga") +basedir = pj(confdir, "profiles") + +class txfile(object): + def __init__(self, name, mode): + self.realname = name + self.tempname = name + ".new" + self.bk = open(self.tempname, mode) + + def close(self, abort=False): + self.bk.close() + if abort: + os.unlink(self.tempname) + else: + os.rename(self.tempname, self.realname) + + def read(self, sz=-1): + return self.bk.read(sz) + + def write(self, data): + return self.bk.write(data) + + def __enter__(self): + return self + + def __exit__(self, *exc_info): + if exc_info[0] is not None: + self.close(True) + else: + self.close(False) def openwdir(nm, mode="r"): + ft = open + if mode == "W": + mode = "w" + ft = txfile if os.path.exists(nm): - return open(nm, mode) + return ft(nm, mode) if mode != "r": d = os.path.dirname(nm) if not os.path.isdir(d): os.makedirs(d) - return open(nm, mode) + return ft(nm, mode) def splitline(line): def bsq(c): @@ -60,6 +93,13 @@ def splitline(line): ret.append(buf) return ret +def splitlines(fp): + for line in fp: + cur = splitline(line) + if len(cur) < 1: + continue + yield cur + def consline(*words): buf = "" for w in words: @@ -86,9 +126,12 @@ class manga(object): self.props = self.loadprops() def open(self): - import lib + from . import lib return lib.findlib(self.libnm).byid(self.id) + def save(self): + pass + class memmanga(manga): def __init__(self, profile, libnm, id): super(memmanga, self).__init__(profile, libnm, id) @@ -96,17 +139,72 @@ class memmanga(manga): def loadprops(self): return {} +class tagview(object): + def __init__(self, manga): + self.manga = manga + self.profile = manga.profile + + def add(self, *tags): + mt = self.getall(self.profile) + ctags = mt.setdefault((self.manga.libnm, self.manga.id), set()) + ctags |= set(tags) + self.save(self.profile, mt) + + def remove(self, *tags): + mt = self.getall(self.profile) + ctags = mt.get((self.manga.libnm, self.manga.id), set()) + ctags -= set(tags) + if len(ctags) < 1: + try: + del mt[self.manga.libnm, self.manga.id] + except KeyError: + pass + self.save(self.profile, mt) + + def __iter__(self): + return iter(self.getall(self.profile).get((self.manga.libnm, self.manga.id), set())) + + @staticmethod + def getall(profile): + ret = {} + try: + with profile.file("tags") as fp: + for words in splitlines(fp): + libnm, id = words[0:2] + tags = set(words[2:]) + ret[libnm, id] = tags + except IOError: + pass + return ret + + @staticmethod + def save(profile, m): + with profile.file("tags", "W") as fp: + for (libnm, id), tags in m.items(): + fp.write(consline(libnm, id, *tags) + "\n") + + @staticmethod + def bytag(profile, tag): + try: + with profile.file("tags") as fp: + for words in splitlines(fp): + libnm, id = words[0:2] + tags = words[2:] + if tag in tags: + yield profile.getmanga(libnm, id) + except IOError: + pass + class filemanga(manga): def __init__(self, profile, libnm, id, path): self.path = path super(filemanga, self).__init__(profile, libnm, id) + self.tags = tagview(self) def loadprops(self): ret = {} with openwdir(self.path) as f: - for line in f: - words = splitline(line) - if len(words) < 1: continue + for words in splitlines(f): if words[0] == "set" and len(words) > 2: ret[words[1]] = words[2] elif words[0] == "lset" and len(words) > 1: @@ -114,13 +212,19 @@ class filemanga(manga): return ret def save(self): - with openwdir(self.path, "w") as f: - for key, val in self.props.iteritems(): + with openwdir(self.path, "W") as f: + for key, val in self.props.items(): if isinstance(val, str): f.write(consline("set", key, val) + "\n") else: f.write(consline("lset", key, *val) + "\n") + def mtime(self): + try: + return os.stat(self.path).st_mtime + except FileNotFoundError: + return 0 + class profile(object): def __init__(self, dir): self.dir = dir @@ -131,10 +235,7 @@ class profile(object): ret = {} if os.path.exists(pj(self.dir, "map")): with openwdir(pj(self.dir, "map")) as f: - for ln in f: - words = splitline(ln) - if len(words) < 1: - continue + for words in splitlines(f): if words[0] == "seq" and len(words) > 1: try: seq = int(words[1]) @@ -148,9 +249,9 @@ class profile(object): return seq, ret def savemapping(self, seq, m): - with openwdir(pj(self.dir, "map"), "w") as f: + with openwdir(pj(self.dir, "map"), "W") as f: f.write(consline("seq", str(seq)) + "\n") - for (libnm, id), num in m.iteritems(): + for (libnm, id), num in m.items(): f.write(consline("manga", libnm, id, str(num)) + "\n") def getmanga(self, libnm, id, creat=False): @@ -161,7 +262,7 @@ class profile(object): raise KeyError("no such manga: (%s, %s)" % (libnm, id)) while True: try: - fp = openwdir(pj(self.dir, "%i.manga" % seq), "wx") + fp = openwdir(pj(self.dir, "%i.manga" % seq), "x") except IOError: seq += 1 else: @@ -174,7 +275,7 @@ class profile(object): def setlast(self): if self.name is None: raise ValueError("profile at " + self.dir + " has no name") - with openwdir(pj(basedir, "last"), "w") as f: + with openwdir(pj(basedir, "last"), "W") as f: f.write(self.name + "\n") def getaliases(self): @@ -189,10 +290,13 @@ class profile(object): return ret def savealiases(self, map): - with openwdir(pj(self.dir, "alias"), "w") as f: - for nm, (libnm, id) in map.iteritems(): + with openwdir(pj(self.dir, "alias"), "W") as f: + for nm, (libnm, id) in map.items(): f.write(consline("alias", nm, libnm, id) + "\n") + def file(self, name, mode="r"): + return openwdir(pj(self.dir, name), mode) + def getalias(self, nm): return self.getaliases()[nm] @@ -201,6 +305,9 @@ class profile(object): aliases[nm] = libnm, id self.savealiases(aliases) + def bytag(self, tag): + return tagview.bytag(self, tag) + @classmethod def byname(cls, name): if not name or name == "last" or name[0] == '.':