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 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) Book.insert_many(book_data).execute() for chunk in chunks(track_data, 25): Track.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)
def write_tracks_to_db(tracks): """ """ if tracks is None or len(tracks) < 1: return if PeeweeVersion[0] == '2': data = list({ "name": t.name, "number": t.track_number, "disk": t.disk, "position": t.position, "book": t.book, "file": t.file, "length": t.length, "modified": t.modified } for t in tracks) Track.insert_many(data).execute() else: fields = [ Track.name, Track.number, Track.disk, Track.position, Track.book, Track.file, Track.length, Track.modified ] data = list((t.name, t.track_number, t.disk, t.position, t.book, t.file, t.length, t.modified) for t in tracks) Track.insert_many(data, fields=fields).execute()
def play_pause(track, jump=False): """ Play a new file or pause/play if the file is already loaded. :param track: Track object that will be played/paused. """ global __current_track global __player global __wait_to_seek global __set_speed __wait_to_seek = jump if __current_track == track or track is None: # Track is already selected, only play/pause if get_gst_player_state() == Gst.State.PLAYING: __player.set_state(Gst.State.PAUSED) emit_event("pause") save_current_track_position() else: __player.set_state(Gst.State.PLAYING) emit_event("play", Track.get(Track.id == __current_track.id)) else: load_file(track) __player.set_state(Gst.State.PLAYING) emit_event("play", Track.get(Track.id == __current_track.id)) __set_speed = True
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
def on_close(self, widget, data=None): """ Close and dispose everything that needs to be when window is closed. """ log.info("Closing.") self.titlebar.close() self.fs_monitor.close() if self.sleep_timer.is_running(): self.sleep_timer.stop() # save current position when still playing if player.get_gst_player_state() == Gst.State.PLAYING: Track.update(position=player.get_current_duration()).where( Track.id == player.get_current_track().id).execute() player.stop() player.dispose() close_db() report.close() log.info("Closing app.") self.app.quit() log.info("App closed.")
def test_setting_length_updates_in_track_object_and_database(peewee_database): from cozy.db.track import Track as TrackModel from cozy.model.track import Track track = Track(peewee_database, 1) track.length = 42.42 assert track.length == 42.42 assert TrackModel.get_by_id(1).length == 42.42
def test_setting_file_updates_in_track_object_and_database(peewee_database): from cozy.db.track import Track as TrackModel from cozy.model.track import Track track = Track(peewee_database, 1) track.file = "altered.mp3" assert track.file == "altered.mp3" assert TrackModel.get_by_id(1).file == "altered.mp3"
def test_setting_disk_updates_in_track_object_and_database(peewee_database): from cozy.db.track import Track as TrackModel from cozy.model.track import Track track = Track(peewee_database, 1) track.disk = 2 assert track.disk == 2 assert TrackModel.get_by_id(1).disk == 2
def _update_track_db_object(self, media_file: MediaFile, book: BookModel): Track.update(name=media_file.chapters[0].name, number=media_file.track_number, book=book, disk=media_file.disk, length=media_file.length, modified=media_file.modified) \ .where(Track.file == media_file.path) \ .execute()
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"
def test_delete_keeps_file_object_if_used_elsewhere(peewee_database): from cozy.db.file import File from cozy.model.track import Track track = Track(peewee_database, 230) file_id = track.file_id track.delete() assert File.get_or_none(file_id)
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)
def test_delete_does_not_delete_book(peewee_database): from cozy.db.track import Track as TrackModel from cozy.db.book import Book from cozy.model.track import Track track = Track(peewee_database, 1) book_id = TrackModel.get(1).book.id track.delete() assert Book.get_or_none(book_id) is not None
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
def test_delete_deletes_track_from_db(peewee_database, mocker): from cozy.db.track import Track as TrackModel 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 spy.assert_called_once_with("chapter-deleted", track) assert len(track._listeners) < 1
def save_current_track_position(pos=None, track=None): """ Saves the current track position to the cozy.db. """ if pos is None: pos = get_current_duration() if track is None: track = get_current_track() if track: Track.update(position=pos).where(Track.id == track.id).execute()
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 ] ids = list(t.id for t in book_tracks) TrackModel.delete().where(TrackModel.id << ids).execute() self._db_object.delete_instance(recursive=True) self.destroy_listeners() self._destroy_observers()
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
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
def blacklist_book(book): """ Removes a book from the library and adds the path(s) to the track list. """ book_tracks = get_tracks(book) data = list((t.file, ) for t in book_tracks) chunks = [data[x:x + 500] for x in range(0, len(data), 500)] for chunk in chunks: StorageBlackList.insert_many(chunk, fields=[StorageBlackList.path]).execute() ids = list(t.id for t in book_tracks) Track.delete().where(Track.id << ids).execute() book.delete_instance()
def blacklist(self): with self._db: book_tracks = [ TrackModel.get_by_id(chapter.id) for chapter in self._chapters ] data = list((t.file, ) for t in book_tracks) chunks = [data[x:x + 500] for x in range(0, len(data), 500)] for chunk in chunks: StorageBlackList.insert_many(chunk, fields=[StorageBlackList.path ]).execute() ids = list(t.id for t in book_tracks) TrackModel.delete().where(TrackModel.id << ids).execute() self._db_object.delete_instance()
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 ] data = list((t.file, ) for t in book_tracks) chunks = [data[x:x + 500] for x in range(0, len(data), 500)] for chunk in chunks: StorageBlackList.insert_many(chunk, fields=[StorageBlackList.path ]).execute() ids = list(t.id for t in book_tracks) TrackModel.delete().where(TrackModel.id << ids).execute() self._db_object.delete_instance(recursive=True)
def test_update_book_position_sets_position_for_single_chapter_file_correctly( ): from cozy.model.database_importer import DatabaseImporter from cozy.db.book import Book from cozy.db.track import Track database_importer = DatabaseImporter() book = Book.get_by_id(2) database_importer._update_book_position(book, 4251) book = Book.get_by_id(2) desired_chapter_position = 4251000000000.0 - ( (Track.get_by_id(198).length + Track.get_by_id(197).length) * 10**9) assert book.position == 194 assert Track.get_by_id(194).position == desired_chapter_position
def __init__(self, db: SqliteDatabase, id: int): super().__init__() self._db: SqliteDatabase = db self.id: int = id with self._db: self._db_object: TrackModel = TrackModel.get(self.id)
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
def test_update_track_db_object_updates_object(): from cozy.model.library import Library from cozy.media.media_file import MediaFile from cozy.db.book import Book from cozy.media.chapter import Chapter from cozy.db.track import Track library = Library() chapter = Chapter("New Chapter", 0) media_file = MediaFile(book_name="New Book Name", author="New Author", reader="New Reader", disk=999, track_number=999, length=1234567, cover=b"cover", path="test.mp3", modified=1234567, chapters=[chapter]) book = Book.select().get() library._update_track_db_object(media_file, book) track_in_db: Track = Track.select().where(Track.file == "test.mp3").get() assert track_in_db.name == "New Chapter" assert track_in_db.disk == 999 assert track_in_db.number == 999 assert track_in_db.length == 1234567 assert track_in_db.modified == 1234567
def is_external(book): """ Tests whether the given book is saved on external storage. """ return any(storage.path in Track.select().join(Book).where( Book.id == book.id).first().file for storage in Storage.select().where(Storage.external == True))
def _get_db_object(self): with self._db: self._db_object: BookModel = BookModel.get(self.id) if TrackModel.select().where( TrackModel.book == self._db_object).count() < 1: raise BookIsEmpty
def load_last_book(filesystem_monitor: FilesystemMonitor): """ Load the last played book into the player. """ global __current_track global __player last_book = Settings.get().last_played_book if last_book and last_book.position != 0: query = Track.select().where(Track.id == last_book.position) if query.exists(): last_track = query.get() if last_track: __player.set_state(Gst.State.NULL) if filesystem_monitor.is_track_online(last_track): path = last_track.file else: path = OfflineCache().get_cached_path(last_track) if not path: return __player.set_property("uri", "file://" + path) __player.set_state(Gst.State.PAUSED) __current_track = last_track Book.update(last_played=int(time.time())).where( Book.id == last_book.id).execute() emit_event("track-changed", last_track)
def __on_button_press(self, eventbox, event): """ Play the selected track. """ current_track = player.get_current_track() if current_track and current_track.id == self.track.id: player.play_pause(None) if player.get_gst_player_state() == Gst.State.PLAYING: player.jump_to_ns(Track.select().where( Track.id == self.track.id).get().position) else: player.load_file( Track.select().where(Track.id == self.track.id).get()) player.play_pause(None, True) Book.update(position=self.track).where( Book.id == self.track.book.id).execute()