示例#1
0
    def test_get_uncached_files(self, mock_os):
        file_path = os.path.join(self.caching_test_dir, 'test.c')
        cache = FileCache(self.log_printer, 'coala_test3', flush_cache=True)

        # Since this is a new FileCache object, the return must be the full set
        cache.current_time = 0
        mock_os.path.getmtime.return_value = 0
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.write()
        self.assertEqual(cache.get_uncached_files({file_path}), set())

        # Simulate changing the file and then getting uncached files
        # Since the file has been edited since the last run it's returned
        cache.current_time = 1
        mock_os.path.getmtime.return_value = 1
        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})
        cache.write()

        # Not changing the file should NOT return it the next time
        cache.current_time = 2
        self.assertEqual(cache.get_uncached_files({file_path}), set())
示例#2
0
    def test_get_uncached_files(self, mock_os):
        file_path = os.path.join(self.caching_test_dir, 'test.c')
        cache = FileCache(self.log_printer, 'coala_test3', flush_cache=True)

        # Since this is a new FileCache object, the return must be the full set
        cache.current_time = 0
        mock_os.path.getmtime.return_value = 0
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.write()
        self.assertEqual(cache.get_uncached_files({file_path}), set())

        # Simulate changing the file and then getting uncached files
        # Since the file has been edited since the last run it's returned
        cache.current_time = 1
        mock_os.path.getmtime.return_value = 1
        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})
        cache.write()

        # Not changing the file should NOT return it the next time
        cache.current_time = 2
        self.assertEqual(cache.get_uncached_files({file_path}), set())
示例#3
0
    def test_time_travel(self):
        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=True)
        cache.track_files({'file.c'})
        cache.write()
        self.assertTrue('file.c' in cache.data)

        cache_data = pickle_load(self.log_printer, 'coala_test2', {})
        # Back to the future :)
        cache_data['time'] = 2000000000
        pickle_dump(self.log_printer, 'coala_test2', cache_data)

        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=False)
        self.assertFalse('file.c' in cache.data)
示例#4
0
    def test_time_travel(self):
        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=True)
        cache.track_files({'file.c'})
        cache.write()
        self.assertTrue('file.c' in cache.data)

        cache_data = pickle_load(self.log_printer, 'coala_test2', {})
        # Back to the future :)
        cache_data['time'] = 2000000000
        pickle_dump(self.log_printer, 'coala_test2', cache_data)

        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=False)
        self.assertFalse('file.c' in cache.data)
示例#5
0
    def test_time_travel(self):
        cache = FileCache(self.log_printer, "coala_test2", flush_cache=True)
        cache.track_files({"file.c"})
        cache.write()
        self.assertTrue("file.c" in cache.data)

        cache_data = pickle_load(self.log_printer, "coala_test2", {})
        # Back to the future :)
        cache_data["time"] = 2000000000
        pickle_dump(self.log_printer, "coala_test2", cache_data)

        cache = FileCache(self.log_printer, "coala_test2", flush_cache=False)
        self.assertFalse("file.c" in cache.data)
示例#6
0
    def test_time_travel(self):
        cache = FileCache(self.log_printer, "coala_test2", flush_cache=True)
        cache.track_files({"file.c"})
        cache.write()
        self.assertTrue("file.c" in cache.data)

        cache_data = pickle_load(self.log_printer, "coala_test2", {})
        # Back to the future :)
        cache_data["time"] = 2000000000
        pickle_dump(self.log_printer, "coala_test2", cache_data)

        cache = FileCache(self.log_printer, "coala_test2", flush_cache=False)
        self.assertFalse("file.c" in cache.data)
示例#7
0
def run_coala(console_printer=None,
              log_printer=None,
              print_results=do_nothing,
              acquire_settings=fail_acquire_settings,
              print_section_beginning=do_nothing,
              nothing_done=do_nothing,
              autoapply=True,
              force_show_patch=False,
              arg_parser=None,
              arg_list=None):
    """
    This is a main method that should be usable for almost all purposes and
    reduces executing coala to one function call.

    :param console_printer:         Object to print messages on the console.
    :param log_printer:             A LogPrinter object to use for logging.
    :param print_results:           A callback that takes a LogPrinter, a
                                    section, a list of results to be printed,
                                    the file dict and the mutable file diff
                                    dict.
    :param acquire_settings:        The method to use for requesting settings.
                                    It will get a parameter which is a
                                    dictionary with the settings name as key
                                    and a list containing a description in [0]
                                    and the names of the bears who need this
                                    setting in all following indexes.
    :param print_section_beginning: A callback that will be called with a
                                    section name string whenever analysis of a
                                    new section is started.
    :param nothing_done:            A callback that will be called with only a
                                    log printer that shall indicate that
                                    nothing was done.
    :param autoapply:               Set this to false to not autoapply any
                                    actions. If you set this to `False`,
                                    `force_show_patch` will be ignored.
    :param force_show_patch:        If set to True, a patch will be always
                                    shown. (Using ApplyPatchAction.)
    :param arg_parser:              Instance of ArgParser that is used to parse
                                    non-setting arguments.
    :param arg_list:                The CLI argument list.
    :return:                        A dictionary containing a list of results
                                    for all analyzed sections as key.
    """

    log_printer = (LogPrinter(ConsolePrinter(), LOG_LEVEL.DEBUG)
                   if log_printer is None else log_printer)

    exitcode = 0
    results = {}
    file_dicts = {}
    try:
        yielded_results = yielded_unfixed_results = False
        did_nothing = True
        sections, local_bears, global_bears, targets = gather_configuration(
            acquire_settings,
            log_printer,
            arg_parser=arg_parser,
            arg_list=arg_list)

        log_printer.debug('Platform {} -- Python {}, coalib {}'.format(
            platform.system(), platform.python_version(), VERSION))

        settings_hash = get_settings_hash(sections, targets)
        flush_cache = bool(sections['cli'].get('flush_cache', False)
                           or settings_changed(log_printer, settings_hash))

        cache = None
        if not sections['cli'].get('disable_caching', False):
            cache = FileCache(log_printer, os.getcwd(), flush_cache)

        for section_name, section in sections.items():
            if not section.is_enabled(targets):
                continue

            if not autoapply:
                section['default_actions'] = ''
            elif force_show_patch:
                section['default_actions'] = '*: ShowPatchAction'
                section['show_result_on_top'] = 'yeah'

            print_section_beginning(section)
            section_result = execute_section(
                section=section,
                global_bear_list=global_bears[section_name],
                local_bear_list=local_bears[section_name],
                print_results=print_results,
                cache=cache,
                log_printer=log_printer,
                console_printer=console_printer)
            yielded, yielded_unfixed, results[section_name] = (
                simplify_section_result(section_result))

            yielded_results = yielded_results or yielded
            yielded_unfixed_results = (yielded_unfixed_results
                                       or yielded_unfixed)
            did_nothing = False

            file_dicts[section_name] = section_result[3]

        update_settings_db(log_printer, settings_hash)
        if cache:
            cache.write()

        if CounterHandler.get_num_calls_for_level('ERROR') > 0:
            exitcode = 1
        elif did_nothing:
            nothing_done(log_printer)
            exitcode = 2
        elif yielded_unfixed_results:
            exitcode = 1
        elif yielded_results:
            exitcode = 5
    except BaseException as exception:  # pylint: disable=broad-except
        exitcode = exitcode or get_exitcode(exception, log_printer)

    return results, exitcode, file_dicts
