Пример #1
0
    def _determine_profiles(self):
        # Use the strictness profile
        if self.config.strictness:
            self.profiles.append('strictness_%s' % self.config.strictness)

        # Use other specialty profiles based on options
        if not self.config.doc_warnings:
            self.profiles.append('no_doc_warnings')
        if not self.config.test_warnings:
            self.profiles.append('no_test_warnings')
        if not self.config.style_warnings:
            self.profiles.append('no_pep8')
        if self.config.full_pep8:
            self.profiles.append('full_pep8')

        # Use the specified profiles
        self.profiles += self.config.profiles

        self.profile_adaptor = ProfileAdaptor(self.profiles)
        self.adaptors.append(self.profile_adaptor)
Пример #2
0
    def _determine_profiles(self):
        # Use the strictness profile
        if self.config.strictness:
            self.profiles.append('strictness_%s' % self.config.strictness)

        # Use other specialty profiles based on options
        if not self.config.doc_warnings:
            self.profiles.append('no_doc_warnings')
        if not self.config.test_warnings:
            self.profiles.append('no_test_warnings')
        if not self.config.style_warnings:
            self.profiles.append('no_pep8')
        if self.config.full_pep8:
            self.profiles.append('full_pep8')

        # Use the specified profiles
        self.profiles += self.config.profiles

        self.profile_adaptor = ProfileAdaptor(self.profiles)
        self.adaptors.append(self.profile_adaptor)
