Completed
Pull Request — master (#2423)
by
unknown
01:54
created

DocstyleDefinition.load()   C

Complexity

Conditions 7

Size

Total Lines 58

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 7
c 1
b 0
f 0
dl 0
loc 58
rs 6.5526

How to fix   Long Method   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
from collections import Iterable, namedtuple
2
import os.path
3
4
from coala_utils.decorators import (
5
    enforce_signature, generate_eq, generate_repr)
6
from coalib.parsing.ConfParser import ConfParser
7
8
9
@generate_repr()
10
@generate_eq("language", "docstyle", "markers")
11
class DocstyleDefinition:
12
    """
13
    The DocstyleDefinition class holds values that identify a certain type of
14
    documentation comment (for which language, documentation style/tool used
15
    etc.).
16
    """
17
    Metadata = namedtuple("Metadata", ("param_start", "param_end",
18
                                       "return_sep"))
19
20
    @enforce_signature
21
    def __init__(self, language: str, docstyle: str, markers: (Iterable, str),
22
                 metadata: Metadata):
23
        """
24
        Instantiates a new DocstyleDefinition.
25
26
        :param language: The case insensitive programming language of the
27
                         documentation comment, e.g. ``"CPP"`` for C++ or
28
                         ``"PYTHON3"``.
29
        :param docstyle: The case insensitive documentation style/tool used
30
                         to document code, e.g. ``"default"`` or ``"doxygen"``.
31
        :param markers:  An iterable of marker/delimiter string iterables
32
                         or a single marker/delimiter string iterable that
33
                         identify a documentation comment. See ``markers``
34
                         property for more details on markers.
35
        :param metadata: A namedtuple consisting of certain attributes that
36
                         form the layout of the certain documentation comment
37
                         e.g. ``param_start`` defining the start symbol of
38
                         the parameter fields and ``param_end`` defining the
39
                         end.
40
        """
41
        self._language = language.lower()
42
        self._docstyle = docstyle.lower()
43
44
        # Check and modify tuple if only one marker_set exists.
45
        markers = tuple(markers)
46
        if len(markers) == 3 and all(isinstance(x, str) for x in markers):
47
            markers = (markers,)
48
49
        self._markers = tuple(tuple(marker_set) for marker_set in markers)
50
51
        # Check marker set dimensions.
52
        for marker_set in self._markers:
53
            length = len(marker_set)
54
            if length != 3:
55
                raise ValueError("Length of a given marker set was not 3 (was "
56
                                 "actually {}).".format(length))
57
58
        self._metadata = metadata
59
60
    @property
61
    def language(self):
62
        """
63
        The programming language.
64
65
        :return: A lower-case string defining the programming language (i.e.
66
                 "cpp" or "python").
67
        """
68
        return self._language
69
70
    @property
71
    def docstyle(self):
72
        """
73
        The documentation style/tool used to document code.
74
75
        :return: A lower-case string defining the docstyle (i.e. "default" or
76
                 "doxygen").
77
        """
78
        return self._docstyle
79
80
    @property
81
    def markers(self):
82
        """
83
        A tuple of marker sets that identify a documentation comment.
84
85
        Marker sets consist of 3 entries where the first is the start-marker,
86
        the second one the each-line marker and the last one the end-marker.
87
        For example a marker tuple with a single marker set
88
        ``(("/**", "*", "*/"),)`` would match following documentation comment:
89
90
        ::
91
92
            /**
93
             * This is documentation.
94
             */
95
96
        It's also possible to supply an empty each-line marker
97
        (``("/**", "", "*/")``):
98
99
        ::
100
101
            /**
102
             This is more documentation.
103
             */
104
105
        Markers are matched "greedy", that means it will match as many
106
        each-line markers as possible. I.e. for ``("///", "///", "///")``):
107
108
        ::
109
110
            /// Brief documentation.
111
            ///
112
            /// Detailed documentation.
113
114
        :return: A tuple of marker/delimiter string tuples that identify a
115
                 documentation comment.
116
        """
117
        return self._markers
118
119
    @property
120
    def metadata(self):
121
        """
122
        A namedtuple of certain attributes present in the documentation.
123
124
        These attributes are used to define parts of the documentation.
125
        """
126
        return self._metadata
127
128
    @classmethod
129
    @enforce_signature
130
    def load(cls, language: str, docstyle: str, coalang_dir=None):
131
        """
132
        Loads a ``DocstyleDefinition`` from the coala docstyle definition files.
133
134
        This function considers all settings inside the according coalang-files
135
        as markers.
136
137
        :param language:           The case insensitive programming language of
138
                                   the documentation comment as a string.
139
        :param docstyle:           The case insensitive documentation
140
                                   style/tool used to document code, e.g.
141
                                   ``"default"`` or ``"doxygen"``.
142
        :param coalang_dir:        Path to directory with coalang docstyle
143
                                   definition files. This replaces the default
144
                                   path if given.
145
        :raises FileNotFoundError: Raised when the given docstyle was not
146
                                   found.
147
        :raises KeyError:          Raised when the given language is not
148
                                   defined for given docstyle.
149
        :return:                   The ``DocstyleDefinition`` for given language
150
                                   and docstyle.
151
        """
152
153
        docstyle = docstyle.lower()
154
155
        language_config_parser = ConfParser(remove_empty_iter_elements=False)
156
157
        coalang_file = os.path.join(
158
            coalang_dir or os.path.dirname(__file__), docstyle + ".coalang")
159
160
        try:
161
            docstyle_settings = language_config_parser.parse(coalang_file)
162
        except FileNotFoundError:
163
            raise FileNotFoundError("Docstyle definition " + repr(docstyle) +
164
                                    " not found.")
165
166
        language = language.lower()
167
168
        try:
169
            docstyle_settings = docstyle_settings[language]
170
        except KeyError:
171
            raise KeyError("Language {!r} is not defined for docstyle {!r}."
172
                           .format(language, docstyle))
173
174
        metadata_settings = ("param_start", "param_end", "return_sep")
175
176
        metadata = cls.Metadata(*(str(docstyle_settings.get(req_setting, ""))
177
                                  for req_setting in metadata_settings))
178
179
        marker_sets = (tuple(value)
180
                       for key, value in
181
                       docstyle_settings.contents.items()
182
                       if key not in metadata_settings and
183
                       not key.startswith("comment"))
184
185
        return cls(language, docstyle, marker_sets, metadata)
186