def load_experiment_by_name( name: str, sample: Optional[str] = None, conn: Optional[ConnectionPlus] = None) -> Experiment: """ Try to load experiment with the specified name. Nothing stops you from having many experiments with the same name and sample_name. In that case this won't work. And warn you. Args: name: the name of the experiment sample: the name of the sample conn: connection to the database. If not supplied, a new connection to the DB file specified in the config is made Returns: the requested experiment Raises: ValueError if the name is not unique and sample name is None. """ conn = conn or connect(get_DB_location()) if sample: sql = """ SELECT * FROM experiments WHERE sample_name = ? AND name = ? """ c = transaction(conn, sql, sample, name) else: sql = """ SELECT * FROM experiments WHERE name = ? """ c = transaction(conn, sql, name) rows = c.fetchall() if len(rows) == 0: raise ValueError("Experiment not found") elif len(rows) > 1: _repr = [] for row in rows: s = (f"exp_id:{row['exp_id']} ({row['name']}-{row['sample_name']})" f" started at ({row['start_time']})") _repr.append(s) _repr_str = "\n".join(_repr) raise ValueError(f"Many experiments matching your request" f" found:\n{_repr_str}") else: e = Experiment(exp_id=rows[0]['exp_id'], conn=conn) return e
def test_atomic_raises(experiment): conn = experiment.conn bad_sql = '""' # it seems that the type of error raised differs between python versions # 3.6.0 (OperationalError) and 3.6.3 (RuntimeError) # -strange, huh? with pytest.raises((OperationalError, RuntimeError)): with mut.atomic(conn): mut.transaction(conn, bad_sql)
def load_experiment_by_name(name: str, sample: Optional[str] = None) -> Experiment: """ Try to load experiment with the specified name. Nothing stops you from having many experiments with the same name and sample_name. In that case this won't work. And warn you. Args: name: the name of the experiment sample: the name of the sample Returns: the requested experiment Raises: ValueError if the name is not unique and sample name is None. """ e = Experiment(get_DB_location()) if sample: sql = """ SELECT * FROM experiments WHERE sample_name = ? AND name = ? """ c = transaction(e.conn, sql, sample, name) else: sql = """ SELECT * FROM experiments WHERE name = ? """ c = transaction(e.conn, sql, name) rows = c.fetchall() if len(rows) == 0: raise ValueError("Experiment not found \n") elif len(rows) > 1: _repr = [] for row in rows: s = f"exp_id:{row['exp_id']} ({row['name']}-{row['sample_name']}) started at({row['start_time']})" _repr.append(s) _repr_str = "\n".join(_repr) raise ValueError( f"Many experiments matching your request found {_repr_str}") else: e.exp_id = rows[0]['exp_id'] return e
def test_atomic_creation(experiment): """" Test that dataset creation is atomic. Test for https://github.com/QCoDeS/Qcodes/issues/1444 """ def just_throw(*args): raise RuntimeError("This breaks adding metadata") # first we patch add_meta_data to throw an exception # if create_data is not atomic this would create a partial # run in the db. Causing the next create_run to fail with patch('qcodes.dataset.sqlite_base.add_meta_data', new=just_throw): x = ParamSpec('x', 'numeric') t = ParamSpec('t', 'numeric') y = ParamSpec('y', 'numeric', depends_on=['x', 't']) with pytest.raises( RuntimeError, match="Rolling back due to unhandled exception") as e: mut.create_run(experiment.conn, experiment.exp_id, name='testrun', guid=generate_guid(), parameters=[x, t, y], metadata={'a': 1}) assert error_caused_by(e, "This breaks adding metadata") # since we are starting from an empty database and the above transaction # should be rolled back there should be no runs in the run table runs = mut.transaction(experiment.conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 0 with shadow_conn(experiment.path_to_db) as new_conn: runs = mut.transaction(new_conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 0 # if the above was not correctly rolled back we # expect the next creation of a run to fail mut.create_run(experiment.conn, experiment.exp_id, name='testrun', guid=generate_guid(), parameters=[x, t, y], metadata={'a': 1}) runs = mut.transaction(experiment.conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 1 with shadow_conn(experiment.path_to_db) as new_conn: runs = mut.transaction(new_conn, 'SELECT run_id FROM runs').fetchall() assert len(runs) == 1
def load_by_counter(counter, exp_id): """ Load a dataset given its counter in one experiment Args: counter: Counter of the dataset exp_id: Experiment the dataset belongs to Returns: the dataset """ conn = connect(get_DB_location()) sql = """ SELECT run_id FROM runs WHERE result_counter= ? AND exp_id = ? """ c = transaction(conn, sql, counter, exp_id) run_id = one(c, 'run_id') conn.close() d = DataSet(get_DB_location(), run_id=run_id) return d
def load_by_counter(counter: int, exp_id: int, conn: Optional[ConnectionPlus] = None) -> DataSet: """ Load a dataset given its counter in a given experiment Lookup is performed in the database file that is specified in the config. Args: counter: counter of the dataset within the given experiment exp_id: id of the experiment where to look for the dataset conn: connection to the database to load from. If not provided, a connection to the DB file specified in the config is made Returns: dataset of the given counter in the given experiment """ conn = conn or connect(get_DB_location()) sql = """ SELECT run_id FROM runs WHERE result_counter= ? AND exp_id = ? """ c = transaction(conn, sql, counter, exp_id) run_id = one(c, 'run_id') d = DataSet(conn=conn, run_id=run_id) return d
def get_run_timestamp(run_id): DB = qc.config["core"]["db_location"] d = DataSet(DB) sql = """ SELECT run_timestamp FROM runs WHERE run_id= ? """ c = transaction(d.conn, sql, run_id) run_timestamp = one(c, 'run_timestamp') return run_timestamp
def load_by_counter(counter, exp_id): """ Load a dataset given its counter in one experiment Args: counter: Counter of the dataset exp_id: Experiment the dataset belongs to Returns: the dataset """ d = DataSet(DB) sql = """ SELECT run_id FROM runs WHERE result_counter= ? AND exp_id = ? """ c = transaction(d.conn, sql, counter, exp_id) d.run_id = one(c, 'run_id') return d
def _remove_trigger(self, name): transaction(self.conn, f"DROP TRIGGER IF EXISTS {name};")