def test_session_scope(): """Test the session scope object.""" db = DB(connect_url=TEST_URL, web_app=False) db.init() with db.session() as session: session.add(User(user_id='U', name='U', secret='U', active=True)) # Query all users. Expects two objects in the resulting list (te created # user and the default user). with db.session() as session: assert len(session.query(User).all()) == 2 # Error when adding user with duplicate key. with pytest.raises(IntegrityError): with db.session() as session: session.add(User(user_id='U', name='U', secret='U', active=True)) # Query all users. Still expects one object in the resulting list. with db.session() as session: assert len(session.query(User).all()) == 2 # Raise an exception within the session scope. with pytest.raises(ValueError): with db.session() as session: session.add(User(user_id='W', name='W', secret='W', active=True)) raise ValueError('some error') # Query all users. Still expects two object in the resulting list. with db.session() as session: assert len(session.query(User).all()) == 2
def test_create_sqlite_dir(tmpdir): """Test function that creates the SQLite databse directory when creating an instance of the database object for a SQLite database. """ DB(connect_url=TEST_DB(os.path.join(tmpdir, 'db'))) assert os.path.isdir(os.path.join(tmpdir, 'db')) # Special case for file path without parent directory. DB(connect_url=TEST_DB(''))
def client(benchmark_id, tmpdir): """Create the app client.""" # Set the environment variables and create the database. connect_url = TEST_DB(tmpdir) DB(connect_url=connect_url).init() # Create a single benchmark. Need to ensure that the API factory points to # the newly created database. from robflask.service import init_service init_service(basedir=tmpdir, database=connect_url) from robflask.service import service with service() as api: # Get the benchmark repository instance from the API api.workflows().create_workflow(identifier=benchmark_id, name='Hello World', description='Hello World Demo', source=BENCHMARK_DIR) # Set the maximum upload file size to 1KB os.environ[config.ROB_WEBAPI_CONTENTLENGTH] = '1024' # Set the UI path. os.environ[config.ROB_UI_PATH] = ROB_UI_PATH # Create the Flask app from robflask.api import create_app app = create_app({'TESTING': True}) with app.test_client() as client: yield client
def success_run(database: DB, fs: StorageVolume, basedir: str) -> Tuple[str, str, str, str]: """Create a successful run with two result files: - A.json - results/B.json Returns the identifier of the created workflow, group, run, and user. """ # Setup temporary run folder. runfs = FileSystemStorage(basedir=os.path.join(basedir, 'tmprun')) runfs.store(file=io_file({'A': 1}), dst='A.json') runfs.store(file=io_file({'B': 1}), dst=util.join('results', 'B.json')) with database.session() as session: user_id = create_user(session, active=True) workflow_id = create_workflow(session) group_id = create_group(session, workflow_id, users=[user_id]) groups = WorkflowGroupManager(session=session, fs=fs) runs = RunManager(session=session, fs=fs) run = runs.create_run(group=groups.get_group(group_id)) run_id = run.run_id state = run.state() runs.update_run( run_id=run_id, state=state.start().success(files=['A.json', 'results/B.json']), runstore=runfs) return workflow_id, group_id, run_id, user_id
def success_run(database: DB, fs: FileStore, basedir: str) -> Tuple[str, str, str, str]: """Create a successful run with two result files: - A.json - run/results/B.json Returns the identifier of the created workflow, group, run, and user. """ # Setup temporary run folder. tmprundir = os.path.join(basedir, 'tmprun') tmpresultsdir = os.path.join(tmprundir, 'run', 'results') os.makedirs(tmprundir) os.makedirs(tmpresultsdir) f1 = os.path.join(tmprundir, 'A.json') util.write_object(f1, {'A': 1}) f2 = os.path.join(tmpresultsdir, 'B.json') util.write_object(f2, {'B': 1}) with database.session() as session: user_id = create_user(session, active=True) workflow_id = create_workflow(session) group_id = create_group(session, workflow_id, users=[user_id]) groups = WorkflowGroupManager(session=session, fs=fs) runs = RunManager(session=session, fs=fs) run = runs.create_run(group=groups.get_group(group_id)) run_id = run.run_id state = run.state() runs.update_run( run_id, state.start().success(files=['A.json', 'run/results/B.json']), rundir=tmprundir) assert not os.path.exists(tmprundir) return workflow_id, group_id, run_id, user_id
def init(force=False): """Initialize database and base directories for the API.""" if not force: click.echo('This will erase an existing database.') click.confirm('Continue?', default=True, abort=True) # Create a new instance of the database. Raise errors if the database URL # is not set. config = env() connect_url = config.get(FLOWSERV_DB) if connect_url is None: raise err.MissingConfigurationError('database Url') DB(connect_url=connect_url).init()
def get_app(source: str, specfile: str, manifestfile: str, name: str) -> Workflow: """Get the application handle for the given workflow template. Creates a fresh database in the application cache directory and installes the given workflow. Parameters ---------- source: string Path to local template, name or URL of the template in the repository. specfile: string Path to the workflow template specification file (absolute or relative to the workflow directory) manifestfile: string Path to manifest file. If not given an attempt is made to read one of the default manifest file names in the base directory. name: string Name of the application that will determine the base folder for all workflow files. Returns ------- flowserv.client.app.workflow.Workflow """ # Use the application cache directory for storing all workflow files. homedir = os.path.join(user_cache_dir(appname='flowapp'), name) util.cleardir(homedir) # Create new database. dburl = SQLITE_DB(dirname=homedir, filename='flowapp.db') DB(connect_url=dburl).init() # Install workflow template and return app handle. env = config\ .env()\ .basedir(homedir)\ .database(dburl)\ .volume(FStore(basedir=homedir, identifier=DEFAULT_STORE))\ .open_access()\ .run_sync() client = Flowserv(env=env) workflow_id = client.install(source=source, specfile=specfile, manifestfile=manifestfile) return client.open(identifier=workflow_id)
def init_db(env: Dict) -> DB: """Create an instance of the database object based on the given configuration settings. Sets the respective variables to the default value if not set. Parameters ---------- env: dict, default=None Dictionary that provides access to configuration parameter values. Returns ------- flowserv.model.database.DB """ # Get the web app flag. Use True as the default if the value is not set. if WEBAPP not in env: env[WEBAPP] = True web_app = env[WEBAPP] # Ensure that the databse connection Url is specified in the configuration. url = env.get(DATABASE) if url is None: # Use a SQLite database in the dabase directory as default. # This database needs to be initialized if it does not exist. dbfile = '{}/flowserv.db'.format(env[config.FLOWSERV_BASEDIR]) url = 'sqlite:///{}'.format(dbfile) env[DATABASE] = url # Maintain a reference to the local database instance for use # when creating API instances. db = DB(connect_url=url, web_app=web_app) if not os.path.isfile(dbfile): # Initialize the database if the database if the configuration # references the default database and the database file does # not exist. db.init() else: # If the database Url is specified in the configuration we create the # database object for that Url. In this case we assume that the referenced # database has been initialized. db = DB(connect_url=env[DATABASE], web_app=web_app) # Return the created database object. return db
def database(): """Create a fresh instance of the database.""" db = DB(connect_url=TEST_URL) db.init() return db
def test_db_webapp(web_app, echo): """Basic tests to ensure that the different parameter options for DB instantiation work without generating errors. """ db = DB(connect_url=TEST_URL, web_app=web_app, echo=echo) db.init()