Skip to content

Commit 07c304c

Browse files
authored
Merge branch 'main' into issue-65329
2 parents b8d967e + 96e1901 commit 07c304c

34 files changed

Lines changed: 548 additions & 157 deletions

Doc/library/functions.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1444,8 +1444,9 @@ are always available. They are listed here in alphabetical order.
14441444
arguments are converted to text strings, :func:`print` cannot be used with
14451445
binary mode file objects. For these, use ``file.write(...)`` instead.
14461446

1447-
Whether the output is buffered is usually determined by *file*, but if the
1448-
*flush* keyword argument is true, the stream is forcibly flushed.
1447+
Output buffering is usually determined by *file*.
1448+
However, if *flush* is true, the stream is forcibly flushed.
1449+
14491450

14501451
.. versionchanged:: 3.3
14511452
Added the *flush* keyword argument.

Doc/library/http.client.rst

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -353,6 +353,13 @@ HTTPConnection Objects
353353
The *headers* argument should be a mapping of extra HTTP headers to send with
354354
the CONNECT request.
355355

356+
As HTTP/1.1 is used for HTTP CONNECT tunnelling request, `as per the RFC
357+
<https://tools.ietf.org/html/rfc7231#section-4.3.6>`_, a HTTP ``Host:``
358+
header must be provided, matching the authority-form of the request target
359+
provided as the destination for the CONNECT request. If a HTTP ``Host:``
360+
header is not provided via the headers argument, one is generated and
361+
transmitted automatically.
362+
356363
For example, to tunnel through a HTTPS proxy server running locally on port
357364
8080, we would pass the address of the proxy to the :class:`HTTPSConnection`
358365
constructor, and the address of the host that we eventually want to reach to
@@ -365,6 +372,11 @@ HTTPConnection Objects
365372

366373
.. versionadded:: 3.2
367374

375+
.. versionchanged:: 3.12
376+
HTTP CONNECT tunnelling requests use protocol HTTP/1.1, upgraded from
377+
protocol HTTP/1.0. ``Host:`` HTTP headers are mandatory for HTTP/1.1, so
378+
one will be automatically generated and transmitted if not provided in
379+
the headers argument.
368380

369381
.. method:: HTTPConnection.connect()
370382

Doc/library/multiprocessing.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -460,16 +460,16 @@ process which created it.
460460
... return x*x
461461
...
462462
>>> with p:
463-
... p.map(f, [1,2,3])
463+
... p.map(f, [1,2,3])
464464
Process PoolWorker-1:
465465
Process PoolWorker-2:
466466
Process PoolWorker-3:
467467
Traceback (most recent call last):
468468
Traceback (most recent call last):
469469
Traceback (most recent call last):
470-
AttributeError: 'module' object has no attribute 'f'
471-
AttributeError: 'module' object has no attribute 'f'
472-
AttributeError: 'module' object has no attribute 'f'
470+
AttributeError: Can't get attribute 'f' on <module '__main__' (<class '_frozen_importlib.BuiltinImporter'>)>
471+
AttributeError: Can't get attribute 'f' on <module '__main__' (<class '_frozen_importlib.BuiltinImporter'>)>
472+
AttributeError: Can't get attribute 'f' on <module '__main__' (<class '_frozen_importlib.BuiltinImporter'>)>
473473

