Skip to content

Commit

Permalink
Merge branch 'main' into argparse-nargs-0-positional
Browse files Browse the repository at this point in the history
  • Loading branch information
serhiy-storchaka committed Oct 2, 2024
2 parents f86e3ba + 2c050d4 commit 04b2a8f
Show file tree
Hide file tree
Showing 64 changed files with 987 additions and 773 deletions.
6 changes: 4 additions & 2 deletions Doc/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -305,13 +305,15 @@ serve:

# for development releases: always build
.PHONY: autobuild-dev
autobuild-dev: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short)
autobuild-dev:
$(MAKE) dist-no-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1'
$(MAKE) dist-no-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION)

# for HTML-only rebuilds
.PHONY: autobuild-dev-html
autobuild-dev-html: DISTVERSION = $(shell $(PYTHON) tools/extensions/patchlevel.py --short)
autobuild-dev-html:
$(MAKE) dist-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1'
$(MAKE) dist-html SPHINXOPTS='$(SPHINXOPTS) -Ea -A daily=1' DISTVERSION=$(DISTVERSION)

# for stable releases: only build if not in pre-release stage (alpha, beta)
# release candidate downloads are okay, since the stable tree can be in that stage
Expand Down
41 changes: 32 additions & 9 deletions Doc/library/argparse.rst
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ Quick Links for ArgumentParser
========================= =========================================================================================================== ==================================================================================
Name Description Values
========================= =========================================================================================================== ==================================================================================
prog_ The name of the program Defaults to ``os.path.basename(sys.argv[0])``
prog_ The name of the program
usage_ The string describing the program usage
description_ A brief description of what the program does
epilog_ Additional description of the program after the argument help
Expand Down Expand Up @@ -214,8 +214,8 @@ ArgumentParser objects
as keyword arguments. Each parameter has its own more detailed description
below, but in short they are:

* prog_ - The name of the program (default:
``os.path.basename(sys.argv[0])``)
* prog_ - The name of the program (default: generated from the ``__main__``
module attributes and ``sys.argv[0]``)

* usage_ - The string describing the program usage (default: generated from
arguments added to parser)
Expand Down Expand Up @@ -268,10 +268,18 @@ The following sections describe how each of these are used.
prog
^^^^

By default, :class:`ArgumentParser` objects use the base name
(see :func:`os.path.basename`) of ``sys.argv[0]`` to determine
how to display the name of the program in help messages. This default is almost
always desirable because it will make the help messages match the name that was
By default, :class:`ArgumentParser` calculates the name of the program
to display in help messages depending on the way the Python inerpreter was run:

* The :func:`base name <os.path.basename>` of ``sys.argv[0]`` if a file was
passed as argument.
* The Python interpreter name followed by ``sys.argv[0]`` if a directory or
a zipfile was passed as argument.
* The Python interpreter name followed by ``-m`` followed by the
module or package name if the :option:`-m` option was used.

This default is almost
always desirable because it will make the help messages match the string that was
used to invoke the program on the command line. For example, consider a file
named ``myprogram.py`` with the following code::

Expand All @@ -281,7 +289,7 @@ named ``myprogram.py`` with the following code::
args = parser.parse_args()

The help for this program will display ``myprogram.py`` as the program name
(regardless of where the program was invoked from):
(regardless of where the program was invoked from) if it is run as a script:

.. code-block:: shell-session
Expand All @@ -299,6 +307,17 @@ The help for this program will display ``myprogram.py`` as the program name
-h, --help show this help message and exit
--foo FOO foo help
If it is executed via the :option:`-m` option, the help will display a corresponding command line:

.. code-block:: shell-session
$ /usr/bin/python3 -m subdir.myprogram --help
usage: python3 -m subdir.myprogram [-h] [--foo FOO]
options:
-h, --help show this help message and exit
--foo FOO foo help
To change this default behavior, another value can be supplied using the
``prog=`` argument to :class:`ArgumentParser`::

Expand All @@ -309,7 +328,8 @@ To change this default behavior, another value can be supplied using the
options:
-h, --help show this help message and exit

Note that the program name, whether determined from ``sys.argv[0]`` or from the
Note that the program name, whether determined from ``sys.argv[0]``,
from the ``__main__`` module attributes or from the
``prog=`` argument, is available to help messages using the ``%(prog)s`` format
specifier.

