Skip to content

Commit e95e19d

Browse files
committed
Fix scrutinizer issues + fix login error
1 parent f1f4521 commit e95e19d

17 files changed

+215
-150
lines changed

requirements.in

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
requests>=2.0.1
2-
pytest
2+
pytest>=4.6

src/nextcloud/__init__.py

+21-17
Original file line numberDiff line numberDiff line change
@@ -31,21 +31,17 @@ class NextCloud(object):
3131
... # some actions #
3232
"""
3333

34-
def __init__(self, endpoint, user=None, password=None, json_output=True, auth=None, session_kwargs=None):
35-
self.query_components = []
36-
self._session = Session(
34+
def __init__(self, endpoint=None,
35+
user=None, password=None, json_output=True, auth=None,
36+
session_kwargs=None,
37+
session=None):
38+
self.session = session or Session(
3739
url=endpoint, user=user, password=password, auth=auth,
3840
session_kwargs=session_kwargs
3941
)
4042
self.json_output = json_output
4143
for functionality_class in API_WRAPPER_CLASSES:
42-
json_able = getattr(functionality_class, 'JSON_ABLE', False)
43-
require_client = getattr(
44-
functionality_class, 'REQUIRE_CLIENT', False)
45-
functionality_instance = functionality_class(
46-
self._session,
47-
json_output=(json_able and json_output),
48-
client=(require_client and self))
44+
functionality_instance = functionality_class(self)
4945
for potential_method in dir(functionality_instance):
5046
if not potential_method.startswith('_'):
5147
if not callable(getattr(functionality_instance, potential_method)):
@@ -56,11 +52,11 @@ def __init__(self, endpoint, user=None, password=None, json_output=True, auth=No
5652

5753
@property
5854
def user(self):
59-
return self._session.user
55+
return self.session.user
6056

6157
@property
6258
def url(self):
63-
return self._session.url
59+
return self.session.url
6460

6561
def __enter__(self):
6662
self.login()
@@ -71,14 +67,22 @@ def __exit__(self, *args):
7167

7268
def login(self, user=None, password=None, auth=None):
7369
self.logout()
74-
self._session.login(user=user, password=password, auth=auth)
70+
return self.session.login(user=user, password=password, auth=auth,
71+
client=self)
72+
73+
def with_attr(self, **kwargs):
74+
if 'auth' in kwargs:
75+
return self.with_auth(**kwargs)
76+
if 'session_kwargs' in kwargs:
77+
return self.with_auth(self.session.auth, **kwargs)
78+
return self.__class__(session=self.session, **kwargs)
7579

7680
def with_auth(self, auth=None, **kwargs):
77-
init_kwargs = {'session_kwargs': self._session._session_kwargs,
81+
init_kwargs = {'session_kwargs': self.session._session_kwargs,
7882
'json_output': self.json_output}
7983
init_kwargs.update(kwargs)
80-
return (self.__class__)(self._session.url, auth=auth, **init_kwargs)
84+
return self.__class__(self.session.url, auth=auth, **init_kwargs)
8185

8286
def logout(self):
83-
if self._session.session:
84-
self._session.logout()
87+
if self.session.session:
88+
self.session.logout()

src/nextcloud/api_wrappers/activity.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,5 +39,5 @@ def get_activities(self, since=None, limit=None, object_type=None, object_id=Non
3939
sort=sort
4040
)
4141
if params['object_type'] and params['object_id']:
42-
return self.requester.get(url="filter", params=params)
42+
return self.requester.get(url="filter", params=params)
4343
return self.requester.get(params=params)

src/nextcloud/api_wrappers/apps.py

+3-1
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,9 @@ def get_apps(self, filter=None):
1616
:param filter: str, optional "enabled" or "disabled"
1717
:return:
1818
"""
19-
params = {"filter": filter}
19+
params = {
20+
"filter": filter
21+
}
2022
return self.requester.get(params=params)
2123

2224
def get_app(self, app_id):

src/nextcloud/api_wrappers/group_folders.py

