diff --git a/picard/coverart/providers/caa.py b/picard/coverart/providers/caa.py index e1bad91d7..1ddf938d9 100644 --- a/picard/coverart/providers/caa.py +++ b/picard/coverart/providers/caa.py @@ -65,10 +65,7 @@ from picard.coverart.utils import ( CAA_TYPES, translate_caa_type, ) -from picard.webservice import ( - hostkey_from_url, - ratecontrol, -) +from picard.webservice import ratecontrol from picard.ui import PicardDialog from picard.ui.ui_provider_options_caa import Ui_CaaOptions @@ -92,8 +89,8 @@ _CAA_IMAGE_SIZE_DEFAULT = 500 _CAA_IMAGE_TYPE_DEFAULT_INCLUDE = ['front'] _CAA_IMAGE_TYPE_DEFAULT_EXCLUDE = ['matrix/runout', 'raw/unedited', 'watermark'] -ratecontrol.set_minimum_delay(hostkey_from_url(CAA_URL), 0) -ratecontrol.set_minimum_delay(hostkey_from_url('https://archive.org'), 0) +ratecontrol.set_minimum_delay_for_url(CAA_URL, 0) +ratecontrol.set_minimum_delay_for_url('https://archive.org', 0) def caa_url_fallback_list(desired_size, thumbnails): diff --git a/picard/webservice/__init__.py b/picard/webservice/__init__.py index 1a277ccba..6fad8f9e7 100644 --- a/picard/webservice/__init__.py +++ b/picard/webservice/__init__.py @@ -64,6 +64,7 @@ from picard.util import ( ) from picard.util.xml import parse_xml from picard.webservice import ratecontrol +from picard.webservice.utils import port_from_qurl COUNT_REQUESTS_DELAY_MS = 250 @@ -91,42 +92,6 @@ class UnknownResponseParserError(Exception): super().__init__(message) -def port_from_qurl(qurl): - """Returns QUrl port or default ports (443 for https, 80 for http)""" - if qurl.scheme() == 'https': - return qurl.port(443) - return qurl.port(80) - - -def hostkey_from_url(url): - """Returns (host, port) from passed url (as string or QUrl)""" - if not isinstance(url, QUrl): - url = QUrl(url) - return (url.host(), port_from_qurl(url)) - - -def host_port_to_url(host, port, path=None, scheme=None, as_string=False): - """Convert host & port (with optional path and scheme) to an URL""" - url = QUrl() - if scheme is None: - if port == 443: - scheme = 'https' - else: - scheme = 'http' - url.setScheme(scheme) - - if ((scheme == 'https' and port != 443) - or (scheme == 'http' and port != 80)): - url.setPort(port) - - url.setHost(host) - - if path is not None: - url.setPath(path) - - return url.toString() if as_string else url - - class WSRequest(QNetworkRequest): """Represents a single HTTP request.""" _access_token = None diff --git a/picard/webservice/api_helpers.py b/picard/webservice/api_helpers.py index 9c01d63b4..ff502a137 100644 --- a/picard/webservice/api_helpers.py +++ b/picard/webservice/api_helpers.py @@ -34,13 +34,12 @@ from picard.const import ( ) from picard.webservice import ( CLIENT_STRING, - host_port_to_url, - hostkey_from_url, ratecontrol, ) +from picard.webservice.utils import host_port_to_url -ratecontrol.set_minimum_delay(hostkey_from_url(ACOUSTID_URL), 333) +ratecontrol.set_minimum_delay_for_url(ACOUSTID_URL, 333) def escape_lucene_query(text): diff --git a/picard/webservice/ratecontrol.py b/picard/webservice/ratecontrol.py index 0235bb024..8e9248270 100644 --- a/picard/webservice/ratecontrol.py +++ b/picard/webservice/ratecontrol.py @@ -29,6 +29,7 @@ import sys import time from picard import log +from picard.webservice.utils import hostkey_from_url # ============================================================================ @@ -85,6 +86,14 @@ def set_minimum_delay(hostkey, delay_ms): REQUEST_DELAY_MINIMUM[hostkey] = delay_ms +def set_minimum_delay_for_url(url, delay_ms): + """Set the minimun delay between requests + url will be converted to an unique key (host, port) + delay_ms is the delay in milliseconds + """ + set_minimum_delay(hostkey_from_url(url), delay_ms) + + def current_delay(hostkey): """Returns the current delay (adaptive) between requests for this hostkey hostkey is an unique key, for example (host, port) diff --git a/picard/webservice/utils.py b/picard/webservice/utils.py new file mode 100644 index 000000000..272208da0 --- /dev/null +++ b/picard/webservice/utils.py @@ -0,0 +1,67 @@ +# -*- coding: utf-8 -*- +# +# Picard, the next-generation MusicBrainz tagger +# +# Copyright (C) 2007 Lukáš Lalinský +# Copyright (C) 2009 Carlin Mangar +# Copyright (C) 2017 Sambhav Kothari +# Copyright (C) 2018-2022 Philipp Wolfer +# Copyright (C) 2018-2023 Laurent Monin +# Copyright (C) 2021 Tche333 +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + + +""" +Asynchronous web service utilities. +""" + +from PyQt5.QtCore import QUrl + + +def port_from_qurl(qurl): + """Returns QUrl port or default ports (443 for https, 80 for http)""" + if qurl.scheme() == 'https': + return qurl.port(443) + return qurl.port(80) + + +def hostkey_from_url(url): + """Returns (host, port) from passed url (as string or QUrl)""" + if not isinstance(url, QUrl): + url = QUrl(url) + return (url.host(), port_from_qurl(url)) + + +def host_port_to_url(host, port, path=None, scheme=None, as_string=False): + """Convert host & port (with optional path and scheme) to an URL""" + url = QUrl() + if scheme is None: + if port == 443: + scheme = 'https' + else: + scheme = 'http' + url.setScheme(scheme) + + if ((scheme == 'https' and port != 443) + or (scheme == 'http' and port != 80)): + url.setPort(port) + + url.setHost(host) + + if path is not None: + url.setPath(path) + + return url.toString() if as_string else url diff --git a/test/test_webservice.py b/test/test_webservice.py index ff0bf55ea..66113f775 100644 --- a/test/test_webservice.py +++ b/test/test_webservice.py @@ -44,10 +44,12 @@ from picard.webservice import ( UnknownResponseParserError, WebService, WSRequest, + ratecontrol, +) +from picard.webservice.utils import ( host_port_to_url, hostkey_from_url, port_from_qurl, - ratecontrol, ) @@ -536,7 +538,7 @@ class WSRequestTest(PicardTestCase): self.assertEqual(request.url().toString(), 'http://example.org/path?a=1&a=2&b=x x&c=1+2&d=%26&e=?') -class MiscWebServiceTest(PicardTestCase): +class WebServiceUtilsTest(PicardTestCase): def test_port_from_qurl_http(self): self.assertEqual(port_from_qurl(QUrl('http://example.org')), 80)