GV

GeezerVison

The World Wide Web, restored to 800 pixels of glory.

Home|About|Gaming cabinet|Archives|How it works|Starter sites

On this site

  • Sign in
  • ActionsCI/CD and automation
  • CodespacesCloud development environments
  • All Features
  • Documentation
  • Training
  • Certifications
  • Build with Copilot
  • Customize Copilot
  • Integrations
  • Trending repos
  • GitHub Sponsors
  • Developer articles
  • Enterprises

This view

  • Original page
  • New address

GeezerVison is showing github.com — bpo-38605: Make postponed evaluation of annotations default by isidentical · Pull Request #20434 · python/cpython

bpo-38605: Make postponed evaluation of annotations default #20434

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

Sign up for GitHub

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
gvanrossum merged 18 commits into python:master from isidentical:bpo-38605
Oct 6, 2020

Uh oh!

There was an error while loading. Please reload this page.

Merged

bpo-38605: Make postponed evaluation of annotations default #20434

Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
4c5b314
make future annotations default
isidentical May 27, 2020
3402877
Fix test_coroutines
isidentical May 27, 2020
9a131a2
Regenerate bytecode for test_dis
isidentical May 27, 2020
fdcea4d
Regenerate static strings for docxmlrpc and pydoc tests
isidentical May 27, 2020
14e7c2d
Update tests for: syntax, opcodes, posonly, grammar...
isidentical May 27, 2020
f217d48
Refactor inspect tests(+doctests) with string annotations
isidentical May 27, 2020
6209fa0
Add documentation, tests for annotations
isidentical May 27, 2020
bbf01bb
Escape double stringified annotations on typing.ForwardRef
isidentical May 27, 2020
246577d
Fix test_dataclassess
isidentical May 27, 2020
1d77917
Initial attempt for typing fix
isidentical May 29, 2020
6bd5fee
Rename test, apply doc suggestion
isidentical May 29, 2020
1e2c3f8
Adapt code into the latest changes
isidentical Oct 1, 2020
0a04da8
Support double-stringified annotations in dataclasses
isidentical Oct 3, 2020
6d1feb5
Use get_type_hints in inspect.signature
isidentical Oct 4, 2020
86181e4
remove reduntant test
isidentical Oct 4, 2020
4276284
Add what's new entry
isidentical Oct 5, 2020
5ae4bd1
mention about inspect.signature
isidentical Oct 5, 2020
1e73aa7
Tweak what's new words
gvanrossum Oct 6, 2020
File filter
Filter by extension

Clear filters
Conversations
Failed to load comments.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Jump to
Jump to file
Failed to load files.
Loading

Uh oh!

There was an error while loading. Please reload this page.

Diff view
Diff view

There are no files selected for viewing

10 changes: 3 additions & 7 deletions 10 Doc/reference/compound_stmts.rst
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -610,13 +610,9 @@ following the parameter name. Any parameter may have an annotation, even those
``*identifier`` or ``**identifier``. Functions may have "return" annotation of
the form "``-> expression``" after the parameter list. These annotations can be
any valid Python expression. The presence of annotations does not change the
semantics of a function. The annotation values are available as values of
a dictionary keyed by the parameters' names in the :attr:`__annotations__`
attribute of the function object. If the ``annotations`` import from
:mod:`__future__` is used, annotations are preserved as strings at runtime which
enables postponed evaluation. Otherwise, they are evaluated when the function
definition is executed. In this case annotations may be evaluated in
a different order than they appear in the source code.
semantics of a function. The annotation values are available as string values
in a dictionary keyed by the parameters' names in the :attr:`__annotations__`
attribute of the function object.

.. index:: pair: lambda; expression

Expand Down
17 changes: 17 additions & 0 deletions 17 Doc/whatsnew/3.10.rst
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,23 @@ Summary -- Release highlights
New Features
============

.. _whatsnew310-pep563:

PEP 563: Postponed Evaluation of Annotations Becomes Default
------------------------------------------------------------

In Python 3.7, postponed evaluation of annotations was added,
to be enabled with a ``from __future__ import annotations``
directive. In 3.10 this became the default behavior, even
without that future directive. With this being default, all
annotations stored in :attr:`__annotations__` will be strings.
If needed, annotations can be resolved at runtime using
:func:`typing.get_type_hints`. See :pep:`563` for a full
description. Also, the :func:`inspect.signature` will try to
resolve types from now on, and when it fails it will fall back to
showing the string annotations. (Contributed by Batuhan Taskaya
in :issue:`38605`.)