+6-6
Original file line numberDiff line numberDiff line change
@@ -75,8 +75,8 @@ def set_permissions_to_group_folder(self, fid, gid, permissions):
7575
:param permissions (int): The new permissions for the group as attribute of Permission class
7676
:returns: resquester response
7777
"""
78-
url = '/'.join([str(fid), 'groups', gid])
79-
return self.requester.post(url=url, data={'permissions': permissions})
78+
url = "/".join([str(fid), "groups", gid])
79+
return self.requester.post(url=url, data={"permissions": permissions})
8080

8181
def set_quota_of_group_folder(self, fid, quota):
8282
"""
@@ -86,8 +86,8 @@ def set_quota_of_group_folder(self, fid, quota):
8686
:param quota (int/str): The new quota for the folder in bytes, user -3 for unlimited
8787
:returns: resquester response
8888
"""
89-
url = '/'.join([str(fid), 'quota'])
90-
return self.requester.post(url, {'quota': quota})
89+
url = "/".join([str(fid), "quota"])
90+
return self.requester.post(url, {"quota": quota})
9191

9292
def rename_group_folder(self, fid, mountpoint):
9393
"""
@@ -97,5 +97,5 @@ def rename_group_folder(self, fid, mountpoint):
9797
:param mountpoint (str): name for the new folder
9898
:returns: resquester response
9999
"""
100-
url = '/'.join([str(fid), 'mountpoint'])
101-
return self.requester.post(url=url, data={'mountpoint': mountpoint})
100+
url = "/".join([str(fid), "mountpoint"])
101+
return self.requester.post(url=url, data={"mountpoint": mountpoint})

src/nextcloud/api_wrappers/systemtags.py

+29-17
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010

1111

1212
class Tag(PropertySet):
13+
""" Define a Tag properties"""
1314
_attrs = [
1415
Prop('oc:id'),
1516
Prop('oc:display-name', json='name', default='default_tag_name'),
@@ -22,19 +23,27 @@ class Tag(PropertySet):
2223
class SystemTags(WebDAVApiWrapper):
2324
""" SystemTags API wrapper """
2425
API_URL = '/remote.php/dav/systemtags'
25-
JSON_ABLE = True
2626

2727
def get_sytemtag(self, name, fields=None, json_output=None):
28+
"""
29+
Get attributes of a nammed tag
30+
31+
:param name (str): tag name
32+
:param fields (<list>str): field names
33+
:returns: requester response with <list>Tag in data
34+
"""
2835
if not fields:
2936
fields = Tag._fields
30-
resp = self.requester.propfind(data=Tag.build_xml_propfind(
31-
fields={'oc': ['display-name'] + fields}))
37+
resp = self.requester.propfind(
38+
data=Tag.build_xml_propfind(fields={
39+
'oc': ['display-name'] + fields
40+
}))
3241
if json_output is None:
3342
json_output = self.json_output
3443
return Tag.from_response(resp,
3544
json_output=json_output,
3645
init_attrs=True,
37-
filtered=(lambda t: t.display_name == name))
46+
filtered=lambda t: t.display_name == name)
3847

3948
def get_systemtags(self):
4049
"""
@@ -43,8 +52,9 @@ def get_systemtags(self):
4352
:returns: requester response with <list>Tag in data
4453
"""
4554
resp = self.requester.propfind(
46-
data=Tag.build_xml_propfind(use_default=True))
47-
return Tag.from_response(resp, json_output=(self.json_output))
55+
data=Tag.build_xml_propfind(use_default=True)
56+
)
57+
return Tag.from_response(resp, json_output=self.json_output)
4858

4959
def create_systemtag(self, name, **kwargs):
5060
"""
@@ -53,9 +63,12 @@ def create_systemtag(self, name, **kwargs):
5363
:param name: tag name
5464
:returns: requester response with tag id as data
5565
"""
56-
data = (Tag.default_get)(name=name, **kwargs)
57-
resp = self.requester.post(data=(json.dumps(data)), headers={
58-
'Content-Type': 'application/json'})
66+
data = Tag.default_get(name=name, **kwargs)
67+
resp = self.requester.post(
68+
data=json.dumps(data),
69+
headers={
70+
'Content-Type': 'application/json'
71+
})
5972
if resp.is_ok:
6073
resp.data = int(
6174
resp.raw.headers['Content-Location'].split('/')[(-1)])
@@ -64,7 +77,7 @@ def create_systemtag(self, name, **kwargs):
6477
def delete_systemtag(self, name=None, tag_id=None):
6578
"""
6679
Delete systemtag
67-
80+
6881
:param name (str): tag name, not required it tag_id is provided
6982
:tag_id (int): tag id, not required if name is provided
7083
@@ -74,16 +87,15 @@ def delete_systemtag(self, name=None, tag_id=None):
7487
resp = self.get_sytemtag(name, ['id'], json_output=False)
7588
if resp.data:
7689
tag_id = resp.data[0].id
77-
elif tag_id:
78-
resp = self.requester.delete(url=(str(tag_id)))
90+
if not tag_id: # lint only
91+
return None
92+
resp = self.requester.delete(url=(str(tag_id)))
7993
return resp
8094

