コード例 #1
0
def test_removing_book_with_missing_file_removes_all_traces_in_db(
        peewee_database):
    from cozy.model.book import Book
    from cozy.db.book import Book as BookDB
    from cozy.db.track import Track
    from cozy.db.file import File
    from cozy.db.track_to_file import TrackToFile

    book = Book(peewee_database, 1)
    track_ids = [chapter.id for chapter in book.chapters]
    track_to_file_ids = [
        track_to_file.id for track_to_file in TrackToFile.select().join(
            Track).where(TrackToFile.track.id << track_ids)
    ]
    file_ids = [
        track_to_file.file.id for track_to_file in TrackToFile.select().join(
            Track).where(TrackToFile.track.id << track_ids)
    ]

    assert len(track_ids) > 0
    assert len(track_to_file_ids) > 0
    assert len(file_ids) > 0

    File.get_by_id(file_ids[0]).delete_instance()

    book.remove()

    assert BookDB.select().where(BookDB.id == 1).count() == 0
    assert Track.select().where(Track.id << track_ids).count() == 0
    assert TrackToFile.select().where(
        TrackToFile.id << track_to_file_ids).count() == 0
    assert File.select().where(File.id << file_ids).count() == 0
コード例 #2
0
ファイル: test_database_importer.py プロジェクト: geigi/cozy
def test_delete_all_tracks_from_db_does_as_it_says():
    from cozy.media.media_file import MediaFile
    from cozy.media.chapter import Chapter
    from cozy.db.file import File
    from cozy.db.track import Track
    from cozy.db.track_to_file import TrackToFile
    from cozy.model.database_importer import DatabaseImporter

    database_importer = DatabaseImporter()

    chapter = Chapter("Ohne Aussicht auf Freiheit", 0, 1234567, 999)
    media_file = MediaFile(
        book_name="Test Book New",
        author="New Author2",
        reader="New Reader",
        disk=999,
        cover=b"cover",
        path="20.000 Meilen unter dem Meer/2-10 Ohne Aussicht auf Freiheit.m4a",
        modified=1234567,
        chapters=[chapter])

    assert Track.select().where(
        Track.name == "Ohne Aussicht auf Freiheit").count() == 1
    assert TrackToFile.select().join(File).where(
        TrackToFile.file.path == media_file.path).count() == 1

    database_importer._delete_tracks_from_db(media_file)
    assert Track.select().where(
        Track.name == "Ohne Aussicht auf Freiheit").count() == 0
    assert TrackToFile.select().join(File).where(
        TrackToFile.file.path == media_file.path).count() == 0
    assert File.select().where(File.path == media_file.path).count() == 1
コード例 #3
0
ファイル: test_track.py プロジェクト: geigi/cozy
def test_track_to_file_not_present_throws_exception_and_deletes_track_instance(peewee_database):
    from cozy.db.track_to_file import TrackToFile
    from cozy.db.track import Track as TrackDB
    from cozy.model.track import Track, TrackInconsistentData

    TrackToFile.select().join(TrackDB).where(TrackToFile.track.id == 1).get().delete_instance()
    with pytest.raises(TrackInconsistentData):
        Track(peewee_database, 1)

    assert not TrackDB.get_or_none(1)
コード例 #4
0
ファイル: conftest.py プロジェクト: geigi/cozy
def peewee_database():
    from cozy.db.track import Track
    from cozy.db.book import Book
    from cozy.db.settings import Settings
    from cozy.db.storage_blacklist import StorageBlackList
    from cozy.db.storage import Storage
    from cozy.db.file import File
    from cozy.db.track_to_file import TrackToFile

    db_path, models, test_db = prepare_db()

    path_of_test_folder = os.path.dirname(os.path.realpath(__file__)) + '/'

    with open(path_of_test_folder + 'books.json') as json_file:
        book_data = json.load(json_file)

    with open(path_of_test_folder + 'tracks.json') as json_file:
        track_data = json.load(json_file)

    with open(path_of_test_folder + 'files.json') as json_file:
        file_data = json.load(json_file)

    with open(path_of_test_folder + 'track_to_file.json') as json_file:
        track_to_file_data = json.load(json_file)

    Book.insert_many(book_data).execute()
    for chunk in chunks(track_data, 25):
        Track.insert_many(chunk).execute()

    for chunk in chunks(file_data, 25):
        File.insert_many(chunk).execute()

    for chunk in chunks(track_to_file_data, 25):
        TrackToFile.insert_many(chunk).execute()

    with open(path_of_test_folder + 'storages.json') as json_file:
        storage_data = json.load(json_file)

    Storage.insert_many(storage_data).execute()

    Settings.create(path="", last_played_book=Book.get())
    StorageBlackList.create(path="/path/to/replace/test1.mp3")
    StorageBlackList.create(path="/path/to/not/replace/test2.mp3")

    print("Provide database...")
    yield test_db

    teardown_db(db_path, models, test_db)
