def connect(name: Union[str, Path], debug: bool = False, version: int = -1) -> ConnectionPlus: """ Connect or create database. If debug the queries will be echoed back. This function takes care of registering the numpy/sqlite type converters that we need. Args: name: name or path to the sqlite file debug: whether or not to turn on tracing version: which version to create. We count from 0. -1 means 'latest'. Should always be left at -1 except when testing. Returns: conn: connection object to the database (note, it is `ConnectionPlus`, not `sqlite3.Connection` """ # register numpy->binary(TEXT) adapter sqlite3.register_adapter(np.ndarray, _adapt_array) # register binary(TEXT) -> numpy converter sqlite3.register_converter("array", _convert_array) sqlite3_conn = sqlite3.connect(name, detect_types=sqlite3.PARSE_DECLTYPES, check_same_thread=True) conn = ConnectionPlus(sqlite3_conn) latest_supported_version = _latest_available_version() db_version = get_user_version(conn) if db_version > latest_supported_version: raise RuntimeError(f"Database {name} is version {db_version} but this " f"version of QCoDeS supports up to " f"version {latest_supported_version}") # sqlite3 options conn.row_factory = sqlite3.Row # Make sure numpy ints and floats types are inserted properly for numpy_int in numpy_ints: sqlite3.register_adapter(numpy_int, int) sqlite3.register_converter("numeric", _convert_numeric) for numpy_float in (float,) + numpy_floats: sqlite3.register_adapter(numpy_float, _adapt_float) for complex_type in complex_types: sqlite3.register_adapter(complex_type, _adapt_complex) sqlite3.register_converter("complex", _convert_complex) if debug: conn.set_trace_callback(print) init_db(conn) perform_db_upgrade(conn, version=version) return conn
def connect(name: str, debug: bool = False, version: int = -1) -> ConnectionPlus: """ Connect or create database. If debug the queries will be echoed back. This function takes care of registering the numpy/sqlite type converters that we need. Args: name: name or path to the sqlite file debug: whether or not to turn on tracing version: which version to create. We count from 0. -1 means 'latest'. Should always be left at -1 except when testing. Returns: conn: connection object to the database (note, it is `ConnectionPlus`, not `sqlite3.Connection` """ # register numpy->binary(TEXT) adapter # the typing here is ignored due to what we think is a flaw in typeshed # see https://github.com/python/typeshed/issues/2429 sqlite3.register_adapter(np.ndarray, _adapt_array) # type: ignore # register binary(TEXT) -> numpy converter # for some reasons mypy complains about this sqlite3.register_converter("array", _convert_array) sqlite3_conn = sqlite3.connect(name, detect_types=sqlite3.PARSE_DECLTYPES) conn = ConnectionPlus(sqlite3_conn) latest_supported_version = _latest_available_version() db_version = get_user_version(conn) if db_version > latest_supported_version: raise RuntimeError(f"Database {name} is version {db_version} but this " f"version of QCoDeS supports up to " f"version {latest_supported_version}") # sqlite3 options conn.row_factory = sqlite3.Row # Make sure numpy ints and floats types are inserted properly for numpy_int in [ np.int, np.int8, np.int16, np.int32, np.int64, np.uint, np.uint8, np.uint16, np.uint32, np.uint64 ]: sqlite3.register_adapter(numpy_int, int) sqlite3.register_converter("numeric", _convert_numeric) for numpy_float in [np.float, np.float16, np.float32, np.float64]: sqlite3.register_adapter(numpy_float, _adapt_float) for complex_type in complex_types: sqlite3.register_adapter(complex_type, _adapt_complex) # type: ignore sqlite3.register_converter("complex", _convert_complex) if debug: conn.set_trace_callback(print) init_db(conn) perform_db_upgrade(conn, version=version) return conn
def test_perform_actual_upgrade_6_to_newest_add_new_data(): """ Insert new runs on top of existing runs upgraded and verify that they get the correct captured_run_id and captured_counter """ from qcodes.dataset.measurements import Measurement from qcodes.instrument.parameter import Parameter import numpy as np fixpath = os.path.join(fixturepath, 'db_files', 'version6') db_file = 'some_runs.db' dbname_old = os.path.join(fixpath, db_file) if not os.path.exists(dbname_old): pytest.skip("No db-file fixtures found. You can generate test db-files" " using the scripts in the " "https://github.com/QCoDeS/qcodes_generate_test_db/ repo") with temporarily_copied_DB(dbname_old, debug=False, version=6) as conn: assert isinstance(conn, ConnectionPlus) perform_db_upgrade(conn) assert get_user_version(conn) >= 7 no_of_runs_query = "SELECT max(run_id) FROM runs" no_of_runs = one( atomic_transaction(conn, no_of_runs_query), 'max(run_id)') # Now let's insert new runs and ensure that they also get # captured_run_id assigned. params = [] for n in range(5): params.append(Parameter(f'p{n}', label=f'Parameter {n}', unit=f'unit {n}', set_cmd=None, get_cmd=None)) # Set up an experiment exp = new_experiment('some-exp', 'some-sample', conn=conn) meas = Measurement(exp=exp) meas.register_parameter(params[0]) meas.register_parameter(params[1]) meas.register_parameter(params[2], basis=(params[0],)) meas.register_parameter(params[3], basis=(params[1],)) meas.register_parameter(params[4], setpoints=(params[2], params[3])) # Make a number of identical runs for _ in range(10): with meas.run() as datasaver: for x in np.random.rand(10): for y in np.random.rand(10): z = np.random.rand() datasaver.add_result((params[0], 0), (params[1], 1), (params[2], x), (params[3], y), (params[4], z)) no_of_runs_new = one( atomic_transaction(conn, no_of_runs_query), 'max(run_id)') assert no_of_runs_new == 20 # check that run_id is equivalent to captured_run_id for new # runs for run_id in range(no_of_runs, no_of_runs_new + 1): ds1 = load_by_id(run_id, conn) ds2 = load_by_run_spec(captured_run_id=run_id, conn=conn) assert ds1.the_same_dataset_as(ds2) assert ds1.run_id == run_id assert ds1.run_id == ds1.captured_run_id assert ds2.run_id == run_id assert ds2.run_id == ds2.captured_run_id # we are creating a new experiment into a db with one exp so: exp_id = 2 # check that counter is equivalent to captured_counter for new # runs for counter in range(1, no_of_runs_new - no_of_runs + 1): ds1 = load_by_counter(counter, exp_id, conn) # giving only the counter is not unique since we have 2 experiments with pytest.raises(NameError, match="More than one" " matching dataset"): load_by_run_spec(captured_counter=counter, conn=conn) # however we can supply counter and experiment ds2 = load_by_run_spec(captured_counter=counter, experiment_name='some-exp', conn=conn) assert ds1.the_same_dataset_as(ds2) assert ds1.counter == counter assert ds1.counter == ds1.captured_counter assert ds2.counter == counter assert ds2.counter == ds2.captured_counter