Skip to content
This repository was archived by the owner on Feb 13, 2025. It is now read-only.

Commit 7f6d884

Browse files
author
Anselm Kruis
committed
Merge tag v3.6.13 into branch 3.6-slp.
2 parents adc3811 + aa73e17 commit 7f6d884

33 files changed

+735
-185
lines changed

.azure-pipelines/ci.yml

+3-2
Original file line numberDiff line numberDiff line change
@@ -30,14 +30,15 @@ jobs:
3030
- job: macOS_CI_Tests
3131
displayName: macOS CI Tests
3232
dependsOn: Prebuild
33-
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
33+
#condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
34+
# bpo-39837: macOS tests on Azure Pipelines are disabled
3435

3536
variables:
3637
testRunTitle: '$(build.sourceBranchName)-macos'
3738
testRunPlatform: macos
3839

3940
pool:
40-
vmImage: xcode9-macos10.13
41+
vmImage: macos-10.14
4142

4243
steps:
4344
- template: ./macos-steps.yml

.azure-pipelines/macos-steps.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -6,14 +6,16 @@ steps:
66
- script: ./configure --with-pydebug --with-openssl=/usr/local/opt/openssl --prefix=/opt/python-azdev
77
displayName: 'Configure CPython (debug)'
88

9-
- script: make -s -j4
9+
- script: make -j4
1010
displayName: 'Build CPython'
1111

1212
- script: make pythoninfo
1313
displayName: 'Display build info'
1414

1515
- script: make buildbottest TESTOPTS="-j4 -uall,-cpu --junit-xml=$(build.binariesDirectory)/test-results.xml"
1616
displayName: 'Tests'
17+
continueOnError: true
18+
timeoutInMinutes: 30
1719

1820
- task: PublishTestResults@2
1921
displayName: 'Publish Test Results'

.azure-pipelines/pr.yml

+3-1
Original file line numberDiff line numberDiff line change
@@ -25,13 +25,15 @@ jobs:
2525
displayName: macOS PR Tests
2626
dependsOn: Prebuild
2727
condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
28+
#condition: and(succeeded(), eq(dependencies.Prebuild.outputs['tests.run'], 'true'))
29+
# bpo-39837: macOS tests on Azure Pipelines are disabled
2830

2931
variables:
3032
testRunTitle: '$(system.pullRequest.TargetBranch)-macos'
3133
testRunPlatform: macos
3234

3335
pool:
34-
vmImage: xcode9-macos10.13
36+
vmImage: macos-10.14
3537

3638
steps:
3739
- template: ./macos-steps.yml

Doc/copyright.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ Copyright
44

55
Python and this documentation is:
66

7-
Copyright © 2001-2020 Python Software Foundation. All rights reserved.
7+
Copyright © 2001-2021 Python Software Foundation. All rights reserved.
88

99
Copyright © 2000 BeOpen.com. All rights reserved.
1010

Doc/library/cgi.rst

+5-3
Original file line numberDiff line numberDiff line change
@@ -277,13 +277,12 @@ These are useful if you want more control, or if you want to employ some of the
277277
algorithms implemented in this module in other circumstances.
278278

279279

280-
.. function:: parse(fp=None, environ=os.environ, keep_blank_values=False, strict_parsing=False)
280+
.. function:: parse(fp=None, environ=os.environ, keep_blank_values=False, strict_parsing=False, separator="&")
281281

282282
Parse a query in the environment or from a file (the file defaults to
283-
``sys.stdin``). The *keep_blank_values* and *strict_parsing* parameters are
283+
``sys.stdin``). The *keep_blank_values*, *strict_parsing* and *separator* parameters are
284284
passed to :func:`urllib.parse.parse_qs` unchanged.
285285

286-
287286
.. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False)
288287

289288
This function is deprecated in this module. Use :func:`urllib.parse.parse_qs`
@@ -308,6 +307,9 @@ algorithms implemented in this module in other circumstances.
308307
Note that this does not parse nested multipart parts --- use
309308
:class:`FieldStorage` for that.
310309

310+
.. versionchanged:: 3.6.13
311+
Added the *separator* parameter.
312+
311313

312314
.. function:: parse_header(string)
313315

Doc/library/urllib.parse.rst

+20-2
Original file line numberDiff line numberDiff line change
@@ -143,7 +143,7 @@ or on combining URL components into a URL string.
143143
now raise :exc:`ValueError`.
144144

145145

