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
7 changes: 5 additions & 2 deletions Lib/idlelib/configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -2285,10 +2285,13 @@ def make_callback(var, config):
def default_callback(*params):
"Add config values to changes instance."
value = var.get()
# A blanked int entry is an empty string; do not save it as an
# invalid config value (gh-83653).
if value != '':
changes.add_option(*config, value)
else:
# A blanked int entry: do not save an invalid value, and
# forget the value recorded while editing (gh-75487).
config_type, section, item = config
changes[config_type].get(section, {}).pop(item, None)
return default_callback

def attach(self):
Expand Down
4 changes: 4 additions & 0 deletions Lib/idlelib/idle_test/test_configdialog.py
Original file line number Diff line number Diff line change
Expand Up @@ -1711,6 +1711,10 @@ def test_make_callback(self):
sv.set('5')
cb()
self.assertEqual(changes['main']['section']['option'], '5')
# gh-75487: blanking the entry forgets the value recorded before.
sv.set('')
cb()
self.assertNotIn('option', changes['main']['section'])
changes.clear()

def test_attach_detach(self):
Expand Down
45 changes: 37 additions & 8 deletions Lib/idlelib/idle_test/test_pyparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ def char_in_string_false(index): return False
' b=True):\n'
' pass\n'
)
pos0, pos = 33, 42 # Start of 'class...', ' def' lines.
pos0, pos, pos1 = 33, 42, 94 # Start of 'class', 'def', 'pass' lines.

# Passing no value or non-callable should fail (issue 32989).
with self.assertRaises(TypeError):
Expand All @@ -91,18 +91,18 @@ def char_in_string_false(index): return False
self.assertIsNone(start(is_char_in_string=lambda index: True))

# Make all text look like it's not in a string. This means that it
# found a good start position.
eq(start(char_in_string_false), pos)
# found a good start position: the last statement.
eq(start(char_in_string_false), pos1)

# If the beginning of the def line is not in a string, then it
# returns that as the index.
eq(start(is_char_in_string=lambda index: index > pos), pos)
# If the beginning of the def line is in a string, then it
# looks for a previous index.
eq(start(is_char_in_string=lambda index: index >= pos), pos0)
# If everything before the 'def' is in a string, then returns None.
# The non-continuation def line returns 44 (see below).
eq(start(is_char_in_string=lambda index: index < pos), None)
# If everything before the 'def' is in a string, then returns
# the start of the 'pass' line.
eq(start(is_char_in_string=lambda index: index < pos), pos1)

# Code without extra line break in def line - mostly returns the same
# values.
Expand All @@ -111,12 +111,41 @@ def char_in_string_false(index): return False
' def __init__(self, a, b=True):\n'
' pass\n'
) # Does not affect class, def positions.
eq(start(char_in_string_false), pos)
pos1 = 77 # Start of 'pass' line.
eq(start(char_in_string_false), pos1)
eq(start(is_char_in_string=lambda index: index > pos), pos)
eq(start(is_char_in_string=lambda index: index >= pos), pos0)
# When the def line isn't split, this returns which doesn't match the
# split line test.
eq(start(is_char_in_string=lambda index: index < pos), pos)
eq(start(is_char_in_string=lambda index: index < pos), pos1)

# gh-85560: 'else' of a conditional expression at the start of
# a continuation line does not start a statement.
setcode('def f():\n'
' return (1 if x\n'
' else 0)\n')
eq(start(char_in_string_false), 9) # Start of 'return' line.
setcode('if x:\n'
' pass\n'
'else:\n'
' x = 1\n')
eq(start(char_in_string_false), 15)
setcode('if x:\n'
' pass\n'
'else : # comment\n'
' x = 1\n')
eq(start(char_in_string_false), 15)
# A yield expression can start a continuation line too.
setcode('def f():\n'
' x = (\n'
' yield y)\n')
eq(start(char_in_string_false), 0)
# Other statements which cannot start a continuation line.
for stmt in ('with x:', 'del x', 'global x', 'nonlocal x', 'pass',
'finally:'):
with self.subTest(stmt=stmt):
setcode(f'if x:\n pass\n{stmt}\n')
eq(start(char_in_string_false), 15)

