def convert_sdb(
    env: Environment,
    sess: Session,
    sdb: StoredDataBlockMetadata,
    conversion_path: ConversionPath,
    target_storage: Storage,
    storages: Optional[List[Storage]] = None,
) -> StoredDataBlockMetadata:
    if not conversion_path.conversions:
        return sdb
    if storages is None:
        storages = env.storages
    prev_sdb = sdb
    next_sdb: Optional[StoredDataBlockMetadata] = None
    prev_storage = sdb.storage
    next_storage: Optional[Storage] = None
    realized_schema = sdb.realized_schema(env, sess)
    for conversion_edge in conversion_path.conversions:
        conversion = conversion_edge.conversion
        target_storage_format = conversion.to_storage_format
        next_storage = select_storage(target_storage, storages,
                                      target_storage_format)
        logger.debug(
            f"CONVERSION: {conversion.from_storage_format} -> {conversion.to_storage_format}"
        )
        next_sdb = StoredDataBlockMetadata(  # type: ignore
            id=get_datablock_id(),
            data_block_id=prev_sdb.data_block_id,
            data_block=prev_sdb.data_block,
            data_format=target_storage_format.data_format,
            storage_url=next_storage.url,
        )
        sess.add(next_sdb)
        conversion_edge.copier.copy(
            from_name=prev_sdb.get_name(),
            to_name=next_sdb.get_name(),
            conversion=conversion,
            from_storage_api=prev_storage.get_api(),
            to_storage_api=next_storage.get_api(),
            schema=realized_schema,
        )
        if (prev_sdb.data_format.is_python_format()
                and not prev_sdb.data_format.is_storable()):
            # If the records obj is in python and not storable, and we just used it, then it can be reused
            # TODO: Bit of a hack. Is there a central place we can do this?
            #       also is reusable a better name than storable?
            prev_storage.get_api().remove(prev_sdb.get_name())
            prev_sdb.data_block.stored_data_blocks.remove(prev_sdb)
            if prev_sdb in sess.new:
                sess.expunge(prev_sdb)
            else:
                sess.delete(prev_sdb)
        prev_sdb = next_sdb
        prev_storage = next_storage
    return next_sdb
def test_meta(session: Session) -> None:
    e = DummyContact(name="test")
    e.meta["key"] = "value"
    e.meta["number"] = 42
    session.add(e)
    session.flush()
    e_id = e.id
    session.expunge(e)
    del e
    e = session.query(DummyContact).get(e_id)
    assert e.meta["key"] == "value"
    assert e.meta["number"] == 42
    def start(self, session: Session) -> None:
        """Start a new run.

        Must run in the recorder thread.
        """
        self._current_run_info = RecorderRuns(
            start=self.recording_start, created=dt_util.utcnow()
        )
        session.add(self._current_run_info)
        session.flush()
        session.expunge(self._current_run_info)
        self.load_from_db(session)
    def load_from_db(self, session: Session) -> None:
        """Update the run cache.

        Must run in the recorder thread.
        """
        run_timestamps: list[int] = []
        runs_by_timestamp: dict[int, RecorderRuns] = {}

        for run in session.query(RecorderRuns).order_by(RecorderRuns.start.asc()).all():
            session.expunge(run)
            if run_dt := process_timestamp(run.start):
                timestamp = run_dt.timestamp()
                run_timestamps.append(timestamp)
                runs_by_timestamp[timestamp] = run
Exemple #5
0
def run_information_with_session(
        session: Session,
        point_in_time: datetime | None = None) -> RecorderRuns | None:
    """Return information about current run from the database."""
    recorder_runs = RecorderRuns

    query = session.query(recorder_runs)
    if point_in_time:
        query = query.filter((recorder_runs.start < point_in_time)
                             & (recorder_runs.end > point_in_time))

    if (res := query.first()) is not None:
        session.expunge(res)
        return cast(RecorderRuns, res)
Exemple #6
0
    def get_existing(self, session: Session) -> Optional["Album"]:
        """Gets a matching Album in the library either by its path or unique tags."""
        existing_album = (session.query(Album).filter(
            or_(
                and_(
                    Album.artist == self.artist,
                    Album.title == self.title,
                    Album.date == self.date,
                ),
                Album.path == self.path,
            )).options(joinedload("*")).one_or_none())
        if not existing_album:
            return None

        session.expunge(existing_album)
        return existing_album
