Exemplo n.º 1
0
 def assert_breaking(self, breaking: bool, from_version: int,
                     to_version: int) -> None:
     self.assertEqual(dbver.semver_is_breaking(from_version, to_version),
                      breaking)
     if breaking:
         with self.assertRaises(dbver.VersionError):
             dbver.semver_check_breaking(from_version, to_version)
     else:
         dbver.semver_check_breaking(from_version, to_version)
Exemplo n.º 2
0
 def _apply(self, jobs: Iterable[Job]) -> None:
     with dbver.begin_pool(self._pool, dbver.IMMEDIATE) as conn:
         dbver.semver_check_breaking(LATEST, upgrade(conn))
         for job in jobs:
             try:
                 job(conn)
             except apsw.Error:
                 _LOG.exception(
                     "dropped resume data update %r",
                     job,
                 )
Exemplo n.º 3
0
def iter_resume_data_from_db(conn: apsw.Connection) -> Iterator[lt.add_torrent_params]:
    version = get_version(conn)
    if version == 0:
        return
    dbver.semver_check_breaking(LATEST, version)
    cur = conn.cursor().execute(
        "SELECT info_sha1, info_sha256, resume_data, info FROM torrent"
    )
    for row in cur:
        info_sha1, info_sha256, resume_data, info = cast(
            tuple[Optional[bytes], Optional[bytes], bytes, Optional[bytes]], row
        )
        # NB: certain fields (creation date, creator, comment) live in the torrent_info
        # object at runtime, but are serialized with the resume data. If the b"info"
        # field is empty, the torrent_info won't be created, and these fields will be
        # dropped. We want to deserialize the resume data all at once, rather than
        # deserialize the torrent_info separately.
        info_dict: Optional[Any] = None
        if info is not None:
            try:
                with ltpy.translate_exceptions():
                    info_dict = lt.bdecode(info)
            except ltpy.Error:
                _LOG.exception(
                    "%s parsing info dict", _log_ih_bytes(info_sha1, info_sha256)
                )
        try:
            with ltpy.translate_exceptions():
                bdecoded = lt.bdecode(resume_data)
                if not isinstance(bdecoded, dict):
                    _LOG.error(
                        "%s resume data not a dict",
                        _log_ih_bytes(info_sha1, info_sha256),
                    )
                    continue
                if bdecoded.get(b"info") is None and info_dict is not None:
                    bdecoded[b"info"] = info_dict
                yield lt.read_resume_data(lt.bencode(bdecoded))
        except ltpy.Error:
            _LOG.exception(
                "%s parsing resume data", _log_ih_bytes(info_sha1, info_sha256)
            )
Exemplo n.º 4
0
def _user_write(pool: dbver.Pool) -> Iterator[Tuple[sqlite3.Connection, int]]:
    with dbver.begin_pool(pool, dbver.LockMode.IMMEDIATE) as conn:
        version = user_db.upgrade(conn)
        dbver.semver_check_breaking(version, _USER_VERSION_SUPPORTED)
        yield (conn, version)
Exemplo n.º 5
0
def _meta_read(pool: dbver.Pool) -> Iterator[Tuple[sqlite3.Connection, int]]:
    with dbver.begin_pool(pool, dbver.LockMode.DEFERRED) as conn:
        version = metadata_db.get_version(conn)
        dbver.semver_check_breaking(version, _META_VERSION_SUPPORTED)
        yield (conn, version)
Exemplo n.º 6
0
def write_metadata_db() -> Iterator[Tuple[sqlite3.Connection, int]]:
    # TODO: should we set WAL? where?
    with dbver.begin_pool(metadata_db_pool, dbver.LockMode.IMMEDIATE) as conn:
        version = metadata_db.upgrade(conn)
        dbver.semver_check_breaking(version, METADATA_DB_VERSION_SUPPORTED)
        yield (conn, version)