Exemple #1
0
    def record_message(self,
                       filename=None,
                       line=None,
                       character=None,
                       code=None,
                       message=None):

        code = code or 'F999'
        if code in self.ignore:
            return

        location = Location(
            path=filename,
            module=None,
            function=None,
            line=line,
            character=character,
        )
        message = Message(
            source='pyflakes',
            code=code,
            location=location,
            message=message,
        )
        self._messages.append(message)
Exemple #2
0
    def _combine_w0614(self, messages):
        """
        For the "unused import from wildcard import" messages,
        we want to combine all warnings about the same line into
        a single message.
        """
        by_loc = defaultdict(list)
        out = []

        for message in messages:
            if message.code == 'unused-wildcard-import':
                by_loc[message.location].append(message)
            else:
                out.append(message)

        for location, message_list in by_loc.items():
            names = []
            for msg in message_list:
                names.append(
                    _UNUSED_WILDCARD_IMPORT_RE.match(msg.message).group(1))

            msgtxt = 'Unused imports from wildcard import: %s' % ', '.join(
                names)
            combined_message = Message('pylint', 'unused-wildcard-import',
                                       location, msgtxt)
            out.append(combined_message)

        return out
Exemple #3
0
    def error(self, line_number, offset, text, check):
        code = super(ProspectorReport, self).error(
            line_number,
            offset,
            text,
            check,
        )
        if code is None:
            # The error pep8 found is being ignored, let's move on.
            return
        else:
            # Get a clean copy of the message text without the code embedded.
            text = text[5:]

        # mixed indentation (E101) is a file global message
        if code == 'E101':
            line_number = None

        # Record the message using prospector's data structures.
        location = Location(
            path=self.filename,
            module=None,
            function=None,
            line=line_number,
            character=(offset + 1),
        )
        message = Message(
            source='pep8',
            code=code,
            location=location,
            message=text,
        )

        self._prospector_messages.append(message)
Exemple #4
0
    def run(self, found_files):

        warnings = []
        for filepath in found_files.iter_file_paths():
            mimetype = mimetypes.guess_type(filepath)
            if mimetype[0] is None or not mimetype[0].startswith(
                    'text/') or mimetype[1] is not None:
                continue
            try:
                contents = read_py_file(filepath)
            except CouldNotHandleEncoding:
                continue
            for line, code, message in check_file_contents(contents):
                warnings.append({
                    'line': line,
                    'code': code,
                    'message': message,
                    'path': filepath
                })

        messages = []
        for warning in warnings:
            path = warning['path']
            prefix = os.path.commonprefix([found_files.rootpath, path])
            loc = Location(path,
                           module_from_path(path[len(prefix):]),
                           '',
                           warning['line'],
                           0,
                           absolute_path=True)
            msg = Message('dodgy', warning['code'], loc, warning['message'])
            messages.append(msg)

        return messages
Exemple #5
0
    def run(self, found_files):
        messages = []

        for code_file in found_files.iter_module_paths():
            try:
                contents = read_py_file(code_file)
                tree = ast.parse(
                    contents,
                    filename=code_file,
                )
            except CouldNotHandleEncoding as err:
                messages.append(make_tool_error_message(
                    code_file, 'mccabe', 'MC0000',
                    message='Could not handle the encoding of this file: %s' % err.encoding
                ))
                continue
            except SyntaxError as err:
                messages.append(make_tool_error_message(
                    code_file, 'mccabe', 'MC0000',
                    line=err.lineno, character=err.offset,
                    message='Syntax Error'
                ))
                continue
            except TypeError:
                messages.append(make_tool_error_message(
                    code_file, 'mccabe', 'MC0000',
                    message='Unable to parse file'
                ))
                continue

            visitor = PathGraphingAstVisitor()
            visitor.preorder(tree, visitor)

            for graph in visitor.graphs.values():
                complexity = graph.complexity()
                if complexity > self.max_complexity:
                    location = Location(
                        path=code_file,
                        module=None,
                        function=graph.entity,
                        line=graph.lineno,
                        character=0,
                        absolute_path=True
                    )
                    message = Message(
                        source='mccabe',
                        code='MC0001',
                        location=location,
                        message='%s is too complex (%s)' % (
                            graph.entity,
                            complexity,
                        ),
                    )
                    messages.append(message)

        return self.filter_messages(messages)
Exemple #6
0
 def add_message(code, message, setting):
     if code in self.ignore_codes:
         return
     line = -1
     for number, fileline in enumerate(raw_contents):
         if setting in fileline:
             line = number + 1
             break
     location = Location(relative_filepath, None, None, line, 0, False)
     message = Message('profile-validator', code, location, message)
     messages.append(message)
Exemple #7
0
    def run(self, found_files):
        messages = []

        checker = PEP257Checker()

        for code_file in found_files.iter_module_paths():
            try:
                for error in checker.check_source(
                    read_py_file(code_file),
                    code_file,
                    None
                ):

                    location = Location(
                        path=code_file,
                        module=None,
                        function='',
                        line=error.line,
                        character=0,
                        absolute_path=True,
                    )
                    message = Message(
                        source='pep257',
                        code=error.code,
                        location=location,
                        message=error.message.partition(':')[2].strip(),
                    )
                    messages.append(message)
            except CouldNotHandleEncoding as err:
                messages.append(make_tool_error_message(
                    code_file, 'pep257', 'D000',
                    message='Could not handle the encoding of this file: %s' % err.encoding
                ))
                continue
            except AllError as exc:
                # pep257's Parser.parse_all method raises AllError when an
                # attempt to analyze the __all__ definition has failed.  This
                # occurs when __all__ is too complex to be parsed.
                messages.append(make_tool_error_message(
                    code_file, 'pep257', 'D000',
                    line=1, character=0,
                    message=exc.args[0]
                ))
                continue

        return self.filter_messages(messages)
