Skip to content

Commit d54f795

Browse files
committed
[WIP] systemtags-relation : optimize add_systemtags_relation
1 parent f7cdc46 commit d54f795

File tree

3 files changed

+97
-49
lines changed

3 files changed

+97
-49
lines changed

src/nextcloud/api_wrappers/systemtags.py

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ def create_systemtag(self, name, **kwargs):
6363
:param name: tag name
6464
:returns: requester response with tag id as data
6565
"""
66-
data = Tag.default_get(name=name, **kwargs)
66+
data = Tag.default_get(display_name=name, **kwargs)
6767
resp = self.requester.post(
6868
data=json.dumps(data),
6969
headers={
@@ -139,9 +139,9 @@ def get_systemtags_relation(self, file_id=None, **kwargs):
139139
resp = self.requester.propfind(additional_url=file_id, data=data)
140140
return Tag.from_response(resp, json_output=(self.json_output))
141141

142-
def delete_systemtags_relation(self, file_id=None, tag_id=None, **kwargs):
142+
def remove_systemtags_relation(self, file_id=None, tag_id=None, **kwargs):
143143
"""
144-
Delete a tag from a given file/folder
144+
Remove a tag from a given file/folder
145145
146146
:param file_id (int): id found in file object
147147
:param tag_id (int): id found in tag object
@@ -152,6 +152,10 @@ def delete_systemtags_relation(self, file_id=None, tag_id=None, **kwargs):
152152
"""
153153
file_id, tag_id = self._arguments_get([
154154
'file_id', 'tag_id'], dict(file_id=file_id, tag_id=tag_id, **kwargs))
155+
if not file_id:
156+
raise ValueError('No file found')
157+
if not tag_id:
158+
raise ValueError('No tag found (%s)' % kwargs.get('tag_name', None))
155159
resp = self.requester.delete(url=('{}/{}'.format(file_id, tag_id)))
156160
return resp
157161

@@ -168,13 +172,17 @@ def add_systemtags_relation(self, file_id=None, tag_id=None, **kwargs):
168172
"""
169173
file_id, tag_id = self._arguments_get([
170174
'file_id', 'tag_id'], locals())
171-
if not tag_id:
172-
if 'tag_name' in kwargs:
173-
resp = self.client.create_systemtag(kwargs['tag_name'])
174-
if not resp.is_ok:
175-
return resp
176-
tag_id = resp.data
177175
if not file_id:
178176
raise ValueError('No file found')
179-
resp = self.requester.put(url=('{}/{}'.format(file_id, tag_id)))
177+
if not tag_id:
178+
data = Tag.default_get(display_name=kwargs.get('tag_name'), **kwargs)
179+
resp = self.requester.post(
180+
url=file_id,
181+
data=json.dumps(data),
182+
headers={'Content-Type': 'application/json'})
183+
# resp = self.client.create_systemtag(kwargs['tag_name'])
184+
# if not resp.is_ok:
185+
return resp
186+
# tag_id = resp.data
187+
resp = self.requester.put(url='{}/{}'.format(file_id, tag_id))
180188
return resp

src/nextcloud/api_wrappers/webdav.py

Lines changed: 78 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
import os
88
try:
99
import pathlib
10-
except:
10+
except ImportError:
1111
import pathlib2 as pathlib
1212

