コード例 #1
0
ファイル: artist.py プロジェクト: azuline/repertoire
def create(name: str, conn: Connection) -> T:
    """
    Create an artist and persist it to the database.

    :param name: The name of the artist.
    :param conn: A connection to the database.
    :return: The newly created artist.
    :raises Duplicate: If an artist with the same name already exists. The duplicate
                       artist is passed as the ``entity`` argument.
    """
    if art := from_name(name, conn):
        raise Duplicate(f'Artist "{name}" already exists.', art)
コード例 #2
0
ファイル: image.py プロジェクト: azuline/repertoire
def create(path: Union[Path, str], conn: Connection) -> T:
    """
    Create an image with the given path.

    :param path: The path of the image file.
    :param conn: A connection to the database.
    :return: The newly created image.
    :raises Duplicate: If an image with the given path already exists. The duplicate
                       image is passed as the ``entity`` argument.
    """
    if img := from_path(path, conn):
        raise Duplicate("An image with the given path already exists.", img)
コード例 #3
0
ファイル: artist.py プロジェクト: azuline/repertoire
def update(art: T, conn: Connection, **changes) -> T:
    """
    Update an artist and persist changes to the database. To update a value, pass it
    in as a keyword argument. To keep the original value, do not pass in a keyword
    argument.

    :param art: The artist to update.
    :param conn: A connection to the database.
    :param name: New artist name.
    :type  name: :py:obj:`str`
    :return: The updated artist.
    :raises Duplicate: If an artist already exists with the new name.
    """
    if "name" in changes and (dupl := from_name(changes["name"],
                                                conn)) and dupl != art:
        raise Duplicate(f'Artist "{changes["name"]}" already exists.', dupl)
コード例 #4
0
ファイル: playlist.py プロジェクト: azuline/repertoire
def update(ply: T, conn: Connection, **changes) -> T:
    """
    Update a playlist and persist changes to the database. To update a value, pass it
    in as a keyword argument. To keep the original value, do not pass in a keyword
    argument.

    **Note: The type and user_id of a playlist cannot be changed.**

    :param ply: The playlist to update.
    :param conn: A connection to the database.
    :param name: New playlist name.
    :type  name: :py:obj:`str`
    :return: The updated playlist.
    :raises Immutable: If the playlist cannot be updated.
    :raises Duplicate: If the new name conflicts with another playlist.
    """
    if ply.type == PlaylistType.SYSTEM:
        raise Immutable("System playlists cannot be modified.")

    if ("name" in changes and (dupl := from_name_type_user(
            changes["name"], ply.type, conn, ply.user_id)) and dupl != ply):
        raise Duplicate(f'Playlist "{changes["name"]}" already exists.', dupl)
コード例 #5
0
ファイル: playlist.py プロジェクト: azuline/repertoire
def create(
    name: str,
    type: PlaylistType,
    conn: Connection,
    user_id: Optional[int] = None,
    override_immutable: bool = False,
) -> T:
    """
    Create a playlist and persist it to the database.

    :param name: The name of the playlist.
    :param type: The type of the playlist.
    :param conn: A connection to the database.
    :param user_id: The ID of the user that this playlist belongs to. Should be set for
                    Personal and System playlists; unset otherwise.
    :param override_immutable: Whether to allow creation of immutable playlists. For
                               internal use.
    :return: The newly created playlist.
    :raises Duplicate: If an playlist with the same name and type already exists. The
                       duplicate playlist is passed as the ``entity`` argument.
    :raises InvalidArgument: If the user_id argument is passed with a non-personal
                             playlist type.
    """
    if type == PlaylistType.SYSTEM and not override_immutable:
        raise InvalidPlaylistType("Cannot create system playlists.")

    if type in [PlaylistType.PERSONAL, PlaylistType.SYSTEM
                ] and user_id is None:
        raise InvalidArgument(
            "Missing user_id argument for personal/system collection.")

    if type not in [PlaylistType.PERSONAL, PlaylistType.SYSTEM
                    ] and user_id is not None:
        raise InvalidArgument(
            "The user_id argument can only be set for personal/system collections."
        )

    if ply := from_name_type_user(name, type, conn, user_id):
        raise Duplicate(f'Playlist "{name}" already exists.', ply)