コード例 #5
0
ファイル: test_database_importer.py プロジェクト: geigi/cozy
def test_insert_track_inserts_all_rows_expected():
    from cozy.model.database_importer import DatabaseImporter, TrackInsertRequest
    from cozy.db.book import Book
    from cozy.db.file import File
    from cozy.db.track_to_file import TrackToFile

    database_importer = DatabaseImporter()

    file = File.create(path="New File", modified=1234567)
    track_data = {
        "name": "Test",
        "number": 2,
        "disk": 2,
        "book": Book.select().where(Book.name == "Test Book").get(),
        "length": 123,
        "position": 0
    }

    track = TrackInsertRequest(track_data, file, 1234)

    database_importer._insert_tracks([track])
    track_to_file_query = TrackToFile.select().join(File).where(
        TrackToFile.file == file.id)
    assert track_to_file_query.count() == 1

    track_to_file: TrackToFile = track_to_file_query.get()

    assert track_to_file.track.name == track_data["name"]
    assert track_to_file.track.number == track_data["number"]
    assert track_to_file.track.disk == track_data["disk"]
    assert track_to_file.track.book.id == Book.select().where(
        Book.name == "Test Book").get().id
    assert track_to_file.track.length == track_data["length"]
    assert track_to_file.track.position == track_data["position"]
コード例 #6
0
ファイル: test_database_importer.py プロジェクト: geigi/cozy
def test_prepare_db_objects_recreates_existing_track(mocker):
    from cozy.model.database_importer import DatabaseImporter
    from cozy.media.media_file import MediaFile
    from cozy.media.chapter import Chapter
    from cozy.db.track_to_file import TrackToFile
    from cozy.db.file import File

    database_importer = DatabaseImporter()

    chapter = Chapter("New Chapter", 0, 1234567, 999)
    media_file = MediaFile(book_name="Test Book",
                           author="New Author",
                           reader="New Reader",
                           disk=999,
                           cover=b"cover",
                           path="test.mp3",
                           modified=1234567,
                           chapters=[chapter])

    res = database_importer._prepare_track_db_objects([media_file])
    res_list = list(res)
    request = res_list[0]

    assert TrackToFile.select().join(File).where(
        File.path == "test.mp3").count() == 0

    assert len(res_list) == 1
    assert request.file.path == "test.mp3"
    assert request.start_at == 0
    assert request.track_data["name"] == "New Chapter"
    assert request.track_data["number"] == 999
    assert request.track_data["disk"] == 999
    assert request.track_data["book"].id == 1
    assert request.track_data["length"] == 1234567
    assert request.track_data["position"] == 0
コード例 #7
0
    def _get_track_db_objects_for_media_file(
            self, media_file: MediaFile) -> List[Track]:
        all_track_mappings = TrackToFile.select().join(File).where(
            TrackToFile.file.path == media_file.path)

        for item in all_track_mappings:
            yield item.track
コード例 #8
0
ファイル: test_track.py プロジェクト: geigi/cozy
def test_setting_file_updates_in_track_object_and_database(peewee_database):
    from cozy.db.track_to_file import TrackToFile
    from cozy.model.track import Track

    track = Track(peewee_database, 1)
    track.file = "altered.mp3"
    file = TrackToFile.get(TrackToFile.track == track.id).file
    assert track.file == "altered.mp3"
    assert file.path == "altered.mp3"