1313
import xml.etree.ElementTree as ET
@@ -32,7 +32,7 @@ class File(PropertySet):
3232
Additionnally, provide an objective CRUD API
3333
(that probably consume more energy than fetching specific attributes)
3434
35-
Example :
35+
Example :
3636
>>> root = nxc.get_folder() # get root
3737
>>> def _list_rec(d, indent=""):
3838
>>> # list files recursively
@@ -43,12 +43,19 @@ class File(PropertySet):
4343
>>>
4444
>>> _list_rec(root)
4545
"""
46+
47+
@staticmethod
48+
def _extract_resource_type(file_property):
49+
file_type = list(file_property)
50+
if file_type:
51+
return re.sub('{.*}', '', file_type[0].tag)
52+
return None
53+
4654
_attrs = [
4755
Prop('d:getlastmodified'),
4856
Prop('d:getetag'),
4957
Prop('d:getcontenttype'),
50-
Prop('d:resourcetype', parse_xml_value=(
51-
lambda p: File._extract_resource_type(p))),
58+
Prop('d:resourcetype', parse_xml_value=File._extract_resource_type),
5259
Prop('d:getcontentlength'),
5360
Prop('oc:id'),
5461
Prop('oc:fileid'),
@@ -65,13 +72,6 @@ class File(PropertySet):
6572
Prop('nc:has-preview')
6673
]
6774

68-
@staticmethod
69-
def _extract_resource_type(file_property):
70-
file_type = list(file_property)
71-
if file_type:
72-
return re.sub('{.*}', '', file_type[0].tag)
73-
return None
74-
7575
def isfile(self):
7676
""" say if the file is a file /!\\ ressourcetype property shall be loaded """
7777
return not self.resource_type
@@ -105,32 +105,38 @@ def __eq__(self, b):
105105
def get_folder(self, path=None):
106106
"""
107107
Get folder (see WebDav wrapper)
108-
:param subpath: if empty list current dir
108+
:param path: if empty list current dir
109109
:returns: a folder (File object)
110110
111111
Note : To check if sub folder exists, use get_file method
112112
"""
113113
return self._wrapper.get_folder(self._get_remote_path(path))
114114

115-
def get_folder(self, path=None):
115+
def get_file(self, path=None):
116116
"""
117-
Get folder (see WebDav wrapper)
118-
:param subpath: if empty list current dir
117+
Get file (see WebDav wrapper)
118+
:param path: if empty list current dir
119119
:returns: a file or folder (File object)
120120
"""
121121
return self._wrapper.get_file(self._get_remote_path(path))
122122

123-
def list(self, subpath=''):
123+
def list(self, subpath='', filter_rules=None):
124124
"""
125125
List folder (see WebDav wrapper)
126126
:param subpath: if empty list current dir
127127
:returns: list of Files
128128
"""
129-
resp = self._wrapper.list_folders(
130-
self._get_remote_path(subpath),
131-
depth=1,
132-
all_properties=True
133-
)
129+
if filter_rules:
130+
resp = self._wrapper.list_files_with_filter(
131+
path=self._get_remote_path(subpath),
132+
filter_rules=filter_rules
133+
)
134+
else:
135+
resp = self._wrapper.list_folders(
136+
self._get_remote_path(subpath),
137+
depth=1,
138+
all_properties=True
139+
)
134140
if resp.is_ok and resp.data:
135141
_dirs = resp.data
136142
# remove current dir
@@ -146,8 +152,8 @@ def upload_file(self, local_filepath, name, timestamp=None):
146152
:returns: True if success
147153
"""
148154
resp = self._wrapper.upload_file(local_filepath,
149-
self._get_remote_path(name),
150-
timestamp=timestamp)
155+
self._get_remote_path(name),
156+
timestamp=timestamp)
151157
return resp.is_ok
152158

153159
def download(self, name=None, target_dir=None):
@@ -158,7 +164,7 @@ def download(self, name=None, target_dir=None):
158164
"""
159165
path = self._get_remote_path(name)
160166
target_path, _file_info = self._wrapper.download_file(path,
161-
target_dir=target_dir)
167+
target_dir=target_dir)
162168
assert os.path.isfile(target_path), "Download failed"
163169
return target_path
164170

@@ -179,8 +185,7 @@ class WebDAV(WebDAVApiWrapper):
179185
def _get_path(self, path):
180186
if path:
181187
return '/'.join([self.client.user, path]).replace('//', '/')
182-
else:
183-
return self.client.user
188+
return self.client.user
184189

185190
def list_folders(self, path=None, depth=1, all_properties=False,
186191
fields=None):
@@ -227,7 +232,7 @@ def download_file(self, path, target_dir=None):
227232
a tuple (target_path, File object)
228233
"""
229234
if not target_dir:
230-
target_dir='./'
235+
target_dir = './'
231236
filename = path.split('/')[(-1)] if '/' in path else path
232237
file_data = self.get_file(path)
233238
if not file_data:
@@ -373,37 +378,71 @@ def copy_path(self, path, destination_path, overwrite=False):
373378
destination_path),
374379
overwrite=overwrite)
375380

