Failed Conditions
Pull Request — master (#2076)
by Abdeali
02:04
created

Bear   A

Complexity

Total Complexity 23

Size/Duplication

Total Lines 200
Duplicated Lines 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 200
rs 10
wmc 23

14 Methods

Rating   Name   Duplication   Size   Complexity  
A execute() 0 17 2
A get_non_optional_settings() 0 12 1
A get_config_dir() 0 7 1
A log_message() 0 3 2
A check_prerequisites() 0 14 1
A _print() 0 2 1
B __init__() 0 35 5
A get_dependencies() 0 12 1
A run_bear_from_section() 0 10 2
A missing_dependencies() 0 16 3
A name() 0 6 1
A kind() 0 6 1
A get_metadata() 0 10 1
A run() 0 2 1
1
import traceback
2
3
from pyprint.Printer import Printer
4
5
from coalib.misc.Decorators import enforce_signature, classproperty
6
from coalib.output.printers.LogPrinter import LogPrinter
7
from coalib.settings.FunctionMetadata import FunctionMetadata
8
from coalib.settings.Section import Section
9
from coalib.settings.ConfigurationGathering import get_config_directory
10
11
12
class Bear(Printer, LogPrinter):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Printer does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable LogPrinter does not seem to be defined.
Loading history...
13
    """
14
    A bear contains the actual subroutine that is responsible for checking
15
    source code for certain specifications. However it can actually do
16
    whatever it wants with the files it gets. If you are missing some Result
17
    type, feel free to contact us and/or help us extending the coalib.
18
19
    This is the base class for every bear. If you want to write an bear, you
20
    will probably want to look at the GlobalBear and LocalBear classes that
21
    inherit from this class. In any case you'll want to overwrite at least the
22
    run method. You can send debug/warning/error messages through the
23
    debug(), warn(), err() functions. These will send the
24
    appropriate messages so that they are outputted. Be aware that if you use
25
    err(), you are expected to also terminate the bear run-through
26
    immediately.
27
28
    If you need some setup or teardown for your bear, feel free to overwrite
29
    the set_up() and tear_down() functions. They will be invoked
30
    before/after every run invocation.
31
32
    Settings are available at all times through self.section.
33
34
    To indicate which languages your bear supports, just give it the
35
    ``LANGUAGES`` value which can either be a string (if the bear supports
36
    only 1 language) or a tuple of strings:
37
38
    >>> class SomeBear(Bear):
39
    ...     LANGUAGES = ('C', 'CPP','C#', 'D')
40
41
    >>> class SomeBear(Bear):
42
    ...     LANGUAGES = "Java"
43
    """
44
45
    LANGUAGES = ()
46
47
    @classproperty
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable classproperty does not seem to be defined.
Loading history...
48
    def name(cls):
49
        """
50
        :return: The name of the bear
51
        """
52
        return cls.__name__
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable cls does not seem to be defined.
Loading history...
53
54
    @enforce_signature
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable enforce_signature does not seem to be defined.
Loading history...
55
    def __init__(self,
56
                 section: Section,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable Section does not seem to be defined.
Loading history...
57
                 message_queue,
58
                 timeout=0):
59
        """
60
        Constructs a new bear.
61
62
        :param section:       The section object where bear settings are
63
                              contained.
64
        :param message_queue: The queue object for messages. Can be ``None``.
65
        :param timeout:       The time the bear is allowed to run. To set no
66
                              time limit, use 0.
67
        :raises TypeError:    Raised when ``message_queue`` is no queue.
68
        :raises RuntimeError: Raised when bear requirements are not fulfilled.
69
        """
70
        Printer.__init__(self)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
71
        LogPrinter.__init__(self, self)
72
73
        if message_queue is not None and not hasattr(message_queue, "put"):
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable message_queue does not seem to be defined.
Loading history...
74
            raise TypeError("message_queue has to be a Queue or None.")
75
76
        self.section = section
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable section does not seem to be defined.
Loading history...
77
        self.message_queue = message_queue
78
        self.timeout = timeout
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable timeout does not seem to be defined.
Loading history...
79
80
        cp = type(self).check_prerequisites()
81
        if cp is not True:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable cp does not seem to be defined.
Loading history...
82
            error_string = ("The bear " + self.name +
83
                            " does not fulfill all requirements.")
84
            if cp is not False:
85
                error_string += " " + cp
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable error_string does not seem to be defined.
Loading history...
86
87
            self.warn(error_string)
88
            raise RuntimeError(error_string)
89
90
    def _print(self, output, **kwargs):
91
        self.debug(output)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable output does not seem to be defined.
Loading history...
92
93
    def log_message(self, log_message, timestamp=None, **kwargs):
94
        if self.message_queue is not None:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
95
            self.message_queue.put(log_message)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable log_message does not seem to be defined.
Loading history...
96
97
    def run(self, *args, dependency_results=None, **kwargs):
98
        raise NotImplementedError
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable NotImplementedError does not seem to be defined.
Loading history...
99
100
    def run_bear_from_section(self, args, kwargs):
101
        try:
102
            kwargs.update(
103
                self.get_metadata().create_params_from_section(self.section))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
104
        except ValueError as err:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable ValueError does not seem to be defined.
Loading history...
105
            self.warn("The bear {} cannot be executed.".format(
106
                self.name), str(err))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable err does not seem to be defined.
Loading history...
107
            return
108
109
        return self.run(*args, **kwargs)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable args does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable kwargs does not seem to be defined.
Loading history...
110
111
    def execute(self, *args, **kwargs):
112
        name = self.name
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
113
        try:
114
            self.debug("Running bear {}...".format(name))
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable name does not seem to be defined.
Loading history...
115
            # If it's already a list it won't change it
116
            return list(self.run_bear_from_section(args, kwargs) or [])
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable kwargs does not seem to be defined.
Loading history...
Comprehensibility Best Practice introduced by
The variable args does not seem to be defined.
Loading history...
117
        except:
118
            self.warn(
119
                "Bear {} failed to run. Take a look at debug messages for "
120
                "further information.".format(name))
121
            self.debug(
122
                "The bear {bear} raised an exception. If you are the writer "
123
                "of this bear, please make sure to catch all exceptions. If "
124
                "not and this error annoys you, you might want to get in "
125
                "contact with the writer of this bear.\n\nTraceback "
126
                "information is provided below:\n\n{traceback}"
127
                "\n".format(bear=name, traceback=traceback.format_exc()))
128
129
    @staticmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable staticmethod does not seem to be defined.
Loading history...
130
    def kind():
131
        """
132
        :return: The kind of the bear
133
        """
134
        raise NotImplementedError
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable NotImplementedError does not seem to be defined.
Loading history...
135
136
    @classmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable classmethod does not seem to be defined.
Loading history...
137
    def get_metadata(cls):
138
        """
139
        :return: Metadata for the run function. However parameters like
140
                 ``self`` or parameters implicitly used by coala (e.g.
141
                 filename for local bears) are already removed.
142
        """
143
        return FunctionMetadata.from_function(
144
            cls.run,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable cls does not seem to be defined.
Loading history...
145
            omit={"self", "dependency_results"})
146
147
    @classmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable classmethod does not seem to be defined.
Loading history...
148
    def missing_dependencies(cls, lst):
149
        """
150
        Checks if the given list contains all dependencies.
151
152
        :param lst: A list of all already resolved bear classes (not
153
                    instances).
154
        :return:    A list of missing dependencies.
155
        """
156
        dep_classes = cls.get_dependencies()
157
158
        for item in lst:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable lst does not seem to be defined.
Loading history...
159
            if item in dep_classes:
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable item does not seem to be defined.
Loading history...
160
                dep_classes.remove(item)
161
162
        return dep_classes
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable dep_classes does not seem to be defined.
Loading history...
163
164
    @staticmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable staticmethod does not seem to be defined.
Loading history...
165
    def get_dependencies():
166
        """
167
        Retrieves bear classes that are to be executed before this bear gets
168
        executed. The results of these bears will then be passed to the
169
        run method as a dict via the dependency_results argument. The dict
170
        will have the name of the Bear as key and the list of its results as
171
        results.
172
173
        :return: A list of bear classes.
174
        """
175
        return []
176
177
    @classmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable classmethod does not seem to be defined.
Loading history...
178
    def get_non_optional_settings(cls):
179
        """
180
        This method has to determine which settings are needed by this bear.
181
        The user will be prompted for needed settings that are not available
182
        in the settings file so don't include settings where a default value
183
        would do.
184
185
        :return: A dictionary of needed settings as keys and a tuple of help
186
                 text and annotation as values
187
        """
188
        return cls.get_metadata().non_optional_params
189
190
    @classmethod
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable classmethod does not seem to be defined.
Loading history...
191
    def check_prerequisites(cls):
192
        """
193
        Checks whether needed runtime prerequisites of the bear are satisfied.
194
195
        This function gets executed at construction and returns True by
196
        default.
197
198
        Section value requirements shall be checked inside the ``run`` method.
199
200
        :return: True if prerequisites are satisfied, else False or a string
201
                 that serves a more detailed description of what's missing.
202
        """
203
        return True
204
205
    def get_config_dir(self):
206
        """
207
        Gives the directory where the configuration file is
208
209
        :return: Directory of the config file
210
        """
211
        return get_config_directory(self.section)
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable self does not seem to be defined.
Loading history...
212