def test_set_lo(self):
code = (
Expand Down
9 changes: 7 additions & 2 deletions Lib/idlelib/pyparse.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
^
[ \t]*
(?: while
| else
| else (?= [ \t]* : ) # not "else" of a conditional expression
| def
| return
| assert
Expand All @@ -34,7 +34,12 @@
| except
| raise
| import
| yield
| with
| del
| global
| nonlocal
| pass
| finally
)
\b
""", re.VERBOSE | re.MULTILINE).search
Expand Down
2 changes: 2 additions & 0 deletions Lib/ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -2458,6 +2458,8 @@ class _IPv6Constants:
_private_networks_exceptions = [
IPv6Network('2001:1::1/128'),
IPv6Network('2001:1::2/128'),
# RFC 9665: https://www.rfc-editor.org/rfc/rfc9665.html
IPv6Network('2001:1::3/128'),
IPv6Network('2001:3::/32'),
IPv6Network('2001:4:112::/48'),
IPv6Network('2001:20::/28'),
Expand Down
4 changes: 4 additions & 0 deletions Lib/test/test_ipaddress.py
Original file line number Diff line number Diff line change
Expand Up @@ -2535,6 +2535,10 @@ def testReservedIpv6(self):
self.assertFalse(ipaddress.ip_address('2001::').is_global)
self.assertTrue(ipaddress.ip_address('2001:1::1').is_global)
self.assertTrue(ipaddress.ip_address('2001:1::2').is_global)
# gh-151049: RFC 9665 anycast address (IANA 2024-04 registration)
self.assertTrue(ipaddress.ip_address('2001:1::3').is_global)
self.assertFalse(ipaddress.ip_address('2001:1::3').is_private)
self.assertFalse(ipaddress.ip_address('2001:1::4').is_global)
self.assertFalse(ipaddress.ip_address('2001:2::').is_global)
self.assertTrue(ipaddress.ip_address('2001:3::').is_global)
self.assertFalse(ipaddress.ip_address('2001:4::').is_global)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix saving a truncated number when an integer entry in the IDLE Settings
dialog is blanked with the Backspace key.
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
Fix IDLE failing to find the opening parenthesis when a continuation line
inside the parentheses starts with ``else`` of a conditional expression or
with ``yield``.
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
:mod:`ipaddress`: fix ``is_global`` and ``is_private`` for the
``2001:1::3/128`` (DNS-SD Service Registration Protocol Anycast) address,
which IANA registered as globally reachable per :rfc:`9665`. It is now
correctly reported with ``is_global`` ``True`` and ``is_private`` ``False``.
14 changes: 7 additions & 7 deletions configure

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 7 additions & 7 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -6555,13 +6555,13 @@ AC_CHECK_FUNCS(
[AC_MSG_ERROR([Python requires C99 compatible libm])]
)

PY_CHECK_FUNC_PRIVATE([acospi])
PY_CHECK_FUNC_PRIVATE([asinpi])
PY_CHECK_FUNC_PRIVATE([atanpi])
PY_CHECK_FUNC_PRIVATE([atan2pi])
PY_CHECK_FUNC_PRIVATE([cospi])
PY_CHECK_FUNC_PRIVATE([sinpi])
PY_CHECK_FUNC_PRIVATE([tanpi])
PY_CHECK_FUNC_PRIVATE([acospi], [@%:@include <math.h>])
PY_CHECK_FUNC_PRIVATE([asinpi], [@%:@include <math.h>])
PY_CHECK_FUNC_PRIVATE([atanpi], [@%:@include <math.h>])
PY_CHECK_FUNC_PRIVATE([atan2pi], [@%:@include <math.h>])
PY_CHECK_FUNC_PRIVATE([cospi], [@%:@include <math.h>])
PY_CHECK_FUNC_PRIVATE([sinpi], [@%:@include <math.h>])
PY_CHECK_FUNC_PRIVATE([tanpi], [@%:@include <math.h>])
LIBS=$LIBS_SAVE

dnl For multiprocessing module, check that sem_open
Expand Down
Loading