示例#1
0
    def test_move(self, real_album_factory, tmp_config, tmp_path):
        """Test all items in the library are moved when the command is invoked."""
        cli_args = ["move"]
        tmp_settings = f"""
        default_plugins = ["move"]
        [move]
        library_path = '''{tmp_path.resolve()}'''
        """
        config = tmp_config(tmp_settings)
        config.init_db()

        album1 = real_album_factory()
        album2 = real_album_factory()

        with session_scope() as session:
            session.merge(album1)
            session.merge(album2)

        moe.cli.main(cli_args, config)

        with session_scope() as new_session:
            albums = new_session.execute(sa.select(Album)).scalars().all()

            for album in albums:
                assert tmp_path in album.path.parents

                for track in album.tracks:
                    assert tmp_path in track.path.parents

                for extra in album.extras:
                    assert tmp_path in extra.path.parents
示例#2
0
    def test_parse_args(self, real_track, tmp_path, tmp_config):
        """Music is removed from the library when the `remove` command is invoked."""
        cli_args = ["remove", "*"]
        config = tmp_config(settings='default_plugins = ["remove"]')
        config.init_db()
        with session_scope() as session:
            session.add(real_track)

        moe.cli.main(cli_args, config)

        with session_scope() as session2:
            assert not session2.query(Track).scalar()
示例#3
0
    def test_add_album(self, real_album, tmp_config, tmp_path):
        """Albums are copied to `library_path` after they are added."""
        cli_args = ["add", str(real_album.path)]
        tmp_settings = f"""
        default_plugins = ["add", "move"]
        [move]
        library_path = '''{tmp_path.resolve()}'''
        """
        config = tmp_config(tmp_settings)

        og_paths = [track.path for track in real_album.tracks]
        og_paths += [extra.path for extra in real_album.extras]
        og_paths.append(real_album.path)
        for track in real_album.tracks:
            assert tmp_path not in track.path.parents
        for extra in real_album.extras:
            assert tmp_path not in extra.path.parents

        moe.cli.main(cli_args, config)

        with session_scope() as session:
            album = session.query(Album).one()

            assert tmp_path in album.path.parents
            assert album.path.exists()
            for new_track in album.tracks:
                assert tmp_path in new_track.path.parents
                assert new_track.path.exists()
            for new_extra in album.extras:
                assert tmp_path in new_extra.path.parents
                assert new_extra.path.exists()

        for og_path in og_paths:
            assert og_path.exists()
示例#4
0
    def test_write_through_flush(self, real_album, tmp_config):
        """If a flush occurs, ensure we still write all items that changed.

        A database "flush" will occur if querying, or if editing an association
        attribute. This test ensures we aren't just naively checking `session.dirty` to
        get a list of all edited items.
        """
        new_genre = "new genre"
        cli_args = ["edit", "*", f"genre={new_genre}"]

        tmp_settings = """
        default_plugins = ["edit", "write"]
        """
        config = tmp_config(tmp_settings)
        config.init_db()
        og_paths = [track.path for track in real_album.tracks]

        with session_scope() as session:
            session.merge(real_album)

        moe.cli.main(cli_args, config)

        new_tracks = [Track.from_tags(path) for path in og_paths]
        for track in new_tracks:
            assert track.genre == new_genre
示例#5
0
    def test_prompt_choice(self, mock_mb_by_id, mock_mb_search, real_album,
                           tmp_config):
        """We can search from user input."""
        cli_args = ["add", str(real_album.path)]
        config = tmp_config(
            settings='default_plugins = ["add", "musicbrainz"]')

        mock_q = Mock()
        mock_q.ask.side_effect = [musicbrainz._enter_id, prompt._apply_changes]
        with patch("moe.plugins.add.prompt.questionary.rawselect",
                   return_value=mock_q):
            mock_q = Mock()
            mock_q.ask.return_value = "new id"
            with patch("moe.plugins.add.prompt.questionary.text",
                       return_value=mock_q):
                cli.main(cli_args, config)

        mock_mb_by_id.assert_called_with("new id",
                                         includes=musicbrainz.RELEASE_INCLUDES)

        with session_scope() as session:
            album = session.query(Album).one()

            assert album.artist == "Kanye West"
            assert album.date == datetime.date(2010, 11, 22)
            assert album.mb_album_id == "2fcfcaaa-6594-4291-b79f-2d354139e108"
            assert album.title == "My Beautiful Dark Twisted Fantasy"
