# Path: src/tidypy/config.py
# def get_project_config(project_path, use_cache=True):
#     """
#     Produces the Tidypy configuration to use for the specified project.
# 
#     If a ``pyproject.toml`` exists, the configuration will be based on that. If
#     not, the TidyPy configuration in the user's home directory will be used. If
#     one does not exist, the default configuration will be used.
# 
#     :param project_path: the path to the project that is going to be analyzed
#     :type project_path: str
#     :param use_cache:
#         whether or not to use cached versions of any remote/referenced TidyPy
#         configurations. If not specified, defaults to ``True``.
#     :type use_cache: bool
#     :rtype: dict
#     """
# 
#     return get_local_config(project_path, use_cache=use_cache) \
#         or get_user_config(project_path, use_cache=use_cache) \
#         or get_default_config()
# 
# Path: src/tidypy/core.py
# def execute_tools(config, path, progress=None):
#     """
#     Executes the suite of TidyPy tools upon the project and returns the
#     issues that are found.
# 
#     :param config: the TidyPy configuration to use
#     :type config: dict
#     :param path: that path to the project to analyze
#     :type path: str
#     :param progress:
#         the progress reporter object that will receive callbacks during the
#         execution of the tool suite. If not specified, not progress
#         notifications will occur.
#     :type progress: tidypy.Progress
#     :rtype: tidypy.Collector
#     """
# 
#     progress = progress or QuietProgress()
#     progress.on_start()
# 
#     with SyncManager() as manager:
#         num_tools = 0
#         tools = manager.Queue()
#         for name, cls in get_tools().items():
#             if config[name]['use'] and cls.can_be_used():
#                 num_tools += 1
#                 tools.put({
#                     'name': name,
#                     'config': config[name],
#                 })
# 
#         collector = Collector(config)
#         if not num_tools:
#             progress.on_finish()
#             return collector
# 
#         notifications = manager.Queue()
#         environment = manager.dict({
#             'finder': Finder(path, config),
#         })
# 
#         workers = []
#         for _ in range(config['workers']):
#             worker = Worker(
#                 args=(
#                     tools,
#                     notifications,
#                     environment,
#                 ),
#             )
#             worker.start()
#             workers.append(worker)
# 
#         while num_tools:
#             try:
#                 notification = notifications.get(True, 0.25)
#             except Empty:
#                 pass
#             else:
#                 if notification['type'] == 'start':
#                     progress.on_tool_start(notification['tool'])
#                 elif notification['type'] == 'complete':
#                     collector.add_issues(notification['issues'])
#                     progress.on_tool_finish(notification['tool'])
#                     num_tools -= 1
# 
#     progress.on_finish()
# 
#     return collector
# 
# Path: src/tidypy/reports/console.py
# class ConsoleReport(Report):
#     """
#     Prints a colored report to the console that groups issues by the file they
#     were found in.
#     """
# 
#     def execute(self, collector):
#         issues = collector.get_grouped_issues()
# 
#         total_issues = 0
#         for filename in sorted(issues.keys()):
#             file_issues = issues[filename]
#             total_issues += len(file_issues)
# 
#             self.output(TMPL_FILENAME.format(
#                 filename=self.relative_filename(filename),
#                 num_errors=len(file_issues),
#             ))
# 
#             for issue in file_issues:
#                 location = TMPL_LOCATION.format(
#                     line=issue.line,
#                     position_splitter=' ' if issue.character is None else ':',
#                     character=issue.character or '',
#                 )
# 
#                 toolinfo = TMPL_TOOLINFO.format(
#                     tool=issue.tool,
#                     code=issue.code,
#                 )
# 
#                 message = issue.message
#                 if '\n' in message:
#                     pad = '\n' + (' ' * len(click.unstyle(location)))
# 
#                     message = pad.join(
#                         issue.message.replace('\t', TAB).splitlines()
#                     )
# 
#                     toolinfo = pad + toolinfo
#                 else:
#                     toolinfo = ' ' + toolinfo
# 
#                 self.output(location + message + toolinfo)
# 
#             self.output('')
# 
#         is_windows = sys.platform == 'win32'
#         if total_issues:
#             self.output(
#                 click.style(
#                     '{icon}{num_issues} issues found.'.format(  # noqa: @2to3
#                         icon='' if is_windows else '\u2717 ',  # noqa: @2to3
#                         num_issues=total_issues,
#                     ),
#                     fg='yellow',
#                     bold=True,
#                 )
#             )
#         else:
#             self.output(
#                 click.style(
#                     '{icon}No issues found!'.format(  # noqa: @2to3
#                         icon='' if is_windows else '\u2714 ',  # noqa: @2to3
#                     ),
#                     fg='green',
#                     bold=True,
#                 )
#             )


import pytest
from ..config import get_project_config
from ..core import execute_tools
from ..reports.console import ConsoleReport
        action='store_true',
        dest='tidypy',
        default=False,
        help='Enable the TidyPy plugin.'
    )

    group.addoption(
        '--tidypy-project-path',
        action='store',
        dest='tidypy_project_path',
        default=None,
        help='The path to the base of the project to analyze with TidyPy.'
    )

    group.addoption(
        '--tidypy-fail-on-issue',
        action='store_true',
        dest='tidypy_fail_on_issue',
        default=False,
        help='Whether or not pytest should fail if TidyPy finds issues.'
    )


def pytest_configure(config):
    if config.getoption('tidypy'):
        if not config.pluginmanager.hasplugin('_tidypy'):
            plugin = TidyPyPlugin(config)
            config.pluginmanager.register(plugin, '_tidypy')



