Repository: internetarchive/openlibrary

Issue:
DeprecationWarning: `urllib.parse.splitquery()` is deprecated as of 3.8
<!-- What problem are we solving? What does the experience look like today? What are the symptoms? -->


### Evidence / Screenshot (if possible)
When we run pytest in our GitHub Actions, we get the following warning
```
=============================== warnings summary ===============================
openlibrary/coverstore/tests/test_doctests.py::test_doctest[openlibrary.coverstore.utils]
openlibrary/coverstore/tests/test_doctests.py::test_doctest[openlibrary.coverstore.utils]
openlibrary/coverstore/tests/test_doctests.py::test_doctest[openlibrary.coverstore.utils]
  /home/runner/work/openlibrary/openlibrary/openlibrary/coverstore/utils.py:88:
   DeprecationWarning: urllib.parse.splitquery() is deprecated as of 3.8, use urllib.parse.urlparse() instead
    base, query = splitquery(URL)
```
https://github.com/internetarchive/openlibrary/blob/master/openlibrary/coverstore/utils.py#L88

### Relevant url?
<!-- `https://openlibrary.org/...` -->

### Steps to Reproduce
<!-- What steps caused you to find the bug? -->
1. Go to ...
2. Do ...

<!-- What actually happened after these steps? What did you expect to happen? -->
* Actual: pytest warning
* Expected: No pytest warning

### Details

- **Logged in (Y/N)?**
- **Browser type/version?**
- **Operating system?**
- **Environment (prod/dev/local)?** prod
<!-- If not sure, put prod -->

### Proposal & Constraints
<!-- What is the proposed solution / implementation? Is there a precedent of this approach succeeding elsewhere? -->

### Related files
<!-- Files related to this issue; this is super useful for new contributors who might want to help! If you're not sure, leave this blank; a maintainer will add them. -->

### Stakeholders
<!-- @ tag stakeholders of this bug -->



Discussion:
I'd like to work on this.
Deprecated in Py38 but is still available in Python 3.11 which is not yet released.

Resolving patch:
diff --git a/openlibrary/coverstore/utils.py b/openlibrary/coverstore/utils.py
--- a/openlibrary/coverstore/utils.py
+++ b/openlibrary/coverstore/utils.py
@@ -9,7 +9,7 @@
 
 import requests
 import web
-from urllib.parse import splitquery, unquote, unquote_plus  # type: ignore[attr-defined]
+from urllib.parse import urlsplit, urlunsplit, parse_qsl, unquote, unquote_plus  # type: ignore[attr-defined]
 from urllib.parse import urlencode as real_urlencode
 
 from openlibrary.coverstore import config, oldb
@@ -78,17 +78,17 @@ def download(url):
     return requests.get(url, headers={'User-Agent': USER_AGENT}).content
 
 
-def urldecode(url):
+def urldecode(url: str) -> tuple[str, dict[str, str]]:
     """
     >>> urldecode('http://google.com/search?q=bar&x=y')
     ('http://google.com/search', {'q': 'bar', 'x': 'y'})
     >>> urldecode('http://google.com/')
     ('http://google.com/', {})
     """
-    base, query = splitquery(url)
-    query = query or ""
-    items = [item.split('=', 1) for item in query.split('&') if '=' in item]
+    split_url = urlsplit(url)
+    items = parse_qsl(split_url.query)
     d = {unquote(k): unquote_plus(v) for (k, v) in items}
+    base = urlunsplit(split_url._replace(query=''))
     return base, d
 
 


Test patch:
diff --git a/openlibrary/coverstore/tests/test_coverstore.py b/openlibrary/coverstore/tests/test_coverstore.py
--- a/openlibrary/coverstore/tests/test_coverstore.py
+++ b/openlibrary/coverstore/tests/test_coverstore.py
@@ -2,7 +2,7 @@
 import web
 from os.path import abspath, exists, join, dirname, pardir
 
-from openlibrary.coverstore import config, coverlib
+from openlibrary.coverstore import config, coverlib, utils
 
 static_dir = abspath(join(dirname(__file__), pardir, pardir, pardir, 'static'))
 
@@ -135,3 +135,21 @@ def test_image_path(image_dir):
         coverlib.find_image_path('covers_0000_00.tar:1234:10')
         == config.data_root + '/items/covers_0000/covers_0000_00.tar:1234:10'
     )
+
+
+def test_urldecode():
+    assert utils.urldecode('http://google.com/search?q=bar&x=y') == (
+        'http://google.com/search',
+        {'q': 'bar', 'x': 'y'},
+    )
+    assert utils.urldecode('google.com/search?q=bar&x=y') == (
+        'google.com/search',
+        {'q': 'bar', 'x': 'y'},
+    )
+    assert utils.urldecode('http://google.com/search') == (
+        'http://google.com/search',
+        {},
+    )
+    assert utils.urldecode('http://google.com/') == ('http://google.com/', {})
+    assert utils.urldecode('http://google.com/?') == ('http://google.com/', {})
+    assert utils.urldecode('?q=bar') == ('', {'q': 'bar'})