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

nextcloud.common.properties.Property.__init__()   A

Complexity

Conditions 4

Size

Total Lines 14
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 12
dl 0
loc 14
rs 9.8
c 0
b 0
f 0
cc 4
nop 5
1
# -*- coding: utf-8 -*-
2
"""
3
Define properties types that can be used one OwnCloud/NextCloud elements
4
5
6
How to define a new property namespace. Example:
7
>>> class NCProp(Property):
8
>>>    # define the namespace code with the namespace value
9
>>>     namespace = ('nc', 'http://nextcloud.org/ns')
10
>>>    # choose which attribute name is given by default on PropertySet
11
>>>    _name_convention = {
12
>>>        # xml     :  python
13
>>>        'xmly-attr-name': 'cute_attr_name',
14
>>>    }  # Note: by default, all '-' are already replaced by '_'
15
16
"""
17
import six
18
19
NAMESPACES_MAP = {}
20
NAMESPACES_CLASSES = {}
21
22
23
class MetaProperty(type):
24
    def __new__(meta, name, bases, attrs):
25
        cls = type.__new__(meta, name, bases, attrs)
26
        if (cls.namespace):
27
            NAMESPACES_MAP[cls.namespace[0]] = cls.namespace[1]
28
            NAMESPACES_CLASSES[cls.namespace[0]] = cls
29
        return cls
30
31
32
class Property(object, six.with_metaclass(MetaProperty)):
33
    """
34
    Define an element property, and naming of resulting python attribute
35
36
    :param xml_name:        xml property name (prefixed with 'ns:' i.e. namespace)
37
    :param json:            json property name
38
    :param default:         default value (value or function without args)
39
    :param parse_xml_value: a function that take xml.etree.ElementTree and
40
                            return value of the property
41
    """
42
    namespace = None
43
    _name_convention = {}
44
45
    def __init__(self, xml_name, json=None, default=None, parse_xml_value=None):
46
        if ':' in xml_name:
47
            (self.ns, self.xml_key) = xml_name.split(':')
48
            if self.ns in NAMESPACES_CLASSES:
49
                self._name_convention = NAMESPACES_CLASSES[self.ns]._name_convention
50
        else:
51
            self.xml_key = xml_name
52
            if self.namespace:
53
                self.ns = self.namespace[0]
54
55
        self.attr_name = self._xml_name_to_py_name(self.xml_key)
56
        self.json_key = json
57
        self.default_val = default
58
        self.parse_xml_value = parse_xml_value
59
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]
72
        else:
73
            return name.replace('-', '_')
74
75
    def _py_name_to_xml_name(self, name):
76
        _reversed_convention = {v: k for k, v in self._name_convention.items()}
77
        if name in _reversed_convention:
78
            return _reversed_convention[name]
79
        else:
80
            return name.replace('_', '-')
81
82
    @property
83
    def default_value(self):
84
        """ Fetch default value """
85
        if callable(self.default_val):
86
            return self.default_val()
87
        else:
88
            return self.default_val
89
90
    def get_value(self, xml=None):
91
        """
92
        Fetch value from input data
93
94
        :param xml:  xml.etree.ElementTree node
95
        :returns:    python value
96
        """
97
        if xml is not None:
98
            if self.parse_xml_value:
99
                return self.parse_xml_value(xml)
100
            else:
101
                return xml.text
102
103
104
class DProp(Property):
105
    """ DAV property """
106
    namespace = ('d', 'DAV:')
107
108
    _name_convention = {
109
        'getlastmodified': 'last_modified',
110
        'getetag': 'etag',
111
        'getcontenttype': 'content_type',
112
        'resourcetype': 'resource_type',
113
        'getcontentlength': 'content_length'
114
    }
115
116
117
class OCProp(Property):
118
    """ OwnCloud property """
119
    namespace = ('oc', 'http://owncloud.org/ns')
120
121
    _name_convention = {
122
        'fileid': 'file_id',
123
        'checksums': 'check_sums'
124
    }
125
126
127
class NCProp(Property):
128
    """ NextCloud property """
129
    namespace = ('nc', 'http://nextcloud.org/ns')
130