474474
(If you try this it will actually output three full tracebacks
475475
interleaved in a semi-random fashion, and then you may have to

Doc/library/shutil.rst

Lines changed: 27 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -433,23 +433,43 @@ Directory and files operations
433433
When no *path* is specified, the results of :func:`os.environ` are used,
434434
returning either the "PATH" value or a fallback of :attr:`os.defpath`.
435435

436-
On Windows, the current directory is always prepended to the *path* whether
437-
or not you use the default or provide your own, which is the behavior the
438-
command shell uses when finding executables. Additionally, when finding the
439-
*cmd* in the *path*, the ``PATHEXT`` environment variable is checked. For
440-
example, if you call ``shutil.which("python")``, :func:`which` will search
441-
``PATHEXT`` to know that it should look for ``python.exe`` within the *path*
442-
directories. For example, on Windows::
436+
On Windows, the current directory is prepended to the *path* if *mode* does
437+
not include ``os.X_OK``. When the *mode* does include ``os.X_OK``, the
438+
Windows API ``NeedCurrentDirectoryForExePathW`` will be consulted to
439+
determine if the current directory should be prepended to *path*. To avoid
440+
consulting the current working directory for executables: set the environment
441+
variable ``NoDefaultCurrentDirectoryInExePath``.
442+
443+
Also on Windows, the ``PATHEXT`` variable is used to resolve commands
444+
that may not already include an extension. For example, if you call
445+
``shutil.which("python")``, :func:`which` will search ``PATHEXT``
446+
to know that it should look for ``python.exe`` within the *path*
447+
directories. For example, on Windows::
443448

444449
>>> shutil.which("python")
445450
'C:\\Python33\\python.EXE'
446451

452+
This is also applied when *cmd* is a path that contains a directory
453+
component::
454+
455+
>> shutil.which("C:\\Python33\\python")
456+
'C:\\Python33\\python.EXE'
457+
447458
.. versionadded:: 3.3
448459

449460
.. versionchanged:: 3.8
450461
The :class:`bytes` type is now accepted. If *cmd* type is
451462
:class:`bytes`, the result type is also :class:`bytes`.
452463

464+
.. versionchanged:: 3.12
465+
On Windows, the current directory is no longer prepended to the search
466+
path if *mode* includes ``os.X_OK`` and WinAPI
467+
``NeedCurrentDirectoryForExePathW(cmd)`` is false, else the current
468+
directory is prepended even if it is already in the search path;
469+
``PATHEXT`` is used now even when *cmd* includes a directory component
470+
or ends with an extension that is in ``PATHEXT``; and filenames that
471+
have no extension can now be found.
472+
453473
.. exception:: Error
454474

455475
This exception collects exceptions that are raised during a multi-file

Doc/library/socket.rst

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1775,7 +1775,7 @@ to sockets.
17751775
much data, if any, was successfully sent.
17761776

17771777
.. versionchanged:: 3.5
1778-
The socket timeout is no more reset each time data is sent successfully.
1778+
The socket timeout is no longer reset each time data is sent successfully.
17791779
The socket timeout is now the maximum total duration to send all data.
17801780

17811781
.. versionchanged:: 3.5
@@ -1998,8 +1998,8 @@ can be changed by calling :func:`setdefaulttimeout`.
19981998

19991999
* In *non-blocking mode*, operations fail (with an error that is unfortunately
20002000
system-dependent) if they cannot be completed immediately: functions from the
2001-
:mod:`select` can be used to know when and whether a socket is available for
2002-
reading or writing.
2001+
:mod:`select` module can be used to know when and whether a socket is available
2002+
for reading or writing.
20032003

20042004
* In *timeout mode*, operations fail if they cannot be completed within the
20052005
timeout specified for the socket (they raise a :exc:`timeout` exception)
@@ -2188,7 +2188,7 @@ manager protocol instead, open a socket with::
21882188
socket.socket(socket.AF_CAN, socket.SOCK_DGRAM, socket.CAN_BCM)
21892189

21902190
After binding (:const:`CAN_RAW`) or connecting (:const:`CAN_BCM`) the socket, you
2191-
can use the :meth:`socket.send`, and the :meth:`socket.recv` operations (and
2191+
can use the :meth:`socket.send` and :meth:`socket.recv` operations (and
21922192
their counterparts) on the socket object as usual.
21932193

21942194
This last example might require special privileges::

Doc/library/sys.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -697,7 +697,7 @@ always available.
697697
the encoding used with the :term:`filesystem error handler <filesystem
698698
encoding and error handler>` to convert between Unicode filenames and bytes
699699
filenames. The filesystem error handler is returned from
700-
:func:`getfilesystemencoding`.
700+
:func:`getfilesystemencodeerrors`.
701701

702702
For best compatibility, str should be used for filenames in all cases,
703703
although representing filenames as bytes is also supported. Functions

Doc/whatsnew/3.12.rst

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -343,6 +343,20 @@ shutil
343343
will be removed in Python 3.14.
344344
(Contributed by Irit Katriel in :gh:`102828`.)
345345

346+
* :func:`shutil.which` now consults the *PATHEXT* environment variable to
347+
find matches within *PATH* on Windows even when the given *cmd* includes
348+
a directory component.
349+
(Contributed by Charles Machalow in :gh:`103179`.)
350+
351+
:func:`shutil.which` will call ``NeedCurrentDirectoryForExePathW`` when
352+
querying for executables on Windows to determine if the current working
353+
directory should be prepended to the search path.
354+
(Contributed by Charles Machalow in :gh:`103179`.)
355+
356+
:func:`shutil.which` will return a path matching the *cmd* with a component
357+
from ``PATHEXT`` prior to a direct match elsewhere in the search path on
358+
Windows.
359+
(Contributed by Charles Machalow in :gh:`103179`.)
346360

347361
sqlite3
348362
-------
@@ -451,7 +465,7 @@ Optimizations
451465

452466
* Added experimental support for using the BOLT binary optimizer in the build
453467
process, which improves performance by 1-5%.
454-
(Contributed by Kevin Modzelewski in :gh:`90536`.)
468+
(Contributed by Kevin Modzelewski in :gh:`90536` and tuned by Dong-hee Na in :gh:`101525`)
455469

456470
* Speed up the regular expression substitution (functions :func:`re.sub` and
457471
:func:`re.subn` and corresponding :class:`!re.Pattern` methods) for

Include/pymacro.h

Lines changed: 16 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,20 +3,23 @@
33

44
// gh-91782: On FreeBSD 12, if the _POSIX_C_SOURCE and _XOPEN_SOURCE macros are
55
// defined, <sys/cdefs.h> disables C11 support and <assert.h> does not define
6-
// the static_assert() macro. Define the static_assert() macro in Python until
7-
// <sys/cdefs.h> suports C11:
6+
// the static_assert() macro.
87
// https://bugs.freebsd.org/bugzilla/show_bug.cgi?id=255290
9-
#if defined(__FreeBSD__) && !defined(static_assert)
10-
# define static_assert _Static_assert
11-
#endif
12-
13-
// static_assert is defined in glibc from version 2.16. Before it requires
14-
// compiler support (gcc >= 4.6) and is called _Static_assert.
15-
// In C++ 11 static_assert is a keyword, redefining is undefined behaviour.
16-
#if (defined(__GLIBC__) \
17-
&& (__GLIBC__ < 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ <= 16)) \
18-
&& !(defined(__cplusplus) && __cplusplus >= 201103L) \
19-
&& !defined(static_assert))
8+
//
9+
// macOS <= 10.10 doesn't define static_assert in assert.h at all despite
10+
// having C11 compiler support.
11+
//
12+
// static_assert is defined in glibc from version 2.16. Compiler support for
13+
// the C11 _Static_assert keyword is in gcc >= 4.6.
14+
//
15+
// MSVC makes static_assert a keyword in C11-17, contrary to the standards.
16+
//
17+
// In C++11 and C2x, static_assert is a keyword, redefining is undefined
18+
// behaviour. So only define if building as C (if __STDC_VERSION__ is defined),
19+
// not C++, and only for C11-17.
20+
#if !defined(static_assert) && (defined(__GNUC__) || defined(__clang__)) \
21+
&& defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L \
22+
&& __STDC_VERSION__ <= 201710L
2023
# define static_assert _Static_assert
2124
#endif
2225

