def test_perform_actual_upgrade_5_to_6():
    fixpath = os.path.join(fixturepath, 'db_files', 'version5')

    db_file = 'empty.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=5) as conn:
        perform_db_upgrade_5_to_6(conn)
        assert get_user_version(conn) == 6

    db_file = 'some_runs.db'
    dbname_old = os.path.join(fixpath, db_file)

    with temporarily_copied_DB(dbname_old, debug=False, version=5) as conn:
        perform_db_upgrade_5_to_6(conn)
        assert get_user_version(conn) == 6

        no_of_runs_query = "SELECT max(run_id) FROM runs"
        no_of_runs = one(
            atomic_transaction(conn, no_of_runs_query), 'max(run_id)')
        assert no_of_runs == 10

        for run_id in range(1, no_of_runs + 1):
            json_str = get_run_description(conn, run_id)

            deser = json.loads(json_str)
            assert deser['version'] == 0

            desc = serial.from_json_to_current(json_str)
            assert desc._version == 1
Example #2
0
def test_version_4a_bugfix():
    v4fixpath = os.path.join(fixturepath, 'db_files', 'version4a')

    dbname_old = os.path.join(v4fixpath, 'some_runs.db')

    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 legacy_DB_generation folder")

    with temporarily_copied_DB(dbname_old, debug=False, version=4) as conn:

        dd = fix_version_4a_run_description_bug(conn)

        assert dd['runs_inspected'] == 10
        assert dd['runs_fixed'] == 10

        # Ensure the structure of the run_description JSON after applying
        # the fix function
        for run_id in range(1, 10 + 1):
            rd_str = get_run_description(conn, run_id)
            rd_dict = json.loads(rd_str)
            assert list(rd_dict.keys()) == ['interdependencies']
            assert list(rd_dict['interdependencies'].keys()) == ['paramspecs']

        dd = fix_version_4a_run_description_bug(conn)

        assert dd['runs_inspected'] == 10
        assert dd['runs_fixed'] == 0
Example #3
0
def fix_version_4a_run_description_bug(conn: ConnectionPlus) -> Dict[str, int]:
    """
    Fix function to fix a bug where the RunDescriber accidentally wrote itself
    to string using the (new) InterDependencies_ object instead of the (old)
    InterDependencies object. After the first call, this function should be
    idempotent.


    Args:
        conn: the connection to the database

    Returns:
        A dict with the fix results ('runs_inspected', 'runs_fixed')
    """

    user_version = get_user_version(conn)

    if not user_version == 4:
        raise RuntimeError('Database of wrong version. Will not apply fix. '
                           'Expected version 4, found version {user_version}')

    no_of_runs_query = "SELECT max(run_id) FROM runs"
    no_of_runs = one(atomic_transaction(conn, no_of_runs_query), 'max(run_id)')
    no_of_runs = no_of_runs or 0

    with atomic(conn) as conn:

        pbar = tqdm(range(1, no_of_runs+1))
        pbar.set_description("Fixing database")

        # collect some metrics
        runs_inspected = 0
        runs_fixed = 0

        old_style_keys = ['paramspecs']
        new_style_keys = ['parameters', 'dependencies', 'inferences',
                          'standalones']

        for run_id in pbar:

            desc_str = get_run_description(conn, run_id)
            desc_ser = json.loads(desc_str)
            idps_ser = desc_ser['interdependencies']

            if list(idps_ser.keys()) == old_style_keys:
                pass
            elif list(idps_ser.keys()) == new_style_keys:
                old_desc_ser = \
                    _convert_run_describer_v1_like_dict_to_v0_like_dict(
                        desc_ser)
                json_str = json.dumps(old_desc_ser)
                _update_run_description(conn, run_id, json_str)
                runs_fixed += 1
            else:
                raise RuntimeError(f'Invalid runs_description for run_id: '
                                   f'{run_id}')

            runs_inspected += 1

    return {'runs_inspected': runs_inspected, 'runs_fixed': runs_fixed}