# Path: src/tidypy/config.py
# def get_project_config(project_path, use_cache=True):
#     """
#     Produces the Tidypy configuration to use for the specified project.
# 
#     If a ``pyproject.toml`` exists, the configuration will be based on that. If
#     not, the TidyPy configuration in the user's home directory will be used. If
#     one does not exist, the default configuration will be used.
# 
#     :param project_path: the path to the project that is going to be analyzed
#     :type project_path: str
#     :param use_cache:
#         whether or not to use cached versions of any remote/referenced TidyPy
#         configurations. If not specified, defaults to ``True``.
#     :type use_cache: bool
#     :rtype: dict
#     """
# 
#     return get_local_config(project_path, use_cache=use_cache) \
#         or get_user_config(project_path, use_cache=use_cache) \
#         or get_default_config()
# 
# Path: src/tidypy/core.py
# def execute_tools(config, path, progress=None):
#     """
#     Executes the suite of TidyPy tools upon the project and returns the
#     issues that are found.
# 
#     :param config: the TidyPy configuration to use
#     :type config: dict
#     :param path: that path to the project to analyze
#     :type path: str
#     :param progress:
#         the progress reporter object that will receive callbacks during the
#         execution of the tool suite. If not specified, not progress
#         notifications will occur.
#     :type progress: tidypy.Progress
#     :rtype: tidypy.Collector
#     """
# 
#     progress = progress or QuietProgress()
#     progress.on_start()
# 
#     with SyncManager() as manager:
#         num_tools = 0
#         tools = manager.Queue()
#         for name, cls in get_tools().items():
#             if config[name]['use'] and cls.can_be_used():
#                 num_tools += 1
#                 tools.put({
#                     'name': name,
#                     'config': config[name],
#                 })
# 
#         collector = Collector(config)
#         if not num_tools:
#             progress.on_finish()
#             return collector
# 
#         notifications = manager.Queue()
#         environment = manager.dict({
#             'finder': Finder(path, config),
#         })
# 
#         workers = []
#         for _ in range(config['workers']):
#             worker = Worker(
#                 args=(
#                     tools,
#                     notifications,
#                     environment,
#                 ),
#             )
#             worker.start()
#             workers.append(worker)
# 
#         while num_tools:
#             try:
#                 notification = notifications.get(True, 0.25)
#             except Empty:
#                 pass
#             else:
#                 if notification['type'] == 'start':
#                     progress.on_tool_start(notification['tool'])
#                 elif notification['type'] == 'complete':
#                     collector.add_issues(notification['issues'])
#                     progress.on_tool_finish(notification['tool'])
#                     num_tools -= 1
# 
#     progress.on_finish()
# 
#     return collector
# 
# Path: src/tidypy/reports/console.py
# class ConsoleReport(Report):
#     """
#     Prints a colored report to the console that groups issues by the file they
#     were found in.
#     """
# 
#     def execute(self, collector):
#         issues = collector.get_grouped_issues()
# 
#         total_issues = 0
#         for filename in sorted(issues.keys()):
#             file_issues = issues[filename]
#             total_issues += len(file_issues)
# 
#             self.output(TMPL_FILENAME.format(
#                 filename=self.relative_filename(filename),
#                 num_errors=len(file_issues),
#             ))
# 
#             for issue in file_issues:
#                 location = TMPL_LOCATION.format(
#                     line=issue.line,
#                     position_splitter=' ' if issue.character is None else ':',
#                     character=issue.character or '',
#                 )
# 
#                 toolinfo = TMPL_TOOLINFO.format(
#                     tool=issue.tool,
#                     code=issue.code,
#                 )
# 
#                 message = issue.message
#                 if '\n' in message:
#                     pad = '\n' + (' ' * len(click.unstyle(location)))
# 
#                     message = pad.join(
#                         issue.message.replace('\t', TAB).splitlines()
#                     )
# 
#                     toolinfo = pad + toolinfo
#                 else:
#                     toolinfo = ' ' + toolinfo
# 
#                 self.output(location + message + toolinfo)
# 
#             self.output('')
# 
#         is_windows = sys.platform == 'win32'
#         if total_issues:
#             self.output(
#                 click.style(
#                     '{icon}{num_issues} issues found.'.format(  # noqa: @2to3
#                         icon='' if is_windows else '\u2717 ',  # noqa: @2to3
#                         num_issues=total_issues,
#                     ),
#                     fg='yellow',
#                     bold=True,
#                 )
#             )
#         else:
#             self.output(
#                 click.style(
#                     '{icon}No issues found!'.format(  # noqa: @2to3
#                         icon='' if is_windows else '\u2714 ',  # noqa: @2to3
#                     ),
#                     fg='green',
#                     bold=True,
#                 )
#             )


# Path: src/tidypy/plugin/pytest.py
import pytest
from ..config import get_project_config
from ..core import execute_tools
from ..reports.console import ConsoleReport

        action='store_true',
        dest='tidypy',
        default=False,
        help='Enable the TidyPy plugin.'
    )

    group.addoption(
        '--tidypy-project-path',
        action='store',
        dest='tidypy_project_path',
        default=None,
        help='The path to the base of the project to analyze with TidyPy.'
    )

    group.addoption(
        '--tidypy-fail-on-issue',
        action='store_true',
        dest='tidypy_fail_on_issue',
        default=False,
        help='Whether or not pytest should fail if TidyPy finds issues.'
    )


def pytest_configure(config):
    if config.getoption('tidypy'):
        if not config.pluginmanager.hasplugin('_tidypy'):
            plugin = TidyPyPlugin(config)
            config.pluginmanager.register(plugin, '_tidypy')



class PyTestReport(ConsoleReport):