8195

8296
class SystemTagsRelation(WebDAVApiWrapper):
8397
""" SystemTagsRelation API wrapper """
8498
API_URL = '/remote.php/dav/systemtags-relations/files'
85-
JSON_ABLE = True
86-
REQUIRE_CLIENT = True
8799

88100
def _get_fileid_from_path(self, path):
89101
""" Tricky function to fetch file """
@@ -121,7 +133,8 @@ def get_systemtags_relation(self, file_id=None, **kwargs):
121133
122134
:returns: requester response with <list>Tag in data
123135
"""
124-
file_id, = self._arguments_get(['file_id'], locals())
136+
file_id, = self._arguments_get(['file_id'], dict(file_id=file_id,
137+
**kwargs))
125138
data = Tag.build_xml_propfind()
126139
resp = self.requester.propfind(additional_url=file_id, data=data)
127140
return Tag.from_response(resp, json_output=(self.json_output))
@@ -138,7 +151,7 @@ def delete_systemtags_relation(self, file_id=None, tag_id=None, **kwargs):
138151
:returns: requester response
139152
"""
140153
file_id, tag_id = self._arguments_get([
141-
'file_id', 'tag_id'], locals())
154+
'file_id', 'tag_id'], dict(file_id=file_id, tag_id=tag_id, **kwargs))
142155
resp = self.requester.delete(url=('{}/{}'.format(file_id, tag_id)))
143156
return resp
144157

@@ -163,6 +176,5 @@ def add_systemtags_relation(self, file_id=None, tag_id=None, **kwargs):
163176
tag_id = resp.data
164177
if not file_id:
165178
raise ValueError('No file found')
166-
data = Tag.build_xml_propfind()
167179
resp = self.requester.put(url=('{}/{}'.format(file_id, tag_id)))
168180
return resp

src/nextcloud/api_wrappers/user.py

-1
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@
99
class User(base.ProvisioningApiWrapper):
1010
""" User API wrapper """
1111
API_URL = "/ocs/v1.php/cloud/users"
12-
REQUIRE_CLIENT = True
1312

1413
def add_user(self, uid, passwd):
1514
"""

src/nextcloud/api_wrappers/user_ldap.py

+1-3
Original file line numberDiff line numberDiff line change
@@ -126,9 +126,7 @@ def edit_ldap_config(self, config_id, data):
126126
127127
:returns: requester response
128128
"""
129-
prepared_data = {
130-
'configData[{}]'.format(key): value
131-
for key, value in data.items()}
129+
prepared_data = {'configData[{}]'.format(key): value for key, value in data.items()}
132130
return self.requester.put(config_id, data=prepared_data)
133131

134132
def ldap_cache_flush(self, config_id):

src/nextcloud/api_wrappers/webdav.py

+2-3
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,12 @@ def _extract_resource_type(file_property):
4646
file_type = list(file_property)
4747
if file_type:
4848
return re.sub('{.*}', '', file_type[0].tag)
49+
return 'file'
4950

5051

5152
class WebDAV(WebDAVApiWrapper):
5253
""" WebDav API wrapper """
5354
API_URL = "/remote.php/dav/files"
54-
JSON_ABLE = True
55-
REQUIRE_CLIENT = True
5655

5756
def _get_path(self, path):
5857
if path:
@@ -287,7 +286,7 @@ def get_file_property(self, path, field, tag='oc'):
287286
if ':' in field:
288287
tag, field = field.split(':')
289288
get_file_prop_xpath = '{DAV:}propstat/d:prop/%s:%s' % (tag, field)
290-
data = (File.build_xml_propfind)(**{tag: [field]})
289+
data = File.build_xml_propfind(**{tag: [field]})
291290
resp = self.requester.propfind(additional_url=(self._get_path(path)), headers={'Depth': str(0)},
292291
data=data)
293292
response_data = resp.data

src/nextcloud/base.py

+16-11
Original file line numberDiff line numberDiff line change
@@ -10,11 +10,12 @@
1010

1111