示例#8
0
class CachingTest(unittest.TestCase):
    def setUp(self):
        current_dir = os.path.split(__file__)[0]
        self.caching_test_dir = os.path.join(current_dir, 'caching_testfiles')
        self.log_printer = LogPrinter(NullPrinter())
        self.cache = FileCache(self.log_printer,
                               'coala_test',
                               flush_cache=True)

    def test_file_tracking(self):
        self.cache.track_files({'test.c', 'file.py'})
        self.assertEqual(self.cache.data, {'test.c': -1, 'file.py': -1})

        self.cache.untrack_files({'test.c'})
        self.cache.track_files({'test.c'})
        self.cache.write()
        self.assertFalse('test.c' in self.cache.data)
        self.assertTrue('file.py' in self.cache.data)

        self.cache.untrack_files({'test.c', 'file.py'})
        self.cache.write()
        self.assertFalse('test.c' in self.cache.data)
        self.assertFalse('file.py' in self.cache.data)

    def test_write(self):
        self.cache.track_files({'test2.c'})
        self.assertEqual(self.cache.data['test2.c'], -1)

        self.cache.write()
        self.assertNotEqual(self.cache.data['test2.c'], -1)

    @patch('coalib.misc.Caching.os')
    def test_get_uncached_files(self, mock_os):
        file_path = os.path.join(self.caching_test_dir, 'test.c')
        cache = FileCache(self.log_printer, 'coala_test3', flush_cache=True)

        # Since this is a new FileCache object, the return must be the full set
        cache.current_time = 0
        mock_os.path.getmtime.return_value = 0
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.write()
        self.assertEqual(cache.get_uncached_files({file_path}), set())

        # Simulate changing the file and then getting uncached files
        # Since the file has been edited since the last run it's returned
        cache.current_time = 1
        mock_os.path.getmtime.return_value = 1
        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})
        cache.write()

        # Not changing the file should NOT return it the next time
        cache.current_time = 2
        self.assertEqual(cache.get_uncached_files({file_path}), set())

    def test_persistence(self):
        with FileCache(self.log_printer, 'test3', flush_cache=True) as cache:
            cache.track_files({'file.c'})
        self.assertTrue('file.c' in cache.data)

        with FileCache(self.log_printer, 'test3', flush_cache=False) as cache:
            self.assertTrue('file.c' in cache.data)

    def test_time_travel(self):
        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=True)
        cache.track_files({'file.c'})
        cache.write()
        self.assertTrue('file.c' in cache.data)

        cache_data = pickle_load(self.log_printer, 'coala_test2', {})
        # Back to the future :)
        cache_data['time'] = 2000000000
        pickle_dump(self.log_printer, 'coala_test2', cache_data)

        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=False)
        self.assertFalse('file.c' in cache.data)

    def test_caching_results(self):
        """
        A simple integration test to assert that results are not dropped
        when coala is ran multiple times with caching enabled.
        """
        with bear_test_module(), \
                prepare_file(['a=(5,6)'], None) as (lines, filename):
            with simulate_console_inputs('n'):
                retval, stdout, stderr = execute_coala(
                    coala.main, 'coala', '-c', os.devnull, '--disable-caching',
                    '--flush-cache', '-f', filename, '-b', 'LineCountTestBear',
                    '-L', 'DEBUG')
                self.assertIn('This file has', stdout)
                self.assertIn('Running bear LineCountTestBear', stderr)

            # Due to the change in configuration from the removal of
            # ``--flush-cache`` this run will not be sufficient to
            # assert this behavior.
            retval, stdout, stderr = execute_coala(coala.main, 'coala',
                                                   '--non-interactive',
                                                   '--no-color', '-c',
                                                   os.devnull, '-f', filename,
                                                   '-b', 'LineCountTestBear')
            self.assertIn('This file has', stdout)
            self.assertEqual(1, len(stderr.splitlines()))
            self.assertIn(
                'LineCountTestBear: This result has no patch attached.',
                stderr)

            retval, stdout, stderr = execute_coala(coala.main, 'coala',
                                                   '--non-interactive',
                                                   '--no-color', '-c',
                                                   os.devnull, '-f', filename,
                                                   '-b', 'LineCountTestBear')
            self.assertIn('This file has', stdout)
            self.assertEqual(1, len(stderr.splitlines()))
            self.assertIn(
                'LineCountTestBear: This result has no patch attached.',
                stderr)

    def test_caching_multi_results(self):
        """
        Integration test to assert that results are not dropped when coala is
        ran multiple times with caching enabled and one section yields a result
        and second one doesn't.
        """
        filename = 'tests/misc/test_caching_multi_results/'
        with bear_test_module():
            with simulate_console_inputs('n'):
                retval, stdout, stderr = execute_coala(coala.main, 'coala',
                                                       '-c',
                                                       filename + '.coafile',
                                                       '-f',
                                                       filename + 'test.py')
                self.assertIn('This file has', stdout)
                self.assertIn(
                    'Implicit \'Default\' section inheritance is deprecated',
                    stderr)

            retval, stdout, stderr = execute_coala(coala.main, 'coala',
                                                   '--non-interactive',
                                                   '--no-color', '-c',
                                                   filename + '.coafile', '-f',
                                                   filename + 'test.py')
            self.assertIn('This file has', stdout)
            self.assertEqual(2, len(stderr.splitlines()))
            self.assertIn(
                'LineCountTestBear: This result has no patch attached.',
                stderr)
            self.assertIn(
                'Implicit \'Default\' section inheritance is deprecated',
                stderr)