Exemple #8
0
    def add_message(self, msg_id, location, msg):
        # (* magic is acceptable here)
        loc = Location(*location)
        # At this point pylint will give us the code but we want the
        # more user-friendly symbol
        try:
            if PYLINT_VERSION < (2, 0):
                msg_data = self._message_store.check_message_id(msg_id)
            else:
                msg_data = self._message_store.get_message_definition(msg_id)
        except UnknownMessageError:
            # this shouldn't happen, as all pylint errors should be
            # in the message store, but just in case we'll fall back
            # to using the code.
            msg_symbol = msg_id
        else:
            msg_symbol = msg_data.symbol

        message = Message('pylint', msg_symbol, loc, msg)
        self._messages.append(message)
Exemple #9
0
    def get_messages(self):
        all_items = (('unused-function', 'Unused function %s',
                      self.unused_funcs),
                     ('unused-property', 'Unused property %s',
                      self.unused_props),
                     ('unused-variable', 'Unused variable %s',
                      self.unused_vars), ('unused-attribute',
                                          'Unused attribute %s',
                                          self.unused_attrs))

        vulture_messages = []
        for code, template, items in all_items:
            for item in items:
                try:
                    filename = item.file
                except AttributeError:
                    filename = item.filename
                loc = Location(filename, None, None, item.lineno, -1)
                message_text = template % item
                message = Message('vulture', code, loc, message_text)
                vulture_messages.append(message)

        return self._internal_messages + vulture_messages
Exemple #10
0
    def run(self, found_files):
        messages = []
        for module in found_files.iter_module_paths(include_ignored=True):
            dirname, filename = os.path.split(module)
            if filename != 'setup.py':
                continue

            data = projectdata.get_data(dirname)

            all_tests = [m() for m in PYROMA_TEST_CLASSES]
            for test in all_tests:
                code = PYROMA_CODES[test.__class__]

                if code in self.ignore_codes:
                    continue

                passed = test.test(data)
                if passed is False:  # passed can be True, False or None...
                    loc = Location(module, 'setup', None, -1, -1)
                    msg = Message('pyroma', code, loc, test.message())
                    messages.append(msg)

        return messages
Exemple #11
0
 def _error_message(self, filepath, message):
     location = Location(filepath, None, None, 0, 0)
     return Message('prospector', 'config-problem', location, message)
 def _msg(source, code, line_number):
     loc = Location('path.py', 'path', None, line_number, 0)
     return Message(source, code, loc, 'Test Message')
Exemple #13
0
    def execute(self):

        summary = {
            'started': datetime.now(),
        }
        summary.update(self.config.get_summary_information())

        found_files = find_python(self.config.ignores, self.config.paths,
                                  self.config.explicit_file_mode,
                                  self.config.workdir)

        # Run the tools
        messages = []
        for tool in self.config.get_tools(found_files):
            for name, cls in tools.TOOLS.items():
                if cls == tool.__class__:
                    toolname = name
                    break
            else:
                toolname = 'Unknown'

            try:
                # Tools can output to stdout/stderr in unexpected places, for example,
                # pep257 emits warnings about __all__ and as pyroma exec's the setup.py
                # file, it will execute any print statements in that, etc etc...
                with capture_output(
                        hide=not self.config.direct_tool_stdout) as capture:
                    messages += tool.run(found_files)

                    if self.config.include_tool_stdout:
                        loc = Location(self.config.workdir, None, None, None,
                                       None)

                        if capture.get_hidden_stderr():
                            msg = 'stderr from %s:\n%s' % (
                                toolname, capture.get_hidden_stderr())
                            messages.append(
                                Message(toolname,
                                        'hidden-output',
                                        loc,
                                        message=msg))
                        if capture.get_hidden_stdout():
                            msg = 'stdout from %s:\n%s' % (
                                toolname, capture.get_hidden_stdout())
                            messages.append(
                                Message(toolname,
                                        'hidden-output',
                                        loc,
                                        message=msg))

            except FatalProspectorException as fatal:
                sys.stderr.write(fatal.message)
                sys.exit(2)

            except Exception:  # pylint: disable=broad-except
                if self.config.die_on_tool_error:
                    raise
                else:
                    loc = Location(self.config.workdir, None, None, None, None)
                    msg = 'Tool %s failed to run (exception was raised)' % (
                        toolname, )
                    message = Message(
                        toolname,
                        'failure',
                        loc,
                        message=msg,
                    )
                    messages.append(message)

        messages = self.process_messages(found_files, messages)

        summary['message_count'] = len(messages)
        summary['completed'] = datetime.now()

        # Timedelta.total_seconds() is not available
        # on Python<=2.6 so we calculate it ourselves
        # See issue #60 and http://stackoverflow.com/a/3694895
        delta = (summary['completed'] - summary['started'])
        total_seconds = (delta.microseconds +
                         (delta.seconds + delta.days * 24 * 3600) * 1e6) / 1e6
        summary['time_taken'] = '%0.2f' % total_seconds

        external_config = []
        for tool, configured_by in self.config.configured_by.items():
            if configured_by is not None:
                external_config.append((tool, configured_by))
        if len(external_config) > 0:
            summary['external_config'] = ', '.join(
                ['%s: %s' % info for info in external_config])

        self.summary = summary
        self.messages = self.messages + messages