def __init__(self,
                 path_to_db: Optional[str] = None,
                 exp_id: Optional[int] = None,
                 name: Optional[str] = None,
                 sample_name: Optional[str] = None,
                 format_string: str = "{}-{}-{}",
                 conn: Optional[ConnectionPlus] = None) -> None:
        """
        Create or load an experiment. If exp_id is None, a new experiment is
        created. If exp_id is not None, an experiment is loaded.

        Args:
            path_to_db: The path of the database file to create in/load from.
              If a conn is passed together with path_to_db, an exception is
              raised
            exp_id: The id of the experiment to load
            name: The name of the experiment to create. Ignored if exp_id is
              not None
            sample_name: The sample name for this experiment. Ignored if exp_id
              is not None
            format_string: The format string used to name result-tables.
              Ignored if exp_id is not None.
            conn: connection to the database. If not supplied, the constructor
              first tries to use path_to_db to figure out where to connect to.
              If path_to_db is not supplied either, a new connection
              to the DB file specified in the config is made
        """

        if path_to_db is not None and conn is not None:
            raise ValueError('Received BOTH conn and path_to_db. Please '
                             'provide only one or the other.')

        self._path_to_db = path_to_db or get_DB_location()
        self.conn = conn or connect(self.path_to_db, get_DB_debug())

        max_id = len(get_experiments(self.conn))

        if exp_id is not None:
            if exp_id not in range(1, max_id + 1):
                raise ValueError('No such experiment in the database')
            self._exp_id = exp_id
        else:

            # it is better to catch an invalid format string earlier than later
            try:
                # the corresponding function from sqlite module will try to
                # format as `(name, exp_id, run_counter)`, hence we prepare
                # for that here
                format_string.format("name", 1, 1)
            except Exception as e:
                raise ValueError("Invalid format string. Can not format "
                                 "(name, exp_id, run_counter)") from e

            log.info("creating new experiment in {}".format(self.path_to_db))

            name = name or f"experiment_{max_id+1}"
            sample_name = sample_name or "some_sample"
            self._exp_id = ne(self.conn, name, sample_name, format_string)
Exemple #2
0
def _create_exp_if_needed(
    target_conn: ConnectionPlus,
    exp_name: str,
    sample_name: str,
    fmt_str: str,
    start_time: float,
    end_time: Union[float, None],
) -> int:
    """
    Look up in the database whether an experiment already exists and create
    it if it doesn't. Note that experiments do not have GUIDs, so this method
    is not guaranteed to work. Matching names and times is the best we can do.
    """

    matching_exp_ids = get_matching_exp_ids(
        target_conn,
        name=exp_name,
        sample_name=sample_name,
        format_string=fmt_str,
        start_time=start_time,
        end_time=end_time,
    )

    if len(matching_exp_ids) > 1:
        exp_id = matching_exp_ids[0]
        warn(f"{len(matching_exp_ids)} experiments found in target DB that "
             "match name, sample_name, fmt_str, start_time, and end_time. "
             f"Inserting into the experiment with exp_id={exp_id}.")
        return exp_id
    if len(matching_exp_ids) == 1:
        return matching_exp_ids[0]
    else:
        lastrowid = ne(
            target_conn,
            name=exp_name,
            sample_name=sample_name,
            format_string=fmt_str,
            start_time=start_time,
            end_time=end_time,
        )
        return lastrowid