コード例 #6
0
ファイル: collection.py プロジェクト: azuline/repertoire
def update(col: T, conn: Connection, **changes) -> T:
    """
    Update a collection and persist changes to the database. To update a value, pass it
    in as a keyword argument. To keep the original value, do not pass in a keyword
    argument.

    **Note: The type of a collection cannot be changed.**

    :param col: The collection to update.
    :param conn: A connection to the database.
    :param name: New collection name.
    :type  name: :py:obj:`str`
    :return: The updated collection.
    :raises Immutable: If the collection cannot be updated.
    :raises Duplicate: If the new name conflicts with another collection.
    """
    if col.type == CollectionType.SYSTEM:
        raise Immutable("System collections cannot be modified.")

    if ("name" in changes and (dupl := from_name_type_user(
            changes["name"], col.type, conn, col.user_id)) and dupl != col):
        raise Duplicate(f'Collection "{changes["name"]}" already exists.',
                        dupl)
コード例 #7
0
def calculate_track_full_sha256(trk: T, conn: Connection) -> bytes:
    """
    Given a track, calculate its full SHA256. If the newly calculated SHA256 is
    equivalent to an existing track's SHA256, delete the passed-in track and raise a
    Duplicate error with the existing track.

    :param trk: The track.
    :param conn: A connection to the DB.
    :return: The calculated SHA256.
    :raises FileNotFoundError: If the track no longer exists.
    :raises Duplicate: If the calculated sha256 is the same as an existing track. The
                       existing track is attached to the error.
    """
    logger.debug(f"Calculating SHA256 for {trk.filepath}.")
    sha256sum = calculate_sha256(trk.filepath)

    # The newly calculated sha256 is a duplicate of another track...
    # To deduplicate, delete the new track.
    if dup := from_sha256(sha256sum, conn):
        logger.info(
            f"Track {trk.id} is a hash-duplicate of {dup.id}. Deleting {trk.id}."
        )
        delete(trk, conn)
        raise Duplicate("Duplicate SHA256 detected.", dup)
コード例 #8
0
ファイル: release.py プロジェクト: azuline/repertoire
    :raises Duplicate: If a release with the same name and artists already exists. The
                       duplicate release is passed as the ``entity`` argument.
    """
    if bad_ids := [
            d["artist_id"] for d in artists
            if not artist.exists(d["artist_id"], conn)
    ]:
        logger.debug(
            f"Artist(s) {', '.join(str(i) for i in bad_ids)} do not exist.")
        raise NotFound(
            f"Artist(s) {', '.join(str(i) for i in bad_ids)} do not exist.")

    if not allow_duplicate and (rls := _find_duplicate_release(
            title, artists, conn)):
        logger.debug(f"Release already exists with ID {rls.id}.")
        raise Duplicate(
            "A release with the same name and artists already exists.", rls)

    # Insert the release into the database.
    cursor = conn.execute(
        """
        INSERT INTO music__releases (
            title, image_id, release_type, release_year, release_date, rating
        ) VALUES (?, ?, ?, ?, ?, ?)
        """,
        (title, image_id, release_type.value, release_year, release_date,
         rating),
    )
    id_ = cursor.lastrowid

    # Insert the release artists into the database.
    for mapping in artists:
コード例 #9
0
        logger.debug(f"Release {release_id} does not exist.")
        raise NotFound(f"Release {release_id} does not exist.")

    if bad_ids := [
            d["artist_id"] for d in artists
            if not artist.exists(d["artist_id"], conn)
    ]:
        logger.debug(
            f"Artist(s) {', '.join(str(i) for i in bad_ids)} do not exist.")
        raise NotFound(
            f"Artist(s) {', '.join(str(i) for i in bad_ids)} do not exist.")

    # First, check to see if a track with the same filepath exists.
    if trk := from_filepath(filepath, conn):
        logger.debug("A track with this filepath already exists.")
        raise Duplicate("A track with this filepath already exists.", trk)

    # Next, check to see if a track with the same sha256 exists.
    if trk := _check_for_duplicate_sha256(sha256_initial, filepath, conn):
        return trk

    # Track is not a duplicate, so we can insert and return.
    cursor = conn.execute(
        """
        INSERT INTO music__tracks (
            title,
            filepath,
            sha256_initial,
            release_id,
            track_number,
            disc_number,