mirror of
https://github.com/python/cpython.git
synced 2024-11-28 12:31:14 +08:00
Issue 600362: Relocated parse_qs() and parse_qsl(), from the cgi module
to the urlparse one. Added a DeprecationWarning in the old module, it will be deprecated in the future. Docs and tests updated.
This commit is contained in:
parent
849f79a5d6
commit
c469d4c3aa
@ -257,49 +257,18 @@ algorithms implemented in this module in other circumstances.
|
|||||||
|
|
||||||
Parse a query in the environment or from a file (the file defaults to
|
Parse a query in the environment or from a file (the file defaults to
|
||||||
``sys.stdin``). The *keep_blank_values* and *strict_parsing* parameters are
|
``sys.stdin``). The *keep_blank_values* and *strict_parsing* parameters are
|
||||||
passed to :func:`parse_qs` unchanged.
|
passed to :func:`urllib.parse.parse_qs` unchanged.
|
||||||
|
|
||||||
|
|
||||||
.. function:: parse_qs(qs[, keep_blank_values[, strict_parsing]])
|
.. function:: parse_qs(qs[, keep_blank_values[, strict_parsing]])
|
||||||
|
|
||||||
Parse a query string given as a string argument (data of type
|
This function is deprecated in this module. Use :func:`urllib.parse.parse_qs`
|
||||||
:mimetype:`application/x-www-form-urlencoded`). Data are returned as a
|
instead. It is maintained here only for backward compatiblity.
|
||||||
dictionary. The dictionary keys are the unique query variable names and the
|
|
||||||
values are lists of values for each name.
|
|
||||||
|
|
||||||
The optional argument *keep_blank_values* is a flag indicating whether blank
|
|
||||||
values in URL encoded queries should be treated as blank strings. A true value
|
|
||||||
indicates that blanks should be retained as blank strings. The default false
|
|
||||||
value indicates that blank values are to be ignored and treated as if they were
|
|
||||||
not included.
|
|
||||||
|
|
||||||
The optional argument *strict_parsing* is a flag indicating what to do with
|
|
||||||
parsing errors. If false (the default), errors are silently ignored. If true,
|
|
||||||
errors raise a :exc:`ValueError` exception.
|
|
||||||
|
|
||||||
Use the :func:`urllib.parse.urlencode` function to convert such dictionaries into
|
|
||||||
query strings.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: parse_qsl(qs[, keep_blank_values[, strict_parsing]])
|
.. function:: parse_qsl(qs[, keep_blank_values[, strict_parsing]])
|
||||||
|
|
||||||
Parse a query string given as a string argument (data of type
|
This function is deprecated in this module. Use :func:`urllib.parse.parse_qs`
|
||||||
:mimetype:`application/x-www-form-urlencoded`). Data are returned as a list of
|
instead. It is maintained here only for backward compatiblity.
|
||||||
name, value pairs.
|
|
||||||
|
|
||||||
The optional argument *keep_blank_values* is a flag indicating whether blank
|
|
||||||
values in URL encoded queries should be treated as blank strings. A true value
|
|
||||||
indicates that blanks should be retained as blank strings. The default false
|
|
||||||
value indicates that blank values are to be ignored and treated as if they were
|
|
||||||
not included.
|
|
||||||
|
|
||||||
The optional argument *strict_parsing* is a flag indicating what to do with
|
|
||||||
parsing errors. If false (the default), errors are silently ignored. If true,
|
|
||||||
errors raise a :exc:`ValueError` exception.
|
|
||||||
|
|
||||||
Use the :func:`urllib.parse.urlencode` function to convert such lists of pairs into
|
|
||||||
query strings.
|
|
||||||
|
|
||||||
|
|
||||||
.. function:: parse_multipart(fp, pdict)
|
.. function:: parse_multipart(fp, pdict)
|
||||||
|
|
||||||
@ -307,7 +276,7 @@ algorithms implemented in this module in other circumstances.
|
|||||||
Arguments are *fp* for the input file and *pdict* for a dictionary containing
|
Arguments are *fp* for the input file and *pdict* for a dictionary containing
|
||||||
other parameters in the :mailheader:`Content-Type` header.
|
other parameters in the :mailheader:`Content-Type` header.
|
||||||
|
|
||||||
Returns a dictionary just like :func:`parse_qs` keys are the field names, each
|
Returns a dictionary just like :func:`urllib.parse.parse_qs` keys are the field names, each
|
||||||
value is a list of values for that field. This is easy to use but not much good
|
value is a list of values for that field. This is easy to use but not much good
|
||||||
if you are expecting megabytes to be uploaded --- in that case, use the
|
if you are expecting megabytes to be uploaded --- in that case, use the
|
||||||
:class:`FieldStorage` class instead which is much more flexible.
|
:class:`FieldStorage` class instead which is much more flexible.
|
||||||
|
@ -89,6 +89,47 @@ The :mod:`urllib.parse` module defines the following functions:
|
|||||||
object.
|
object.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: parse_qs(qs[, keep_blank_values[, strict_parsing]])
|
||||||
|
|
||||||
|
Parse a query string given as a string argument (data of type
|
||||||
|
:mimetype:`application/x-www-form-urlencoded`). Data are returned as a
|
||||||
|
dictionary. The dictionary keys are the unique query variable names and the
|
||||||
|
values are lists of values for each name.
|
||||||
|
|
||||||
|
The optional argument *keep_blank_values* is a flag indicating whether blank
|
||||||
|
values in URL encoded queries should be treated as blank strings. A true value
|
||||||
|
indicates that blanks should be retained as blank strings. The default false
|
||||||
|
value indicates that blank values are to be ignored and treated as if they were
|
||||||
|
not included.
|
||||||
|
|
||||||
|
The optional argument *strict_parsing* is a flag indicating what to do with
|
||||||
|
parsing errors. If false (the default), errors are silently ignored. If true,
|
||||||
|
errors raise a :exc:`ValueError` exception.
|
||||||
|
|
||||||
|
Use the :func:`urllib.urlencode` function to convert such dictionaries into
|
||||||
|
query strings.
|
||||||
|
|
||||||
|
|
||||||
|
.. function:: parse_qsl(qs[, keep_blank_values[, strict_parsing]])
|
||||||
|
|
||||||
|
Parse a query string given as a string argument (data of type
|
||||||
|
:mimetype:`application/x-www-form-urlencoded`). Data are returned as a list of
|
||||||
|
name, value pairs.
|
||||||
|
|
||||||
|
The optional argument *keep_blank_values* is a flag indicating whether blank
|
||||||
|
values in URL encoded queries should be treated as blank strings. A true value
|
||||||
|
indicates that blanks should be retained as blank strings. The default false
|
||||||
|
value indicates that blank values are to be ignored and treated as if they were
|
||||||
|
not included.
|
||||||
|
|
||||||
|
The optional argument *strict_parsing* is a flag indicating what to do with
|
||||||
|
parsing errors. If false (the default), errors are silently ignored. If true,
|
||||||
|
errors raise a :exc:`ValueError` exception.
|
||||||
|
|
||||||
|
Use the :func:`urllib.parse.urlencode` function to convert such lists of pairs into
|
||||||
|
query strings.
|
||||||
|
|
||||||
|
|
||||||
.. function:: urlunparse(parts)
|
.. function:: urlunparse(parts)
|
||||||
|
|
||||||
Construct a URL from a tuple as returned by ``urlparse()``. The *parts*
|
Construct a URL from a tuple as returned by ``urlparse()``. The *parts*
|
||||||
@ -273,7 +314,7 @@ The :mod:`urllib.parse` module defines the following functions:
|
|||||||
of the sequence. When a sequence of two-element tuples is used as the *query*
|
of the sequence. When a sequence of two-element tuples is used as the *query*
|
||||||
argument, the first element of each tuple is a key and the second is a value.
|
argument, the first element of each tuple is a key and the second is a value.
|
||||||
The order of parameters in the encoded string will match the order of parameter
|
The order of parameters in the encoded string will match the order of parameter
|
||||||
tuples in the sequence. The :mod:`cgi` module provides the functions
|
tuples in the sequence. This module provides the functions
|
||||||
:func:`parse_qs` and :func:`parse_qsl` which are used to parse query strings
|
:func:`parse_qs` and :func:`parse_qsl` which are used to parse query strings
|
||||||
into Python data structures.
|
into Python data structures.
|
||||||
|
|
||||||
|
85
Lib/cgi.py
85
Lib/cgi.py
@ -37,6 +37,7 @@ import sys
|
|||||||
import os
|
import os
|
||||||
import urllib.parse
|
import urllib.parse
|
||||||
import email.parser
|
import email.parser
|
||||||
|
from warnings import warn
|
||||||
|
|
||||||
__all__ = ["MiniFieldStorage", "FieldStorage",
|
__all__ = ["MiniFieldStorage", "FieldStorage",
|
||||||
"parse", "parse_qs", "parse_qsl", "parse_multipart",
|
"parse", "parse_qs", "parse_qsl", "parse_multipart",
|
||||||
@ -153,75 +154,23 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
|
|||||||
else:
|
else:
|
||||||
qs = ""
|
qs = ""
|
||||||
environ['QUERY_STRING'] = qs # XXX Shouldn't, really
|
environ['QUERY_STRING'] = qs # XXX Shouldn't, really
|
||||||
return parse_qs(qs, keep_blank_values, strict_parsing)
|
return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing)
|
||||||
|
|
||||||
|
|
||||||
|
# parse query string function called from urlparse,
|
||||||
|
# this is done in order to maintain backward compatiblity.
|
||||||
|
|
||||||
def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
|
def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
|
||||||
"""Parse a query given as a string argument.
|
"""Parse a query given as a string argument."""
|
||||||
|
warn("cgi.parse_qs is deprecated, use urllib.parse.parse_qs instead",
|
||||||
Arguments:
|
DeprecationWarning)
|
||||||
|
return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing)
|
||||||
qs: URL-encoded query string to be parsed
|
|
||||||
|
|
||||||
keep_blank_values: flag indicating whether blank values in
|
|
||||||
URL encoded queries should be treated as blank strings.
|
|
||||||
A true value indicates that blanks should be retained as
|
|
||||||
blank strings. The default false value indicates that
|
|
||||||
blank values are to be ignored and treated as if they were
|
|
||||||
not included.
|
|
||||||
|
|
||||||
strict_parsing: flag indicating what to do with parsing errors.
|
|
||||||
If false (the default), errors are silently ignored.
|
|
||||||
If true, errors raise a ValueError exception.
|
|
||||||
"""
|
|
||||||
dict = {}
|
|
||||||
for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
|
|
||||||
if name in dict:
|
|
||||||
dict[name].append(value)
|
|
||||||
else:
|
|
||||||
dict[name] = [value]
|
|
||||||
return dict
|
|
||||||
|
|
||||||
def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
|
def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
|
||||||
"""Parse a query given as a string argument.
|
"""Parse a query given as a string argument."""
|
||||||
|
warn("cgi.parse_qsl is deprecated, use urllib.parse.parse_qs instead",
|
||||||
Arguments:
|
DeprecationWarning)
|
||||||
|
return urllib.parse.parse_qsl(qs, keep_blank_values, strict_parsing)
|
||||||
qs: URL-encoded query string to be parsed
|
|
||||||
|
|
||||||
keep_blank_values: flag indicating whether blank values in
|
|
||||||
URL encoded queries should be treated as blank strings. A
|
|
||||||
true value indicates that blanks should be retained as blank
|
|
||||||
strings. The default false value indicates that blank values
|
|
||||||
are to be ignored and treated as if they were not included.
|
|
||||||
|
|
||||||
strict_parsing: flag indicating what to do with parsing errors. If
|
|
||||||
false (the default), errors are silently ignored. If true,
|
|
||||||
errors raise a ValueError exception.
|
|
||||||
|
|
||||||
Returns a list, as G-d intended.
|
|
||||||
"""
|
|
||||||
pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
|
|
||||||
r = []
|
|
||||||
for name_value in pairs:
|
|
||||||
if not name_value and not strict_parsing:
|
|
||||||
continue
|
|
||||||
nv = name_value.split('=', 1)
|
|
||||||
if len(nv) != 2:
|
|
||||||
if strict_parsing:
|
|
||||||
raise ValueError("bad query field: %r" % (name_value,))
|
|
||||||
# Handle case of a control-name with no equal sign
|
|
||||||
if keep_blank_values:
|
|
||||||
nv.append('')
|
|
||||||
else:
|
|
||||||
continue
|
|
||||||
if len(nv[1]) or keep_blank_values:
|
|
||||||
name = urllib.parse.unquote(nv[0].replace('+', ' '))
|
|
||||||
value = urllib.parse.unquote(nv[1].replace('+', ' '))
|
|
||||||
r.append((name, value))
|
|
||||||
|
|
||||||
return r
|
|
||||||
|
|
||||||
|
|
||||||
def parse_multipart(fp, pdict):
|
def parse_multipart(fp, pdict):
|
||||||
"""Parse multipart input.
|
"""Parse multipart input.
|
||||||
@ -624,8 +573,8 @@ class FieldStorage:
|
|||||||
if self.qs_on_post:
|
if self.qs_on_post:
|
||||||
qs += '&' + self.qs_on_post
|
qs += '&' + self.qs_on_post
|
||||||
self.list = list = []
|
self.list = list = []
|
||||||
for key, value in parse_qsl(qs, self.keep_blank_values,
|
for key, value in urllib.parse.parse_qsl(qs, self.keep_blank_values,
|
||||||
self.strict_parsing):
|
self.strict_parsing):
|
||||||
list.append(MiniFieldStorage(key, value))
|
list.append(MiniFieldStorage(key, value))
|
||||||
self.skip_lines()
|
self.skip_lines()
|
||||||
|
|
||||||
@ -638,8 +587,8 @@ class FieldStorage:
|
|||||||
raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
|
raise ValueError('Invalid boundary in multipart form: %r' % (ib,))
|
||||||
self.list = []
|
self.list = []
|
||||||
if self.qs_on_post:
|
if self.qs_on_post:
|
||||||
for key, value in parse_qsl(self.qs_on_post, self.keep_blank_values,
|
for key, value in urllib.parse.parse_qsl(self.qs_on_post,
|
||||||
self.strict_parsing):
|
self.keep_blank_values, self.strict_parsing):
|
||||||
self.list.append(MiniFieldStorage(key, value))
|
self.list.append(MiniFieldStorage(key, value))
|
||||||
FieldStorageClass = None
|
FieldStorageClass = None
|
||||||
|
|
||||||
|
@ -53,25 +53,6 @@ def do_test(buf, method):
|
|||||||
except Exception as err:
|
except Exception as err:
|
||||||
return ComparableException(err)
|
return ComparableException(err)
|
||||||
|
|
||||||
# A list of test cases. Each test case is a a two-tuple that contains
|
|
||||||
# a string with the query and a dictionary with the expected result.
|
|
||||||
|
|
||||||
parse_qsl_test_cases = [
|
|
||||||
("", []),
|
|
||||||
("&", []),
|
|
||||||
("&&", []),
|
|
||||||
("=", [('', '')]),
|
|
||||||
("=a", [('', 'a')]),
|
|
||||||
("a", [('a', '')]),
|
|
||||||
("a=", [('a', '')]),
|
|
||||||
("a=", [('a', '')]),
|
|
||||||
("&a=b", [('a', 'b')]),
|
|
||||||
("a=a+b&b=b+c", [('a', 'a b'), ('b', 'b c')]),
|
|
||||||
("a=1&a=2", [('a', '1'), ('a', '2')]),
|
|
||||||
("a=%26&b=%3D", [('a', '&'), ('b', '=')]),
|
|
||||||
("a=%C3%BC&b=%CA%83", [('a', '\xfc'), ('b', '\u0283')]),
|
|
||||||
]
|
|
||||||
|
|
||||||
parse_strict_test_cases = [
|
parse_strict_test_cases = [
|
||||||
("", ValueError("bad query field: ''")),
|
("", ValueError("bad query field: ''")),
|
||||||
("&", ValueError("bad query field: ''")),
|
("&", ValueError("bad query field: ''")),
|
||||||
@ -141,11 +122,6 @@ def gen_result(data, environ):
|
|||||||
|
|
||||||
class CgiTests(unittest.TestCase):
|
class CgiTests(unittest.TestCase):
|
||||||
|
|
||||||
def test_qsl(self):
|
|
||||||
for orig, expect in parse_qsl_test_cases:
|
|
||||||
result = cgi.parse_qsl(orig, keep_blank_values=True)
|
|
||||||
self.assertEqual(result, expect, "Error parsing %s" % repr(orig))
|
|
||||||
|
|
||||||
def test_strict(self):
|
def test_strict(self):
|
||||||
for orig, expect in parse_strict_test_cases:
|
for orig, expect in parse_strict_test_cases:
|
||||||
# Test basic parsing
|
# Test basic parsing
|
||||||
|
@ -8,6 +8,23 @@ RFC1808_BASE = "http://a/b/c/d;p?q#f"
|
|||||||
RFC2396_BASE = "http://a/b/c/d;p?q"
|
RFC2396_BASE = "http://a/b/c/d;p?q"
|
||||||
RFC3986_BASE = "http://a/b/c/d;p?q"
|
RFC3986_BASE = "http://a/b/c/d;p?q"
|
||||||
|
|
||||||
|
# A list of test cases. Each test case is a a two-tuple that contains
|
||||||
|
# a string with the query and a dictionary with the expected result.
|
||||||
|
|
||||||
|
parse_qsl_test_cases = [
|
||||||
|
("", []),
|
||||||
|
("&", []),
|
||||||
|
("&&", []),
|
||||||
|
("=", [('', '')]),
|
||||||
|
("=a", [('', 'a')]),
|
||||||
|
("a", [('a', '')]),
|
||||||
|
("a=", [('a', '')]),
|
||||||
|
("a=", [('a', '')]),
|
||||||
|
("&a=b", [('a', 'b')]),
|
||||||
|
("a=a+b&b=b+c", [('a', 'a b'), ('b', 'b c')]),
|
||||||
|
("a=1&a=2", [('a', '1'), ('a', '2')]),
|
||||||
|
]
|
||||||
|
|
||||||
class UrlParseTestCase(unittest.TestCase):
|
class UrlParseTestCase(unittest.TestCase):
|
||||||
|
|
||||||
def checkRoundtrips(self, url, parsed, split):
|
def checkRoundtrips(self, url, parsed, split):
|
||||||
@ -61,6 +78,12 @@ class UrlParseTestCase(unittest.TestCase):
|
|||||||
self.assertEqual(result3.hostname, result.hostname)
|
self.assertEqual(result3.hostname, result.hostname)
|
||||||
self.assertEqual(result3.port, result.port)
|
self.assertEqual(result3.port, result.port)
|
||||||
|
|
||||||
|
def test_qsl(self):
|
||||||
|
for orig, expect in parse_qsl_test_cases:
|
||||||
|
result = urllib.parse.parse_qsl(orig, keep_blank_values=True)
|
||||||
|
self.assertEqual(result, expect, "Error parsing %s" % repr(orig))
|
||||||
|
|
||||||
|
|
||||||
def test_roundtrips(self):
|
def test_roundtrips(self):
|
||||||
testcases = [
|
testcases = [
|
||||||
('file:///tmp/junk.txt',
|
('file:///tmp/junk.txt',
|
||||||
|
@ -8,7 +8,7 @@ import sys
|
|||||||
import collections
|
import collections
|
||||||
|
|
||||||
__all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag",
|
__all__ = ["urlparse", "urlunparse", "urljoin", "urldefrag",
|
||||||
"urlsplit", "urlunsplit",
|
"urlsplit", "urlunsplit", "parse_qs", "parse_qsl",
|
||||||
"quote", "quote_plus", "quote_from_bytes",
|
"quote", "quote_plus", "quote_from_bytes",
|
||||||
"unquote", "unquote_plus", "unquote_to_bytes"]
|
"unquote", "unquote_plus", "unquote_to_bytes"]
|
||||||
|
|
||||||
@ -329,6 +329,72 @@ def unquote(string, encoding='utf-8', errors='replace'):
|
|||||||
res[-1] = b''.join(pct_sequence).decode(encoding, errors)
|
res[-1] = b''.join(pct_sequence).decode(encoding, errors)
|
||||||
return ''.join(res)
|
return ''.join(res)
|
||||||
|
|
||||||
|
def parse_qs(qs, keep_blank_values=0, strict_parsing=0):
|
||||||
|
"""Parse a query given as a string argument.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
qs: URL-encoded query string to be parsed
|
||||||
|
|
||||||
|
keep_blank_values: flag indicating whether blank values in
|
||||||
|
URL encoded queries should be treated as blank strings.
|
||||||
|
A true value indicates that blanks should be retained as
|
||||||
|
blank strings. The default false value indicates that
|
||||||
|
blank values are to be ignored and treated as if they were
|
||||||
|
not included.
|
||||||
|
|
||||||
|
strict_parsing: flag indicating what to do with parsing errors.
|
||||||
|
If false (the default), errors are silently ignored.
|
||||||
|
If true, errors raise a ValueError exception.
|
||||||
|
"""
|
||||||
|
dict = {}
|
||||||
|
for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
|
||||||
|
if name in dict:
|
||||||
|
dict[name].append(value)
|
||||||
|
else:
|
||||||
|
dict[name] = [value]
|
||||||
|
return dict
|
||||||
|
|
||||||
|
def parse_qsl(qs, keep_blank_values=0, strict_parsing=0):
|
||||||
|
"""Parse a query given as a string argument.
|
||||||
|
|
||||||
|
Arguments:
|
||||||
|
|
||||||
|
qs: URL-encoded query string to be parsed
|
||||||
|
|
||||||
|
keep_blank_values: flag indicating whether blank values in
|
||||||
|
URL encoded queries should be treated as blank strings. A
|
||||||
|
true value indicates that blanks should be retained as blank
|
||||||
|
strings. The default false value indicates that blank values
|
||||||
|
are to be ignored and treated as if they were not included.
|
||||||
|
|
||||||
|
strict_parsing: flag indicating what to do with parsing errors. If
|
||||||
|
false (the default), errors are silently ignored. If true,
|
||||||
|
errors raise a ValueError exception.
|
||||||
|
|
||||||
|
Returns a list, as G-d intended.
|
||||||
|
"""
|
||||||
|
pairs = [s2 for s1 in qs.split('&') for s2 in s1.split(';')]
|
||||||
|
r = []
|
||||||
|
for name_value in pairs:
|
||||||
|
if not name_value and not strict_parsing:
|
||||||
|
continue
|
||||||
|
nv = name_value.split('=', 1)
|
||||||
|
if len(nv) != 2:
|
||||||
|
if strict_parsing:
|
||||||
|
raise ValueError("bad query field: %r" % (name_value,))
|
||||||
|
# Handle case of a control-name with no equal sign
|
||||||
|
if keep_blank_values:
|
||||||
|
nv.append('')
|
||||||
|
else:
|
||||||
|
continue
|
||||||
|
if len(nv[1]) or keep_blank_values:
|
||||||
|
name = unquote(nv[0].replace('+', ' '))
|
||||||
|
value = unquote(nv[1].replace('+', ' '))
|
||||||
|
r.append((name, value))
|
||||||
|
|
||||||
|
return r
|
||||||
|
|
||||||
def unquote_plus(string, encoding='utf-8', errors='replace'):
|
def unquote_plus(string, encoding='utf-8', errors='replace'):
|
||||||
"""Like unquote(), but also replace plus signs by spaces, as required for
|
"""Like unquote(), but also replace plus signs by spaces, as required for
|
||||||
unquoting HTML form values.
|
unquoting HTML form values.
|
||||||
|
@ -73,6 +73,10 @@ C API
|
|||||||
Library
|
Library
|
||||||
-------
|
-------
|
||||||
|
|
||||||
|
- Issue 600362: Relocated parse_qs() and parse_qsl(), from the cgi module
|
||||||
|
to the urlparse one. Added a DeprecationWarning in the old module, it
|
||||||
|
will be deprecated in the future.
|
||||||
|
|
||||||
- The bsddb module has been removed.
|
- The bsddb module has been removed.
|
||||||
|
|
||||||
- Issue #3719: platform.architecture() fails if there are spaces in the
|
- Issue #3719: platform.architecture() fails if there are spaces in the
|
||||||
|
Loading…
Reference in New Issue
Block a user