From e69ff34e81eceb69de6623205c87e0145f1831e4 Mon Sep 17 00:00:00 2001 From: Stanley <46876382+slateny@users.noreply.github.com> Date: Tue, 24 Sep 2024 03:57:37 -0700 Subject: [PATCH 1/7] gh-65169: Clarify prog default in argparse (GH-31602) --- Doc/library/argparse.rst | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index c4e2dbcac2156c..f22aeb8c13c605 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -249,11 +249,12 @@ The following sections describe how each of these are used. prog ^^^^ -By default, :class:`ArgumentParser` objects use ``sys.argv[0]`` to determine +By default, :class:`ArgumentParser` objects use the base name +(see :func:`os.path.basename`) of ``sys.argv[0]`` to determine how to display the name of the program in help messages. This default is almost -always desirable because it will make the help messages match how the program was -invoked on the command line. For example, consider a file named -``myprogram.py`` with the following code:: +always desirable because it will make the help messages match the name that was +used to invoke the program on the command line. For example, consider a file +named ``myprogram.py`` with the following code:: import argparse parser = argparse.ArgumentParser() From 4a5e4aade420c594c5b3fe0589e9e6b444bd6ee5 Mon Sep 17 00:00:00 2001 From: Serhiy Storchaka Date: Tue, 24 Sep 2024 15:46:41 +0300 Subject: [PATCH 2/7] gh-59317: Improve parsing optional positional arguments in argparse (GH-124303) Fix parsing positional argument with nargs equal to '?' or '*' if it is preceded by an option and another positional argument. --- Lib/argparse.py | 13 +- Lib/test/test_argparse.py | 129 +++++++++++++----- ...4-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst | 2 + 3 files changed, 102 insertions(+), 42 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst diff --git a/Lib/argparse.py b/Lib/argparse.py index 3974ebedabe6f4..66192fb92832a2 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -2227,18 +2227,19 @@ def _match_argument(self, action, arg_strings_pattern): def _match_arguments_partial(self, actions, arg_strings_pattern): # progressively shorten the actions list by slicing off the # final actions until we find a match - result = [] for i in range(len(actions), 0, -1): actions_slice = actions[:i] pattern = ''.join([self._get_nargs_pattern(action) for action in actions_slice]) match = _re.match(pattern, arg_strings_pattern) if match is not None: - result.extend([len(string) for string in match.groups()]) - break - - # return the list of arg string counts - return result + result = [len(string) for string in match.groups()] + if (match.end() < len(arg_strings_pattern) + and arg_strings_pattern[match.end()] == 'O'): + while result and not result[-1]: + del result[-1] + return result + return [] def _parse_optional(self, arg_string): # if it's an empty string, it was meant to be a positional diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index b04f044f5e2580..c6b76986940977 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -280,16 +280,18 @@ def test_failures(self, tester): parser = self._get_parser(tester) for args_str in tester.failures: args = args_str.split() - with tester.assertRaises(ArgumentParserError, msg=args): - parser.parse_args(args) + with tester.subTest(args=args): + with tester.assertRaises(ArgumentParserError, msg=args): + parser.parse_args(args) def test_successes(self, tester): parser = self._get_parser(tester) for args, expected_ns in tester.successes: if isinstance(args, str): args = args.split() - result_ns = self._parse_args(parser, args) - tester.assertEqual(expected_ns, result_ns) + with tester.subTest(args=args): + result_ns = self._parse_args(parser, args) + tester.assertEqual(expected_ns, result_ns) # add tests for each combination of an optionals adding method # and an arg parsing method @@ -1089,57 +1091,87 @@ class TestPositionalsNargs2None(ParserTestCase): class TestPositionalsNargsNoneZeroOrMore(ParserTestCase): """Test a Positional with no nargs followed by one with unlimited""" - argument_signatures = [Sig('foo'), Sig('bar', nargs='*')] - failures = ['', '--foo'] + argument_signatures = [Sig('-x'), Sig('foo'), Sig('bar', nargs='*')] + failures = ['', '--foo', 'a b -x X c'] successes = [ - ('a', NS(foo='a', bar=[])), - ('a b', NS(foo='a', bar=['b'])), - ('a b c', NS(foo='a', bar=['b', 'c'])), + ('a', NS(x=None, foo='a', bar=[])), + ('a b', NS(x=None, foo='a', bar=['b'])), + ('a b c', NS(x=None, foo='a', bar=['b', 'c'])), + ('-x X a', NS(x='X', foo='a', bar=[])), + ('a -x X', NS(x='X', foo='a', bar=[])), + ('-x X a b', NS(x='X', foo='a', bar=['b'])), + ('a -x X b', NS(x='X', foo='a', bar=['b'])), + ('a b -x X', NS(x='X', foo='a', bar=['b'])), + ('-x X a b c', NS(x='X', foo='a', bar=['b', 'c'])), + ('a -x X b c', NS(x='X', foo='a', bar=['b', 'c'])), + ('a b c -x X', NS(x='X', foo='a', bar=['b', 'c'])), ] class TestPositionalsNargsNoneOneOrMore(ParserTestCase): """Test a Positional with no nargs followed by one with one or more""" - argument_signatures = [Sig('foo'), Sig('bar', nargs='+')] - failures = ['', '--foo', 'a'] + argument_signatures = [Sig('-x'), Sig('foo'), Sig('bar', nargs='+')] + failures = ['', '--foo', 'a', 'a b -x X c'] successes = [ - ('a b', NS(foo='a', bar=['b'])), - ('a b c', NS(foo='a', bar=['b', 'c'])), + ('a b', NS(x=None, foo='a', bar=['b'])), + ('a b c', NS(x=None, foo='a', bar=['b', 'c'])), + ('-x X a b', NS(x='X', foo='a', bar=['b'])), + ('a -x X b', NS(x='X', foo='a', bar=['b'])), + ('a b -x X', NS(x='X', foo='a', bar=['b'])), + ('-x X a b c', NS(x='X', foo='a', bar=['b', 'c'])), + ('a -x X b c', NS(x='X', foo='a', bar=['b', 'c'])), + ('a b c -x X', NS(x='X', foo='a', bar=['b', 'c'])), ] class TestPositionalsNargsNoneOptional(ParserTestCase): """Test a Positional with no nargs followed by one with an Optional""" - argument_signatures = [Sig('foo'), Sig('bar', nargs='?')] + argument_signatures = [Sig('-x'), Sig('foo'), Sig('bar', nargs='?')] failures = ['', '--foo', 'a b c'] successes = [ - ('a', NS(foo='a', bar=None)), - ('a b', NS(foo='a', bar='b')), + ('a', NS(x=None, foo='a', bar=None)), + ('a b', NS(x=None, foo='a', bar='b')), + ('-x X a', NS(x='X', foo='a', bar=None)), + ('a -x X', NS(x='X', foo='a', bar=None)), + ('-x X a b', NS(x='X', foo='a', bar='b')), + ('a -x X b', NS(x='X', foo='a', bar='b')), + ('a b -x X', NS(x='X', foo='a', bar='b')), ] class TestPositionalsNargsZeroOrMoreNone(ParserTestCase): """Test a Positional with unlimited nargs followed by one with none""" - argument_signatures = [Sig('foo', nargs='*'), Sig('bar')] - failures = ['', '--foo'] + argument_signatures = [Sig('-x'), Sig('foo', nargs='*'), Sig('bar')] + failures = ['', '--foo', 'a -x X b', 'a -x X b c', 'a b -x X c'] successes = [ - ('a', NS(foo=[], bar='a')), - ('a b', NS(foo=['a'], bar='b')), - ('a b c', NS(foo=['a', 'b'], bar='c')), + ('a', NS(x=None, foo=[], bar='a')), + ('a b', NS(x=None, foo=['a'], bar='b')), + ('a b c', NS(x=None, foo=['a', 'b'], bar='c')), + ('-x X a', NS(x='X', foo=[], bar='a')), + ('a -x X', NS(x='X', foo=[], bar='a')), + ('-x X a b', NS(x='X', foo=['a'], bar='b')), + ('a b -x X', NS(x='X', foo=['a'], bar='b')), + ('-x X a b c', NS(x='X', foo=['a', 'b'], bar='c')), + ('a b c -x X', NS(x='X', foo=['a', 'b'], bar='c')), ] class TestPositionalsNargsOneOrMoreNone(ParserTestCase): """Test a Positional with one or more nargs followed by one with none""" - argument_signatures = [Sig('foo', nargs='+'), Sig('bar')] - failures = ['', '--foo', 'a'] + argument_signatures = [Sig('-x'), Sig('foo', nargs='+'), Sig('bar')] + failures = ['', '--foo', 'a', 'a -x X b c', 'a b -x X c'] successes = [ - ('a b', NS(foo=['a'], bar='b')), - ('a b c', NS(foo=['a', 'b'], bar='c')), + ('a b', NS(x=None, foo=['a'], bar='b')), + ('a b c', NS(x=None, foo=['a', 'b'], bar='c')), + ('-x X a b', NS(x='X', foo=['a'], bar='b')), + ('a -x X b', NS(x='X', foo=['a'], bar='b')), + ('a b -x X', NS(x='X', foo=['a'], bar='b')), + ('-x X a b c', NS(x='X', foo=['a', 'b'], bar='c')), + ('a b c -x X', NS(x='X', foo=['a', 'b'], bar='c')), ] @@ -1224,14 +1256,21 @@ class TestPositionalsNargsNoneZeroOrMore1(ParserTestCase): """Test three Positionals: no nargs, unlimited nargs and 1 nargs""" argument_signatures = [ + Sig('-x'), Sig('foo'), Sig('bar', nargs='*'), Sig('baz', nargs=1), ] - failures = ['', '--foo', 'a'] + failures = ['', '--foo', 'a', 'a b -x X c'] successes = [ - ('a b', NS(foo='a', bar=[], baz=['b'])), - ('a b c', NS(foo='a', bar=['b'], baz=['c'])), + ('a b', NS(x=None, foo='a', bar=[], baz=['b'])), + ('a b c', NS(x=None, foo='a', bar=['b'], baz=['c'])), + ('-x X a b', NS(x='X', foo='a', bar=[], baz=['b'])), + ('a -x X b', NS(x='X', foo='a', bar=[], baz=['b'])), + ('a b -x X', NS(x='X', foo='a', bar=[], baz=['b'])), + ('-x X a b c', NS(x='X', foo='a', bar=['b'], baz=['c'])), + ('a -x X b c', NS(x='X', foo='a', bar=['b'], baz=['c'])), + ('a b c -x X', NS(x='X', foo='a', bar=['b'], baz=['c'])), ] @@ -1239,14 +1278,22 @@ class TestPositionalsNargsNoneOneOrMore1(ParserTestCase): """Test three Positionals: no nargs, one or more nargs and 1 nargs""" argument_signatures = [ + Sig('-x'), Sig('foo'), Sig('bar', nargs='+'), Sig('baz', nargs=1), ] - failures = ['', '--foo', 'a', 'b'] + failures = ['', '--foo', 'a', 'b', 'a b -x X c d', 'a b c -x X d'] successes = [ - ('a b c', NS(foo='a', bar=['b'], baz=['c'])), - ('a b c d', NS(foo='a', bar=['b', 'c'], baz=['d'])), + ('a b c', NS(x=None, foo='a', bar=['b'], baz=['c'])), + ('a b c d', NS(x=None, foo='a', bar=['b', 'c'], baz=['d'])), + ('-x X a b c', NS(x='X', foo='a', bar=['b'], baz=['c'])), + ('a -x X b c', NS(x='X', foo='a', bar=['b'], baz=['c'])), + ('a b -x X c', NS(x='X', foo='a', bar=['b'], baz=['c'])), + ('a b c -x X', NS(x='X', foo='a', bar=['b'], baz=['c'])), + ('-x X a b c d', NS(x='X', foo='a', bar=['b', 'c'], baz=['d'])), + ('a -x X b c d', NS(x='X', foo='a', bar=['b', 'c'], baz=['d'])), + ('a b c d -x X', NS(x='X', foo='a', bar=['b', 'c'], baz=['d'])), ] @@ -1254,14 +1301,21 @@ class TestPositionalsNargsNoneOptional1(ParserTestCase): """Test three Positionals: no nargs, optional narg and 1 nargs""" argument_signatures = [ + Sig('-x'), Sig('foo'), Sig('bar', nargs='?', default=0.625), Sig('baz', nargs=1), ] - failures = ['', '--foo', 'a'] + failures = ['', '--foo', 'a', 'a b -x X c'] successes = [ - ('a b', NS(foo='a', bar=0.625, baz=['b'])), - ('a b c', NS(foo='a', bar='b', baz=['c'])), + ('a b', NS(x=None, foo='a', bar=0.625, baz=['b'])), + ('a b c', NS(x=None, foo='a', bar='b', baz=['c'])), + ('-x X a b', NS(x='X', foo='a', bar=0.625, baz=['b'])), + ('a -x X b', NS(x='X', foo='a', bar=0.625, baz=['b'])), + ('a b -x X', NS(x='X', foo='a', bar=0.625, baz=['b'])), + ('-x X a b c', NS(x='X', foo='a', bar='b', baz=['c'])), + ('a -x X b c', NS(x='X', foo='a', bar='b', baz=['c'])), + ('a b c -x X', NS(x='X', foo='a', bar='b', baz=['c'])), ] @@ -1477,6 +1531,9 @@ class TestNargsRemainder(ParserTestCase): successes = [ ('X', NS(x='X', y=[], z=None)), ('-z Z X', NS(x='X', y=[], z='Z')), + ('-z Z X A B', NS(x='X', y=['A', 'B'], z='Z')), + ('X -z Z A B', NS(x='X', y=['-z', 'Z', 'A', 'B'], z=None)), + ('X A -z Z B', NS(x='X', y=['A', '-z', 'Z', 'B'], z=None)), ('X A B -z Z', NS(x='X', y=['A', 'B', '-z', 'Z'], z=None)), ('X Y --foo', NS(x='X', y=['Y', '--foo'], z=None)), ] @@ -6018,8 +6075,8 @@ def test_basic(self): args, extras = parser.parse_known_args(argv) # cannot parse the '1,2,3' - self.assertEqual(NS(bar='y', cmd='cmd', foo='x', rest=[]), args) - self.assertEqual(["1", "2", "3"], extras) + self.assertEqual(NS(bar='y', cmd='cmd', foo='x', rest=[1]), args) + self.assertEqual(["2", "3"], extras) argv = 'cmd --foo x 1 --error 2 --bar y 3'.split() args, extras = parser.parse_known_intermixed_args(argv) diff --git a/Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst b/Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst new file mode 100644 index 00000000000000..0b1df9e3b7dea8 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2024-09-21-19-02-37.gh-issue-59317.OAhNZZ.rst @@ -0,0 +1,2 @@ +Fix parsing positional argument with :ref:`nargs` equal to ``'?'`` or ``'*'`` +if it is preceded by an option and another positional argument. From d21b0b5d36834d4d35aec3a01661597019594936 Mon Sep 17 00:00:00 2001 From: Payton <72841140+paytonward6@users.noreply.github.com> Date: Tue, 24 Sep 2024 09:14:35 -0500 Subject: [PATCH 3/7] gh-113008: Correct argparse usage output for required, mutually exclusive groups (GH-113085) --- Lib/argparse.py | 4 ++-- Lib/test/test_argparse.py | 23 +++++++++++++++++++ ...-12-14-13-43-27.gh-issue-113008.jWYn8T.rst | 1 + 3 files changed, 26 insertions(+), 2 deletions(-) create mode 100644 Misc/NEWS.d/next/Library/2023-12-14-13-43-27.gh-issue-113008.jWYn8T.rst diff --git a/Lib/argparse.py b/Lib/argparse.py index 66192fb92832a2..694c46db61d177 100644 --- a/Lib/argparse.py +++ b/Lib/argparse.py @@ -395,12 +395,12 @@ def _get_actions_usage_parts(self, actions, groups): continue try: - start = actions.index(group._group_actions[0]) + start = min(actions.index(item) for item in group._group_actions) except ValueError: continue else: end = start + len(group._group_actions) - if actions[start:end] == group._group_actions: + if set(actions[start:end]) == set(group._group_actions): group_actions.update(group._group_actions) inserts[start, end] = group diff --git a/Lib/test/test_argparse.py b/Lib/test/test_argparse.py index c6b76986940977..ef05a6fefcffcc 100644 --- a/Lib/test/test_argparse.py +++ b/Lib/test/test_argparse.py @@ -2902,6 +2902,29 @@ def test_help(self): ''' self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + def test_optional_order(self): + parser = ErrorRaisingArgumentParser(prog='PROG') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('--foo') + group.add_argument('bar', nargs='?') + expected = '''\ + usage: PROG [-h] (--foo FOO | bar) + + positional arguments: + bar + + options: + -h, --help show this help message and exit + --foo FOO + ''' + self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + + parser = ErrorRaisingArgumentParser(prog='PROG') + group = parser.add_mutually_exclusive_group(required=True) + group.add_argument('bar', nargs='?') + group.add_argument('--foo') + self.assertEqual(parser.format_help(), textwrap.dedent(expected)) + def test_help_subparser_all_mutually_exclusive_group_members_suppressed(self): self.maxDiff = None parser = ErrorRaisingArgumentParser(prog='PROG') diff --git a/Misc/NEWS.d/next/Library/2023-12-14-13-43-27.gh-issue-113008.jWYn8T.rst b/Misc/NEWS.d/next/Library/2023-12-14-13-43-27.gh-issue-113008.jWYn8T.rst new file mode 100644 index 00000000000000..0f2a44299717c0 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-12-14-13-43-27.gh-issue-113008.jWYn8T.rst @@ -0,0 +1 @@ +Correct argparse usage output for required, mutually exclusive groups containing a positional argument From 38a5beb12a64461a06b84fab285944ecb66de04c Mon Sep 17 00:00:00 2001 From: Victor Stinner Date: Tue, 24 Sep 2024 16:33:27 +0200 Subject: [PATCH 4/7] gh-124402: Require cpu resource in test_free_threading (#124438) Require the 'cpu' test resource on slow test_free_threading tests. --- Lib/test/test_free_threading/test_list.py | 3 +++ Lib/test/test_free_threading/test_monitoring.py | 3 +++ Lib/test/test_free_threading/test_type.py | 2 ++ 3 files changed, 8 insertions(+) diff --git a/Lib/test/test_free_threading/test_list.py b/Lib/test/test_free_threading/test_list.py index 6ad806d67a80ed..c6b58fcd86f449 100644 --- a/Lib/test/test_free_threading/test_list.py +++ b/Lib/test/test_free_threading/test_list.py @@ -3,6 +3,7 @@ from threading import Thread from unittest import TestCase +from test import support from test.support import threading_helper @@ -13,6 +14,7 @@ def __init__(self, v): @threading_helper.requires_working_threading() class TestList(TestCase): + @support.requires_resource('cpu') def test_racing_iter_append(self): l = [] @@ -42,6 +44,7 @@ def reader_func(): for reader in readers: reader.join() + @support.requires_resource('cpu') def test_racing_iter_extend(self): iters = [ lambda x: [x], diff --git a/Lib/test/test_free_threading/test_monitoring.py b/Lib/test/test_free_threading/test_monitoring.py index 78303f4206decc..be582455d118ac 100644 --- a/Lib/test/test_free_threading/test_monitoring.py +++ b/Lib/test/test_free_threading/test_monitoring.py @@ -7,6 +7,7 @@ import weakref from sys import monitoring +from test import support from test.support import threading_helper from threading import Thread, _PyRLock from unittest import TestCase @@ -43,6 +44,7 @@ def after_test(self): """Runs once after the test is done""" pass + @support.requires_resource('cpu') def test_instrumentation(self): # Setup a bunch of functions which will need instrumentation... funcs = [] @@ -218,6 +220,7 @@ def test_register_callback(self): for ref in self.refs: self.assertEqual(ref(), None) + @support.requires_resource('cpu') def test_set_local_trace_opcodes(self): def trace(frame, event, arg): frame.f_trace_opcodes = True diff --git a/Lib/test/test_free_threading/test_type.py b/Lib/test/test_free_threading/test_type.py index 649676db9c08a5..977bfd2c7fd2f7 100644 --- a/Lib/test/test_free_threading/test_type.py +++ b/Lib/test/test_free_threading/test_type.py @@ -5,6 +5,7 @@ from threading import Thread from unittest import TestCase +from test import support from test.support import threading_helper @@ -96,6 +97,7 @@ def reader_func(): self.run_one(writer_func, reader_func) + @support.requires_resource('cpu') def test___class___modification(self): class Foo: pass From 20ccda000b5f8365d5f864fd07876804157c2378 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Tue, 24 Sep 2024 09:30:01 -0700 Subject: [PATCH 5/7] GH-87358: Add clarification about nargs and default argparse behaviour (#124094) --- Doc/library/argparse.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Doc/library/argparse.rst b/Doc/library/argparse.rst index f22aeb8c13c605..53ecc97d5659f4 100644 --- a/Doc/library/argparse.rst +++ b/Doc/library/argparse.rst @@ -1123,6 +1123,9 @@ is used when no command-line argument was present:: >>> parser.parse_args([]) Namespace(foo=42) +For required_ arguments, the ``default`` value is ignored. For example, this +applies to positional arguments with nargs_ values other than ``?`` or ``*``, +or optional arguments marked as ``required=True``. Providing ``default=argparse.SUPPRESS`` causes no attribute to be added if the command-line argument was not present:: From b4d0d7de0f6d938128bf525e119c18af5632b804 Mon Sep 17 00:00:00 2001 From: Savannah Ostrowski Date: Tue, 24 Sep 2024 10:03:16 -0700 Subject: [PATCH 6/7] GH-124398: Pin LLVM to 18.1.0 for Windows JIT CI (GH-124399) --- .github/workflows/jit.yml | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/.github/workflows/jit.yml b/.github/workflows/jit.yml index 5e3ac9e9e0fada..8f56220feea90b 100644 --- a/.github/workflows/jit.yml +++ b/.github/workflows/jit.yml @@ -110,8 +110,7 @@ jobs: - name: Native Windows if: runner.os == 'Windows' && matrix.architecture != 'ARM64' run: | - choco upgrade llvm -y - choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }} + choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0 ./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '--pgo' }} -p ${{ matrix.architecture }} ./PCbuild/rt.bat ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} -q --multiprocess 0 --timeout 4500 --verbose2 --verbose3 @@ -119,8 +118,7 @@ jobs: - name: Emulated Windows if: runner.os == 'Windows' && matrix.architecture == 'ARM64' run: | - choco upgrade llvm -y - choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }} + choco install llvm --allow-downgrade --no-progress --version ${{ matrix.llvm }}.1.0 ./PCbuild/build.bat --experimental-jit ${{ matrix.debug && '-d' || '' }} -p ${{ matrix.architecture }} - name: Native macOS From 17b3bc9cc7608920077f5f08f970c7157a2d2e72 Mon Sep 17 00:00:00 2001 From: sobolevn Date: Tue, 24 Sep 2024 21:06:39 +0300 Subject: [PATCH 7/7] gh-124405: Fix `NameError` in `openpty` (#124406) --- Lib/pty.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Lib/pty.py b/Lib/pty.py index eb3d5f1ff657bb..4b25ac32c8da14 100644 --- a/Lib/pty.py +++ b/Lib/pty.py @@ -39,8 +39,8 @@ def openpty(): except ImportError: return master_fd, slave_fd try: - ioctl(result, I_PUSH, "ptem") - ioctl(result, I_PUSH, "ldterm") + ioctl(slave_fd, I_PUSH, "ptem") + ioctl(slave_fd, I_PUSH, "ldterm") except OSError: pass return master_fd, slave_fd