146-
.. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None)
146+
.. function:: parse_qs(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')
147147

148148
Parse a query string given as a string argument (data of type
149149
:mimetype:`application/x-www-form-urlencoded`). Data are returned as a
@@ -168,6 +168,9 @@ or on combining URL components into a URL string.
168168
read. If set, then throws a :exc:`ValueError` if there are more than
169169
*max_num_fields* fields read.
170170

171+
The optional argument *separator* is the symbol to use for separating the
172+
query arguments. It defaults to ``&``.
173+
171174
Use the :func:`urllib.parse.urlencode` function (with the ``doseq``
172175
parameter set to ``True``) to convert such dictionaries into query
173176
strings.
@@ -179,8 +182,14 @@ or on combining URL components into a URL string.
179182
.. versionchanged:: 3.6.8
180183
Added *max_num_fields* parameter.
181184

185+
.. versionchanged:: 3.6.13
186+
Added *separator* parameter with the default value of ``&``. Python
187+
versions earlier than Python 3.6.13 allowed using both ``;`` and ``&`` as
188+
query parameter separator. This has been changed to allow only a single
189+
separator key, with ``&`` as the default separator.
190+
182191

183-
.. function:: parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None)
192+
.. function:: parse_qsl(qs, keep_blank_values=False, strict_parsing=False, encoding='utf-8', errors='replace', max_num_fields=None, separator='&')
184193

185194
Parse a query string given as a string argument (data of type
186195
:mimetype:`application/x-www-form-urlencoded`). Data are returned as a list of
@@ -204,6 +213,9 @@ or on combining URL components into a URL string.
204213
read. If set, then throws a :exc:`ValueError` if there are more than
205214
*max_num_fields* fields read.
206215

216+
The optional argument *separator* is the symbol to use for separating the
217+
query arguments. It defaults to ``&``.
218+
207219
Use the :func:`urllib.parse.urlencode` function to convert such lists of pairs into
208220
query strings.
209221

@@ -213,6 +225,12 @@ or on combining URL components into a URL string.
213225
.. versionchanged:: 3.6.8
214226
Added *max_num_fields* parameter.
215227

228+
.. versionchanged:: 3.6.13
229+
Added *separator* parameter with the default value of ``&``. Python
230+
versions earlier than Python 3.6.13 allowed using both ``;`` and ``&`` as
231+
query parameter separator. This has been changed to allow only a single
232+
separator key, with ``&`` as the default separator.
233+
216234

217235
.. function:: urlunparse(parts)
218236

Doc/license.rst

+1-1
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ PSF LICENSE AGREEMENT FOR PYTHON |release|
8787
analyze, test, perform and/or display publicly, prepare derivative works,
8888
distribute, and otherwise use Python |release| alone or in any derivative
8989
version, provided, however, that PSF's License Agreement and PSF's notice of
90-
copyright, i.e., "Copyright © 2001-2020 Python Software Foundation; All Rights
90+
copyright, i.e., "Copyright © 2001-2021 Python Software Foundation; All Rights
9191
Reserved" are retained in Python |release| alone or in any derivative version
9292
prepared by Licensee.
9393

Doc/tools/static/switchers.js

-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,6 @@
1515
'3.8': '3.8',
1616
'3.7': '3.7',
1717
'3.6': '3.6',
18-
'3.5': '3.5',
1918
'2.7': '2.7',
2019
};
2120

Doc/tools/templates/indexsidebar.html

-1
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ <h3>{% trans %}Docs by version{% endtrans %}</h3>
77
<li><a href="https://docs.python.org/3.8/">{% trans %}Python 3.8 (stable){% endtrans %}</a></li>
88
<li><a href="https://docs.python.org/3.7/">{% trans %}Python 3.7 (stable){% endtrans %}</a></li>
99
<li><a href="https://docs.python.org/3.6/">{% trans %}Python 3.6 (security-fixes){% endtrans %}</a></li>
10-
<li><a href="https://docs.python.org/3.5/">{% trans %}Python 3.5 (security-fixes){% endtrans %}</a></li>
1110
<li><a href="https://docs.python.org/2.7/">{% trans %}Python 2.7 (EOL){% endtrans %}</a></li>
1211
<li><a href="https://www.python.org/doc/versions/">{% trans %}All versions{% endtrans %}</a></li>
1312
</ul>

Doc/whatsnew/3.6.rst

