def create_app(data_dir=None, config=None): """Create web app with RESTful API built from resources. The function is named such that the flask cli detects it as app factory method. The log file handler is set up very first. If 'data_dir' or the environment variable 'FINANCEAGER_FLASK_DATA_DIR' is given, a directory is created to store application data. An instance of 'server.Server' is created, passing 'data_dir'. If 'data_dir' is not given, the application data is stored in memory and will be lost when the app terminates. 'config' is a dict of configuration variables that flask understands. """ setup_log_file_handler() # Propagate flask and werkzeug log messages to financeager logs init_logger("flask.app") init_logger("werkzeug") app = Flask(__name__) app.config.update(config or {}) if app.debug: make_log_stream_handler_verbose() data_dir = data_dir or os.environ.get("FINANCEAGER_FLASK_DATA_DIR") if data_dir is None: logger.warning("'data_dir' not given. Application data is stored in " "memory and is lost when the flask app terminates. Set " "the environment variable FINANCEAGER_FLASK_DATA_DIR " "accordingly for persistent data storage.") else: os.makedirs(data_dir, exist_ok=True) logger.debug("Created flask app {} - {} mode".format( app.name, "debug" if app.debug else "production")) srv = server.Server(data_dir=data_dir) logger.debug( "Started financeager server with data dir '{}'".format(data_dir)) api = Api(app) api.add_resource(resources.PocketsResource, POCKETS_TAIL, resource_class_args=(srv, )) api.add_resource(resources.CopyResource, COPY_TAIL, resource_class_args=(srv, )) api.add_resource(resources.PocketResource, "{}/<pocket_name>".format(POCKETS_TAIL), resource_class_args=(srv, )) api.add_resource( resources.EntryResource, "{}/<pocket_name>/<table_name>/<eid>".format(POCKETS_TAIL), resource_class_args=(srv, )) # Assign attribute such that e.g. test_cli can access Server methods app._server = srv return app
def main(): """Main command line entry point of the application. The config and the log directory are created. A FileHandler is added to the package logger. All command line arguments and options are parsed and passed to 'run()'. """ os.makedirs(financeager.DATA_DIR, exist_ok=True) # Adding the FileHandler here avoids cluttering the log during tests setup_log_file_handler() # Most runs return None which evaluates to return code 0 sys.exit(run(**_parse_command()))
import tempfile import time import unittest from threading import Thread from unittest import mock from financeager import (DEFAULT_TABLE, cli, clients, config, entries, setup_log_file_handler) from requests import RequestException, Response from requests import get as requests_get from financeager_flask import fflask, main TEST_CONFIG_FILEPATH = "/tmp/financeager-test-config" TEST_DATA_DIR = tempfile.mkdtemp(prefix="financeager-") setup_log_file_handler(log_dir=TEST_DATA_DIR) class CliTestCase(unittest.TestCase): @classmethod def setUpClass(cls): # Create test config file for client with open(TEST_CONFIG_FILEPATH, "w") as file: file.write(cls.CONFIG_FILE_CONTENT) cls.pocket = 1900 def setUp(self): # Separate test runs by running individual test methods using distinct # pockets (especially crucial for CliFlaskTestCase which uses a single # Flask instance for all tests)