示例#9
0
class CachingTest(unittest.TestCase):

    def setUp(self):
        current_dir = os.path.split(__file__)[0]
        self.caching_test_dir = os.path.join(
            current_dir,
            'caching_testfiles')
        self.log_printer = LogPrinter(NullPrinter())
        self.cache = FileCache(self.log_printer, 'coala_test', flush_cache=True)

    def test_file_tracking(self):
        self.cache.track_files({'test.c', 'file.py'})
        self.assertEqual(self.cache.data, {'test.c': -1, 'file.py': -1})

        self.cache.untrack_files({'test.c'})
        self.cache.track_files({'test.c'})
        self.cache.write()
        self.assertFalse('test.c' in self.cache.data)
        self.assertTrue('file.py' in self.cache.data)

        self.cache.untrack_files({'test.c', 'file.py'})
        self.cache.write()
        self.assertFalse('test.c' in self.cache.data)
        self.assertFalse('file.py' in self.cache.data)

    def test_write(self):
        self.cache.track_files({'test2.c'})
        self.assertEqual(self.cache.data['test2.c'], -1)

        self.cache.write()
        self.assertNotEqual(self.cache.data['test2.c'], -1)

    @patch('coalib.misc.Caching.os')
    def test_get_uncached_files(self, mock_os):
        file_path = os.path.join(self.caching_test_dir, 'test.c')
        cache = FileCache(self.log_printer, 'coala_test3', flush_cache=True)

        # Since this is a new FileCache object, the return must be the full set
        cache.current_time = 0
        mock_os.path.getmtime.return_value = 0
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.write()
        self.assertEqual(cache.get_uncached_files({file_path}), set())

        # Simulate changing the file and then getting uncached files
        # Since the file has been edited since the last run it's returned
        cache.current_time = 1
        mock_os.path.getmtime.return_value = 1
        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})
        cache.write()

        # Not changing the file should NOT return it the next time
        cache.current_time = 2
        self.assertEqual(cache.get_uncached_files({file_path}), set())

    def test_persistence(self):
        with FileCache(self.log_printer, 'test3', flush_cache=True) as cache:
            cache.track_files({'file.c'})
        self.assertTrue('file.c' in cache.data)

        with FileCache(self.log_printer, 'test3', flush_cache=False) as cache:
            self.assertTrue('file.c' in cache.data)

    def test_time_travel(self):
        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=True)
        cache.track_files({'file.c'})
        cache.write()
        self.assertTrue('file.c' in cache.data)

        cache_data = pickle_load(self.log_printer, 'coala_test2', {})
        # Back to the future :)
        cache_data['time'] = 2000000000
        pickle_dump(self.log_printer, 'coala_test2', cache_data)

        cache = FileCache(self.log_printer, 'coala_test2', flush_cache=False)
        self.assertFalse('file.c' in cache.data)

    def test_caching_results(self):
        """
        A simple integration test to assert that results are not dropped
        when coala is ran multiple times with caching enabled.
        """
        with bear_test_module():
            with prepare_file(['a=(5,6)'], None) as (lines, filename):
                with simulate_console_inputs('n'):
                    retval, stdout, stderr = execute_coala(
                        coala.main,
                        'coala',
                        '-c', os.devnull,
                        '--disable-caching',
                        '--flush-cache',
                        '-f', filename,
                        '-b', 'LineCountTestBear',
                        '-L', 'DEBUG')
                    self.assertIn('This file has', stdout)
                    self.assertIn('Running bear LineCountTestBear', stderr)

                # Due to the change in configuration from the removal of
                # ``--flush-cache`` this run will not be sufficient to
                # assert this behavior.
                retval, stdout, stderr = execute_coala(
                    coala.main,
                    'coala',
                    '--non-interactive', '--no-color',
                    '-c', os.devnull,
                    '-f', filename,
                    '-b', 'LineCountTestBear')
                self.assertIn('This file has', stdout)
                self.assertEqual(1, len(stderr.splitlines()))
                self.assertIn(
                    'LineCountTestBear: This result has no patch attached.',
                    stderr)

                retval, stdout, stderr = execute_coala(
                    coala.main,
                    'coala',
                    '--non-interactive', '--no-color',
                    '-c', os.devnull,
                    '-f', filename,
                    '-b', 'LineCountTestBear')
                self.assertIn('This file has', stdout)
                self.assertEqual(1, len(stderr.splitlines()))
                self.assertIn(
                    'LineCountTestBear: This result has no patch attached.',
                    stderr)

    def test_caching_multi_results(self):
        """
        Integration test to assert that results are not dropped when coala is
        ran multiple times with caching enabled and one section yields a result
        and second one doesn't.
        """
        filename = 'tests/misc/test_caching_multi_results/'
        with bear_test_module():
            with simulate_console_inputs('n'):
                retval, stdout, stderr = execute_coala(
                   coala.main,
                   'coala',
                   '-c', filename + '.coafile',
                   '-f', filename + 'test.py')
                self.assertIn('This file has', stdout)
                self.assertIn(
                    'Implicit \'Default\' section inheritance is deprecated',
                    stderr)

            retval, stdout, stderr = execute_coala(
               coala.main,
               'coala',
               '--non-interactive', '--no-color',
               '-c', filename + '.coafile',
               '-f', filename + 'test.py')
            self.assertIn('This file has', stdout)
            self.assertEqual(2, len(stderr.splitlines()))
            self.assertIn(
                'LineCountTestBear: This result has no patch attached.',
                stderr)
            self.assertIn(
                'Implicit \'Default\' section inheritance is deprecated',
                stderr)