+13
Original file line numberDiff line numberDiff line change
@@ -2459,3 +2459,16 @@ because of the behavior of the socket option ``SO_REUSEADDR`` in UDP. For more
24592459
details, see the documentation for ``loop.create_datagram_endpoint()``.
24602460
(Contributed by Kyle Stanley, Antoine Pitrou, and Yury Selivanov in
24612461
:issue:`37228`.)
2462+
2463+
Notable changes in Python 3.6.13
2464+
================================
2465+
2466+
Earlier Python versions allowed using both ``;`` and ``&`` as
2467+
query parameter separators in :func:`urllib.parse.parse_qs` and
2468+
:func:`urllib.parse.parse_qsl`. Due to security concerns, and to conform with
2469+
newer W3C recommendations, this has been changed to allow only a single
2470+
separator key, with ``&`` as the default. This change also affects
2471+
:func:`cgi.parse` and :func:`cgi.parse_multipart` as they use the affected
2472+
functions internally. For more details, please see their respective
2473+
documentation.
2474+
(Contributed by Adam Goldschmidt, Senthil Kumaran and Ken Jin in :issue:`42967`.)

Include/patchlevel.h

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@
1818
/*--start constants--*/
1919
#define PY_MAJOR_VERSION 3
2020
#define PY_MINOR_VERSION 6
21-
#define PY_MICRO_VERSION 12
21+
#define PY_MICRO_VERSION 13
2222
#define PY_RELEASE_LEVEL PY_RELEASE_LEVEL_FINAL
2323
#define PY_RELEASE_SERIAL 0
2424

2525
/* Version as a string */
26-
#define PY_VERSION "3.6.12"
26+
#define PY_VERSION "3.6.13"
2727
/*--end constants--*/
2828