Expand All @@ -324,6 +344,9 @@ specifier.
-h, --help show this help message and exit
--foo FOO foo of the myprogram program

.. versionchanged:: 3.14
The default ``prog`` value now reflects how ``__main__`` was actually executed,
rather than always being ``os.path.basename(sys.argv[0])``.

usage
^^^^^
Expand Down
10 changes: 9 additions & 1 deletion Doc/library/dataclasses.rst
Original file line number Diff line number Diff line change
Expand Up @@ -399,7 +399,7 @@ Module contents
:func:`!astuple` raises :exc:`TypeError` if *obj* is not a dataclass
instance.

.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False, module=None)
.. function:: make_dataclass(cls_name, fields, *, bases=(), namespace=None, init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False, match_args=True, kw_only=False, slots=False, weakref_slot=False, module=None, decorator=dataclass)

Creates a new dataclass with name *cls_name*, fields as defined
in *fields*, base classes as given in *bases*, and initialized
Expand All @@ -415,6 +415,11 @@ Module contents
of the dataclass is set to that value.
By default, it is set to the module name of the caller.

The *decorator* parameter is a callable that will be used to create the dataclass.
It should take the class object as a first argument and the same keyword arguments
as :func:`@dataclass <dataclass>`. By default, the :func:`@dataclass <dataclass>`
function is used.

This function is not strictly required, because any Python
mechanism for creating a new class with :attr:`!__annotations__` can
then apply the :func:`@dataclass <dataclass>` function to convert that class to
Expand All @@ -438,6 +443,9 @@ Module contents
def add_one(self):
return self.x + 1

.. versionadded:: 3.14
Added the *decorator* parameter.

.. function:: replace(obj, /, **changes)

Creates a new object of the same type as *obj*, replacing
Expand Down
16 changes: 15 additions & 1 deletion Doc/library/datetime.rst
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,20 @@ Instance attributes (read-only):

Between 0 and 86,399 inclusive.

.. caution::

It is a somewhat common bug for code to unintentionally use this attribute
when it is actually intended to get a :meth:`~timedelta.total_seconds`
value instead:

.. doctest::

>>> from datetime import timedelta
>>> duration = timedelta(seconds=11235813)
>>> duration.days, duration.seconds
(130, 3813)
>>> duration.total_seconds()
11235813.0

.. attribute:: timedelta.microseconds

Expand Down Expand Up @@ -351,7 +365,7 @@ Supported operations:
| | same value. (2) |
+--------------------------------+-----------------------------------------------+
| ``-t1`` | Equivalent to ``timedelta(-t1.days, |
| | -t1.seconds*, -t1.microseconds)``, |
| | -t1.seconds, -t1.microseconds)``, |
| | and to ``t1 * -1``. (1)(4) |
+--------------------------------+-----------------------------------------------+
| ``abs(t)`` | Equivalent to ``+t`` when ``t.days >= 0``, |
Expand Down
12 changes: 5 additions & 7 deletions Doc/library/sys.monitoring.rst
Original file line number Diff line number Diff line change
Expand Up @@ -50,16 +50,14 @@ Registering and using tools
*tool_id* must be in the range 0 to 5 inclusive.
Raises a :exc:`ValueError` if *tool_id* is in use.

.. function:: free_tool_id(tool_id: int, /) -> None
.. function:: clear_tool_id(tool_id: int, /) -> None

Should be called once a tool no longer requires *tool_id*.
Unregister all events and callback functions associated with *tool_id*.

.. note::
.. function:: free_tool_id(tool_id: int, /) -> None

:func:`free_tool_id` will not disable global or local events associated
with *tool_id*, nor will it unregister any callback functions. This
function is only intended to be used to notify the VM that the
particular *tool_id* is no longer in use.
Should be called once a tool no longer requires *tool_id*.
Will call :func:`clear_tool_id` before releasing *tool_id*.

.. function:: get_tool(tool_id: int, /) -> str | None

Expand Down
6 changes: 5 additions & 1 deletion Doc/tools/extensions/patchlevel.py
Original file line number Diff line number Diff line change
Expand Up @@ -74,4 +74,8 @@ def get_version_info():


