Skip to content

Commit 43e7796

Browse files
committed
Merge main (TODO: PyObject *value etc.)
2 parents b8b4f15 + 7dcd28e commit 43e7796

37 files changed

+642
-190
lines changed

Doc/library/enum.rst

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -242,8 +242,8 @@ Data Types
242242

243243
Member values can be anything: :class:`int`, :class:`str`, etc.. If
244244
the exact value is unimportant you may use :class:`auto` instances and an
245-
appropriate value will be chosen for you. Care must be taken if you mix
246-
:class:`auto` with other values.
245+
appropriate value will be chosen for you. See :class:`auto` for the
246+
details.
247247

248248
.. attribute:: Enum._ignore_
249249

@@ -778,7 +778,16 @@ Utilities and Decorators
778778
For *Enum* and *IntEnum* that appropriate value will be the last value plus
779779
one; for *Flag* and *IntFlag* it will be the first power-of-two greater
780780
than the last value; for *StrEnum* it will be the lower-cased version of the
781-
member's name.
781+
member's name. Care must be taken if mixing *auto()* with manually specified
782+
values.
783+
784+
*auto* instances are only resolved when at the top level of an assignment:
785+
786+
* ``FIRST = auto()`` will work (auto() is replaced with ``1``);
787+
* ``SECOND = auto(), -2`` will work (auto is replaced with ``2``, so ``2, -2`` is
788+
used to create the ``SECOND`` enum member;
789+
* ``THREE = [auto(), -3]`` will *not* work (``<auto instance>, -3`` is used to
790+
create the ``THREE`` enum member)
782791

783792
``_generate_next_value_`` can be overridden to customize the values used by
784793
*auto*.

Doc/tutorial/errors.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ Raising and Handling Multiple Unrelated Exceptions
496496
==================================================
497497

498498
There are situations where it is necessary to report several exceptions that
499-
have occurred. This it often the case in concurrency frameworks, when several
499+
have occurred. This is often the case in concurrency frameworks, when several
500500
tasks may have failed in parallel, but there are also other use cases where
501501
it is desirable to continue execution and collect multiple errors rather than
502502
raise the first exception.

Doc/whatsnew/3.12.rst

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,27 @@ Important deprecations, removals or restrictions:
7575
Improved Error Messages
7676
=======================
7777

78+
* Improve the error suggestion for :exc:`NameError` exceptions for instances.
79+
Now if a :exc:`NameError` is raised in a method and the instance has an
80+
attribute that's exactly equal to the name in the exception, the suggestion
81+
will include ``self.<NAME>`` instead of the closest match in the method
82+
scope. Contributed by Pablo Galindo in :gh:`99139`.
83+
84+
>>> class A:
85+
... def __init__(self):
86+
... self.blech = 1
87+
...
88+
... def foo(self):
89+
... somethin = blech
90+
91+
>>> A().foo()
92+
Traceback (most recent call last):
93+
File "<stdin>", line 1
94+
somethin = blech
95+
^^^^^
96+
NameError: name 'blech' is not defined. Did you mean: 'self.blech'?
97+
98+
7899
* Improve the :exc:`SyntaxError` error message when the user types ``import x
79100
from y`` instead of ``from y import x``. Contributed by Pablo Galindo in :gh:`98931`.
80101

Grammar/python.gram

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1254,8 +1254,8 @@ invalid_try_stmt:
12541254
| a='try' ':' NEWLINE !INDENT {
12551255
RAISE_INDENTATION_ERROR("expected an indented block after 'try' statement on line %d", a->lineno) }
12561256
| 'try' ':' block !('except' | 'finally') { RAISE_SYNTAX_ERROR("expected 'except' or 'finally' block") }
1257-
| 'try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block* {
1258-
RAISE_SYNTAX_ERROR("cannot have both 'except' and 'except*' on the same 'try'") }
1257+
| a='try' ':' block* ((except_block+ except_star_block) | (except_star_block+ except_block)) block* {
1258+
RAISE_SYNTAX_ERROR_KNOWN_LOCATION(a, "cannot have both 'except' and 'except*' on the same 'try'") }
12591259
invalid_except_stmt:
12601260
| 'except' '*'? a=expression ',' expressions ['as' NAME ] ':' {
12611261
RAISE_SYNTAX_ERROR_STARTING_FROM(a, "multiple exception types must be parenthesized") }

