Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 14 additions & 0 deletions Doc/c-api/float.rst
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,20 @@ Floating-Point Objects
Return the minimum normalized positive float *DBL_MIN* as C :c:expr:`double`.


.. c:macro:: Py_MATH_El

High precision (long double) definition of :data:`~math.e` constant.

.. deprecated-removed:: 3.15 3.20


.. c:macro:: Py_MATH_PIl

High precision (long double) definition of :data:`~math.pi` constant.

.. deprecated-removed:: 3.15 3.20


.. c:macro:: Py_RETURN_NAN

Return :data:`math.nan` from a function.
Expand Down
2 changes: 2 additions & 0 deletions Doc/deprecations/c-api-pending-removal-in-3.20.rst
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,5 @@ Pending removal in Python 3.20
Use :c:func:`PyComplex_AsCComplex` and :c:func:`PyComplex_FromCComplex`
to convert a Python complex number to/from the C :c:type:`Py_complex`
representation.

* Macros :c:macro:`!Py_MATH_PIl` and :c:macro:`!Py_MATH_El`.
2 changes: 1 addition & 1 deletion Doc/library/functions.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1859,7 +1859,7 @@ are always available. They are listed here in alphabetical order.
the same data with other ordering tools such as :func:`max` that rely
on a different underlying method. Implementing all six comparisons
also helps avoid confusion for mixed type comparisons which can call
reflected the :meth:`~object.__gt__` method.
the reflected :meth:`~object.__gt__` method.

For sorting examples and a brief sorting tutorial, see :ref:`sortinghowto`.

Expand Down
2 changes: 2 additions & 0 deletions Doc/library/msvcrt.rst
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ api. The normal API deals only with ASCII characters and is of limited use
for internationalized applications. The wide char API should be used where
ever possible.

.. availability:: Windows.

.. versionchanged:: 3.3
Operations in this module now raise :exc:`OSError` where :exc:`IOError`
was raised.
Expand Down
2 changes: 2 additions & 0 deletions Doc/library/winreg.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ integer as the registry handle, a :ref:`handle object <handle-object>` is used
to ensure that the handles are closed correctly, even if the programmer neglects
to explicitly close them.

.. availability:: Windows.

.. _exception-changed:

.. versionchanged:: 3.3
Expand Down
2 changes: 2 additions & 0 deletions Doc/library/winsound.rst
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
The :mod:`winsound` module provides access to the basic sound-playing machinery
provided by Windows platforms. It includes functions and several constants.

.. availability:: Windows.


.. function:: Beep(frequency, duration)

Expand Down
6 changes: 1 addition & 5 deletions Doc/tools/templates/download.html
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,7 @@ <h1>{% trans %}Download Python {{ dl_version }} documentation{% endtrans %}</h1>

{% if last_updated %}<p><b>{% trans %}Last updated on: {{ last_updated }}.{% endtrans %}</b></p>{% endif %}

<p>{% trans %}To download an archive containing all the documents for this version of
Python in one of various formats, follow one of links in this table.{% endtrans %}</p>
<p>{% trans %}Download an archive containing all the documentation for this version of Python:{% endtrans %}</p>

<table class="docutils">
<tr>
Expand Down Expand Up @@ -62,8 +61,6 @@ <h1>{% trans %}Download Python {{ dl_version }} documentation{% endtrans %}</h1>
</tr>
</table>

<p>{% trans %}These archives contain all the content in the documentation.{% endtrans %}</p>

<p>{% trans %}
We no longer provide pre-built PDFs of the documentation.
To build a PDF archive, follow the instructions in the
Expand All @@ -75,7 +72,6 @@ <h1>{% trans %}Download Python {{ dl_version }} documentation{% endtrans %}</h1>
See the <a href="https://docs.python.org/{{ version }}/archives/">directory listing</a>
for file sizes.{% endtrans %}</p>


