Merge branch 'ngs'

This commit is contained in:
rembo10
2012-05-29 19:17:33 +05:30
17 changed files with 1165 additions and 7887 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -1 +1 @@
from musicbrainz import *
from lib.musicbrainzngs.musicbrainz import *

View 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)

View File

@@ -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

View 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