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_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_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 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
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)
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)
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
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)
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
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
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
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)
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