示例#10
0
def run_coala(log_printer=None,
              print_results=do_nothing,
              acquire_settings=fail_acquire_settings,
              print_section_beginning=do_nothing,
              nothing_done=do_nothing,
              autoapply=True,
              arg_parser=None):
    """
    This is a main method that should be usable for almost all purposes and
    reduces executing coala to one function call.

    :param log_printer:             A LogPrinter object to use for logging.
    :param print_results:           A callback that takes a LogPrinter, a
                                    section, a list of results to be printed,
                                    the file dict and the mutable file diff
                                    dict.
    :param acquire_settings:        The method to use for requesting settings.
                                    It will get a parameter which is a
                                    dictionary with the settings name as key
                                    and a list containing a description in [0]
                                    and the names of the bears who need this
                                    setting in all following indexes.
    :param print_section_beginning: A callback that will be called with a
                                    section name string whenever analysis of a
                                    new section is started.
    :param nothing_done:            A callback that will be called with only a
                                    log printer that shall indicate that
                                    nothing was done.
    :param autoapply:               Set to False to autoapply nothing by
                                    default; this is overridable via any
                                    configuration file/CLI.
    :return:                        A dictionary containing a list of results
                                    for all analyzed sections as key.
    """
    log_printer = log_printer or LogPrinter(ConsolePrinter(), LOG_LEVEL.DEBUG)

    exitcode = 0
    results = {}
    file_dicts = {}
    try:
        yielded_results = yielded_unfixed_results = False
        did_nothing = True
        sections, local_bears, global_bears, targets = gather_configuration(
            acquire_settings,
            log_printer,
            autoapply=autoapply,
            arg_parser=arg_parser)

        log_printer.debug("Platform {} -- Python {}, pip {}, coalib {}"
                          .format(platform.system(), platform.python_version(),
                                  pip.__version__, VERSION))

        config_file = os.path.abspath(str(sections["default"].get("config")))

        settings_hash = get_settings_hash(sections)
        flush_cache = bool(sections["default"].get("flush_cache", False) or
                           settings_changed(log_printer, settings_hash))

        cache = FileCache(log_printer, os.getcwd(), flush_cache)
        for section_name, section in sections.items():
            if not section.is_enabled(targets):
                continue

            print_section_beginning(section)
            section_result = execute_section(
                section=section,
                global_bear_list=global_bears[section_name],
                local_bear_list=local_bears[section_name],
                print_results=print_results,
                cache=cache,
                log_printer=log_printer)
            yielded, yielded_unfixed, results[section_name] = (
                simplify_section_result(section_result))

            yielded_results = yielded_results or yielded
            yielded_unfixed_results = (
                yielded_unfixed_results or yielded_unfixed)
            did_nothing = False

            file_dicts[section_name] = section_result[3]

        update_settings_db(log_printer, settings_hash)
        if sections["default"].get("changed_files", False):
            cache.write()

        if did_nothing:
            nothing_done(log_printer)
        elif yielded_unfixed_results:
            exitcode = 1
        elif yielded_results:
            exitcode = 5
    except BaseException as exception:  # pylint: disable=broad-except
        exitcode = exitcode or get_exitcode(exception, log_printer)

    return results, exitcode, file_dicts
示例#11
0
class CachingTest(unittest.TestCase):
    def setUp(self):
        current_dir = os.path.split(__file__)[0]
        self.caching_test_dir = os.path.join(current_dir, "caching_testfiles")
        self.log_printer = LogPrinter(NullPrinter())
        self.cache = FileCache(self.log_printer,
                               "coala_test",
                               flush_cache=True)

    def test_file_tracking(self):
        self.cache.track_files({"test.c", "file.py"})
        self.assertEqual(self.cache.data, {"test.c": -1, "file.py": -1})

        self.cache.untrack_files({"test.c"})
        self.assertFalse("test.c" in self.cache.data)
        self.assertTrue("file.py" in self.cache.data)

        self.cache.untrack_files({"test.c", "file.py"})
        self.assertFalse("test.c" in self.cache.data)
        self.assertFalse("file.py" in self.cache.data)

    def test_write(self):
        self.cache.track_files({"test2.c"})
        self.assertEqual(self.cache.data["test2.c"], -1)

        self.cache.write()
        self.assertNotEqual(self.cache.data["test2.c"], -1)

    @patch('coalib.misc.Caching.os')
    def test_get_uncached_files(self, mock_os):
        file_path = os.path.join(self.caching_test_dir, "test.c")
        cache = FileCache(self.log_printer, "coala_test3", flush_cache=True)

        # Since this is a new FileCache object, the return must be the full set
        cache.current_time = 0
        mock_os.path.getmtime.return_value = 0
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.write()
        self.assertEqual(cache.get_uncached_files({file_path}), set())

        # Simulate changing the file and then getting uncached files
        # Since the file has been edited since the last run it's returned
        cache.current_time = 1
        mock_os.path.getmtime.return_value = 1
        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})
        cache.write()

        # Not changing the file should NOT return it the next time
        cache.current_time = 2
        self.assertEqual(cache.get_uncached_files({file_path}), set())

    def test_persistence(self):
        with FileCache(self.log_printer, "test3", flush_cache=True) as cache:
            cache.track_files({"file.c"})
        self.assertTrue("file.c" in cache.data)

        with FileCache(self.log_printer, "test3", flush_cache=False) as cache:
            self.assertTrue("file.c" in cache.data)

    def test_time_travel(self):
        cache = FileCache(self.log_printer, "coala_test2", flush_cache=True)
        cache.track_files({"file.c"})
        cache.write()
        self.assertTrue("file.c" in cache.data)

        cache_data = pickle_load(self.log_printer, "coala_test2", {})
        # Back to the future :)
        cache_data["time"] = 2000000000
        pickle_dump(self.log_printer, "coala_test2", cache_data)

        cache = FileCache(self.log_printer, "coala_test2", flush_cache=False)
        self.assertFalse("file.c" in cache.data)

    def test_caching_results(self):
        """
        A simple integration test to assert that results are not dropped
        when coala is ran multiple times with caching enabled.
        """
        with bear_test_module(), \
                prepare_file(["a=(5,6)"], None) as (lines, filename):
            with simulate_console_inputs("0"):
                retval, output = execute_coala(coala.main, "coala", "-c",
                                               os.devnull, "--disable-caching",
                                               "--flush-cache", "-f",
                                               re.escape(filename), "-b",
                                               "LineCountTestBear", "-L",
                                               "DEBUG")
                self.assertIn("This file has", output)

            # Due to the change in configuration from the removal of
            # ``--flush-cache`` this run will not be sufficient to
            # assert this behavior.
            retval, output = execute_coala(coala.main, "coala",
                                           "-c", os.devnull, "-f",
                                           re.escape(filename), "-b",
                                           "LineCountTestBear")
            self.assertIn("This file has", output)

            retval, output = execute_coala(coala.main, "coala",
                                           "-c", os.devnull, "-f",
                                           re.escape(filename), "-b",
                                           "LineCountTestBear")
            self.assertIn("This file has", output)
