def test_failed_recover(self): period_name = "123" kwargs = dict(name="money", value=111, period=period_name) command = "add" self.assertTrue(add(command, offline_filepath=self.filepath, **kwargs)) self.assertTrue(add(command, offline_filepath=self.filepath, **kwargs)) # Create client, and fake the run method client = utils.Client() def run(command, **kwargs): raise Exception client.run = run self.assertRaises( OfflineRecoveryError, recover, client, offline_filepath=self.filepath) content = _load(self.filepath) kwargs["command"] = command self.assertDictEqual(content[0], kwargs) self.assertDictEqual(content[1], kwargs)
def run(command=None, config_filepath=None, verbose=False, **params): """High-level API entry point. All 'params' are passed to 'Client.safely_run()'. 'config_filepath' specifies the path to a custom config file (optional). If 'verbose' is set, debug level log messages are printed to the terminal. This function can be used for scripting. Provide 'command' and 'params' according to what the command line interface accepts (consult help via `financeager [command] --help`), e.g. {"command": "add", "name": "champagne", "value": "99"}. :return: UNIX return code (zero for success, non-zero otherwise) """ if verbose: make_log_stream_handler_verbose() exit_code = FAILURE if config_filepath is None and os.path.exists(financeager.CONFIG_FILEPATH): config_filepath = financeager.CONFIG_FILEPATH try: configuration = Configuration(filepath=config_filepath) except InvalidConfigError as e: logger.error("Invalid configuration: {}".format(e)) return FAILURE date_format = configuration.get_option("FRONTEND", "date_format") try: _preprocess(params, date_format) except PreprocessingError as e: logger.error(e) return FAILURE service_name = configuration.get_option("SERVICE", "name") if service_name == "flask": init_logger("urllib3") client = Client(configuration=configuration, out=Client.Out(logger.info, logger.error)) success, store_offline = client.safely_run(command, **params) if success: exit_code = SUCCESS # When regular command was successfully executed, attempt to recover # offline backup try: if offline.recover(client): logger.info("Recovered offline backup.") except OfflineRecoveryError: logger.error("Offline backup recovery failed!") exit_code = FAILURE if store_offline and offline.add(command, **params): logger.info("Stored '{}' request in offline backup.".format(command)) if service_name == "none": client.run("stop") return exit_code
def test_failed_recover(self, run_mock): run_mock.side_effect = Exception() period_name = "123" kwargs = dict(name="money", value=111, period=period_name) command = "add" self.assertTrue(add(command, offline_filepath=self.filepath, **kwargs)) self.assertTrue(add(command, offline_filepath=self.filepath, **kwargs)) proxy = local_proxy() self.assertRaises(OfflineRecoveryError, recover, proxy, offline_filepath=self.filepath) content = _load(self.filepath) kwargs["command"] = command self.assertDictEqual(content[0], kwargs) self.assertDictEqual(content[1], kwargs)
def test_add_recover(self): period_name = "123" kwargs = dict(name="money", value=111, date="01-31", period=period_name) self.assertTrue(add("add", offline_filepath=self.filepath, **kwargs)) content = _load(self.filepath) self.assertIsInstance(content, list) self.assertEqual(len(content), 1) data = content[0] self.assertEqual(data.pop("command"), "add") self.assertDictEqual(kwargs, data) client = utils.Client() self.assertTrue(recover(client, offline_filepath=self.filepath)) element = client.proxy.run("get", eid=1, period=period_name)["element"] self.assertEqual(element["name"], "money") self.assertEqual(element["value"], 111)
def run(command=None, config_filepath=None, verbose=False, **cl_kwargs): """High-level API entry point, useful for scripts. Run 'command' passing 'cl_kwargs' according to what the command line interface accepts (consult help via `financeager [command] --help`), e.g. {"command": "add", "name": "champagne", "value": "99"}. All kwargs are passed to 'communication.run()'. 'config' specifies the path to a custom config file (optional). If 'verbose' is set, debug level log messages are printed to the terminal. :return: UNIX return code (zero for success, non-zero otherwise) """ if verbose: make_log_stream_handler_verbose() exit_code = FAILURE if config_filepath is None and os.path.exists(financeager.CONFIG_FILEPATH): config_filepath = financeager.CONFIG_FILEPATH try: configuration = Configuration(filepath=config_filepath) except InvalidConfigError as e: logger.error("Invalid configuration: {}".format(e)) return FAILURE backend_name = configuration.get_option("SERVICE", "name") communication_module = communication.module(backend_name) proxy_kwargs = {} if backend_name == "flask": init_logger("urllib3") proxy_kwargs["http_config"] = configuration.get_option("SERVICE:FLASK") else: # 'none' is the only other option proxy_kwargs["data_dir"] = financeager.DATA_DIR # Indicate whether to store request offline, if failed store_offline = False proxy = communication_module.proxy(**proxy_kwargs) try: logger.info( communication.run(proxy, command, default_category=configuration.get_option( "FRONTEND", "default_category"), date_format=configuration.get_option( "FRONTEND", "date_format"), **cl_kwargs)) if offline.recover(proxy): logger.info("Recovered offline backup.") exit_code = SUCCESS except OfflineRecoveryError: logger.error("Offline backup recovery failed!") except (PreprocessingError, InvalidRequest) as e: # Command is erroneous and hence not stored offline logger.error(e) except CommunicationError as e: logger.error(e) store_offline = True except Exception: logger.exception("Unexpected error") store_offline = True if store_offline and offline.add(command, **cl_kwargs): logger.info("Stored '{}' request in offline backup.".format(command)) if backend_name == "none": communication.run(proxy, "stop") return exit_code
def test_no_add(self): self.assertFalse(add("print"))
def test_no_add(self): self.assertFalse(add("list"))