Include/internal/pycore_global_strings.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,6 @@ struct _Py_global_strings {
3737
STRUCT_FOR_STR(anon_string, "<string>")
3838
STRUCT_FOR_STR(anon_unknown, "<unknown>")
3939
STRUCT_FOR_STR(close_br, "}")
40-
STRUCT_FOR_STR(comma_sep, ", ")
4140
STRUCT_FOR_STR(dbl_close_br, "}}")
4241
STRUCT_FOR_STR(dbl_open_br, "{{")
4342
STRUCT_FOR_STR(dbl_percent, "%%")
@@ -601,6 +600,7 @@ struct _Py_global_strings {
601600
STRUCT_FOR_ID(seek)
602601
STRUCT_FOR_ID(seekable)
603602
STRUCT_FOR_ID(selectors)
603+
STRUCT_FOR_ID(self)
604604
STRUCT_FOR_ID(send)
605605
STRUCT_FOR_ID(sep)
606606
STRUCT_FOR_ID(sequence)

Include/internal/pycore_runtime_init_generated.h

Lines changed: 7 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Lib/ensurepip/__init__.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
__all__ = ["version", "bootstrap"]
1212
_PACKAGE_NAMES = ('setuptools', 'pip')
1313
_SETUPTOOLS_VERSION = "65.5.0"
14-
_PIP_VERSION = "22.3"
14+
_PIP_VERSION = "22.3.1"
1515
_PROJECTS = [
1616
("setuptools", _SETUPTOOLS_VERSION, "py3"),
1717
("pip", _PIP_VERSION, "py3"),
1.96 MB
Binary file not shown.

Lib/enum.py

Lines changed: 25 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,8 @@ class auto:
171171
"""
172172
Instances are replaced with an appropriate value in Enum class suites.
173173
"""
174-
value = _auto_null
174+
def __init__(self, value=_auto_null):
175+
self.value = value
175176

176177
def __repr__(self):
177178
return "auto(%r)" % self.value
@@ -427,15 +428,31 @@ def __setitem__(self, key, value):
427428
elif isinstance(value, member):
428429
# unwrap value here -- it will become a member
429430
value = value.value
431+
non_auto_store = True
432+
single = False
430433
if isinstance(value, auto):
431-
if value.value == _auto_null:
432-
value.value = self._generate_next_value(
433-
key, 1, len(self._member_names), self._last_values[:],
434-
)
435-
self._auto_called = True
436-
value = value.value
434+
single = True
435+
value = (value, )
436+
if isinstance(value, tuple):
437+
auto_valued = []
438+
for v in value:
439+
if isinstance(v, auto):
440+
non_auto_store = False
441+
if v.value == _auto_null:
442+
v.value = self._generate_next_value(
443+
key, 1, len(self._member_names), self._last_values[:],
444+
)
445+
self._auto_called = True
446+
v = v.value
447+
self._last_values.append(v)
448+
auto_valued.append(v)
449+
if single:
450+
value = auto_valued[0]
451+
else:
452+
value = tuple(auto_valued)
437453
self._member_names[key] = None
438-
self._last_values.append(value)
454+
if non_auto_store:
455+
self._last_values.append(value)
439456
super().__setitem__(key, value)
440457

441458
def update(self, members, **more_members):

Lib/test/test_abc.py

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ class C(metaclass=abc_ABCMeta):
154154
@abc.abstractmethod
155155
def method_one(self):
156156
pass
157-
msg = r"class C without an implementation for abstract method method_one"
157+
msg = r"class C without an implementation for abstract method 'method_one'"
158158
self.assertRaisesRegex(TypeError, msg, C)
159159

160160
def test_object_new_with_many_abstractmethods(self):
@@ -165,7 +165,7 @@ def method_one(self):
165165
@abc.abstractmethod
166166
def method_two(self):
167167
pass
168-
msg = r"class C without an implementation for abstract methods method_one, method_two"
168+
msg = r"class C without an implementation for abstract methods 'method_one', 'method_two'"
169169
self.assertRaisesRegex(TypeError, msg, C)
170170

171171
def test_abstractmethod_integration(self):
@@ -535,7 +535,7 @@ def updated_foo(self):
535535
A.foo = updated_foo
536536
abc.update_abstractmethods(A)
537537
self.assertEqual(A.__abstractmethods__, {'foo', 'bar'})
538-
msg = "class A without an implementation for abstract methods bar, foo"
538+
msg = "class A without an implementation for abstract methods 'bar', 'foo'"
539539
self.assertRaisesRegex(TypeError, msg, A)
540540

541541
def test_update_implementation(self):
@@ -547,7 +547,7 @@ def foo(self):
547547
class B(A):
548548
pass
549549

550-
msg = "class B without an implementation for abstract method foo"
550+
msg = "class B without an implementation for abstract method 'foo'"
551551
self.assertRaisesRegex(TypeError, msg, B)
552552
self.assertEqual(B.__abstractmethods__, {'foo'})
553553

@@ -605,7 +605,7 @@ def foo(self):
605605

606606
abc.update_abstractmethods(B)
607607

608-
msg = "class B without an implementation for abstract method foo"
608+
msg = "class B without an implementation for abstract method 'foo'"
609609
self.assertRaisesRegex(TypeError, msg, B)
610610

611611
def test_update_layered_implementation(self):
@@ -627,7 +627,7 @@ def foo(self):
627627

628628
abc.update_abstractmethods(C)
629629

630-
msg = "class C without an implementation for abstract method foo"
630+
msg = "class C without an implementation for abstract method 'foo'"
631631
self.assertRaisesRegex(TypeError, msg, C)
632632

633633
def test_update_multi_inheritance(self):

0 commit comments

Comments
 (0)