Python-checkins
Threads by month
- ----- 2025 -----
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
October 2017
- 3 participants
- 331 discussions
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
bpo-31507 Add docstring to parseaddr function in email.utils.parseaddr (GH-3647) (GH-3733)
by Mariatta Oct. 7, 2017
by Mariatta Oct. 7, 2017
Oct. 7, 2017
https://github.com/python/cpython/commit/93c0885dc84381cbbb970402b1a21bf690…
commit: 93c0885dc84381cbbb970402b1a21bf690ee312c
branch: 3.6
author: Rohit Balasubramanian <brohit23(a)outlook.com>
committer: Mariatta <Mariatta(a)users.noreply.github.com>
date: 2017-10-06T22:27:36-07:00
summary:
bpo-31507 Add docstring to parseaddr function in email.utils.parseaddr (GH-3647) (GH-3733)
(cherry picked from commit 9e7b9b21fe45f7d93eaf9382fedfa18247d0d2b2)
files:
M Lib/email/utils.py
diff --git a/Lib/email/utils.py b/Lib/email/utils.py
index a759d23308d..e2bfb362c6e 100644
--- a/Lib/email/utils.py
+++ b/Lib/email/utils.py
@@ -215,6 +215,12 @@ def parsedate_to_datetime(data):
def parseaddr(addr):
+ """
+ Parse addr into its constituent realname and email address parts.
+
+ Return a tuple of realname and email address, unless the parse fails, in
+ which case return a 2-tuple of ('', '').
+ """
addrs = _AddressList(addr).addresslist
if not addrs:
return '', ''
1
0
![](https://secure.gravatar.com/avatar/628f74ad69d6dcc809f7cfa1417733a9.jpg?s=120&d=mm&r=g)
[6 up, 59 flat] Results for Python (master branch) 2017-10-06
by lp_benchmark_robot@intel.com Oct. 6, 2017
by lp_benchmark_robot@intel.com Oct. 6, 2017
Oct. 6, 2017
Results for project python/master, build date: 2017-10-06 03:02:52-07:00.
- commit: b8ab9d3
- previous commit: c1c47c1
- revision date: 2017-10-06 02:58:28-04:00
- environment: Broadwell-EP
- cpu: Intel(R) Xeon(R) CPU E5-2699 v4 @ 2.20GHz 2x22 cores,
stepping 1, LLC 55 MB
- mem: 128 GB
- os: Ubuntu 16.04.2 LTS
- kernel: 4.4.0-62-generic x86_64 GNU/Linux
Baseline results were generated using release v3.6.0, with hash 5c4568a from
2016-12-22 23:38:47+00:00.
+-----+------------------------+--------+------------+------------+------------+
| | |relative|change since|change since|current rev |
| | benchmark|std_dev*| last run | baseline |run with PGO|
+-----+------------------------+--------+------------+------------+------------+
| :-| | 2to3| 1.070% | -0.052% | +4.100% | +9.410% |
+-----+------------------------+--------+------------+------------+------------+
| :-) | call_method| 0.539% | +3.797% | +19.675% | +12.525% |
+-----+------------------------+--------+------------+------------+------------+
| :-) | call_method_slots| 0.396% | +3.016% | +20.655% | +12.388% |
+-----+------------------------+--------+------------+------------+------------+
| :-) | call_method_unknown| 0.661% | +3.743% | +19.983% | +11.322% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | call_simple| 2.944% | +2.624% | +6.249% | +10.349% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | chameleon| 1.695% | +0.407% | +10.765% | +10.875% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | chaos| 0.561% | -1.263% | +5.829% | +12.846% |
+-----+------------------------+--------+------------+------------+------------+
| :-) | crypto_pyaes| 0.636% | +3.160% | +3.888% | +4.756% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | deltablue| 3.270% | -0.814% | +7.244% | +19.716% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | django_template| 3.210% | +1.167% | +9.216% | +14.773% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | dulwich_log| 1.209% | -0.439% | +4.355% | +5.910% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | fannkuch| 0.252% | -0.267% | +5.604% | +4.467% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | float| 0.882% | -1.879% | +0.786% | +9.095% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | genshi_text| 1.171% | -0.803% | +7.908% | +12.504% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | genshi_xml| 1.507% | -1.695% | +6.762% | +10.870% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | go| 0.795% | -0.615% | +5.474% | +13.396% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | hexiom| 0.819% | -0.854% | +8.327% | +13.025% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | html5lib| 2.689% | -1.016% | +8.288% | +10.808% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | json_dumps| 1.362% | -1.178% | +3.619% | +8.942% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | json_loads| 0.913% | +4.282% | +1.109% | +11.593% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | logging_format| 1.512% | -1.558% | +7.205% | +12.903% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | logging_silent| 2.380% | -0.853% | +46.281% | +12.489% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | logging_simple| 1.586% | -0.286% | +8.407% | +13.714% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | mako| 0.528% | +1.359% | +18.539% | +10.844% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | mdp| 1.978% | +0.789% | +8.572% | +8.994% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | meteor_contest| 1.924% | -1.189% | +2.988% | +5.578% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | nbody| 0.320% | -1.601% | -2.347% | +2.351% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | nqueens| 0.910% | -0.299% | +2.002% | +8.420% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pathlib| 1.001% | -2.555% | +4.915% | +9.296% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle| 1.463% | +2.116% | +1.505% | +18.668% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle_dict| 0.317% | +0.888% | +3.156% | +20.557% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle_list| 0.872% | +1.058% | +6.508% | +15.761% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pickle_pure_python| 4.333% | -0.568% | +11.191% | +11.041% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | pidigits| 0.076% | +0.073% | +0.448% | +9.285% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | python_startup| 0.130% | -0.202% | +10.725% | +5.401% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | python_startup_no_site| 0.088% | +0.184% | +2.244% | +5.321% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | raytrace| 1.180% | -0.697% | +8.383% | +14.752% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | regex_compile| 5.317% | -2.767% | +1.136% | +14.241% |
+-----+------------------------+--------+------------+------------+------------+
| :-) | regex_dna| 1.114% | +3.562% | +1.933% | +6.852% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | regex_effbot| 1.161% | +2.231% | -0.031% | -2.621% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | regex_v8| 2.823% | -0.010% | +9.782% | +3.445% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | richards| 1.453% | -0.479% | +6.794% | +15.949% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_fft| 0.501% | +1.279% | +1.402% | +2.874% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_lu| 1.124% | -0.459% | +26.561% | +9.024% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_monte_carlo| 1.745% | -2.285% | +2.238% | +9.671% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_sor| 0.412% | -0.538% | +14.019% | +10.414% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | scimark_sparse_mat_mult| 1.024% | -1.857% | +0.374% | +1.221% |
+-----+------------------------+--------+------------+------------+------------+
| :-) | spectral_norm| 0.374% | +3.114% | +6.620% | +1.087% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sqlalchemy_declarative| 1.131% | +0.300% | +6.769% | +7.670% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sqlalchemy_imperative| 2.914% | +0.932% | +6.818% | +4.035% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sqlite_synth| 5.549% | +0.325% | +20.393% | +6.295% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_expand| 2.525% | +0.531% | +11.678% | +9.709% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_integrate| 2.363% | -0.543% | +9.171% | +7.929% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_str| 4.542% | +0.075% | +10.710% | +10.745% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | sympy_sum| 5.347% | -0.409% | +11.393% | +12.279% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | telco| 5.649% | +1.203% | +23.199% | +8.933% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | tornado_http| 1.017% | -1.338% | +5.065% | +7.415% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | unpack_sequence| 1.065% | +0.122% | +2.236% | +2.985% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | unpickle| 6.288% | -0.572% | +8.203% | +20.544% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | unpickle_list| 0.570% | +2.974% | +0.218% | +16.969% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | unpickle_pure_python| 1.224% | -0.585% | +7.315% | +7.303% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_generate| 1.174% | +0.134% | +6.495% | +7.024% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_iterparse| 2.846% | -0.818% | +1.106% | +7.157% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_parse| 3.794% | -0.848% | -7.439% | +10.921% |
+-----+------------------------+--------+------------+------------+------------+
| :-| | xml_etree_process| 1.569% | -1.480% | +5.689% | +8.213% |
+-----+------------------------+--------+------------+------------+------------+
* Relative Standard Deviation (Standard Deviation/Average)
If this is not displayed properly please visit our results page here:
http://languagesperformance.intel.com/6-up-59-flat-results-for-python-maste…
Our lab does a nightly source pull and build of the Python project and measures
performance changes against the previous stable version and the previous nightly
measurement. This is provided as a service to the community so that quality
issues with current hardware can be identified quickly.
Intel technologies' features and benefits depend on system configuration and may
require enabled hardware, software or service activation. Performance varies
depending on system configuration.
1
0
https://github.com/python/cpython/commit/02e82a0596121e7b6fcd1142b60c744e8e…
commit: 02e82a0596121e7b6fcd1142b60c744e8e254d41
branch: master
author: Yury Selivanov <yury(a)magic.io>
committer: GitHub <noreply(a)github.com>
date: 2017-10-06T10:18:10-04:00
summary:
bpo-31709: Update importlib magic (#3906)
files:
M Doc/library/dis.rst
M Lib/importlib/_bootstrap_external.py
M Python/importlib_external.h
diff --git a/Doc/library/dis.rst b/Doc/library/dis.rst
index 7b7c84df776..4d011036d7a 100644
--- a/Doc/library/dis.rst
+++ b/Doc/library/dis.rst
@@ -558,8 +558,11 @@ the original TOS1.
.. opcode:: GET_AITER
- Implements ``TOS = get_awaitable(TOS.__aiter__())``. See ``GET_AWAITABLE``
- for details about ``get_awaitable``
+ Implements ``TOS = TOS.__aiter__()``.
+
+ .. versionchanged:: 3.7
+ Returning awaitable objects from ``__aiter__`` is no longer
+ supported.
.. opcode:: GET_ANEXT
diff --git a/Lib/importlib/_bootstrap_external.py b/Lib/importlib/_bootstrap_external.py
index e9f870bf7f4..41de8a7b863 100644
--- a/Lib/importlib/_bootstrap_external.py
+++ b/Lib/importlib/_bootstrap_external.py
@@ -241,6 +241,7 @@ def _write_atomic(path, data, mode=0o666):
# Python 3.6b2 3378 (add BUILD_TUPLE_UNPACK_WITH_CALL #28257)
# Python 3.6rc1 3379 (more thorough __class__ validation #23722)
# Python 3.7a0 3390 (add LOAD_METHOD and CALL_METHOD opcodes)
+# Python 3.7a0 3391 (update GET_AITER #31709)
#
# MAGIC must change whenever the bytecode emitted by the compiler may no
# longer be understood by older implementations of the eval loop (usually
@@ -249,7 +250,7 @@ def _write_atomic(path, data, mode=0o666):
# Whenever MAGIC_NUMBER is changed, the ranges in the magic_values array
# in PC/launcher.c must also be updated.
-MAGIC_NUMBER = (3390).to_bytes(2, 'little') + b'\r\n'
+MAGIC_NUMBER = (3391).to_bytes(2, 'little') + b'\r\n'
_RAW_MAGIC_NUMBER = int.from_bytes(MAGIC_NUMBER, 'little') # For import.c
_PYCACHE = '__pycache__'
diff --git a/Python/importlib_external.h b/Python/importlib_external.h
index 83fe39c0762..f122f14f542 100644
--- a/Python/importlib_external.h
+++ b/Python/importlib_external.h
@@ -242,7 +242,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,95,97,116,111,109,105,99,106,0,0,0,115,26,0,0,
0,0,5,16,1,6,1,26,1,2,3,14,1,20,1,16,
1,14,1,2,1,14,1,14,1,6,1,114,58,0,0,0,
- 105,62,13,0,0,233,2,0,0,0,114,15,0,0,0,115,
+ 105,63,13,0,0,233,2,0,0,0,114,15,0,0,0,115,
2,0,0,0,13,10,90,11,95,95,112,121,99,97,99,104,
101,95,95,122,4,111,112,116,45,122,3,46,112,121,122,4,
46,112,121,99,78,41,1,218,12,111,112,116,105,109,105,122,
@@ -346,7 +346,7 @@ const unsigned char _Py_M__importlib_external[] = {
103,90,15,97,108,109,111,115,116,95,102,105,108,101,110,97,
109,101,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,218,17,99,97,99,104,101,95,102,114,111,109,95,115,111,
- 117,114,99,101,8,1,0,0,115,48,0,0,0,0,18,8,
+ 117,114,99,101,9,1,0,0,115,48,0,0,0,0,18,8,
1,6,1,6,1,8,1,4,1,8,1,12,1,10,1,12,
1,16,1,8,1,8,1,8,1,24,1,8,1,12,1,6,
2,8,1,8,1,8,1,8,1,14,1,14,1,114,83,0,
@@ -420,7 +420,7 @@ const unsigned char _Py_M__importlib_external[] = {
112,116,95,108,101,118,101,108,90,13,98,97,115,101,95,102,
105,108,101,110,97,109,101,114,4,0,0,0,114,4,0,0,
0,114,6,0,0,0,218,17,115,111,117,114,99,101,95,102,
- 114,111,109,95,99,97,99,104,101,53,1,0,0,115,46,0,
+ 114,111,109,95,99,97,99,104,101,54,1,0,0,115,46,0,
0,0,0,9,12,1,8,1,10,1,12,1,12,1,8,1,
6,1,10,1,10,1,8,1,6,1,10,1,8,1,16,1,
10,1,6,1,8,1,16,1,8,1,6,1,8,1,14,1,
@@ -455,7 +455,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,38,0,0,0,90,9,101,120,116,101,110,115,105,
111,110,218,11,115,111,117,114,99,101,95,112,97,116,104,114,
4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,15,
- 95,103,101,116,95,115,111,117,114,99,101,102,105,108,101,87,
+ 95,103,101,116,95,115,111,117,114,99,101,102,105,108,101,88,
1,0,0,115,20,0,0,0,0,7,12,1,4,1,16,1,
24,1,4,1,2,1,12,1,18,1,18,1,114,95,0,0,
0,99,1,0,0,0,0,0,0,0,1,0,0,0,11,0,
@@ -469,7 +469,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,70,0,0,0,114,78,0,0,0,41,1,218,
8,102,105,108,101,110,97,109,101,114,4,0,0,0,114,4,
0,0,0,114,6,0,0,0,218,11,95,103,101,116,95,99,
- 97,99,104,101,100,106,1,0,0,115,16,0,0,0,0,1,
+ 97,99,104,101,100,107,1,0,0,115,16,0,0,0,0,1,
14,1,2,1,8,1,14,1,8,1,14,1,4,2,114,99,
0,0,0,99,1,0,0,0,0,0,0,0,2,0,0,0,
11,0,0,0,67,0,0,0,115,52,0,0,0,121,14,116,
@@ -483,7 +483,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,41,3,114,41,0,0,0,114,43,0,0,0,114,42,
0,0,0,41,2,114,37,0,0,0,114,44,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,10,
- 95,99,97,108,99,95,109,111,100,101,118,1,0,0,115,12,
+ 95,99,97,108,99,95,109,111,100,101,119,1,0,0,115,12,
0,0,0,0,2,2,1,14,1,14,1,10,3,8,1,114,
101,0,0,0,99,1,0,0,0,0,0,0,0,3,0,0,
0,11,0,0,0,3,0,0,0,115,68,0,0,0,100,6,
@@ -521,7 +521,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,90,6,107,119,97,114,103,115,41,1,218,6,109,101,116,
104,111,100,114,4,0,0,0,114,6,0,0,0,218,19,95,
99,104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,
- 101,114,138,1,0,0,115,12,0,0,0,0,1,8,1,8,
+ 101,114,139,1,0,0,115,12,0,0,0,0,1,8,1,8,
1,10,1,4,1,18,1,122,40,95,99,104,101,99,107,95,
110,97,109,101,46,60,108,111,99,97,108,115,62,46,95,99,
104,101,99,107,95,110,97,109,101,95,119,114,97,112,112,101,
@@ -540,7 +540,7 @@ const unsigned char _Py_M__importlib_external[] = {
99,116,95,95,218,6,117,112,100,97,116,101,41,3,90,3,
110,101,119,90,3,111,108,100,114,55,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,218,5,95,119,
- 114,97,112,149,1,0,0,115,8,0,0,0,0,1,10,1,
+ 114,97,112,150,1,0,0,115,8,0,0,0,0,1,10,1,
10,1,22,1,122,26,95,99,104,101,99,107,95,110,97,109,
101,46,60,108,111,99,97,108,115,62,46,95,119,114,97,112,
41,1,78,41,3,218,10,95,98,111,111,116,115,116,114,97,
@@ -548,7 +548,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,41,3,114,106,0,0,0,114,107,0,0,0,114,117,0,
0,0,114,4,0,0,0,41,1,114,106,0,0,0,114,6,
0,0,0,218,11,95,99,104,101,99,107,95,110,97,109,101,
- 130,1,0,0,115,14,0,0,0,0,8,14,7,2,1,10,
+ 131,1,0,0,115,14,0,0,0,0,8,14,7,2,1,10,
1,14,2,14,5,10,1,114,120,0,0,0,99,2,0,0,
0,0,0,0,0,5,0,0,0,6,0,0,0,67,0,0,
0,115,60,0,0,0,124,0,160,0,124,1,161,1,92,2,
@@ -576,7 +576,7 @@ const unsigned char _Py_M__importlib_external[] = {
218,8,112,111,114,116,105,111,110,115,218,3,109,115,103,114,
4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,17,
95,102,105,110,100,95,109,111,100,117,108,101,95,115,104,105,
- 109,158,1,0,0,115,10,0,0,0,0,10,14,1,16,1,
+ 109,159,1,0,0,115,10,0,0,0,0,10,14,1,16,1,
4,1,22,1,114,127,0,0,0,99,4,0,0,0,0,0,
0,0,11,0,0,0,20,0,0,0,67,0,0,0,115,136,
1,0,0,105,0,125,4,124,2,100,1,107,9,114,22,124,
@@ -656,7 +656,7 @@ const unsigned char _Py_M__importlib_external[] = {
117,114,99,101,95,115,105,122,101,114,4,0,0,0,114,4,
0,0,0,114,6,0,0,0,218,25,95,118,97,108,105,100,
97,116,101,95,98,121,116,101,99,111,100,101,95,104,101,97,
- 100,101,114,175,1,0,0,115,76,0,0,0,0,11,4,1,
+ 100,101,114,176,1,0,0,115,76,0,0,0,0,11,4,1,
8,1,10,3,4,1,8,1,8,1,12,1,12,1,12,1,
8,1,12,1,12,1,14,1,12,1,10,1,12,1,10,1,
12,1,10,1,12,1,8,1,10,1,2,1,16,1,16,1,
@@ -685,7 +685,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,114,102,0,0,0,114,93,0,0,0,114,94,0,0,0,
218,4,99,111,100,101,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,218,17,95,99,111,109,112,105,108,101,95,
- 98,121,116,101,99,111,100,101,230,1,0,0,115,16,0,0,
+ 98,121,116,101,99,111,100,101,231,1,0,0,115,16,0,0,
0,0,2,10,1,10,1,12,1,8,1,12,1,4,2,10,
1,114,145,0,0,0,114,62,0,0,0,99,3,0,0,0,
0,0,0,0,4,0,0,0,5,0,0,0,67,0,0,0,
@@ -704,7 +704,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,130,0,0,0,114,138,0,0,0,114,56,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
0,218,17,95,99,111,100,101,95,116,111,95,98,121,116,101,
- 99,111,100,101,242,1,0,0,115,10,0,0,0,0,3,8,
+ 99,111,100,101,243,1,0,0,115,10,0,0,0,0,3,8,
1,14,1,14,1,16,1,114,148,0,0,0,99,1,0,0,
0,0,0,0,0,5,0,0,0,6,0,0,0,67,0,0,
0,115,62,0,0,0,100,1,100,2,108,0,125,1,116,1,
@@ -731,7 +731,7 @@ const unsigned char _Py_M__importlib_external[] = {
99,111,100,105,110,103,90,15,110,101,119,108,105,110,101,95,
100,101,99,111,100,101,114,114,4,0,0,0,114,4,0,0,
0,114,6,0,0,0,218,13,100,101,99,111,100,101,95,115,
- 111,117,114,99,101,252,1,0,0,115,10,0,0,0,0,5,
+ 111,117,114,99,101,253,1,0,0,115,10,0,0,0,0,5,
8,1,12,1,10,1,12,1,114,153,0,0,0,41,2,114,
124,0,0,0,218,26,115,117,98,109,111,100,117,108,101,95,
115,101,97,114,99,104,95,108,111,99,97,116,105,111,110,115,
@@ -792,7 +792,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,117,102,102,105,120,101,115,114,157,0,0,0,90,7,100,
105,114,110,97,109,101,114,4,0,0,0,114,4,0,0,0,
114,6,0,0,0,218,23,115,112,101,99,95,102,114,111,109,
- 95,102,105,108,101,95,108,111,99,97,116,105,111,110,13,2,
+ 95,102,105,108,101,95,108,111,99,97,116,105,111,110,14,2,
0,0,115,62,0,0,0,0,12,8,4,4,1,10,2,2,
1,14,1,14,1,8,2,10,8,16,1,6,3,8,1,16,
1,14,1,10,1,6,1,6,2,4,3,8,2,10,1,2,
@@ -829,7 +829,7 @@ const unsigned char _Py_M__importlib_external[] = {
76,79,67,65,76,95,77,65,67,72,73,78,69,41,2,218,
3,99,108,115,114,5,0,0,0,114,4,0,0,0,114,4,
0,0,0,114,6,0,0,0,218,14,95,111,112,101,110,95,
- 114,101,103,105,115,116,114,121,93,2,0,0,115,8,0,0,
+ 114,101,103,105,115,116,114,121,94,2,0,0,115,8,0,0,
0,0,2,2,1,14,1,14,1,122,36,87,105,110,100,111,
119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,114,
46,95,111,112,101,110,95,114,101,103,105,115,116,114,121,99,
@@ -855,7 +855,7 @@ const unsigned char _Py_M__importlib_external[] = {
5,0,0,0,90,4,104,107,101,121,218,8,102,105,108,101,
112,97,116,104,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,218,16,95,115,101,97,114,99,104,95,114,101,103,
- 105,115,116,114,121,100,2,0,0,115,22,0,0,0,0,2,
+ 105,115,116,114,121,101,2,0,0,115,22,0,0,0,0,2,
6,1,8,2,6,1,6,1,22,1,2,1,12,1,26,1,
14,1,6,1,122,38,87,105,110,100,111,119,115,82,101,103,
105,115,116,114,121,70,105,110,100,101,114,46,95,115,101,97,
@@ -877,7 +877,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,218,6,116,97,114,103,101,116,114,174,0,0,0,114,124,
0,0,0,114,164,0,0,0,114,162,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,218,9,102,105,
- 110,100,95,115,112,101,99,115,2,0,0,115,26,0,0,0,
+ 110,100,95,115,112,101,99,116,2,0,0,115,26,0,0,0,
0,2,10,1,8,1,4,1,2,1,12,1,14,1,6,1,
16,1,14,1,6,1,8,1,8,1,122,31,87,105,110,100,
111,119,115,82,101,103,105,115,116,114,121,70,105,110,100,101,
@@ -896,7 +896,7 @@ const unsigned char _Py_M__importlib_external[] = {
124,0,0,0,41,4,114,168,0,0,0,114,123,0,0,0,
114,37,0,0,0,114,162,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,6,0,0,0,218,11,102,105,110,100,95,
- 109,111,100,117,108,101,131,2,0,0,115,8,0,0,0,0,
+ 109,111,100,117,108,101,132,2,0,0,115,8,0,0,0,0,
7,12,1,8,1,6,2,122,33,87,105,110,100,111,119,115,
82,101,103,105,115,116,114,121,70,105,110,100,101,114,46,102,
105,110,100,95,109,111,100,117,108,101,41,2,78,78,41,1,
@@ -906,7 +906,7 @@ const unsigned char _Py_M__importlib_external[] = {
104,111,100,114,169,0,0,0,114,175,0,0,0,114,178,0,
0,0,114,179,0,0,0,114,4,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,166,0,0,0,
- 81,2,0,0,115,18,0,0,0,12,5,4,3,4,2,4,
+ 82,2,0,0,115,18,0,0,0,12,5,4,3,4,2,4,
2,12,7,12,15,2,1,12,15,2,1,114,166,0,0,0,
99,0,0,0,0,0,0,0,0,0,0,0,0,2,0,0,
0,64,0,0,0,115,48,0,0,0,101,0,90,1,100,0,
@@ -940,7 +940,7 @@ const unsigned char _Py_M__importlib_external[] = {
5,114,104,0,0,0,114,123,0,0,0,114,98,0,0,0,
90,13,102,105,108,101,110,97,109,101,95,98,97,115,101,90,
9,116,97,105,108,95,110,97,109,101,114,4,0,0,0,114,
- 4,0,0,0,114,6,0,0,0,114,157,0,0,0,150,2,
+ 4,0,0,0,114,6,0,0,0,114,157,0,0,0,151,2,
0,0,115,8,0,0,0,0,3,18,1,16,1,14,1,122,
24,95,76,111,97,100,101,114,66,97,115,105,99,115,46,105,
115,95,112,97,99,107,97,103,101,99,2,0,0,0,0,0,
@@ -951,7 +951,7 @@ const unsigned char _Py_M__importlib_external[] = {
116,105,111,110,46,78,114,4,0,0,0,41,2,114,104,0,
0,0,114,162,0,0,0,114,4,0,0,0,114,4,0,0,
0,114,6,0,0,0,218,13,99,114,101,97,116,101,95,109,
- 111,100,117,108,101,158,2,0,0,115,0,0,0,0,122,27,
+ 111,100,117,108,101,159,2,0,0,115,0,0,0,0,122,27,
95,76,111,97,100,101,114,66,97,115,105,99,115,46,99,114,
101,97,116,101,95,109,111,100,117,108,101,99,2,0,0,0,
0,0,0,0,3,0,0,0,5,0,0,0,67,0,0,0,
@@ -971,7 +971,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,41,3,114,104,0,0,0,218,6,109,111,100,117,108,101,
114,144,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,218,11,101,120,101,99,95,109,111,100,117,108,
- 101,161,2,0,0,115,10,0,0,0,0,2,12,1,8,1,
+ 101,162,2,0,0,115,10,0,0,0,0,2,12,1,8,1,
6,1,10,1,122,25,95,76,111,97,100,101,114,66,97,115,
105,99,115,46,101,120,101,99,95,109,111,100,117,108,101,99,
2,0,0,0,0,0,0,0,2,0,0,0,4,0,0,0,
@@ -982,13 +982,13 @@ const unsigned char _Py_M__importlib_external[] = {
100,95,109,111,100,117,108,101,95,115,104,105,109,41,2,114,
104,0,0,0,114,123,0,0,0,114,4,0,0,0,114,4,
0,0,0,114,6,0,0,0,218,11,108,111,97,100,95,109,
- 111,100,117,108,101,169,2,0,0,115,2,0,0,0,0,2,
+ 111,100,117,108,101,170,2,0,0,115,2,0,0,0,0,2,
122,25,95,76,111,97,100,101,114,66,97,115,105,99,115,46,
108,111,97,100,95,109,111,100,117,108,101,78,41,8,114,109,
0,0,0,114,108,0,0,0,114,110,0,0,0,114,111,0,
0,0,114,157,0,0,0,114,183,0,0,0,114,188,0,0,
0,114,190,0,0,0,114,4,0,0,0,114,4,0,0,0,
- 114,4,0,0,0,114,6,0,0,0,114,181,0,0,0,145,
+ 114,4,0,0,0,114,6,0,0,0,114,181,0,0,0,146,
2,0,0,115,8,0,0,0,12,5,8,8,8,3,8,8,
114,181,0,0,0,99,0,0,0,0,0,0,0,0,0,0,
0,0,3,0,0,0,64,0,0,0,115,74,0,0,0,101,
@@ -1014,7 +1014,7 @@ const unsigned char _Py_M__importlib_external[] = {
32,78,41,1,114,42,0,0,0,41,2,114,104,0,0,0,
114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,218,10,112,97,116,104,95,109,116,105,109,101,
- 176,2,0,0,115,2,0,0,0,0,6,122,23,83,111,117,
+ 177,2,0,0,115,2,0,0,0,0,6,122,23,83,111,117,
114,99,101,76,111,97,100,101,114,46,112,97,116,104,95,109,
116,105,109,101,99,2,0,0,0,0,0,0,0,2,0,0,
0,4,0,0,0,67,0,0,0,115,14,0,0,0,100,1,
@@ -1049,7 +1049,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,41,1,114,192,0,0,0,41,2,114,104,0,0,0,
114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,218,10,112,97,116,104,95,115,116,97,116,115,
- 184,2,0,0,115,2,0,0,0,0,11,122,23,83,111,117,
+ 185,2,0,0,115,2,0,0,0,0,11,122,23,83,111,117,
114,99,101,76,111,97,100,101,114,46,112,97,116,104,95,115,
116,97,116,115,99,4,0,0,0,0,0,0,0,4,0,0,
0,4,0,0,0,67,0,0,0,115,12,0,0,0,124,0,
@@ -1072,7 +1072,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,104,0,0,0,114,94,0,0,0,90,10,99,97,99,104,
101,95,112,97,116,104,114,56,0,0,0,114,4,0,0,0,
114,4,0,0,0,114,6,0,0,0,218,15,95,99,97,99,
- 104,101,95,98,121,116,101,99,111,100,101,197,2,0,0,115,
+ 104,101,95,98,121,116,101,99,111,100,101,198,2,0,0,115,
2,0,0,0,0,8,122,28,83,111,117,114,99,101,76,111,
97,100,101,114,46,95,99,97,99,104,101,95,98,121,116,101,
99,111,100,101,99,3,0,0,0,0,0,0,0,3,0,0,
@@ -1089,7 +1089,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,115,46,10,32,32,32,32,32,32,32,32,78,114,4,0,
0,0,41,3,114,104,0,0,0,114,37,0,0,0,114,56,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
- 0,0,114,194,0,0,0,207,2,0,0,115,0,0,0,0,
+ 0,0,114,194,0,0,0,208,2,0,0,115,0,0,0,0,
122,21,83,111,117,114,99,101,76,111,97,100,101,114,46,115,
101,116,95,100,97,116,97,99,2,0,0,0,0,0,0,0,
5,0,0,0,16,0,0,0,67,0,0,0,115,82,0,0,
@@ -1110,7 +1110,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,123,0,0,0,114,37,0,0,0,114,151,0,
0,0,218,3,101,120,99,114,4,0,0,0,114,4,0,0,
0,114,6,0,0,0,218,10,103,101,116,95,115,111,117,114,
- 99,101,214,2,0,0,115,14,0,0,0,0,2,10,1,2,
+ 99,101,215,2,0,0,115,14,0,0,0,0,2,10,1,2,
1,14,1,16,1,4,1,28,1,122,23,83,111,117,114,99,
101,76,111,97,100,101,114,46,103,101,116,95,115,111,117,114,
99,101,114,31,0,0,0,41,1,218,9,95,111,112,116,105,
@@ -1131,7 +1131,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,218,7,99,111,109,112,105,108,101,41,4,114,104,0,0,
0,114,56,0,0,0,114,37,0,0,0,114,199,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,
- 14,115,111,117,114,99,101,95,116,111,95,99,111,100,101,224,
+ 14,115,111,117,114,99,101,95,116,111,95,99,111,100,101,225,
2,0,0,115,4,0,0,0,0,5,12,1,122,27,83,111,
117,114,99,101,76,111,97,100,101,114,46,115,111,117,114,99,
101,95,116,111,95,99,111,100,101,99,2,0,0,0,0,0,
@@ -1188,7 +1188,7 @@ const unsigned char _Py_M__importlib_external[] = {
98,121,116,101,115,95,100,97,116,97,114,151,0,0,0,90,
11,99,111,100,101,95,111,98,106,101,99,116,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,184,0,0,0,
- 232,2,0,0,115,78,0,0,0,0,7,10,1,4,1,2,
+ 233,2,0,0,115,78,0,0,0,0,7,10,1,4,1,2,
1,12,1,14,1,10,2,2,1,14,1,14,1,6,2,12,
1,2,1,14,1,14,1,6,2,2,1,4,1,4,1,12,
1,18,1,6,2,8,1,6,1,6,1,2,1,8,1,10,
@@ -1200,7 +1200,7 @@ const unsigned char _Py_M__importlib_external[] = {
195,0,0,0,114,194,0,0,0,114,198,0,0,0,114,202,
0,0,0,114,184,0,0,0,114,4,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,191,0,0,
- 0,174,2,0,0,115,14,0,0,0,8,2,8,8,8,13,
+ 0,175,2,0,0,115,14,0,0,0,8,2,8,8,8,13,
8,10,8,7,8,10,14,8,114,191,0,0,0,99,0,0,
0,0,0,0,0,0,0,0,0,0,4,0,0,0,0,0,
0,0,115,80,0,0,0,101,0,90,1,100,0,90,2,100,
@@ -1226,7 +1226,7 @@ const unsigned char _Py_M__importlib_external[] = {
102,105,110,100,101,114,46,78,41,2,114,102,0,0,0,114,
37,0,0,0,41,3,114,104,0,0,0,114,123,0,0,0,
114,37,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 6,0,0,0,114,182,0,0,0,33,3,0,0,115,4,0,
+ 6,0,0,0,114,182,0,0,0,34,3,0,0,115,4,0,
0,0,0,3,6,1,122,19,70,105,108,101,76,111,97,100,
101,114,46,95,95,105,110,105,116,95,95,99,2,0,0,0,
0,0,0,0,2,0,0,0,2,0,0,0,67,0,0,0,
@@ -1235,7 +1235,7 @@ const unsigned char _Py_M__importlib_external[] = {
41,2,218,9,95,95,99,108,97,115,115,95,95,114,115,0,
0,0,41,2,114,104,0,0,0,218,5,111,116,104,101,114,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,
- 6,95,95,101,113,95,95,39,3,0,0,115,4,0,0,0,
+ 6,95,95,101,113,95,95,40,3,0,0,115,4,0,0,0,
0,1,12,1,122,17,70,105,108,101,76,111,97,100,101,114,
46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0,
1,0,0,0,3,0,0,0,67,0,0,0,115,20,0,0,
@@ -1243,7 +1243,7 @@ const unsigned char _Py_M__importlib_external[] = {
1,65,0,83,0,41,1,78,41,3,218,4,104,97,115,104,
114,102,0,0,0,114,37,0,0,0,41,1,114,104,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,
- 218,8,95,95,104,97,115,104,95,95,43,3,0,0,115,2,
+ 218,8,95,95,104,97,115,104,95,95,44,3,0,0,115,2,
0,0,0,0,1,122,19,70,105,108,101,76,111,97,100,101,
114,46,95,95,104,97,115,104,95,95,99,2,0,0,0,0,
0,0,0,2,0,0,0,3,0,0,0,3,0,0,0,115,
@@ -1258,7 +1258,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,117,112,101,114,114,206,0,0,0,114,190,0,0,0,41,
2,114,104,0,0,0,114,123,0,0,0,41,1,114,207,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,190,0,0,
- 0,46,3,0,0,115,2,0,0,0,0,10,122,22,70,105,
+ 0,47,3,0,0,115,2,0,0,0,0,10,122,22,70,105,
108,101,76,111,97,100,101,114,46,108,111,97,100,95,109,111,
100,117,108,101,99,2,0,0,0,0,0,0,0,2,0,0,
0,1,0,0,0,67,0,0,0,115,6,0,0,0,124,0,
@@ -1268,7 +1268,7 @@ const unsigned char _Py_M__importlib_external[] = {
117,110,100,32,98,121,32,116,104,101,32,102,105,110,100,101,
114,46,41,1,114,37,0,0,0,41,2,114,104,0,0,0,
114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 6,0,0,0,114,155,0,0,0,58,3,0,0,115,2,0,
+ 6,0,0,0,114,155,0,0,0,59,3,0,0,115,2,0,
0,0,0,3,122,23,70,105,108,101,76,111,97,100,101,114,
46,103,101,116,95,102,105,108,101,110,97,109,101,99,2,0,
0,0,0,0,0,0,3,0,0,0,9,0,0,0,67,0,
@@ -1280,7 +1280,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,46,218,1,114,78,41,3,114,52,0,0,0,114,53,0,
0,0,90,4,114,101,97,100,41,3,114,104,0,0,0,114,
37,0,0,0,114,57,0,0,0,114,4,0,0,0,114,4,
- 0,0,0,114,6,0,0,0,114,196,0,0,0,63,3,0,
+ 0,0,0,114,6,0,0,0,114,196,0,0,0,64,3,0,
0,115,4,0,0,0,0,2,14,1,122,19,70,105,108,101,
76,111,97,100,101,114,46,103,101,116,95,100,97,116,97,41,
12,114,109,0,0,0,114,108,0,0,0,114,110,0,0,0,
@@ -1289,7 +1289,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,196,0,0,0,90,13,95,95,99,108,97,115,
115,99,101,108,108,95,95,114,4,0,0,0,114,4,0,0,
0,41,1,114,207,0,0,0,114,6,0,0,0,114,206,0,
- 0,0,28,3,0,0,115,12,0,0,0,12,5,8,6,8,
+ 0,0,29,3,0,0,115,12,0,0,0,12,5,8,6,8,
4,8,3,16,12,12,5,114,206,0,0,0,99,0,0,0,
0,0,0,0,0,0,0,0,0,3,0,0,0,64,0,0,
0,115,46,0,0,0,101,0,90,1,100,0,90,2,100,1,
@@ -1310,7 +1310,7 @@ const unsigned char _Py_M__importlib_external[] = {
218,8,115,116,95,109,116,105,109,101,90,7,115,116,95,115,
105,122,101,41,3,114,104,0,0,0,114,37,0,0,0,114,
204,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,
- 0,0,0,114,193,0,0,0,73,3,0,0,115,4,0,0,
+ 0,0,0,114,193,0,0,0,74,3,0,0,115,4,0,0,
0,0,2,8,1,122,27,83,111,117,114,99,101,70,105,108,
101,76,111,97,100,101,114,46,112,97,116,104,95,115,116,97,
116,115,99,4,0,0,0,0,0,0,0,5,0,0,0,5,
@@ -1320,7 +1320,7 @@ const unsigned char _Py_M__importlib_external[] = {
41,2,114,101,0,0,0,114,194,0,0,0,41,5,114,104,
0,0,0,114,94,0,0,0,114,93,0,0,0,114,56,0,
0,0,114,44,0,0,0,114,4,0,0,0,114,4,0,0,
- 0,114,6,0,0,0,114,195,0,0,0,78,3,0,0,115,
+ 0,114,6,0,0,0,114,195,0,0,0,79,3,0,0,115,
4,0,0,0,0,2,8,1,122,32,83,111,117,114,99,101,
70,105,108,101,76,111,97,100,101,114,46,95,99,97,99,104,
101,95,98,121,116,101,99,111,100,101,105,182,1,0,0,41,
@@ -1355,7 +1355,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,216,0,0,0,218,6,112,97,114,101,110,116,114,98,0,
0,0,114,29,0,0,0,114,25,0,0,0,114,197,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,
- 114,194,0,0,0,83,3,0,0,115,42,0,0,0,0,2,
+ 114,194,0,0,0,84,3,0,0,115,42,0,0,0,0,2,
12,1,4,2,14,1,12,1,14,2,14,1,10,1,2,1,
14,1,14,2,6,1,16,3,6,1,8,1,20,1,2,1,
12,1,16,1,16,2,8,1,122,25,83,111,117,114,99,101,
@@ -1364,7 +1364,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,110,0,0,0,114,111,0,0,0,114,193,0,0,0,114,
195,0,0,0,114,194,0,0,0,114,4,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,214,0,
- 0,0,69,3,0,0,115,6,0,0,0,12,4,8,5,8,
+ 0,0,70,3,0,0,115,6,0,0,0,12,4,8,5,8,
5,114,214,0,0,0,99,0,0,0,0,0,0,0,0,0,
0,0,0,2,0,0,0,64,0,0,0,115,32,0,0,0,
101,0,90,1,100,0,90,2,100,1,90,3,100,2,100,3,
@@ -1384,7 +1384,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,41,5,114,104,0,0,0,114,123,0,0,0,114,37,
0,0,0,114,56,0,0,0,114,205,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,184,0,0,
- 0,118,3,0,0,115,8,0,0,0,0,1,10,1,10,1,
+ 0,119,3,0,0,115,8,0,0,0,0,1,10,1,10,1,
14,1,122,29,83,111,117,114,99,101,108,101,115,115,70,105,
108,101,76,111,97,100,101,114,46,103,101,116,95,99,111,100,
101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,0,
@@ -1394,13 +1394,13 @@ const unsigned char _Py_M__importlib_external[] = {
117,114,99,101,32,99,111,100,101,46,78,114,4,0,0,0,
41,2,114,104,0,0,0,114,123,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,198,0,0,0,
- 124,3,0,0,115,2,0,0,0,0,2,122,31,83,111,117,
+ 125,3,0,0,115,2,0,0,0,0,2,122,31,83,111,117,
114,99,101,108,101,115,115,70,105,108,101,76,111,97,100,101,
114,46,103,101,116,95,115,111,117,114,99,101,78,41,6,114,
109,0,0,0,114,108,0,0,0,114,110,0,0,0,114,111,
0,0,0,114,184,0,0,0,114,198,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
- 0,114,219,0,0,0,114,3,0,0,115,4,0,0,0,12,
+ 0,114,219,0,0,0,115,3,0,0,115,4,0,0,0,12,
4,8,6,114,219,0,0,0,99,0,0,0,0,0,0,0,
0,0,0,0,0,3,0,0,0,64,0,0,0,115,92,0,
0,0,101,0,90,1,100,0,90,2,100,1,90,3,100,2,
@@ -1422,7 +1422,7 @@ const unsigned char _Py_M__importlib_external[] = {
78,41,2,114,102,0,0,0,114,37,0,0,0,41,3,114,
104,0,0,0,114,102,0,0,0,114,37,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,182,0,
- 0,0,141,3,0,0,115,4,0,0,0,0,1,6,1,122,
+ 0,0,142,3,0,0,115,4,0,0,0,0,1,6,1,122,
28,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,
97,100,101,114,46,95,95,105,110,105,116,95,95,99,2,0,
0,0,0,0,0,0,2,0,0,0,2,0,0,0,67,0,
@@ -1430,7 +1430,7 @@ const unsigned char _Py_M__importlib_external[] = {
2,111,22,124,0,106,1,124,1,106,1,107,2,83,0,41,
1,78,41,2,114,207,0,0,0,114,115,0,0,0,41,2,
114,104,0,0,0,114,208,0,0,0,114,4,0,0,0,114,
- 4,0,0,0,114,6,0,0,0,114,209,0,0,0,145,3,
+ 4,0,0,0,114,6,0,0,0,114,209,0,0,0,146,3,
0,0,115,4,0,0,0,0,1,12,1,122,26,69,120,116,
101,110,115,105,111,110,70,105,108,101,76,111,97,100,101,114,
46,95,95,101,113,95,95,99,1,0,0,0,0,0,0,0,
@@ -1439,7 +1439,7 @@ const unsigned char _Py_M__importlib_external[] = {
1,65,0,83,0,41,1,78,41,3,114,210,0,0,0,114,
102,0,0,0,114,37,0,0,0,41,1,114,104,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,
- 211,0,0,0,149,3,0,0,115,2,0,0,0,0,1,122,
+ 211,0,0,0,150,3,0,0,115,2,0,0,0,0,1,122,
28,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,
97,100,101,114,46,95,95,104,97,115,104,95,95,99,2,0,
0,0,0,0,0,0,3,0,0,0,5,0,0,0,67,0,
@@ -1456,7 +1456,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,102,0,0,0,114,37,0,0,0,41,3,114,
104,0,0,0,114,162,0,0,0,114,187,0,0,0,114,4,
0,0,0,114,4,0,0,0,114,6,0,0,0,114,183,0,
- 0,0,152,3,0,0,115,10,0,0,0,0,2,4,1,10,
+ 0,0,153,3,0,0,115,10,0,0,0,0,2,4,1,10,
1,6,1,12,1,122,33,69,120,116,101,110,115,105,111,110,
70,105,108,101,76,111,97,100,101,114,46,99,114,101,97,116,
101,95,109,111,100,117,108,101,99,2,0,0,0,0,0,0,
@@ -1473,7 +1473,7 @@ const unsigned char _Py_M__importlib_external[] = {
105,99,114,133,0,0,0,114,102,0,0,0,114,37,0,0,
0,41,2,114,104,0,0,0,114,187,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,188,0,0,
- 0,160,3,0,0,115,6,0,0,0,0,2,14,1,6,1,
+ 0,161,3,0,0,115,6,0,0,0,0,2,14,1,6,1,
122,31,69,120,116,101,110,115,105,111,110,70,105,108,101,76,
111,97,100,101,114,46,101,120,101,99,95,109,111,100,117,108,
101,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0,
@@ -1490,7 +1490,7 @@ const unsigned char _Py_M__importlib_external[] = {
182,0,0,0,78,114,4,0,0,0,41,2,114,24,0,0,
0,218,6,115,117,102,102,105,120,41,1,218,9,102,105,108,
101,95,110,97,109,101,114,4,0,0,0,114,6,0,0,0,
- 250,9,60,103,101,110,101,120,112,114,62,169,3,0,0,115,
+ 250,9,60,103,101,110,101,120,112,114,62,170,3,0,0,115,
2,0,0,0,4,1,122,49,69,120,116,101,110,115,105,111,
110,70,105,108,101,76,111,97,100,101,114,46,105,115,95,112,
97,99,107,97,103,101,46,60,108,111,99,97,108,115,62,46,
@@ -1499,7 +1499,7 @@ const unsigned char _Py_M__importlib_external[] = {
78,83,73,79,78,95,83,85,70,70,73,88,69,83,41,2,
114,104,0,0,0,114,123,0,0,0,114,4,0,0,0,41,
1,114,222,0,0,0,114,6,0,0,0,114,157,0,0,0,
- 166,3,0,0,115,6,0,0,0,0,2,14,1,12,1,122,
+ 167,3,0,0,115,6,0,0,0,0,2,14,1,12,1,122,
30,69,120,116,101,110,115,105,111,110,70,105,108,101,76,111,
97,100,101,114,46,105,115,95,112,97,99,107,97,103,101,99,
2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,
@@ -1510,7 +1510,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,32,97,32,99,111,100,101,32,111,98,106,101,99,116,46,
78,114,4,0,0,0,41,2,114,104,0,0,0,114,123,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
- 0,114,184,0,0,0,172,3,0,0,115,2,0,0,0,0,
+ 0,114,184,0,0,0,173,3,0,0,115,2,0,0,0,0,
2,122,28,69,120,116,101,110,115,105,111,110,70,105,108,101,
76,111,97,100,101,114,46,103,101,116,95,99,111,100,101,99,
2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,
@@ -1520,7 +1520,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,32,104,97,118,101,32,110,111,32,115,111,117,114,99,101,
32,99,111,100,101,46,78,114,4,0,0,0,41,2,114,104,
0,0,0,114,123,0,0,0,114,4,0,0,0,114,4,0,
- 0,0,114,6,0,0,0,114,198,0,0,0,176,3,0,0,
+ 0,0,114,6,0,0,0,114,198,0,0,0,177,3,0,0,
115,2,0,0,0,0,2,122,30,69,120,116,101,110,115,105,
111,110,70,105,108,101,76,111,97,100,101,114,46,103,101,116,
95,115,111,117,114,99,101,99,2,0,0,0,0,0,0,0,
@@ -1531,7 +1531,7 @@ const unsigned char _Py_M__importlib_external[] = {
32,102,111,117,110,100,32,98,121,32,116,104,101,32,102,105,
110,100,101,114,46,41,1,114,37,0,0,0,41,2,114,104,
0,0,0,114,123,0,0,0,114,4,0,0,0,114,4,0,
- 0,0,114,6,0,0,0,114,155,0,0,0,180,3,0,0,
+ 0,0,114,6,0,0,0,114,155,0,0,0,181,3,0,0,
115,2,0,0,0,0,3,122,32,69,120,116,101,110,115,105,
111,110,70,105,108,101,76,111,97,100,101,114,46,103,101,116,
95,102,105,108,101,110,97,109,101,78,41,14,114,109,0,0,
@@ -1540,7 +1540,7 @@ const unsigned char _Py_M__importlib_external[] = {
183,0,0,0,114,188,0,0,0,114,157,0,0,0,114,184,
0,0,0,114,198,0,0,0,114,120,0,0,0,114,155,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,
- 0,114,6,0,0,0,114,220,0,0,0,133,3,0,0,115,
+ 0,114,6,0,0,0,114,220,0,0,0,134,3,0,0,115,
18,0,0,0,12,8,8,4,8,4,8,3,8,8,8,6,
8,6,8,4,8,4,114,220,0,0,0,99,0,0,0,0,
0,0,0,0,0,0,0,0,2,0,0,0,64,0,0,0,
@@ -1581,7 +1581,7 @@ const unsigned char _Py_M__importlib_external[] = {
112,97,116,104,95,102,105,110,100,101,114,41,4,114,104,0,
0,0,114,102,0,0,0,114,37,0,0,0,218,11,112,97,
116,104,95,102,105,110,100,101,114,114,4,0,0,0,114,4,
- 0,0,0,114,6,0,0,0,114,182,0,0,0,193,3,0,
+ 0,0,0,114,6,0,0,0,114,182,0,0,0,194,3,0,
0,115,8,0,0,0,0,1,6,1,6,1,14,1,122,23,
95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,
95,105,110,105,116,95,95,99,1,0,0,0,0,0,0,0,
@@ -1599,7 +1599,7 @@ const unsigned char _Py_M__importlib_external[] = {
4,114,104,0,0,0,114,218,0,0,0,218,3,100,111,116,
90,2,109,101,114,4,0,0,0,114,4,0,0,0,114,6,
0,0,0,218,23,95,102,105,110,100,95,112,97,114,101,110,
- 116,95,112,97,116,104,95,110,97,109,101,115,199,3,0,0,
+ 116,95,112,97,116,104,95,110,97,109,101,115,200,3,0,0,
115,8,0,0,0,0,2,18,1,8,2,4,3,122,38,95,
78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,102,
105,110,100,95,112,97,114,101,110,116,95,112,97,116,104,95,
@@ -1612,7 +1612,7 @@ const unsigned char _Py_M__importlib_external[] = {
18,112,97,114,101,110,116,95,109,111,100,117,108,101,95,110,
97,109,101,90,14,112,97,116,104,95,97,116,116,114,95,110,
97,109,101,114,4,0,0,0,114,4,0,0,0,114,6,0,
- 0,0,114,229,0,0,0,209,3,0,0,115,4,0,0,0,
+ 0,0,114,229,0,0,0,210,3,0,0,115,4,0,0,0,
0,1,12,1,122,31,95,78,97,109,101,115,112,97,99,101,
80,97,116,104,46,95,103,101,116,95,112,97,114,101,110,116,
95,112,97,116,104,99,1,0,0,0,0,0,0,0,3,0,
@@ -1628,7 +1628,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,90,11,112,97,114,101,110,116,95,112,97,116,104,
114,162,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,218,12,95,114,101,99,97,108,99,117,108,97,
- 116,101,213,3,0,0,115,16,0,0,0,0,2,12,1,10,
+ 116,101,214,3,0,0,115,16,0,0,0,0,2,12,1,10,
1,14,3,18,1,6,1,8,1,6,1,122,27,95,78,97,
109,101,115,112,97,99,101,80,97,116,104,46,95,114,101,99,
97,108,99,117,108,97,116,101,99,1,0,0,0,0,0,0,
@@ -1636,7 +1636,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,116,0,124,0,160,1,161,0,131,1,83,0,41,1,
78,41,2,218,4,105,116,101,114,114,236,0,0,0,41,1,
114,104,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 6,0,0,0,218,8,95,95,105,116,101,114,95,95,226,3,
+ 6,0,0,0,218,8,95,95,105,116,101,114,95,95,227,3,
0,0,115,2,0,0,0,0,1,122,23,95,78,97,109,101,
115,112,97,99,101,80,97,116,104,46,95,95,105,116,101,114,
95,95,99,3,0,0,0,0,0,0,0,3,0,0,0,3,
@@ -1645,14 +1645,14 @@ const unsigned char _Py_M__importlib_external[] = {
228,0,0,0,41,3,114,104,0,0,0,218,5,105,110,100,
101,120,114,37,0,0,0,114,4,0,0,0,114,4,0,0,
0,114,6,0,0,0,218,11,95,95,115,101,116,105,116,101,
- 109,95,95,229,3,0,0,115,2,0,0,0,0,1,122,26,
+ 109,95,95,230,3,0,0,115,2,0,0,0,0,1,122,26,
95,78,97,109,101,115,112,97,99,101,80,97,116,104,46,95,
95,115,101,116,105,116,101,109,95,95,99,1,0,0,0,0,
0,0,0,1,0,0,0,3,0,0,0,67,0,0,0,115,
12,0,0,0,116,0,124,0,160,1,161,0,131,1,83,0,
41,1,78,41,2,114,33,0,0,0,114,236,0,0,0,41,
1,114,104,0,0,0,114,4,0,0,0,114,4,0,0,0,
- 114,6,0,0,0,218,7,95,95,108,101,110,95,95,232,3,
+ 114,6,0,0,0,218,7,95,95,108,101,110,95,95,233,3,
0,0,115,2,0,0,0,0,1,122,22,95,78,97,109,101,
115,112,97,99,101,80,97,116,104,46,95,95,108,101,110,95,
95,99,1,0,0,0,0,0,0,0,1,0,0,0,3,0,
@@ -1661,7 +1661,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,115,112,97,99,101,80,97,116,104,40,123,33,114,125,41,
41,2,114,50,0,0,0,114,228,0,0,0,41,1,114,104,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
- 0,0,218,8,95,95,114,101,112,114,95,95,235,3,0,0,
+ 0,0,218,8,95,95,114,101,112,114,95,95,236,3,0,0,
115,2,0,0,0,0,1,122,23,95,78,97,109,101,115,112,
97,99,101,80,97,116,104,46,95,95,114,101,112,114,95,95,
99,2,0,0,0,0,0,0,0,2,0,0,0,3,0,0,
@@ -1669,7 +1669,7 @@ const unsigned char _Py_M__importlib_external[] = {
161,0,107,6,83,0,41,1,78,41,1,114,236,0,0,0,
41,2,114,104,0,0,0,218,4,105,116,101,109,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,218,12,95,95,
- 99,111,110,116,97,105,110,115,95,95,238,3,0,0,115,2,
+ 99,111,110,116,97,105,110,115,95,95,239,3,0,0,115,2,
0,0,0,0,1,122,27,95,78,97,109,101,115,112,97,99,
101,80,97,116,104,46,95,95,99,111,110,116,97,105,110,115,
95,95,99,2,0,0,0,0,0,0,0,2,0,0,0,3,
@@ -1677,7 +1677,7 @@ const unsigned char _Py_M__importlib_external[] = {
160,1,124,1,161,1,1,0,100,0,83,0,41,1,78,41,
2,114,228,0,0,0,114,161,0,0,0,41,2,114,104,0,
0,0,114,243,0,0,0,114,4,0,0,0,114,4,0,0,
- 0,114,6,0,0,0,114,161,0,0,0,241,3,0,0,115,
+ 0,114,6,0,0,0,114,161,0,0,0,242,3,0,0,115,
2,0,0,0,0,1,122,21,95,78,97,109,101,115,112,97,
99,101,80,97,116,104,46,97,112,112,101,110,100,78,41,14,
114,109,0,0,0,114,108,0,0,0,114,110,0,0,0,114,
@@ -1685,7 +1685,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,236,0,0,0,114,238,0,0,0,114,240,0,
0,0,114,241,0,0,0,114,242,0,0,0,114,244,0,0,
0,114,161,0,0,0,114,4,0,0,0,114,4,0,0,0,
- 114,4,0,0,0,114,6,0,0,0,114,226,0,0,0,186,
+ 114,4,0,0,0,114,6,0,0,0,114,226,0,0,0,187,
3,0,0,115,20,0,0,0,12,7,8,6,8,10,8,4,
8,13,8,3,8,3,8,3,8,3,8,3,114,226,0,0,
0,99,0,0,0,0,0,0,0,0,0,0,0,0,3,0,
@@ -1702,7 +1702,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,226,0,0,0,114,228,0,0,0,41,4,114,104,0,0,
0,114,102,0,0,0,114,37,0,0,0,114,232,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,
- 182,0,0,0,247,3,0,0,115,2,0,0,0,0,1,122,
+ 182,0,0,0,248,3,0,0,115,2,0,0,0,0,1,122,
25,95,78,97,109,101,115,112,97,99,101,76,111,97,100,101,
114,46,95,95,105,110,105,116,95,95,99,2,0,0,0,0,
0,0,0,2,0,0,0,3,0,0,0,67,0,0,0,115,
@@ -1719,21 +1719,21 @@ const unsigned char _Py_M__importlib_external[] = {
41,62,41,2,114,50,0,0,0,114,109,0,0,0,41,2,
114,168,0,0,0,114,187,0,0,0,114,4,0,0,0,114,
4,0,0,0,114,6,0,0,0,218,11,109,111,100,117,108,
- 101,95,114,101,112,114,250,3,0,0,115,2,0,0,0,0,
+ 101,95,114,101,112,114,251,3,0,0,115,2,0,0,0,0,
7,122,28,95,78,97,109,101,115,112,97,99,101,76,111,97,
100,101,114,46,109,111,100,117,108,101,95,114,101,112,114,99,
2,0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,
67,0,0,0,115,4,0,0,0,100,1,83,0,41,2,78,
84,114,4,0,0,0,41,2,114,104,0,0,0,114,123,0,
0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
- 0,114,157,0,0,0,3,4,0,0,115,2,0,0,0,0,
+ 0,114,157,0,0,0,4,4,0,0,115,2,0,0,0,0,
1,122,27,95,78,97,109,101,115,112,97,99,101,76,111,97,
100,101,114,46,105,115,95,112,97,99,107,97,103,101,99,2,
0,0,0,0,0,0,0,2,0,0,0,1,0,0,0,67,
0,0,0,115,4,0,0,0,100,1,83,0,41,2,78,114,
32,0,0,0,114,4,0,0,0,41,2,114,104,0,0,0,
114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 6,0,0,0,114,198,0,0,0,6,4,0,0,115,2,0,
+ 6,0,0,0,114,198,0,0,0,7,4,0,0,115,2,0,
0,0,0,1,122,27,95,78,97,109,101,115,112,97,99,101,
76,111,97,100,101,114,46,103,101,116,95,115,111,117,114,99,
101,99,2,0,0,0,0,0,0,0,2,0,0,0,6,0,
@@ -1743,7 +1743,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,84,41,1,114,200,0,0,0,41,1,114,201,0,0,
0,41,2,114,104,0,0,0,114,123,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,184,0,0,
- 0,9,4,0,0,115,2,0,0,0,0,1,122,25,95,78,
+ 0,10,4,0,0,115,2,0,0,0,0,1,122,25,95,78,
97,109,101,115,112,97,99,101,76,111,97,100,101,114,46,103,
101,116,95,99,111,100,101,99,2,0,0,0,0,0,0,0,
2,0,0,0,1,0,0,0,67,0,0,0,115,4,0,0,
@@ -1752,14 +1752,14 @@ const unsigned char _Py_M__importlib_external[] = {
111,114,32,109,111,100,117,108,101,32,99,114,101,97,116,105,
111,110,46,78,114,4,0,0,0,41,2,114,104,0,0,0,
114,162,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 6,0,0,0,114,183,0,0,0,12,4,0,0,115,0,0,
+ 6,0,0,0,114,183,0,0,0,13,4,0,0,115,0,0,
0,0,122,30,95,78,97,109,101,115,112,97,99,101,76,111,
97,100,101,114,46,99,114,101,97,116,101,95,109,111,100,117,
108,101,99,2,0,0,0,0,0,0,0,2,0,0,0,1,
0,0,0,67,0,0,0,115,4,0,0,0,100,0,83,0,
41,1,78,114,4,0,0,0,41,2,114,104,0,0,0,114,
187,0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,
- 0,0,0,114,188,0,0,0,15,4,0,0,115,2,0,0,
+ 0,0,0,114,188,0,0,0,16,4,0,0,115,2,0,0,
0,0,1,122,28,95,78,97,109,101,115,112,97,99,101,76,
111,97,100,101,114,46,101,120,101,99,95,109,111,100,117,108,
101,99,2,0,0,0,0,0,0,0,2,0,0,0,4,0,
@@ -1777,7 +1777,7 @@ const unsigned char _Py_M__importlib_external[] = {
33,114,125,41,4,114,118,0,0,0,114,133,0,0,0,114,
228,0,0,0,114,189,0,0,0,41,2,114,104,0,0,0,
114,123,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 6,0,0,0,114,190,0,0,0,18,4,0,0,115,6,0,
+ 6,0,0,0,114,190,0,0,0,19,4,0,0,115,6,0,
0,0,0,7,6,1,8,1,122,28,95,78,97,109,101,115,
112,97,99,101,76,111,97,100,101,114,46,108,111,97,100,95,
109,111,100,117,108,101,78,41,12,114,109,0,0,0,114,108,
@@ -1785,7 +1785,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,246,0,0,0,114,157,0,0,0,114,198,0,0,
0,114,184,0,0,0,114,183,0,0,0,114,188,0,0,0,
114,190,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
- 4,0,0,0,114,6,0,0,0,114,245,0,0,0,246,3,
+ 4,0,0,0,114,6,0,0,0,114,245,0,0,0,247,3,
0,0,115,16,0,0,0,8,1,8,3,12,9,8,3,8,
3,8,3,8,3,8,3,114,245,0,0,0,99,0,0,0,
0,0,0,0,0,0,0,0,0,4,0,0,0,64,0,0,
@@ -1819,7 +1819,7 @@ const unsigned char _Py_M__importlib_external[] = {
99,104,101,218,6,118,97,108,117,101,115,114,112,0,0,0,
114,248,0,0,0,41,2,114,168,0,0,0,218,6,102,105,
110,100,101,114,114,4,0,0,0,114,4,0,0,0,114,6,
- 0,0,0,114,248,0,0,0,36,4,0,0,115,6,0,0,
+ 0,0,0,114,248,0,0,0,37,4,0,0,115,6,0,0,
0,0,4,16,1,10,1,122,28,80,97,116,104,70,105,110,
100,101,114,46,105,110,118,97,108,105,100,97,116,101,95,99,
97,99,104,101,115,99,2,0,0,0,0,0,0,0,3,0,
@@ -1839,7 +1839,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,114,103,0,0,0,41,3,114,168,0,0,0,114,37,0,
0,0,90,4,104,111,111,107,114,4,0,0,0,114,4,0,
0,0,114,6,0,0,0,218,11,95,112,97,116,104,95,104,
- 111,111,107,115,44,4,0,0,115,16,0,0,0,0,3,16,
+ 111,111,107,115,45,4,0,0,115,16,0,0,0,0,3,16,
1,12,1,12,1,2,1,8,1,14,1,12,2,122,22,80,
97,116,104,70,105,110,100,101,114,46,95,112,97,116,104,95,
104,111,111,107,115,99,2,0,0,0,0,0,0,0,3,0,
@@ -1870,7 +1870,7 @@ const unsigned char _Py_M__importlib_external[] = {
253,0,0,0,41,3,114,168,0,0,0,114,37,0,0,0,
114,251,0,0,0,114,4,0,0,0,114,4,0,0,0,114,
6,0,0,0,218,20,95,112,97,116,104,95,105,109,112,111,
- 114,116,101,114,95,99,97,99,104,101,57,4,0,0,115,22,
+ 114,116,101,114,95,99,97,99,104,101,58,4,0,0,115,22,
0,0,0,0,8,8,1,2,1,12,1,14,3,6,1,2,
1,14,1,14,1,10,1,16,1,122,31,80,97,116,104,70,
105,110,100,101,114,46,95,112,97,116,104,95,105,109,112,111,
@@ -1888,7 +1888,7 @@ const unsigned char _Py_M__importlib_external[] = {
251,0,0,0,114,124,0,0,0,114,125,0,0,0,114,162,
0,0,0,114,4,0,0,0,114,4,0,0,0,114,6,0,
0,0,218,16,95,108,101,103,97,99,121,95,103,101,116,95,
- 115,112,101,99,79,4,0,0,115,18,0,0,0,0,4,10,
+ 115,112,101,99,80,4,0,0,115,18,0,0,0,0,4,10,
1,16,2,10,1,4,1,8,1,12,1,12,1,6,1,122,
27,80,97,116,104,70,105,110,100,101,114,46,95,108,101,103,
97,99,121,95,103,101,116,95,115,112,101,99,78,99,4,0,
@@ -1919,7 +1919,7 @@ const unsigned char _Py_M__importlib_external[] = {
115,112,97,99,101,95,112,97,116,104,90,5,101,110,116,114,
121,114,251,0,0,0,114,162,0,0,0,114,125,0,0,0,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,
- 9,95,103,101,116,95,115,112,101,99,94,4,0,0,115,40,
+ 9,95,103,101,116,95,115,112,101,99,95,4,0,0,115,40,
0,0,0,0,5,4,1,10,1,14,1,2,1,10,1,8,
1,10,1,14,2,12,1,8,1,2,1,10,1,4,1,6,
1,8,1,8,5,14,2,12,1,6,1,122,20,80,97,116,
@@ -1947,7 +1947,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,41,6,114,168,0,0,0,114,123,0,0,0,114,37,0,
0,0,114,177,0,0,0,114,162,0,0,0,114,2,1,0,
0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,
- 114,178,0,0,0,126,4,0,0,115,26,0,0,0,0,6,
+ 114,178,0,0,0,127,4,0,0,115,26,0,0,0,0,6,
8,1,6,1,14,1,8,1,4,1,10,1,6,1,4,3,
6,1,16,1,4,2,6,2,122,20,80,97,116,104,70,105,
110,100,101,114,46,102,105,110,100,95,115,112,101,99,99,3,
@@ -1968,7 +1968,7 @@ const unsigned char _Py_M__importlib_external[] = {
32,32,32,32,78,41,2,114,178,0,0,0,114,124,0,0,
0,41,4,114,168,0,0,0,114,123,0,0,0,114,37,0,
0,0,114,162,0,0,0,114,4,0,0,0,114,4,0,0,
- 0,114,6,0,0,0,114,179,0,0,0,150,4,0,0,115,
+ 0,114,6,0,0,0,114,179,0,0,0,151,4,0,0,115,
8,0,0,0,0,8,12,1,8,1,4,1,122,22,80,97,
116,104,70,105,110,100,101,114,46,102,105,110,100,95,109,111,
100,117,108,101,41,1,78,41,2,78,78,41,1,78,41,12,
@@ -1977,7 +1977,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,255,0,0,0,114,0,1,0,0,114,3,1,
0,0,114,178,0,0,0,114,179,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,
- 114,247,0,0,0,32,4,0,0,115,20,0,0,0,12,4,
+ 114,247,0,0,0,33,4,0,0,115,20,0,0,0,12,4,
12,8,12,13,12,22,12,15,2,1,12,31,2,1,12,23,
2,1,114,247,0,0,0,99,0,0,0,0,0,0,0,0,
0,0,0,0,3,0,0,0,64,0,0,0,115,90,0,0,
@@ -2021,7 +2021,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,113,2,100,0,83,0,41,1,78,114,4,0,0,0,41,
2,114,24,0,0,0,114,221,0,0,0,41,1,114,124,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,223,0,0,
- 0,179,4,0,0,115,2,0,0,0,4,0,122,38,70,105,
+ 0,180,4,0,0,115,2,0,0,0,4,0,122,38,70,105,
108,101,70,105,110,100,101,114,46,95,95,105,110,105,116,95,
95,46,60,108,111,99,97,108,115,62,46,60,103,101,110,101,
120,112,114,62,114,61,0,0,0,114,31,0,0,0,78,114,
@@ -2033,7 +2033,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,104,0,0,0,114,37,0,0,0,218,14,108,111,97,100,
101,114,95,100,101,116,97,105,108,115,90,7,108,111,97,100,
101,114,115,114,164,0,0,0,114,4,0,0,0,41,1,114,
- 124,0,0,0,114,6,0,0,0,114,182,0,0,0,173,4,
+ 124,0,0,0,114,6,0,0,0,114,182,0,0,0,174,4,
0,0,115,16,0,0,0,0,4,4,1,14,1,28,1,6,
2,10,1,6,1,8,1,122,19,70,105,108,101,70,105,110,
100,101,114,46,95,95,105,110,105,116,95,95,99,1,0,0,
@@ -2044,7 +2044,7 @@ const unsigned char _Py_M__importlib_external[] = {
109,101,46,114,31,0,0,0,78,114,91,0,0,0,41,1,
114,6,1,0,0,41,1,114,104,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,248,0,0,0,
- 187,4,0,0,115,2,0,0,0,0,2,122,28,70,105,108,
+ 188,4,0,0,115,2,0,0,0,0,2,122,28,70,105,108,
101,70,105,110,100,101,114,46,105,110,118,97,108,105,100,97,
116,101,95,99,97,99,104,101,115,99,2,0,0,0,0,0,
0,0,3,0,0,0,3,0,0,0,67,0,0,0,115,42,
@@ -2066,7 +2066,7 @@ const unsigned char _Py_M__importlib_external[] = {
32,32,32,32,32,32,78,41,3,114,178,0,0,0,114,124,
0,0,0,114,154,0,0,0,41,3,114,104,0,0,0,114,
123,0,0,0,114,162,0,0,0,114,4,0,0,0,114,4,
- 0,0,0,114,6,0,0,0,114,121,0,0,0,193,4,0,
+ 0,0,0,114,6,0,0,0,114,121,0,0,0,194,4,0,
0,115,8,0,0,0,0,7,10,1,8,1,8,1,122,22,
70,105,108,101,70,105,110,100,101,114,46,102,105,110,100,95,
108,111,97,100,101,114,99,6,0,0,0,0,0,0,0,7,
@@ -2077,7 +2077,7 @@ const unsigned char _Py_M__importlib_external[] = {
41,7,114,104,0,0,0,114,163,0,0,0,114,123,0,0,
0,114,37,0,0,0,90,4,115,109,115,108,114,177,0,0,
0,114,124,0,0,0,114,4,0,0,0,114,4,0,0,0,
- 114,6,0,0,0,114,3,1,0,0,205,4,0,0,115,6,
+ 114,6,0,0,0,114,3,1,0,0,206,4,0,0,115,6,
0,0,0,0,1,10,1,8,1,122,20,70,105,108,101,70,
105,110,100,101,114,46,95,103,101,116,95,115,112,101,99,78,
99,3,0,0,0,0,0,0,0,14,0,0,0,16,0,0,
@@ -2132,7 +2132,7 @@ const unsigned char _Py_M__importlib_external[] = {
90,13,105,110,105,116,95,102,105,108,101,110,97,109,101,90,
9,102,117,108,108,95,112,97,116,104,114,162,0,0,0,114,
4,0,0,0,114,4,0,0,0,114,6,0,0,0,114,178,
- 0,0,0,210,4,0,0,115,70,0,0,0,0,5,4,1,
+ 0,0,0,211,4,0,0,115,70,0,0,0,0,5,4,1,
14,1,2,1,24,1,14,1,10,1,10,1,8,1,6,2,
6,1,6,1,10,2,6,1,4,2,8,1,12,1,16,1,
8,1,10,1,8,1,24,4,8,2,16,1,16,1,16,1,
@@ -2163,7 +2163,7 @@ const unsigned char _Py_M__importlib_external[] = {
1,160,0,161,0,146,2,113,4,83,0,114,4,0,0,0,
41,1,114,92,0,0,0,41,2,114,24,0,0,0,90,2,
102,110,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
- 0,250,9,60,115,101,116,99,111,109,112,62,31,5,0,0,
+ 0,250,9,60,115,101,116,99,111,109,112,62,32,5,0,0,
115,2,0,0,0,6,0,122,41,70,105,108,101,70,105,110,
100,101,114,46,95,102,105,108,108,95,99,97,99,104,101,46,
60,108,111,99,97,108,115,62,46,60,115,101,116,99,111,109,
@@ -2180,7 +2180,7 @@ const unsigned char _Py_M__importlib_external[] = {
105,120,95,99,111,110,116,101,110,116,115,114,243,0,0,0,
114,102,0,0,0,114,233,0,0,0,114,221,0,0,0,90,
8,110,101,119,95,110,97,109,101,114,4,0,0,0,114,4,
- 0,0,0,114,6,0,0,0,114,11,1,0,0,2,5,0,
+ 0,0,0,114,6,0,0,0,114,11,1,0,0,3,5,0,
0,115,34,0,0,0,0,2,6,1,2,1,22,1,20,3,
10,3,12,1,12,7,6,1,10,1,16,1,4,1,18,2,
4,1,14,1,6,1,12,1,122,22,70,105,108,101,70,105,
@@ -2218,7 +2218,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,114,103,0,0,0,41,1,114,37,0,0,0,41,2,
114,168,0,0,0,114,10,1,0,0,114,4,0,0,0,114,
6,0,0,0,218,24,112,97,116,104,95,104,111,111,107,95,
- 102,111,114,95,70,105,108,101,70,105,110,100,101,114,43,5,
+ 102,111,114,95,70,105,108,101,70,105,110,100,101,114,44,5,
0,0,115,6,0,0,0,0,2,8,1,12,1,122,54,70,
105,108,101,70,105,110,100,101,114,46,112,97,116,104,95,104,
111,111,107,46,60,108,111,99,97,108,115,62,46,112,97,116,
@@ -2226,7 +2226,7 @@ const unsigned char _Py_M__importlib_external[] = {
105,110,100,101,114,114,4,0,0,0,41,3,114,168,0,0,
0,114,10,1,0,0,114,16,1,0,0,114,4,0,0,0,
41,2,114,168,0,0,0,114,10,1,0,0,114,6,0,0,
- 0,218,9,112,97,116,104,95,104,111,111,107,33,5,0,0,
+ 0,218,9,112,97,116,104,95,104,111,111,107,34,5,0,0,
115,4,0,0,0,0,10,14,6,122,20,70,105,108,101,70,
105,110,100,101,114,46,112,97,116,104,95,104,111,111,107,99,
1,0,0,0,0,0,0,0,1,0,0,0,3,0,0,0,
@@ -2235,7 +2235,7 @@ const unsigned char _Py_M__importlib_external[] = {
110,100,101,114,40,123,33,114,125,41,41,2,114,50,0,0,
0,114,37,0,0,0,41,1,114,104,0,0,0,114,4,0,
0,0,114,4,0,0,0,114,6,0,0,0,114,242,0,0,
- 0,51,5,0,0,115,2,0,0,0,0,1,122,19,70,105,
+ 0,52,5,0,0,115,2,0,0,0,0,1,122,19,70,105,
108,101,70,105,110,100,101,114,46,95,95,114,101,112,114,95,
95,41,1,78,41,15,114,109,0,0,0,114,108,0,0,0,
114,110,0,0,0,114,111,0,0,0,114,182,0,0,0,114,
@@ -2243,7 +2243,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,0,114,3,1,0,0,114,178,0,0,0,114,11,1,
0,0,114,180,0,0,0,114,17,1,0,0,114,242,0,0,
0,114,4,0,0,0,114,4,0,0,0,114,4,0,0,0,
- 114,6,0,0,0,114,4,1,0,0,164,4,0,0,115,18,
+ 114,6,0,0,0,114,4,1,0,0,165,4,0,0,115,18,
0,0,0,12,9,8,14,8,4,4,2,8,12,8,5,10,
48,8,31,12,18,114,4,1,0,0,99,4,0,0,0,0,
0,0,0,6,0,0,0,11,0,0,0,67,0,0,0,115,
@@ -2266,7 +2266,7 @@ const unsigned char _Py_M__importlib_external[] = {
97,116,104,110,97,109,101,90,9,99,112,97,116,104,110,97,
109,101,114,124,0,0,0,114,162,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,218,14,95,102,105,
- 120,95,117,112,95,109,111,100,117,108,101,57,5,0,0,115,
+ 120,95,117,112,95,109,111,100,117,108,101,58,5,0,0,115,
34,0,0,0,0,2,10,1,10,1,4,1,4,1,8,1,
8,1,12,2,10,1,4,1,14,1,2,1,8,1,8,1,
8,1,12,1,14,2,114,22,1,0,0,99,0,0,0,0,
@@ -2286,7 +2286,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,0,41,3,90,10,101,120,116,101,110,115,105,111,110,115,
90,6,115,111,117,114,99,101,90,8,98,121,116,101,99,111,
100,101,114,4,0,0,0,114,4,0,0,0,114,6,0,0,
- 0,114,159,0,0,0,80,5,0,0,115,8,0,0,0,0,
+ 0,114,159,0,0,0,81,5,0,0,115,8,0,0,0,0,
5,12,1,8,1,8,1,114,159,0,0,0,99,1,0,0,
0,0,0,0,0,12,0,0,0,12,0,0,0,67,0,0,
0,115,156,1,0,0,124,0,97,0,116,0,106,1,97,1,
@@ -2337,7 +2337,7 @@ const unsigned char _Py_M__importlib_external[] = {
0,41,2,114,31,0,0,0,78,41,1,114,33,0,0,0,
41,2,114,24,0,0,0,114,81,0,0,0,114,4,0,0,
0,114,4,0,0,0,114,6,0,0,0,114,223,0,0,0,
- 116,5,0,0,115,2,0,0,0,4,0,122,25,95,115,101,
+ 117,5,0,0,115,2,0,0,0,4,0,122,25,95,115,101,
116,117,112,46,60,108,111,99,97,108,115,62,46,60,103,101,
110,101,120,112,114,62,114,62,0,0,0,122,30,105,109,112,
111,114,116,108,105,98,32,114,101,113,117,105,114,101,115,32,
@@ -2366,7 +2366,7 @@ const unsigned char _Py_M__importlib_external[] = {
101,90,14,119,101,97,107,114,101,102,95,109,111,100,117,108,
101,90,13,119,105,110,114,101,103,95,109,111,100,117,108,101,
114,4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,
- 6,95,115,101,116,117,112,91,5,0,0,115,76,0,0,0,
+ 6,95,115,101,116,117,112,92,5,0,0,115,76,0,0,0,
0,8,4,1,6,1,6,3,10,1,10,1,10,1,12,2,
10,1,16,3,22,1,14,2,22,1,8,1,10,1,10,1,
4,2,2,1,10,1,6,1,14,1,12,2,8,1,12,1,
@@ -2386,7 +2386,7 @@ const unsigned char _Py_M__importlib_external[] = {
114,247,0,0,0,41,2,114,29,1,0,0,90,17,115,117,
112,112,111,114,116,101,100,95,108,111,97,100,101,114,115,114,
4,0,0,0,114,4,0,0,0,114,6,0,0,0,218,8,
- 95,105,110,115,116,97,108,108,155,5,0,0,115,8,0,0,
+ 95,105,110,115,116,97,108,108,156,5,0,0,115,8,0,0,
0,0,2,8,1,6,1,20,1,114,32,1,0,0,41,1,
114,0,0,0,0,41,2,114,1,0,0,0,114,2,0,0,
0,41,1,114,49,0,0,0,41,1,78,41,3,78,78,78,
@@ -2420,7 +2420,7 @@ const unsigned char _Py_M__importlib_external[] = {
6,0,0,0,218,8,60,109,111,100,117,108,101,62,24,0,
0,0,115,108,0,0,0,4,0,4,1,4,1,2,1,6,
3,8,17,8,5,8,5,8,6,8,12,8,10,8,9,8,
- 5,8,7,10,22,10,124,16,1,12,2,4,1,4,2,6,
+ 5,8,7,10,22,10,125,16,1,12,2,4,1,4,2,6,
2,6,2,8,2,16,45,8,34,8,19,8,12,8,12,8,
28,8,17,10,55,10,12,10,10,8,14,6,3,4,1,14,
67,14,64,14,29,16,110,14,41,18,45,18,16,4,3,18,
1
0
https://github.com/python/cpython/commit/a51b90a31399a8826e590da8e327bd65dd…
commit: a51b90a31399a8826e590da8e327bd65dd29e5a4
branch: master
author: Barry Warsaw <barry(a)python.org>
committer: GitHub <noreply(a)github.com>
date: 2017-10-06T09:53:48-04:00
summary:
Document Py_GETENV() (#3890)
files:
M Doc/c-api/intro.rst
diff --git a/Doc/c-api/intro.rst b/Doc/c-api/intro.rst
index 4942b1a4698..e654c4c0126 100644
--- a/Doc/c-api/intro.rst
+++ b/Doc/c-api/intro.rst
@@ -132,6 +132,11 @@ complete listing.
Argument must be a character or an integer in the range [-128, 127] or [0,
255]. This macro returns ``c`` cast to an ``unsigned char``.
+.. c:macro:: Py_GETENV(s)
+
+ Like ``getenv(s)``, but returns *NULL* if :option:`-E` was passed on the
+ command line (i.e. if ``Py_IgnoreEnvironmentFlag`` is set).
+
.. _api-objects:
1
0
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
bpo-25658: Implement PEP 539 for Thread Specific Storage (TSS) API (GH-1362)
by Nick Coghlan Oct. 6, 2017
by Nick Coghlan Oct. 6, 2017
Oct. 6, 2017
https://github.com/python/cpython/commit/731e18901484c75b60167a06a0ba0719a6…
commit: 731e18901484c75b60167a06a0ba0719a6d4827d
branch: master
author: Masayuki Yamamoto <ma3yuki.8mamo10(a)gmail.com>
committer: Nick Coghlan <ncoghlan(a)gmail.com>
date: 2017-10-06T20:41:34+10:00
summary:
bpo-25658: Implement PEP 539 for Thread Specific Storage (TSS) API (GH-1362)
See PEP 539 for details.
Highlights of changes:
- Add Thread Specific Storage (TSS) API
- Document the Thread Local Storage (TLS) API as deprecated
- Update code that used TLS API to use TSS API
files:
A Misc/NEWS.d/next/C API/2017-06-24-14-30-44.bpo-25658.vm8vGE.rst
M Doc/c-api/init.rst
M Doc/whatsnew/3.7.rst
M Include/internal/pystate.h
M Include/pythread.h
M Modules/_testcapimodule.c
M Modules/_tracemalloc.c
M Modules/faulthandler.c
M Modules/posixmodule.c
M PC/python3.def
M Python/pystate.c
M Python/thread.c
M Python/thread_nt.h
M Python/thread_pthread.h
M Python/traceback.c
M configure
M configure.ac
M pyconfig.h.in
diff --git a/Doc/c-api/init.rst b/Doc/c-api/init.rst
index c12e1c7fba3..7792058683d 100644
--- a/Doc/c-api/init.rst
+++ b/Doc/c-api/init.rst
@@ -1192,3 +1192,160 @@ These functions are only intended to be used by advanced debugging tools.
Return the next thread state object after *tstate* from the list of all such
objects belonging to the same :c:type:`PyInterpreterState` object.
+
+.. _thread-local-storage:
+
+Thread Local Storage Support
+============================
+
+.. sectionauthor:: Masayuki Yamamoto <ma3yuki.8mamo10(a)gmail.com>
+
+The Python interpreter provides low-level support for thread-local storage
+(TLS) which wraps the underlying native TLS implementation to support the
+Python-level thread local storage API (:class:`threading.local`). The
+CPython C level APIs are similar to those offered by pthreads and Windows:
+use a thread key and functions to associate a :c:type:`void\*` value per
+thread.
+
+The GIL does *not* need to be held when calling these functions; they supply
+their own locking.
+
+Note that :file:`Python.h` does not include the declaration of the TLS APIs,
+you need to include :file:`pythread.h` to use thread-local storage.
+
+.. note::
+ None of these API functions handle memory management on behalf of the
+ :c:type:`void\*` values. You need to allocate and deallocate them yourself.
+ If the :c:type:`void\*` values happen to be :c:type:`PyObject\*`, these
+ functions don't do refcount operations on them either.
+
+.. _thread-specific-storage-api:
+
+Thread Specific Storage (TSS) API
+---------------------------------
+
+TSS API is introduced to supersede the use of the existing TLS API within the
+CPython interpreter. This API uses a new type :c:type:`Py_tss_t` instead of
+:c:type:`int` to represent thread keys.
+
+.. versionadded:: 3.7
+
+.. seealso:: "A New C-API for Thread-Local Storage in CPython" (:pep:`539`)
+
+
+.. c:type:: Py_tss_t
+
+ This data structure represents the state of a thread key, the definition of
+ which may depend on the underlying TLS implementation, and it has an
+ internal field representing the key's initialization state. There are no
+ public members in this structure.
+
+ When :ref:`Py_LIMITED_API <stable>` is not defined, static allocation of
+ this type by :c:macro:`Py_tss_NEEDS_INIT` is allowed.
+
+
+.. c:macro:: Py_tss_NEEDS_INIT
+
+ This macro expands to the default value for :c:type:`Py_tss_t` variables.
+ Note that this macro won't be defined with :ref:`Py_LIMITED_API <stable>`.
+
+
+Dynamic Allocation
+~~~~~~~~~~~~~~~~~~
+
+Dynamic allocation of the :c:type:`Py_tss_t`, required in extension modules
+built with :ref:`Py_LIMITED_API <stable>`, where static allocation of this type
+is not possible due to its implementation being opaque at build time.
+
+
+.. c:function:: Py_tss_t* PyThread_tss_alloc()
+
+ Return a value which is the same state as a value initialized with
+ :c:macro:`Py_tss_NEEDS_INIT`, or *NULL* in the case of dynamic allocation
+ failure.
+
+
+.. c:function:: void PyThread_tss_free(Py_tss_t *key)
+
+ Free the given *key* allocated by :c:func:`PyThread_tss_alloc`, after
+ first calling :c:func:`PyThread_tss_delete` to ensure any associated
+ thread locals have been unassigned. This is a no-op if the *key*
+ argument is `NULL`.
+
+ .. note::
+ A freed key becomes a dangling pointer, you should reset the key to
+ `NULL`.
+
+
+Methods
+~~~~~~~
+
+The parameter *key* of these functions must not be *NULL*. Moreover, the
+behaviors of :c:func:`PyThread_tss_set` and :c:func:`PyThread_tss_get` are
+undefined if the given :c:type:`Py_tss_t` has not been initialized by
+:c:func:`PyThread_tss_create`.
+
+
+.. c:function:: int PyThread_tss_is_created(Py_tss_t *key)
+
+ Return a non-zero value if the given :c:type:`Py_tss_t` has been initialized
+ by :c:func:`PyThread_tss_create`.
+
+
+.. c:function:: int PyThread_tss_create(Py_tss_t *key)
+
+ Return a zero value on successful initialization of a TSS key. The behavior
+ is undefined if the value pointed to by the *key* argument is not
+ initialized by :c:macro:`Py_tss_NEEDS_INIT`. This function can be called
+ repeatedly on the same key -- calling it on an already initialized key is a
+ no-op and immediately returns success.
+
+
+.. c:function:: void PyThread_tss_delete(Py_tss_t *key)
+
+ Destroy a TSS key to forget the values associated with the key across all
+ threads, and change the key's initialization state to uninitialized. A
+ destroyed key is able to be initialized again by
+ :c:func:`PyThread_tss_create`. This function can be called repeatedly on
+ the same key -- calling it on an already destroyed key is a no-op.
+
+
+.. c:function:: int PyThread_tss_set(Py_tss_t *key, void *value)
+
+ Return a zero value to indicate successfully associating a :c:type:`void\*`
+ value with a TSS key in the current thread. Each thread has a distinct
+ mapping of the key to a :c:type:`void\*` value.
+
+
+.. c:function:: void* PyThread_tss_get(Py_tss_t *key)
+
+ Return the :c:type:`void\*` value associated with a TSS key in the current
+ thread. This returns *NULL* if no value is associated with the key in the
+ current thread.
+
+
+.. _thread-local-storage-api:
+
+Thread Local Storage (TLS) API
+------------------------------
+
+.. deprecated:: 3.7
+ This API is superseded by
+ :ref:`Thread Specific Storage (TSS) API <thread-specific-storage-api>`.
+
+.. note::
+ This version of the API does not support platforms where the native TLS key
+ is defined in a way that cannot be safely cast to ``int``. On such platforms,
+ :c:func:`PyThread_create_key` will return immediately with a failure status,
+ and the other TLS functions will all be no-ops on such platforms.
+
+Due to the compatibility problem noted above, this version of the API should not
+be used in new code.
+
+.. c:function:: int PyThread_create_key()
+.. c:function:: void PyThread_delete_key(int key)
+.. c:function:: int PyThread_set_key_value(int key, void *value)
+.. c:function:: void* PyThread_get_key_value(int key)
+.. c:function:: void PyThread_delete_key_value(int key)
+.. c:function:: void PyThread_ReInitTLS()
+
diff --git a/Doc/whatsnew/3.7.rst b/Doc/whatsnew/3.7.rst
index 3e8617ef2a1..ecdd2fe2713 100644
--- a/Doc/whatsnew/3.7.rst
+++ b/Doc/whatsnew/3.7.rst
@@ -127,6 +127,38 @@ built-in ``breakpoint()``.
PEP written and implemented by Barry Warsaw
+.. _whatsnew37-pep539:
+
+PEP 539: A New C-API for Thread-Local Storage in CPython
+--------------------------------------------------------
+
+While Python provides a C API for thread-local storage support; the existing
+:ref:`Thread Local Storage (TLS) API <thread-local-storage-api>` has used
+:c:type:`int` to represent TLS keys across all platforms. This has not
+generally been a problem for officially-support platforms, but that is neither
+POSIX-compliant, nor portable in any practical sense.
+
+:pep:`539` changes this by providing a new :ref:`Thread Specific Storage (TSS)
+API <thread-specific-storage-api>` to CPython which supersedes use of the
+existing TLS API within the CPython interpreter, while deprecating the existing
+API. The TSS API uses a new type :c:type:`Py_tss_t` instead of :c:type:`int`
+to represent TSS keys--an opaque type the definition of which may depend on
+the underlying TLS implementation. Therefore, this will allow to build CPython
+on platforms where the native TLS key is defined in a way that cannot be safely
+cast to :c:type:`int`.
+
+Note that on platforms where the native TLS key is defined in a way that cannot
+be safely cast to :c:type:`int`, all functions of the existing TLS API will be
+no-op and immediately return failure. This indicates clearly that the old API
+is not supported on platforms where it cannot be used reliably, and that no
+effort will be made to add such support.
+
+.. seealso::
+
+ :pep:`539` -- A New C-API for Thread-Local Storage in CPython
+ PEP written by Erik M. Bray; implementation by Masayuki Yamamoto.
+
+
Other Language Changes
======================
diff --git a/Include/internal/pystate.h b/Include/internal/pystate.h
index 20c5946b14f..210917bb325 100644
--- a/Include/internal/pystate.h
+++ b/Include/internal/pystate.h
@@ -26,7 +26,7 @@ struct _gilstate_runtime_state {
*/
/* TODO: Given interp_main, it may be possible to kill this ref */
PyInterpreterState *autoInterpreterState;
- int autoTLSkey;
+ Py_tss_t autoTSSkey;
};
/* hook for PyEval_GetFrame(), requested for Psyco */
diff --git a/Include/pythread.h b/Include/pythread.h
index dbacb8bbbcd..d6674685f28 100644
--- a/Include/pythread.h
+++ b/Include/pythread.h
@@ -29,8 +29,8 @@ PyAPI_FUNC(unsigned long) PyThread_get_thread_ident(void);
PyAPI_FUNC(PyThread_type_lock) PyThread_allocate_lock(void);
PyAPI_FUNC(void) PyThread_free_lock(PyThread_type_lock);
PyAPI_FUNC(int) PyThread_acquire_lock(PyThread_type_lock, int);
-#define WAIT_LOCK 1
-#define NOWAIT_LOCK 0
+#define WAIT_LOCK 1
+#define NOWAIT_LOCK 0
/* PY_TIMEOUT_T is the integral type used to specify timeouts when waiting
on a lock (see PyThread_acquire_lock_timed() below).
@@ -77,15 +77,69 @@ PyAPI_FUNC(int) PyThread_set_stacksize(size_t);
PyAPI_FUNC(PyObject*) PyThread_GetInfo(void);
#endif
-/* Thread Local Storage (TLS) API */
-PyAPI_FUNC(int) PyThread_create_key(void);
-PyAPI_FUNC(void) PyThread_delete_key(int);
-PyAPI_FUNC(int) PyThread_set_key_value(int, void *);
-PyAPI_FUNC(void *) PyThread_get_key_value(int);
-PyAPI_FUNC(void) PyThread_delete_key_value(int key);
+
+/* Thread Local Storage (TLS) API
+ TLS API is DEPRECATED. Use Thread Specific Storage (TSS) API.
+
+ The existing TLS API has used int to represent TLS keys across all
+ platforms, but it is not POSIX-compliant. Therefore, the new TSS API uses
+ opaque data type to represent TSS keys to be compatible (see PEP 539).
+*/
+PyAPI_FUNC(int) PyThread_create_key(void) Py_DEPRECATED(3.7);
+PyAPI_FUNC(void) PyThread_delete_key(int key) Py_DEPRECATED(3.7);
+PyAPI_FUNC(int) PyThread_set_key_value(int key, void *value) Py_DEPRECATED(3.7);
+PyAPI_FUNC(void *) PyThread_get_key_value(int key) Py_DEPRECATED(3.7);
+PyAPI_FUNC(void) PyThread_delete_key_value(int key) Py_DEPRECATED(3.7);
/* Cleanup after a fork */
-PyAPI_FUNC(void) PyThread_ReInitTLS(void);
+PyAPI_FUNC(void) PyThread_ReInitTLS(void) Py_DEPRECATED(3.7);
+
+
+#if !defined(Py_LIMITED_API) || Py_LIMITED_API+0 >= 0x03070000
+/* New in 3.7 */
+/* Thread Specific Storage (TSS) API */
+
+typedef struct _Py_tss_t Py_tss_t; /* opaque */
+
+#ifndef Py_LIMITED_API
+#if defined(_POSIX_THREADS)
+ /* Darwin needs pthread.h to know type name the pthread_key_t. */
+# include <pthread.h>
+# define NATIVE_TSS_KEY_T pthread_key_t
+#elif defined(NT_THREADS)
+ /* In Windows, native TSS key type is DWORD,
+ but hardcode the unsigned long to avoid errors for include directive.
+ */
+# define NATIVE_TSS_KEY_T unsigned long
+#else
+# error "Require native threads. See https://bugs.python.org/issue31370"
+#endif
+
+/* When Py_LIMITED_API is not defined, the type layout of Py_tss_t is
+ exposed to allow static allocation in the API clients. Even in this case,
+ you must handle TSS keys through API functions due to compatibility.
+*/
+struct _Py_tss_t {
+ int _is_initialized;
+ NATIVE_TSS_KEY_T _key;
+};
+
+#undef NATIVE_TSS_KEY_T
+
+/* When static allocation, you must initialize with Py_tss_NEEDS_INIT. */
+#define Py_tss_NEEDS_INIT {0}
+#endif /* !Py_LIMITED_API */
+
+PyAPI_FUNC(Py_tss_t *) PyThread_tss_alloc(void);
+PyAPI_FUNC(void) PyThread_tss_free(Py_tss_t *key);
+
+/* The parameter key must not be NULL. */
+PyAPI_FUNC(int) PyThread_tss_is_created(Py_tss_t *key);
+PyAPI_FUNC(int) PyThread_tss_create(Py_tss_t *key);
+PyAPI_FUNC(void) PyThread_tss_delete(Py_tss_t *key);
+PyAPI_FUNC(int) PyThread_tss_set(Py_tss_t *key, void *value);
+PyAPI_FUNC(void *) PyThread_tss_get(Py_tss_t *key);
+#endif /* New in 3.7 */
#ifdef __cplusplus
}
diff --git a/Misc/NEWS.d/next/C API/2017-06-24-14-30-44.bpo-25658.vm8vGE.rst b/Misc/NEWS.d/next/C API/2017-06-24-14-30-44.bpo-25658.vm8vGE.rst
new file mode 100644
index 00000000000..d4bb19acc4b
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2017-06-24-14-30-44.bpo-25658.vm8vGE.rst
@@ -0,0 +1,4 @@
+Implement PEP 539 for Thread Specific Stroage (TSS) API: it is a new Thread
+Local Storage (TLS) API to CPython which would supersede use of the existing
+TLS API within the CPython interpreter, while deprecating the existing API.
+PEP written by Erik M. Bray, patch by Masayuki Yamamoto.
diff --git a/Modules/_testcapimodule.c b/Modules/_testcapimodule.c
index 1a296214739..b512c05a3fe 100644
--- a/Modules/_testcapimodule.c
+++ b/Modules/_testcapimodule.c
@@ -4306,6 +4306,61 @@ py_w_stopcode(PyObject *self, PyObject *args)
#endif
+static PyObject *
+test_pythread_tss_key_state(PyObject *self, PyObject *args)
+{
+ Py_tss_t tss_key = Py_tss_NEEDS_INIT;
+ if (PyThread_tss_is_created(&tss_key)) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "TSS key not in an uninitialized state at "
+ "creation time");
+ }
+ if (PyThread_tss_create(&tss_key) != 0) {
+ PyErr_SetString(PyExc_RuntimeError, "PyThread_tss_create failed");
+ return NULL;
+ }
+ if (!PyThread_tss_is_created(&tss_key)) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "PyThread_tss_create succeeded, "
+ "but with TSS key in an uninitialized state");
+ }
+ if (PyThread_tss_create(&tss_key) != 0) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "PyThread_tss_create unsuccessful with "
+ "an already initialized key");
+ }
+#define CHECK_TSS_API(expr) \
+ (void)(expr); \
+ if (!PyThread_tss_is_created(&tss_key)) { \
+ return raiseTestError("test_pythread_tss_key_state", \
+ "TSS key initialization state was not " \
+ "preserved after calling " #expr); }
+ CHECK_TSS_API(PyThread_tss_set(&tss_key, NULL));
+ CHECK_TSS_API(PyThread_tss_get(&tss_key));
+#undef CHECK_TSS_API
+ PyThread_tss_delete(&tss_key);
+ if (PyThread_tss_is_created(&tss_key)) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "PyThread_tss_delete called, but did not "
+ "set the key state to uninitialized");
+ }
+
+ Py_tss_t *ptr_key = PyThread_tss_alloc();
+ if (ptr_key == NULL) {
+ PyErr_SetString(PyExc_RuntimeError, "PyThread_tss_alloc failed");
+ return NULL;
+ }
+ if (PyThread_tss_is_created(ptr_key)) {
+ return raiseTestError("test_pythread_tss_key_state",
+ "TSS key not in an uninitialized state at "
+ "allocation time");
+ }
+ PyThread_tss_free(ptr_key);
+ ptr_key = NULL;
+ Py_RETURN_NONE;
+}
+
+
static PyMethodDef TestMethods[] = {
{"raise_exception", raise_exception, METH_VARARGS},
{"raise_memoryerror", (PyCFunction)raise_memoryerror, METH_NOARGS},
@@ -4518,6 +4573,7 @@ static PyMethodDef TestMethods[] = {
#ifdef W_STOPCODE
{"W_STOPCODE", py_w_stopcode, METH_VARARGS},
#endif
+ {"test_pythread_tss_key_state", test_pythread_tss_key_state, METH_VARARGS},
{NULL, NULL} /* sentinel */
};
diff --git a/Modules/_tracemalloc.c b/Modules/_tracemalloc.c
index 386f2f11ba7..af2a2fa4d52 100644
--- a/Modules/_tracemalloc.c
+++ b/Modules/_tracemalloc.c
@@ -167,14 +167,7 @@ tracemalloc_error(const char *format, ...)
#if defined(TRACE_RAW_MALLOC)
#define REENTRANT_THREADLOCAL
-/* If your OS does not provide native thread local storage, you can implement
- it manually using a lock. Functions of thread.c cannot be used because
- they use PyMem_RawMalloc() which leads to a reentrant call. */
-#if !(defined(_POSIX_THREADS) || defined(NT_THREADS))
-# error "need native thread local storage (TLS)"
-#endif
-
-static int tracemalloc_reentrant_key = -1;
+static Py_tss_t tracemalloc_reentrant_key = Py_tss_NEEDS_INIT;
/* Any non-NULL pointer can be used */
#define REENTRANT Py_True
@@ -184,8 +177,8 @@ get_reentrant(void)
{
void *ptr;
- assert(tracemalloc_reentrant_key != -1);
- ptr = PyThread_get_key_value(tracemalloc_reentrant_key);
+ assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
+ ptr = PyThread_tss_get(&tracemalloc_reentrant_key);
if (ptr != NULL) {
assert(ptr == REENTRANT);
return 1;
@@ -198,15 +191,15 @@ static void
set_reentrant(int reentrant)
{
assert(reentrant == 0 || reentrant == 1);
- assert(tracemalloc_reentrant_key != -1);
+ assert(PyThread_tss_is_created(&tracemalloc_reentrant_key));
if (reentrant) {
assert(!get_reentrant());
- PyThread_set_key_value(tracemalloc_reentrant_key, REENTRANT);
+ PyThread_tss_set(&tracemalloc_reentrant_key, REENTRANT);
}
else {
assert(get_reentrant());
- PyThread_set_key_value(tracemalloc_reentrant_key, NULL);
+ PyThread_tss_set(&tracemalloc_reentrant_key, NULL);
}
}
@@ -975,8 +968,7 @@ tracemalloc_init(void)
PyMem_GetAllocator(PYMEM_DOMAIN_RAW, &allocators.raw);
#ifdef REENTRANT_THREADLOCAL
- tracemalloc_reentrant_key = PyThread_create_key();
- if (tracemalloc_reentrant_key == -1) {
+ if (PyThread_tss_create(&tracemalloc_reentrant_key) != 0) {
#ifdef MS_WINDOWS
PyErr_SetFromWindowsErr(0);
#else
@@ -1061,8 +1053,7 @@ tracemalloc_deinit(void)
#endif
#ifdef REENTRANT_THREADLOCAL
- PyThread_delete_key(tracemalloc_reentrant_key);
- tracemalloc_reentrant_key = -1;
+ PyThread_tss_delete(&tracemalloc_reentrant_key);
#endif
Py_XDECREF(unknown_filename);
diff --git a/Modules/faulthandler.c b/Modules/faulthandler.c
index 4f3d971bc52..c2c2c537b12 100644
--- a/Modules/faulthandler.c
+++ b/Modules/faulthandler.c
@@ -232,7 +232,7 @@ faulthandler_dump_traceback(int fd, int all_threads,
PyThreadState_Get() doesn't give the state of the thread that caused the
fault if the thread released the GIL, and so this function cannot be
- used. Read the thread local storage (TLS) instead: call
+ used. Read the thread specific storage (TSS) instead: call
PyGILState_GetThisThreadState(). */
tstate = PyGILState_GetThisThreadState();
diff --git a/Modules/posixmodule.c b/Modules/posixmodule.c
index 13ff9166e71..5f30b202ec6 100644
--- a/Modules/posixmodule.c
+++ b/Modules/posixmodule.c
@@ -454,9 +454,6 @@ PyOS_AfterFork_Parent(void)
void
PyOS_AfterFork_Child(void)
{
- /* PyThread_ReInitTLS() must be called early, to make sure that the TLS API
- * can be called safely. */
- PyThread_ReInitTLS();
_PyGILState_Reinit();
PyEval_ReInitThreads();
_PyImport_ReInitLock();
diff --git a/PC/python3.def b/PC/python3.def
index ad65294045f..1d089ec28b1 100644
--- a/PC/python3.def
+++ b/PC/python3.def
@@ -570,6 +570,13 @@ EXPORTS
PyThreadState_New=python37.PyThreadState_New
PyThreadState_SetAsyncExc=python37.PyThreadState_SetAsyncExc
PyThreadState_Swap=python37.PyThreadState_Swap
+ PyThread_tss_alloc=python37.PyThread_tss_alloc
+ PyThread_tss_create=python37.PyThread_tss_create
+ PyThread_tss_delete=python37.PyThread_tss_delete
+ PyThread_tss_free=python37.PyThread_tss_free
+ PyThread_tss_get=python37.PyThread_tss_get
+ PyThread_tss_is_created=python37.PyThread_tss_is_created
+ PyThread_tss_set=python37.PyThread_tss_set
PyTraceBack_Here=python37.PyTraceBack_Here
PyTraceBack_Print=python37.PyTraceBack_Print
PyTraceBack_Type=python37.PyTraceBack_Type DATA
diff --git a/Python/pystate.c b/Python/pystate.c
index 53c12361457..3feae346d44 100644
--- a/Python/pystate.c
+++ b/Python/pystate.c
@@ -46,7 +46,12 @@ _PyRuntimeState_Init(_PyRuntimeState *runtime)
_PyEval_Initialize(&runtime->ceval);
runtime->gilstate.check_enabled = 1;
- runtime->gilstate.autoTLSkey = -1;
+ /* A TSS key must be initialized with Py_tss_NEEDS_INIT
+ in accordance with the specification. */
+ {
+ Py_tss_t initial = Py_tss_NEEDS_INIT;
+ runtime->gilstate.autoTSSkey = initial;
+ }
runtime->interpreters.mutex = PyThread_allocate_lock();
if (runtime->interpreters.mutex == NULL)
@@ -485,9 +490,9 @@ PyThreadState_Delete(PyThreadState *tstate)
if (tstate == GET_TSTATE())
Py_FatalError("PyThreadState_Delete: tstate is still current");
if (_PyRuntime.gilstate.autoInterpreterState &&
- PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == tstate)
+ PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate)
{
- PyThread_delete_key_value(_PyRuntime.gilstate.autoTLSkey);
+ PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL);
}
tstate_delete_common(tstate);
}
@@ -502,9 +507,9 @@ PyThreadState_DeleteCurrent()
"PyThreadState_DeleteCurrent: no current tstate");
tstate_delete_common(tstate);
if (_PyRuntime.gilstate.autoInterpreterState &&
- PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == tstate)
+ PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == tstate)
{
- PyThread_delete_key_value(_PyRuntime.gilstate.autoTLSkey);
+ PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, NULL);
}
SET_TSTATE(NULL);
PyEval_ReleaseLock();
@@ -761,11 +766,11 @@ void
_PyGILState_Init(PyInterpreterState *i, PyThreadState *t)
{
assert(i && t); /* must init with valid states */
- _PyRuntime.gilstate.autoTLSkey = PyThread_create_key();
- if (_PyRuntime.gilstate.autoTLSkey == -1)
- Py_FatalError("Could not allocate TLS entry");
+ if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {
+ Py_FatalError("Could not allocate TSS entry");
+ }
_PyRuntime.gilstate.autoInterpreterState = i;
- assert(PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == NULL);
+ assert(PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL);
assert(t->gilstate_counter == 0);
_PyGILState_NoteThreadState(t);
@@ -780,14 +785,13 @@ _PyGILState_GetInterpreterStateUnsafe(void)
void
_PyGILState_Fini(void)
{
- PyThread_delete_key(_PyRuntime.gilstate.autoTLSkey);
- _PyRuntime.gilstate.autoTLSkey = -1;
+ PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey);
_PyRuntime.gilstate.autoInterpreterState = NULL;
}
-/* Reset the TLS key - called by PyOS_AfterFork_Child().
+/* Reset the TSS key - called by PyOS_AfterFork_Child().
* This should not be necessary, but some - buggy - pthread implementations
- * don't reset TLS upon fork(), see issue #10517.
+ * don't reset TSS upon fork(), see issue #10517.
*/
void
_PyGILState_Reinit(void)
@@ -796,15 +800,18 @@ _PyGILState_Reinit(void)
if (_PyRuntime.interpreters.mutex == NULL)
Py_FatalError("Can't initialize threads for interpreter");
PyThreadState *tstate = PyGILState_GetThisThreadState();
- PyThread_delete_key(_PyRuntime.gilstate.autoTLSkey);
- if ((_PyRuntime.gilstate.autoTLSkey = PyThread_create_key()) == -1)
- Py_FatalError("Could not allocate TLS entry");
+ PyThread_tss_delete(&_PyRuntime.gilstate.autoTSSkey);
+ if (PyThread_tss_create(&_PyRuntime.gilstate.autoTSSkey) != 0) {
+ Py_FatalError("Could not allocate TSS entry");
+ }
/* If the thread had an associated auto thread state, reassociate it with
* the new key. */
- if (tstate && PyThread_set_key_value(_PyRuntime.gilstate.autoTLSkey,
- (void *)tstate) < 0)
- Py_FatalError("Couldn't create autoTLSkey mapping");
+ if (tstate &&
+ PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate) != 0)
+ {
+ Py_FatalError("Couldn't create autoTSSkey mapping");
+ }
}
/* When a thread state is created for a thread by some mechanism other than
@@ -815,13 +822,13 @@ _PyGILState_Reinit(void)
static void
_PyGILState_NoteThreadState(PyThreadState* tstate)
{
- /* If autoTLSkey isn't initialized, this must be the very first
+ /* If autoTSSkey isn't initialized, this must be the very first
threadstate created in Py_Initialize(). Don't do anything for now
(we'll be back here when _PyGILState_Init is called). */
if (!_PyRuntime.gilstate.autoInterpreterState)
return;
- /* Stick the thread state for this thread in thread local storage.
+ /* Stick the thread state for this thread in thread specific storage.
The only situation where you can legitimately have more than one
thread state for an OS level thread is when there are multiple
@@ -833,12 +840,11 @@ _PyGILState_NoteThreadState(PyThreadState* tstate)
The first thread state created for that given OS level thread will
"win", which seems reasonable behaviour.
*/
- if (PyThread_get_key_value(_PyRuntime.gilstate.autoTLSkey) == NULL) {
- if ((PyThread_set_key_value(_PyRuntime.gilstate.autoTLSkey,
- (void *)tstate)
- ) < 0)
+ if (PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey) == NULL) {
+ if ((PyThread_tss_set(&_PyRuntime.gilstate.autoTSSkey, (void *)tstate)
+ ) != 0)
{
- Py_FatalError("Couldn't create autoTLSkey mapping");
+ Py_FatalError("Couldn't create autoTSSkey mapping");
}
}
@@ -852,8 +858,7 @@ PyGILState_GetThisThreadState(void)
{
if (_PyRuntime.gilstate.autoInterpreterState == NULL)
return NULL;
- return (PyThreadState *)PyThread_get_key_value(
- _PyRuntime.gilstate.autoTLSkey);
+ return (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey);
}
int
@@ -864,8 +869,9 @@ PyGILState_Check(void)
if (!_PyGILState_check_enabled)
return 1;
- if (_PyRuntime.gilstate.autoTLSkey == -1)
+ if (!PyThread_tss_is_created(&_PyRuntime.gilstate.autoTSSkey)) {
return 1;
+ }
tstate = GET_TSTATE();
if (tstate == NULL)
@@ -886,8 +892,7 @@ PyGILState_Ensure(void)
*/
/* Py_Initialize() hasn't been called! */
assert(_PyRuntime.gilstate.autoInterpreterState);
- tcur = (PyThreadState *)PyThread_get_key_value(
- _PyRuntime.gilstate.autoTLSkey);
+ tcur = (PyThreadState *)PyThread_tss_get(&_PyRuntime.gilstate.autoTSSkey);
if (tcur == NULL) {
/* At startup, Python has no concrete GIL. If PyGILState_Ensure() is
called from a new thread for the first time, we need the create the
@@ -919,8 +924,8 @@ PyGILState_Ensure(void)
void
PyGILState_Release(PyGILState_STATE oldstate)
{
- PyThreadState *tcur = (PyThreadState *)PyThread_get_key_value(
- _PyRuntime.gilstate.autoTLSkey);
+ PyThreadState *tcur = (PyThreadState *)PyThread_tss_get(
+ &_PyRuntime.gilstate.autoTSSkey);
if (tcur == NULL)
Py_FatalError("auto-releasing thread-state, "
"but no thread-state for this thread");
diff --git a/Python/thread.c b/Python/thread.c
index f742d0521e1..7eac836dc16 100644
--- a/Python/thread.c
+++ b/Python/thread.c
@@ -84,7 +84,7 @@ PyThread_init_thread(void)
# define PYTHREAD_NAME "nt"
# include "thread_nt.h"
#else
-# error "Require native thread feature. See https://bugs.python.org/issue30832"
+# error "Require native threads. See https://bugs.python.org/issue31370"
#endif
@@ -111,41 +111,37 @@ PyThread_set_stacksize(size_t size)
}
-/* ------------------------------------------------------------------------
-Per-thread data ("key") support.
+/* Thread Specific Storage (TSS) API
-Use PyThread_create_key() to create a new key. This is typically shared
-across threads.
-
-Use PyThread_set_key_value(thekey, value) to associate void* value with
-thekey in the current thread. Each thread has a distinct mapping of thekey
-to a void* value. Caution: if the current thread already has a mapping
-for thekey, value is ignored.
-
-Use PyThread_get_key_value(thekey) to retrieve the void* value associated
-with thekey in the current thread. This returns NULL if no value is
-associated with thekey in the current thread.
-
-Use PyThread_delete_key_value(thekey) to forget the current thread's associated
-value for thekey. PyThread_delete_key(thekey) forgets the values associated
-with thekey across *all* threads.
-
-While some of these functions have error-return values, none set any
-Python exception.
+ Cross-platform components of TSS API implementation.
+*/
-None of the functions does memory management on behalf of the void* values.
-You need to allocate and deallocate them yourself. If the void* values
-happen to be PyObject*, these functions don't do refcount operations on
-them either.
+Py_tss_t *
+PyThread_tss_alloc(void)
+{
+ Py_tss_t *new_key = (Py_tss_t *)PyMem_RawMalloc(sizeof(Py_tss_t));
+ if (new_key == NULL) {
+ return NULL;
+ }
+ new_key->_is_initialized = 0;
+ return new_key;
+}
-The GIL does not need to be held when calling these functions; they supply
-their own locking. This isn't true of PyThread_create_key(), though (see
-next paragraph).
+void
+PyThread_tss_free(Py_tss_t *key)
+{
+ if (key != NULL) {
+ PyThread_tss_delete(key);
+ PyMem_RawFree((void *)key);
+ }
+}
-There's a hidden assumption that PyThread_create_key() will be called before
-any of the other functions are called. There's also a hidden assumption
-that calls to PyThread_create_key() are serialized externally.
------------------------------------------------------------------------- */
+int
+PyThread_tss_is_created(Py_tss_t *key)
+{
+ assert(key != NULL);
+ return key->_is_initialized;
+}
PyDoc_STRVAR(threadinfo__doc__,
diff --git a/Python/thread_nt.h b/Python/thread_nt.h
index 2f3a71b86ad..bae8bcc3566 100644
--- a/Python/thread_nt.h
+++ b/Python/thread_nt.h
@@ -349,10 +349,15 @@ _pythread_nt_set_stacksize(size_t size)
#define THREAD_SET_STACKSIZE(x) _pythread_nt_set_stacksize(x)
+/* Thread Local Storage (TLS) API
+
+ This API is DEPRECATED since Python 3.7. See PEP 539 for details.
+*/
+
int
PyThread_create_key(void)
{
- DWORD result= TlsAlloc();
+ DWORD result = TlsAlloc();
if (result == TLS_OUT_OF_INDEXES)
return -1;
return (int)result;
@@ -367,12 +372,8 @@ PyThread_delete_key(int key)
int
PyThread_set_key_value(int key, void *value)
{
- BOOL ok;
-
- ok = TlsSetValue(key, value);
- if (!ok)
- return -1;
- return 0;
+ BOOL ok = TlsSetValue(key, value);
+ return ok ? 0 : -1;
}
void *
@@ -399,9 +400,74 @@ PyThread_delete_key_value(int key)
TlsSetValue(key, NULL);
}
+
/* reinitialization of TLS is not necessary after fork when using
* the native TLS functions. And forking isn't supported on Windows either.
*/
void
PyThread_ReInitTLS(void)
-{}
+{
+}
+
+
+/* Thread Specific Storage (TSS) API
+
+ Platform-specific components of TSS API implementation.
+*/
+
+int
+PyThread_tss_create(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has been created, function is silently skipped. */
+ if (key->_is_initialized) {
+ return 0;
+ }
+
+ DWORD result = TlsAlloc();
+ if (result == TLS_OUT_OF_INDEXES) {
+ return -1;
+ }
+ /* In Windows, platform-specific key type is DWORD. */
+ key->_key = result;
+ key->_is_initialized = 1;
+ return 0;
+}
+
+void
+PyThread_tss_delete(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has not been created, function is silently skipped. */
+ if (!key->_is_initialized) {
+ return;
+ }
+
+ TlsFree(key->_key);
+ key->_key = TLS_OUT_OF_INDEXES;
+ key->_is_initialized = 0;
+}
+
+int
+PyThread_tss_set(Py_tss_t *key, void *value)
+{
+ assert(key != NULL);
+ BOOL ok = TlsSetValue(key->_key, value);
+ return ok ? 0 : -1;
+}
+
+void *
+PyThread_tss_get(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* because TSS is used in the Py_END_ALLOW_THREAD macro,
+ * it is necessary to preserve the windows error state, because
+ * it is assumed to be preserved across the call to the macro.
+ * Ideally, the macro should be fixed, but it is simpler to
+ * do it here.
+ */
+ DWORD error = GetLastError();
+ void *result = TlsGetValue(key->_key);
+ SetLastError(error);
+ return result;
+}
diff --git a/Python/thread_pthread.h b/Python/thread_pthread.h
index 2dcd107c2ce..c5b7f3256fa 100644
--- a/Python/thread_pthread.h
+++ b/Python/thread_pthread.h
@@ -589,9 +589,25 @@ _pythread_pthread_set_stacksize(size_t size)
#define THREAD_SET_STACKSIZE(x) _pythread_pthread_set_stacksize(x)
+/* Thread Local Storage (TLS) API
+
+ This API is DEPRECATED since Python 3.7. See PEP 539 for details.
+*/
+
+/* Issue #25658: On platforms where native TLS key is defined in a way that
+ cannot be safely cast to int, PyThread_create_key returns immediately a
+ failure status and other TLS functions all are no-ops. This indicates
+ clearly that the old API is not supported on platforms where it cannot be
+ used reliably, and that no effort will be made to add such support.
+
+ Note: PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT will be unnecessary after
+ removing this API.
+*/
+
int
PyThread_create_key(void)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
pthread_key_t key;
int fail = pthread_key_create(&key, NULL);
if (fail)
@@ -603,34 +619,102 @@ PyThread_create_key(void)
return -1;
}
return (int)key;
+#else
+ return -1; /* never return valid key value. */
+#endif
}
void
PyThread_delete_key(int key)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
pthread_key_delete(key);
+#endif
}
void
PyThread_delete_key_value(int key)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
pthread_setspecific(key, NULL);
+#endif
}
int
PyThread_set_key_value(int key, void *value)
{
- int fail;
- fail = pthread_setspecific(key, value);
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
+ int fail = pthread_setspecific(key, value);
return fail ? -1 : 0;
+#else
+ return -1;
+#endif
}
void *
PyThread_get_key_value(int key)
{
+#ifdef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
return pthread_getspecific(key);
+#else
+ return NULL;
+#endif
}
+
void
PyThread_ReInitTLS(void)
-{}
+{
+}
+
+
+/* Thread Specific Storage (TSS) API
+
+ Platform-specific components of TSS API implementation.
+*/
+
+int
+PyThread_tss_create(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has been created, function is silently skipped. */
+ if (key->_is_initialized) {
+ return 0;
+ }
+
+ int fail = pthread_key_create(&(key->_key), NULL);
+ if (fail) {
+ return -1;
+ }
+ key->_is_initialized = 1;
+ return 0;
+}
+
+void
+PyThread_tss_delete(Py_tss_t *key)
+{
+ assert(key != NULL);
+ /* If the key has not been created, function is silently skipped. */
+ if (!key->_is_initialized) {
+ return;
+ }
+
+ pthread_key_delete(key->_key);
+ /* pthread has not provided the defined invalid value for the key. */
+ key->_is_initialized = 0;
+}
+
+int
+PyThread_tss_set(Py_tss_t *key, void *value)
+{
+ assert(key != NULL);
+ int fail = pthread_setspecific(key->_key, value);
+ return fail ? -1 : 0;
+}
+
+void *
+PyThread_tss_get(Py_tss_t *key)
+{
+ assert(key != NULL);
+ return pthread_getspecific(key->_key);
+}
diff --git a/Python/traceback.c b/Python/traceback.c
index ba979aad8fa..21b36b14719 100644
--- a/Python/traceback.c
+++ b/Python/traceback.c
@@ -760,7 +760,7 @@ _Py_DumpTracebackThreads(int fd, PyInterpreterState *interp,
PyThreadState_Get() doesn't give the state of the thread that caused
the fault if the thread released the GIL, and so this function
- cannot be used. Read the thread local storage (TLS) instead: call
+ cannot be used. Read the thread specific storage (TSS) instead: call
PyGILState_GetThisThreadState(). */
current_tstate = PyGILState_GetThisThreadState();
}
diff --git a/configure b/configure
index 2d1bed22476..741a834ab38 100755
--- a/configure
+++ b/configure
@@ -8884,6 +8884,75 @@ _ACEOF
fi
+
+# Issue #25658: POSIX hasn't defined that pthread_key_t is compatible with int.
+# This checking will be unnecessary after removing deprecated TLS API.
+# The cast to long int works around a bug in the HP C Compiler
+# version HP92453-01 B.11.11.23709.GP, which incorrectly rejects
+# declarations like `int a3[[(sizeof (unsigned char)) >= 0]];'.
+# This bug is HP SR number 8606223364.
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking size of pthread_key_t" >&5
+$as_echo_n "checking size of pthread_key_t... " >&6; }
+if ${ac_cv_sizeof_pthread_key_t+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ if ac_fn_c_compute_int "$LINENO" "(long int) (sizeof (pthread_key_t))" "ac_cv_sizeof_pthread_key_t" "#include <pthread.h>
+"; then :
+
+else
+ if test "$ac_cv_type_pthread_key_t" = yes; then
+ { { $as_echo "$as_me:${as_lineno-$LINENO}: error: in \`$ac_pwd':" >&5
+$as_echo "$as_me: error: in \`$ac_pwd':" >&2;}
+as_fn_error 77 "cannot compute sizeof (pthread_key_t)
+See \`config.log' for more details" "$LINENO" 5; }
+ else
+ ac_cv_sizeof_pthread_key_t=0
+ fi
+fi
+
+fi
+{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_sizeof_pthread_key_t" >&5
+$as_echo "$ac_cv_sizeof_pthread_key_t" >&6; }
+
+
+
+cat >>confdefs.h <<_ACEOF
+#define SIZEOF_PTHREAD_KEY_T $ac_cv_sizeof_pthread_key_t
+_ACEOF
+
+
+{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether pthread_key_t is compatible with int" >&5
+$as_echo_n "checking whether pthread_key_t is compatible with int... " >&6; }
+if test "$ac_cv_sizeof_pthread_key_t" -eq "$ac_cv_sizeof_int" ; then
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+#include <pthread.h>
+int
+main ()
+{
+pthread_key_t k; k * 1;
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_compile "$LINENO"; then :
+ ac_pthread_key_t_is_arithmetic_type=yes
+else
+ ac_pthread_key_t_is_arithmetic_type=no
+
+fi
+rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_pthread_key_t_is_arithmetic_type" >&5
+$as_echo "$ac_pthread_key_t_is_arithmetic_type" >&6; }
+ if test "$ac_pthread_key_t_is_arithmetic_type" = yes ; then
+
+$as_echo "#define PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT 1" >>confdefs.h
+
+ fi
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+$as_echo "no" >&6; }
+fi
CC="$ac_save_cc"
diff --git a/configure.ac b/configure.ac
index b562fe405a4..a3114be7387 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2263,6 +2263,25 @@ if test "$have_pthread_t" = yes ; then
#endif
])
fi
+
+# Issue #25658: POSIX hasn't defined that pthread_key_t is compatible with int.
+# This checking will be unnecessary after removing deprecated TLS API.
+AC_CHECK_SIZEOF(pthread_key_t, [], [[#include <pthread.h>]])
+AC_MSG_CHECKING(whether pthread_key_t is compatible with int)
+if test "$ac_cv_sizeof_pthread_key_t" -eq "$ac_cv_sizeof_int" ; then
+ AC_COMPILE_IFELSE(
+ [AC_LANG_PROGRAM([[#include <pthread.h>]], [[pthread_key_t k; k * 1;]])],
+ [ac_pthread_key_t_is_arithmetic_type=yes],
+ [ac_pthread_key_t_is_arithmetic_type=no]
+ )
+ AC_MSG_RESULT($ac_pthread_key_t_is_arithmetic_type)
+ if test "$ac_pthread_key_t_is_arithmetic_type" = yes ; then
+ AC_DEFINE(PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT, 1,
+ [Define if pthread_key_t is compatible with int.])
+ fi
+else
+ AC_MSG_RESULT(no)
+fi
CC="$ac_save_cc"
AC_SUBST(OTHER_LIBTOOL_OPT)
diff --git a/pyconfig.h.in b/pyconfig.h.in
index 637341afee3..7f0c6b33a95 100644
--- a/pyconfig.h.in
+++ b/pyconfig.h.in
@@ -1241,6 +1241,9 @@
/* Define if POSIX semaphores aren't enabled on your system */
#undef POSIX_SEMAPHORES_NOT_ENABLED
+/* Define if pthread_key_t is compatible with int. */
+#undef PTHREAD_KEY_T_IS_COMPATIBLE_WITH_INT
+
/* Defined if PTHREAD_SCOPE_SYSTEM supported. */
#undef PTHREAD_SYSTEM_SCHED_SUPPORTED
@@ -1302,6 +1305,9 @@
/* The size of `pid_t', as computed by sizeof. */
#undef SIZEOF_PID_T
+/* The size of `pthread_key_t', as computed by sizeof. */
+#undef SIZEOF_PTHREAD_KEY_T
+
/* The size of `pthread_t', as computed by sizeof. */
#undef SIZEOF_PTHREAD_T
1
0
results for 4243df51fe43 on branch "default"
--------------------------------------------
test_collections leaked [-7, 1, 0] memory blocks, sum=-6
test_functools leaked [0, 3, 1] memory blocks, sum=4
test_multiprocessing_forkserver leaked [-1, 1, -2] memory blocks, sum=-2
Command line was: ['./python', '-m', 'test.regrtest', '-uall', '-R', '3:3:/home/psf-users/antoine/refleaks/reflogGu6uli', '--timeout', '7200']
1
0
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
bpo-31708: Allow async generator expressions in synchronous functions (#3905)
by Yury Selivanov Oct. 6, 2017
by Yury Selivanov Oct. 6, 2017
Oct. 6, 2017
https://github.com/python/cpython/commit/b8ab9d3fc816f85f4d6dbef12b7414e6dc…
commit: b8ab9d3fc816f85f4d6dbef12b7414e6dc10e4dd
branch: master
author: Yury Selivanov <yury(a)magic.io>
committer: GitHub <noreply(a)github.com>
date: 2017-10-06T02:58:28-04:00
summary:
bpo-31708: Allow async generator expressions in synchronous functions (#3905)
files:
A Misc/NEWS.d/next/Core and Builtins/2017-10-06-02-10-48.bpo-31708.66CCVU.rst
M Doc/reference/expressions.rst
M Lib/test/test_asyncgen.py
M Lib/test/test_coroutines.py
M Python/compile.c
diff --git a/Doc/reference/expressions.rst b/Doc/reference/expressions.rst
index 094b92841e2..1cff8a52df9 100644
--- a/Doc/reference/expressions.rst
+++ b/Doc/reference/expressions.rst
@@ -326,14 +326,16 @@ range(10) for y in bar(x))``.
The parentheses can be omitted on calls with only one argument. See section
:ref:`calls` for details.
-Since Python 3.6, if the generator appears in an :keyword:`async def` function,
-then :keyword:`async for` clauses and :keyword:`await` expressions are permitted
-as with an asynchronous comprehension. If a generator expression
-contains either :keyword:`async for` clauses or :keyword:`await` expressions
-it is called an :dfn:`asynchronous generator expression`.
-An asynchronous generator expression yields a new asynchronous
-generator object, which is an asynchronous iterator
-(see :ref:`async-iterators`).
+If a generator expression contains either :keyword:`async for`
+clauses or :keyword:`await` expressions it is called an
+:dfn:`asynchronous generator expression`. An asynchronous generator
+expression returns a new asynchronous generator object,
+which is an asynchronous iterator (see :ref:`async-iterators`).
+
+.. versionchanged:: 3.7
+ Prior to Python 3.7, asynchronous generator expressions could
+ only appear in :keyword:`async def` coroutines. Starting
+ with 3.7, any function can use asynchronous generator expressions.
.. _yieldexpr:
diff --git a/Lib/test/test_asyncgen.py b/Lib/test/test_asyncgen.py
index 8c69d2bf45d..5a36423dc97 100644
--- a/Lib/test/test_asyncgen.py
+++ b/Lib/test/test_asyncgen.py
@@ -1037,5 +1037,37 @@ def logger(loop, context):
t.cancel()
self.loop.run_until_complete(asyncio.sleep(0.1, loop=self.loop))
+ def test_async_gen_expression_01(self):
+ async def arange(n):
+ for i in range(n):
+ await asyncio.sleep(0.01, loop=self.loop)
+ yield i
+
+ def make_arange(n):
+ # This syntax is legal starting with Python 3.7
+ return (i * 2 async for i in arange(n))
+
+ async def run():
+ return [i async for i in make_arange(10)]
+
+ res = self.loop.run_until_complete(run())
+ self.assertEqual(res, [i * 2 for i in range(10)])
+
+ def test_async_gen_expression_02(self):
+ async def wrap(n):
+ await asyncio.sleep(0.01, loop=self.loop)
+ return n
+
+ def make_arange(n):
+ # This syntax is legal starting with Python 3.7
+ return (i * 2 for i in range(n) if await wrap(i))
+
+ async def run():
+ return [i async for i in make_arange(10)]
+
+ res = self.loop.run_until_complete(run())
+ self.assertEqual(res, [i * 2 for i in range(1, 10)])
+
+
if __name__ == "__main__":
unittest.main()
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index 08035173d99..d7d38a3bf9d 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -150,6 +150,14 @@ def bar():
""",
"""def bar():
+ {i: i async for i in els}
+ """,
+
+ """def bar():
+ {i async for i in els}
+ """,
+
+ """def bar():
[await i for i in els]
""",
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-06-02-10-48.bpo-31708.66CCVU.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-06-02-10-48.bpo-31708.66CCVU.rst
new file mode 100644
index 00000000000..f732fee755e
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-06-02-10-48.bpo-31708.66CCVU.rst
@@ -0,0 +1 @@
+Allow use of asynchronous generator expressions in synchronous functions.
diff --git a/Python/compile.c b/Python/compile.c
index 431e7531e84..58a708ce23e 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -3974,7 +3974,7 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
is_async_generator = c->u->u_ste->ste_coroutine;
- if (is_async_generator && !is_async_function) {
+ if (is_async_generator && !is_async_function && type != COMP_GENEXP) {
if (e->lineno > c->u->u_lineno) {
c->u->u_lineno = e->lineno;
c->u->u_lineno_set = 0;
1
0
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
Oct. 6, 2017
https://github.com/python/cpython/commit/faa135acbfcd55f79fb97f7525c8aa6f5a…
commit: faa135acbfcd55f79fb97f7525c8aa6f5a5b6a22
branch: master
author: Yury Selivanov <yury(a)magic.io>
committer: GitHub <noreply(a)github.com>
date: 2017-10-06T02:08:57-04:00
summary:
bpo-31709: Drop support for asynchronous __aiter__. (#3903)
files:
A Misc/NEWS.d/next/Core and Builtins/2017-10-06-00-27-04.bpo-31709._PmU51.rst
M Doc/reference/datamodel.rst
M Include/genobject.h
M Lib/asyncio/streams.py
M Lib/test/test_collections.py
M Lib/test/test_coroutines.py
M Objects/genobject.c
M Python/ceval.c
M Python/compile.c
diff --git a/Doc/reference/datamodel.rst b/Doc/reference/datamodel.rst
index 31a7671f55f..153b58b4fbf 100644
--- a/Doc/reference/datamodel.rst
+++ b/Doc/reference/datamodel.rst
@@ -2520,9 +2520,8 @@ generators, coroutines do not directly support iteration.
Asynchronous Iterators
----------------------
-An *asynchronous iterable* is able to call asynchronous code in its
-``__aiter__`` implementation, and an *asynchronous iterator* can call
-asynchronous code in its ``__anext__`` method.
+An *asynchronous iterator* can call asynchronous code in
+its ``__anext__`` method.
Asynchronous iterators can be used in an :keyword:`async for` statement.
@@ -2552,48 +2551,14 @@ An example of an asynchronous iterable object::
.. versionadded:: 3.5
-.. note::
+.. versionchanged:: 3.7
+ Prior to Python 3.7, ``__aiter__`` could return an *awaitable*
+ that would resolve to an
+ :term:`asynchronous iterator <asynchronous iterator>`.
- .. versionchanged:: 3.5.2
- Starting with CPython 3.5.2, ``__aiter__`` can directly return
- :term:`asynchronous iterators <asynchronous iterator>`. Returning
- an :term:`awaitable` object will result in a
- :exc:`PendingDeprecationWarning`.
-
- The recommended way of writing backwards compatible code in
- CPython 3.5.x is to continue returning awaitables from
- ``__aiter__``. If you want to avoid the PendingDeprecationWarning
- and keep the code backwards compatible, the following decorator
- can be used::
-
- import functools
- import sys
-
- if sys.version_info < (3, 5, 2):
- def aiter_compat(func):
- @functools.wraps(func)
- async def wrapper(self):
- return func(self)
- return wrapper
- else:
- def aiter_compat(func):
- return func
-
- Example::
-
- class AsyncIterator:
-
- @aiter_compat
- def __aiter__(self):
- return self
-
- async def __anext__(self):
- ...
-
- Starting with CPython 3.6, the :exc:`PendingDeprecationWarning`
- will be replaced with the :exc:`DeprecationWarning`.
- In CPython 3.7, returning an awaitable from ``__aiter__`` will
- result in a :exc:`RuntimeError`.
+ Starting with Python 3.7, ``__aiter__`` must return an
+ asynchronous iterator object. Returning anything else
+ will result in a :exc:`TypeError` error.
.. _async-context-managers:
diff --git a/Include/genobject.h b/Include/genobject.h
index 8c1825fc070..b9db9f9c1c4 100644
--- a/Include/genobject.h
+++ b/Include/genobject.h
@@ -56,7 +56,6 @@ PyAPI_DATA(PyTypeObject) PyCoro_Type;
PyAPI_DATA(PyTypeObject) _PyCoroWrapper_Type;
PyAPI_DATA(PyTypeObject) _PyAIterWrapper_Type;
-PyObject *_PyAIterWrapper_New(PyObject *aiter);
#define PyCoro_CheckExact(op) (Py_TYPE(op) == &PyCoro_Type)
PyObject *_PyCoro_GetAwaitableIter(PyObject *o);
diff --git a/Lib/asyncio/streams.py b/Lib/asyncio/streams.py
index a82cc79acaa..9fda8537686 100644
--- a/Lib/asyncio/streams.py
+++ b/Lib/asyncio/streams.py
@@ -676,20 +676,12 @@ def readexactly(self, n):
self._maybe_resume_transport()
return data
- if compat.PY35:
- @coroutine
- def __aiter__(self):
- return self
-
- @coroutine
- def __anext__(self):
- val = yield from self.readline()
- if val == b'':
- raise StopAsyncIteration
- return val
-
- if compat.PY352:
- # In Python 3.5.2 and greater, __aiter__ should return
- # the asynchronous iterator directly.
- def __aiter__(self):
- return self
+ def __aiter__(self):
+ return self
+
+ @coroutine
+ def __anext__(self):
+ val = yield from self.readline()
+ if val == b'':
+ raise StopAsyncIteration
+ return val
diff --git a/Lib/test/test_collections.py b/Lib/test/test_collections.py
index 75defa12739..7e106affbe0 100644
--- a/Lib/test/test_collections.py
+++ b/Lib/test/test_collections.py
@@ -660,7 +660,7 @@ def __hash__(self):
def test_AsyncIterable(self):
class AI:
- async def __aiter__(self):
+ def __aiter__(self):
return self
self.assertTrue(isinstance(AI(), AsyncIterable))
self.assertTrue(issubclass(AI, AsyncIterable))
@@ -674,7 +674,7 @@ class AI:
def test_AsyncIterator(self):
class AI:
- async def __aiter__(self):
+ def __aiter__(self):
return self
async def __anext__(self):
raise StopAsyncIteration
diff --git a/Lib/test/test_coroutines.py b/Lib/test/test_coroutines.py
index ebd880bab0c..08035173d99 100644
--- a/Lib/test/test_coroutines.py
+++ b/Lib/test/test_coroutines.py
@@ -1382,7 +1382,7 @@ class AsyncIter:
def __init__(self):
self.i = 0
- async def __aiter__(self):
+ def __aiter__(self):
nonlocal aiter_calls
aiter_calls += 1
return self
@@ -1401,9 +1401,8 @@ def __init__(self):
buffer = []
async def test1():
- with self.assertWarnsRegex(DeprecationWarning, "legacy"):
- async for i1, i2 in AsyncIter():
- buffer.append(i1 + i2)
+ async for i1, i2 in AsyncIter():
+ buffer.append(i1 + i2)
yielded, _ = run_async(test1())
# Make sure that __aiter__ was called only once
@@ -1415,13 +1414,12 @@ def __init__(self):
buffer = []
async def test2():
nonlocal buffer
- with self.assertWarnsRegex(DeprecationWarning, "legacy"):
- async for i in AsyncIter():
- buffer.append(i[0])
- if i[0] == 20:
- break
- else:
- buffer.append('what?')
+ async for i in AsyncIter():
+ buffer.append(i[0])
+ if i[0] == 20:
+ break
+ else:
+ buffer.append('what?')
buffer.append('end')
yielded, _ = run_async(test2())
@@ -1434,13 +1432,12 @@ def __init__(self):
buffer = []
async def test3():
nonlocal buffer
- with self.assertWarnsRegex(DeprecationWarning, "legacy"):
- async for i in AsyncIter():
- if i[0] > 20:
- continue
- buffer.append(i[0])
- else:
- buffer.append('what?')
+ async for i in AsyncIter():
+ if i[0] > 20:
+ continue
+ buffer.append(i[0])
+ else:
+ buffer.append('what?')
buffer.append('end')
yielded, _ = run_async(test3())
@@ -1479,7 +1476,7 @@ def __aiter__(self):
with self.assertRaisesRegex(
TypeError,
- r"async for' received an invalid object.*__aiter.*\: I"):
+ r"that does not implement __anext__"):
run_async(foo())
@@ -1508,25 +1505,6 @@ def __anext__(self):
self.assertEqual(sys.getrefcount(aiter), refs_before)
- def test_for_5(self):
- class I:
- async def __aiter__(self):
- return self
-
- def __anext__(self):
- return 123
-
- async def foo():
- with self.assertWarnsRegex(DeprecationWarning, "legacy"):
- async for i in I():
- print('never going to happen')
-
- with self.assertRaisesRegex(
- TypeError,
- "async for' received an invalid object.*__anext.*int"):
-
- run_async(foo())
-
def test_for_6(self):
I = 0
@@ -1622,13 +1600,12 @@ def __aiter__(self):
def test_for_7(self):
CNT = 0
class AI:
- async def __aiter__(self):
+ def __aiter__(self):
1/0
async def foo():
nonlocal CNT
- with self.assertWarnsRegex(DeprecationWarning, "legacy"):
- async for i in AI():
- CNT += 1
+ async for i in AI():
+ CNT += 1
CNT += 10
with self.assertRaises(ZeroDivisionError):
run_async(foo())
@@ -1652,37 +1629,6 @@ def __aiter__(self):
run_async(foo())
self.assertEqual(CNT, 0)
- def test_for_9(self):
- # Test that DeprecationWarning can safely be converted into
- # an exception (__aiter__ should not have a chance to raise
- # a ZeroDivisionError.)
- class AI:
- async def __aiter__(self):
- 1/0
- async def foo():
- async for i in AI():
- pass
-
- with self.assertRaises(DeprecationWarning):
- with warnings.catch_warnings():
- warnings.simplefilter("error")
- run_async(foo())
-
- def test_for_10(self):
- # Test that DeprecationWarning can safely be converted into
- # an exception.
- class AI:
- async def __aiter__(self):
- pass
- async def foo():
- async for i in AI():
- pass
-
- with self.assertRaises(DeprecationWarning):
- with warnings.catch_warnings():
- warnings.simplefilter("error")
- run_async(foo())
-
def test_for_11(self):
class F:
def __aiter__(self):
@@ -1703,24 +1649,6 @@ def __await__(self):
err = c.exception
self.assertIsInstance(err.__cause__, ZeroDivisionError)
- def test_for_12(self):
- class F:
- def __aiter__(self):
- return self
- def __await__(self):
- 1 / 0
-
- async def main():
- async for _ in F():
- pass
-
- with self.assertRaisesRegex(TypeError,
- 'an invalid object from __aiter__') as c:
- main().send(None)
-
- err = c.exception
- self.assertIsInstance(err.__cause__, ZeroDivisionError)
-
def test_for_tuple(self):
class Done(Exception): pass
diff --git a/Misc/NEWS.d/next/Core and Builtins/2017-10-06-00-27-04.bpo-31709._PmU51.rst b/Misc/NEWS.d/next/Core and Builtins/2017-10-06-00-27-04.bpo-31709._PmU51.rst
new file mode 100644
index 00000000000..6c342eacae3
--- /dev/null
+++ b/Misc/NEWS.d/next/Core and Builtins/2017-10-06-00-27-04.bpo-31709._PmU51.rst
@@ -0,0 +1 @@
+Drop support of asynchronous __aiter__.
diff --git a/Objects/genobject.c b/Objects/genobject.c
index 1a8c37abf23..5d5798c2f48 100644
--- a/Objects/genobject.c
+++ b/Objects/genobject.c
@@ -1141,100 +1141,6 @@ PyCoro_New(PyFrameObject *f, PyObject *name, PyObject *qualname)
}
-/* __aiter__ wrapper; see http://bugs.python.org/issue27243 for details. */
-
-typedef struct {
- PyObject_HEAD
- PyObject *ags_aiter;
-} PyAIterWrapper;
-
-
-static PyObject *
-aiter_wrapper_iternext(PyAIterWrapper *aw)
-{
- _PyGen_SetStopIterationValue(aw->ags_aiter);
- return NULL;
-}
-
-static int
-aiter_wrapper_traverse(PyAIterWrapper *aw, visitproc visit, void *arg)
-{
- Py_VISIT((PyObject *)aw->ags_aiter);
- return 0;
-}
-
-static void
-aiter_wrapper_dealloc(PyAIterWrapper *aw)
-{
- _PyObject_GC_UNTRACK((PyObject *)aw);
- Py_CLEAR(aw->ags_aiter);
- PyObject_GC_Del(aw);
-}
-
-static PyAsyncMethods aiter_wrapper_as_async = {
- PyObject_SelfIter, /* am_await */
- 0, /* am_aiter */
- 0 /* am_anext */
-};
-
-PyTypeObject _PyAIterWrapper_Type = {
- PyVarObject_HEAD_INIT(&PyType_Type, 0)
- "aiter_wrapper",
- sizeof(PyAIterWrapper), /* tp_basicsize */
- 0, /* tp_itemsize */
- (destructor)aiter_wrapper_dealloc, /* destructor tp_dealloc */
- 0, /* tp_print */
- 0, /* tp_getattr */
- 0, /* tp_setattr */
- &aiter_wrapper_as_async, /* tp_as_async */
- 0, /* tp_repr */
- 0, /* tp_as_number */
- 0, /* tp_as_sequence */
- 0, /* tp_as_mapping */
- 0, /* tp_hash */
- 0, /* tp_call */
- 0, /* tp_str */
- PyObject_GenericGetAttr, /* tp_getattro */
- 0, /* tp_setattro */
- 0, /* tp_as_buffer */
- Py_TPFLAGS_DEFAULT | Py_TPFLAGS_HAVE_GC, /* tp_flags */
- "A wrapper object for __aiter__ bakwards compatibility.",
- (traverseproc)aiter_wrapper_traverse, /* tp_traverse */
- 0, /* tp_clear */
- 0, /* tp_richcompare */
- 0, /* tp_weaklistoffset */
- PyObject_SelfIter, /* tp_iter */
- (iternextfunc)aiter_wrapper_iternext, /* tp_iternext */
- 0, /* tp_methods */
- 0, /* tp_members */
- 0, /* tp_getset */
- 0, /* tp_base */
- 0, /* tp_dict */
- 0, /* tp_descr_get */
- 0, /* tp_descr_set */
- 0, /* tp_dictoffset */
- 0, /* tp_init */
- 0, /* tp_alloc */
- 0, /* tp_new */
- 0, /* tp_free */
-};
-
-
-PyObject *
-_PyAIterWrapper_New(PyObject *aiter)
-{
- PyAIterWrapper *aw = PyObject_GC_New(PyAIterWrapper,
- &_PyAIterWrapper_Type);
- if (aw == NULL) {
- return NULL;
- }
- Py_INCREF(aiter);
- aw->ags_aiter = aiter;
- _PyObject_GC_TRACK(aw);
- return (PyObject *)aw;
-}
-
-
/* ========= Asynchronous Generators ========= */
diff --git a/Python/ceval.c b/Python/ceval.c
index cf0c6c9ae2f..86ffec42b31 100644
--- a/Python/ceval.c
+++ b/Python/ceval.c
@@ -1708,7 +1708,6 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
TARGET(GET_AITER) {
unaryfunc getter = NULL;
PyObject *iter = NULL;
- PyObject *awaitable = NULL;
PyObject *obj = TOP();
PyTypeObject *type = Py_TYPE(obj);
@@ -1735,57 +1734,20 @@ _PyEval_EvalFrameDefault(PyFrameObject *f, int throwflag)
goto error;
}
- if (Py_TYPE(iter)->tp_as_async != NULL &&
- Py_TYPE(iter)->tp_as_async->am_anext != NULL) {
-
- /* Starting with CPython 3.5.2 __aiter__ should return
- asynchronous iterators directly (not awaitables that
- resolve to asynchronous iterators.)
-
- Therefore, we check if the object that was returned
- from __aiter__ has an __anext__ method. If it does,
- we wrap it in an awaitable that resolves to `iter`.
+ if (Py_TYPE(iter)->tp_as_async == NULL ||
+ Py_TYPE(iter)->tp_as_async->am_anext == NULL) {
- See http://bugs.python.org/issue27243 for more
- details.
- */
-
- PyObject *wrapper = _PyAIterWrapper_New(iter);
- Py_DECREF(iter);
- SET_TOP(wrapper);
- DISPATCH();
- }
-
- awaitable = _PyCoro_GetAwaitableIter(iter);
- if (awaitable == NULL) {
- _PyErr_FormatFromCause(
+ SET_TOP(NULL);
+ PyErr_Format(
PyExc_TypeError,
- "'async for' received an invalid object "
- "from __aiter__: %.100s",
+ "'async for' received an object from __aiter__ "
+ "that does not implement __anext__: %.100s",
Py_TYPE(iter)->tp_name);
-
- SET_TOP(NULL);
Py_DECREF(iter);
goto error;
- } else {
- Py_DECREF(iter);
-
- if (PyErr_WarnFormat(
- PyExc_DeprecationWarning, 1,
- "'%.100s' implements legacy __aiter__ protocol; "
- "__aiter__ should return an asynchronous "
- "iterator, not awaitable",
- type->tp_name))
- {
- /* Warning was converted to an error. */
- Py_DECREF(awaitable);
- SET_TOP(NULL);
- goto error;
- }
}
- SET_TOP(awaitable);
- PREDICT(LOAD_CONST);
+ SET_TOP(iter);
DISPATCH();
}
diff --git a/Python/compile.c b/Python/compile.c
index df5070aad2a..431e7531e84 100644
--- a/Python/compile.c
+++ b/Python/compile.c
@@ -2298,8 +2298,6 @@ compiler_async_for(struct compiler *c, stmt_ty s)
VISIT(c, expr, s->v.AsyncFor.iter);
ADDOP(c, GET_AITER);
- ADDOP_O(c, LOAD_CONST, Py_None, consts);
- ADDOP(c, YIELD_FROM);
compiler_use_next_block(c, try);
@@ -3867,8 +3865,6 @@ compiler_async_comprehension_generator(struct compiler *c,
/* Sub-iter - calculate on the fly */
VISIT(c, expr, gen->iter);
ADDOP(c, GET_AITER);
- ADDOP_O(c, LOAD_CONST, Py_None, consts);
- ADDOP(c, YIELD_FROM);
}
compiler_use_next_block(c, try);
@@ -4033,8 +4029,6 @@ compiler_comprehension(struct compiler *c, expr_ty e, int type,
if (outermost->is_async) {
ADDOP(c, GET_AITER);
- ADDOP_O(c, LOAD_CONST, Py_None, consts);
- ADDOP(c, YIELD_FROM);
} else {
ADDOP(c, GET_ITER);
}
1
0
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
Oct. 6, 2017
https://github.com/python/cpython/commit/86566702f311f8e90600e85350f6b6769a…
commit: 86566702f311f8e90600e85350f6b6769a384ea5
branch: master
author: Benjamin Peterson <benjamin(a)python.org>
committer: GitHub <noreply(a)github.com>
date: 2017-10-05T22:50:42-07:00
summary:
weaken pthread_getcpuclockid test (more bpo-31596) (#3904)
There just isn't much we can assert in a portable way.
files:
M Lib/test/test_time.py
diff --git a/Lib/test/test_time.py b/Lib/test/test_time.py
index 1456748ed8e..c92e66bf49a 100644
--- a/Lib/test/test_time.py
+++ b/Lib/test/test_time.py
@@ -85,20 +85,13 @@ def test_clock_monotonic(self):
'need time.pthread_getcpuclockid()')
@unittest.skipUnless(hasattr(time, 'clock_gettime'),
'need time.clock_gettime()')
- @unittest.skipUnless(hasattr(time, 'CLOCK_THREAD_CPUTIME_ID'),
- 'need time.CLOCK_THREAD_CPUTIME_ID')
def test_pthread_getcpuclockid(self):
clk_id = time.pthread_getcpuclockid(threading.get_ident())
self.assertTrue(type(clk_id) is int)
self.assertNotEqual(clk_id, time.CLOCK_THREAD_CPUTIME_ID)
- # This should suffice to show that both calls are measuring the same clock.
t1 = time.clock_gettime(clk_id)
- t2 = time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID)
- t3 = time.clock_gettime(clk_id)
- t4 = time.clock_gettime(time.CLOCK_THREAD_CPUTIME_ID)
+ t2 = time.clock_gettime(clk_id)
self.assertLessEqual(t1, t2)
- self.assertLessEqual(t2, t3)
- self.assertLessEqual(t3, t4)
@unittest.skipUnless(hasattr(time, 'clock_getres'),
'need time.clock_getres()')
1
0
![](https://secure.gravatar.com/avatar/cc7737cd64a84f1b5c61a160798e97ee.jpg?s=120&d=mm&r=g)
closes bpo-31696: don't mention GCC in sys.version when building with clang (#3891)
by Benjamin Peterson Oct. 6, 2017
by Benjamin Peterson Oct. 6, 2017
Oct. 6, 2017
https://github.com/python/cpython/commit/7faf7e50757dde2cb8583ee08ef31f4b83…
commit: 7faf7e50757dde2cb8583ee08ef31f4b8312e44f
branch: master
author: Benjamin Peterson <benjamin(a)python.org>
committer: GitHub <noreply(a)github.com>
date: 2017-10-05T21:15:14-07:00
summary:
closes bpo-31696: don't mention GCC in sys.version when building with clang (#3891)
files:
A Misc/NEWS.d/next/Build/2017-10-04-23-40-32.bpo-31696.Y3_aBV.rst
M Python/getcompiler.c
diff --git a/Misc/NEWS.d/next/Build/2017-10-04-23-40-32.bpo-31696.Y3_aBV.rst b/Misc/NEWS.d/next/Build/2017-10-04-23-40-32.bpo-31696.Y3_aBV.rst
new file mode 100644
index 00000000000..00aae0b8ae1
--- /dev/null
+++ b/Misc/NEWS.d/next/Build/2017-10-04-23-40-32.bpo-31696.Y3_aBV.rst
@@ -0,0 +1,2 @@
+Improve compiler version information in :data:`sys.version` when Python is
+built with Clang.
diff --git a/Python/getcompiler.c b/Python/getcompiler.c
index 9d9c33ac2de..59c0dbf92ae 100644
--- a/Python/getcompiler.c
+++ b/Python/getcompiler.c
@@ -5,15 +5,14 @@
#ifndef COMPILER
-#ifdef __GNUC__
+// Note the __clang__ conditional has to come before the __GNUC__ one because
+// clang pretends to be GCC.
+#if defined(__clang__)
+#define COMPILER "\n[Clang " __clang_version__ "]"
+#elif defined(__GNUC__)
#define COMPILER "\n[GCC " __VERSION__ "]"
-#endif
-
-#endif /* !COMPILER */
-
-#ifndef COMPILER
-
-#ifdef __cplusplus
+// Generic fallbacks.
+#elif defined(__cplusplus)
#define COMPILER "[C++]"
#else
#define COMPILER "[C]"
1
0