Sort albums by month if two releases of the same artist happen in the same year #155

Merged
8 changed files with 227 additions and 113 deletions
Showing only changes of commit 88d1dc2b01 - Show all commits

View File

@ -118,6 +118,12 @@ impl Merge for Album {
} }
} }
impl<S: Into<String>> From<S> for AlbumId {
fn from(value: S) -> Self {
AlbumId::new(value)
}
}
impl AsRef<AlbumId> for AlbumId { impl AsRef<AlbumId> for AlbumId {
fn as_ref(&self) -> &AlbumId { fn as_ref(&self) -> &AlbumId {
self self
@ -193,6 +199,32 @@ mod tests {
assert!(album_1 < album_2); assert!(album_1 < album_2);
} }
#[test]
fn set_clear_seq() {
let mut album = Album {
id: "an album".into(),
date: AlbumDate::default(),
seq: AlbumSeq::default(),
tracks: vec![],
};
assert_eq!(album.seq, AlbumSeq(0));
// Setting a seq on an album.
album.set_seq(AlbumSeq(6));
assert_eq!(album.seq, AlbumSeq(6));
album.set_seq(AlbumSeq(6));
assert_eq!(album.seq, AlbumSeq(6));
album.set_seq(AlbumSeq(8));
assert_eq!(album.seq, AlbumSeq(8));
// Clearing seq.
album.clear_seq();
assert_eq!(album.seq, AlbumSeq(0));
}
#[test] #[test]
fn merge_album_no_overlap() { fn merge_album_no_overlap() {
let left = FULL_COLLECTION[0].albums[0].to_owned(); let left = FULL_COLLECTION[0].albums[0].to_owned();

View File

@ -2,6 +2,7 @@ use std::{
collections::HashMap, collections::HashMap,
fmt::{self, Debug, Display}, fmt::{self, Debug, Display},
mem, mem,
str::FromStr,
}; };
use url::Url; use url::Url;
@ -139,6 +140,12 @@ impl Merge for Artist {
} }
} }
impl<S: Into<String>> From<S> for ArtistId {
fn from(value: S) -> Self {
ArtistId::new(value)
}
}
impl AsRef<ArtistId> for ArtistId { impl AsRef<ArtistId> for ArtistId {
fn as_ref(&self) -> &ArtistId { fn as_ref(&self) -> &ArtistId {
self self
@ -169,9 +176,13 @@ pub struct MusicBrainz(Url);
impl MusicBrainz { impl MusicBrainz {
/// Validate and wrap a MusicBrainz URL. /// Validate and wrap a MusicBrainz URL.
pub fn new<S: AsRef<str>>(url: S) -> Result<Self, Error> { pub fn new_from_str<S: AsRef<str>>(url: S) -> Result<Self, Error> {
let url = Url::parse(url.as_ref())?; let url = Url::parse(url.as_ref())?;
Self::new_from_url(url)
}
/// Validate and wrap a MusicBrainz URL.
pub fn new_from_url(url: Url) -> Result<Self, Error> {
if !url if !url
.domain() .domain()
.map(|u| u.ends_with("musicbrainz.org")) .map(|u| u.ends_with("musicbrainz.org"))
@ -199,11 +210,36 @@ impl AsRef<str> for MusicBrainz {
} }
} }
impl TryFrom<&str> for MusicBrainz { impl FromStr for MusicBrainz {
type Err = Error;
fn from_str(s: &str) -> Result<Self, Self::Err> {
MusicBrainz::new_from_str(s)
}
}
// A blanket TryFrom would be better, but https://stackoverflow.com/a/64407892
macro_rules! impl_try_from_for_musicbrainz {
($from:ty) => {
impl TryFrom<$from> for MusicBrainz {
type Error = Error;
fn try_from(value: $from) -> Result<Self, Self::Error> {
MusicBrainz::new_from_str(value)
}
}
};
}
impl_try_from_for_musicbrainz!(&str);
impl_try_from_for_musicbrainz!(&String);
impl_try_from_for_musicbrainz!(String);
impl TryFrom<Url> for MusicBrainz {
type Error = Error; type Error = Error;
fn try_from(value: &str) -> Result<Self, Self::Error> { fn try_from(value: Url) -> Result<Self, Self::Error> {
MusicBrainz::new(value) MusicBrainz::new_from_url(value)
} }
} }
@ -230,34 +266,35 @@ mod tests {
#[test] #[test]
fn musicbrainz() { fn musicbrainz() {
let uuid = "d368baa8-21ca-4759-9731-0b2753071ad8"; let uuid = "d368baa8-21ca-4759-9731-0b2753071ad8";
let url = format!("https://musicbrainz.org/artist/{uuid}"); let url_str = format!("https://musicbrainz.org/artist/{uuid}");
let mb = MusicBrainz::new(&url).unwrap(); let url: Url = url_str.as_str().try_into().unwrap();
assert_eq!(url, mb.as_ref()); let mb: MusicBrainz = url.try_into().unwrap();
assert_eq!(url_str, mb.as_ref());
assert_eq!(uuid, mb.mbid()); assert_eq!(uuid, mb.mbid());
let url = "not a url at all".to_string(); let url = "not a url at all".to_string();
let expected_error: Error = url::ParseError::RelativeUrlWithoutBase.into(); let expected_error: Error = url::ParseError::RelativeUrlWithoutBase.into();
let actual_error = MusicBrainz::new(url).unwrap_err(); let actual_error = MusicBrainz::from_str(&url).unwrap_err();
assert_eq!(actual_error, expected_error); assert_eq!(actual_error, expected_error);
assert_eq!(actual_error.to_string(), expected_error.to_string()); assert_eq!(actual_error.to_string(), expected_error.to_string());
let url = "https://musicbrainz.org/artist/i-am-not-a-uuid".to_string(); let url = "https://musicbrainz.org/artist/i-am-not-a-uuid".to_string();
let expected_error: Error = Uuid::try_parse("i-am-not-a-uuid").unwrap_err().into(); let expected_error: Error = Uuid::try_parse("i-am-not-a-uuid").unwrap_err().into();
let actual_error = MusicBrainz::new(url).unwrap_err(); let actual_error = MusicBrainz::from_str(&url).unwrap_err();
assert_eq!(actual_error, expected_error); assert_eq!(actual_error, expected_error);
assert_eq!(actual_error.to_string(), expected_error.to_string()); assert_eq!(actual_error.to_string(), expected_error.to_string());
let url = "https://musicbrainz.org/artist".to_string(); let url = "https://musicbrainz.org/artist".to_string();
let expected_error = Error::UrlError(format!("invalid MusicBrainz URL: {url}")); let expected_error = Error::UrlError(format!("invalid MusicBrainz URL: {url}"));
let actual_error = MusicBrainz::new(&url).unwrap_err(); let actual_error = MusicBrainz::from_str(&url).unwrap_err();
assert_eq!(actual_error, expected_error); assert_eq!(actual_error, expected_error);
assert_eq!(actual_error.to_string(), expected_error.to_string()); assert_eq!(actual_error.to_string(), expected_error.to_string());
} }
#[test] #[test]
fn urls() { fn urls() {
assert!(MusicBrainz::new(MUSICBRAINZ).is_ok()); assert!(MusicBrainz::from_str(MUSICBRAINZ).is_ok());
assert!(MusicBrainz::new(MUSICBUTLER).is_err()); assert!(MusicBrainz::from_str(MUSICBUTLER).is_err());
} }
#[test] #[test]
@ -266,7 +303,7 @@ mod tests {
let sort_id_1 = ArtistId::new("sort id 1"); let sort_id_1 = ArtistId::new("sort id 1");
let sort_id_2 = ArtistId::new("sort id 2"); let sort_id_2 = ArtistId::new("sort id 2");
let mut artist = Artist::new(artist_id.clone()); let mut artist = Artist::new(&artist_id.name);
assert_eq!(artist.id, artist_id); assert_eq!(artist.id, artist_id);
assert_eq!(artist.sort, None); assert_eq!(artist.sort, None);
@ -317,14 +354,14 @@ mod tests {
// Setting a URL on an artist. // Setting a URL on an artist.
artist.set_musicbrainz_url(MUSICBRAINZ.try_into().unwrap()); artist.set_musicbrainz_url(MUSICBRAINZ.try_into().unwrap());
_ = expected.insert(MusicBrainz::new(MUSICBRAINZ).unwrap()); _ = expected.insert(MUSICBRAINZ.try_into().unwrap());
assert_eq!(artist.musicbrainz, expected); assert_eq!(artist.musicbrainz, expected);
artist.set_musicbrainz_url(MUSICBRAINZ.try_into().unwrap()); artist.set_musicbrainz_url(MUSICBRAINZ.try_into().unwrap());
assert_eq!(artist.musicbrainz, expected); assert_eq!(artist.musicbrainz, expected);
artist.set_musicbrainz_url(MUSICBRAINZ_2.try_into().unwrap()); artist.set_musicbrainz_url(MUSICBRAINZ_2.try_into().unwrap());
_ = expected.insert(MusicBrainz::new(MUSICBRAINZ_2).unwrap()); _ = expected.insert(MUSICBRAINZ_2.try_into().unwrap());
assert_eq!(artist.musicbrainz, expected); assert_eq!(artist.musicbrainz, expected);
// Clearing URLs. // Clearing URLs.

View File

@ -5,7 +5,7 @@ use serde::Deserialize;
use crate::core::{ use crate::core::{
collection::{ collection::{
album::{Album, AlbumDate, AlbumId, AlbumSeq}, album::{Album, AlbumDate, AlbumId, AlbumSeq},
artist::{Artist, ArtistId, MusicBrainz}, artist::{Artist, ArtistId},
Collection, Collection,
}, },
database::LoadError, database::LoadError,
@ -51,7 +51,7 @@ impl TryFrom<DeserializeArtist> for Artist {
Ok(Artist { Ok(Artist {
id: ArtistId::new(artist.name), id: ArtistId::new(artist.name),
sort: artist.sort.map(ArtistId::new), sort: artist.sort.map(ArtistId::new),
musicbrainz: artist.musicbrainz.map(MusicBrainz::new).transpose()?, musicbrainz: artist.musicbrainz.map(TryInto::try_into).transpose()?,
properties: artist.properties, properties: artist.properties,
albums: artist.albums.into_iter().map(Into::into).collect(), albums: artist.albums.into_iter().map(Into::into).collect(),
}) })

View File

@ -3,7 +3,7 @@ use std::collections::HashMap;
use crate::core::{ use crate::core::{
collection::{ collection::{
album::{Album, AlbumDate, AlbumId, AlbumSeq}, album::{Album, AlbumDate, AlbumId, AlbumSeq},
artist::{Artist, ArtistId}, artist::{Artist, ArtistId, MusicBrainz},
track::{Track, TrackId, TrackNum, TrackQuality}, track::{Track, TrackId, TrackNum, TrackQuality},
Collection, MergeCollections, Collection, MergeCollections,
}, },
@ -259,63 +259,61 @@ impl<LIB, DB: IDatabase> MusicHoard<LIB, DB> {
Ok(()) Ok(())
} }
fn update_collection<FN>(&mut self, func: FN) -> Result<(), Error> fn update_collection<FnColl>(&mut self, fn_coll: FnColl) -> Result<(), Error>
where where
FN: FnOnce(&mut Collection), FnColl: FnOnce(&mut Collection),
{ {
func(&mut self.pre_commit); fn_coll(&mut self.pre_commit);
self.commit() self.commit()
} }
fn update_artist_and<ID: AsRef<ArtistId>, FNARTIST, FNCOLL>( fn update_artist_and<FnArtist, FnColl>(
&mut self, &mut self,
artist_id: ID, artist_id: &ArtistId,
fn_artist: FNARTIST, fn_artist: FnArtist,
fn_collection: FNCOLL, fn_coll: FnColl,
) -> Result<(), Error> ) -> Result<(), Error>
where where
FNARTIST: FnOnce(&mut Artist), FnArtist: FnOnce(&mut Artist),
FNCOLL: FnOnce(&mut Collection), FnColl: FnOnce(&mut Collection),
{ {
fn_artist(Self::get_artist_mut_or_err( let artist = Self::get_artist_mut_or_err(&mut self.pre_commit, artist_id)?;
&mut self.pre_commit, fn_artist(artist);
artist_id.as_ref(), self.update_collection(fn_coll)
)?);
self.update_collection(fn_collection)
} }
fn update_artist<ID: AsRef<ArtistId>, FN>( fn update_artist<FnArtist>(
&mut self, &mut self,
artist_id: ID, artist_id: &ArtistId,
func: FN, fn_artist: FnArtist,
) -> Result<(), Error> ) -> Result<(), Error>
where where
FN: FnOnce(&mut Artist), FnArtist: FnOnce(&mut Artist),
{ {
self.update_artist_and(artist_id, func, |_| {}) self.update_artist_and(artist_id, fn_artist, |_| {})
} }
fn update_album_and<ARTIST: AsRef<ArtistId>, ALBUM: AsRef<AlbumId>, FNALBUM, FNARTIST, FNCOLL>( fn update_album_and<FnAlbum, FnArtist, FnColl>(
&mut self, &mut self,
artist_id: ARTIST, artist_id: &ArtistId,
album_id: ALBUM, album_id: &AlbumId,
fn_album: FNALBUM, fn_album: FnAlbum,
fn_artist: FNARTIST, fn_artist: FnArtist,
fn_collection: FNCOLL, fn_coll: FnColl,
) -> Result<(), Error> ) -> Result<(), Error>
where where
FNALBUM: FnOnce(&mut Album), FnAlbum: FnOnce(&mut Album),
FNARTIST: FnOnce(&mut Artist), FnArtist: FnOnce(&mut Artist),
FNCOLL: FnOnce(&mut Collection), FnColl: FnOnce(&mut Collection),
{ {
let artist = Self::get_artist_mut_or_err(&mut self.pre_commit, artist_id.as_ref())?; let artist = Self::get_artist_mut_or_err(&mut self.pre_commit, artist_id)?;
let album = Self::get_album_mut_or_err(artist, album_id.as_ref())?; let album = Self::get_album_mut_or_err(artist, album_id)?;
fn_album(album); fn_album(album);
fn_artist(artist); fn_artist(artist);
self.update_collection(fn_collection) self.update_collection(fn_coll)
} }
pub fn add_artist<ID: Into<ArtistId>>(&mut self, artist_id: ID) -> Result<(), Error> { pub fn add_artist<IntoId: Into<ArtistId>>(&mut self, artist_id: IntoId) -> Result<(), Error> {
let artist_id: ArtistId = artist_id.into(); let artist_id: ArtistId = artist_id.into();
self.update_collection(|collection| { self.update_collection(|collection| {
@ -326,7 +324,7 @@ impl<LIB, DB: IDatabase> MusicHoard<LIB, DB> {
}) })
} }
pub fn remove_artist<ID: AsRef<ArtistId>>(&mut self, artist_id: ID) -> Result<(), Error> { pub fn remove_artist<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
self.update_collection(|collection| { self.update_collection(|collection| {
let index_opt = collection.iter().position(|a| &a.id == artist_id.as_ref()); let index_opt = collection.iter().position(|a| &a.id == artist_id.as_ref());
if let Some(index) = index_opt { if let Some(index) = index_opt {
@ -335,102 +333,109 @@ impl<LIB, DB: IDatabase> MusicHoard<LIB, DB> {
}) })
} }
pub fn set_artist_sort<ID: AsRef<ArtistId>, SORT: Into<ArtistId>>( pub fn set_artist_sort<Id: AsRef<ArtistId>, IntoId: Into<ArtistId>>(
&mut self, &mut self,
artist_id: ID, artist_id: Id,
artist_sort: SORT, artist_sort: IntoId,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist_and( self.update_artist_and(
artist_id, artist_id.as_ref(),
|artist| artist.set_sort_key(artist_sort), |artist| artist.set_sort_key(artist_sort),
|collection| Self::sort_artists(collection), |collection| Self::sort_artists(collection),
) )
} }
pub fn clear_artist_sort<ID: AsRef<ArtistId>>(&mut self, artist_id: ID) -> Result<(), Error> { pub fn clear_artist_sort<Id: AsRef<ArtistId>>(&mut self, artist_id: Id) -> Result<(), Error> {
self.update_artist_and( self.update_artist_and(
artist_id, artist_id.as_ref(),
|artist| artist.clear_sort_key(), |artist| artist.clear_sort_key(),
|collection| Self::sort_artists(collection), |collection| Self::sort_artists(collection),
) )
} }
pub fn set_artist_musicbrainz<ID: AsRef<ArtistId>, S: AsRef<str>>( pub fn set_artist_musicbrainz<Id: AsRef<ArtistId>, Mb: TryInto<MusicBrainz, Error = E>, E>(
&mut self, &mut self,
artist_id: ID, artist_id: Id,
url: S, url: Mb,
) -> Result<(), Error> { ) -> Result<(), Error>
let url = url.as_ref().try_into()?; where
self.update_artist(artist_id, |artist| artist.set_musicbrainz_url(url)) Error: From<E>,
{
let mb = url.try_into()?;
self.update_artist(artist_id.as_ref(), |artist| artist.set_musicbrainz_url(mb))
} }
pub fn clear_artist_musicbrainz<ID: AsRef<ArtistId>>( pub fn clear_artist_musicbrainz<Id: AsRef<ArtistId>>(
&mut self, &mut self,
artist_id: ID, artist_id: Id,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id, |artist| artist.clear_musicbrainz_url()) self.update_artist(artist_id.as_ref(), |artist| artist.clear_musicbrainz_url())
} }
pub fn add_to_artist_property<ID: AsRef<ArtistId>, S: AsRef<str> + Into<String>>( pub fn add_to_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
&mut self, &mut self,
artist_id: ID, artist_id: Id,
property: S, property: S,
values: Vec<S>, values: Vec<S>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id, |artist| artist.add_to_property(property, values)) self.update_artist(artist_id.as_ref(), |artist| {
artist.add_to_property(property, values)
})
} }
pub fn remove_from_artist_property<ID: AsRef<ArtistId>, S: AsRef<str>>( pub fn remove_from_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
&mut self, &mut self,
artist_id: ID, artist_id: Id,
property: S, property: S,
values: Vec<S>, values: Vec<S>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id, |artist| { self.update_artist(artist_id.as_ref(), |artist| {
artist.remove_from_property(property, values) artist.remove_from_property(property, values)
}) })
} }
pub fn set_artist_property<ID: AsRef<ArtistId>, S: AsRef<str> + Into<String>>( pub fn set_artist_property<Id: AsRef<ArtistId>, S: AsRef<str> + Into<String>>(
&mut self, &mut self,
artist_id: ID, artist_id: Id,
property: S, property: S,
values: Vec<S>, values: Vec<S>,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id, |artist| artist.set_property(property, values)) self.update_artist(artist_id.as_ref(), |artist| {
artist.set_property(property, values)
})
} }
pub fn clear_artist_property<ID: AsRef<ArtistId>, S: AsRef<str>>( pub fn clear_artist_property<Id: AsRef<ArtistId>, S: AsRef<str>>(
&mut self, &mut self,
artist_id: ID, artist_id: Id,
property: S, property: S,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_artist(artist_id, |artist| artist.clear_property(property)) self.update_artist(artist_id.as_ref(), |artist| artist.clear_property(property))
} }
pub fn set_album_seq<ARTIST: AsRef<ArtistId>, ALBUM: AsRef<AlbumId>>( pub fn set_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self, &mut self,
artist_id: ARTIST, artist_id: ArtistIdRef,
album_id: ALBUM, album_id: AlbumIdRef,
seq: u8, seq: u8,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_album_and( self.update_album_and(
artist_id, artist_id.as_ref(),
album_id, album_id.as_ref(),
|album| album.set_seq(AlbumSeq(seq)), |album| album.set_seq(AlbumSeq(seq)),
|artist| artist.albums.sort_unstable(), |artist| artist.albums.sort_unstable(),
|_| {}, |_| {},
) )
} }
pub fn clear_album_seq<ARTIST: AsRef<ArtistId>, ALBUM: AsRef<AlbumId>>( pub fn clear_album_seq<ArtistIdRef: AsRef<ArtistId>, AlbumIdRef: AsRef<AlbumId>>(
&mut self, &mut self,
artist_id: ARTIST, artist_id: ArtistIdRef,
album_id: ALBUM, album_id: AlbumIdRef,
) -> Result<(), Error> { ) -> Result<(), Error> {
self.update_album_and( self.update_album_and(
artist_id, artist_id.as_ref(),
album_id, album_id.as_ref(),
|album| album.clear_seq(), |album| album.clear_seq(),
|artist| artist.albums.sort_unstable(), |artist| artist.albums.sort_unstable(),
|_| {}, |_| {},
@ -621,7 +626,7 @@ mod tests {
assert!(music_hoard assert!(music_hoard
.set_artist_musicbrainz(&artist_id, MUSICBRAINZ) .set_artist_musicbrainz(&artist_id, MUSICBRAINZ)
.is_ok()); .is_ok());
_ = expected.insert(MusicBrainz::new(MUSICBRAINZ).unwrap()); _ = expected.insert(MUSICBRAINZ.try_into().unwrap());
assert_eq!(music_hoard.collection[0].musicbrainz, expected); assert_eq!(music_hoard.collection[0].musicbrainz, expected);
// Clearing URLs on an artist that does not exist is an error. // Clearing URLs on an artist that does not exist is an error.
@ -733,6 +738,51 @@ mod tests {
assert!(music_hoard.collection[0].properties.is_empty()); assert!(music_hoard.collection[0].properties.is_empty());
} }
#[test]
fn set_clear_album_seq() {
let mut database = MockIDatabase::new();
let artist_id = ArtistId::new("an artist");
let album_id = AlbumId::new("an album");
let album_id_2 = AlbumId::new("another album");
let mut database_result = vec![Artist::new(artist_id.clone())];
database_result[0].albums.push(Album {
id: album_id.clone(),
date: AlbumDate::default(),
seq: AlbumSeq::default(),
tracks: vec![],
});
database
.expect_load()
.times(1)
.return_once(|| Ok(database_result));
database.expect_save().times(2).returning(|_| Ok(()));
let mut music_hoard = MusicHoard::database(database).unwrap();
assert_eq!(music_hoard.collection[0].albums[0].seq, AlbumSeq(0));
// Seting seq on an album not belonging to the artist is an error.
assert!(music_hoard
.set_album_seq(&artist_id, &album_id_2, 6)
.is_err());
assert_eq!(music_hoard.collection[0].albums[0].seq, AlbumSeq(0));
// Set seq.
assert!(music_hoard.set_album_seq(&artist_id, &album_id, 6).is_ok());
assert_eq!(music_hoard.collection[0].albums[0].seq, AlbumSeq(6));
// Clearing seq on an album that does not exist is an error.
assert!(music_hoard
.clear_album_seq(&artist_id, &album_id_2)
.is_err());
// Clear seq.
assert!(music_hoard.clear_album_seq(&artist_id, &album_id).is_ok());
assert_eq!(music_hoard.collection[0].albums[0].seq, AlbumSeq(0));
}
#[test] #[test]
fn merge_collection_no_overlap() { fn merge_collection_no_overlap() {
let half: usize = FULL_COLLECTION.len() / 2; let half: usize = FULL_COLLECTION.len() / 2;

View File

@ -1,5 +1,5 @@
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::collections::HashMap; use std::{collections::HashMap, str::FromStr};
use crate::core::collection::{ use crate::core::collection::{
album::{Album, AlbumDate, AlbumId, AlbumMonth, AlbumSeq}, album::{Album, AlbumDate, AlbumId, AlbumMonth, AlbumSeq},

View File

@ -454,11 +454,9 @@ macro_rules! full_collection {
let artist_a = iter.next().unwrap(); let artist_a = iter.next().unwrap();
assert_eq!(artist_a.id.name, "Album_Artist A"); assert_eq!(artist_a.id.name, "Album_Artist A");
artist_a.musicbrainz = Some( artist_a.musicbrainz = Some(MusicBrainz::from_str(
MusicBrainz::new( "https://musicbrainz.org/artist/00000000-0000-0000-0000-000000000000",
"https://musicbrainz.org/artist/00000000-0000-0000-0000-000000000000", ).unwrap());
).unwrap(),
);
artist_a.properties = HashMap::from([ artist_a.properties = HashMap::from([
(String::from("MusicButler"), vec![ (String::from("MusicButler"), vec![
@ -477,11 +475,9 @@ macro_rules! full_collection {
let artist_b = iter.next().unwrap(); let artist_b = iter.next().unwrap();
assert_eq!(artist_b.id.name, "Album_Artist B"); assert_eq!(artist_b.id.name, "Album_Artist B");
artist_b.musicbrainz = Some( artist_b.musicbrainz = Some(MusicBrainz::from_str(
MusicBrainz::new( "https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111",
"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111", ).unwrap());
).unwrap(),
);
artist_b.properties = HashMap::from([ artist_b.properties = HashMap::from([
(String::from("MusicButler"), vec![ (String::from("MusicButler"), vec![
@ -504,11 +500,9 @@ macro_rules! full_collection {
let artist_c = iter.next().unwrap(); let artist_c = iter.next().unwrap();
assert_eq!(artist_c.id.name, "The Album_Artist C"); assert_eq!(artist_c.id.name, "The Album_Artist C");
artist_c.musicbrainz = Some( artist_c.musicbrainz = Some(MusicBrainz::from_str(
MusicBrainz::new( "https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111",
"https://musicbrainz.org/artist/11111111-1111-1111-1111-111111111111", ).unwrap());
).unwrap(),
);
// Nothing for artist_d // Nothing for artist_d

View File

@ -1,10 +1,11 @@
use std::{collections::HashMap, str::FromStr};
use musichoard::collection::{ use musichoard::collection::{
album::{Album, AlbumDate, AlbumId, AlbumMonth, AlbumSeq}, album::{Album, AlbumDate, AlbumId, AlbumMonth, AlbumSeq},
artist::{Artist, ArtistId, MusicBrainz}, artist::{Artist, ArtistId, MusicBrainz},
track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality}, track::{Track, TrackFormat, TrackId, TrackNum, TrackQuality},
}; };
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::collections::HashMap;
use crate::tests::*; use crate::tests::*;

View File

@ -1,5 +1,5 @@
use once_cell::sync::Lazy; use once_cell::sync::Lazy;
use std::collections::HashMap; use std::{collections::HashMap, str::FromStr};
use musichoard::collection::{ use musichoard::collection::{
album::{Album, AlbumDate, AlbumId, AlbumMonth, AlbumSeq}, album::{Album, AlbumDate, AlbumId, AlbumMonth, AlbumSeq},
@ -17,8 +17,8 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
sort: Some(ArtistId{ sort: Some(ArtistId{
name: String::from("Arkona") name: String::from("Arkona")
}), }),
musicbrainz: Some(MusicBrainz::new( musicbrainz: Some(MusicBrainz::from_str(
"https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212", "https://musicbrainz.org/artist/baad262d-55ef-427a-83c7-f7530964f212"
).unwrap()), ).unwrap()),
properties: HashMap::from([ properties: HashMap::from([
(String::from("MusicButler"), vec![ (String::from("MusicButler"), vec![
@ -204,7 +204,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
name: String::from("Eluveitie"), name: String::from("Eluveitie"),
}, },
sort: None, sort: None,
musicbrainz: Some(MusicBrainz::new( musicbrainz: Some(MusicBrainz::from_str(
"https://musicbrainz.org/artist/8000598a-5edb-401c-8e6d-36b167feaf38", "https://musicbrainz.org/artist/8000598a-5edb-401c-8e6d-36b167feaf38",
).unwrap()), ).unwrap()),
properties: HashMap::from([ properties: HashMap::from([
@ -447,7 +447,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
name: String::from("Frontside"), name: String::from("Frontside"),
}, },
sort: None, sort: None,
musicbrainz: Some(MusicBrainz::new( musicbrainz: Some(MusicBrainz::from_str(
"https://musicbrainz.org/artist/3a901353-fccd-4afd-ad01-9c03f451b490", "https://musicbrainz.org/artist/3a901353-fccd-4afd-ad01-9c03f451b490",
).unwrap()), ).unwrap()),
properties: HashMap::from([ properties: HashMap::from([
@ -600,7 +600,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
sort: Some(ArtistId { sort: Some(ArtistId {
name: String::from("Heavens Basement"), name: String::from("Heavens Basement"),
}), }),
musicbrainz: Some(MusicBrainz::new( musicbrainz: Some(MusicBrainz::from_str(
"https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc", "https://musicbrainz.org/artist/c2c4d56a-d599-4a18-bd2f-ae644e2198cc",
).unwrap()), ).unwrap()),
properties: HashMap::from([ properties: HashMap::from([
@ -730,7 +730,7 @@ pub static COLLECTION: Lazy<Vec<Artist>> = Lazy::new(|| -> Collection {
name: String::from("Metallica"), name: String::from("Metallica"),
}, },
sort: None, sort: None,
musicbrainz: Some(MusicBrainz::new( musicbrainz: Some(MusicBrainz::from_str(
"https://musicbrainz.org/artist/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab", "https://musicbrainz.org/artist/65f4f0c5-ef9e-490c-aee3-909e7ae6b2ab",
).unwrap()), ).unwrap()),
properties: HashMap::from([ properties: HashMap::from([