示例#6
0
    def test_parse_args(self, real_track, tmp_config):
        """Music is edited when the `edit` command is invoked."""
        new_title = "Lovely Day"
        assert real_track.title != new_title
        cli_args = ["edit", "*", f"title={new_title}"]

        config = tmp_config(settings='default_plugins = ["edit"]')
        config.init_db()
        with session_scope() as pre_edit_session:
            pre_edit_session.add(real_track)

        moe.cli.main(cli_args, config)

        with session_scope() as post_edit_session:
            edited_track = post_edit_session.query(Track).one()

            assert edited_track.title == "Lovely Day"
示例#7
0
文件: test_add.py 项目: jtpavlock/Moe
    def test_file(self, real_track, tmp_config):
        """Tracks are added to the library when a file is passed to `add`."""
        cli_args = ["add", str(real_track.path)]
        config = tmp_config(settings='default_plugins = ["add"]')

        moe.cli.main(cli_args, config)

        with session_scope() as session:
            assert session.query(Track).one()
示例#8
0
    def test_dup(self, mock_track_factory, tmp_session):
        """Duplicate tracks should raise a DbDupAlbumError."""
        track1 = mock_track_factory()
        track2 = mock_track_factory()
        track2.track_num = track1.track_num

        with pytest.raises(DbDupAlbumError):
            with session_scope() as session:
                session.add(track1)
                session.add(track2)
示例#9
0
    def test_dup(self, mock_album_factory, tmp_session):
        """Duplicate albums should raise a DbDupAlbumError."""
        album1 = mock_album_factory()
        album2 = mock_album_factory()
        album1.date = album2.date

        with pytest.raises(DbDupAlbumError):
            with session_scope() as session:
                session.add(album1)
                session.add(album2)
示例#10
0
    def test_parse_args(self, capsys, real_track, tmp_config):
        """A track's info is printed when the `info` command is invoked."""
        cli_args = ["info", "*"]

        config = tmp_config(settings='default_plugins = ["info"]')
        config.init_db()
        with session_scope() as session:
            session.add(real_track)

        moe.cli.main(cli_args, config)

        assert capsys.readouterr().out
示例#11
0
    def test_parse_args(self, capsys, real_track, tmp_config):
        """Music is listed from the library when the `list` command is invoked."""
        cli_args = ["list", "*"]

        config = tmp_config(settings='default_plugins = ["list"]')
        config.init_db()
        with session_scope() as session:
            session.add(real_track)

        moe.cli.main(cli_args, config)

        assert capsys.readouterr().out
示例#12
0
    def test_commit_on_systemexit(self, real_track, tmp_config):
        """If SystemExit intentionally raised, still commit the session."""
        cli_args = ["add", "bad_file", str(real_track.path)]
        config = tmp_config(settings='default_plugins = ["add"]')

        with pytest.raises(SystemExit) as error:
            moe.cli.main(cli_args, config)

        assert error.value.code != 0

        with session_scope() as session:
            session.query(Track).one()
示例#13
0
    def test_dup_path(self, mock_album_factory, tmp_session):
        """Duplicate albums can also be defined as having the same path.

        These should also raise the same DbDupTrackError.
        """
        album1 = mock_album_factory()
        album2 = mock_album_factory()
        album2.path = album1.path

        with pytest.raises(DbDupAlbumError):
            with session_scope() as session:
                session.add(album1)
                session.add(album2)