コード例 #9
0
    def _exchange_file(self, file: File):
        old_file_id = self._track_to_file_db_object.file.id
        self._track_to_file_db_object.file = file
        self._track_to_file_db_object.save(
            only=self._track_to_file_db_object.dirty_fields)

        if TrackToFile.select().join(File).where(
                TrackToFile.file.id == old_file_id).count() == 0:
            File.delete().where(File.id == old_file_id).execute()
コード例 #10
0
ファイル: test_track.py プロジェクト: geigi/cozy
def test_setting_modified_updates_in_track_object_and_database(peewee_database):
    from cozy.model.track import Track
    from cozy.db.track_to_file import TrackToFile

    track = Track(peewee_database, 1)
    track.modified = 42
    track_to_file = TrackToFile.select().where(TrackToFile.track == track._db_object.id).get()

    assert track.modified == 42
    assert track_to_file.file.modified == 42
コード例 #11
0
    def delete(self):
        file_id = self.file_id
        self._db_object.delete_instance(recursive=True)

        if TrackToFile.select().join(File).where(
                TrackToFile.file.id == file_id).count() == 0:
            File.delete().where(File.id == file_id).execute()

        self.emit_event("chapter-deleted", self)
        self.destroy_listeners()
コード例 #12
0
ファイル: test_track.py プロジェクト: geigi/cozy
def test_setting_file_gets_file_object_if_it_is_already_present_in_database(peewee_database):
    from cozy.db.track_to_file import TrackToFile
    from cozy.db.file import File
    from cozy.model.track import Track

    track = Track(peewee_database, 1)
    track.file = "file with multiple chapters.m4b"
    file = TrackToFile.get(TrackToFile.track == track.id).file

    assert track.file == "file with multiple chapters.m4b"
    assert file.path == "file with multiple chapters.m4b"
    assert File.select().where(File.id == 0).count() == 0
コード例 #13
0
ファイル: test_track.py プロジェクト: geigi/cozy
def test_delete_deletes_track_from_db(peewee_database, mocker):
    from cozy.db.track import Track as TrackModel
    from cozy.db.track_to_file import TrackToFile
    from cozy.model.track import Track

    track = Track(peewee_database, 1)
    spy = mocker.spy(track, "emit_event")
    track.delete()

    assert TrackModel.select().where(TrackModel.id == 1).count() < 1
    assert TrackToFile.select().join(TrackModel).where(TrackToFile.track.id == 1).count() < 1
    spy.assert_called_once_with("chapter-deleted", track)
    assert len(track._listeners) < 1
コード例 #14
0
ファイル: test_track.py プロジェクト: geigi/cozy
def test_setting_file_gets_file_object_if_it_is_already_present_in_database_but_preserves_old_file_if_still_used(
        peewee_database):
    from cozy.db.track_to_file import TrackToFile
    from cozy.db.file import File
    from cozy.model.track import Track

    track = Track(peewee_database, 230)
    track.file = "Changed path"
    file = TrackToFile.get(TrackToFile.track == track.id).file

    assert track.file == "Changed path"
    assert file.path == "Changed path"
    assert File.select().where(File.id == 229).count() == 1
コード例 #15
0
    def __init__(self, db: SqliteDatabase, id: int):
        super().__init__()
        self._db: SqliteDatabase = db
        self.id: int = id

        self._db_object: TrackModel = TrackModel.get(self.id)
        self._track_to_file_db_object: TrackToFile = TrackToFile.get_or_none(
            TrackToFile.track == self.id)
        if not self._track_to_file_db_object:
            log.error(
                "Inconsistent DB, TrackToFile object is missing. Deleting this track."
            )
            self._db_object.delete_instance(recursive=True,
                                            delete_nullable=False)
            raise TrackInconsistentData
コード例 #16
0
    def remove(self):
        if self._settings.last_played_book and self._settings.last_played_book.id == self._db_object.id:
            self._settings.last_played_book = None

        book_tracks = [
            TrackModel.get_by_id(chapter.id) for chapter in self.chapters
        ]
        track_to_files = TrackToFile.select().join(TrackModel).where(
            TrackToFile.track << book_tracks)

        for track in track_to_files:
            try:
                track.file.delete_instance(recursive=True)
            except DoesNotExist:
                track.delete_instance()

        for track in book_tracks:
            track.delete_instance(recursive=True)

        self._db_object.delete_instance(recursive=True)
        self.destroy_listeners()
        self._destroy_observers()
