Skip to content
Merged
8 changes: 4 additions & 4 deletions Doc/library/asyncio-stream.rst
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ and work with streams:


.. function:: open_connection(host=None, port=None, *, \
limit=None, ssl=None, family=0, proto=0, \
limit=65536, ssl=None, family=0, proto=0, \
flags=0, sock=None, local_addr=None, \
server_hostname=None, ssl_handshake_timeout=None, \
ssl_shutdown_timeout=None, \
Expand Down Expand Up @@ -89,7 +89,7 @@ and work with streams:


.. function:: start_server(client_connected_cb, host=None, \
port=None, *, limit=None, \
port=None, *, limit=65536, \
family=socket.AF_UNSPEC, \
flags=socket.AI_PASSIVE, sock=None, \
backlog=100, ssl=None, reuse_address=None, \
Expand Down Expand Up @@ -137,7 +137,7 @@ and work with streams:

.. rubric:: Unix Sockets

.. function:: open_unix_connection(path=None, *, limit=None, \
.. function:: open_unix_connection(path=None, *, limit=65536, \
ssl=None, sock=None, server_hostname=None, \
ssl_handshake_timeout=None, ssl_shutdown_timeout=None)
:async:
Expand Down Expand Up @@ -169,7 +169,7 @@ and work with streams:


.. function:: start_unix_server(client_connected_cb, path=None, \
*, limit=None, sock=None, backlog=100, ssl=None, \
*, limit=65536, sock=None, backlog=100, ssl=None, \
ssl_handshake_timeout=None, \
ssl_shutdown_timeout=None, start_serving=True, \
cleanup_socket=True, mode=None)
Expand Down
4 changes: 2 additions & 2 deletions Doc/library/asyncio-subprocess.rst
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ Creating Subprocesses
=====================

.. function:: create_subprocess_exec(program, *args, stdin=None, \
stdout=None, stderr=None, limit=None, **kwds)
stdout=None, stderr=None, limit=65536, **kwds)
:async:

Create a subprocess.
Expand All @@ -84,7 +84,7 @@ Creating Subprocesses


.. function:: create_subprocess_shell(cmd, stdin=None, \
stdout=None, stderr=None, limit=None, **kwds)
stdout=None, stderr=None, limit=65536, **kwds)
:async:

Run the *cmd* shell command.
Expand Down
14 changes: 7 additions & 7 deletions Doc/library/zlib.rst
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ The available exception and functions in this module are:
Exception raised on compression and decompression errors.


.. function:: adler32(data[, value])
.. function:: adler32(data, value=1, /)

Computes an Adler-32 checksum of *data*. (An Adler-32 checksum is almost as
reliable as a CRC32 but can be computed much more quickly.) The result
Expand Down Expand Up @@ -127,7 +127,7 @@ The available exception and functions in this module are:
Added the *zdict* parameter and keyword argument support.


.. function:: crc32(data[, value])
.. function:: crc32(data, value=0, /)

.. index::
single: Cyclic Redundancy Check
Expand Down Expand Up @@ -205,7 +205,7 @@ The available exception and functions in this module are:
.. versionchanged:: 3.6
*wbits* and *bufsize* can be used as keyword arguments.

.. function:: decompressobj(wbits=MAX_WBITS[, zdict])
.. function:: decompressobj(wbits=MAX_WBITS, zdict=b'')

Returns a decompression object, to be used for decompressing data streams that
won't fit into memory at once.
Expand All @@ -231,15 +231,15 @@ The available exception and functions in this module are:
Compression objects support the following methods:


.. method:: Compress.compress(data)
.. method:: Compress.compress(data, /)

Compress *data*, returning a bytes object containing compressed data for at least
part of the data in *data*. This data should be concatenated to the output
produced by any preceding calls to the :meth:`compress` method. Some input may
be kept in internal buffers for later processing.


.. method:: Compress.flush([mode])
.. method:: Compress.flush(mode=Z_FINISH, /)

All pending input is processed, and a bytes object containing the remaining compressed
output is returned. *mode* can be selected from the constants
Expand Down Expand Up @@ -294,7 +294,7 @@ Decompression objects support the following methods and attributes:
.. versionadded:: 3.3


.. method:: Decompress.decompress(data, max_length=0)
.. method:: Decompress.decompress(data, /, max_length=0)

Decompress *data*, returning a bytes object containing the uncompressed data
corresponding to at least part of the data in *string*. This data should be
Expand All @@ -318,7 +318,7 @@ Decompression objects support the following methods and attributes:
*max_length* can be used as a keyword argument.


.. method:: Decompress.flush([length])
.. method:: Decompress.flush(length=DEF_BUF_SIZE, /)

All pending input is processed, and a bytes object containing the remaining
uncompressed output is returned. After calling :meth:`flush`, the
Expand Down
4 changes: 3 additions & 1 deletion Lib/asyncio/selector_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -253,7 +253,9 @@ async def _accept_connection2(
except (SystemExit, KeyboardInterrupt):
raise
except BaseException as exc:
if self._debug:
if transport is None:
conn.close()
if transport is None or self._debug:
context = {
'message':
'Error on transport creation for incoming connection',
Expand Down
5 changes: 5 additions & 0 deletions Lib/asyncio/taskgroups.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,13 +116,15 @@ async def _aexit(self, et, exc):
# can be cancelled multiple times if our parent task
# is being cancelled repeatedly (or even once, when
# our own cancellation is already in progress)
pending_cancellation_error = None
while self._tasks:
if self._on_completed_fut is None:
self._on_completed_fut = self._loop.create_future()

try:
await self._on_completed_fut
except exceptions.CancelledError as ex:
pending_cancellation_error = ex
if not self._aborting:
# Our parent task is being cancelled:
#
Expand Down Expand Up @@ -163,6 +165,9 @@ async def _aexit(self, et, exc):
# If there are no pending cancellations left,
# don't propagate CancelledError.
propagate_cancellation_error = None
elif propagate_cancellation_error is None:
# gh-155433: the remaining cancellation is not ours, don't drop it
propagate_cancellation_error = pending_cancellation_error

# Propagate CancelledError if there is one, except if there
# are other errors -- those have priority.
Expand Down
4 changes: 2 additions & 2 deletions Lib/idlelib/idle_test/README.txt
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ insert the import and main lines before the htest lines.

if __name__ == "__main__":
from unittest import main
main('idlelib.idle_test.test_abc', verbosity=2, exit=False)
main('idlelib.idle_test.test_abc', verbosity=2)

The ', exit=False' is only needed if an htest follows.
Add ', exit=False' to the main call if and only if an htest follows.



Expand Down
66 changes: 34 additions & 32 deletions Lib/idlelib/idle_test/htest.py
Original file line number Diff line number Diff line change
@@ -1,48 +1,51 @@
"""Run human tests of Idle's window, dialog, and popup widgets.

run(*tests) Create a master Tk() htest window. Within that, run each
callable in tests after finding the matching test spec in this file. If
tests is empty, run an htest for each spec dict in this file after
finding the matching callable in the module named in the spec. Close
the master window to end testing.

In a tested module, let X be a global name bound to a callable (class or
function) whose .__name__ attribute is also X (the usual situation). The
first parameter of X must be 'parent' or 'master'. When called, the
first argument will be the root window. X must create a child
Toplevel(parent/master) (or subclass thereof). The Toplevel may be a
test widget or dialog, in which case the callable is the corresponding
class. Or the Toplevel may contain the widget to be tested or set up a
context in which a test widget is invoked. In this latter case, the
callable is a wrapper function that sets up the Toplevel and other
objects. Wrapper function names, such as _editor_window', should start
with '_' and be lowercase.

The main function, `run(*tests)`, is defined at the end of this file.
Argument `tests` is a possibly empty tuple of callables defined in some
idlelib.abc module (or possibly modules). Its steps:
1. Create a master Tk() htest window. Within that window ...
2a. If tuple `tests` is not empty, run was likely called from one
module. Run each callable in `tests` after finding the matching
callable_spec test spec in this file.
2b. If tests is empty, run was likely called from this file.
Run an htest for each spec dict in this file after finding the
matching callable in the module named in the spec.
3. Close the master window to end testing.

In a tested module, let X be a global name bound to a callable (class
or function) whose .__name__ attribute (its `class` or `def` definition
name) is also X. X must expect exactly 1 positional argument, a
parent toplevel window. Run passes the htest window. X must create a
child Toplevel(parent/master). The callable may be either a runtime
object or a wrapper function written just for the test. In the latter
case, its name should start with '_' and be lowercase (such as '_ttt').

End the module with

```
if __name__ == '__main__':
<run unittest.main with 'exit=False'>
from unittest import main
main("idlelib.idle_test.test_xyz", verbosity=2, exit=False)

from idlelib.idle_test.htest import run
run(callable) # There could be multiple comma-separated callables.
run(callable)
```
Replace 'xyz' as appropriate and 'callable' with the callable name or
comma-separated names (multiple names is rare). 'exit=False' is needed
for the htest to run.

To have wrapper functions ignored by coverage reports, tag the def
header like so: "def _wrapper(parent): # htest #". Use the same tag
for htest lines in widget code. Make sure that the 'if __name__' line
matches the above. Then have make sure that .coveragerc includes the
following:

header like so: "def _wrapper(root): # htest #". Use the same tag
for htest-only lines in the main code. To ignore the 'if __name__'
statement, match the example above. Add the below to coveragerc.
```
[report]
exclude_lines =
.*# htest #
if __name__ == .__main__.:

(The "." instead of "'" is intentional and necessary.)

```

To run any X, this file must contain a matching instance of the
following template, with X.__name__ prepended to '_spec'.
When all tests are run, the prefix is use to get X.

callable_spec = {
'file': '',
Expand All @@ -51,11 +54,10 @@
}

file (no .py): run() imports file.py.
kwds: augmented with {'parent':root} and passed to X as **kwds.
kwds: run() augments with {'parent':root} and passes to X as **kwds.
title: an example kwd; some widgets need this, delete line if not.
msg: master window hints about testing the widget.


TODO test these modules and classes:
autocomplete_w.AutoCompleteWindow
debugger.Debugger
Expand Down
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_delegator.py
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,4 @@ def test_mydel(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=2)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_format.py
Original file line number Diff line number Diff line change
Expand Up @@ -665,4 +665,4 @@ def test_rstrip_end(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=2)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_history.py
Original file line number Diff line number Diff line change
Expand Up @@ -169,4 +169,4 @@ def test_history_prev_next(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=2)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_pathbrowser.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,4 +83,4 @@ def test_PathBrowserTreeItem(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_query.py
Original file line number Diff line number Diff line change
Expand Up @@ -448,4 +448,4 @@ def test_click_args(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_search.py
Original file line number Diff line number Diff line change
Expand Up @@ -77,4 +77,4 @@ def test_find_selection(self):
text.delete('2.0', 'end')

if __name__ == '__main__':
unittest.main(verbosity=2, exit=2)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_searchbase.py
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,4 @@ def test_create_command_buttons(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=2)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_text.py
Original file line number Diff line number Diff line change
Expand Up @@ -233,4 +233,4 @@ def setUp(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
unittest.main(verbosity=2)
2 changes: 1 addition & 1 deletion Lib/idlelib/idle_test/test_undo.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,4 +132,4 @@ def test_addcmd(self):


if __name__ == '__main__':
unittest.main(verbosity=2, exit=False)
unittest.main(verbosity=2)
54 changes: 54 additions & 0 deletions Lib/test/test_asyncio/test_selector_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -421,6 +421,60 @@ def test_accept_connection_reschedules_once_on_resource_error(self):
self.assertEqual(self.loop.call_exception_handler.call_count, 1)
self.assertEqual(self.loop.call_later.call_count, 1)

def test_accept_connection2_factory_error_closes_conn(self):
# gh-155934: if the transport was never created, the accepted
# socket is closed and the error is reported even when debug
# mode is disabled.
self.loop.set_debug(False)
conn = mock.Mock()

def factory():
raise RuntimeError("protocol_factory failed")

self.loop.call_exception_handler = mock.Mock()
self.loop.run_until_complete(
self.loop._accept_connection2(factory, conn, {}))

self.assertTrue(conn.close.called)
self.loop.call_exception_handler.assert_called_once()

def test_accept_connection2_transport_error_closes_conn(self):
# gh-155934: same when the transport creation itself fails.
self.loop.set_debug(False)
conn = mock.Mock()
self.loop._make_socket_transport = mock.Mock(
side_effect=ZeroDivisionError)
self.loop.call_exception_handler = mock.Mock()

self.loop.run_until_complete(
self.loop._accept_connection2(mock.Mock(), conn, {}))

self.assertTrue(conn.close.called)
self.loop.call_exception_handler.assert_called_once()

def test_accept_connection2_waiter_error_stays_debug_only(self):
# Once the transport exists it owns the socket: waiter failures
# (e.g. SSL handshake errors) close the transport and stay
# debug-only, and the accepted socket is not closed directly.
self.loop.set_debug(False)
conn = mock.Mock()
transport = mock.Mock()

def make_transport(conn, protocol, waiter=None, **kwargs):
waiter.set_exception(OSError("handshake failed"))
return transport

self.loop._make_socket_transport = make_transport
self.loop.call_exception_handler = mock.Mock()

self.loop.run_until_complete(
self.loop._accept_connection2(mock.Mock(), conn, {}))

self.assertTrue(transport.close.called)
self.assertFalse(conn.close.called)
self.assertFalse(self.loop.call_exception_handler.called)


class SelectorTransportTests(test_utils.TestCase):

def setUp(self):
Expand Down
Loading
Loading