Passed
Pull Request — master (#69)
by
unknown
01:10
created

nextcloud.common.collections   A

Complexity

Total Complexity 25

Size/Duplication

Total Lines 119
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
wmc 25
eloc 77
dl 0
loc 119
rs 10
c 0
b 0
f 0

10 Methods

Rating   Name   Duplication   Size   Complexity  
A PropertySet._fields() 0 3 1
A PropertySet._fetch_property() 0 5 3
A PropertySet._properties() 0 3 1
A PropertySet.default_get() 0 11 1
A PropertySet.__repr__() 0 2 1
A PropertySet.as_dict() 0 4 1
A PropertySet.build_xml_propfind() 0 14 4
A PropertySet.build_xml_propupdate() 0 4 1
B PropertySet.__init__() 0 19 7
B PropertySet.from_response() 0 22 5
1
# -*- coding: utf-8 -*-
2
"""
3
Define generic request/result class
4
common to File and Tag
5
"""
6
import re
7
from nextcloud.common.simplexml import SimpleXml
8
from nextcloud.common.properties import NAMESPACES_MAP
9
10
11
class PropertySet(object):
12
    """
13
    Set of nextcloud.common.properties.Prop
14
    defined in _attrs class variable.
15
16
    The inherited classes can do additionnal complex operations
17
    if wrapper instance is defined at initialization.
18
    """
19
    SUCCESS_STATUS = 'HTTP/1.1 200 OK'
20
    COLLECTION_RESOURCE_TYPE = 'collection'
21
    _attrs = []
22
23
    @property
24
    def _fields(self):
25
        return [v.attr_name for v in self._attrs]
26
27
    @property
28
    def _properties(self):
29
        return [v.xml_key for v in self._attrs]
30
31
    @classmethod
32
    def _fetch_property(cls, key, attr='xml_key'):
33
        for k in cls._attrs:
34
            if getattr(k, attr) == key:
35
                return k
36
37
    def __repr__(self, add_info=''):
38
        return "<%s %s%s>" % (self.__class__.__name__, self.href, add_info)
39
40
    def __init__(self, xml_data, init_attrs=False, wrapper=None):
41
        if init_attrs:
42
            for attr in self._attrs:
43
                setattr(self, attr.attr_name, None)
44
45
        self._wrapper = wrapper
46
        self.href = xml_data.find('d:href', NAMESPACES_MAP).text
47
        for propstat in xml_data.iter('{DAV:}propstat'):
48
            if propstat.find('d:status', NAMESPACES_MAP).text != self.SUCCESS_STATUS:
49
                pass
50
            else:
51
                for xml_property in propstat.find('d:prop', NAMESPACES_MAP):
52
                    property_name = re.sub('{.*}', '', xml_property.tag)
53
                    prop = self._fetch_property(property_name)
54
                    if not prop:
55
                        pass
56
                    else:
57
                        value = prop.get_value(xml=xml_property)
58
                        setattr(self, prop.attr_name, value)
59
60
    @classmethod
61
    def default_get(cls, key_format='json', **kwargs):
62
        """
63
        Get default values
64
65
        :param key_format: 'json' or 'xml'
66
        :param (any):       values to force (python names)
67
        """
68
        vals = {getattr(v, '%s_key' % key_format): kwargs.get(v.attr_name, v.default_value)
69
                for v in cls._attrs if getattr(v, '%s_key' % key_format, False)}
70
        return vals
71
72
    @classmethod
73
    def build_xml_propfind(cls, instr=None, filter_rules=None, use_default=False, fields=None):
74
        """see SimpleXml.build_propfind_datas
75
76
        :param use_default:   True to use all values specified in PropertySet
77
        """
78
        if use_default:
79
            if not fields:
80
                fields = {k: [] for k in NAMESPACES_MAP.keys()}
81
                for attr in cls._attrs:
82
                    fields[attr.ns].append(attr.xml_key)
83
84
        return SimpleXml.build_propfind_datas(instr=instr, filter_rules=filter_rules,
85
                                              fields=(fields or {}))
86
87
    @classmethod
88
    def build_xml_propupdate(cls, values):
89
        """ see SimpleXml.build_propupdate_datas """
90
        return SimpleXml.build_propupdate_datas(values)
91
92
    @classmethod
93
    def from_response(cls, resp, json_output=None, filtered=None,
94
                      init_attrs=None, wrapper=None):
95
        """ Build list of PropertySet from a NextcloudResponse """
96
        if not resp.is_ok:
97
            resp.data = None
98
            return resp
99
        else:
100
            response_data = resp.data
101
            response_xml_data = SimpleXml.fromstring(response_data)
102
            attr_datas = [cls(xml_data, init_attrs=init_attrs, wrapper=wrapper)
103
                          for xml_data in response_xml_data]
104
            if filtered:
105
                if callable(filtered):
106
                    attr_datas = [
107
                        attr_data
108
                        for attr_data in attr_datas
109
                        if filtered(attr_data)
110
                    ]
111
            resp.data = attr_datas if not json_output else [
112
                attr_data.as_dict() for attr_data in attr_datas]
113
            return resp
114
115
    def as_dict(self):
116
        """ Return current instance as a {k: val} dict """
117
        attrs = [v.attr_name for v in self._attrs]
118
        return {key: value for key, value in self.__dict__.items() if key in attrs}
119