mirror of
https://github.com/rembo10/headphones.git
synced 2026-03-21 20:29:27 +00:00
Merge branch 'ngs'
This commit is contained in:
938
headphones/mb.py
938
headphones/mb.py
@@ -3,16 +3,13 @@ from __future__ import with_statement
|
||||
import time
|
||||
import threading
|
||||
|
||||
import lib.musicbrainz2.webservice as ws
|
||||
import lib.musicbrainz2.model as m
|
||||
import lib.musicbrainz2.utils as u
|
||||
|
||||
from lib.musicbrainz2.webservice import WebServiceError
|
||||
|
||||
import headphones
|
||||
from headphones import logger, db
|
||||
from headphones.helpers import multikeysort, replace_all
|
||||
|
||||
import lib.musicbrainzngs as musicbrainzngs
|
||||
from lib.musicbrainzngs import WebServiceError
|
||||
|
||||
mb_lock = threading.Lock()
|
||||
|
||||
|
||||
@@ -20,500 +17,477 @@ mb_lock = threading.Lock()
|
||||
# being used, so we can send those values to the log
|
||||
def startmb(forcemb=False):
|
||||
|
||||
mbuser = None
|
||||
mbpass = None
|
||||
|
||||
# Can use headphones mirror for queries
|
||||
if headphones.MIRROR == "headphones" or "custom":
|
||||
forcemb=False
|
||||
|
||||
if forcemb or headphones.MIRROR == "musicbrainz.org":
|
||||
mbhost = "musicbrainz.org"
|
||||
mbport = 80
|
||||
sleepytime = 1
|
||||
elif headphones.MIRROR == "custom":
|
||||
mbhost = headphones.CUSTOMHOST
|
||||
mbport = int(headphones.CUSTOMPORT)
|
||||
sleepytime = int(headphones.CUSTOMSLEEP)
|
||||
elif headphones.MIRROR == "headphones":
|
||||
mbhost = "178.63.142.150"
|
||||
mbport = 8181
|
||||
mbuser = headphones.HPUSER
|
||||
mbpass = headphones.HPPASS
|
||||
sleepytime = 0
|
||||
else:
|
||||
mbhost = "tbueter.com"
|
||||
mbport = 5000
|
||||
sleepytime = 0
|
||||
|
||||
service = ws.WebService(host=mbhost, port=mbport, username=mbuser, password=mbpass, mirror=headphones.MIRROR)
|
||||
q = ws.Query(service)
|
||||
|
||||
logger.debug('Using the following server values:\nMBHost: %s ; MBPort: %i ; Sleep Interval: %i ' % (mbhost, mbport, sleepytime))
|
||||
|
||||
return (q, sleepytime)
|
||||
mbuser = None
|
||||
mbpass = None
|
||||
|
||||
# Can use headphones mirror for queries
|
||||
if headphones.MIRROR == "headphones" or "custom":
|
||||
forcemb=False
|
||||
|
||||
if forcemb or headphones.MIRROR == "musicbrainz.org":
|
||||
mbhost = "musicbrainz.org"
|
||||
mbport = 80
|
||||
sleepytime = 1
|
||||
elif headphones.MIRROR == "custom":
|
||||
mbhost = headphones.CUSTOMHOST
|
||||
mbport = int(headphones.CUSTOMPORT)
|
||||
sleepytime = int(headphones.CUSTOMSLEEP)
|
||||
elif headphones.MIRROR == "headphones":
|
||||
mbhost = "178.63.142.150"
|
||||
mbport = 8181
|
||||
mbuser = headphones.HPUSER
|
||||
mbpass = headphones.HPPASS
|
||||
sleepytime = 0
|
||||
else:
|
||||
mbhost = "tbueter.com"
|
||||
mbport = 5000
|
||||
sleepytime = 0
|
||||
|
||||
musicbrainzngs.set_useragent("headphones","0.0","https://github.com/rembo10/headphones")
|
||||
musicbrainzngs.set_hostname(mbhost + ":" + str(mbport))
|
||||
if sleepytime == 0:
|
||||
musicbrainzngs.set_rate_limit(False)
|
||||
else:
|
||||
musicbrainzngs.set_rate_limit(True)
|
||||
|
||||
# Add headphones credentials
|
||||
if headphones.MIRROR == "headphones":
|
||||
if not mbuser and mbpass:
|
||||
logger.warn("No username or password set for VIP server")
|
||||
else:
|
||||
musicbrainzngs.hpauth(mbuser,mbpass)
|
||||
|
||||
#q = musicbrainzngs
|
||||
q = musicbrainzngs
|
||||
|
||||
logger.debug('Using the following server values:\nMBHost: %s ; MBPort: %i ; Sleep Interval: %i ' % (mbhost, mbport, sleepytime))
|
||||
|
||||
return (q, sleepytime)
|
||||
|
||||
def findArtist(name, limit=1):
|
||||
|
||||
with mb_lock:
|
||||
|
||||
artistlist = []
|
||||
attempt = 0
|
||||
artistResults = None
|
||||
|
||||
chars = set('!?*')
|
||||
if any((c in chars) for c in name):
|
||||
name = '"'+name+'"'
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
artistResults = q.getArtists(ws.ArtistFilter(query=name, limit=limit))
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to query MusicBrainz for %s failed (%s)' % (name, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(10)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not artistResults:
|
||||
return False
|
||||
|
||||
for result in artistResults:
|
||||
|
||||
if result.artist.name != result.artist.getUniqueName() and limit == 1:
|
||||
|
||||
logger.debug('Found an artist with a disambiguation: %s - doing an album based search' % name)
|
||||
artistdict = findArtistbyAlbum(name)
|
||||
|
||||
if not artistdict:
|
||||
logger.debug('Cannot determine the best match from an artist/album search. Using top match instead')
|
||||
artistlist.append({
|
||||
'name': result.artist.name,
|
||||
'uniquename': result.artist.getUniqueName(),
|
||||
'id': u.extractUuid(result.artist.id),
|
||||
'url': result.artist.id,
|
||||
'score': result.score
|
||||
})
|
||||
|
||||
else:
|
||||
artistlist.append(artistdict)
|
||||
|
||||
else:
|
||||
artistlist.append({
|
||||
'name': result.artist.name,
|
||||
'uniquename': result.artist.getUniqueName(),
|
||||
'id': u.extractUuid(result.artist.id),
|
||||
'url': result.artist.id,
|
||||
'score': result.score
|
||||
})
|
||||
|
||||
return artistlist
|
||||
|
||||
with mb_lock:
|
||||
artistlist = []
|
||||
artistResults = None
|
||||
|
||||
chars = set('!?*')
|
||||
if any((c in chars) for c in name):
|
||||
name = '"'+name+'"'
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
try:
|
||||
artistResults = musicbrainzngs.search_artists(query=name,limit=limit)['artist-list']
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to query MusicBrainz for %s failed (%s)' % (name, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not artistResults:
|
||||
return False
|
||||
for result in artistResults:
|
||||
if 'disambiguation' in result:
|
||||
uniquename = unicode(result['sort-name'] + " (" + result['disambiguation'] + ")")
|
||||
else:
|
||||
uniquename = unicode(result['sort-name'])
|
||||
if result['name'] != uniquename and limit == 1:
|
||||
logger.debug('Found an artist with a disambiguation: %s - doing an album based search' % name)
|
||||
artistdict = findArtistbyAlbum(name)
|
||||
if not artistdict:
|
||||
logger.debug('Cannot determine the best match from an artist/album search. Using top match instead')
|
||||
artistlist.append({
|
||||
'name': unicode(result['sort-name']),
|
||||
'uniquename': uniquename,
|
||||
'id': unicode(result['id']),
|
||||
'url': unicode("http://musicbrainz.org/artist/" + result['id']),#probably needs to be changed
|
||||
'score': int(result['ext:score'])
|
||||
})
|
||||
else:
|
||||
artistlist.append(artistdict)
|
||||
else:
|
||||
artistlist.append({
|
||||
'name': unicode(result['sort-name']),
|
||||
'uniquename': uniquename,
|
||||
'id': unicode(result['id']),
|
||||
'url': unicode("http://musicbrainz.org/artist/" + result['id']),#probably needs to be changed
|
||||
'score': int(result['ext:score'])
|
||||
})
|
||||
return artistlist
|
||||
|
||||
def findRelease(name, limit=1):
|
||||
|
||||
with mb_lock:
|
||||
|
||||
releaselist = []
|
||||
attempt = 0
|
||||
releaseResults = None
|
||||
|
||||
chars = set('!?')
|
||||
if any((c in chars) for c in name):
|
||||
name = '"'+name+'"'
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
releaseResults = q.getReleases(ws.ReleaseFilter(query=name, limit=limit))
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to query MusicBrainz for "%s" failed: %s' % (name, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(10)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not releaseResults:
|
||||
return False
|
||||
|
||||
for result in releaseResults:
|
||||
|
||||
releaselist.append({
|
||||
'uniquename': result.release.artist.name,
|
||||
'title': result.release.title,
|
||||
'id': u.extractUuid(result.release.artist.id),
|
||||
'albumid': u.extractUuid(result.release.id),
|
||||
'url': result.release.artist.id,
|
||||
'albumurl': result.release.id,
|
||||
'score': result.score
|
||||
})
|
||||
|
||||
return releaselist
|
||||
with mb_lock:
|
||||
releaselistngs = []
|
||||
releaseResultsngs = None
|
||||
|
||||
chars = set('!?')
|
||||
if any((c in chars) for c in name):
|
||||
name = '"'+name+'"'
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
try:
|
||||
releaseResultsngs = musicbrainzngs.search_releases(query=name,limit=limit)['release-list']
|
||||
except WebServiceError, e: #need to update exceptions
|
||||
logger.warn('Attempt to query MusicBrainz for "%s" failed: %s' % (name, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not releaseResultsngs:
|
||||
return False
|
||||
for result in releaseResultsngs:
|
||||
releaselistngs.append({
|
||||
'uniquename': unicode(result['artist-credit'][0]['artist']['name']),
|
||||
'title': unicode(result['title']),
|
||||
'id': unicode(result['artist-credit'][0]['artist']['id']),
|
||||
'albumid': unicode(result['id']),
|
||||
'url': unicode("http://musicbrainz.org/artist/" + result['artist-credit'][0]['artist']['id']),#probably needs to be changed
|
||||
'albumurl': unicode("http://musicbrainz.org/release/" + result['id']),#probably needs to be changed
|
||||
'score': int(result['ext:score'])
|
||||
})
|
||||
return releaselistngs
|
||||
|
||||
def getArtist(artistid, extrasonly=False):
|
||||
|
||||
with mb_lock:
|
||||
|
||||
artist_dict = {}
|
||||
|
||||
#Get all official release groups
|
||||
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, m.Release.TYPE_ALBUM), releaseGroups=True)
|
||||
artist = None
|
||||
attempt = 0
|
||||
|
||||
q, sleepytime = startmb()
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
artist = q.getArtistById(artistid, inc)
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve artist information from MusicBrainz failed for artistid: %s (%s)' % (artistid, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(5)
|
||||
|
||||
if not artist:
|
||||
return False
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
artist_dict['artist_name'] = artist.name
|
||||
artist_dict['artist_sortname'] = artist.sortName
|
||||
artist_dict['artist_uniquename'] = artist.getUniqueName()
|
||||
artist_dict['artist_type'] = u.extractFragment(artist.type)
|
||||
artist_dict['artist_begindate'] = artist.beginDate
|
||||
artist_dict['artist_enddate'] = artist.endDate
|
||||
|
||||
releasegroups = []
|
||||
|
||||
if not extrasonly:
|
||||
|
||||
for rg in artist.getReleaseGroups():
|
||||
|
||||
releasegroups.append({
|
||||
'title': rg.title,
|
||||
'id': u.extractUuid(rg.id),
|
||||
'url': rg.id,
|
||||
'type': u.getReleaseTypeName(rg.type)
|
||||
})
|
||||
|
||||
# See if we need to grab extras
|
||||
myDB = db.DBConnection()
|
||||
with mb_lock:
|
||||
artist_dict = {}
|
||||
|
||||
artist = None
|
||||
|
||||
q, sleepytime = startmb()
|
||||
|
||||
try:
|
||||
limit = 100
|
||||
artist = musicbrainzngs.get_artist_by_id(artistid)['artist']
|
||||
newRgs = None
|
||||
artist['release-group-list'] = []
|
||||
while newRgs == None or len(newRgs) >= limit:
|
||||
newRgs = musicbrainzngs.browse_release_groups(artistid,release_type="album",offset=len(artist['release-group-list']),limit=limit)['release-group-list']
|
||||
artist['release-group-list'] += newRgs
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve artist information from MusicBrainz failed for artistid: %s (%s)' % (artistid, str(e)))
|
||||
time.sleep(5)
|
||||
except Exception,e:
|
||||
pass
|
||||
|
||||
if not artist:
|
||||
return False
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if 'disambiguation' in artist:
|
||||
uniquename = unicode(artist['sort-name'] + " (" + artist['disambiguation'] + ")")
|
||||
else:
|
||||
uniquename = unicode(artist['sort-name'])
|
||||
artist_dict['artist_name'] = unicode(artist['name'])
|
||||
artist_dict['artist_sortname'] = unicode(artist['sort-name'])
|
||||
artist_dict['artist_uniquename'] = uniquename
|
||||
artist_dict['artist_type'] = unicode(artist['type'])
|
||||
|
||||
try:
|
||||
includeExtras = myDB.select('SELECT IncludeExtras from artists WHERE ArtistID=?', [artistid])[0][0]
|
||||
except IndexError:
|
||||
includeExtras = False
|
||||
|
||||
if includeExtras or headphones.INCLUDE_EXTRAS:
|
||||
includes = [m.Release.TYPE_COMPILATION, m.Release.TYPE_REMIX, m.Release.TYPE_SINGLE, m.Release.TYPE_LIVE, m.Release.TYPE_EP, m.Release.TYPE_SOUNDTRACK]
|
||||
for include in includes:
|
||||
inc = ws.ArtistIncludes(releases=(m.Release.TYPE_OFFICIAL, include), releaseGroups=True)
|
||||
|
||||
artist = None
|
||||
attempt = 0
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
artist = q.getArtistById(artistid, inc)
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve artist information from MusicBrainz failed for artistid: %s (%s)' % (artistid, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(5)
|
||||
|
||||
if not artist:
|
||||
continue
|
||||
|
||||
for rg in artist.getReleaseGroups():
|
||||
|
||||
releasegroups.append({
|
||||
'title': rg.title,
|
||||
'id': u.extractUuid(rg.id),
|
||||
'url': rg.id,
|
||||
'type': u.getReleaseTypeName(rg.type)
|
||||
})
|
||||
|
||||
artist_dict['releasegroups'] = releasegroups
|
||||
|
||||
return artist_dict
|
||||
|
||||
artist_dict['artist_begindate'] = None
|
||||
artist_dict['artist_enddate'] = None
|
||||
if 'life-span' in artist:
|
||||
if 'begin' in artist['life-span']:
|
||||
artist_dict['artist_begindate'] = unicode(artist['life-span']['begin'])
|
||||
if 'end' in artist['life-span']:
|
||||
artist_dict['artist_enddate'] = unicode(artist['life-span']['end'])
|
||||
|
||||
|
||||
|
||||
releasegroups = []
|
||||
|
||||
if not extrasonly:
|
||||
for rg in artist['release-group-list']:
|
||||
if rg['type'] != 'Album': #only add releases without a secondary type
|
||||
continue
|
||||
releasegroups.append({
|
||||
'title': unicode(rg['title']),
|
||||
'id': unicode(rg['id']),
|
||||
'url': u"http://musicbrainz.org/release-group/" + rg['id'],
|
||||
'type': unicode(rg['type'])
|
||||
})
|
||||
|
||||
# See if we need to grab extras
|
||||
myDB = db.DBConnection()
|
||||
|
||||
try:
|
||||
includeExtras = myDB.select('SELECT IncludeExtras from artists WHERE ArtistID=?', [artistid])[0][0]
|
||||
except IndexError:
|
||||
includeExtras = False
|
||||
|
||||
if includeExtras or headphones.INCLUDE_EXTRAS:
|
||||
includes = ["single", "ep", "compilation", "soundtrack", "live", "remix"]
|
||||
for include in includes:
|
||||
|
||||
artist = None
|
||||
|
||||
try:
|
||||
artist = musicbrainzngs.get_artist_by_id(artistid,includes=["releases","release-groups"],release_status=['official'],release_type=include)['artist']
|
||||
except WebServiceError, e:#update exceptions
|
||||
logger.warn('Attempt to retrieve artist information from MusicBrainz failed for artistid: %s (%s)' % (artistid, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
if not artist:
|
||||
continue
|
||||
for rg in artist['release-group-list']:
|
||||
releasegroups.append({
|
||||
'title': unicode(rg['title']),
|
||||
'id': unicode(rg['id']),
|
||||
'url': u"http://musicbrainz.org/release-group/" + rg['id'],
|
||||
'type': unicode(rg['type'])
|
||||
})
|
||||
|
||||
artist_dict['releasegroups'] = releasegroups
|
||||
|
||||
return artist_dict
|
||||
|
||||
def getReleaseGroup(rgid):
|
||||
"""
|
||||
Returns a dictionary of the best stuff from a release group
|
||||
"""
|
||||
with mb_lock:
|
||||
|
||||
releaselist = []
|
||||
|
||||
inc = ws.ReleaseGroupIncludes(releases=True, artist=True)
|
||||
releaseGroup = None
|
||||
attempt = 0
|
||||
|
||||
q, sleepytime = startmb()
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
releaseGroup = q.getReleaseGroupById(rgid, inc)
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve information from MusicBrainz for release group "%s" failed (%s)' % (rgid, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(5)
|
||||
|
||||
if not releaseGroup:
|
||||
return False
|
||||
|
||||
time.sleep(sleepytime)
|
||||
# I think for now we have to make separate queries for each release, in order
|
||||
# to get more detailed release info (ASIN, track count, etc.)
|
||||
for release in releaseGroup.releases:
|
||||
|
||||
inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True)
|
||||
releaseResult = None
|
||||
attempt = 0
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
releaseResult = q.getReleaseById(release.id, inc)
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve release information for %s from MusicBrainz failed (%s)' % (releaseResult.title, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(5)
|
||||
|
||||
if not releaseResult:
|
||||
continue
|
||||
|
||||
# Release filter for non-official live albums
|
||||
types = releaseResult.getTypes()
|
||||
if any('Live' in type for type in types):
|
||||
if not any('Official' in type for type in types):
|
||||
logger.debug('%s is not an official live album. Skipping' % releaseResult.name)
|
||||
continue
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
formats = {
|
||||
'2xVinyl': '2',
|
||||
'Vinyl': '2',
|
||||
'CD': '0',
|
||||
'Cassette': '3',
|
||||
'2xCD': '1',
|
||||
'Digital Media': '0'
|
||||
}
|
||||
|
||||
country = {
|
||||
'US': '0',
|
||||
'GB': '1',
|
||||
'JP': '2',
|
||||
}
|
||||
"""
|
||||
Returns a dictionary of the best stuff from a release group
|
||||
"""
|
||||
with mb_lock:
|
||||
|
||||
releaselist = []
|
||||
|
||||
releaseGroup = None
|
||||
|
||||
q, sleepytime = startmb()
|
||||
|
||||
try:
|
||||
releaseGroup = musicbrainzngs.get_release_group_by_id(rgid,["artists","releases","media","discids",])['release-group']
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve information from MusicBrainz for release group "%s" failed (%s)' % (rgid, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
if not releaseGroup:
|
||||
return False
|
||||
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
# I think for now we have to make separate queries for each release, in order
|
||||
# to get more detailed release info (ASIN, track count, etc.)
|
||||
for release in releaseGroup['release-list']:
|
||||
releaseResult = None
|
||||
|
||||
try:
|
||||
releaseResult = musicbrainzngs.get_release_by_id(release['id'],["recordings","media"])['release']
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve release information for %s from MusicBrainz failed (%s)' % (releaseResult.title, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
|
||||
try:
|
||||
format = int(replace_all(u.extractFragment(releaseResult.releaseEvents[0].format), formats))
|
||||
except:
|
||||
format = 3
|
||||
|
||||
try:
|
||||
country = int(replace_all(releaseResult.releaseEvents[0].country, country))
|
||||
except:
|
||||
country = 3
|
||||
|
||||
release_dict = {
|
||||
'hasasin': bool(releaseResult.asin),
|
||||
'asin': releaseResult.asin,
|
||||
'trackscount': len(releaseResult.getTracks()),
|
||||
'releaseid': u.extractUuid(releaseResult.id),
|
||||
'releasedate': releaseResult.getEarliestReleaseDate(),
|
||||
'format': format,
|
||||
'country': country
|
||||
}
|
||||
|
||||
tracks = []
|
||||
|
||||
i = 1
|
||||
for track in releaseResult.tracks:
|
||||
|
||||
tracks.append({
|
||||
'number': i,
|
||||
'title': track.title,
|
||||
'id': u.extractUuid(track.id),
|
||||
'url': track.id,
|
||||
'duration': track.duration
|
||||
})
|
||||
i += 1
|
||||
|
||||
release_dict['tracks'] = tracks
|
||||
|
||||
releaselist.append(release_dict)
|
||||
|
||||
average_tracks = sum(x['trackscount'] for x in releaselist) / float(len(releaselist))
|
||||
|
||||
for item in releaselist:
|
||||
item['trackscount_delta'] = abs(average_tracks - item['trackscount'])
|
||||
|
||||
a = multikeysort(releaselist, ['-hasasin', 'country', 'format', 'trackscount_delta'])
|
||||
|
||||
release_dict = {'releaseid' :a[0]['releaseid'],
|
||||
'releasedate' : releaselist[0]['releasedate'],
|
||||
'trackcount' : a[0]['trackscount'],
|
||||
'tracks' : a[0]['tracks'],
|
||||
'asin' : a[0]['asin'],
|
||||
'releaselist' : releaselist,
|
||||
'artist_name' : releaseGroup.artist.name,
|
||||
'artist_id' : u.extractUuid(releaseGroup.artist.id),
|
||||
'title' : releaseGroup.title,
|
||||
'type' : u.extractFragment(releaseGroup.type)
|
||||
}
|
||||
|
||||
return release_dict
|
||||
|
||||
if not releaseResult:
|
||||
continue
|
||||
|
||||
if releaseGroup['type'] == 'live' and releaseResult['status'] != 'Official':
|
||||
logger.debug('%s is not an official live album. Skipping' % releaseResult.name)
|
||||
continue
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
formats = {
|
||||
'2xVinyl': '2',
|
||||
'Vinyl': '2',
|
||||
'CD': '0',
|
||||
'Cassette': '3',
|
||||
'2xCD': '1',
|
||||
'Digital Media': '0'
|
||||
}
|
||||
|
||||
countries = {
|
||||
'US': '0',
|
||||
|
||||
'GB': '1',
|
||||
'JP': '2',
|
||||
}
|
||||
try:
|
||||
format = int(formats[releaseResult['medium-list'][0]['format']])
|
||||
except:
|
||||
format = 3
|
||||
|
||||
try:
|
||||
country = int(countries[releaseResult['country']])
|
||||
except:
|
||||
country = 3
|
||||
totalTracks = 0
|
||||
tracks = []
|
||||
for medium in releaseResult['medium-list']:
|
||||
for track in medium['track-list']:
|
||||
tracks.append({
|
||||
'number': totalTracks + 1,
|
||||
'title': unicode(track['recording']['title']),
|
||||
'id': unicode(track['recording']['id']),
|
||||
'url': u"http://musicbrainz.org/track/" + track['recording']['id'],
|
||||
'duration': int(track['recording']['length'] if 'length' in track['recording'] else track['length'] if 'length' in track else 0)
|
||||
})
|
||||
totalTracks += 1
|
||||
|
||||
release_dict = {
|
||||
'hasasin': bool(releaseResult.get('asin')),
|
||||
'asin': unicode(releaseResult.get('asin')) if 'asin' in releaseResult else None,
|
||||
'trackscount': totalTracks,
|
||||
'releaseid': unicode(releaseResult.get('id')),
|
||||
'releasedate': unicode(releaseResult.get('date')),
|
||||
'format': format,
|
||||
'country': country
|
||||
}
|
||||
release_dict['tracks'] = tracks
|
||||
releaselist.append(release_dict)
|
||||
#necessary to make dates that miss the month and/or day show up after full dates
|
||||
def getSortableReleaseDate(releaseDate):
|
||||
if releaseDate.count('-') == 2:
|
||||
return releaseDate
|
||||
elif releaseDate.count('-') == 1:
|
||||
return releaseDate + '32'
|
||||
else:
|
||||
return releaseDate + '13-32'
|
||||
|
||||
releaselist.sort(key=lambda x:getSortableReleaseDate(x['releasedate']))
|
||||
|
||||
|
||||
average_tracks = sum(x['trackscount'] for x in releaselist) / float(len(releaselist))
|
||||
for item in releaselist:
|
||||
item['trackscount_delta'] = abs(average_tracks - item['trackscount'])
|
||||
a = multikeysort(releaselist, ['-hasasin', 'country', 'format', 'trackscount_delta'])
|
||||
|
||||
release_dict = {'releaseid' :a[0]['releaseid'],
|
||||
'releasedate' : unicode(releaselist[0]['releasedate']),
|
||||
'trackcount' : a[0]['trackscount'],
|
||||
'tracks' : a[0]['tracks'],
|
||||
'asin' : a[0]['asin'],
|
||||
'releaselist' : releaselist,
|
||||
'artist_name' : unicode(releaseGroup['artist-credit'][0]['artist']['name']),
|
||||
'artist_id' : unicode(releaseGroup['artist-credit'][0]['artist']['id']),
|
||||
'title' : unicode(releaseGroup['title']),
|
||||
'type' : unicode(releaseGroup['type'])
|
||||
}
|
||||
|
||||
return release_dict
|
||||
|
||||
def getRelease(releaseid):
|
||||
"""
|
||||
Deep release search to get track info
|
||||
"""
|
||||
with mb_lock:
|
||||
|
||||
release = {}
|
||||
|
||||
inc = ws.ReleaseIncludes(tracks=True, releaseEvents=True, releaseGroup=True, artist=True)
|
||||
results = None
|
||||
attempt = 0
|
||||
|
||||
q, sleepytime = startmb()
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
results = q.getReleaseById(releaseid, inc)
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve information from MusicBrainz for release "%s" failed (%s)' % (releaseid, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(5)
|
||||
|
||||
if not results:
|
||||
return False
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
release['title'] = results.title
|
||||
release['id'] = u.extractUuid(results.id)
|
||||
release['asin'] = results.asin
|
||||
release['date'] = results.getEarliestReleaseDate()
|
||||
"""
|
||||
Deep release search to get track info
|
||||
"""
|
||||
with mb_lock:
|
||||
|
||||
release = {}
|
||||
results = None
|
||||
|
||||
q, sleepytime = startmb()
|
||||
|
||||
try:
|
||||
results = musicbrainzngs.get_release_by_id(releaseid,["artists","release-groups","media","recordings"]).get('release')
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to retrieve information from MusicBrainz for release "%s" failed (%s)' % (releaseid, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
if not results:
|
||||
return False
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
release['title'] = unicode(results['title'])
|
||||
release['id'] = unicode(results['id'])
|
||||
release['asin'] = unicode(results['asin']) if 'asin' in results else None
|
||||
release['date'] = unicode(results['date'])
|
||||
|
||||
rg = results.getReleaseGroup()
|
||||
if rg:
|
||||
release['rgid'] = u.extractUuid(rg.id)
|
||||
release['rg_title'] = rg.title
|
||||
release['rg_type'] = u.extractFragment(rg.type)
|
||||
else:
|
||||
logger.warn("Release " + releaseid + "had no ReleaseGroup associated")
|
||||
#so we can start with a releaseID from anywhere and get the artist info
|
||||
#it looks like MB api v1 only returns 1 artist object - 2.0 returns more...
|
||||
release['artist_name'] = results.artist.name
|
||||
release['artist_id'] = u.extractUuid(results.artist.id)
|
||||
|
||||
tracks = []
|
||||
|
||||
i = 1
|
||||
for track in results.tracks:
|
||||
tracks.append({
|
||||
'number': i,
|
||||
'title': track.title,
|
||||
'id': u.extractUuid(track.id),
|
||||
'url': track.id,
|
||||
'duration': track.duration
|
||||
})
|
||||
i += 1
|
||||
|
||||
release['tracks'] = tracks
|
||||
|
||||
return release
|
||||
if 'release-group' in results:
|
||||
release['rgid'] = unicode(results['release-group']['id'])
|
||||
release['rg_title'] = unicode(results['release-group']['title'])
|
||||
release['rg_type'] = unicode(results['release-group']['type'])
|
||||
else:
|
||||
logger.warn("Release " + releaseid + "had no ReleaseGroup associated")
|
||||
|
||||
release['artist_name'] = unicode(results['artist-credit'][0]['artist']['name'])
|
||||
release['artist_id'] = unicode(results['artist-credit'][0]['artist']['id'])
|
||||
|
||||
|
||||
totalTracks = 0
|
||||
tracks = []
|
||||
for medium in results['medium-list']:
|
||||
for track in medium['track-list']:
|
||||
tracks.append({
|
||||
'number': totalTracks + 1,
|
||||
'title': unicode(track['recording']['title']),
|
||||
'id': unicode(track['recording']['id']),
|
||||
'url': u"http://musicbrainz.org/track/" + track['recording']['id'],
|
||||
'duration': int(track['length']) if 'length' in track else 0
|
||||
})
|
||||
totalTracks += 1
|
||||
|
||||
release['tracks'] = tracks
|
||||
|
||||
return release
|
||||
|
||||
# Used when there is a disambiguation
|
||||
def findArtistbyAlbum(name):
|
||||
|
||||
myDB = db.DBConnection()
|
||||
|
||||
artist = myDB.action('SELECT AlbumTitle from have WHERE ArtistName=? AND AlbumTitle IS NOT NULL ORDER BY RANDOM()', [name]).fetchone()
|
||||
|
||||
if not artist:
|
||||
return False
|
||||
|
||||
# Probably not neccessary but just want to double check
|
||||
if not artist['AlbumTitle']:
|
||||
return False
|
||||
|
||||
term = '"'+artist['AlbumTitle']+'" AND artist:"'+name+'"'
|
||||
|
||||
f = ws.ReleaseGroupFilter(query=term, limit=1)
|
||||
results = None
|
||||
attempt = 0
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
results = q.getReleaseGroups(f)
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to query MusicBrainz for %s failed (%s)' % (name, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(10)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not results:
|
||||
return False
|
||||
myDB = db.DBConnection()
|
||||
|
||||
artist = myDB.action('SELECT AlbumTitle from have WHERE ArtistName=? AND AlbumTitle IS NOT NULL ORDER BY RANDOM()', [name]).fetchone()
|
||||
|
||||
if not artist:
|
||||
return False
|
||||
|
||||
# Probably not neccessary but just want to double check
|
||||
if not artist['AlbumTitle']:
|
||||
return False
|
||||
|
||||
artist_dict = {}
|
||||
|
||||
for result in results:
|
||||
releaseGroup = result.releaseGroup
|
||||
artist_dict['name'] = releaseGroup.artist.name
|
||||
artist_dict['uniquename'] = releaseGroup.artist.getUniqueName()
|
||||
artist_dict['id'] = u.extractUuid(releaseGroup.artist.id)
|
||||
artist_dict['url'] = releaseGroup.artist.id
|
||||
artist_dict['score'] = result.score
|
||||
|
||||
return artist_dict
|
||||
|
||||
term = '"'+artist['AlbumTitle']+'" AND artist:"'+name+'"'
|
||||
|
||||
results = None
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
try:
|
||||
results = musicbrainzngs.search_release_groups(term).get('release-group-list')
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to query MusicBrainz for %s failed (%s)' % (name, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not results:
|
||||
return False
|
||||
|
||||
artist_dict = {}
|
||||
for releaseGroup in results:
|
||||
newArtist = releaseGroup['artist-credit'][0]['artist']
|
||||
if 'disambiguation' in newArtist:
|
||||
uniquename = unicode(newArtist['sort-name'] + " (" + newArtist['disambiguation'] + ")")
|
||||
else:
|
||||
uniquename = unicode(newArtist['sort-name'])
|
||||
artist_dict['name'] = unicode(newArtist['sort-name'])
|
||||
artist_dict['uniquename'] = uniquename
|
||||
artist_dict['id'] = unicode(newArtist['id'])
|
||||
artist_dict['url'] = u'http://musicbrainz.org/artist/' + newArtist['id']
|
||||
artist_dict['score'] = int(releaseGroup['ext:score'])
|
||||
|
||||
|
||||
|
||||
return artist_dict
|
||||
|
||||
def findAlbumID(artist=None, album=None):
|
||||
|
||||
f = ws.ReleaseGroupFilter(title=album, artistName=artist, limit=1)
|
||||
results = None
|
||||
attempt = 0
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
while attempt < 5:
|
||||
|
||||
try:
|
||||
results = q.getReleaseGroups(f)
|
||||
break
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to query MusicBrainz for %s - %s failed (%s)' % (artist, album, str(e)))
|
||||
attempt += 1
|
||||
time.sleep(10)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not results:
|
||||
return False
|
||||
|
||||
rgid = u.extractUuid(results[0].releaseGroup.id)
|
||||
return rgid
|
||||
results_ngs = None
|
||||
|
||||
q, sleepytime = startmb(forcemb=True)
|
||||
|
||||
try:
|
||||
term = '"'+album+'" AND artist:"'+artist+'"'
|
||||
results_ngs = musicbrainzngs.search_release_groups(term,1).get('release-group-list')
|
||||
except WebServiceError, e:
|
||||
logger.warn('Attempt to query MusicBrainz for %s - %s failed (%s)' % (artist, album, str(e)))
|
||||
time.sleep(5)
|
||||
|
||||
time.sleep(sleepytime)
|
||||
|
||||
if not results_ngs:
|
||||
return False
|
||||
|
||||
if len(results_ngs) < 1:
|
||||
return False
|
||||
rgid_ngs = unicode(results_ngs[0]['id'])
|
||||
return rgid_ngs
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
"""A collection of classes for MusicBrainz.
|
||||
|
||||
To get started quickly, have a look at L{webservice.Query} and the examples
|
||||
there. The source distribution also contains example code you might find
|
||||
interesting.
|
||||
|
||||
This package contains the following modules:
|
||||
|
||||
1. L{model}: The MusicBrainz domain model, containing classes like
|
||||
L{Artist <model.Artist>}, L{Release <model.Release>}, or
|
||||
L{Track <model.Track>}
|
||||
|
||||
2. L{webservice}: An interface to the MusicBrainz XML web service.
|
||||
|
||||
3. L{wsxml}: A parser for the web service XML format (MMD).
|
||||
|
||||
4. L{disc}: Functions for creating and submitting DiscIDs.
|
||||
|
||||
5. L{utils}: Utilities for working with URIs and other commonly needed tools.
|
||||
|
||||
@author: Matthias Friedrich <matt@mafr.de>
|
||||
"""
|
||||
__revision__ = '$Id: __init__.py 12974 2011-05-01 08:43:54Z luks $'
|
||||
__version__ = '0.7.3'
|
||||
|
||||
# EOF
|
||||
@@ -1,10 +0,0 @@
|
||||
"""Support data for the musicbrainz2 package.
|
||||
|
||||
This package is I{not} part of the public API, it has been added to work
|
||||
around shortcomings in python and may thus be removed at any time.
|
||||
|
||||
Please use the L{musicbrainz2.utils} module instead.
|
||||
"""
|
||||
__revision__ = '$Id: __init__.py 7386 2006-04-30 11:12:55Z matt $'
|
||||
|
||||
# EOF
|
||||
@@ -1,253 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__revision__ = '$Id: countrynames.py 7386 2006-04-30 11:12:55Z matt $'
|
||||
|
||||
countryNames = {
|
||||
u'BD': u'Bangladesh',
|
||||
u'BE': u'Belgium',
|
||||
u'BF': u'Burkina Faso',
|
||||
u'BG': u'Bulgaria',
|
||||
u'BB': u'Barbados',
|
||||
u'WF': u'Wallis and Futuna Islands',
|
||||
u'BM': u'Bermuda',
|
||||
u'BN': u'Brunei Darussalam',
|
||||
u'BO': u'Bolivia',
|
||||
u'BH': u'Bahrain',
|
||||
u'BI': u'Burundi',
|
||||
u'BJ': u'Benin',
|
||||
u'BT': u'Bhutan',
|
||||
u'JM': u'Jamaica',
|
||||
u'BV': u'Bouvet Island',
|
||||
u'BW': u'Botswana',
|
||||
u'WS': u'Samoa',
|
||||
u'BR': u'Brazil',
|
||||
u'BS': u'Bahamas',
|
||||
u'BY': u'Belarus',
|
||||
u'BZ': u'Belize',
|
||||
u'RU': u'Russian Federation',
|
||||
u'RW': u'Rwanda',
|
||||
u'RE': u'Reunion',
|
||||
u'TM': u'Turkmenistan',
|
||||
u'TJ': u'Tajikistan',
|
||||
u'RO': u'Romania',
|
||||
u'TK': u'Tokelau',
|
||||
u'GW': u'Guinea-Bissau',
|
||||
u'GU': u'Guam',
|
||||
u'GT': u'Guatemala',
|
||||
u'GR': u'Greece',
|
||||
u'GQ': u'Equatorial Guinea',
|
||||
u'GP': u'Guadeloupe',
|
||||
u'JP': u'Japan',
|
||||
u'GY': u'Guyana',
|
||||
u'GF': u'French Guiana',
|
||||
u'GE': u'Georgia',
|
||||
u'GD': u'Grenada',
|
||||
u'GB': u'United Kingdom',
|
||||
u'GA': u'Gabon',
|
||||
u'SV': u'El Salvador',
|
||||
u'GN': u'Guinea',
|
||||
u'GM': u'Gambia',
|
||||
u'GL': u'Greenland',
|
||||
u'GI': u'Gibraltar',
|
||||
u'GH': u'Ghana',
|
||||
u'OM': u'Oman',
|
||||
u'TN': u'Tunisia',
|
||||
u'JO': u'Jordan',
|
||||
u'HT': u'Haiti',
|
||||
u'HU': u'Hungary',
|
||||
u'HK': u'Hong Kong',
|
||||
u'HN': u'Honduras',
|
||||
u'HM': u'Heard and Mc Donald Islands',
|
||||
u'VE': u'Venezuela',
|
||||
u'PR': u'Puerto Rico',
|
||||
u'PW': u'Palau',
|
||||
u'PT': u'Portugal',
|
||||
u'SJ': u'Svalbard and Jan Mayen Islands',
|
||||
u'PY': u'Paraguay',
|
||||
u'IQ': u'Iraq',
|
||||
u'PA': u'Panama',
|
||||
u'PF': u'French Polynesia',
|
||||
u'PG': u'Papua New Guinea',
|
||||
u'PE': u'Peru',
|
||||
u'PK': u'Pakistan',
|
||||
u'PH': u'Philippines',
|
||||
u'PN': u'Pitcairn',
|
||||
u'PL': u'Poland',
|
||||
u'PM': u'St. Pierre and Miquelon',
|
||||
u'ZM': u'Zambia',
|
||||
u'EH': u'Western Sahara',
|
||||
u'EE': u'Estonia',
|
||||
u'EG': u'Egypt',
|
||||
u'ZA': u'South Africa',
|
||||
u'EC': u'Ecuador',
|
||||
u'IT': u'Italy',
|
||||
u'VN': u'Viet Nam',
|
||||
u'SB': u'Solomon Islands',
|
||||
u'ET': u'Ethiopia',
|
||||
u'SO': u'Somalia',
|
||||
u'ZW': u'Zimbabwe',
|
||||
u'SA': u'Saudi Arabia',
|
||||
u'ES': u'Spain',
|
||||
u'ER': u'Eritrea',
|
||||
u'MD': u'Moldova, Republic of',
|
||||
u'MG': u'Madagascar',
|
||||
u'MA': u'Morocco',
|
||||
u'MC': u'Monaco',
|
||||
u'UZ': u'Uzbekistan',
|
||||
u'MM': u'Myanmar',
|
||||
u'ML': u'Mali',
|
||||
u'MO': u'Macau',
|
||||
u'MN': u'Mongolia',
|
||||
u'MH': u'Marshall Islands',
|
||||
u'MK': u'Macedonia, The Former Yugoslav Republic of',
|
||||
u'MU': u'Mauritius',
|
||||
u'MT': u'Malta',
|
||||
u'MW': u'Malawi',
|
||||
u'MV': u'Maldives',
|
||||
u'MQ': u'Martinique',
|
||||
u'MP': u'Northern Mariana Islands',
|
||||
u'MS': u'Montserrat',
|
||||
u'MR': u'Mauritania',
|
||||
u'UG': u'Uganda',
|
||||
u'MY': u'Malaysia',
|
||||
u'MX': u'Mexico',
|
||||
u'IL': u'Israel',
|
||||
u'FR': u'France',
|
||||
u'IO': u'British Indian Ocean Territory',
|
||||
u'SH': u'St. Helena',
|
||||
u'FI': u'Finland',
|
||||
u'FJ': u'Fiji',
|
||||
u'FK': u'Falkland Islands (Malvinas)',
|
||||
u'FM': u'Micronesia, Federated States of',
|
||||
u'FO': u'Faroe Islands',
|
||||
u'NI': u'Nicaragua',
|
||||
u'NL': u'Netherlands',
|
||||
u'NO': u'Norway',
|
||||
u'NA': u'Namibia',
|
||||
u'VU': u'Vanuatu',
|
||||
u'NC': u'New Caledonia',
|
||||
u'NE': u'Niger',
|
||||
u'NF': u'Norfolk Island',
|
||||
u'NG': u'Nigeria',
|
||||
u'NZ': u'New Zealand',
|
||||
u'ZR': u'Zaire',
|
||||
u'NP': u'Nepal',
|
||||
u'NR': u'Nauru',
|
||||
u'NU': u'Niue',
|
||||
u'CK': u'Cook Islands',
|
||||
u'CI': u'Cote d\'Ivoire',
|
||||
u'CH': u'Switzerland',
|
||||
u'CO': u'Colombia',
|
||||
u'CN': u'China',
|
||||
u'CM': u'Cameroon',
|
||||
u'CL': u'Chile',
|
||||
u'CC': u'Cocos (Keeling) Islands',
|
||||
u'CA': u'Canada',
|
||||
u'CG': u'Congo',
|
||||
u'CF': u'Central African Republic',
|
||||
u'CZ': u'Czech Republic',
|
||||
u'CY': u'Cyprus',
|
||||
u'CX': u'Christmas Island',
|
||||
u'CR': u'Costa Rica',
|
||||
u'CV': u'Cape Verde',
|
||||
u'CU': u'Cuba',
|
||||
u'SZ': u'Swaziland',
|
||||
u'SY': u'Syrian Arab Republic',
|
||||
u'KG': u'Kyrgyzstan',
|
||||
u'KE': u'Kenya',
|
||||
u'SR': u'Suriname',
|
||||
u'KI': u'Kiribati',
|
||||
u'KH': u'Cambodia',
|
||||
u'KN': u'Saint Kitts and Nevis',
|
||||
u'KM': u'Comoros',
|
||||
u'ST': u'Sao Tome and Principe',
|
||||
u'SI': u'Slovenia',
|
||||
u'KW': u'Kuwait',
|
||||
u'SN': u'Senegal',
|
||||
u'SM': u'San Marino',
|
||||
u'SL': u'Sierra Leone',
|
||||
u'SC': u'Seychelles',
|
||||
u'KZ': u'Kazakhstan',
|
||||
u'KY': u'Cayman Islands',
|
||||
u'SG': u'Singapore',
|
||||
u'SE': u'Sweden',
|
||||
u'SD': u'Sudan',
|
||||
u'DO': u'Dominican Republic',
|
||||
u'DM': u'Dominica',
|
||||
u'DJ': u'Djibouti',
|
||||
u'DK': u'Denmark',
|
||||
u'VG': u'Virgin Islands (British)',
|
||||
u'DE': u'Germany',
|
||||
u'YE': u'Yemen',
|
||||
u'DZ': u'Algeria',
|
||||
u'US': u'United States',
|
||||
u'UY': u'Uruguay',
|
||||
u'YT': u'Mayotte',
|
||||
u'UM': u'United States Minor Outlying Islands',
|
||||
u'LB': u'Lebanon',
|
||||
u'LC': u'Saint Lucia',
|
||||
u'LA': u'Lao People\'s Democratic Republic',
|
||||
u'TV': u'Tuvalu',
|
||||
u'TW': u'Taiwan',
|
||||
u'TT': u'Trinidad and Tobago',
|
||||
u'TR': u'Turkey',
|
||||
u'LK': u'Sri Lanka',
|
||||
u'LI': u'Liechtenstein',
|
||||
u'LV': u'Latvia',
|
||||
u'TO': u'Tonga',
|
||||
u'LT': u'Lithuania',
|
||||
u'LU': u'Luxembourg',
|
||||
u'LR': u'Liberia',
|
||||
u'LS': u'Lesotho',
|
||||
u'TH': u'Thailand',
|
||||
u'TF': u'French Southern Territories',
|
||||
u'TG': u'Togo',
|
||||
u'TD': u'Chad',
|
||||
u'TC': u'Turks and Caicos Islands',
|
||||
u'LY': u'Libyan Arab Jamahiriya',
|
||||
u'VA': u'Vatican City State (Holy See)',
|
||||
u'VC': u'Saint Vincent and The Grenadines',
|
||||
u'AE': u'United Arab Emirates',
|
||||
u'AD': u'Andorra',
|
||||
u'AG': u'Antigua and Barbuda',
|
||||
u'AF': u'Afghanistan',
|
||||
u'AI': u'Anguilla',
|
||||
u'VI': u'Virgin Islands (U.S.)',
|
||||
u'IS': u'Iceland',
|
||||
u'IR': u'Iran (Islamic Republic of)',
|
||||
u'AM': u'Armenia',
|
||||
u'AL': u'Albania',
|
||||
u'AO': u'Angola',
|
||||
u'AN': u'Netherlands Antilles',
|
||||
u'AQ': u'Antarctica',
|
||||
u'AS': u'American Samoa',
|
||||
u'AR': u'Argentina',
|
||||
u'AU': u'Australia',
|
||||
u'AT': u'Austria',
|
||||
u'AW': u'Aruba',
|
||||
u'IN': u'India',
|
||||
u'TZ': u'Tanzania, United Republic of',
|
||||
u'AZ': u'Azerbaijan',
|
||||
u'IE': u'Ireland',
|
||||
u'ID': u'Indonesia',
|
||||
u'UA': u'Ukraine',
|
||||
u'QA': u'Qatar',
|
||||
u'MZ': u'Mozambique',
|
||||
u'BA': u'Bosnia and Herzegovina',
|
||||
u'CD': u'Congo, The Democratic Republic of the',
|
||||
u'CS': u'Serbia and Montenegro',
|
||||
u'HR': u'Croatia',
|
||||
u'KP': u'Korea (North), Democratic People\'s Republic of',
|
||||
u'KR': u'Korea (South), Republic of',
|
||||
u'SK': u'Slovakia',
|
||||
u'SU': u'Soviet Union (historical, 1922-1991)',
|
||||
u'TL': u'East Timor',
|
||||
u'XC': u'Czechoslovakia (historical, 1918-1992)',
|
||||
u'XE': u'Europe',
|
||||
u'XG': u'East Germany (historical, 1949-1990)',
|
||||
u'XU': u'[Unknown Country]',
|
||||
u'XW': u'[Worldwide]',
|
||||
u'YU': u'Yugoslavia (historical, 1918-1992)',
|
||||
}
|
||||
|
||||
# EOF
|
||||
@@ -1,400 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__revision__ = '$Id: languagenames.py 8725 2006-12-17 22:39:07Z luks $'
|
||||
|
||||
languageNames = {
|
||||
u'ART': u'Artificial (Other)',
|
||||
u'ROH': u'Raeto-Romance',
|
||||
u'SCO': u'Scots',
|
||||
u'SCN': u'Sicilian',
|
||||
u'ROM': u'Romany',
|
||||
u'RON': u'Romanian',
|
||||
u'OSS': u'Ossetian; Ossetic',
|
||||
u'ALE': u'Aleut',
|
||||
u'MNI': u'Manipuri',
|
||||
u'NWC': u'Classical Newari; Old Newari; Classical Nepal Bhasa',
|
||||
u'OSA': u'Osage',
|
||||
u'MNC': u'Manchu',
|
||||
u'MWR': u'Marwari',
|
||||
u'VEN': u'Venda',
|
||||
u'MWL': u'Mirandese',
|
||||
u'FAS': u'Persian',
|
||||
u'FAT': u'Fanti',
|
||||
u'FAN': u'Fang',
|
||||
u'FAO': u'Faroese',
|
||||
u'DIN': u'Dinka',
|
||||
u'HYE': u'Armenian',
|
||||
u'DSB': u'Lower Sorbian',
|
||||
u'CAR': u'Carib',
|
||||
u'DIV': u'Divehi',
|
||||
u'TEL': u'Telugu',
|
||||
u'TEM': u'Timne',
|
||||
u'NBL': u'Ndebele, South; South Ndebele',
|
||||
u'TER': u'Tereno',
|
||||
u'TET': u'Tetum',
|
||||
u'SUN': u'Sundanese',
|
||||
u'KUT': u'Kutenai',
|
||||
u'SUK': u'Sukuma',
|
||||
u'KUR': u'Kurdish',
|
||||
u'KUM': u'Kumyk',
|
||||
u'SUS': u'Susu',
|
||||
u'NEW': u'Newari; Nepal Bhasa',
|
||||
u'KUA': u'Kuanyama; Kwanyama',
|
||||
u'MEN': u'Mende',
|
||||
u'LEZ': u'Lezghian',
|
||||
u'GLA': u'Gaelic; Scottish Gaelic',
|
||||
u'BOS': u'Bosnian',
|
||||
u'GLE': u'Irish',
|
||||
u'EKA': u'Ekajuk',
|
||||
u'GLG': u'Gallegan',
|
||||
u'AKA': u'Akan',
|
||||
u'BOD': u'Tibetan',
|
||||
u'GLV': u'Manx',
|
||||
u'JRB': u'Judeo-Arabic',
|
||||
u'VIE': u'Vietnamese',
|
||||
u'IPK': u'Inupiaq',
|
||||
u'UZB': u'Uzbek',
|
||||
u'BRE': u'Breton',
|
||||
u'BRA': u'Braj',
|
||||
u'AYM': u'Aymara',
|
||||
u'CHA': u'Chamorro',
|
||||
u'CHB': u'Chibcha',
|
||||
u'CHE': u'Chechen',
|
||||
u'CHG': u'Chagatai',
|
||||
u'CHK': u'Chuukese',
|
||||
u'CHM': u'Mari',
|
||||
u'CHN': u'Chinook jargon',
|
||||
u'CHO': u'Choctaw',
|
||||
u'CHP': u'Chipewyan',
|
||||
u'CHR': u'Cherokee',
|
||||
u'CHU': u'Church Slavic; Old Slavonic; Church Slavonic; Old Bulgarian; Old Church Slavonic',
|
||||
u'CHV': u'Chuvash',
|
||||
u'CHY': u'Cheyenne',
|
||||
u'MSA': u'Malay',
|
||||
u'III': u'Sichuan Yi',
|
||||
u'ACE': u'Achinese',
|
||||
u'IBO': u'Igbo',
|
||||
u'IBA': u'Iban',
|
||||
u'XHO': u'Xhosa',
|
||||
u'DEU': u'German',
|
||||
u'CAT': u'Catalan; Valencian',
|
||||
u'DEL': u'Delaware',
|
||||
u'DEN': u'Slave (Athapascan)',
|
||||
u'CAD': u'Caddo',
|
||||
u'TAT': u'Tatar',
|
||||
u'RAJ': u'Rajasthani',
|
||||
u'SPA': u'Spanish; Castilian',
|
||||
u'TAM': u'Tamil',
|
||||
u'TAH': u'Tahitian',
|
||||
u'AFH': u'Afrihili',
|
||||
u'ENG': u'English',
|
||||
u'CSB': u'Kashubian',
|
||||
u'NYN': u'Nyankole',
|
||||
u'NYO': u'Nyoro',
|
||||
u'SID': u'Sidamo',
|
||||
u'NYA': u'Chichewa; Chewa; Nyanja',
|
||||
u'SIN': u'Sinhala; Sinhalese',
|
||||
u'AFR': u'Afrikaans',
|
||||
u'LAM': u'Lamba',
|
||||
u'SND': u'Sindhi',
|
||||
u'MAR': u'Marathi',
|
||||
u'LAH': u'Lahnda',
|
||||
u'NYM': u'Nyamwezi',
|
||||
u'SNA': u'Shona',
|
||||
u'LAD': u'Ladino',
|
||||
u'SNK': u'Soninke',
|
||||
u'MAD': u'Madurese',
|
||||
u'MAG': u'Magahi',
|
||||
u'MAI': u'Maithili',
|
||||
u'MAH': u'Marshallese',
|
||||
u'LAV': u'Latvian',
|
||||
u'MAL': u'Malayalam',
|
||||
u'MAN': u'Mandingo',
|
||||
u'ZND': u'Zande',
|
||||
u'ZEN': u'Zenaga',
|
||||
u'KBD': u'Kabardian',
|
||||
u'ITA': u'Italian',
|
||||
u'VAI': u'Vai',
|
||||
u'TSN': u'Tswana',
|
||||
u'TSO': u'Tsonga',
|
||||
u'TSI': u'Tsimshian',
|
||||
u'BYN': u'Blin; Bilin',
|
||||
u'FIJ': u'Fijian',
|
||||
u'FIN': u'Finnish',
|
||||
u'EUS': u'Basque',
|
||||
u'CEB': u'Cebuano',
|
||||
u'DAN': u'Danish',
|
||||
u'NOG': u'Nogai',
|
||||
u'NOB': u'Norwegian Bokmål; Bokmål, Norwegian',
|
||||
u'DAK': u'Dakota',
|
||||
u'CES': u'Czech',
|
||||
u'DAR': u'Dargwa',
|
||||
u'DAY': u'Dayak',
|
||||
u'NOR': u'Norwegian',
|
||||
u'KPE': u'Kpelle',
|
||||
u'GUJ': u'Gujarati',
|
||||
u'MDF': u'Moksha',
|
||||
u'MAS': u'Masai',
|
||||
u'LAO': u'Lao',
|
||||
u'MDR': u'Mandar',
|
||||
u'GON': u'Gondi',
|
||||
u'SMS': u'Skolt Sami',
|
||||
u'SMO': u'Samoan',
|
||||
u'SMN': u'Inari Sami',
|
||||
u'SMJ': u'Lule Sami',
|
||||
u'GOT': u'Gothic',
|
||||
u'SME': u'Northern Sami',
|
||||
u'BLA': u'Siksika',
|
||||
u'SMA': u'Southern Sami',
|
||||
u'GOR': u'Gorontalo',
|
||||
u'AST': u'Asturian; Bable',
|
||||
u'ORM': u'Oromo',
|
||||
u'QUE': u'Quechua',
|
||||
u'ORI': u'Oriya',
|
||||
u'CRH': u'Crimean Tatar; Crimean Turkish',
|
||||
u'ASM': u'Assamese',
|
||||
u'PUS': u'Pushto',
|
||||
u'DGR': u'Dogrib',
|
||||
u'LTZ': u'Luxembourgish; Letzeburgesch',
|
||||
u'NDO': u'Ndonga',
|
||||
u'GEZ': u'Geez',
|
||||
u'ISL': u'Icelandic',
|
||||
u'LAT': u'Latin',
|
||||
u'MAK': u'Makasar',
|
||||
u'ZAP': u'Zapotec',
|
||||
u'YID': u'Yiddish',
|
||||
u'KOK': u'Konkani',
|
||||
u'KOM': u'Komi',
|
||||
u'KON': u'Kongo',
|
||||
u'UKR': u'Ukrainian',
|
||||
u'TON': u'Tonga (Tonga Islands)',
|
||||
u'KOS': u'Kosraean',
|
||||
u'KOR': u'Korean',
|
||||
u'TOG': u'Tonga (Nyasa)',
|
||||
u'HUN': u'Hungarian',
|
||||
u'HUP': u'Hupa',
|
||||
u'CYM': u'Welsh',
|
||||
u'UDM': u'Udmurt',
|
||||
u'BEJ': u'Beja',
|
||||
u'BEN': u'Bengali',
|
||||
u'BEL': u'Belarusian',
|
||||
u'BEM': u'Bemba',
|
||||
u'AAR': u'Afar',
|
||||
u'NZI': u'Nzima',
|
||||
u'SAH': u'Yakut',
|
||||
u'SAN': u'Sanskrit',
|
||||
u'SAM': u'Samaritan Aramaic',
|
||||
u'SAG': u'Sango',
|
||||
u'SAD': u'Sandawe',
|
||||
u'RAR': u'Rarotongan',
|
||||
u'RAP': u'Rapanui',
|
||||
u'SAS': u'Sasak',
|
||||
u'SAT': u'Santali',
|
||||
u'MIN': u'Minangkabau',
|
||||
u'LIM': u'Limburgan; Limburger; Limburgish',
|
||||
u'LIN': u'Lingala',
|
||||
u'LIT': u'Lithuanian',
|
||||
u'EFI': u'Efik',
|
||||
u'BTK': u'Batak (Indonesia)',
|
||||
u'KAC': u'Kachin',
|
||||
u'KAB': u'Kabyle',
|
||||
u'KAA': u'Kara-Kalpak',
|
||||
u'KAN': u'Kannada',
|
||||
u'KAM': u'Kamba',
|
||||
u'KAL': u'Kalaallisut; Greenlandic',
|
||||
u'KAS': u'Kashmiri',
|
||||
u'KAR': u'Karen',
|
||||
u'KAU': u'Kanuri',
|
||||
u'KAT': u'Georgian',
|
||||
u'KAZ': u'Kazakh',
|
||||
u'TYV': u'Tuvinian',
|
||||
u'AWA': u'Awadhi',
|
||||
u'URD': u'Urdu',
|
||||
u'DOI': u'Dogri',
|
||||
u'TPI': u'Tok Pisin',
|
||||
u'MRI': u'Maori',
|
||||
u'ABK': u'Abkhazian',
|
||||
u'TKL': u'Tokelau',
|
||||
u'NLD': u'Dutch; Flemish',
|
||||
u'OJI': u'Ojibwa',
|
||||
u'OCI': u'Occitan (post 1500); Provençal',
|
||||
u'WOL': u'Wolof',
|
||||
u'JAV': u'Javanese',
|
||||
u'HRV': u'Croatian',
|
||||
u'DYU': u'Dyula',
|
||||
u'SSW': u'Swati',
|
||||
u'MUL': u'Multiple languages',
|
||||
u'HIL': u'Hiligaynon',
|
||||
u'HIM': u'Himachali',
|
||||
u'HIN': u'Hindi',
|
||||
u'BAS': u'Basa',
|
||||
u'GBA': u'Gbaya',
|
||||
u'WLN': u'Walloon',
|
||||
u'BAD': u'Banda',
|
||||
u'NEP': u'Nepali',
|
||||
u'CRE': u'Cree',
|
||||
u'BAN': u'Balinese',
|
||||
u'BAL': u'Baluchi',
|
||||
u'BAM': u'Bambara',
|
||||
u'BAK': u'Bashkir',
|
||||
u'SHN': u'Shan',
|
||||
u'ARP': u'Arapaho',
|
||||
u'ARW': u'Arawak',
|
||||
u'ARA': u'Arabic',
|
||||
u'ARC': u'Aramaic',
|
||||
u'ARG': u'Aragonese',
|
||||
u'SEL': u'Selkup',
|
||||
u'ARN': u'Araucanian',
|
||||
u'LUS': u'Lushai',
|
||||
u'MUS': u'Creek',
|
||||
u'LUA': u'Luba-Lulua',
|
||||
u'LUB': u'Luba-Katanga',
|
||||
u'LUG': u'Ganda',
|
||||
u'LUI': u'Luiseno',
|
||||
u'LUN': u'Lunda',
|
||||
u'LUO': u'Luo (Kenya and Tanzania)',
|
||||
u'IKU': u'Inuktitut',
|
||||
u'TUR': u'Turkish',
|
||||
u'TUK': u'Turkmen',
|
||||
u'TUM': u'Tumbuka',
|
||||
u'COP': u'Coptic',
|
||||
u'COS': u'Corsican',
|
||||
u'COR': u'Cornish',
|
||||
u'ILO': u'Iloko',
|
||||
u'GWI': u'Gwich´in',
|
||||
u'TLI': u'Tlingit',
|
||||
u'TLH': u'Klingon; tlhIngan-Hol',
|
||||
u'POR': u'Portuguese',
|
||||
u'PON': u'Pohnpeian',
|
||||
u'POL': u'Polish',
|
||||
u'TGK': u'Tajik',
|
||||
u'TGL': u'Tagalog',
|
||||
u'FRA': u'French',
|
||||
u'BHO': u'Bhojpuri',
|
||||
u'SWA': u'Swahili',
|
||||
u'DUA': u'Duala',
|
||||
u'SWE': u'Swedish',
|
||||
u'YAP': u'Yapese',
|
||||
u'TIV': u'Tiv',
|
||||
u'YAO': u'Yao',
|
||||
u'XAL': u'Kalmyk',
|
||||
u'FRY': u'Frisian',
|
||||
u'GAY': u'Gayo',
|
||||
u'OTA': u'Turkish, Ottoman (1500-1928)',
|
||||
u'HMN': u'Hmong',
|
||||
u'HMO': u'Hiri Motu',
|
||||
u'GAA': u'Ga',
|
||||
u'FUR': u'Friulian',
|
||||
u'MLG': u'Malagasy',
|
||||
u'SLV': u'Slovenian',
|
||||
u'FIL': u'Filipino; Pilipino',
|
||||
u'MLT': u'Maltese',
|
||||
u'SLK': u'Slovak',
|
||||
u'FUL': u'Fulah',
|
||||
u'JPN': u'Japanese',
|
||||
u'VOL': u'Volapük',
|
||||
u'VOT': u'Votic',
|
||||
u'IND': u'Indonesian',
|
||||
u'AVE': u'Avestan',
|
||||
u'JPR': u'Judeo-Persian',
|
||||
u'AVA': u'Avaric',
|
||||
u'PAP': u'Papiamento',
|
||||
u'EWO': u'Ewondo',
|
||||
u'PAU': u'Palauan',
|
||||
u'EWE': u'Ewe',
|
||||
u'PAG': u'Pangasinan',
|
||||
u'PAM': u'Pampanga',
|
||||
u'PAN': u'Panjabi; Punjabi',
|
||||
u'KIR': u'Kirghiz',
|
||||
u'NIA': u'Nias',
|
||||
u'KIK': u'Kikuyu; Gikuyu',
|
||||
u'SYR': u'Syriac',
|
||||
u'KIN': u'Kinyarwanda',
|
||||
u'NIU': u'Niuean',
|
||||
u'EPO': u'Esperanto',
|
||||
u'JBO': u'Lojban',
|
||||
u'MIC': u'Mi\'kmaq; Micmac',
|
||||
u'THA': u'Thai',
|
||||
u'HAI': u'Haida',
|
||||
u'ELL': u'Greek, Modern (1453-)',
|
||||
u'ADY': u'Adyghe; Adygei',
|
||||
u'ELX': u'Elamite',
|
||||
u'ADA': u'Adangme',
|
||||
u'GRB': u'Grebo',
|
||||
u'HAT': u'Haitian; Haitian Creole',
|
||||
u'HAU': u'Hausa',
|
||||
u'HAW': u'Hawaiian',
|
||||
u'BIN': u'Bini',
|
||||
u'AMH': u'Amharic',
|
||||
u'BIK': u'Bikol',
|
||||
u'BIH': u'Bihari',
|
||||
u'MOS': u'Mossi',
|
||||
u'MOH': u'Mohawk',
|
||||
u'MON': u'Mongolian',
|
||||
u'MOL': u'Moldavian',
|
||||
u'BIS': u'Bislama',
|
||||
u'TVL': u'Tuvalu',
|
||||
u'IJO': u'Ijo',
|
||||
u'EST': u'Estonian',
|
||||
u'KMB': u'Kimbundu',
|
||||
u'UMB': u'Umbundu',
|
||||
u'TMH': u'Tamashek',
|
||||
u'FON': u'Fon',
|
||||
u'HSB': u'Upper Sorbian',
|
||||
u'RUN': u'Rundi',
|
||||
u'RUS': u'Russian',
|
||||
u'PLI': u'Pali',
|
||||
u'SRD': u'Sardinian',
|
||||
u'ACH': u'Acoli',
|
||||
u'NDE': u'Ndebele, North; North Ndebele',
|
||||
u'DZO': u'Dzongkha',
|
||||
u'KRU': u'Kurukh',
|
||||
u'SRR': u'Serer',
|
||||
u'IDO': u'Ido',
|
||||
u'SRP': u'Serbian',
|
||||
u'KRO': u'Kru',
|
||||
u'KRC': u'Karachay-Balkar',
|
||||
u'NDS': u'Low German; Low Saxon; German, Low; Saxon, Low',
|
||||
u'ZUN': u'Zuni',
|
||||
u'ZUL': u'Zulu',
|
||||
u'TWI': u'Twi',
|
||||
u'NSO': u'Northern Sotho, Pedi; Sepedi',
|
||||
u'SOM': u'Somali',
|
||||
u'SON': u'Songhai',
|
||||
u'SOT': u'Sotho, Southern',
|
||||
u'MKD': u'Macedonian',
|
||||
u'HER': u'Herero',
|
||||
u'LOL': u'Mongo',
|
||||
u'HEB': u'Hebrew',
|
||||
u'LOZ': u'Lozi',
|
||||
u'GIL': u'Gilbertese',
|
||||
u'WAS': u'Washo',
|
||||
u'WAR': u'Waray',
|
||||
u'BUL': u'Bulgarian',
|
||||
u'WAL': u'Walamo',
|
||||
u'BUA': u'Buriat',
|
||||
u'BUG': u'Buginese',
|
||||
u'AZE': u'Azerbaijani',
|
||||
u'ZHA': u'Zhuang; Chuang',
|
||||
u'ZHO': u'Chinese',
|
||||
u'NNO': u'Norwegian Nynorsk; Nynorsk, Norwegian',
|
||||
u'UIG': u'Uighur; Uyghur',
|
||||
u'MYV': u'Erzya',
|
||||
u'INH': u'Ingush',
|
||||
u'KHM': u'Khmer',
|
||||
u'MYA': u'Burmese',
|
||||
u'KHA': u'Khasi',
|
||||
u'INA': u'Interlingua (International Auxiliary Language Association)',
|
||||
u'NAH': u'Nahuatl',
|
||||
u'TIR': u'Tigrinya',
|
||||
u'NAP': u'Neapolitan',
|
||||
u'NAV': u'Navajo; Navaho',
|
||||
u'NAU': u'Nauru',
|
||||
u'GRN': u'Guarani',
|
||||
u'TIG': u'Tigre',
|
||||
u'YOR': u'Yoruba',
|
||||
u'ILE': u'Interlingue',
|
||||
u'SQI': u'Albanian',
|
||||
}
|
||||
|
||||
# EOF
|
||||
@@ -1,24 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__revision__ = '$Id: releasetypenames.py 8728 2006-12-17 23:42:30Z luks $'
|
||||
|
||||
releaseTypeNames = {
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#None': u'None',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Album': u'Album',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Single': u'Single',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#EP': u'EP',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Compilation': u'Compilation',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Soundtrack': u'Soundtrack',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Spokenword': u'Spokenword',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Interview': u'Interview',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Audiobook': u'Audiobook',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Live': u'Live',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Remix': u'Remix',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Other': u'Other',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Official': u'Official',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Promotion': u'Promotion',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Bootleg': u'Bootleg',
|
||||
u'http://musicbrainz.org/ns/mmd-1.0#Pseudo-Release': u'Pseudo-Release',
|
||||
}
|
||||
|
||||
# EOF
|
||||
@@ -1,59 +0,0 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
__revision__ = '$Id: scriptnames.py 7386 2006-04-30 11:12:55Z matt $'
|
||||
|
||||
scriptNames = {
|
||||
u'Yiii': u'Yi',
|
||||
u'Telu': u'Telugu',
|
||||
u'Taml': u'Tamil',
|
||||
u'Guru': u'Gurmukhi',
|
||||
u'Hebr': u'Hebrew',
|
||||
u'Geor': u'Georgian (Mkhedruli)',
|
||||
u'Ugar': u'Ugaritic',
|
||||
u'Cyrl': u'Cyrillic',
|
||||
u'Hrkt': u'Kanji & Kana',
|
||||
u'Armn': u'Armenian',
|
||||
u'Runr': u'Runic',
|
||||
u'Khmr': u'Khmer',
|
||||
u'Latn': u'Latin',
|
||||
u'Hani': u'Han (Hanzi, Kanji, Hanja)',
|
||||
u'Ital': u'Old Italic (Etruscan, Oscan, etc.)',
|
||||
u'Hano': u'Hanunoo (Hanunóo)',
|
||||
u'Ethi': u'Ethiopic (Ge\'ez)',
|
||||
u'Gujr': u'Gujarati',
|
||||
u'Hang': u'Hangul',
|
||||
u'Arab': u'Arabic',
|
||||
u'Thaa': u'Thaana',
|
||||
u'Buhd': u'Buhid',
|
||||
u'Sinh': u'Sinhala',
|
||||
u'Orya': u'Oriya',
|
||||
u'Hans': u'Han (Simplified variant)',
|
||||
u'Thai': u'Thai',
|
||||
u'Cprt': u'Cypriot',
|
||||
u'Linb': u'Linear B',
|
||||
u'Hant': u'Han (Traditional variant)',
|
||||
u'Osma': u'Osmanya',
|
||||
u'Mong': u'Mongolian',
|
||||
u'Deva': u'Devanagari (Nagari)',
|
||||
u'Laoo': u'Lao',
|
||||
u'Tagb': u'Tagbanwa',
|
||||
u'Hira': u'Hiragana',
|
||||
u'Bopo': u'Bopomofo',
|
||||
u'Goth': u'Gothic',
|
||||
u'Tale': u'Tai Le',
|
||||
u'Mymr': u'Myanmar (Burmese)',
|
||||
u'Tglg': u'Tagalog',
|
||||
u'Grek': u'Greek',
|
||||
u'Mlym': u'Malayalam',
|
||||
u'Cher': u'Cherokee',
|
||||
u'Tibt': u'Tibetan',
|
||||
u'Kana': u'Katakana',
|
||||
u'Syrc': u'Syriac',
|
||||
u'Cans': u'Unified Canadian Aboriginal Syllabics',
|
||||
u'Beng': u'Bengali',
|
||||
u'Limb': u'Limbu',
|
||||
u'Ogam': u'Ogham',
|
||||
u'Knda': u'Kannada',
|
||||
}
|
||||
|
||||
# EOF
|
||||
@@ -1,221 +0,0 @@
|
||||
"""Utilities for working with Audio CDs.
|
||||
|
||||
This module contains utilities for working with Audio CDs.
|
||||
|
||||
The functions in this module need both a working ctypes package (already
|
||||
included in python-2.5) and an installed libdiscid. If you don't have
|
||||
libdiscid, it can't be loaded, or your platform isn't supported by either
|
||||
ctypes or this module, a C{NotImplementedError} is raised when using the
|
||||
L{readDisc()} function.
|
||||
|
||||
@author: Matthias Friedrich <matt@mafr.de>
|
||||
"""
|
||||
__revision__ = '$Id: disc.py 11987 2009-08-22 11:57:51Z matt $'
|
||||
|
||||
import sys
|
||||
import urllib
|
||||
import urlparse
|
||||
import ctypes
|
||||
import ctypes.util
|
||||
from lib.musicbrainz2.model import Disc
|
||||
|
||||
__all__ = [ 'DiscError', 'readDisc', 'getSubmissionUrl' ]
|
||||
|
||||
|
||||
class DiscError(IOError):
|
||||
"""The Audio CD could not be read.
|
||||
|
||||
This may be simply because no disc was in the drive, the device name
|
||||
was wrong or the disc can't be read. Reading errors can occur in case
|
||||
of a damaged disc or a copy protection mechanism, for example.
|
||||
"""
|
||||
pass
|
||||
|
||||
|
||||
def _openLibrary():
|
||||
"""Tries to open libdiscid.
|
||||
|
||||
@return: a C{ctypes.CDLL} object, representing the opened library
|
||||
|
||||
@raise NotImplementedError: if the library can't be opened
|
||||
"""
|
||||
# This only works for ctypes >= 0.9.9.3. Any libdiscid is found,
|
||||
# no matter how it's called on this platform.
|
||||
try:
|
||||
if hasattr(ctypes.cdll, 'find'):
|
||||
libDiscId = ctypes.cdll.find('discid')
|
||||
_setPrototypes(libDiscId)
|
||||
return libDiscId
|
||||
except OSError, e:
|
||||
raise NotImplementedError('Error opening library: ' + str(e))
|
||||
|
||||
# Try to find the library using ctypes.util
|
||||
libName = ctypes.util.find_library('discid')
|
||||
if libName != None:
|
||||
try:
|
||||
libDiscId = ctypes.cdll.LoadLibrary(libName)
|
||||
_setPrototypes(libDiscId)
|
||||
return libDiscId
|
||||
except OSError, e:
|
||||
raise NotImplementedError('Error opening library: ' +
|
||||
str(e))
|
||||
|
||||
# For compatibility with ctypes < 0.9.9.3 try to figure out the library
|
||||
# name without the help of ctypes. We use cdll.LoadLibrary() below,
|
||||
# which isn't available for ctypes == 0.9.9.3.
|
||||
#
|
||||
if sys.platform == 'linux2':
|
||||
libName = 'libdiscid.so.0'
|
||||
elif sys.platform == 'darwin':
|
||||
libName = 'libdiscid.0.dylib'
|
||||
elif sys.platform == 'win32':
|
||||
libName = 'discid.dll'
|
||||
else:
|
||||
# This should at least work for Un*x-style operating systems
|
||||
libName = 'libdiscid.so.0'
|
||||
|
||||
try:
|
||||
libDiscId = ctypes.cdll.LoadLibrary(libName)
|
||||
_setPrototypes(libDiscId)
|
||||
return libDiscId
|
||||
except OSError, e:
|
||||
raise NotImplementedError('Error opening library: ' + str(e))
|
||||
|
||||
assert False # not reached
|
||||
|
||||
|
||||
def _setPrototypes(libDiscId):
|
||||
ct = ctypes
|
||||
libDiscId.discid_new.argtypes = ( )
|
||||
libDiscId.discid_new.restype = ct.c_void_p
|
||||
|
||||
libDiscId.discid_free.argtypes = (ct.c_void_p, )
|
||||
|
||||
libDiscId.discid_read.argtypes = (ct.c_void_p, ct.c_char_p)
|
||||
|
||||
libDiscId.discid_get_error_msg.argtypes = (ct.c_void_p, )
|
||||
libDiscId.discid_get_error_msg.restype = ct.c_char_p
|
||||
|
||||
libDiscId.discid_get_id.argtypes = (ct.c_void_p, )
|
||||
libDiscId.discid_get_id.restype = ct.c_char_p
|
||||
|
||||
libDiscId.discid_get_first_track_num.argtypes = (ct.c_void_p, )
|
||||
libDiscId.discid_get_first_track_num.restype = ct.c_int
|
||||
|
||||
libDiscId.discid_get_last_track_num.argtypes = (ct.c_void_p, )
|
||||
libDiscId.discid_get_last_track_num.restype = ct.c_int
|
||||
|
||||
libDiscId.discid_get_sectors.argtypes = (ct.c_void_p, )
|
||||
libDiscId.discid_get_sectors.restype = ct.c_int
|
||||
|
||||
libDiscId.discid_get_track_offset.argtypes = (ct.c_void_p, ct.c_int)
|
||||
libDiscId.discid_get_track_offset.restype = ct.c_int
|
||||
|
||||
libDiscId.discid_get_track_length.argtypes = (ct.c_void_p, ct.c_int)
|
||||
libDiscId.discid_get_track_length.restype = ct.c_int
|
||||
|
||||
|
||||
def getSubmissionUrl(disc, host='mm.musicbrainz.org', port=80):
|
||||
"""Returns a URL for adding a disc to the MusicBrainz database.
|
||||
|
||||
A fully initialized L{musicbrainz2.model.Disc} object is needed, as
|
||||
returned by L{readDisc}. A disc object returned by the web service
|
||||
doesn't provide the necessary information.
|
||||
|
||||
Note that the created URL is intended for interactive use and points
|
||||
to the MusicBrainz disc submission wizard by default. This method
|
||||
just returns a URL, no network connection is needed. The disc drive
|
||||
isn't used.
|
||||
|
||||
@param disc: a fully initialized L{musicbrainz2.model.Disc} object
|
||||
@param host: a string containing a host name
|
||||
@param port: an integer containing a port number
|
||||
|
||||
@return: a string containing the submission URL
|
||||
|
||||
@see: L{readDisc}
|
||||
"""
|
||||
assert isinstance(disc, Disc), 'musicbrainz2.model.Disc expected'
|
||||
discid = disc.getId()
|
||||
first = disc.getFirstTrackNum()
|
||||
last = disc.getLastTrackNum()
|
||||
sectors = disc.getSectors()
|
||||
assert None not in (discid, first, last, sectors)
|
||||
|
||||
tracks = last - first + 1
|
||||
toc = "%d %d %d " % (first, last, sectors)
|
||||
toc = toc + ' '.join( map(lambda x: str(x[0]), disc.getTracks()) )
|
||||
|
||||
query = urllib.urlencode({ 'id': discid, 'toc': toc, 'tracks': tracks })
|
||||
|
||||
if port == 80:
|
||||
netloc = host
|
||||
else:
|
||||
netloc = host + ':' + str(port)
|
||||
|
||||
url = ('http', netloc, '/bare/cdlookup.html', '', query, '')
|
||||
|
||||
return urlparse.urlunparse(url)
|
||||
|
||||
|
||||
def readDisc(deviceName=None):
|
||||
"""Reads an Audio CD in the disc drive.
|
||||
|
||||
This reads a CD's table of contents (TOC) and calculates the MusicBrainz
|
||||
DiscID, which is a 28 character ASCII string. This DiscID can be used
|
||||
to retrieve a list of matching releases from the web service (see
|
||||
L{musicbrainz2.webservice.Query}).
|
||||
|
||||
Note that an Audio CD has to be in drive for this to work. The
|
||||
C{deviceName} argument may be used to set the device. The default
|
||||
depends on the operating system (on linux, it's C{'/dev/cdrom'}).
|
||||
No network connection is needed for this function.
|
||||
|
||||
If the device doesn't exist or there's no valid Audio CD in the drive,
|
||||
a L{DiscError} exception is raised.
|
||||
|
||||
@param deviceName: a string containing the CD drive's device name
|
||||
|
||||
@return: a L{musicbrainz2.model.Disc} object
|
||||
|
||||
@raise DiscError: if there was a problem reading the disc
|
||||
@raise NotImplementedError: if DiscID generation isn't supported
|
||||
"""
|
||||
libDiscId = _openLibrary()
|
||||
|
||||
handle = libDiscId.discid_new()
|
||||
assert handle != 0, "libdiscid: discid_new() returned NULL"
|
||||
|
||||
# Access the CD drive. This also works if deviceName is None because
|
||||
# ctypes passes a NULL pointer in this case.
|
||||
#
|
||||
res = libDiscId.discid_read(handle, deviceName)
|
||||
if res == 0:
|
||||
raise DiscError(libDiscId.discid_get_error_msg(handle))
|
||||
|
||||
|
||||
# Now extract the data from the result.
|
||||
#
|
||||
disc = Disc()
|
||||
|
||||
disc.setId( libDiscId.discid_get_id(handle) )
|
||||
|
||||
firstTrackNum = libDiscId.discid_get_first_track_num(handle)
|
||||
lastTrackNum = libDiscId.discid_get_last_track_num(handle)
|
||||
|
||||
disc.setSectors(libDiscId.discid_get_sectors(handle))
|
||||
|
||||
for i in range(firstTrackNum, lastTrackNum+1):
|
||||
trackOffset = libDiscId.discid_get_track_offset(handle, i)
|
||||
trackSectors = libDiscId.discid_get_track_length(handle, i)
|
||||
|
||||
disc.addTrack( (trackOffset, trackSectors) )
|
||||
|
||||
disc.setFirstTrackNum(firstTrackNum)
|
||||
disc.setLastTrackNum(lastTrackNum)
|
||||
|
||||
libDiscId.discid_free(handle)
|
||||
|
||||
return disc
|
||||
|
||||
# EOF
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,204 +0,0 @@
|
||||
"""Various utilities to simplify common tasks.
|
||||
|
||||
This module contains helper functions to make common tasks easier.
|
||||
|
||||
@author: Matthias Friedrich <matt@mafr.de>
|
||||
"""
|
||||
__revision__ = '$Id: utils.py 11853 2009-07-21 09:26:50Z luks $'
|
||||
|
||||
import re
|
||||
import urlparse
|
||||
import os.path
|
||||
|
||||
__all__ = [
|
||||
'extractUuid', 'extractFragment', 'extractEntityType',
|
||||
'getReleaseTypeName', 'getCountryName', 'getLanguageName',
|
||||
'getScriptName',
|
||||
]
|
||||
|
||||
|
||||
# A pattern to split the path part of an absolute MB URI.
|
||||
PATH_PATTERN = '^/(artist|release|track|label|release-group)/([^/]*)$'
|
||||
|
||||
|
||||
def extractUuid(uriStr, resType=None):
|
||||
"""Extract the UUID part from a MusicBrainz identifier.
|
||||
|
||||
This function takes a MusicBrainz ID (an absolute URI) as the input
|
||||
and returns the UUID part of the URI, thus turning it into a relative
|
||||
URI. If C{uriStr} is None or a relative URI, then it is returned
|
||||
unchanged.
|
||||
|
||||
The C{resType} parameter can be used for error checking. Set it to
|
||||
'artist', 'release', or 'track' to make sure C{uriStr} is a
|
||||
syntactically valid MusicBrainz identifier of the given resource
|
||||
type. If it isn't, a C{ValueError} exception is raised.
|
||||
This error checking only works if C{uriStr} is an absolute URI, of
|
||||
course.
|
||||
|
||||
Example:
|
||||
|
||||
>>> from musicbrainz2.utils import extractUuid
|
||||
>>> extractUuid('http://musicbrainz.org/artist/c0b2500e-0cef-4130-869d-732b23ed9df5', 'artist')
|
||||
'c0b2500e-0cef-4130-869d-732b23ed9df5'
|
||||
>>>
|
||||
|
||||
@param uriStr: a string containing a MusicBrainz ID (an URI), or None
|
||||
@param resType: a string containing a resource type
|
||||
|
||||
@return: a string containing a relative URI, or None
|
||||
|
||||
@raise ValueError: the given URI is no valid MusicBrainz ID
|
||||
"""
|
||||
if uriStr is None:
|
||||
return None
|
||||
|
||||
(scheme, netloc, path) = urlparse.urlparse(uriStr)[:3]
|
||||
|
||||
if scheme == '':
|
||||
return uriStr # no URI, probably already the UUID
|
||||
|
||||
if scheme != 'http' or netloc != 'musicbrainz.org':
|
||||
raise ValueError('%s is no MB ID.' % uriStr)
|
||||
|
||||
m = re.match(PATH_PATTERN, path)
|
||||
|
||||
if m:
|
||||
if resType is None:
|
||||
return m.group(2)
|
||||
else:
|
||||
if m.group(1) == resType:
|
||||
return m.group(2)
|
||||
else:
|
||||
raise ValueError('expected "%s" Id' % resType)
|
||||
else:
|
||||
raise ValueError('%s is no valid MB ID.' % uriStr)
|
||||
|
||||
|
||||
def extractFragment(uriStr, uriPrefix=None):
|
||||
"""Extract the fragment part from a URI.
|
||||
|
||||
If C{uriStr} is None or no absolute URI, then it is returned unchanged.
|
||||
|
||||
The C{uriPrefix} parameter can be used for error checking. If C{uriStr}
|
||||
is an absolute URI, then the function checks if it starts with
|
||||
C{uriPrefix}. If it doesn't, a C{ValueError} exception is raised.
|
||||
|
||||
@param uriStr: a string containing an absolute URI
|
||||
@param uriPrefix: a string containing an URI prefix
|
||||
|
||||
@return: a string containing the fragment, or None
|
||||
|
||||
@raise ValueError: the given URI doesn't start with C{uriPrefix}
|
||||
"""
|
||||
if uriStr is None:
|
||||
return None
|
||||
|
||||
(scheme, netloc, path, params, query, frag) = urlparse.urlparse(uriStr)
|
||||
if scheme == '':
|
||||
return uriStr # this is no URI
|
||||
|
||||
if uriPrefix is None or uriStr.startswith(uriPrefix):
|
||||
return frag
|
||||
else:
|
||||
raise ValueError("prefix doesn't match URI %s" % uriStr)
|
||||
|
||||
|
||||
def extractEntityType(uriStr):
|
||||
"""Returns the entity type an entity URI is referring to.
|
||||
|
||||
@param uriStr: a string containing an absolute entity URI
|
||||
|
||||
@return: a string containing 'artist', 'release', 'track', or 'label'
|
||||
|
||||
@raise ValueError: if the given URI is no valid MusicBrainz ID
|
||||
"""
|
||||
if uriStr is None:
|
||||
raise ValueError('None is no valid entity URI')
|
||||
|
||||
(scheme, netloc, path) = urlparse.urlparse(uriStr)[:3]
|
||||
|
||||
if scheme == '':
|
||||
raise ValueError('%s is no absolute MB ID.' % uriStr)
|
||||
|
||||
if scheme != 'http' or netloc != 'musicbrainz.org':
|
||||
raise ValueError('%s is no MB ID.' % uriStr)
|
||||
|
||||
m = re.match(PATH_PATTERN, path)
|
||||
|
||||
if m:
|
||||
return m.group(1)
|
||||
else:
|
||||
raise ValueError('%s is no valid MB ID.' % uriStr)
|
||||
|
||||
|
||||
def getReleaseTypeName(releaseType):
|
||||
"""Returns the name of a release type URI.
|
||||
|
||||
@param releaseType: a string containing a release type URI
|
||||
|
||||
@return: a string containing a printable name for the release type
|
||||
|
||||
@see: L{musicbrainz2.model.Release}
|
||||
"""
|
||||
from lib.musicbrainz2.data.releasetypenames import releaseTypeNames
|
||||
return releaseTypeNames.get(releaseType)
|
||||
|
||||
|
||||
def getCountryName(id_):
|
||||
"""Returns a country's name based on an ISO-3166 country code.
|
||||
|
||||
The country table this function is based on has been modified for
|
||||
MusicBrainz purposes by using the extension mechanism defined in
|
||||
ISO-3166. All IDs are still valid ISO-3166 country codes, but some
|
||||
IDs have been added to include historic countries and some of the
|
||||
country names have been modified to make them better suited for
|
||||
display purposes.
|
||||
|
||||
If the country ID is not found, None is returned. This may happen
|
||||
for example, when new countries are added to the MusicBrainz web
|
||||
service which aren't known to this library yet.
|
||||
|
||||
@param id_: a two-letter upper case string containing an ISO-3166 code
|
||||
|
||||
@return: a string containing the country's name, or None
|
||||
|
||||
@see: L{musicbrainz2.model}
|
||||
"""
|
||||
from musicbrainz2.data.countrynames import countryNames
|
||||
return countryNames.get(id_)
|
||||
|
||||
|
||||
def getLanguageName(id_):
|
||||
"""Returns a language name based on an ISO-639-2/T code.
|
||||
|
||||
This function uses a subset of the ISO-639-2/T code table to map
|
||||
language IDs (terminologic, not bibliographic ones!) to names.
|
||||
|
||||
@param id_: a three-letter upper case string containing an ISO-639-2/T code
|
||||
|
||||
@return: a string containing the language's name, or None
|
||||
|
||||
@see: L{musicbrainz2.model}
|
||||
"""
|
||||
from musicbrainz2.data.languagenames import languageNames
|
||||
return languageNames.get(id_)
|
||||
|
||||
|
||||
def getScriptName(id_):
|
||||
"""Returns a script name based on an ISO-15924 code.
|
||||
|
||||
This function uses a subset of the ISO-15924 code table to map
|
||||
script IDs to names.
|
||||
|
||||
@param id_: a four-letter string containing an ISO-15924 script code
|
||||
|
||||
@return: a string containing the script's name, or None
|
||||
|
||||
@see: L{musicbrainz2.model}
|
||||
"""
|
||||
from musicbrainz2.data.scriptnames import scriptNames
|
||||
return scriptNames.get(id_)
|
||||
|
||||
|
||||
# EOF
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -1 +1 @@
|
||||
from musicbrainz import *
|
||||
from lib.musicbrainzngs.musicbrainz import *
|
||||
|
||||
62
lib/musicbrainzngs/compat.py
Normal file
62
lib/musicbrainzngs/compat.py
Normal file
@@ -0,0 +1,62 @@
|
||||
# -*- coding: utf-8 -*-
|
||||
# Copyright (c) 2012 Kenneth Reitz.
|
||||
|
||||
# Permission to use, copy, modify, and/or distribute this software for any
|
||||
# purpose with or without fee is hereby granted, provided that the above
|
||||
# copyright notice and this permission notice appear in all copies.
|
||||
|
||||
# THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
|
||||
# WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
|
||||
# MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
|
||||
# ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
|
||||
# WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
|
||||
# ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
|
||||
# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
|
||||
|
||||
"""
|
||||
pythoncompat
|
||||
"""
|
||||
|
||||
|
||||
import sys
|
||||
|
||||
# -------
|
||||
# Pythons
|
||||
# -------
|
||||
|
||||
# Syntax sugar.
|
||||
_ver = sys.version_info
|
||||
|
||||
#: Python 2.x?
|
||||
is_py2 = (_ver[0] == 2)
|
||||
|
||||
#: Python 3.x?
|
||||
is_py3 = (_ver[0] == 3)
|
||||
|
||||
# ---------
|
||||
# Specifics
|
||||
# ---------
|
||||
|
||||
if is_py2:
|
||||
from StringIO import StringIO
|
||||
from urllib2 import HTTPPasswordMgr, HTTPDigestAuthHandler, Request,\
|
||||
HTTPHandler, build_opener, HTTPError, URLError,\
|
||||
build_opener
|
||||
from httplib import BadStatusLine, HTTPException
|
||||
from urlparse import urlunparse
|
||||
from urllib import urlencode
|
||||
|
||||
bytes = str
|
||||
unicode = unicode
|
||||
basestring = basestring
|
||||
elif is_py3:
|
||||
from io import StringIO
|
||||
from urllib.request import HTTPPasswordMgr, HTTPDigestAuthHandler, Request,\
|
||||
HTTPHandler, build_opener
|
||||
from urllib.error import HTTPError, URLError
|
||||
from http.client import HTTPException, BadStatusLine
|
||||
from urllib.parse import urlunparse, urlencode
|
||||
|
||||
unicode = str
|
||||
bytes = bytes
|
||||
basestring = (str,bytes)
|
||||
@@ -4,9 +4,11 @@
|
||||
# See the COPYING file for more information.
|
||||
|
||||
import xml.etree.ElementTree as ET
|
||||
import string
|
||||
import StringIO
|
||||
import logging
|
||||
|
||||
from lib.musicbrainzngs import compat
|
||||
from lib.musicbrainzngs import util
|
||||
|
||||
try:
|
||||
from ET import fixtag
|
||||
except:
|
||||
@@ -16,7 +18,7 @@ except:
|
||||
# tag and namespace declaration, if any
|
||||
if isinstance(tag, ET.QName):
|
||||
tag = tag.text
|
||||
namespace_uri, tag = string.split(tag[1:], "}", 1)
|
||||
namespace_uri, tag = tag[1:].split("}", 1)
|
||||
prefix = namespaces.get(namespace_uri)
|
||||
if prefix is None:
|
||||
prefix = "ns%d" % len(namespaces)
|
||||
@@ -29,6 +31,7 @@ except:
|
||||
xmlns = None
|
||||
return "%s:%s" % (prefix, tag), xmlns
|
||||
|
||||
|
||||
NS_MAP = {"http://musicbrainz.org/ns/mmd-2.0#": "ws2",
|
||||
"http://musicbrainz.org/ns/ext#-2.0": "ext"}
|
||||
_log = logging.getLogger("python-musicbrainz-ngs")
|
||||
@@ -113,9 +116,7 @@ def parse_inner(inner_els, element):
|
||||
return result
|
||||
|
||||
def parse_message(message):
|
||||
s = message.read()
|
||||
f = StringIO.StringIO(s)
|
||||
tree = ET.ElementTree(file=f)
|
||||
tree = util.bytes_to_elementtree(message)
|
||||
root = tree.getroot()
|
||||
result = {}
|
||||
valid_elements = {"artist": parse_artist,
|
||||
@@ -176,7 +177,8 @@ def parse_artist_list(al):
|
||||
def parse_artist(artist):
|
||||
result = {}
|
||||
attribs = ["id", "type", "ext:score"]
|
||||
elements = ["name", "sort-name", "country", "user-rating", "disambiguation"]
|
||||
elements = ["name", "sort-name", "country", "user-rating",
|
||||
"disambiguation", "gender", "ipi"]
|
||||
inner_els = {"life-span": parse_artist_lifespan,
|
||||
"recording-list": parse_recording_list,
|
||||
"release-list": parse_release_list,
|
||||
@@ -199,7 +201,8 @@ def parse_label_list(ll):
|
||||
def parse_label(label):
|
||||
result = {}
|
||||
attribs = ["id", "type", "ext:score"]
|
||||
elements = ["name", "sort-name", "country", "label-code", "user-rating"]
|
||||
elements = ["name", "sort-name", "country", "label-code", "user-rating",
|
||||
"ipi", "disambiguation"]
|
||||
inner_els = {"life-span": parse_artist_lifespan,
|
||||
"release-list": parse_release_list,
|
||||
"tag-list": parse_tag_list,
|
||||
@@ -427,7 +430,7 @@ def parse_track_list(tl):
|
||||
|
||||
def parse_track(track):
|
||||
result = {}
|
||||
elements = ["position", "title"]
|
||||
elements = ["position", "title","length"] #CHANGED!!!
|
||||
inner_els = {"recording": parse_recording}
|
||||
|
||||
result.update(parse_elements(elements, track))
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
37
lib/musicbrainzngs/util.py
Normal file
37
lib/musicbrainzngs/util.py
Normal file
@@ -0,0 +1,37 @@
|
||||
# This file is part of the musicbrainzngs library
|
||||
# Copyright (C) Alastair Porter, Adrian Sampson, and others
|
||||
# This file is distributed under a BSD-2-Clause type license.
|
||||
# See the COPYING file for more information.
|
||||
|
||||
import sys
|
||||
import locale
|
||||
import xml.etree.ElementTree as ET
|
||||
|
||||
from . import compat
|
||||
|
||||
def _unicode(string, encoding=None):
|
||||
"""Try to decode byte strings to unicode.
|
||||
This can only be a guess, but this might be better than failing.
|
||||
It is safe to use this on numbers or strings that are already unicode.
|
||||
"""
|
||||
if isinstance(string, compat.unicode):
|
||||
unicode_string = string
|
||||
elif isinstance(string, compat.bytes):
|
||||
# use given encoding, stdin, preferred until something != None is found
|
||||
if encoding is None:
|
||||
encoding = sys.stdin.encoding
|
||||
if encoding is None:
|
||||
encoding = locale.getpreferredencoding()
|
||||
unicode_string = string.decode(encoding, "ignore")
|
||||
else:
|
||||
unicode_string = compat.unicode(string)
|
||||
return unicode_string.replace('\x00', '').strip()
|
||||
|
||||
def bytes_to_elementtree(_bytes):
|
||||
if compat.is_py3:
|
||||
s = _unicode(_bytes.read(), "utf-8")
|
||||
else:
|
||||
s = _bytes.read()
|
||||
f = compat.StringIO(s)
|
||||
tree = ET.ElementTree(file=f)
|
||||
return tree
|
||||
Reference in New Issue
Block a user