Example #4
0
def upgrade_5_to_6(conn: ConnectionPlus) -> None:
    """
    Perform the upgrade from version 5 to version 6.

    The upgrade ensures that the runs_description has a top-level entry
    called 'version'. Note that version changes of the runs_description will
    not be tracked as schema upgrades.
    """
    no_of_runs_query = "SELECT max(run_id) FROM runs"
    no_of_runs = one(atomic_transaction(conn, no_of_runs_query), 'max(run_id)')
    no_of_runs = no_of_runs or 0

    # If one run fails, we want the whole upgrade to roll back, hence the
    # entire upgrade is one atomic transaction

    with atomic(conn) as conn:
        pbar = tqdm(range(1, no_of_runs + 1))
        pbar.set_description("Upgrading database, version 5 -> 6")

        empty_idps_ser = InterDependencies()._to_dict()

        for run_id in pbar:
            json_str = get_run_description(conn, run_id)
            if json_str is None:
                new_json = json.dumps({
                    'version': 0,
                    'interdependencies': empty_idps_ser
                })
            else:
                ser = json.loads(json_str)
                new_ser = {'version': 0}  # let 'version' be the first entry
                new_ser['interdependencies'] = ser['interdependencies']
                new_json = json.dumps(new_ser)
            update_run_description(conn, run_id, new_json)
Example #5
0
def test_fix_wrong_run_descriptions():
    v3fixpath = os.path.join(fixturepath, 'db_files', 'version3')

    dbname_old = os.path.join(v3fixpath,
                              'some_runs_without_run_description.db')

    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 legacy_DB_generation folder")

    def make_ps(n):
        ps = ParamSpec(f'p{n}',
                       label=f'Parameter {n}',
                       unit=f'unit {n}',
                       paramtype='numeric')
        return ps

    paramspecs = [make_ps(n) for n in range(6)]
    paramspecs[2]._inferred_from = ['p0']
    paramspecs[3]._inferred_from = ['p1', 'p0']
    paramspecs[4]._depends_on = ['p2', 'p3']
    paramspecs[5]._inferred_from = ['p0']

    with temporarily_copied_DB(dbname_old, debug=False, version=3) as conn:

        assert get_user_version(conn) == 3

        expected_description = v0.RunDescriber(
            v0.InterDependencies(*paramspecs))

        empty_description = v0.RunDescriber(v0.InterDependencies())

        fix_wrong_run_descriptions(conn, [1, 2, 3, 4])

        for run_id in [1, 2, 3]:
            desc_str = get_run_description(conn, run_id)
            desc = serial.from_json_to_native(desc_str)
            assert desc == expected_description

        desc_str = get_run_description(conn, run_id=4)
        desc = serial.from_json_to_native(desc_str)
        assert desc == empty_description
Example #6
0
def fix_version_4a_run_description_bug(conn: ConnectionPlus) -> Dict[str, int]:
    """
    Fix function to fix a bug where the RunDescriber accidentally wrote itself
    to string using the (new) InterDependencies_ object instead of the (old)
    InterDependencies object. After the first run, this function should be
    idempotent.


    Args:
        conn: the connection to the database

    Returns:
        A dict with the fix results ('runs_inspected', 'runs_fixed')
    """

    user_version = get_user_version(conn)

    if not user_version == 4:
        raise RuntimeError('Database of wrong version. Will not apply fix. '
                           'Expected version 4, found version {user_version}')

    no_of_runs_query = "SELECT max(run_id) FROM runs"
    no_of_runs = one(atomic_transaction(conn, no_of_runs_query), 'max(run_id)')
    no_of_runs = no_of_runs or 0

    with atomic(conn) as conn:

        pbar = tqdm(range(1, no_of_runs + 1))
        pbar.set_description("Fixing database")

        # collect some metrics
        runs_inspected = 0
        runs_fixed = 0

        for run_id in pbar:

            desc_str = get_run_description(conn, run_id)
            desc_ser = json.loads(desc_str)
            idps_ser = desc_ser['interdependencies']

            if RunDescriber._is_description_old_style(idps_ser):
                pass
            else:
                new_desc = RunDescriber.from_json(desc_str)
                update_run_description(conn, run_id, new_desc.to_json())
                runs_fixed += 1

            runs_inspected += 1

    return {'runs_inspected': runs_inspected, 'runs_fixed': runs_fixed}
Example #7
0
 def _get_run_description_from_db(self) -> RunDescriber:
     """
     Look up the run_description from the database
     """
     desc_str = get_run_description(self.conn, self.run_id)
     return RunDescriber.from_json(desc_str)