<h2>{% trans %}Problems{% endtrans %}</h2>
{% set bugs = pathto('bugs') %}
<p>{% trans bugs = bugs %}<a href="{{ bugs }}">Open an issue</a>
Expand Down
12 changes: 12 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -368,6 +368,14 @@ collections.abc
previously emitted if it was merely imported or accessed from the
:mod:`!collections.abc` module.


dataclasses
-----------

* Annotations for generated ``__init__`` methods no longer include internal
type names.


dbm
---

Expand Down Expand Up @@ -1068,6 +1076,10 @@ Deprecated C APIs
since 3.15 and will be removed in 3.17.
(Contributed by Nikita Sobolev in :gh:`136355`.)

* :c:macro:`!Py_MATH_El` and :c:macro:`!Py_MATH_PIl` are deprecated
since 3.15 and will be removed in 3.20.
(Contributed by Sergey B Kirpichev in :gh:`141004`.)


.. Add C API deprecations above alphabetically, not here at the end.

Expand Down
2 changes: 2 additions & 0 deletions Include/pymath.h
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,15 @@
/* High precision definition of pi and e (Euler)
* The values are taken from libc6's math.h.
*/
// Deprecated since Python 3.15.
#ifndef Py_MATH_PIl
#define Py_MATH_PIl 3.1415926535897932384626433832795029L
#endif
#ifndef Py_MATH_PI
#define Py_MATH_PI 3.14159265358979323846
#endif

// Deprecated since Python 3.15.
#ifndef Py_MATH_El
#define Py_MATH_El 2.7182818284590452353602874713526625L
#endif
Expand Down
94 changes: 80 additions & 14 deletions Lib/dataclasses.py
Original file line number Diff line number Diff line change
Expand Up @@ -441,9 +441,11 @@ def __init__(self, globals):
self.locals = {}
self.overwrite_errors = {}
self.unconditional_adds = {}
self.method_annotations = {}

def add_fn(self, name, args, body, *, locals=None, return_type=MISSING,
overwrite_error=False, unconditional_add=False, decorator=None):
overwrite_error=False, unconditional_add=False, decorator=None,
annotation_fields=None):
if locals is not None:
self.locals.update(locals)