2929
/* Version as a single 4-byte hex number, e.g. 0x010502B2 == 1.5.2b2.

LICENSE

+1-1
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ analyze, test, perform and/or display publicly, prepare derivative works,
7373
distribute, and otherwise use Python alone or in any derivative version,
7474
provided, however, that PSF's License Agreement and PSF's notice of copyright,
7575
i.e., "Copyright (c) 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
76-
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020 Python Software Foundation;
76+
2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018, 2019, 2020, 2021 Python Software Foundation;
7777
All Rights Reserved" are retained in Python alone or in any derivative version
7878
prepared by Licensee.
7979

Lib/cgi.py

+11-6
Original file line numberDiff line numberDiff line change
@@ -117,7 +117,8 @@ def closelog():
117117
# 0 ==> unlimited input
118118
maxlen = 0
119119

120-
def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
120+
def parse(fp=None, environ=os.environ, keep_blank_values=0,
121+
strict_parsing=0, separator='&'):
121122
"""Parse a query in the environment or from a file (default stdin)
122123
123124
Arguments, all optional:
@@ -136,6 +137,9 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
136137
strict_parsing: flag indicating what to do with parsing errors.
137138
If false (the default), errors are silently ignored.
138139
If true, errors raise a ValueError exception.
140+
141+
separator: str. The symbol to use for separating the query arguments.
142+
Defaults to &.
139143
"""
140144
if fp is None:
141145
fp = sys.stdin
@@ -180,7 +184,7 @@ def parse(fp=None, environ=os.environ, keep_blank_values=0, strict_parsing=0):
180184
qs = ""
181185
environ['QUERY_STRING'] = qs # XXX Shouldn't, really
182186
return urllib.parse.parse_qs(qs, keep_blank_values, strict_parsing,
183-
encoding=encoding)
187+
encoding=encoding, separator=separator)
184188

185189

186190
# parse query string function called from urlparse,
@@ -405,7 +409,7 @@ class FieldStorage:
405409
def __init__(self, fp=None, headers=None, outerboundary=b'',
406410
environ=os.environ, keep_blank_values=0, strict_parsing=0,
407411
limit=None, encoding='utf-8', errors='replace',
408-
max_num_fields=None):
412+
max_num_fields=None, separator='&'):
409413
"""Constructor. Read multipart/* until last part.
410414
411415
Arguments, all optional:
@@ -453,6 +457,7 @@ def __init__(self, fp=None, headers=None, outerboundary=b'',
453457
self.keep_blank_values = keep_blank_values
454458
self.strict_parsing = strict_parsing
455459
self.max_num_fields = max_num_fields
460+
self.separator = separator
456461
if 'REQUEST_METHOD' in environ:
457462
method = environ['REQUEST_METHOD'].upper()
458463
self.qs_on_post = None
@@ -678,7 +683,7 @@ def read_urlencoded(self):
678683
query = urllib.parse.parse_qsl(
679684
qs, self.keep_blank_values, self.strict_parsing,
680685
encoding=self.encoding, errors=self.errors,
681-
max_num_fields=self.max_num_fields)
686+
max_num_fields=self.max_num_fields, separator=self.separator)
682687
self.list = [MiniFieldStorage(key, value) for key, value in query]
683688
self.skip_lines()
684689

@@ -694,7 +699,7 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
694699
query = urllib.parse.parse_qsl(
695700
self.qs_on_post, self.keep_blank_values, self.strict_parsing,
696701
encoding=self.encoding, errors=self.errors,
697-
max_num_fields=self.max_num_fields)
702+
max_num_fields=self.max_num_fields, separator=self.separator)
698703
self.list.extend(MiniFieldStorage(key, value) for key, value in query)
699704

700705
klass = self.FieldStorageClass or self.__class__
@@ -736,7 +741,7 @@ def read_multi(self, environ, keep_blank_values, strict_parsing):
736741

737742
part = klass(self.fp, headers, ib, environ, keep_blank_values,
738743
strict_parsing,self.limit-self.bytes_read,
739-
self.encoding, self.errors, max_num_fields)
744+
self.encoding, self.errors, max_num_fields, self.separator)
740745

741746
if max_num_fields is not None:
742747
max_num_fields -= 1

Lib/ctypes/test/test_parameters.py

+43
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,49 @@ def __dict__(self):
201201
with self.assertRaises(ZeroDivisionError):
202202
WorseStruct().__setstate__({}, b'foo')
203203

204+
def test_parameter_repr(self):
205+
from ctypes import (
206+
c_bool,
207+
c_char,
208+
c_wchar,
209+
c_byte,
210+
c_ubyte,
211+
c_short,
212+
c_ushort,
213+
c_int,
214+
c_uint,
215+
c_long,
216+
c_ulong,
217+
c_longlong,
218+
c_ulonglong,
219+
c_float,
220+
c_double,
221+
c_longdouble,
222+
c_char_p,
223+
c_wchar_p,
224+
c_void_p,
225+
)
226+
self.assertRegex(repr(c_bool.from_param(True)), r"^<cparam '\?' at 0x[A-Fa-f0-9]+>$")
227+
self.assertEqual(repr(c_char.from_param(97)), "<cparam 'c' ('a')>")
228+
self.assertRegex(repr(c_wchar.from_param('a')), r"^<cparam 'u' at 0x[A-Fa-f0-9]+>$")
229+
self.assertEqual(repr(c_byte.from_param(98)), "<cparam 'b' (98)>")
230+
self.assertEqual(repr(c_ubyte.from_param(98)), "<cparam 'B' (98)>")
231+
self.assertEqual(repr(c_short.from_param(511)), "<cparam 'h' (511)>")
232+
self.assertEqual(repr(c_ushort.from_param(511)), "<cparam 'H' (511)>")
233+
self.assertRegex(repr(c_int.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
234+
self.assertRegex(repr(c_uint.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
235+
self.assertRegex(repr(c_long.from_param(20000)), r"^<cparam '[li]' \(20000\)>$")
236+
self.assertRegex(repr(c_ulong.from_param(20000)), r"^<cparam '[LI]' \(20000\)>$")
237+
self.assertRegex(repr(c_longlong.from_param(20000)), r"^<cparam '[liq]' \(20000\)>$")
238+
self.assertRegex(repr(c_ulonglong.from_param(20000)), r"^<cparam '[LIQ]' \(20000\)>$")
239+
self.assertEqual(repr(c_float.from_param(1.5)), "<cparam 'f' (1.5)>")
240+
self.assertEqual(repr(c_double.from_param(1.5)), "<cparam 'd' (1.5)>")
241+
self.assertEqual(repr(c_double.from_param(1e300)), "<cparam 'd' (1e+300)>")
242+
self.assertRegex(repr(c_longdouble.from_param(1.5)), r"^<cparam ('d' \(1.5\)|'g' at 0x[A-Fa-f0-9]+)>$")
243+
self.assertRegex(repr(c_char_p.from_param(b'hihi')), "^<cparam 'z' \(0x[A-Fa-f0-9]+\)>$")
244+
self.assertRegex(repr(c_wchar_p.from_param('hihi')), "^<cparam 'Z' \(0x[A-Fa-f0-9]+\)>$")
245+
self.assertRegex(repr(c_void_p.from_param(0x12)), r"^<cparam 'P' \(0x0*12\)>$")
246+
204247
################################################################
205248

206249
if __name__ == '__main__':

0 commit comments

Comments
 (0)