Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 2887f76

Browse files
committed
Merge.
2 parents f26c2e7 + ca2e02c commit 2887f76

9 files changed

Lines changed: 199 additions & 40 deletions

File tree

Doc/library/email.parser.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ have the same API as the :class:`Parser` and :class:`BytesParser` classes.
181181
.. versionchanged:: 3.3
182182
Removed the *strict* argument. Added the *policy* keyword.
183183

184-
.. method:: parse(fp, headeronly=False)
184+
.. method:: parse(fp, headersonly=False)
185185

186186
Read all the data from the binary file-like object *fp*, parse the
187187
resulting bytes, and return the message object. *fp* must support

Doc/library/subprocess.rst

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -406,12 +406,18 @@ functions.
406406

407407
Read the `Security Considerations`_ section before using ``shell=True``.
408408

409-
*bufsize* will be supplied as the corresponding argument to the :func:`open`
410-
function when creating the stdin/stdout/stderr pipe file objects: :const:`0`
411-
means unbuffered (read and write are one system call and can return short),
412-
:const:`1` means line buffered, any other positive value means use a buffer
413-
of approximately that size. A negative bufsize (the default) means the
414-
system default of io.DEFAULT_BUFFER_SIZE will be used.
409+
*bufsize* will be supplied as the corresponding argument to the
410+
:func:`open` function when creating the stdin/stdout/stderr pipe
411+
file objects:
412+
413+
- :const:`0` means unbuffered (read and write are one
414+
system call and can return short)
415+
- :const:`1` means line buffered
416+
(only usable if ``universal_newlines=True`` i.e., in a text mode)
417+
- any other positive value means use a buffer of approximately that
418+
size
419+
- negative bufsize (the default) means the system default of
420+
io.DEFAULT_BUFFER_SIZE will be used.
415421

416422
.. versionchanged:: 3.3.1
417423
*bufsize* now defaults to -1 to enable buffering by default to match the

Lib/sre_parse.py

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -94,33 +94,45 @@ def __init__(self, pattern, data=None):
9494
self.data = data
9595
self.width = None
9696
def dump(self, level=0):
97-
nl = 1
97+
nl = True
9898
seqtypes = (tuple, list)
9999
for op, av in self.data:
100-
print(level*" " + op, end=' '); nl = 0
101-
if op == "in":
100+
print(level*" " + op, end='')
101+
if op == IN:
102102
# member sublanguage
103-
print(); nl = 1
103+
print()
104104
for op, a in av:
105105
print((level+1)*" " + op, a)
106-
elif op == "branch":
107-
print(); nl = 1
108-
i = 0
109-
for a in av[1]:
110-
if i > 0:
106+
elif op == BRANCH:
107+
print()
108+
for i, a in enumerate(av[1]):
109+
if i:
111110
print(level*" " + "or")
112-
a.dump(level+1); nl = 1
113-
i = i + 1
111+
a.dump(level+1)
112+
elif op == GROUPREF_EXISTS:
113+
condgroup, item_yes, item_no = av
114+
print('', condgroup)
115+
item_yes.dump(level+1)
116+
if item_no:
117+
print(level*" " + "else")
118+
item_no.dump(level+1)
114119
elif isinstance(av, seqtypes):
120+
nl = False
115121
for a in av:
116122
if isinstance(a, SubPattern):
117-
if not nl: print()
118-
a.dump(level+1); nl = 1
123+
if not nl:
124+
print()
125+
a.dump(level+1)
126+
nl = True
119127
else:
120-
print(a, end=' ') ; nl = 0
128+
if not nl:
129+
print(' ', end='')
130+
print(a, end='')
131+
nl = False
132+
if not nl:
133+
print()
121134
else:
122-
print(av, end=' ') ; nl = 0
123-
if not nl: print()
135+
print('', av)
124136
def __repr__(self):
125137
return repr(self.data)
126138
def __len__(self):

