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
15 changes: 10 additions & 5 deletions Doc/library/logging.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1082,12 +1082,13 @@ LoggerAdapter Objects
information into logging calls. For a usage example, see the section on
:ref:`adding contextual information to your logging output <context-info>`.

.. class:: LoggerAdapter(logger, extra, merge_extra=False)
.. class:: LoggerAdapter(logger, extra=None, merge_extra=False)

Returns an instance of :class:`LoggerAdapter` initialized with an
underlying :class:`Logger` instance, a dict-like object (*extra*), and a
boolean (*merge_extra*) indicating whether or not the *extra* argument of
individual log calls should be merged with the :class:`LoggerAdapter` extra.
underlying :class:`Logger` instance, an optional dict-like object (*extra*),
and an optional boolean (*merge_extra*) indicating whether or not
the *extra* argument of individual log calls should be merged with
the :class:`LoggerAdapter` extra.
The default behavior is to ignore the *extra* argument of individual log
calls and only use the one of the :class:`LoggerAdapter` instance

Expand Down Expand Up @@ -1127,9 +1128,13 @@ information into logging calls. For a usage example, see the section on
Attribute :attr:`!manager` and method :meth:`!_log` were added, which
delegate to the underlying logger and allow adapters to be nested.

.. versionchanged:: 3.10

The *extra* argument is now optional.

.. versionchanged:: 3.13

The *merge_extra* argument was added.
The *merge_extra* parameter was added.


Thread Safety
Expand Down
48 changes: 39 additions & 9 deletions Doc/library/unicodedata.rst
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ following functions:
this module.


.. function:: lookup(name)
.. function:: lookup(name, /)

Look up character by name. If a character with the given name is found, return
the corresponding character. If not found, :exc:`KeyError` is raised.
Expand Down Expand Up @@ -94,7 +94,7 @@ following functions:
0.5


.. function:: category(chr)
.. function:: category(chr, /)

Returns the general category assigned to the character *chr* as
string. General category names consist of two letters.
Expand All @@ -106,7 +106,7 @@ following functions:
'Lu'


.. function:: bidirectional(chr)
.. function:: bidirectional(chr, /)

Returns the bidirectional class assigned to the character *chr* as
string. If no such value is defined, an empty string is returned.
Expand All @@ -118,7 +118,7 @@ following functions:
'AN'


.. function:: combining(chr)
.. function:: combining(chr, /)

Returns the canonical combining class assigned to the character *chr*
as integer. Returns ``0`` if no combining class is defined.
Expand All @@ -127,14 +127,14 @@ following functions:
for more information.


.. function:: east_asian_width(chr)
.. function:: east_asian_width(chr, /)

Returns the east asian width assigned to the character *chr* as
string. For a list of widths and or more information, see the
`Unicode Standard Annex #11 <https://www.unicode.org/reports/tr11/>`_.


.. function:: mirrored(chr)
.. function:: mirrored(chr, /)

Returns the mirrored property assigned to the character *chr* as
integer. Returns ``1`` if the character has been identified as a "mirrored"
Expand All @@ -144,7 +144,37 @@ following functions:
1


.. function:: decomposition(chr)
.. function:: isxidstart(chr, /)

Return ``True`` if *chr* is a valid identifier start per the
`Unicode Standard Annex #31 <https://www.unicode.org/reports/tr31/>`_,
that is, it has the ``XID_Start`` property. Return ``False`` otherwise.
For example::

>>> unicodedata.isxidstart('S')
True
>>> unicodedata.isxidstart('0')
False

.. versionadded:: next


.. function:: isxidcontinue(chr, /)

Return ``True`` if *chr* is a valid identifier character per the
`Unicode Standard Annex #31 <https://www.unicode.org/reports/tr31/>`_,
that is, it has the ``XID_Continue`` property. Return ``False`` otherwise.
For example::

>>> unicodedata.isxidcontinue('S')
True
>>> unicodedata.isxidcontinue(' ')
False

.. versionadded:: next


.. function:: decomposition(chr, /)

Returns the character decomposition mapping assigned to the character
*chr* as string. An empty string is returned in case no such mapping is
Expand All @@ -154,7 +184,7 @@ following functions:
'0041 0303'


