diff --git a/CHANGES.rst b/CHANGES.rst index 2a4ca7b..63f2036 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,8 @@ +0.1.0 +===== + +- add verb sync-up and sync-down + 0.0.2 ===== diff --git a/piwigotools/__init__.py b/piwigotools/__init__.py index c74e6e7..04c26b8 100644 --- a/piwigotools/__init__.py +++ b/piwigotools/__init__.py @@ -5,7 +5,7 @@ Module piwigotools """ -__version_info__ = (0, 0, 2) +__version_info__ = (0, 1, 0) __version__ = '.'.join([str(val) for val in __version_info__]) import inspect @@ -14,6 +14,9 @@ import requests import piwigo +FORCE_PLAN = False +FORCE_IMAGES = False + class LoginException(Exception): def __str__(self): @@ -41,6 +44,8 @@ class Piwigo(piwigo.Piwigo): def __init__(self, url): piwigo.Piwigo.__init__(self, url) self._login = False + self._plan = {} + self._images = {} def login(self, username, password): """ @@ -60,8 +65,11 @@ class Piwigo(piwigo.Piwigo): @property def plan(self): - return { i["name"] : i["id"] for i in self.pwg.categories.getList(recursive=True, fullname=True)['categories'] } - + if FORCE_PLAN or not len(self._plan): + plan = { i["name"] : i["id"] for i in self.pwg.categories.getList(recursive=True, fullname=True)['categories'] } + plan[""] = 0 + self._plan = plan + return self._plan def _checkarg(fn): def checking(self, *args, **kw): @@ -113,18 +121,24 @@ class Piwigo(piwigo.Piwigo): """ return list of file name image for path """ - kw["cat_id"]= self.idcategory(path) - kw["per_page"] = 200 - kw["page"] = 0 - imgs = {} - loop = True - while loop: - req = self.pwg.categories.getImages(**kw) - for img in req["images"]: - imgs[img["file"]] = img - if req["paging"]["count"] < req["paging"]["per_page"]: - loop = False - return imgs + if FORCE_IMAGES or path not in self._images: + try: + kw["cat_id"]= self.idcategory(path) + except PiwigoExistException: + return {} + kw["per_page"] = 200 + kw["page"] = 0 + imgs = {} + loop = True + while loop: + req = self.pwg.categories.getImages(**kw) + for img in req["images"]: + imgs[img["file"]] = img + if req["paging"]["count"] < req["paging"]["per_page"]: + loop = False + kw["page"] = kw["page"] + 1 + self._images[path] = imgs + return self._images[path] @_checkarg def sublevels(self, path, **kw): @@ -145,11 +159,13 @@ class Piwigo(piwigo.Piwigo): @_checkarg def idimage(self, path): - if not self.isimage(path): - raise PiwigoExistException("image %s not exist" % path) img = path.split(' / ')[-1] path = ' / '.join(path.split(' / ')[:-1]) - return self.images(path)[img]["id"] + try: + return self.images(path)[img]["id"] + except: + raise PiwigoExistException("image %s not exist" % path) + @_checkarg @_checklogin @@ -162,7 +178,9 @@ class Piwigo(piwigo.Piwigo): if parent and not self.iscategory(parent): raise PiwigoExistException("category %s not exist" % parent) if parent : kw['parent'] = self.plan[parent] - self.pwg.categories.add(**kw) + id = self.pwg.categories.add(**kw)['id'] + if not FORCE_PLAN: + self._plan[path] = id return self.idcategory(path) @_checkarg @@ -186,6 +204,8 @@ class Piwigo(piwigo.Piwigo): remove (delete) category """ self.pwg.categories.delete(category_id=self.idcategory(path), pwg_token=self.token, **kw) + if not FORCE_PLAN and path in self._plan: + del self._plan[path] return True @_checkarg @@ -197,9 +217,12 @@ class Piwigo(piwigo.Piwigo): kw["image"] = image if len(path): if not self.iscategory(path): - raise PiwigoExistException("category %s not exist" % parent) + raise PiwigoExistException("category %s not exist" % path) kw['category'] = self.idcategory(path) - return self.pwg.images.addSimple(**kw)['image_id'] + res = self.pwg.images.addSimple(**kw)['image_id'] + if ' / '.join(path.split(' / ')[:-1]) in self._images: + del self._images[' / '.join(path.split(' / ')[:-1])] + return res @_checkarg @_checklogin @@ -227,4 +250,6 @@ class Piwigo(piwigo.Piwigo): if not self.isimage(path): raise PiwigoException("image %s not exist" % path) self.pwg.images.delete(image_id= self.idimage(path), pwg_token=self.token) + if ' / '.join(path.split(' / ')[:-1]) in self._images: + del self._images[' / '.join(path.split(' / ')[:-1])] return True diff --git a/piwigotools/interface.py b/piwigotools/interface.py index dd377f2..86afc4e 100644 --- a/piwigotools/interface.py +++ b/piwigotools/interface.py @@ -70,11 +70,12 @@ class Run: ' ', progressbar.Timer()], maxval=self._qin.qsize()).start() - for thread in self._threads: - thread.start() - while not self._qout.full(): - time.sleep(0.1) # sleep 0.1s - pbar.update(self._qout.qsize()) + if self._qin.qsize(): + for thread in self._threads: + thread.start() + while not self._qout.full(): + time.sleep(0.1) # sleep 0.1s + pbar.update(self._qout.qsize()) pbar.finish() return self._qerr diff --git a/piwigotools/main.py b/piwigotools/main.py index 44d4eba..338053d 100644 --- a/piwigotools/main.py +++ b/piwigotools/main.py @@ -3,6 +3,7 @@ import sys import os, os.path import glob +import fnmatch import pprint try: @@ -35,7 +36,7 @@ VERBS = { "description" : "upload file in piwigo gallery", "arg" : { - "category" : {"type":"string", "default":"/", "help":"destination category of piwigo gallery"}, + "category" : {"type":"string", "default":"", "help":"destination category of piwigo gallery"}, "source" : {"type":"string", "default":"*.jpg", "help":"path of upload picture"}, "url" : {"type":"string", "default":"", "help":"url of piwigo gallery"}, "user" : {"type":"string", "default":"", "help":"user of piwigo gallery"}, @@ -49,7 +50,7 @@ VERBS = { "description" : "download image from piwigo gallery", "arg" : { - "category" : {"type":"string", "default":"/", "help":"source category of piwigo gallery"}, + "category" : {"type":"string", "default":"", "help":"source category of piwigo gallery"}, "dest" : {"type":"string", "default":".", "help":"path of destination"}, "url" : {"type":"string", "default":"", "help":"url of piwigo gallery"}, "user" : {"type":"string", "default":"", "help":"user of piwigo gallery"}, @@ -57,18 +58,34 @@ VERBS = { "thread" : {"type":"int", "default":"1", "help":"number of thread"}, }, }, - "sync": + "sync-up": { - "usage" : "usage for verb sync", - "description" : "synchronization between path and piwigo gallery", + "usage" : "usage for verb sync-up", + "description" : "synchronization local path to piwigo gallery", "arg" : { - "category" : {"type":"string", "default":"/", "help":"category of piwigo gallery"}, + "category" : {"type":"string", "default":"", "help":"category of piwigo gallery"}, "source" : {"type":"string", "default":".", "help":"path of picture"}, "url" : {"type":"string", "default":"", "help":"url of piwigo gallery"}, "user" : {"type":"string", "default":"", "help":"user of piwigo gallery"}, "password" : {"type":"string", "default":"", "help":"password of piwigo gallery"}, "thread" : {"type":"int", "default":"1", "help":"number of thread"}, + "extension" : {"type":"string", "default":"*.JPG,*.jpg,*.PNG,*.png,*.JPEG,*.jpeg,*.GIF,*.gif", "help":"extension for upload"}, + }, + }, + "sync-down": + { + "usage" : "usage for verb sync-down", + "description" : "synchronization piwigo gallery to local path", + "arg" : + { + "category" : {"type":"string", "default":"", "help":"category of piwigo gallery"}, + "source" : {"type":"string", "default":".", "help":"path of picture"}, + "url" : {"type":"string", "default":"", "help":"url of piwigo gallery"}, + "user" : {"type":"string", "default":"", "help":"user of piwigo gallery"}, + "password" : {"type":"string", "default":"", "help":"password of piwigo gallery"}, + "thread" : {"type":"int", "default":"1", "help":"number of thread"}, + "extension" : {"type":"string", "default":"*.JPG,*.jpg,*.PNG,*.png,*.JPEG,*.jpeg,*.GIF,*.gif", "help":"extension for upload"}, }, }, "ws": @@ -166,7 +183,7 @@ def main(): kw = purge_kw(options.__dict__,('user','password','url','dest','category','thread')) for img in piwigo.images(options.category, **kw): run.add(piwigo.download, - ["%s / %s" % (options.category, str(img)), "%s/%s" % (options.dest, str(img))], + ["%s / %s" % (options.category, str(img)), "%s%s%s" % (options.dest, os.path.sep, str(img))], kw) except Exception as e: ana.stop() @@ -199,6 +216,78 @@ def main(): piwigo.logout() if run.error: parser.error(run.strerror) + if verb == "sync-up": + ana = Analyse('Analyze') + ana.start() + try: + piwigo = Piwigo(url=options.url) + piwigo.login(options.user, options.password) + # check + options.source = os.path.abspath(options.source) + if not os.path.isdir(options.source): + raise Exception("%s is not directory" % options.source) + piwigo.iscategory(options.category) + if len(options.category) and options.category[-1] != '/' and options.category[:-3] != ' / ': + options.category = options.category+ ' / ' + # treatment + run = Run(verb, options.thread) + kw = purge_kw(options.__dict__,('user','password','url','source','category','thread')) + # local -> piwigo + for root, dirnames, filenames in os.walk(options.source): + filtering = fnmatch.filter(filenames, options.extension.split(',')[0]) + for ext in options.extension.split(',')[1:]: + filtering = filtering + fnmatch.filter(filenames, ext) + for filename in filtering: + pathrel = os.path.abspath(os.path.join(root, filename))[len(options.source)+1:] + pathabs = os.path.abspath(os.path.join(root, filename)) + category = options.category + ' / '.join(pathrel.split(os.sep)[:-1]) + if not piwigo.isimage(category + ' / ' + filename): + run.add(piwigo.makedirs,[category,], kw) + run.add(piwigo.upload,[pathabs, category], kw) + ana.stop() + except Exception as e: + ana.stop() + raise e + run.start() + piwigo.logout() + if run.error: + parser.error(run.strerror) + if verb == "sync-down": + ana = Analyse('Analyze') + ana.start() + try: + piwigo = Piwigo(url=options.url) + piwigo.login(options.user, options.password) + # check + options.source = os.path.abspath(options.source) + if not os.path.isdir(options.source): + raise Exception("%s is not directory" % options.source) + piwigo.iscategory(options.category) + if len(options.category) and options.category[-1] != '/' and options.category[:-3] != ' / ': + options.category = options.category+ ' / ' + # treatment + run = Run(verb, options.thread) + kw = purge_kw(options.__dict__,('user','password','url','source','category','thread')) + # piwigo -> local + for category, item in piwigo.plan.iteritems(): + if options.category == category[0:len(options.category)]: + path = os.path.join(options.source, *category[len(options.category):].split(' / ')) + if not os.path.exists(path): + os.makedirs(path) + for img in piwigo.images(category): + pathimg = os.path.join(path, img) + if not os.path.exists(pathimg): + run.add(piwigo.download, + ["%s / %s" % (category, str(img)), pathimg], + kw) + ana.stop() + except Exception as e: + ana.stop() + raise e + run.start() + piwigo.logout() + if run.error: + parser.error(run.strerror) except Exception as e: parser.error(e) sys.exit(1)