if __name__ == "__main__":
print(format_version_info(get_header_version_info())[0])
short_ver, full_ver = format_version_info(get_header_version_info())
if sys.argv[1:2] == ["--short"]:
print(short_ver)
else:
print(full_ver)
5 changes: 3 additions & 2 deletions Doc/using/windows.rst
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,9 @@ available for application-local distributions.

As specified in :pep:`11`, a Python release only supports a Windows platform
while Microsoft considers the platform under extended support. This means that
Python |version| supports Windows 8.1 and newer. If you require Windows 7
support, please install Python 3.8.
Python |version| supports Windows 10 and newer. If you require Windows 7
support, please install Python 3.8. If you require Windows 8.1 support,
please install Python 3.12.

There are a number of different installers available for Windows, each with
certain benefits and downsides.
Expand Down
5 changes: 1 addition & 4 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -320,12 +320,9 @@ The free-threaded mode requires a different executable,
usually called ``python3.13t`` or ``python3.13t.exe``.
Pre-built binaries marked as *free-threaded* can be installed as part of
the official :ref:`Windows <install-freethreaded-windows>`
and :ref:`macOS <getting-and-installing-macpython>` installers,
and :ref:`macOS <install-freethreaded-macos>` installers,
or CPython can be built from source with the :option:`--disable-gil` option.

.. better macOS link pending
https://github.com/python/cpython/issues/109975#issuecomment-2286391179
Free-threaded execution allows for full utilization of the available
processing power by running threads in parallel on available CPU cores.
While not all software will benefit from this automatically, programs
Expand Down
7 changes: 7 additions & 0 deletions Doc/whatsnew/3.14.rst
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,13 @@ New Modules
Improved Modules
================

argparse
--------

* The default value of the :ref:`program name <prog>` for
:class:`argparse.ArgumentParser` now reflects the way the Python
interpreter was instructed to find the ``__main__`` module code.
(Contributed by Serhiy Storchaka and Alyssa Coghlan in :gh:`66436`.)