* The :class:`int` type has a new method :meth:`int.bit_count`, returning the
number of ones in the binary expansion of a given integer, also known
as the population count. (Contributed by Niklas Fiekas in :issue:`29882`.)
Expand Down
13 changes: 10 additions & 3 deletions 13 Lib/dataclasses.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -398,8 +398,10 @@ def _create_fn(name, args, body, *, globals=None, locals=None,

ns = {}
exec(txt, globals, ns)
return ns['__create_fn__'](**locals)

func = ns['__create_fn__'](**locals)
for arg, annotation in func.__annotations__.copy().items():
func.__annotations__[arg] = locals[annotation]
Comment thread
isidentical marked this conversation as resolved.
Resolved

Uh oh!

There was an error while loading. Please reload this page.

return func

def _field_assign(frozen, name, value, self_name):
# If we're a frozen class, then assign to our fields in __init__
Expand Down Expand Up @@ -650,6 +652,11 @@ def _is_type(annotation, cls, a_module, a_type, is_type_predicate):
# a eval() penalty for every single field of every dataclass
# that's defined. It was judged not worth it.

# Strip away the extra quotes as a result of double-stringifying when the
# 'annotations' feature became default.
if annotation.startswith(("'", '"')) and annotation.endswith(("'", '"')):
annotation = annotation[1:-1]

match = _MODULE_IDENTIFIER_RE.match(annotation)
if match:
ns = None
Expand Down Expand Up @@ -990,7 +997,7 @@ def _process_class(cls, init, repr, eq, order, unsafe_hash, frozen):
if not getattr(cls, '__doc__'):
# Create a class doc-string.
cls.__doc__ = (cls.__name__ +
str(inspect.signature(cls)).replace(' -> None', ''))
str(inspect.signature(cls)).replace(' -> NoneType', ''))
Comment thread
gvanrossum marked this conversation as resolved.
Resolved

Uh oh!

There was an error while loading. Please reload this page.


return cls

Expand Down
19 changes: 17 additions & 2 deletions 19 Lib/inspect.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@
import tokenize
import token
import types
import typing
import warnings
import functools
import builtins
Expand Down Expand Up @@ -1877,7 +1878,10 @@ def _signature_is_functionlike(obj):
code = getattr(obj, '__code__', None)
defaults = getattr(obj, '__defaults__', _void) # Important to use _void ...
kwdefaults = getattr(obj, '__kwdefaults__', _void) # ... and not None here
annotations = getattr(obj, '__annotations__', None)
try:
annotations = _get_type_hints(obj)
except AttributeError:
annotations = None

return (isinstance(code, types.CodeType) and
isinstance(name, str) and
Expand Down Expand Up @@ -2118,6 +2122,16 @@ def p(name_node, default_node, default=empty):

return cls(parameters, return_annotation=cls.empty)

def _get_type_hints(func):
try:
return typing.get_type_hints(func)
except Exception:
# First, try to use the get_type_hints to resolve
# annotations. But for keeping the behavior intact
# if there was a problem with that (like the namespace
# can't resolve some annotation) continue to use
# string annotations
return func.__annotations__
Comment thread
isidentical marked this conversation as resolved.
Resolved

Uh oh!

There was an error while loading. Please reload this page.


def _signature_from_builtin(cls, func, skip_bound_arg=True):
"""Private helper function to get signature for
Expand Down Expand Up @@ -2161,7 +2175,8 @@ def _signature_from_function(cls, func, skip_bound_arg=True):
positional = arg_names[:pos_count]
keyword_only_count = func_code.co_kwonlyargcount
keyword_only = arg_names[pos_count:pos_count + keyword_only_count]
annotations = func.__annotations__
annotations = _get_type_hints(func)

defaults = func.__defaults__
kwdefaults = func.__kwdefaults__

Expand Down
6 changes: 0 additions & 6 deletions 6 Lib/test/dataclass_module_1.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
#from __future__ import annotations
USING_STRINGS = False

# dataclass_module_1.py and dataclass_module_1_str.py are identical
# except only the latter uses string annotations.

import dataclasses
import typing

Expand Down
32 changes: 0 additions & 32 deletions 32 Lib/test/dataclass_module_1_str.py
Show comments
View file
Open in desktop

This file was deleted.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

6 changes: 0 additions & 6 deletions 6 Lib/test/dataclass_module_2.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -1,9 +1,3 @@
#from __future__ import annotations
USING_STRINGS = False

# dataclass_module_2.py and dataclass_module_2_str.py are identical
# except only the latter uses string annotations.

from dataclasses import dataclass, InitVar
from typing import ClassVar

Expand Down
32 changes: 0 additions & 32 deletions 32 Lib/test/dataclass_module_2_str.py
Show comments
View file
Open in desktop

This file was deleted.

Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

2 changes: 0 additions & 2 deletions 2 Lib/test/dataclass_textanno.py
Show comments
View file
Open in desktop
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import annotations

import dataclasses


Expand Down
Loading
Oops, something went wrong.

Uh oh!

There was an error while loading. Please reload this page.

Add this suggestion to a batch that can be applied as a single commit. This suggestion is invalid because no changes were made to the code. Suggestions cannot be applied while the pull request is closed. Suggestions cannot be applied while viewing a subset of changes. Only one suggestion per line can be applied in a batch. Add this suggestion to a batch that can be applied as a single commit. Applying suggestions on deleted lines is not supported. You must change the existing code in this line in order to create a valid suggestion. Outdated suggestions cannot be applied. This suggestion has been applied or marked resolved. Suggestions cannot be applied from pending reviews. Suggestions cannot be applied on multi-line comments. Suggestions cannot be applied while the pull request is queued to merge. Suggestion cannot be applied right now. Please check back later.
You are visitor 01402520 — GeezerVison does not store the pages you look up.
Best viewed with Netscape Navigator 4.7 or Internet Explorer 6 at 800×600. No cookies required.