コード例 #17
0
def _update_db_9(db):
    log.info("Migrating to DB Version 9...")

    models = generate_models(db)

    migrator: SqliteMigrator = SqliteMigrator(db)

    db.create_tables([File, TrackToFile])
    db.stop()
    db.start()

    files: List[File] = []
    track_to_files: List[TrackToFile] = []
    file_id = 1

    if "file" in models["track"]._meta.sorted_field_names:
        log.info("Generating File and TrackToFile objects...")
        for track in models["track"].select():
            path = track.file

            file = next((f for f in files if f.path == path), None)

            if File.select().where(File.path == path).count() > 0:
                log.info("Path already existing in db: {}".format(path))
                file = File.select().where(File.path == path).get()
            elif not file:
                file = File(path=path, modified=track.modified, id=file_id)
                files.append(file)
                file_id += 1

            if TrackToFile.select().join(Track).where(
                    TrackToFile.track.id == track.id).count() > 0:
                log.info("TrackToFile already existing in db: {}".format(path))
                continue

            track_to_file = TrackToFile(track=track, file=file, start_at=0)
            track_to_files.append(track_to_file)

        log.info("Inserting File and TrackToFile objects...")
        File.bulk_create(files, batch_size=300)
        TrackToFile.bulk_create(track_to_files, batch_size=300)

    field = ForeignKeyField(File, null=True, field=File.id)

    if "cached_file" not in models["offlinecache"]._meta.sorted_field_names:
        log.info("Rename in OfflineCache: file to cached_file...")
        migrate(migrator.rename_column("offlinecache", "file",
                                       "cached_file"), )

    if "original_file" not in models["offlinecache"]._meta.sorted_field_names:
        log.info("Add in OfflineCache: original_file_id...")
        migrate(migrator.add_column("offlinecache", "original_file_id", field))

    db.stop()
    db.start()
    models = generate_models(db)

    if "file" in models["track"]._meta.sorted_field_names:
        log.info("Migrating OfflineCache...")
        for cache in models["offlinecache"].select():
            file_query = File.select().where(File.path == cache.track.file)
            if file_query.count() < 0:
                cache.delete_instance()

            file = file_query.get()
            cache.original_file = file
            cache.save(only=cache.dirty_fields)

    if "file" in models["track"]._meta.sorted_field_names:
        log.info("Drop in Track: file...")
        migrate(migrator.drop_column("track", "file"))

    if "modified" in models["track"]._meta.sorted_field_names:
        log.info("Drop in Track: modified...")
        migrate(migrator.drop_column("track", "modified"))

    if "track_id" in models["offlinecache"]._meta.sorted_field_names:
        log.info("Drop in OfflineCache: track_id...")
        migrate(migrator.drop_column("offlinecache", "track_id"))

    migrate(migrator.add_not_null("offlinecache", "original_file_id"))

    db.stop()
    db.start()

    log.info("Reset modified on all m4b files")
    File.update(modified=0).where(fn.Lower(
        File.path).endswith("m4b")).execute()

    db.stop()
    db.start()

    Settings.update(version=9).execute()
コード例 #18
0
    def _get_chapter_count_in_db(self, media_file: MediaFile) -> int:
        all_track_mappings = TrackToFile.select().join(File).where(
            TrackToFile.file.path == media_file.path)

        return all_track_mappings.count()
コード例 #19
0
 def _insert_tracks(self, tracks: Set[TrackInsertRequest]):
     for track in tracks:
         track_db = Track.insert(track.track_data).execute()
         TrackToFile.create(track=track_db,
                            file=track.file,
                            start_at=track.start_at)
コード例 #20
0
 def _get_book_to_file(self, file: File):
     track_to_file = TrackToFile.select().join(File).where(
         TrackToFile.file == file.id).get()
     return track_to_file.track.book