Exemple #7
0
class InboxSession(object):
    """ Inbox custom ORM (with SQLAlchemy compatible API).

    Parameters
    ----------
    engine : <sqlalchemy.engine.Engine>
        A configured database engine to use for this session
    versioned : bool
        Do you want to enable the transaction log?
    ignore_soft_deletes : bool
        Whether or not to ignore soft-deleted objects in query results.
    namespace_id : int
        Namespace to limit query results with.
    """
    def __init__(self, engine, versioned=True, ignore_soft_deletes=True,
                 namespace_id=None):
        # TODO: support limiting on namespaces
        assert engine, "Must set the database engine"

        args = dict(bind=engine, autoflush=True, autocommit=False)
        self.ignore_soft_deletes = ignore_soft_deletes
        if ignore_soft_deletes:
            args['query_cls'] = InboxQuery
        self._session = Session(**args)

        if versioned:
            from inbox.models.transaction import create_revisions

            @event.listens_for(self._session, 'after_flush')
            def after_flush(session, flush_context):
                """
                Hook to log revision snapshots. Must be post-flush in order to
                grab object IDs on new objects.
                """
                create_revisions(session)

    def query(self, *args, **kwargs):
        q = self._session.query(*args, **kwargs)
        if self.ignore_soft_deletes:
            return q.options(IgnoreSoftDeletesOption())
        else:
            return q

    def add(self, instance):
        if not self.ignore_soft_deletes or not instance.is_deleted:
            self._session.add(instance)
        else:
            raise Exception("Why are you adding a deleted object?")

    def add_all(self, instances):
        if True not in [i.is_deleted for i in instances] or \
                not self.ignore_soft_deletes:
            self._session.add_all(instances)
        else:
            raise Exception("Why are you adding a deleted object?")

    def delete(self, instance):
        if self.ignore_soft_deletes:
            instance.mark_deleted()
            # just to make sure
            self._session.add(instance)
        else:
            self._session.delete(instance)

    def begin(self):
        self._session.begin()

    def commit(self):
        self._session.commit()

    def rollback(self):
        self._session.rollback()

    def flush(self):
        self._session.flush()

    def close(self):
        self._session.close()

    def expunge(self, obj):
        self._session.expunge(obj)

    def merge(self, obj):
        return self._session.merge(obj)

    @property
    def no_autoflush(self):
        return self._session.no_autoflush
# inspect the current state of an object
state = inspect(user)
assert state.persistent

################################################################################
#                              expunge
# Expunging removes an object from the session.
#     Pending instances are sent to the transient state.
#     Persistent instances from flush() are sent to detached state. Qualify
# their attributes are valid.
#     Persistent instances from query are sent to detached state and expired.
# By default, qualify their attribute will cause DetachedInstanceError, for no
# no session can be used to reload these instances from database again.
#     All the scenes will not change the instances' attributes.
################################################################################
session.expunge(user)


################################################################################
#                              rollback
# rollback DOES NOT remove all the instances from the session.
#     For pending instances and persistent instances that result by flush(),
# they are expunged and set to transient state. Their attributes will not be
# changed.
#     For persistent instances result by query(), they are still persistent
# but expired, which means that qualify their attributes will reload them by
# emitting a query.
#     All objects not expunged are fully expired.
################################################################################
session.rollback() 
Exemple #9
0
# inspect the current state of an object
state = inspect(user)
assert state.persistent

################################################################################
#                              expunge
# Expunging removes an object from the session.
#     Pending instances are sent to the transient state.
#     Persistent instances from flush() are sent to detached state. Qualify
# their attributes are valid.
#     Persistent instances from query are sent to detached state and expired.
# By default, qualify their attribute will cause DetachedInstanceError, for no
# no session can be used to reload these instances from database again.
#     All the scenes will not change the instances' attributes.
################################################################################
session.expunge(user)

################################################################################
#                              rollback
# rollback DOES NOT remove all the instances from the session.
#     For pending instances and persistent instances that result by flush(),
# they are expunged and set to transient state. Their attributes will not be
# changed.
#     For persistent instances result by query(), they are still persistent
# but expired, which means that qualify their attributes will reload them by
# emitting a query.
#     All objects not expunged are fully expired.
################################################################################
session.rollback()

################################################################################