ast
---
Expand Down
4 changes: 4 additions & 0 deletions Include/cpython/code.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@
extern "C" {
#endif

/* Total tool ids available */
#define _PY_MONITORING_TOOL_IDS 8
/* Count of all local monitoring events */
#define _PY_MONITORING_LOCAL_EVENTS 10
/* Count of all "real" monitoring events (not derived from other events) */
Expand Down Expand Up @@ -57,6 +59,8 @@ typedef struct {
_Py_LocalMonitors active_monitors;
/* The tools that are to be notified for events for the matching code unit */
uint8_t *tools;
/* The version of tools when they instrument the code */
uintptr_t tool_versions[_PY_MONITORING_TOOL_IDS];
/* Information to support line events */
_PyCoLineInstrumentationData *lines;
/* The tools that are to be notified for line events for the matching code unit */
Expand Down
13 changes: 4 additions & 9 deletions Include/cpython/dictobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -14,16 +14,11 @@ typedef struct {
/* Number of items in the dictionary */
Py_ssize_t ma_used;

/* Dictionary version: globally unique, value change each time
the dictionary is modified */
#ifdef Py_BUILD_CORE
/* Bits 0-7 are for dict watchers.
/* This is a private field for CPython's internal use.
* Bits 0-7 are for dict watchers.
* Bits 8-11 are for the watched mutation counter (used by tier2 optimization)
* The remaining bits (12-63) are the actual version tag. */
uint64_t ma_version_tag;
#else
Py_DEPRECATED(3.12) uint64_t ma_version_tag;
#endif
* The remaining bits are not currently used. */
uint64_t _ma_watcher_tag;

PyDictKeysObject *ma_keys;

Expand Down
30 changes: 2 additions & 28 deletions Include/internal/pycore_dict.h
Original file line number Diff line number Diff line change
Expand Up @@ -230,31 +230,6 @@ static inline PyDictUnicodeEntry* DK_UNICODE_ENTRIES(PyDictKeysObject *dk) {
#define DICT_WATCHER_MASK ((1 << DICT_MAX_WATCHERS) - 1)
#define DICT_WATCHER_AND_MODIFICATION_MASK ((1 << (DICT_MAX_WATCHERS + DICT_WATCHED_MUTATION_BITS)) - 1)

#ifdef Py_GIL_DISABLED

#define THREAD_LOCAL_DICT_VERSION_COUNT 256
#define THREAD_LOCAL_DICT_VERSION_BATCH THREAD_LOCAL_DICT_VERSION_COUNT * DICT_VERSION_INCREMENT

static inline uint64_t
dict_next_version(PyInterpreterState *interp)
{
PyThreadState *tstate = PyThreadState_GET();
uint64_t cur_progress = (tstate->dict_global_version &
(THREAD_LOCAL_DICT_VERSION_BATCH - 1));
if (cur_progress == 0) {
uint64_t next = _Py_atomic_add_uint64(&interp->dict_state.global_version,
THREAD_LOCAL_DICT_VERSION_BATCH);
tstate->dict_global_version = next;
}
return tstate->dict_global_version += DICT_VERSION_INCREMENT;
}

#define DICT_NEXT_VERSION(INTERP) dict_next_version(INTERP)

#else
#define DICT_NEXT_VERSION(INTERP) \
((INTERP)->dict_state.global_version += DICT_VERSION_INCREMENT)
#endif

PyAPI_FUNC(void)
_PyDict_SendEvent(int watcher_bits,
Expand All @@ -263,20 +238,19 @@ _PyDict_SendEvent(int watcher_bits,
PyObject *key,
PyObject *value);

static inline uint64_t
static inline void
_PyDict_NotifyEvent(PyInterpreterState *interp,
PyDict_WatchEvent event,
PyDictObject *mp,
PyObject *key,
PyObject *value)
{
assert(Py_REFCNT((PyObject*)mp) > 0);
int watcher_bits = mp->ma_version_tag & DICT_WATCHER_MASK;
int watcher_bits = mp->_ma_watcher_tag & DICT_WATCHER_MASK;
if (watcher_bits) {
RARE_EVENT_STAT_INC(watched_dict_modification);
_PyDict_SendEvent(watcher_bits, event, mp, key, value);
}
return DICT_NEXT_VERSION(interp) | (mp->ma_version_tag & DICT_WATCHER_AND_MODIFICATION_MASK);
}

extern PyDictObject *_PyObject_MaterializeManagedDict(PyObject *obj);
Expand Down
4 changes: 0 additions & 4 deletions Include/internal/pycore_dict_state.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,10 +12,6 @@ extern "C" {
#define DICT_WATCHED_MUTATION_BITS 4

struct _Py_dict_state {
/*Global counter used to set ma_version_tag field of dictionary.
* It is incremented each time that a dictionary is created and each
* time that a dictionary is modified. */
uint64_t global_version;
uint32_t next_keys_version;
PyDict_WatchCallback watchers[DICT_MAX_WATCHERS];
};
Expand Down
5 changes: 3 additions & 2 deletions Include/internal/pycore_interp.h
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ extern "C" {
#include "pycore_qsbr.h" // struct _qsbr_state
#include "pycore_tstate.h" // _PyThreadStateImpl
#include "pycore_tuple.h" // struct _Py_tuple_state
#include "pycore_typeid.h" // struct _Py_type_id_pool
#include "pycore_uniqueid.h" // struct _Py_unique_id_pool
#include "pycore_typeobject.h" // struct types_state
#include "pycore_unicodeobject.h" // struct _Py_unicode_state
#include "pycore_warnings.h" // struct _warnings_runtime_state
Expand Down Expand Up @@ -221,7 +221,7 @@ struct _is {
#if defined(Py_GIL_DISABLED)
struct _mimalloc_interp_state mimalloc;
struct _brc_state brc; // biased reference counting state
struct _Py_type_id_pool type_ids;
struct _Py_unique_id_pool unique_ids; // object ids for per-thread refcounts
PyMutex weakref_locks[NUM_WEAKREF_LIST_LOCKS];
#endif

Expand Down Expand Up @@ -272,6 +272,7 @@ struct _is {
Py_ssize_t sys_tracing_threads; /* Count of threads with c_tracefunc set */
PyObject *monitoring_callables[PY_MONITORING_TOOL_IDS][_PY_MONITORING_EVENTS];
PyObject *monitoring_tool_names[PY_MONITORING_TOOL_IDS];
uintptr_t monitoring_tool_versions[PY_MONITORING_TOOL_IDS];

struct _Py_interp_cached_objects cached_objects;
struct _Py_interp_static_objects static_objects;
Expand Down
Loading

0 comments on commit 04b2a8f

Please sign in to comment.