示例#12
0
def run_coala(log_printer=None,
              print_results=do_nothing,
              acquire_settings=fail_acquire_settings,
              print_section_beginning=do_nothing,
              nothing_done=do_nothing,
              autoapply=True,
              arg_parser=None,
              arg_list=None):
    """
    This is a main method that should be usable for almost all purposes and
    reduces executing coala to one function call.

    :param log_printer:             A LogPrinter object to use for logging.
    :param print_results:           A callback that takes a LogPrinter, a
                                    section, a list of results to be printed,
                                    the file dict and the mutable file diff
                                    dict.
    :param acquire_settings:        The method to use for requesting settings.
                                    It will get a parameter which is a
                                    dictionary with the settings name as key
                                    and a list containing a description in [0]
                                    and the names of the bears who need this
                                    setting in all following indexes.
    :param print_section_beginning: A callback that will be called with a
                                    section name string whenever analysis of a
                                    new section is started.
    :param nothing_done:            A callback that will be called with only a
                                    log printer that shall indicate that
                                    nothing was done.
    :param autoapply:               Set to False to autoapply nothing by
                                    default; this is overridable via any
                                    configuration file/CLI.
    :param arg_list:                The CLI argument list.
    :return:                        A dictionary containing a list of results
                                    for all analyzed sections as key.
    """
    configure_logging()

    log_printer = (LogPrinter(ConsolePrinter(), LOG_LEVEL.DEBUG)
                   if log_printer is None else log_printer)

    exitcode = 0
    results = {}
    file_dicts = {}
    try:
        yielded_results = yielded_unfixed_results = False
        did_nothing = True
        sections, local_bears, global_bears, targets = gather_configuration(
            acquire_settings,
            log_printer,
            autoapply=autoapply,
            arg_parser=arg_parser,
            arg_list=arg_list)

        log_printer.debug("Platform {} -- Python {}, pip {}, coalib {}".format(
            platform.system(), platform.python_version(), pip.__version__,
            VERSION))

        config_file = os.path.abspath(str(sections["default"].get("config")))

        settings_hash = get_settings_hash(sections, targets)
        flush_cache = bool(sections["default"].get("flush_cache", False)
                           or settings_changed(log_printer, settings_hash))

        disable_caching = bool(sections["default"].get("disable_caching",
                                                       False))
        cache = None
        if not sections["default"].get("disable_caching", False):
            cache = FileCache(log_printer, os.getcwd(), flush_cache)

        for section_name, section in sections.items():
            if not section.is_enabled(targets):
                continue

            print_section_beginning(section)
            section_result = execute_section(
                section=section,
                global_bear_list=global_bears[section_name],
                local_bear_list=local_bears[section_name],
                print_results=print_results,
                cache=cache,
                log_printer=log_printer)
            yielded, yielded_unfixed, results[section_name] = (
                simplify_section_result(section_result))

            yielded_results = yielded_results or yielded
            yielded_unfixed_results = (yielded_unfixed_results
                                       or yielded_unfixed)
            did_nothing = False

            file_dicts[section_name] = section_result[3]

        update_settings_db(log_printer, settings_hash)
        if cache:
            cache.write()

        if did_nothing:
            nothing_done(log_printer)
        elif yielded_unfixed_results:
            exitcode = 1
        elif yielded_results:
            exitcode = 5
    except BaseException as exception:  # pylint: disable=broad-except
        exitcode = exitcode or get_exitcode(exception, log_printer)

    return results, exitcode, file_dicts
