From 6c844dd1fd1ab9cfba7cea19fc2c5e0fcb17f06d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ha=CC=8Avard=20Gulldahl?= Date: Sat, 25 Jun 2016 13:38:15 +0200 Subject: [PATCH] Add .state property to file tuples returned from JFSFileDirList(), and revamp logic to be more resilient to unexpected file objects. See #88 --- src/jottalib/JFS.py | 41 ++++++++++++++++++++++++++++++++--------- tests/test_JFS.py | 10 +++++++++- 2 files changed, 41 insertions(+), 10 deletions(-) diff --git a/src/jottalib/JFS.py b/src/jottalib/JFS.py index b90e6c9..b1cfd83 100644 --- a/src/jottalib/JFS.py +++ b/src/jottalib/JFS.py @@ -148,8 +148,19 @@ class JFSServerError(JFSError): # HTTP 500 class JFSFileDirList(object): - 'Wrapping , a simple tree of folders and their files' - """get a for any jottafolder by appending ?mode=list to your query + '''Wrapping , a simple tree of folders and their files + + Get a for any jottafolder by appending ?mode=list to your query + + Then you will get this object, with a .tree property, which is a list of all + files and folders. + + Files will be a namedtuple() with five properties: + .name - file name + .state - file state (str): one of JFS.ProtoFile.STATE_*, e.g 'COMPLETED' or 'INCOMPLETE' + .size - file size (int or None): full size , partially uploaded size or no size, depentant on file state + .md5 - jottacloud file hash (str or None): corrupt files have no md5 hash + .uuid - jottacloud assigned uuid @@ -157,7 +168,7 @@ class JFSFileDirList(object): /havardgulldahl/Jotta /havardgulldahl/Jotta - ...""" + ...''' def __init__(self, filedirlistobject, jfs, parentpath): # filedirlistobject from lxml.objectify @@ -165,7 +176,7 @@ def __init__(self, filedirlistobject, jfs, parentpath): # filedirlistobject from self.parentPath = parentpath self.jfs = jfs - treefile = namedtuple('TreeFile', 'name size md5 uuid') + treefile = namedtuple('TreeFile', 'name size md5 uuid state') self.tree = {} for folder in self.filedirlist.folders.iterchildren(): @@ -178,15 +189,27 @@ def __init__(self, filedirlistobject, jfs, parentpath): # filedirlistobject from t.append(treefile(unicode(file_.attrib['name']), int(file_.currentRevision.size), unicode(file_.currentRevision.md5), - unicode(file_.attrib['uuid']) + unicode(file_.attrib['uuid']), + unicode(file_.currentRevision.state) ) ) else: - # an incomplete file + # This is an incomplete or, possibly, corrupt file + # + # Incomplete files have no `size` in a filedirlist, you + # need to fetch the JFSFile explicitly to see that property + try: + # incomplete files carry a md5 hash, + _md5 = unicode(file_.latestRevision.md5) + except AttributeError: + # while other may not + # see discussion in #88 + _md5 = None t.append(treefile(unicode(file_.attrib['name']), - -1, # incomplete files have no size - unicode(file_.latestRevision.md5), - unicode(file_.attrib['uuid']) + None, # return size as None + _md5, + unicode(file_.attrib['uuid']), + unicode(file_.latestRevision.state) ) ) self.tree[posixpath.join(path, foldername)] = t diff --git a/tests/test_JFS.py b/tests/test_JFS.py index 51b981d..cc451e8 100644 --- a/tests/test_JFS.py +++ b/tests/test_JFS.py @@ -22,7 +22,7 @@ __author__ = 'havard@gulldahl.no' # import standardlib -import os, logging, datetime +import os, logging, datetime, types import tempfile, posixpath, urllib import six from six.moves import cStringIO as StringIO @@ -462,6 +462,14 @@ def test_api(self): fdl = jfs.getObject('/Jotta/Sync/?mode=list') assert isinstance(fdl, JFS.JFSFileDirList) assert len(fdl.tree) > 0 + i = 0 + for folders in fdl.tree.values(): # iterate over all files in tree list + for f in folders: + assert isinstance(f.name, unicode) + assert isinstance(f.md5, (basestring, types.NoneType)) + assert isinstance(f.state, basestring) + assert isinstance(f.uuid, basestring) + assert isinstance(f.size, (int, types.NoneType)) class TestJFSError: 'Test different JFSErrors'