Lib/http/client.py

Lines changed: 19 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -870,27 +870,39 @@ def __init__(self, host, port=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
870870
def set_tunnel(self, host, port=None, headers=None):
871871
"""Set up host and port for HTTP CONNECT tunnelling.
872872
873-
In a connection that uses HTTP CONNECT tunneling, the host passed to the
874-
constructor is used as a proxy server that relays all communication to
875-
the endpoint passed to `set_tunnel`. This done by sending an HTTP
873+
In a connection that uses HTTP CONNECT tunnelling, the host passed to
874+
the constructor is used as a proxy server that relays all communication
875+
to the endpoint passed to `set_tunnel`. This done by sending an HTTP
876876
CONNECT request to the proxy server when the connection is established.
877877
878878
This method must be called before the HTTP connection has been
879879
established.
880880
881881
The headers argument should be a mapping of extra HTTP headers to send
882882
with the CONNECT request.
883+
884+
As HTTP/1.1 is used for HTTP CONNECT tunnelling request, as per the RFC
885+
(https://tools.ietf.org/html/rfc7231#section-4.3.6), a HTTP Host:
886+
header must be provided, matching the authority-form of the request
887+
target provided as the destination for the CONNECT request. If a
888+
HTTP Host: header is not provided via the headers argument, one
889+
is generated and transmitted automatically.
883890
"""
884891

885892
if self.sock:
886893
raise RuntimeError("Can't set up tunnel for established connection")
887894

888895
self._tunnel_host, self._tunnel_port = self._get_hostport(host, port)
889896
if headers:
890-
self._tunnel_headers = headers
897+
self._tunnel_headers = headers.copy()
891898
else:
892899
self._tunnel_headers.clear()
893900

901+
if not any(header.lower() == "host" for header in self._tunnel_headers):
902+
encoded_host = self._tunnel_host.encode("idna").decode("ascii")
903+
self._tunnel_headers["Host"] = "%s:%d" % (
904+
encoded_host, self._tunnel_port)
905+
894906
def _get_hostport(self, host, port):
895907
if port is None:
896908
i = host.rfind(':')
@@ -915,8 +927,9 @@ def set_debuglevel(self, level):
915927
self.debuglevel = level
916928

917929
def _tunnel(self):
918-
connect = b"CONNECT %s:%d HTTP/1.0\r\n" % (
919-
self._tunnel_host.encode("ascii"), self._tunnel_port)
930+
connect = b"CONNECT %s:%d %s\r\n" % (
931+
self._tunnel_host.encode("idna"), self._tunnel_port,
932+
self._http_vsn_str.encode("ascii"))
920933
headers = [connect]
921934
for header, value in self._tunnel_headers.items():
922935
headers.append(f"{header}: {value}\r\n".encode("latin-1"))

Lib/inspect.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,9 +1772,9 @@ def trace(context=1):
17721772
# ------------------------------------------------ static version of getattr
17731773

17741774
_sentinel = object()
1775+
_static_getmro = type.__dict__['__mro__'].__get__
1776+
_get_dunder_dict_of_class = type.__dict__["__dict__"].__get__
17751777

1776-
def _static_getmro(klass):
1777-
return type.__dict__['__mro__'].__get__(klass)
17781778

17791779
def _check_instance(obj, attr):
17801780
instance_dict = {}
@@ -1802,10 +1802,9 @@ def _is_type(obj):
18021802
return True
18031803

18041804
def _shadowed_dict(klass):
1805-
dict_attr = type.__dict__["__dict__"]
18061805
for entry in _static_getmro(klass):
18071806
try:
1808-
class_dict = dict_attr.__get__(entry)["__dict__"]
1807+
class_dict = _get_dunder_dict_of_class(entry)["__dict__"]
18091808
except KeyError:
18101809
pass
18111810
else:

0 commit comments

Comments
 (0)