1212
class MetaWrapper(type):
13-
def __new__(meta, name, bases, attrs):
14-
cls = type.__new__(meta, name, bases, attrs)
15-
if (cls.API_URL != NotImplementedError and cls.VERIFIED):
16-
API_WRAPPER_CLASSES.append(cls)
17-
return cls
13+
""" Meta class to register wrappers """
14+
def __new__(cls, name, bases, attrs):
15+
new_cls = type.__new__(cls, name, bases, attrs)
16+
if (new_cls.API_URL != NotImplementedError and new_cls.VERIFIED):
17+
API_WRAPPER_CLASSES.append(new_cls)
18+
return new_cls
1819

1920

2021
class BaseApiWrapper(object, six.with_metaclass(MetaWrapper)):
@@ -40,19 +41,19 @@ class BaseApiWrapper(object, six.with_metaclass(MetaWrapper)):
4041
API_URL = NotImplementedError
4142
VERIFIED = True
4243
JSON_ABLE = True
43-
REQUIRE_CLIENT = False
44-
REQUIRE_USER = False
4544
REQUESTER = Requester
4645

47-
def __init__(self, session, json_output=None, client=None, user=None):
48-
self.json_output = json_output
46+
def __init__(self, client=None):
4947
self.client = client
50-
self.user = user
51-
self.requester = self.REQUESTER(session, json_output=json_output)
48+
self.requester = self.REQUESTER(self)
5249

5350
for attr_name in ['API_URL', 'SUCCESS_CODE', 'METHODS_SUCCESS_CODES']:
5451
setattr(self.requester, attr_name, getattr(self, attr_name, None))
5552

53+
@property
54+
def json_output(self):
55+
return self.JSON_ABLE and self.client.json_output
56+
5657
def _arguments_get(self, varnames, vals):
5758
"""
5859
allows to automatically fetch values of varnames
@@ -66,6 +67,10 @@ def _arguments_get(self, varnames, vals):
6667
>>> return self.get_file_id_from_name(vals.get('name', None))
6768
>>>
6869
>>> nxc.get_file_id(name='foo.bar')
70+
71+
:param varmames: list of wanted python var names
72+
:param vals: a dict object containing already set variables
73+
:returns: list of wanted values
6974
"""
7075
if 'kwargs' in vals:
7176
vals.update(vals['kwargs'])

src/nextcloud/common/properties.py

+17-8
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ class Property(object, six.with_metaclass(MetaProperty)):
4545
def __init__(self, xml_name, json=None, default=None, parse_xml_value=None):
4646
if ':' in xml_name:
4747
(self.ns, self.xml_key) = xml_name.split(':')
48-
self._name_convention = NAMESPACES_CLASSES[self.ns]
48+
if self.ns in NAMESPACES_CLASSES:
49+
self._name_convention = NAMESPACES_CLASSES[self.ns]._name_convention
4950
else:
5051
self.xml_key = xml_name
5152
if self.namespace:
@@ -56,16 +57,23 @@ def __init__(self, xml_name, json=None, default=None, parse_xml_value=None):
5657
self.default_val = default
5758
self.parse_xml_value = parse_xml_value
5859

59-
@classmethod
60-
def _xml_name_to_py_name(cls, name):
61-
if name in cls._name_convention:
62-
return cls._name_convention[name]
60+
def __repr__(self):
61+
return "<{}: ns={}, xml={}, py={}, json={}>".format(
62+
self.__class__.__name__,
63+
self.ns,
64+
self.attr_name,
65+
self.xml_key,
66+
self.json_key
67+
)
68+
69+
def _xml_name_to_py_name(self, name):
70+
if name in self._name_convention:
71+
return self._name_convention[name]
6372
else:
6473
return name.replace('-', '_')
6574

66-
@classmethod
67-
def _py_name_to_xml_name(cls, name):
68-
_reversed_convention = {v: k for k, v in cls._name_convention.items()}
75+
def _py_name_to_xml_name(self, name):
76+
_reversed_convention = {v: k for k, v in self._name_convention.items()}
6977
if name in _reversed_convention:
7078
return _reversed_convention[name]
7179
else:
@@ -105,6 +113,7 @@ class DProp(Property):
105113
'getcontentlength': 'content_length'
106114
}
107115

116+
108117
class OCProp(Property):
109118
""" OwnCloud property """
110119
namespace = ('oc', 'http://owncloud.org/ns')

0 commit comments

Comments
 (0)