Expand All @@ -464,16 +466,14 @@ def add_fn(self, name, args, body, *, locals=None, return_type=MISSING,

self.names.append(name)

if return_type is not MISSING:
self.locals[f'__dataclass_{name}_return_type__'] = return_type
return_annotation = f'->__dataclass_{name}_return_type__'
else:
return_annotation = ''
if annotation_fields is not None:
self.method_annotations[name] = (annotation_fields, return_type)

args = ','.join(args)
body = '\n'.join(body)

# Compute the text of the entire function, add it to the text we're generating.
self.src.append(f'{f' {decorator}\n' if decorator else ''} def {name}({args}){return_annotation}:\n{body}')
self.src.append(f'{f' {decorator}\n' if decorator else ''} def {name}({args}):\n{body}')

def add_fns_to_class(self, cls):
# The source to all of the functions we're generating.
Expand Down Expand Up @@ -509,6 +509,15 @@ def add_fns_to_class(self, cls):
# Now that we've generated the functions, assign them into cls.
for name, fn in zip(self.names, fns):
fn.__qualname__ = f"{cls.__qualname__}.{fn.__name__}"

try:
annotation_fields, return_type = self.method_annotations[name]
except KeyError:
pass
else:
annotate_fn = _make_annotate_function(cls, name, annotation_fields, return_type)
fn.__annotate__ = annotate_fn

if self.unconditional_adds.get(name, False):
setattr(cls, name, fn)
else:
Expand All @@ -524,6 +533,44 @@ def add_fns_to_class(self, cls):
raise TypeError(error_msg)


def _make_annotate_function(__class__, method_name, annotation_fields, return_type):
# Create an __annotate__ function for a dataclass
# Try to return annotations in the same format as they would be
# from a regular __init__ function

def __annotate__(format, /):
Format = annotationlib.Format
match format:
case Format.VALUE | Format.FORWARDREF | Format.STRING:
cls_annotations = {}
for base in reversed(__class__.__mro__):
cls_annotations.update(
annotationlib.get_annotations(base, format=format)
)

new_annotations = {}
for k in annotation_fields:
new_annotations[k] = cls_annotations[k]

if return_type is not MISSING:
if format == Format.STRING:
new_annotations["return"] = annotationlib.type_repr(return_type)
else:
new_annotations["return"] = return_type

return new_annotations

case _:
raise NotImplementedError(format)

# This is a flag for _add_slots to know it needs to regenerate this method
# In order to remove references to the original class when it is replaced
__annotate__.__generated_by_dataclasses__ = True
__annotate__.__qualname__ = f"{__class__.__qualname__}.{method_name}.__annotate__"

return __annotate__


def _field_assign(frozen, name, value, self_name):
# If we're a frozen class, then assign to our fields in __init__
# via object.__setattr__. Otherwise, just use a simple
Expand Down Expand Up @@ -612,7 +659,7 @@ def _init_param(f):
elif f.default_factory is not MISSING:
# There's a factory function. Set a marker.
default = '=__dataclass_HAS_DEFAULT_FACTORY__'
return f'{f.name}:__dataclass_type_{f.name}__{default}'
return f'{f.name}{default}'


def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init,
Expand All @@ -635,11 +682,10 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init,
raise TypeError(f'non-default argument {f.name!r} '
f'follows default argument {seen_default.name!r}')

locals = {**{f'__dataclass_type_{f.name}__': f.type for f in fields},
**{'__dataclass_HAS_DEFAULT_FACTORY__': _HAS_DEFAULT_FACTORY,
'__dataclass_builtins_object__': object,
}
}
annotation_fields = [f.name for f in fields if f.init]

locals = {'__dataclass_HAS_DEFAULT_FACTORY__': _HAS_DEFAULT_FACTORY,
'__dataclass_builtins_object__': object}

body_lines = []
for f in fields:
Expand Down Expand Up @@ -670,7 +716,8 @@ def _init_fn(fields, std_fields, kw_only_fields, frozen, has_post_init,
[self_name] + _init_params,
body_lines,
locals=locals,
return_type=None)
return_type=None,
annotation_fields=annotation_fields)


def _frozen_get_del_attr(cls, fields, func_builder):
Expand Down Expand Up @@ -1337,6 +1384,25 @@ def _add_slots(cls, is_frozen, weakref_slot, defined_fields):
or _update_func_cell_for__class__(member.fdel, cls, newcls)):
break

# Get new annotations to remove references to the original class
# in forward references
newcls_ann = annotationlib.get_annotations(
newcls, format=annotationlib.Format.FORWARDREF)

# Fix references in dataclass Fields
for f in getattr(newcls, _FIELDS).values():
try:
ann = newcls_ann[f.name]
except KeyError:
pass
else:
f.type = ann

# Fix the class reference in the __annotate__ method
init_annotate = newcls.__init__.__annotate__
if getattr(init_annotate, "__generated_by_dataclasses__", False):
_update_func_cell_for__class__(init_annotate, cls, newcls)

return newcls


Expand Down
19 changes: 19 additions & 0 deletions Lib/test/libregrtest/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -294,6 +294,25 @@ def clear_caches():
else:
importlib_metadata.FastPath.__new__.cache_clear()

try:
encodings = sys.modules['encodings']
except KeyError:
pass
else:
encodings._cache.clear()

try:
codecs = sys.modules['codecs']
except KeyError:
pass
else:
# There's no direct API to clear the codecs search cache, but
# `unregister` clears it implicitly.
def noop_search_function(name):
return None
codecs.register(noop_search_function)
codecs.unregister(noop_search_function)


def get_build_info():
# Get most important configure and build options as a list of strings.
Expand Down
Loading
Loading