示例#13
0
def run_coala(console_printer=None,
              log_printer=None,
              print_results=do_nothing,
              acquire_settings=fail_acquire_settings,
              print_section_beginning=do_nothing,
              nothing_done=do_nothing,
              autoapply=True,
              force_show_patch=False,
              arg_parser=None,
              arg_list=None,
              args=None,
              debug=False):
    """
    This is a main method that should be usable for almost all purposes and
    reduces executing coala to one function call.

    :param console_printer:         Object to print messages on the console.
    :param log_printer:             A LogPrinter object to use for logging.
    :param print_results:           A callback that takes a LogPrinter, a
                                    section, a list of results to be printed,
                                    the file dict and the mutable file diff
                                    dict.
    :param acquire_settings:        The method to use for requesting settings.
                                    It will get a parameter which is a
                                    dictionary with the settings name as key
                                    and a list containing a description in [0]
                                    and the names of the bears who need this
                                    setting in all following indexes.
    :param print_section_beginning: A callback that will be called with a
                                    section name string whenever analysis of a
                                    new section is started.
    :param nothing_done:            A callback that will be called with only a
                                    log printer that shall indicate that
                                    nothing was done.
    :param autoapply:               Set this to false to not autoapply any
                                    actions. If you set this to `False`,
                                    `force_show_patch` will be ignored.
    :param force_show_patch:        If set to True, a patch will be always
                                    shown. (Using ApplyPatchAction.)
    :param arg_parser:              Instance of ArgParser that is used to parse
                                    non-setting arguments.
    :param arg_list:                The CLI argument list.
    :param args:                    Alternative pre-parsed CLI arguments.
    :param debug:                   Run in debug mode, bypassing
                                    multiprocessing, and not catching any
                                    exceptions.
    :return:                        A dictionary containing a list of results
                                    for all analyzed sections as key.
    """
    all_actions_possible = provide_all_actions()
    apply_single = None
    if getattr(args, 'single_action', None) is not None:
        while True:
            for i, action in enumerate(all_actions_possible, 1):
                console_printer.print(
                    format_lines('{}'.format(action), symbol='['))

            line = format_lines(STR_ENTER_NUMBER, symbol='[')

            choice = input(line)

            if choice.isalpha():
                choice = choice.upper()
                choice = '(' + choice + ')'
                if choice == '(N)':
                    apply_single = 'Do (N)othing'
                    break
                for i, action in enumerate(all_actions_possible, 1):
                    if choice in action:
                        apply_single = action
                        break
                if apply_single:
                    break
                console_printer.print(
                    format_lines('Please enter a valid letter.', symbol='['))

        args.apply_patch = False

    log_printer = (LogPrinter(ConsolePrinter(), LOG_LEVEL.DEBUG)
                   if log_printer is None else log_printer)

    exitcode = 0
    sections = {}
    results = {}
    file_dicts = {}
    try:
        yielded_results = yielded_unfixed_results = False
        did_nothing = True
        sections, local_bears, global_bears, targets = gather_configuration(
            acquire_settings,
            log_printer,
            arg_parser=arg_parser,
            arg_list=arg_list,
            args=args)

        log_printer.debug('Platform {} -- Python {}, coalib {}'.format(
            platform.system(), platform.python_version(), VERSION))

        settings_hash = get_settings_hash(sections, targets)
        flush_cache = bool(sections['cli'].get('flush_cache', False)
                           or settings_changed(log_printer, settings_hash))

        cache = None
        if not sections['cli'].get('disable_caching', False):
            cache = FileCache(log_printer, os.getcwd(), flush_cache)

        for section_name, section in sections.items():
            if not section.is_enabled(targets):
                continue

            if not autoapply:
                section['default_actions'] = ''
            elif force_show_patch:
                section['default_actions'] = '*: ShowPatchAction'
                section['show_result_on_top'] = 'yeah'

            print_section_beginning(section)
            section_result = execute_section(
                section=section,
                global_bear_list=global_bears[section_name],
                local_bear_list=local_bears[section_name],
                print_results=print_results,
                cache=cache,
                log_printer=log_printer,
                console_printer=console_printer,
                debug=debug or args and args.debug,
                apply_single=(apply_single
                              if apply_single is not None else False))
            yielded, yielded_unfixed, results[section_name] = (
                simplify_section_result(section_result))

            yielded_results = yielded_results or yielded
            yielded_unfixed_results = (yielded_unfixed_results
                                       or yielded_unfixed)
            did_nothing = False

            file_dicts[section_name] = section_result[3]

        update_settings_db(log_printer, settings_hash)
        if cache:
            cache.write()

        if CounterHandler.get_num_calls_for_level('ERROR') > 0:
            exitcode = 1
        elif did_nothing:
            nothing_done(log_printer)
            exitcode = 2
        elif yielded_unfixed_results:
            exitcode = 1
        elif yielded_results:
            exitcode = 5
    except BaseException as exception:  # pylint: disable=broad-except
        if not isinstance(exception, SystemExit):
            if args and args.debug or (sections and sections.get(
                    'cli', {}).get('debug', False)):
                import ipdb
                with ipdb.launch_ipdb_on_exception():
                    raise

            if debug:
                raise

        exitcode = exitcode or get_exitcode(exception, log_printer)

    return results, exitcode, file_dicts
