DocstringMetadata   A
last analyzed

Complexity

Total Complexity 14

Size/Duplication

Total Lines 71
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 71
rs 10
c 0
b 0
f 0
wmc 14

4 Methods

Rating   Name   Duplication   Size   Complexity  
A __init__() 0 13 1
F from_docstring() 0 51 12
A __str__() 0 2 1
A concat_doc_parts() 0 5 4
1
import inspect
2
from collections import OrderedDict
3
4
from coalib.misc.Enum import enum
5
6
7
class DocstringMetadata:
8
    _ParseMode = enum("DESCRIPTION", "PARAM", "RETVAL")
9
10
    def __init__(self, desc, param_dict, retval_desc):
11
        """
12
        Represents a docstring of a python class or function.
13
14
        :param desc:        A description as string.
15
        :param param_dict:  A dictionary containing parameter names as key and
16
                            their description as value. To preserve the order,
17
                            use OrderedDict.
18
        :param retval_desc: A string describing the return value.
19
        """
20
        self.desc = desc
21
        self.param_dict = param_dict
22
        self.retval_desc = retval_desc
23
24
    @classmethod
25
    def from_docstring(cls, docstring):
26
        """
27
        Parses a python docstring. Usable attributes are:
28
        :param
29
        @param
30
        :return
31
        @return
32
        """
33
        lines = inspect.cleandoc(docstring).split("\n")
34
35
        parse_mode = cls._ParseMode.DESCRIPTION
36
        cur_param = ""
37
38
        desc = ""
39
        param_dict = OrderedDict()
40
        retval_desc = ""
41
        for line in lines:
42
            line = line.strip()
43
44
            if line.startswith(":param ") or line.startswith("@param "):
45
                parse_mode = cls._ParseMode.PARAM
46
                splitted = line[7:].split(":", 1)
47
                cur_param = splitted[0]
48
                param_dict[cur_param] = splitted[1].strip()
49
50
                continue
51
52
            if line.startswith(":return: ") or line.startswith("@return: "):
53
                parse_mode = cls._ParseMode.RETVAL
54
                retval_desc = line[9:].strip()
55
56
                continue
57
58
            def concat_doc_parts(old: str, new: str):
59
                if new != '' and not old.endswith('\n'):
60
                    return old + ' ' + new
61
62
                return old + (new if new != '' else '\n')
63
64
            if parse_mode == cls._ParseMode.RETVAL:
65
                retval_desc = concat_doc_parts(retval_desc, line)
66
            elif parse_mode == cls._ParseMode.PARAM:
67
                param_dict[cur_param] = concat_doc_parts(param_dict[cur_param],
68
                                                         line)
69
            else:
70
                desc = concat_doc_parts(desc, line)
71
72
        return (cls(desc=desc.strip(),
73
                    param_dict=param_dict,
74
                    retval_desc=retval_desc.strip()))
75
76
    def __str__(self):
77
        return str(self.desc)
78