示例#14
0
文件: test_add.py 项目: jtpavlock/Moe
    def test_album(self, real_album, tmp_config):
        """Prompt is run with a plugin implementing the ``import_album`` hook."""
        cli_args = ["add", str(real_album.path)]
        config = tmp_config(settings='default_plugins = ["add"]')
        config.plugin_manager.register(ImportPlugin)

        mock_q = Mock()
        mock_q.ask.return_value = add.prompt._apply_changes
        with patch("moe.plugins.add.prompt.questionary.rawselect",
                   return_value=mock_q):
            moe.cli.main(cli_args, config)

        with session_scope() as session:
            album = session.query(Album).one()
            assert album.title == "pre-add plugin"
示例#15
0
文件: conftest.py 项目: jtpavlock/Moe
def tmp_session() -> Iterator[Session]:
    """Creates temporary Session instance for database interaction.

    The database is a temporary sqlite instance created in memory.

    Yields:
        session: temp Session instance
    """
    engine = sqlalchemy.create_engine("sqlite:///:memory:")

    config = Config(config_dir=MagicMock())
    config.init_db(engine=engine)

    with session_scope() as session:
        yield session
示例#16
0
    def test_dup_merge(self, real_album_factory, tmp_session):
        """Duplicate errors should not occur if the existing album is merged."""
        album1 = real_album_factory()
        album2 = real_album_factory()
        album1.date = album2.date
        album1.path = album2.path

        album1.tracks.pop(0)
        album1.extras.pop(0)

        with session_scope() as session:
            session.add(album1)
            album2.merge(album2.get_existing(session))
            session.merge(album2)

            db_album = session.query(Album).one()
            assert sorted(db_album.tracks) == sorted(album2.tracks)
            assert sorted(db_album.extras) == sorted(album2.extras)
示例#17
0
    def test_edit_track(self, real_track, tmp_config):
        """Any altered Tracks have their tags written."""
        new_title = "Summertime"
        cli_args = ["edit", "*", f"title={new_title}"]

        tmp_settings = """
        default_plugins = ["edit", "write"]
        """
        config = tmp_config(tmp_settings)
        config.init_db()
        og_path = real_track.path

        with session_scope() as session:
            session.add(real_track)

        moe.cli.main(cli_args, config)

        new_track = Track.from_tags(og_path)
        assert new_track.title == new_title
示例#18
0
    def test_album(self, mock_mb_by_id, mock_mb_search, real_album,
                   tmp_config):
        """We can import and add an album to the library."""
        cli_args = ["add", str(real_album.path)]
        config = tmp_config(
            settings='default_plugins = ["add", "musicbrainz"]')

        mock_q = Mock()
        mock_q.ask.return_value = prompt._apply_changes
        with patch("moe.plugins.add.prompt.questionary.rawselect",
                   return_value=mock_q):
            cli.main(cli_args, config)

        with session_scope() as session:
            album = session.query(Album).one()

            assert album.artist == "Kanye West"
            assert album.date == datetime.date(2010, 11, 22)
            assert album.mb_album_id == "2fcfcaaa-6594-4291-b79f-2d354139e108"
            assert album.title == "My Beautiful Dark Twisted Fantasy"
示例#19
0
def _parse_args(args: List[str], config: Config):
    """Parses the commandline arguments.

    Args:
        args: Arguments to parse. Should not include 'moe'.
        config: User configuration for moe.

    Raises:
        SystemExit: No sub-commands given.
            Does not include root commands such as `--version` or `--help`.
    """
    moe_parser = _create_arg_parser()

    # load all sub-commands
    cmd_parsers = moe_parser.add_subparsers(help="command to run",
                                            dest="command")
    config.plugin_manager.hook.add_command(cmd_parsers=cmd_parsers)

    parsed_args = moe_parser.parse_args(args)

    # no sub-command given
    if not parsed_args.command:
        moe_parser.print_help(sys.stderr)
        raise SystemExit(1)

    _set_root_log_lvl(parsed_args)

    # call the sub-command's handler within a single session
    config.init_db()
    with session_scope() as session:
        sqlalchemy.event.listen(
            session, "before_flush",
            functools.partial(_edit_new_items, config=config))
        sqlalchemy.event.listen(
            session, "after_flush",
            functools.partial(_process_new_items, config=config))

        parsed_args.func(config, session, args=parsed_args)