Lib/subprocess.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -837,7 +837,8 @@ def __init__(self, args, bufsize=-1, executable=None,
837837
if p2cwrite != -1:
838838
self.stdin = io.open(p2cwrite, 'wb', bufsize)
839839
if universal_newlines:
840-
self.stdin = io.TextIOWrapper(self.stdin, write_through=True)
840+
self.stdin = io.TextIOWrapper(self.stdin, write_through=True,
841+
line_buffering=(bufsize == 1))
841842
if c2pread != -1:
842843
self.stdout = io.open(c2pread, 'rb', bufsize)
843844
if universal_newlines:

Lib/test/test_re.py

Lines changed: 23 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1203,16 +1203,33 @@ def test_bug_2537(self):
12031203
self.assertEqual(m.group(2), "y")
12041204

12051205
def test_debug_flag(self):
1206+
pat = r'(\.)(?:[ch]|py)(?(1)$|: )'
12061207
with captured_stdout() as out:
1207-
re.compile('foo', re.DEBUG)
1208-
self.assertEqual(out.getvalue().splitlines(),
1209-
['literal 102 ', 'literal 111 ', 'literal 111 '])
1208+
re.compile(pat, re.DEBUG)
1209+
dump = '''\
1210+
subpattern 1
1211+
literal 46
1212+
subpattern None
1213+
branch
1214+
in
1215+
literal 99
1216+
literal 104
1217+
or
1218+
literal 112
1219+
literal 121
1220+
subpattern None
1221+
groupref_exists 1
1222+
at at_end
1223+
else
1224+
literal 58
1225+
literal 32
1226+
'''
1227+
self.assertEqual(out.getvalue(), dump)
12101228
# Debug output is output again even a second time (bypassing
12111229
# the cache -- issue #20426).
12121230
with captured_stdout() as out:
1213-
re.compile('foo', re.DEBUG)
1214-
self.assertEqual(out.getvalue().splitlines(),
1215-
['literal 102 ', 'literal 111 ', 'literal 111 '])
1231+
re.compile(pat, re.DEBUG)
1232+
self.assertEqual(out.getvalue(), dump)
12161233

12171234
def test_keyword_parameters(self):
12181235
# Issue #20283: Accepting the string keyword parameter.

Lib/test/test_subprocess.py

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1008,6 +1008,39 @@ def test_bufsize_is_none(self):
10081008
p = subprocess.Popen([sys.executable, "-c", "pass"], bufsize=None)
10091009
self.assertEqual(p.wait(), 0)
10101010

1011+
def _test_bufsize_equal_one(self, line, expected, universal_newlines):
1012+
# subprocess may deadlock with bufsize=1, see issue #21332
1013+
with subprocess.Popen([sys.executable, "-c", "import sys;"
1014+
"sys.stdout.write(sys.stdin.readline());"
1015+
"sys.stdout.flush()"],
1016+
stdin=subprocess.PIPE,
1017+
stdout=subprocess.PIPE,
1018+
stderr=subprocess.DEVNULL,
1019+
bufsize=1,
1020+
universal_newlines=universal_newlines) as p:
1021+
p.stdin.write(line) # expect that it flushes the line in text mode
1022+
os.close(p.stdin.fileno()) # close it without flushing the buffer
1023+
read_line = p.stdout.readline()
1024+
try:
1025+
p.stdin.close()
1026+
except OSError:
1027+
pass
1028+
p.stdin = None
1029+
self.assertEqual(p.returncode, 0)
1030+
self.assertEqual(read_line, expected)
1031+
1032+
def test_bufsize_equal_one_text_mode(self):
1033+
# line is flushed in text mode with bufsize=1.
1034+
# we should get the full line in return
1035+
line = "line\n"
1036+
self._test_bufsize_equal_one(line, line, universal_newlines=True)
1037+
1038+
def test_bufsize_equal_one_binary_mode(self):
1039+
# line is not flushed in binary mode with bufsize=1.
1040+
# we should get empty response
1041+
line = b'line' + os.linesep.encode() # assume ascii-based locale
1042+
self._test_bufsize_equal_one(line, b'', universal_newlines=False)
1043+
10111044
def test_leaking_fds_on_error(self):
10121045
# see bug #5179: Popen leaks file descriptors to PIPEs if
10131046
# the child fails to execute; this will eventually exhaust

Lib/test/test_threading.py

Lines changed: 83 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44

55
import test.support
66
from test.support import verbose, strip_python_stderr, import_module, cpython_only
7-
from test.script_helper import assert_python_ok
7+
from test.script_helper import assert_python_ok, assert_python_failure
88

99
import random
1010
import re
@@ -15,7 +15,6 @@
1515
import unittest
1616
import weakref
1717
import os
18-
from test.script_helper import assert_python_ok, assert_python_failure
1918
import subprocess
2019

2120
from test import lock_tests
@@ -962,6 +961,88 @@ def outer():
962961
self.assertEqual(p.returncode, 0, "Unexpected error: " + stderr.decode())
963962
self.assertEqual(data, expected_output)
964963

964+
def test_print_exception(self):
965+
script = r"""if True:
966+
import threading
967+
import time
968+
969+
running = False
970+
def run():
971+
global running
972+
running = True
973+
while running:
974+
time.sleep(0.01)
975+
1/0
976+
t = threading.Thread(target=run)
977+
t.start()
978+
while not running:
979+
time.sleep(0.01)
980+
running = False
981+
t.join()
982+
"""
983+
rc, out, err = assert_python_ok("-c", script)
984+
self.assertEqual(out, b'')
985+
err = err.decode()
986+
self.assertIn("Exception in thread", err)
987+
self.assertIn("Traceback (most recent call last):", err)
988+
self.assertIn("ZeroDivisionError", err)
989+
self.assertNotIn("Unhandled exception", err)
990+
991+
def test_print_exception_stderr_is_none_1(self):
992+
script = r"""if True:
993+
import sys
994+
import threading
995+
import time
996+
997+
running = False
998+
def run():
999+
global running
1000+
running = True
1001+
while running:
1002+
time.sleep(0.01)
1003+
1/0
1004+
t = threading.Thread(target=run)
1005+
t.start()
1006+
while not running:
1007+
time.sleep(0.01)
1008+
sys.stderr = None
1009+
running = False
1010+
t.join()
1011+
"""
1012+
rc, out, err = assert_python_ok("-c", script)
1013+
self.assertEqual(out, b'')
1014+
err = err.decode()
1015+
self.assertIn("Exception in thread", err)
1016+
self.assertIn("Traceback (most recent call last):", err)
1017+
self.assertIn("ZeroDivisionError", err)
1018+
self.assertNotIn("Unhandled exception", err)
1019+
1020+
def test_print_exception_stderr_is_none_2(self):
1021+
script = r"""if True:
1022+
import sys
1023+
import threading
1024+
import time
1025+
1026+
running = False
1027+
def run():
1028+
global running
1029+
running = True
1030+
while running:
1031+
time.sleep(0.01)
1032+
1/0
1033+
sys.stderr = None
1034+
t = threading.Thread(target=run)
1035+
t.start()
1036+
while not running:
1037+
time.sleep(0.01)
1038+
running = False
1039+
t.join()
1040+
"""
1041+
rc, out, err = assert_python_ok("-c", script)
1042+
self.assertEqual(out, b'')
1043+
self.assertNotIn("Unhandled exception", err.decode())
1044+
1045+
9651046
class TimerTests(BaseTestCase):
9661047

9671048
def setUp(self):

Lib/threading.py

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -248,7 +248,7 @@ def _acquire_restore(self, x):
248248

249249
def _is_owned(self):
250250
# Return True if lock is owned by current_thread.
251-
# This method is called only if __lock doesn't have _is_owned().
251+
# This method is called only if _lock doesn't have _is_owned().
252252
if self._lock.acquire(0):
253253
self._lock.release()
254254
return False
@@ -749,12 +749,12 @@ class Thread:
749749
750750
"""
751751

752-
__initialized = False
752+
_initialized = False
753753
# Need to store a reference to sys.exc_info for printing
754754
# out exceptions when a thread tries to use a global var. during interp.
755755
# shutdown and thus raises an exception about trying to perform some
756756
# operation on/with a NoneType
757-
__exc_info = _sys.exc_info
757+
_exc_info = _sys.exc_info
758758
# Keep sys.exc_clear too to clear the exception just before
759759
# allowing .join() to return.
760760
#XXX __exc_clear = _sys.exc_clear
@@ -926,10 +926,10 @@ def _bootstrap_inner(self):
926926
# shutdown) use self._stderr. Otherwise still use sys (as in
927927
# _sys) in case sys.stderr was redefined since the creation of
928928
# self.
929-
if _sys:
930-
_sys.stderr.write("Exception in thread %s:\n%s\n" %
931-
(self.name, _format_exc()))
932-
else:
929+
if _sys and _sys.stderr is not None:
930+
print("Exception in thread %s:\n%s" %
931+
(self.name, _format_exc()), file=self._stderr)
932+
elif self._stderr is not None:
933933
# Do the best job possible w/o a huge amt. of code to
934934
# approximate a traceback (code ideas from
935935
# Lib/traceback.py)
@@ -957,7 +957,7 @@ def _bootstrap_inner(self):
957957
# test_threading.test_no_refcycle_through_target when
958958
# the exception keeps the target alive past when we
959959
# assert that it's dead.
960-
#XXX self.__exc_clear()
960+
#XXX self._exc_clear()
961961
pass
962962
finally:
963963
with _active_limbo_lock:

Misc/NEWS

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,15 @@ Core and Builtins
1313
Library
1414
-------
1515

16+
- Issue #22415: Fixed debugging output of the GROUPREF_EXISTS opcode in the re
17+
module. Removed trailing spaces in debugging output.
18+
19+
- Issue #22423: Unhandled exception in thread no longer causes unhandled
20+
AttributeError when sys.stderr is None.
21+
22+
- Issue #21332: Ensure that ``bufsize=1`` in subprocess.Popen() selects
23+
line buffering, rather than block buffering. Patch by Akira Li.
24+
1625

1726
What's New in Python 3.4.2rc1?
1827
==============================

0 commit comments

Comments
 (0)