376-
def set_favorites(self, path):
381+
def set_file_property(self, path, update_rules):
377382
"""
378-
Set files of a user favorite
383+
Set file property
379384
380385
Args:
381386
path (str): file or folder path to make favorite
387+
update_rules : a dict { namespace: {key : value } }
382388
383389
Returns:
384-
requester response
390+
requester response with <list>File in data
391+
392+
Note :
393+
check keys in nextcloud.common.properties.NAMESPACES_MAP for namespace codes
394+
check object property xml_name for property name
385395
"""
386-
data = File.build_xml_propupdate({'oc': {'favorite': 1}})
396+
data = File.build_xml_propupdate(update_rules)
387397
return self.requester.proppatch(additional_url=self._get_path(path), data=data)
388398

389-
def list_favorites(self, path=''):
399+
def list_files_with_filter(self, path='', filter_rules=''):
390400
"""
391-
List favorites (files) of the user
401+
List files according to a filter
392402
393403
Args:
394-
path (str): file or folder path to make favorite
404+
path (str): file or folder path to search
405+
filter_rules : a dict { namespace: {key : value } }
395406
396407
Returns:
397408
requester response with <list>File in data
409+
410+
Note :
411+
check keys in nextcloud.common.properties.NAMESPACES_MAP for namespace codes
412+
check object property xml_name for property name
398413
"""
399414
data = File.build_xml_propfind(
400-
instr='oc:filter-files', filter_rules={'oc': {'favorite': 1}})
415+
instr='oc:filter-files', filter_rules=filter_rules)
401416
resp = self.requester.report(
402417
additional_url=self._get_path(path), data=data)
403418
return File.from_response(resp, json_output=self.json_output,
404419
wrapper=self)
405420

406-
def get_file_property(self, path, field, tag='oc'):
421+
def set_favorites(self, path):
422+
"""
423+
Set files of a user favorite
424+
425+
Args:
426+
path (str): file or folder path to make favorite
427+
428+
Returns:
429+
requester response
430+
"""
431+
return self.set_file_property(path, {'oc': {'favorite': 1}})
432+
433+
def list_favorites(self, path=''):
434+
"""
435+
List favorites (files) of the user
436+
437+
Args:
438+
path (str): file or folder path to search favorite
439+
440+
Returns:
441+
requester response with <list>File in data
442+
"""
443+
return self.list_files_with_filter(path, {'oc': {'favorite': 1}})
444+
445+
def get_file_property(self, path, field, ns='oc'):
407446
"""
408447
Fetch asked properties from a file path.
409448
@@ -415,9 +454,9 @@ def get_file_property(self, path, field, tag='oc'):
415454
requester response with asked value in data
416455
"""
417456
if ':' in field:
418-
tag, field = field.split(':')
419-
get_file_prop_xpath = '{DAV:}propstat/d:prop/%s:%s' % (tag, field)
420-
data = File.build_xml_propfind(fields={tag: [field]})
457+
ns, field = field.split(':')
458+
get_file_prop_xpath = '{DAV:}propstat/d:prop/%s:%s' % (ns, field)
459+
data = File.build_xml_propfind(fields={ns: [field]})
421460
resp = self.requester.propfind(additional_url=(self._get_path(path)), headers={'Depth': str(0)},
422461
data=data)
423462
response_data = resp.data

src/nextcloud/codes.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ class WebDAVCode(enum.IntEnum):
5454
MULTISTATUS = 207
5555
NOT_AUTHENTICATED = 401
5656
ALREADY_EXISTS = 405
57+
CONFLICT = 409
5758
PRECONDITION_FAILED = 412
5859

5960

0 commit comments

Comments
 (0)