2015-07-17 6 views
2

Что я хотел бы сделать, так это построить дерево из API Dropbox для заданного пути с общими ссылками для каждого пути, используя привязки python.Создание дерева каталогов из Dropbox API

Моя предлагаемая структура выглядит следующим образом:

[ 
    { 
     'path': '/a', 
     'is_dir': True, 
     'contents': [ 
      { 
       'path': '/a/b', 
       'is_dir': True, 
       'contents': [etc] 
      }, 
      { 
       'path': '/a/readme.txt', 
       'is_dir': False, 
       'share_link': 'http://etc' 
      } 
     ] 
    }, 
    etc. 
] 

Я получил то, что в основном работает с использованием metadata(), но это безобразно медленно, как это нужно сделать вызов API в каталог приложения, проходимый.

Вместо этого я хотел бы использовать delta(), который будет получать каждый файл в одном запросе, а затем встраивать его в дерево, но у меня возникают проблемы с выяснением того, как, в частности, как разбирать пути в дерево.

Редактировать: И я понял, что есть призыв к каждой ссылке на общий ресурс, поэтому я собираюсь опустить их и просто получить их по запросу.

Вот код, я должен получить нужные мне данные до сих пор:

paths = [] 

for path, metadata in client.delta(path_prefix='/whatever')['entries']: 
    paths.append({ 
     'path': path, 
     'is_dir': metadata['is_dir'] 
    }) 

Так я думаю у меня возникают проблемы, выяснить, как получить эти пути вложенными. Довольно мне здесь нужна рекурсивная функция, но я не могу это понять.

+0

HTTP-документы для/delta содержат дополнительную информацию о возвращенных данных: https://www.dropbox.com/developers/core/docs#delta И это сообщение в блоге, хотя и на Python, может быть полезным: https : //blogs.dropbox.com/developers/2013/12/efficiently-enumerating-dropbox-with-delta/ – Greg

+0

'/ delta' - это, безусловно, способ перечислить файлы, но вам все равно нужно создать ссылку на общий ресурс для каждого файла, правильно? Это будет медленная часть. – smarx

+0

Я думаю, вы, ребята, пропустили тег python, поэтому я отредактирую, чтобы сделать это более понятным. –

ответ

2

Я немного изменил вашу структуру ... вот представление JSON того, что дает код ниже. Обратите внимание, что я сделал поле содержимого словарем, индексированным по пути, а не массивом. Это просто немного легче и делает для более эффективного поиска, но это должно быть довольно легко превратить в то, что у вас есть выше, если вы хотите:

{ 
    "is_dir": true, 
    "contents": { 
     "/foo.txt": { 
      "is_dir": false, 
      "contents": {} 
     }, 
     "/a": { 
      "is_dir": true, 
      "contents": { 
       "https://stackoverflow.com/a/bar.txt": { 
        "is_dir": false, 
        "contents": {} 
       }, 
       "https://stackoverflow.com/a/b": { 
        "is_dir": true, 
        "contents": { 
         "https://stackoverflow.com/a/b/hello.txt": { 
          "is_dir": false, 
          "contents": {} 
         } 
        } 
       } 
      } 
     } 
    } 
} 

Вот код, который производит этот вывод:

ACCESS_TOKEN = '<REDACTED>' 

from collections import defaultdict 
import json 

from dropbox.client import DropboxClient 

def make_tree(): 
    return { 
     'is_dir': True, 
     'contents': defaultdict(make_tree) 
    } 
tree = defaultdict(make_tree) 

client = DropboxClient(ACCESS_TOKEN) 

has_more = True 
cursor = None 

while has_more: 
    delta = client.delta(cursor) 

    cursor = delta['cursor'] 
    has_more = delta['has_more'] 

    for path, metadata in delta['entries']: 
     if metadata is not None: 

      # find the right place in the tree 
      segments = path.split('/') 
      location = tree['/'] 
      for i in xrange(1, len(segments)-1): 
       current_path = '/'.join(segments[:i+1]) 
       location = location['contents'][current_path] 

      # insert the new entry 
      location['contents'][path] = { 
       'is_dir': metadata['is_dir'], 
       'contents': {} 
      } 

print json.dumps(tree['/'], indent=4) 
+0

Спасибо! Это почти отлично работает, но одно - если я называю 'delta()' префиксом, например 'delta (cursor, '/ a/prefix')', '/' все еще находится в корне дерева. Я могу изменить его на префикс, который я укажу, но тогда в '/ a/prefix' есть еще один избыточный'/a/prefix'. Есть идеи? –

+0

Не нужно быть там сложным ... это звучит как одно утверждение 'if', возможно, решило бы это. :-) – smarx

+0

Теперь, когда я думаю об этом, это не совсем проблема. Проблема в том, что если я укажу префикс '/ a/prefix', он в настоящее время показывает'/a' и '/ a/prefix', хотя я не получаю файлы от них. Действительно, если я укажу префикс, я бы хотел, чтобы этот префикс был корневым и не отображал ничего над ним. –