Пример #3
0
class Prospector(object):
    def __init__(self, config, path):
        self.config = config
        self.path = path
        self.adaptors = []
        self.libraries = []
        self.profiles = []
        self.profile_adaptor = None
        self.tool_runners = []
        self.ignores = []

        self._determine_adapters()
        self._determine_profiles()
        self._determine_tool_runners()
        self._determine_ignores()

    def _determine_adapters(self):
        # Bring in the common adaptor
        if self.config.common_plugin:
            self.adaptors.append(CommonAdaptor())

        # Bring in adaptors that we automatically detect are needed
        if self.config.autodetect:
            for name, adaptor in autodetect_libraries(self.path):
                self.libraries.append(name)
                self.adaptors.append(adaptor)

        # Bring in adaptors for the specified libraries
        for name in self.config.uses:
            if name not in self.libraries:
                self.libraries.append(name)
                self.adaptors.append(LIBRARY_ADAPTORS[name]())

    def _determine_profiles(self):
        # Use the strictness profile
        if self.config.strictness:
            self.profiles.append('strictness_%s' % self.config.strictness)

        # Use other specialty profiles based on options
        if not self.config.doc_warnings:
            self.profiles.append('no_doc_warnings')
        if not self.config.test_warnings:
            self.profiles.append('no_test_warnings')
        if not self.config.style_warnings:
            self.profiles.append('no_pep8')
        if self.config.full_pep8:
            self.profiles.append('full_pep8')

        # Use the specified profiles
        self.profiles += self.config.profiles

        self.profile_adaptor = ProfileAdaptor(self.profiles)
        self.adaptors.append(self.profile_adaptor)

    def _determine_tool_runners(self):
        for tool in self.config.tools:
            if self.profile_adaptor.is_tool_enabled(tool):
                self.tool_runners.append(tools.TOOLS[tool]())

    def _determine_ignores(self):
        # Grab ignore patterns from the profile adapter
        ignores = [
            re.compile(ignore)
            for ignore in self.profile_adaptor.profile.ignore
        ]

        # Grab ignore patterns from the options
        ignores += [re.compile(patt) for patt in self.config.ignore_patterns]

        # Grab ignore paths from the options
        boundary = r"(^|/|\\)%s(/|\\|$)"
        ignores += [
            re.compile(boundary % re.escape(ignore_path))
            for ignore_path in self.config.ignore_paths
        ]

        # Add any specified by the other adaptors
        for adaptor in self.adaptors:
            if hasattr(adaptor.__class__, 'ignore_patterns'):
                ignores += [re.compile(p) for p in adaptor.ignore_patterns]

        self.ignores = ignores

    def process_messages(self, messages):
        for message in messages:
            if self.config.absolute_paths:
                message.to_absolute_path(self.path)
            else:
                message.to_relative_path(self.path)
        if self.config.blending:
            messages = blender.blend(messages)

        return messages

    def execute(self):
        summary = {
            'started': datetime.now(),
            'libraries': self.libraries,
            'strictness': self.config.strictness,
            'profiles': self.profiles,
            'adaptors': [adaptor.name for adaptor in self.adaptors],
            'tools': self.config.tools,
        }

        # Prep the tools.
        for tool in self.tool_runners:
            tool.prepare(self.path, self.ignores, self.config, self.adaptors)

        # Run the tools
        messages = []
        for tool in self.tool_runners:
            try:
                messages += tool.run()
            except Exception:  # pylint: disable=W0703
                if self.config.die_on_tool_error:
                    raise
                else:
                    for name, cls in tools.TOOLS.items():
                        if cls == tool.__class__:
                            toolname = name
                            break
                    else:
                        toolname = 'Unknown'

                    loc = Location(self.path, 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(messages)

        summary['message_count'] = len(messages)
        summary['completed'] = datetime.now()
        delta = (summary['completed'] - summary['started'])
        summary['time_taken'] = '%0.2f' % delta.total_seconds()

        return summary, messages
Пример #4
0
    def _determine_profiles(self):

        # Use other specialty profiles based on options
        if not self.config.doc_warnings:
            self.profiles.append('no_doc_warnings')
        if not self.config.test_warnings:
            self.profiles.append('no_test_warnings')
        if not self.config.style_warnings:
            self.profiles.append('no_pep8')
        if self.config.full_pep8:
            self.profiles.append('full_pep8')

        # Use the specified profiles
        profile_provided = False
        if len(self.config.profiles) > 0:
            profile_provided = True
        self.profiles += self.config.profiles

        # if there is a '.prospector.yaml' or a '.prospector/prospector.yaml'
        # file then we'll include that
        prospector_yaml = os.path.join(self.path, '.prospector.yaml')
        if os.path.exists(prospector_yaml) and os.path.isfile(prospector_yaml):
            profile_provided = True
            self.profiles.append(prospector_yaml)

        prospector_yaml = os.path.join(self.path, 'prospector', 'prospector.yaml')
        if os.path.exists(prospector_yaml) and os.path.isfile('prospector'):
            profile_provided = True
            self.profiles.append(prospector_yaml)

        if not profile_provided:
            # Use the strictness profile only if no profile has been given
            if self.config.strictness:
                self.profiles = ['strictness_%s' % self.config.strictness] + self.profiles
                self.strictness = self.config.strictness
        else:
            self.strictness = 'from profile'

        # the profile path is
        #   * anything provided as an argument
        #   * a directory called .prospector in the check path
        #   * the check path
        #   * prospector provided profiles
        profile_path = self.config.profile_path

        prospector_dir = os.path.join(self.path, '.prospector')
        if os.path.exists(prospector_dir) and os.path.isdir(prospector_dir):
            profile_path.append(prospector_dir)

        profile_path.append(self.path)

        provided = os.path.join(os.path.dirname(__file__), 'profiles/profiles')
        profile_path.append(provided)

        try:
            self.profile_adaptor = ProfileAdaptor(self.profiles, profile_path)
        except ProfileNotFound as nfe:
            sys.stderr.write("Failed to run:\nCould not find profile %s. Search path: %s\n" %
                             (nfe.name, ':'.join(nfe.profile_path)))
            sys.exit(1)

        self.adaptors.append(self.profile_adaptor)
Пример #5
0
class Prospector(object):
    def __init__(self, config, path):
        self.config = config
        self.path = path
        if os.path.isdir(path):
            self.rootpath = path
        else:
            self.rootpath = os.getcwd()
        self.adaptors = []
        self.libraries = []
        self.profiles = []
        self.profile_adaptor = None
        self.tool_runners = []
        self.ignores = []
        self.strictness = None
        self.tools_to_run = []

        self.summary = None
        self.messages = None

        self._determine_adapters()
        self._determine_profiles()
        self._determine_tool_runners()
        self._determine_ignores()

    def _determine_adapters(self):
        # Bring in the common adaptor
        if self.config.common_plugin:
            self.adaptors.append(CommonAdaptor())

        # Bring in adaptors that we automatically detect are needed
        if self.config.autodetect:
            for name, adaptor in autodetect_libraries(self.path):
                self.libraries.append(name)
                self.adaptors.append(adaptor)

        # Bring in adaptors for the specified libraries
        for name in self.config.uses:
            if name not in self.libraries:
                self.libraries.append(name)
                self.adaptors.append(LIBRARY_ADAPTORS[name]())

    def _determine_profiles(self):

        # Use other specialty profiles based on options
        if not self.config.doc_warnings:
            self.profiles.append('no_doc_warnings')
        if not self.config.test_warnings:
            self.profiles.append('no_test_warnings')
        if not self.config.style_warnings:
            self.profiles.append('no_pep8')
        if self.config.full_pep8:
            self.profiles.append('full_pep8')

        # Use the specified profiles
        profile_provided = False
        if len(self.config.profiles) > 0:
            profile_provided = True
        self.profiles += self.config.profiles

        # if there is a '.prospector.yaml' or a '.prospector/prospector.yaml'
        # file then we'll include that
        prospector_yaml = os.path.join(self.path, '.prospector.yaml')
        if os.path.exists(prospector_yaml) and os.path.isfile(prospector_yaml):
            profile_provided = True
            self.profiles.append(prospector_yaml)

        prospector_yaml = os.path.join(self.path, 'prospector', 'prospector.yaml')
        if os.path.exists(prospector_yaml) and os.path.isfile('prospector'):
            profile_provided = True
            self.profiles.append(prospector_yaml)

        if not profile_provided:
            # Use the strictness profile only if no profile has been given
            if self.config.strictness:
                self.profiles = ['strictness_%s' % self.config.strictness] + self.profiles
                self.strictness = self.config.strictness
        else:
            self.strictness = 'from profile'

        # the profile path is
        #   * anything provided as an argument
        #   * a directory called .prospector in the check path
        #   * the check path
        #   * prospector provided profiles
        profile_path = self.config.profile_path

        prospector_dir = os.path.join(self.path, '.prospector')
        if os.path.exists(prospector_dir) and os.path.isdir(prospector_dir):
            profile_path.append(prospector_dir)

        profile_path.append(self.path)

        provided = os.path.join(os.path.dirname(__file__), 'profiles/profiles')
        profile_path.append(provided)

        try:
            self.profile_adaptor = ProfileAdaptor(self.profiles, profile_path)
        except ProfileNotFound as nfe:
            sys.stderr.write("Failed to run:\nCould not find profile %s. Search path: %s\n" %
                             (nfe.name, ':'.join(nfe.profile_path)))
            sys.exit(1)

        self.adaptors.append(self.profile_adaptor)

    def _determine_tool_runners(self):

        if self.config.tools is None:
            # we had no command line settings for an explicit list of
            # tools, so we use the defaults
            to_run = set(DEFAULT_TOOLS)
            # we can also use any that the profiles dictate
            for tool in tools.TOOLS.keys():
                if self.profile_adaptor.is_tool_enabled(tool):
                    to_run.add(tool)
        else:
            to_run = set(self.config.tools)
            # profiles have no say in the list of tools run when
            # a command line is specified

        for tool in self.config.with_tools:
            to_run.add(tool)

        for tool in self.config.without_tools:
            to_run.remove(tool)

        if self.config.tools is None and len(self.config.with_tools) == 0 and len(self.config.without_tools) == 0:
            for tool in tools.TOOLS.keys():
                enabled = self.profile_adaptor.is_tool_enabled(tool)
                if enabled is None:
                    enabled = tool in DEFAULT_TOOLS
                if tool in to_run and not enabled:
                    to_run.remove(tool)

        self.tools_to_run = sorted(list(to_run))
        for tool in self.tools_to_run:
            self.tool_runners.append(tools.TOOLS[tool]())

    def _determine_ignores(self):
        # Grab ignore patterns from the profile adapter
        ignores = [
            re.compile(ignore)
            for ignore in self.profile_adaptor.profile.ignore
        ]

        # Grab ignore patterns from the options
        ignores += [
            re.compile(patt)
            for patt in self.config.ignore_patterns
        ]

        # Grab ignore paths from the options
        boundary = r"(^|/|\\)%s(/|\\|$)"
        ignores += [
            re.compile(boundary % re.escape(ignore_path))
            for ignore_path in self.config.ignore_paths
        ]

        # Add any specified by the other adaptors
        for adaptor in self.adaptors:
            if hasattr(adaptor.__class__, 'ignore_patterns'):
                ignores += [re.compile(p) for p in adaptor.ignore_patterns]

        self.ignores = ignores

    def process_messages(self, messages):
        for message in messages:
            if self.config.absolute_paths:
                message.to_absolute_path(self.rootpath)
            else:
                message.to_relative_path(self.rootpath)
        if self.config.blending:
            messages = blender.blend(messages)

        return postfilter.filter_messages(messages)

    def execute(self):

        summary = {
            'started': datetime.now(),
            'libraries': self.libraries,
            'strictness': self.strictness,
            'profiles': self.profiles,
            'adaptors': [adaptor.name for adaptor in self.adaptors],
            'tools': self.tools_to_run,
        }

        # Find the files and packages in a common way, so that each tool
        # gets the same list.
        found_files = find_python(self.ignores, self.path)

        # Prep the tools.
        for tool in self.tool_runners:
            tool.prepare(found_files, self.config, self.adaptors)

        # Run the tools
        messages = []
        for tool in self.tool_runners:
            try:
                messages += tool.run()
            except Exception:  # pylint: disable=W0703
                if self.config.die_on_tool_error:
                    raise
                else:
                    for name, cls in tools.TOOLS.items():
                        if cls == tool.__class__:
                            toolname = name
                            break
                    else:
                        toolname = 'Unknown'

                    loc = Location(self.path, 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(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

        self.summary = summary
        self.messages = messages

    def get_summary(self):
        return self.summary

    def get_messages(self):
        return self.messages

    def print_messages(self, write_to=None):
        write_to = write_to or sys.stdout

        # Get the output formatter
        if self.config.output_format is not None:
            output_format = self.config.output_format
        else:
            output_format = self.profile_adaptor.get_output_format()

        if output_format is None:
            output_format = 'text'

        self.summary['formatter'] = output_format
        formatter = FORMATTERS[output_format](self.summary, self.messages)

        # Produce the output
        write_to.write(formatter.render(
            summary=not self.config.messages_only,
            messages=not self.config.summary_only,
        ))
        write_to.write('\n')
Пример #6
0
def run():
    parser = make_arg_parser()
    args = parser.parse_args()

    if args.version:
        sys.stdout.write("Prospector version %s\n" % __pkginfo__.get_version())
        sys.exit(0)

    summary = {
        'started': datetime.now()
    }

    path = args.path or os.path.abspath(os.getcwd())

    try:
        formatter = FORMATTERS[args.output_format]
        summary['formatter'] = args.output_format
    except KeyError:
        _die("Formatter %s is not valid - possible values are %s" % (
            args.output_format,
            ', '.join(FORMATTERS.keys()),
        ))

    libraries_used = []
    profiles = []
    adaptors = []

    if not args.no_common_plugin:
        adaptors.append(CommonAdaptor())
    if not args.no_autodetect:
        for libname, adaptor in autodetect_libraries(path):
            libraries_used.append(libname)
            adaptors.append(adaptor)

    strictness = args.strictness
    strictness_options = ('veryhigh', 'high', 'medium', 'low', 'verylow')
    if strictness not in strictness_options:
        possible = ', '.join(strictness_options)
        _die(
            "%s is not a valid value for strictness - possible values are %s" %
            (strictness, possible)
        )
    else:
        profiles.append('strictness_%s' % strictness)
        summary['strictness'] = strictness

    for library in args.uses:
        if library not in LIBRARY_ADAPTORS:
            possible = ', '.join(LIBRARY_ADAPTORS.keys())
            _die(
                "Library/framework %s is not valid - possible values are %s" %
                (library, possible)
            )
        libraries_used.append(library)
        adaptors.append(LIBRARY_ADAPTORS[library]())

    summary['libraries'] = ', '.join(libraries_used)

    if not args.doc_warnings:
        profiles.append('no_doc_warnings')

    if not args.test_warnings:
        profiles.append('no_test_warnings')

    if args.no_style_warnings:
        profiles.append('no_pep8')

    profiles += args.profiles

    profile_adaptor = ProfileAdaptor(profiles)
    adaptors.append(profile_adaptor)

    summary['adaptors'] = []
    for adaptor in adaptors:
        summary['adaptors'].append(adaptor.name)
    summary['adaptors'] = ', '.join(summary['adaptors'])

    tool_runners = []
    tool_names = args.tools or tools.DEFAULT_TOOLS
    for tool in tool_names:
        if not tool in tools.TOOLS:
            _die("Tool %s is not valid - possible values are %s" % (
                tool,
                ', '.join(tools.TOOLS.keys())
            ))
        if not profile_adaptor.is_tool_enabled(tool):
            continue
        tool_runners.append(tools.TOOLS[tool]())

    summary['tools'] = ', '.join(tool_names)

    ignore = [re.compile(ignore) for ignore in profile_adaptor.profile.ignore]

    for tool in tool_runners:
        tool.prepare(path, ignore, args, adaptors)

    messages = []
    for tool in tool_runners:
        try:
            messages += tool.run()
        except Exception:
            if args.die_on_tool_error:
                raise
            loc = Location(path, None, None, None, None)
            message = "Tool %s failed to run (exception was raised)" % tool.__class__.__name__
            msg = Message(tool.__class__.__name__, 'failure', loc, message=message)
            messages.append(msg)

    for message in messages:
        if args.absolute_paths:
            message.to_absolute_path(path)
        else:
            message.to_relative_path(path)

    if not args.no_blending:
        messages = blender.blend(messages)

    summary['message_count'] = len(messages)
    summary['completed'] = datetime.now()
    delta = (summary['completed'] - summary['started'])
    summary['time_taken'] = '%0.2f' % delta.total_seconds()

    summary['started'] = str(summary['started'])
    summary['completed'] = str(summary['completed'])

    if args.messages_only:
        summary = None
    if args.summary_only:
        messages = None

    formatter(summary, messages)

    sys.exit(0)
Пример #7
0
class Prospector(object):
    def __init__(self, config, path):
        self.config = config
        self.path = path
        self.adaptors = []
        self.libraries = []
        self.profiles = []
        self.profile_adaptor = None
        self.tool_runners = []
        self.ignores = []

        self._determine_adapters()
        self._determine_profiles()
        self._determine_tool_runners()
        self._determine_ignores()

    def _determine_adapters(self):
        # Bring in the common adaptor
        if self.config.common_plugin:
            self.adaptors.append(CommonAdaptor())

        # Bring in adaptors that we automatically detect are needed
        if self.config.autodetect:
            for name, adaptor in autodetect_libraries(self.path):
                self.libraries.append(name)
                self.adaptors.append(adaptor)

        # Bring in adaptors for the specified libraries
        for name in self.config.uses:
            if name not in self.libraries:
                self.libraries.append(name)
                self.adaptors.append(LIBRARY_ADAPTORS[name]())

    def _determine_profiles(self):
        # Use the strictness profile
        if self.config.strictness:
            self.profiles.append('strictness_%s' % self.config.strictness)

        # Use other specialty profiles based on options
        if not self.config.doc_warnings:
            self.profiles.append('no_doc_warnings')
        if not self.config.test_warnings:
            self.profiles.append('no_test_warnings')
        if not self.config.style_warnings:
            self.profiles.append('no_pep8')
        if self.config.full_pep8:
            self.profiles.append('full_pep8')

        # Use the specified profiles
        self.profiles += self.config.profiles

        self.profile_adaptor = ProfileAdaptor(self.profiles)
        self.adaptors.append(self.profile_adaptor)

    def _determine_tool_runners(self):
        for tool in self.config.tools:
            if self.profile_adaptor.is_tool_enabled(tool):
                self.tool_runners.append(tools.TOOLS[tool]())

    def _determine_ignores(self):
        # Grab ignore patterns from the profile adapter
        ignores = [
            re.compile(ignore)
            for ignore in self.profile_adaptor.profile.ignore
        ]

        # Grab ignore patterns from the options
        ignores += [
            re.compile(patt)
            for patt in self.config.ignore_patterns
        ]

        # Grab ignore paths from the options
        boundary = r"(^|/|\\)%s(/|\\|$)"
        ignores += [
            re.compile(boundary % re.escape(ignore_path))
            for ignore_path in self.config.ignore_paths
        ]

        # Add any specified by the other adaptors
        for adaptor in self.adaptors:
            if hasattr(adaptor.__class__, 'ignore_patterns'):
                ignores += [re.compile(p) for p in adaptor.ignore_patterns]

        self.ignores = ignores

    def process_messages(self, messages):
        for message in messages:
            if self.config.absolute_paths:
                message.to_absolute_path(self.path)
            else:
                message.to_relative_path(self.path)
        if self.config.blending:
            messages = blender.blend(messages)

        return messages

    def execute(self):
        summary = {
            'started': datetime.now(),
            'libraries': self.libraries,
            'strictness': self.config.strictness,
            'profiles': self.profiles,
            'adaptors': [adaptor.name for adaptor in self.adaptors],
            'tools': self.config.tools,
        }

        # Prep the tools.
        for tool in self.tool_runners:
            tool.prepare(self.path, self.ignores, self.config, self.adaptors)

        # Run the tools
        messages = []
        for tool in self.tool_runners:
            try:
                messages += tool.run()
            except Exception:  # pylint: disable=W0703
                if self.config.die_on_tool_error:
                    raise
                else:
                    for name, cls in tools.TOOLS.items():
                        if cls == tool.__class__:
                            toolname = name
                            break
                    else:
                        toolname = 'Unknown'

                    loc = Location(self.path, 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(messages)

        summary['message_count'] = len(messages)
        summary['completed'] = datetime.now()
        delta = (summary['completed'] - summary['started'])
        summary['time_taken'] = '%0.2f' % delta.total_seconds()

        return summary, messages