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

PropertySet.default_get()   A

Complexity

Conditions 1

Size

Total Lines 11
Code Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 5
dl 0
loc 11
rs 10
c 0
b 0
f 0
cc 1
nop 3
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 __init__(self, xml_data, init_attrs=False, wrapper=None):
38
        if init_attrs:
39
            for attr in self._attrs:
40
                setattr(self, attr.attr_name, None)
41
42
        self._wrapper = wrapper
43
        self.href = xml_data.find('d:href', NAMESPACES_MAP).text
44
        for propstat in xml_data.iter('{DAV:}propstat'):
45
            if propstat.find('d:status', NAMESPACES_MAP).text != self.SUCCESS_STATUS:
46
                pass
47
            else:
48
                for xml_property in propstat.find('d:prop', NAMESPACES_MAP):
49
                    property_name = re.sub('{.*}', '', xml_property.tag)
50
                    prop = self._fetch_property(property_name)
51
                    if not prop:
52
                        pass
53
                    else:
54
                        value = prop.get_value(xml=xml_property)
55
                        setattr(self, prop.attr_name, value)
56
57
    @classmethod
58
    def default_get(cls, key_format='json', **kwargs):
59
        """
60
        Get default values
61
62
        :param key_format: 'json' or 'xml'
63
        :param (any):       values to force (python names)
64
        """
65
        vals = {getattr(v, '%s_key' % key_format): kwargs.get(v.attr_name, v.default_value)
66
                for v in cls._attrs if getattr(v, '%s_key' % key_format, False)}
67
        return vals
68
69
    @classmethod
70
    def build_xml_propfind(cls, instr=None, filter_rules=None, use_default=False, fields=None):
71
        """see SimpleXml.build_propfind_datas
72
73
        :param use_default:   True to use all values specified in PropertySet
74
        """
75
        if use_default:
76
            if not fields:
77
                fields = {k: [] for k in NAMESPACES_MAP.keys()}
78
                for attr in cls._attrs:
79
                    fields[attr.ns].append(attr.xml_key)
80
81
        return SimpleXml.build_propfind_datas(instr=instr, filter_rules=filter_rules,
82
                                              fields=(fields or {}))
83
84
    @classmethod
85
    def build_xml_propupdate(cls, values):
86
        """ see SimpleXml.build_propupdate_datas """
87
        return SimpleXml.build_propupdate_datas(values)
88
89
    @classmethod
90
    def from_response(cls, resp, json_output=None, filtered=None,
91
                      init_attrs=None, wrapper=None):
92
        """ Build list of PropertySet from a NextcloudResponse """
93
        if not resp.is_ok:
94
            resp.data = None
95
            return resp
96
        else:
97
            response_data = resp.data
98
            response_xml_data = SimpleXml.fromstring(response_data)
99
            attr_datas = [cls(xml_data, init_attrs=init_attrs, wrapper=wrapper)
100
                          for xml_data in response_xml_data]
101
            if filtered:
102
                if callable(filtered):
103
                    attr_datas = [
104
                        attr_data for attr_data in attr_datas if filtered(attr_data)]
105
            resp.data = attr_datas if not json_output else [
106
                attr_data.as_dict() for attr_data in attr_datas]
107
            return resp
108
109
    def as_dict(self):
110
        """ Return current instance as a {k: val} dict """
111
        attrs = [v.attr_name for v in self._attrs]
112
        return {key: value for key, value in self.__dict__.items() if key in attrs}
113