.. function:: normalize(form, unistr)
.. function:: normalize(form, unistr, /)

Return the normal form *form* for the Unicode string *unistr*. Valid values for
*form* are 'NFC', 'NFKC', 'NFD', and 'NFKD'.
Expand Down Expand Up @@ -187,7 +217,7 @@ following functions:
doesn't, they may not compare equal.


.. function:: is_normalized(form, unistr)
.. function:: is_normalized(form, unistr, /)

Return whether the Unicode string *unistr* is in the normal form *form*. Valid
values for *form* are 'NFC', 'NFKC', 'NFD', and 'NFKD'.
Expand Down
5 changes: 5 additions & 0 deletions Doc/whatsnew/3.15.rst
Original file line number Diff line number Diff line change
Expand Up @@ -794,6 +794,11 @@ unicodedata

* The Unicode database has been updated to Unicode 17.0.0.

* Add :func:`unicodedata.isxidstart` and :func:`unicodedata.isxidcontinue`
functions to check whether a character can start or continue a
`Unicode Standard Annex #31 <https://www.unicode.org/reports/tr31/>`_ identifier.
(Contributed by Stan Ulbrych in :gh:`129117`.)


wave
----
Expand Down
3 changes: 2 additions & 1 deletion Include/internal/pycore_compile.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,8 @@ extern int _PyAST_Preprocess(
PyObject *filename,
int optimize,
int ff_features,
int syntax_check_only);
int syntax_check_only,
int enable_warnings);


typedef struct {
Expand Down
25 changes: 25 additions & 0 deletions Include/internal/pycore_unicodectype.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
#ifndef Py_INTERNAL_UNICODECTYPE_H
#define Py_INTERNAL_UNICODECTYPE_H
#ifdef __cplusplus
extern "C" {
#endif

#ifndef Py_BUILD_CORE
# error "this header requires Py_BUILD_CORE define"
#endif

extern int _PyUnicode_ToLowerFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_ToTitleFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_ToUpperFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_ToFoldedFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_IsCaseIgnorable(Py_UCS4 ch);
extern int _PyUnicode_IsCased(Py_UCS4 ch);

// Export for 'unicodedata' shared extension.
PyAPI_FUNC(int) _PyUnicode_IsXidStart(Py_UCS4 ch);
PyAPI_FUNC(int) _PyUnicode_IsXidContinue(Py_UCS4 ch);

#ifdef __cplusplus
}
#endif
#endif /* !Py_INTERNAL_UNICODECTYPE_H */
12 changes: 0 additions & 12 deletions Include/internal/pycore_unicodeobject.h
Original file line number Diff line number Diff line change
Expand Up @@ -74,18 +74,6 @@ _PyUnicodeWriter_WriteCharInline(_PyUnicodeWriter *writer, Py_UCS4 ch)
return 0;
}


/* --- Characters Type APIs ----------------------------------------------- */

extern int _PyUnicode_IsXidStart(Py_UCS4 ch);
extern int _PyUnicode_IsXidContinue(Py_UCS4 ch);
extern int _PyUnicode_ToLowerFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_ToTitleFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_ToUpperFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_ToFoldedFull(Py_UCS4 ch, Py_UCS4 *res);
extern int _PyUnicode_IsCaseIgnorable(Py_UCS4 ch);
extern int _PyUnicode_IsCased(Py_UCS4 ch);

/* --- Unicode API -------------------------------------------------------- */

// Export for '_json' shared extension
Expand Down
11 changes: 6 additions & 5 deletions Lib/logging/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -1849,9 +1849,9 @@ class LoggerAdapter(object):