示例#14
0
def run_coala(console_printer=None,
              log_printer=None,
              print_results=do_nothing,
              acquire_settings=fail_acquire_settings,
              print_section_beginning=do_nothing,
              nothing_done=do_nothing,
              autoapply=True,
              force_show_patch=False,
              arg_parser=None,
              arg_list=None):
    """
    This is a main method that should be usable for almost all purposes and
    reduces executing coala to one function call.

    :param console_printer:         Object to print messages on the console.
    :param log_printer:             A LogPrinter object to use for logging.
    :param print_results:           A callback that takes a LogPrinter, a
                                    section, a list of results to be printed,
                                    the file dict and the mutable file diff
                                    dict.
    :param acquire_settings:        The method to use for requesting settings.
                                    It will get a parameter which is a
                                    dictionary with the settings name as key
                                    and a list containing a description in [0]
                                    and the names of the bears who need this
                                    setting in all following indexes.
    :param print_section_beginning: A callback that will be called with a
                                    section name string whenever analysis of a
                                    new section is started.
    :param nothing_done:            A callback that will be called with only a
                                    log printer that shall indicate that
                                    nothing was done.
    :param autoapply:               Set this to false to not autoapply any
                                    actions. If you set this to `False`,
                                    `force_show_patch` will be ignored.
    :param force_show_patch:        If set to True, a patch will be always
                                    shown. (Using ApplyPatchAction.)
    :param arg_parser:              Instance of ArgParser that is used to parse
                                    non-setting arguments.
    :param arg_list:                The CLI argument list.
    :return:                        A dictionary containing a list of results
                                    for all analyzed sections as key.
    """

    log_printer = (
        LogPrinter(ConsolePrinter(), LOG_LEVEL.DEBUG) if log_printer is None
        else log_printer)

    exitcode = 0
    results = {}
    file_dicts = {}
    try:
        yielded_results = yielded_unfixed_results = False
        did_nothing = True
        sections, local_bears, global_bears, targets = gather_configuration(
            acquire_settings,
            log_printer,
            arg_parser=arg_parser,
            arg_list=arg_list)

        log_printer.debug('Platform {} -- Python {}, coalib {}'
                          .format(platform.system(), platform.python_version(),
                                  VERSION))

        settings_hash = get_settings_hash(sections, targets)
        flush_cache = bool(sections['cli'].get('flush_cache', False) or
                           settings_changed(log_printer, settings_hash))

        cache = None
        if not sections['cli'].get('disable_caching', False):
            cache = FileCache(log_printer, os.getcwd(), flush_cache)

        for section_name, section in sections.items():
            if not section.is_enabled(targets):
                continue

            if not autoapply:
                section['default_actions'] = ''
            elif force_show_patch:
                section['default_actions'] = '*: ShowPatchAction'
                section['show_result_on_top'] = 'yeah'

            print_section_beginning(section)
            section_result = execute_section(
                section=section,
                global_bear_list=global_bears[section_name],
                local_bear_list=local_bears[section_name],
                print_results=print_results,
                cache=cache,
                log_printer=log_printer,
                console_printer=console_printer)
            yielded, yielded_unfixed, results[section_name] = (
                simplify_section_result(section_result))

            yielded_results = yielded_results or yielded
            yielded_unfixed_results = (
                yielded_unfixed_results or yielded_unfixed)
            did_nothing = False

            file_dicts[section_name] = section_result[3]

        update_settings_db(log_printer, settings_hash)
        if cache:
            cache.write()

        if did_nothing:
            nothing_done(log_printer)
            exitcode = 2
        elif yielded_unfixed_results:
            exitcode = 1
        elif yielded_results:
            exitcode = 5
    except BaseException as exception:  # pylint: disable=broad-except
        exitcode = exitcode or get_exitcode(exception, log_printer)

    return results, exitcode, file_dicts
示例#15
0
class CachingTest(unittest.TestCase):

    def setUp(self):
        current_dir = os.path.split(__file__)[0]
        self.caching_test_dir = os.path.join(
            current_dir,
            "caching_testfiles")
        self.log_printer = LogPrinter(NullPrinter())
        self.cache = FileCache(self.log_printer, "coala_test", flush_cache=True)

    def test_file_tracking(self):
        self.cache.track_files({"test.c", "file.py"})
        self.assertEqual(self.cache.data, {"test.c": -1, "file.py": -1})

        self.cache.untrack_files({"test.c"})
        self.cache.track_files({"test.c"})
        self.cache.write()
        self.assertFalse("test.c" in self.cache.data)
        self.assertTrue("file.py" in self.cache.data)

        self.cache.untrack_files({"test.c", "file.py"})
        self.cache.write()
        self.assertFalse("test.c" in self.cache.data)
        self.assertFalse("file.py" in self.cache.data)

    def test_write(self):
        self.cache.track_files({"test2.c"})
        self.assertEqual(self.cache.data["test2.c"], -1)

        self.cache.write()
        self.assertNotEqual(self.cache.data["test2.c"], -1)

    @patch('coalib.misc.Caching.os')
    def test_get_uncached_files(self, mock_os):
        file_path = os.path.join(self.caching_test_dir, "test.c")
        cache = FileCache(self.log_printer, "coala_test3", flush_cache=True)

        # Since this is a new FileCache object, the return must be the full set
        cache.current_time = 0
        mock_os.path.getmtime.return_value = 0
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})

        cache.write()
        self.assertEqual(cache.get_uncached_files({file_path}), set())

        # Simulate changing the file and then getting uncached files
        # Since the file has been edited since the last run it's returned
        cache.current_time = 1
        mock_os.path.getmtime.return_value = 1
        cache.track_files({file_path})
        self.assertEqual(cache.get_uncached_files({file_path}), {file_path})
        cache.write()

        # Not changing the file should NOT return it the next time
        cache.current_time = 2
        self.assertEqual(cache.get_uncached_files({file_path}), set())

    def test_persistence(self):
        with FileCache(self.log_printer, "test3", flush_cache=True) as cache:
            cache.track_files({"file.c"})
        self.assertTrue("file.c" in cache.data)

        with FileCache(self.log_printer, "test3", flush_cache=False) as cache:
            self.assertTrue("file.c" in cache.data)

    def test_time_travel(self):
        cache = FileCache(self.log_printer, "coala_test2", flush_cache=True)
        cache.track_files({"file.c"})
        cache.write()
        self.assertTrue("file.c" in cache.data)

        cache_data = pickle_load(self.log_printer, "coala_test2", {})
        # Back to the future :)
        cache_data["time"] = 2000000000
        pickle_dump(self.log_printer, "coala_test2", cache_data)

        cache = FileCache(self.log_printer, "coala_test2", flush_cache=False)
        self.assertFalse("file.c" in cache.data)

    def test_caching_results(self):
        """
        A simple integration test to assert that results are not dropped
        when coala is ran multiple times with caching enabled.
        """
        with bear_test_module(), \
                prepare_file(["a=(5,6)"], None) as (lines, filename):
            with simulate_console_inputs("0"):
                retval, output = execute_coala(
                    coala.main,
                    "coala",
                    "-c", os.devnull,
                    "--disable-caching",
                    "--flush-cache",
                    "-f", re.escape(filename),
                    "-b", "LineCountTestBear",
                    "-L", "DEBUG")
                self.assertIn("This file has", output)

            # Due to the change in configuration from the removal of
            # ``--flush-cache`` this run will not be sufficient to
            # assert this behavior.
            retval, output = execute_coala(
                coala.main,
                "coala",
                "-c", os.devnull,
                "-f", re.escape(filename),
                "-b", "LineCountTestBear")
            self.assertIn("This file has", output)

            retval, output = execute_coala(
                coala.main,
                "coala",
                "-c", os.devnull,
                "-f", re.escape(filename),
                "-b", "LineCountTestBear")
            self.assertIn("This file has", output)

    def test_caching_multi_results(self):
        """
        Integration test to assert that results are not dropped when coala is
        ran multiple times with caching enabled and one section yields a result
        and second one doesn't.
        """
        filename = "tests/misc/test_caching_multi_results/"
        with bear_test_module():
            with simulate_console_inputs("0"):
                retval, output = execute_coala(
                   coala.main,
                   "coala",
                   "-c", filename + ".coafile",
                   "-f", filename + "test.py")
                self.assertIn("This file has", output)

            retval, output = execute_coala(
               coala.main,
               "coala",
               "-c", filename + ".coafile",
               "-f", filename + "test.py")
            self.assertIn("This file has", output)
