def _create_shallow_releases_mb(mb_artist): """ Create CachedReleaseGroup documents using basic MusicBrainz data fetched with artist. @param mb_artist: a musicbrainz2.model.Artist object """ mb_releases = mb_artist.getReleases() artist_mbid = extractUuid(mb_artist.id) # magical place where all data is cached/processed before database commit there_will_be_dragons = {} for mb_release in mb_releases: group_mbid = extractUuid(mb_release.releaseGroup.id) release_mbid = extractUuid(mb_release.id) # its ugly, but we fill this only once (place for future improvements) if group_mbid not in there_will_be_dragons: release_group = {} release_group['_id'] = group_mbid release_group['artist_mbid'] = artist_mbid release_group['artist_name'] = mb_artist.name release_group['title'] = mb_release.releaseGroup.title # small fix: in some rare cases, ReleaseGroup at Musicbrainz has no 'type' property release_group['release_type'] = decruft_mb(mb_release.releaseGroup.type) if mb_release.releaseGroup.type else 'Other' release_group['releases'] = {} there_will_be_dragons[group_mbid] = release_group else: release_group = there_will_be_dragons[group_mbid] # store only basic information about release event mb_release_events = [] for mb_event in mb_release.getReleaseEvents(): event = {} if mb_event.date: event['date'] = mb_event.date if mb_event.format: event['format'] = decruft_mb(mb_event.format) if mb_event.country: event['country'] = mb_event.country if event: mb_release_events.append(event) release_group['releases'][release_mbid] = { 'title':mb_release.title, 'tracks_count':mb_release.tracksCount, 'release_events':mb_release_events, 'cache_state':{'mb':[1,datetime.utcnow()]} } # primary release is the one with earliest release date (place for future improvements) mb_earliest_release_date = mb_release.getEarliestReleaseEvent().getDate() if mb_release.getEarliestReleaseEvent() else None if 'primary' not in release_group or release_group['primary'][1] == None or mb_earliest_release_date < release_group['primary'][1]: release_group['primary'] = [release_mbid, mb_earliest_release_date] # just to make sure no old data is left.. old_cached_release_groups = get_db('artists').view('artists/release_groups', key=artist_mbid) for group in old_cached_release_groups: del get_db('artists')[group['id']] for release_group in there_will_be_dragons.itervalues(): cached_release_group = CachedReleaseGroup.wrap(release_group) # TODO: think if wrap is the best way of dealing with this cached_release_group.cache_state['mb'] = [1,datetime.utcnow()] cached_release_group.save() # TODO: add try in case of ResourceConflict? mmda_logger('db','store', cached_release_group)
def _populate_deep_release_mb(release_group,release_mbid): """ Make sure ReleaseGroup contains additional, detailed information about specified release. @param release_group: a CachedReleaseGroup object @param release_mbid: a string containing a MusicBrainz ID of a release @return: a verified/updated CachedReleaseGroup object """ release = release_group.releases[release_mbid] if release['cache_state']['mb'][0] == 1: # TODO: remove unused includes try: t = mmda_logger('mb','request','release',release_mbid) mb_release = mb_query.getReleaseById(release_mbid, MB_RELEASE_INCLUDES) mmda_logger('mb','result','release',mb_release.title,t) except WebServiceError, e: # TODO: hard error here mmda_logger('mb-release','ERROR',e) raise e else: # make sure mbid of an artist is present if 'artist_mbid' not in release_group: release_group.artist_mbid = extractUuid(mb_release.artist.id) # TRACK LISTING # TODO: think about duration representation here tracks = [] for mb_track in mb_release.tracks: track = {'title':mb_track.title, 'mbid':extractUuid(mb_track.id)} if mb_track.duration: track['duration'] = humanize_duration(mb_track.duration) tracks.append(track) release['tracks'] = tracks # URL relations urls = {} for relation in mb_release.getRelations(Relation.TO_URL): relation_type = decruft_mb(relation.type) if relation_type not in urls: urls[relation_type] = [] urls[relation_type].append(relation.targetId) # urls is used in many places, so its handy to have it ready release['urls'] = urls # CREDIT relations credits = [{'type':decruft_mb(r.type), 'mbid':extractUuid(r.targetId), 'name':r.target.name} for r in mb_release.getRelations(Relation.TO_ARTIST)] if credits: release['credits'] = credits # MULTI-DISC-RELEASE information remasters = [] for relation in mb_release.getRelations(Relation.TO_RELEASE): relation_type = decruft_mb(relation.type) linked_release = {'mbid':extractUuid(relation.targetId), 'title':relation.target.title} if relation_type == 'PartOfSet': if relation.direction == 'backward': release['set_prev'] = linked_release else: release['set_next'] = linked_release elif relation_type == 'Remaster': if relation.direction == 'backward': remasters.append(linked_release) else: release['remaster_of'] = linked_release if remasters: release['remasters'] = remasters release['cache_state']['mb'] = [2,datetime.utcnow()] release_group = _perform_cover_lookup_on_mb_data(release_group, release_mbid) release_group.changes_present = True
def _populate_artist_mb(artist, mb_artist): """ Process data from MusicBrainz and store it in dedicated structures of CachedArtist. @param artist: a CachedArtist object @param mb_artist: a musicbrainz2.model.Artist object @return: a populated CachedArtist object """ artist.artist_type = decruft_mb(mb_artist.type) artist.name = mb_artist.name artist.sort_name = mb_artist.sortName if mb_artist.disambiguation: artist.disambiguation = mb_artist.disambiguation if mb_artist.aliases: artist.aliases = [a.value for a in mb_artist.aliases] if mb_artist.beginDate or mb_artist.endDate: artist.dates = {} if mb_artist.beginDate: artist.dates['from'] = mb_artist.beginDate if mb_artist.endDate: artist.dates['to'] = mb_artist.endDate # urls are stored in dict with lists as values (there can be many of the same type) urls = {} for relation in mb_artist.getRelations(Relation.TO_URL): relation_type = decruft_mb(relation.type) if relation_type not in urls: urls[relation_type] = [] urls[relation_type].append(relation.targetId) if urls: artist.urls = urls # on the other hand, memberships and collaborations are stored in lists of dicts ;-) members = [] member_of = [] collaborations = [] collaboration_of = [] for relation in mb_artist.getRelations(Relation.TO_ARTIST): relation_type = decruft_mb(relation.type) if relation_type == 'MemberOfBand': member_info = { 'name':relation.target.name, 'mbid':extractUuid(relation.targetId), 'from':relation.beginDate, 'to':relation.endDate } if relation.direction == 'backward': members.append(member_info) else: member_of.append(member_info) elif relation_type == 'Collaboration': member_info = { 'name':relation.target.name, 'mbid':extractUuid(relation.targetId) } if relation.direction == 'backward': collaboration_of.append(member_info) else: collaborations.append(member_info) if members: artist.members = members if member_of: artist.member_of = member_of if collaborations: artist.collaborations = collaborations if collaboration_of: artist.collaboration_of = collaboration_of return artist