Skip to content

Commit db31015

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

File tree

3 files changed

+85
-43
lines changed

3 files changed

+85
-43
lines changed

src/nextcloud/api_wrappers/systemtags.py

+18-10
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

+66-33
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,17 +105,17 @@ 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))
@@ -146,8 +146,8 @@ def upload_file(self, local_filepath, name, timestamp=None):
146146
:returns: True if success
147147
"""
148148
resp = self._wrapper.upload_file(local_filepath,
149-
self._get_remote_path(name),
150-
timestamp=timestamp)
149+
self._get_remote_path(name),
150+
timestamp=timestamp)
151151
return resp.is_ok
152152

153153
def download(self, name=None, target_dir=None):
@@ -158,7 +158,7 @@ def download(self, name=None, target_dir=None):
158158
"""
159159
path = self._get_remote_path(name)
160160
target_path, _file_info = self._wrapper.download_file(path,
161-
target_dir=target_dir)
161+
target_dir=target_dir)
162162
assert os.path.isfile(target_path), "Download failed"
163163
return target_path
164164

@@ -179,8 +179,7 @@ class WebDAV(WebDAVApiWrapper):
179179
def _get_path(self, path):
180180
if path:
181181
return '/'.join([self.client.user, path]).replace('//', '/')
182-
else:
183-
return self.client.user
182+
return self.client.user
184183

185184
def list_folders(self, path=None, depth=1, all_properties=False,
186185
fields=None):
@@ -227,7 +226,7 @@ def download_file(self, path, target_dir=None):
227226
a tuple (target_path, File object)
228227
"""
229228
if not target_dir:
230-
target_dir='./'
229+
target_dir = './'
231230
filename = path.split('/')[(-1)] if '/' in path else path
232231
file_data = self.get_file(path)
233232
if not file_data:
@@ -373,37 +372,71 @@ def copy_path(self, path, destination_path, overwrite=False):
373372
destination_path),
374373
overwrite=overwrite)
375374

376-
def set_favorites(self, path):
375+
def set_file_property(self, path, update_rules):
377376
"""
378-
Set files of a user favorite
377+
Set file property
379378
380379
Args:
381380
path (str): file or folder path to make favorite
381+
update_rules : a dict { namespace: {key : value } }
382382
383383
Returns:
384-
requester response
384+
requester response with <list>File in data
385+
386+
Note :
387+
check keys in nextcloud.common.properties.NAMESPACES_MAP for namespace codes
388+
check object property xml_name for property name
385389
"""
386-
data = File.build_xml_propupdate({'oc': {'favorite': 1}})
390+
data = File.build_xml_propupdate(update_rules)
387391
return self.requester.proppatch(additional_url=self._get_path(path), data=data)
388392

389-
def list_favorites(self, path=''):
393+
def list_files_with_filter(self, path='', filter_rules=''):
390394
"""
391-
List favorites (files) of the user
395+
List files according to a filter
392396
393397
Args:
394-
path (str): file or folder path to make favorite
398+
path (str): file or folder path to search
399+
filter_rules : a dict { namespace: {key : value } }
395400
396401
Returns:
397402
requester response with <list>File in data
403+
404+
Note :
405+
check keys in nextcloud.common.properties.NAMESPACES_MAP for namespace codes
406+
check object property xml_name for property name
398407
"""
399408
data = File.build_xml_propfind(
400-
instr='oc:filter-files', filter_rules={'oc': {'favorite': 1}})
409+
instr='oc:filter-files', filter_rules=filter_rules)
401410
resp = self.requester.report(
402411
additional_url=self._get_path(path), data=data)
403412
return File.from_response(resp, json_output=self.json_output,
404413
wrapper=self)
405414

406-
def get_file_property(self, path, field, tag='oc'):
415+
def set_favorites(self, path):
416+
"""
417+
Set files of a user favorite
418+
419+
Args:
420+
path (str): file or folder path to make favorite
421+
422+
Returns:
423+
requester response
424+
"""
425+
return self.set_file_property(path, {'oc': {'favorite': 1}})
426+
427+
def list_favorites(self, path=''):
428+
"""
429+
List favorites (files) of the user
430+
431+
Args:
432+
path (str): file or folder path to search favorite
433+
434+
Returns:
435+
requester response with <list>File in data
436+
"""
437+
return self.list_files_with_filter(path, {'oc': {'favorite': 1}})
438+
439+
def get_file_property(self, path, field, ns='oc'):
407440
"""
408441
Fetch asked properties from a file path.
409442
@@ -415,9 +448,9 @@ def get_file_property(self, path, field, tag='oc'):
415448
requester response with asked value in data
416449
"""
417450
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]})
451+
ns, field = field.split(':')
452+
get_file_prop_xpath = '{DAV:}propstat/d:prop/%s:%s' % (ns, field)
453+
data = File.build_xml_propfind(fields={ns: [field]})
421454
resp = self.requester.propfind(additional_url=(self._get_path(path)), headers={'Depth': str(0)},
422455
data=data)
423456
response_data = resp.data

src/nextcloud/codes.py

+1
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)