Conflicts:
	NEWS.txt
This commit is contained in:
Lukáš Lalinský
2011-10-20 10:08:16 +02:00
2 changed files with 41 additions and 14 deletions

View File

@@ -1,12 +1,12 @@
Version 0.16 - 2011-XX-XX
* Added AcoustID support.
* Fixed track metadata plugins.
* Added new internal %_totalalbumtracks% tag field.
* Track metadata plugins now run also on non-album tracks.
* Added new internal %_totalalbumtracks% tag field. (PICARD-16)
* Track metadata plugins now run also on non-album tracks. (PICARD-7)
* Fixed custom Various Artists name on the %albumartist% field. (PICARD-5)
* Album artist is now correctly "translated". (PICARD-1)
* Unicode punctuation is now converted to ASCII by default.
* WavPack correction files are moved together with the main files.
* WavPack correction files are moved together with the main files. (PICARD-15)
* Unicode filename normalization on OS X.
* Original release date is now saved into %originaldate%.
* Allow tagging with localized artist aliases (PICARD-17)
@@ -15,6 +15,8 @@ Version 0.16 - 2011-XX-XX
* Refreshing an album will refresh its "other versions" listing. (PICARD-8)
* "Unicode punctuation to ASCII" now works on album-level metadata. (PICARD-50)
* DJ-mix tags should only be written to the medium where they apply. (PICARD-20)
* Support URL redirects in web service/network request module (PICARD-54)
* Jamendo and Archive.org cover art is displayed on web page, but not loaded by Picard plugin (PICARD-52)
Version 0.15.1 - 2011-07-31
* "Other versions" menu now displays release labels and catalog numbers.

View File

@@ -30,6 +30,7 @@ import traceback
import time
from collections import deque, defaultdict
from PyQt4 import QtCore, QtNetwork, QtXml
from PyQt4.QtCore import QUrl
from picard import version_string
from picard.util import partial
from picard.const import PUID_SUBMIT_HOST, PUID_SUBMIT_PORT, ACOUSTID_KEY
@@ -142,7 +143,7 @@ class XmlWebService(QtCore.QObject):
def _start_request(self, method, host, port, path, data, handler, xml, mblogin=False):
self.log.debug("%s http://%s:%d%s", method, host, port, path)
url = QtCore.QUrl.fromEncoded("http://%s:%d%s" % (host, port, path))
url = QUrl.fromEncoded("http://%s:%d%s" % (host, port, path))
if mblogin:
url.setUserName(self.config.setting["username"])
url.setPassword(self.config.setting["password"])
@@ -157,6 +158,16 @@ class XmlWebService(QtCore.QObject):
self._active_requests[reply] = (request, handler, xml)
return True
@staticmethod
def urls_equivalent(leftUrl, rightUrl):
"""
Lazy method to determine whether two QUrls are equivalent. At the moment it assumes that if ports are unset
that they are port 80 - in absence of a URL normalization function in QUrl or ability to use qHash
from QT 4.7
"""
return leftUrl.port(80) == rightUrl.port(80) and \
leftUrl.toString(QUrl.FormattingOption(QUrl.RemovePort)) == rightUrl.toString(QUrl.FormattingOption(QUrl.RemovePort))
def _process_reply(self, reply):
try:
request, handler, xml = self._active_requests.pop(reply)
@@ -164,13 +175,28 @@ class XmlWebService(QtCore.QObject):
self.log.error("Error: Request not found for %s" % str(reply.request().url().toString()))
return
error = int(reply.error())
redirect = reply.attribute(QtNetwork.QNetworkRequest.RedirectionTargetAttribute).toUrl()
self.log.debug("Received reply for %s: HTTP %d (%s)",
reply.request().url().toString(),
reply.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute).toInt()[0],
reply.attribute(QtNetwork.QNetworkRequest.HttpReasonPhraseAttribute).toString())
if handler is not None:
if error:
#print "ERROR", reply.error(), reply.errorString()
#for name in reply.rawHeaderList():
# print name, reply.rawHeader(name)
self.log.debug("HTTP Error: %d", error)
if xml:
self.log.error("Network request error for %s: %s (QT code %d, HTTP code %d)",
reply.request().url().toString(),
reply.errorString(),
error,
reply.attribute(QtNetwork.QNetworkRequest.HttpStatusCodeAttribute).toInt()[0])
# Redirect if found and not infinite
if not redirect.isEmpty() and not XmlWebService.urls_equivalent(redirect, reply.request().url()):
self.log.debug("Redirect to %s requested", redirect.toString())
self.get(str(redirect.host()),
redirect.port(80),
# retain path, query string and anchors from redirect URL
redirect.toString(QUrl.FormattingOption(QUrl.RemoveAuthority | QUrl.RemoveScheme)),
handler, xml, priority=True, important=True)
elif xml:
xml_handler = XmlHandler()
xml_handler.init()
xml_reader = QtXml.QXmlSimpleReader()
@@ -296,7 +322,7 @@ class XmlWebService(QtCore.QObject):
if query: filters.append(('query', ' '.join(query)))
params = []
for name, value in filters:
value = str(QtCore.QUrl.toPercentEncoding(QtCore.QString(value)))
value = str(QUrl.toPercentEncoding(QtCore.QString(value)))
params.append('%s=%s' % (str(name), value))
path = "/ws/2/%s/?%s" % (entitytype, "&".join(params))
return self.get(host, port, path, handler)
@@ -337,7 +363,7 @@ class XmlWebService(QtCore.QObject):
host, port = 'ofa.musicdns.org', 80
filters = []
for name, value in kwargs.items():
value = str(QtCore.QUrl.toPercentEncoding(value))
value = str(QUrl.toPercentEncoding(value))
filters.append('%s=%s' % (str(name), value))
return self.post(host, port, '/ofa/1/track/', '&'.join(filters), handler, mblogin=False)
@@ -346,7 +372,7 @@ class XmlWebService(QtCore.QObject):
args['client'] = ACOUSTID_KEY
args['format'] = 'xml'
for name, value in args.items():
value = str(QtCore.QUrl.toPercentEncoding(value))
value = str(QUrl.toPercentEncoding(value))
filters.append('%s=%s' % (str(name), value))
return '&'.join(filters)
@@ -356,8 +382,7 @@ class XmlWebService(QtCore.QObject):
return self.post(host, port, '/v2/lookup', body, handler, mblogin=False)
def submit_acoustid_fingerprints(self, submissions, handler):
args = {}
args['user'] = self.config.setting["acoustid_apikey"]
args = {'user': self.config.setting["acoustid_apikey"]}
for i, submission in enumerate(submissions):
args['fingerprint.%d' % i] = str(submission.fingerprint)
args['duration.%d' % i] = str(submission.duration)