示例#16
0
def run_coala(console_printer=None,
              log_printer=None,
              print_results=do_nothing,
              acquire_settings=fail_acquire_settings,
              print_section_beginning=do_nothing,
              nothing_done=do_nothing,
              autoapply=True,
              force_show_patch=False,
              arg_parser=None,
              arg_list=None,
              args=None,
              debug=False):
    """
    This is a main method that should be usable for almost all purposes and
    reduces executing coala to one function call.

    :param console_printer:         Object to print messages on the console.
    :param log_printer:             A LogPrinter object to use for logging.
    :param print_results:           A callback that takes a LogPrinter, a
                                    section, a list of results to be printed,
                                    the file dict and the mutable file diff
                                    dict.
    :param acquire_settings:        The method to use for requesting settings.
                                    It will get a parameter which is a
                                    dictionary with the settings name as key
                                    and a list containing a description in [0]
                                    and the names of the bears who need this
                                    setting in all following indexes.
    :param print_section_beginning: A callback that will be called with a
                                    section name string whenever analysis of a
                                    new section is started.
    :param nothing_done:            A callback that will be called with only a
                                    log printer that shall indicate that
                                    nothing was done.
    :param autoapply:               Set this to false to not autoapply any
                                    actions. If you set this to `False`,
                                    `force_show_patch` will be ignored.
    :param force_show_patch:        If set to True, a patch will be always
                                    shown. (Using ApplyPatchAction.)
    :param arg_parser:              Instance of ArgParser that is used to parse
                                    non-setting arguments.
    :param arg_list:                The CLI argument list.
    :param args:                    Alternative pre-parsed CLI arguments.
    :param debug:                   Run in debug mode, bypassing
                                    multiprocessing, and not catching any
                                    exceptions.
    :return:                        A dictionary containing a list of results
                                    for all analyzed sections as key.
    """
    all_actions_possible = provide_all_actions()
    apply_single = None
    if getattr(args, 'single_action', None) is not None:
        while True:
            for i, action in enumerate(all_actions_possible, 1):
                console_printer.print(format_lines('{}'.format(
                    action), symbol='['))

            line = format_lines(STR_ENTER_NUMBER, symbol='[')

            choice = input(line)

            if choice.isalpha():
                choice = choice.upper()
                choice = '(' + choice + ')'
                if choice == '(N)':
                    apply_single = 'Do (N)othing'
                    break
                for i, action in enumerate(all_actions_possible, 1):
                    if choice in action:
                        apply_single = action
                        break
                if apply_single:
                    break
                console_printer.print(format_lines(
                                    'Please enter a valid letter.',
                                    symbol='['))

        args.apply_patch = False

    exitcode = 0
    sections = {}
    results = {}
    file_dicts = {}
    try:
        yielded_results = yielded_unfixed_results = False
        did_nothing = True
        sections, local_bears, global_bears, targets = gather_configuration(
            acquire_settings,
            arg_parser=arg_parser,
            arg_list=arg_list,
            args=args)

        logging.debug('Platform {} -- Python {}, coalib {}'
                      .format(platform.system(), platform.python_version(),
                              VERSION))

        settings_hash = get_settings_hash(sections, targets)
        flush_cache = bool(sections['cli'].get('flush_cache', False) or
                           settings_changed(None, settings_hash))

        cache = None
        if not sections['cli'].get('disable_caching', False):
            cache = FileCache(None, os.getcwd(), flush_cache)

        for section_name, section in sections.items():
            if not section.is_enabled(targets):
                continue

            if not autoapply:
                section['default_actions'] = ''
            elif force_show_patch:
                section['default_actions'] = '*: ShowPatchAction'
                section['show_result_on_top'] = 'yeah'

            print_section_beginning(section)
            section_result = execute_section(
                section=section,
                global_bear_list=global_bears[section_name],
                local_bear_list=local_bears[section_name],
                print_results=print_results,
                cache=cache,
                log_printer=None,
                console_printer=console_printer,
                debug=debug or args and args.debug,
                apply_single=(apply_single
                              if apply_single is not None else
                              False))
            yielded, yielded_unfixed, results[section_name] = (
                simplify_section_result(section_result))

            yielded_results = yielded_results or yielded
            yielded_unfixed_results = (
                yielded_unfixed_results or yielded_unfixed)
            did_nothing = False

            file_dicts[section_name] = section_result[3]

        update_settings_db(None, settings_hash)
        if cache:
            cache.write()

        if CounterHandler.get_num_calls_for_level('ERROR') > 0:
            exitcode = 1
        elif did_nothing:
            nothing_done(None)
            exitcode = 2
        elif yielded_unfixed_results:
            exitcode = 1
        elif yielded_results:
            exitcode = 5
    except BaseException as exception:  # pylint: disable=broad-except
        if not isinstance(exception, SystemExit):
            if args and args.debug or (
                    sections and sections.get('cli', {}).get('debug', False)
            ):
                import ipdb
                with ipdb.launch_ipdb_on_exception():
                    raise

            if debug:
                raise

        exitcode = exitcode or get_exitcode(exception)

    return results, exitcode, file_dicts