def __init__(self, logger, extra=None, merge_extra=False):
"""
Initialize the adapter with a logger and a dict-like object which
provides contextual information. This constructor signature allows
easy stacking of LoggerAdapters, if so desired.
Initialize the adapter with a logger and an optional dict-like object
which provides contextual information. This constructor signature
allows easy stacking of LoggerAdapters, if so desired.

You can effectively pass keyword arguments as shown in the
following example:
Expand Down Expand Up @@ -1882,8 +1882,9 @@ def process(self, msg, kwargs):
Normally, you'll only need to override this one method in a
LoggerAdapter subclass for your specific needs.
"""
if self.merge_extra and "extra" in kwargs:
kwargs["extra"] = {**self.extra, **kwargs["extra"]}
if self.merge_extra and kwargs.get("extra") is not None:
if self.extra is not None:
kwargs["extra"] = {**self.extra, **kwargs["extra"]}
else:
kwargs["extra"] = self.extra
return msg, kwargs
Expand Down
4 changes: 4 additions & 0 deletions Lib/test/support/socket_helper.py
Original file line number Diff line number Diff line change
Expand Up @@ -259,6 +259,10 @@ def filter_error(err):
# raise OSError('socket error', msg) from msg
elif len(a) >= 2 and isinstance(a[1], OSError):
err = a[1]
# The error can also be wrapped as __cause__:
# raise URLError(f"ftp error: {exp}") from exp
elif isinstance(err, urllib.error.URLError) and err.__cause__:
err = err.__cause__
else:
break
filter_error(err)
Expand Down
55 changes: 0 additions & 55 deletions Lib/test/test_ast/test_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -1057,61 +1057,6 @@ def test_repr_large_input_crash(self):
r"Exceeds the limit \(\d+ digits\)"):
repr(ast.Constant(value=eval(source)))

def test_pep_765_warnings(self):
srcs = [
textwrap.dedent("""
def f():
try:
pass
finally:
return 42
"""),
textwrap.dedent("""
for x in y:
try:
pass
finally:
break
"""),
textwrap.dedent("""
for x in y:
try:
pass
finally:
continue
"""),
]
for src in srcs:
with self.assertWarnsRegex(SyntaxWarning, 'finally'):
ast.parse(src)

def test_pep_765_no_warnings(self):
srcs = [
textwrap.dedent("""
try:
pass
finally:
def f():
return 42
"""),
textwrap.dedent("""
try:
pass
finally:
for x in y:
break
"""),
textwrap.dedent("""
try:
pass
finally:
for x in y:
continue
"""),
]
for src in srcs:
ast.parse(src)

def test_tstring(self):
# Test AST structure for simple t-string
tree = ast.parse('t"Hello"')
Expand Down
60 changes: 60 additions & 0 deletions Lib/test/test_compile.py
Original file line number Diff line number Diff line change
Expand Up @@ -1745,6 +1745,66 @@ def test_compile_warning_in_finally(self):
self.assertEqual(wm.category, SyntaxWarning)
self.assertIn("\"is\" with 'int' literal", str(wm.message))

@support.subTests('src', [
textwrap.dedent("""
def f():
try:
pass
finally:
return 42
"""),
textwrap.dedent("""
for x in y:
try:
pass
finally:
break
"""),
textwrap.dedent("""
for x in y:
try:
pass
finally:
continue
"""),
])
def test_pep_765_warnings(self, src):
with self.assertWarnsRegex(SyntaxWarning, 'finally'):
compile(src, '<string>', 'exec')
with warnings.catch_warnings():
warnings.simplefilter("error")
tree = ast.parse(src)
with self.assertWarnsRegex(SyntaxWarning, 'finally'):
compile(tree, '<string>', 'exec')

@support.subTests('src', [
textwrap.dedent("""
try:
pass
finally:
def f():
return 42
"""),
textwrap.dedent("""
try:
pass
finally:
for x in y:
break
"""),
textwrap.dedent("""
try:
pass
finally:
for x in y:
continue
"""),
])
def test_pep_765_no_warnings(self, src):
with warnings.catch_warnings():
warnings.simplefilter("error")
compile(src, '<string>', 'exec')


class TestBooleanExpression(unittest.TestCase):
class Value:
Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_json/test_scanstring.py
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,7 @@ def test_bad_escapes(self):

def test_overflow(self):
with self.assertRaises(OverflowError):
self.json.decoder.scanstring(b"xxx", sys.maxsize+1)
self.json.decoder.scanstring("xxx", sys.maxsize+1)


class TestPyScanstring(TestScanstring, PyTest): pass
Expand Down
Loading
Loading