4 home = os.getenv("HOME")
5 if home is None or not os.path.isdir(home):
6 raise Exception("Could not find home directory for profile keeping")
7 confdir = pj(home, ".manga")
8 basedir = pj(confdir, "profiles")
11 def __init__(self, name, mode):
13 self.tempname = name + ".new"
14 self.bk = open(self.tempname, mode)
16 def close(self, abort=False):
19 os.unlink(self.tempname)
21 os.rename(self.tempname, self.realname)
23 def read(self, sz=-1):
24 return self.bk.read(sz)
26 def write(self, data):
27 return self.bk.write(data)
32 def __exit__(self, *exc_info):
33 if exc_info[0] is not None:
38 def openwdir(nm, mode="r"):
43 if os.path.exists(nm):
46 d = os.path.dirname(nm)
47 if not os.path.isdir(d):
53 if c == "\\": return "\\"
54 elif c == '"': return '"'
55 elif c == " ": return " "
56 elif c == "n": return "\n"
77 elif c == "\\" and p < len(line):
87 elif c == "\\" and p < len(line):
103 def consline(*words):
106 if any((c == "\\" or c == '"' or c == "\n" for c in w)):
109 if c == "\\": wb += "\\\\"
110 elif c == '"': wb += '\\"'
111 elif c == "\n": wb += "\\n"
114 if w == "" or any((c.isspace() for c in w)):
122 def __init__(self, profile, libnm, id):
123 self.profile = profile
126 self.props = self.loadprops()
130 return lib.findlib(self.libnm).byid(self.id)
135 class memmanga(manga):
136 def __init__(self, profile, libnm, id):
137 super(memmanga, self).__init__(profile, libnm, id)
142 class tagview(object):
143 def __init__(self, manga):
145 self.profile = manga.profile
147 def add(self, *tags):
148 mt = self.getall(self.profile)
149 ctags = mt.setdefault((self.manga.libnm, self.manga.id), set())
151 self.save(self.profile, mt)
153 def remove(self, *tags):
154 mt = self.getall(self.profile)
155 ctags = mt.get((self.manga.libnm, self.manga.id), set())
159 del mt[self.manga.libnm, self.manga.id]
162 self.save(self.profile, mt)
165 return iter(self.getall(self.profile).get((self.manga.libnm, self.manga.id), set()))
171 with profile.file("tags") as fp:
172 for words in splitlines(fp):
173 libnm, id = words[0:2]
174 tags = set(words[2:])
175 ret[libnm, id] = tags
181 def save(profile, m):
182 with profile.file("tags", "W") as fp:
183 for (libnm, id), tags in m.items():
184 fp.write(consline(libnm, id, *tags) + "\n")
187 def bytag(profile, tag):
189 with profile.file("tags") as fp:
190 for words in splitlines(fp):
191 libnm, id = words[0:2]
194 yield profile.getmanga(libnm, id)
198 class filemanga(manga):
199 def __init__(self, profile, libnm, id, path):
201 super(filemanga, self).__init__(profile, libnm, id)
202 self.tags = tagview(self)
206 with openwdir(self.path) as f:
207 for words in splitlines(f):
208 if words[0] == "set" and len(words) > 2:
209 ret[words[1]] = words[2]
210 elif words[0] == "lset" and len(words) > 1:
211 ret[words[1]] = words[2:]
215 with openwdir(self.path, "W") as f:
216 for key, val in self.props.items():
217 if isinstance(val, str):
218 f.write(consline("set", key, val) + "\n")
220 f.write(consline("lset", key, *val) + "\n")
222 class profile(object):
223 def __init__(self, dir):
227 def getmapping(self):
230 if os.path.exists(pj(self.dir, "map")):
231 with openwdir(pj(self.dir, "map")) as f:
232 for words in splitlines(f):
233 if words[0] == "seq" and len(words) > 1:
238 elif words[0] == "manga" and len(words) > 3:
240 ret[words[1], words[2]] = int(words[3])
245 def savemapping(self, seq, m):
246 with openwdir(pj(self.dir, "map"), "W") as f:
247 f.write(consline("seq", str(seq)) + "\n")
248 for (libnm, id), num in m.items():
249 f.write(consline("manga", libnm, id, str(num)) + "\n")
251 def getmanga(self, libnm, id, creat=False):
252 seq, m = self.getmapping()
254 return filemanga(self, libnm, id, pj(self.dir, "%i.manga" % m[(libnm, id)]))
256 raise KeyError("no such manga: (%s, %s)" % (libnm, id))
259 fp = openwdir(pj(self.dir, "%i.manga" % seq), "x")
266 self.savemapping(seq, m)
267 return filemanga(self, libnm, id, pj(self.dir, "%i.manga" % seq))
270 if self.name is None:
271 raise ValueError("profile at " + self.dir + " has no name")
272 with openwdir(pj(basedir, "last"), "W") as f:
273 f.write(self.name + "\n")
275 def getaliases(self):
277 if os.path.exists(pj(self.dir, "alias")):
278 with openwdir(pj(self.dir, "alias")) as f:
281 if len(ln) < 1: continue
282 if ln[0] == "alias" and len(ln) > 3:
283 ret[ln[1]] = ln[2], ln[3]
286 def savealiases(self, map):
287 with openwdir(pj(self.dir, "alias"), "W") as f:
288 for nm, (libnm, id) in map.items():
289 f.write(consline("alias", nm, libnm, id) + "\n")
291 def file(self, name, mode="r"):
292 return openwdir(pj(self.dir, name), mode)
294 def getalias(self, nm):
295 return self.getaliases()[nm]
297 def setalias(self, nm, libnm, id):
298 aliases = self.getaliases()
299 aliases[nm] = libnm, id
300 self.savealiases(aliases)
302 def bytag(self, tag):
303 return tagview.bytag(self, tag)
306 def byname(cls, name):
307 if not name or name == "last" or name[0] == '.':
308 raise KeyError("invalid profile name: " + name)
309 ret = cls(pj(basedir, name))
315 if not os.path.exists(pj(basedir, "last")):
316 raise KeyError("there is no last used profile")
317 with open(pj(basedir, "last")) as f:
318 return cls.byname(f.readline().strip())