Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
C
cpython
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
cpython
Commits
e02f8fc4
Commit
e02f8fc4
authored
Oct 10, 2015
by
Martin Panter
Browse files
Options
Browse Files
Download
Plain Diff
Issue #24402: Merge input() fix from 3.4 into 3.5
parents
09a00eb0
c9a6ab56
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
116 additions
and
77 deletions
+116
-77
Lib/test/test_builtin.py
Lib/test/test_builtin.py
+110
-76
Misc/NEWS
Misc/NEWS
+3
-0
Python/bltinmodule.c
Python/bltinmodule.c
+3
-1
No files found.
Lib/test/test_builtin.py
View file @
e02f8fc4
...
...
@@ -1134,82 +1134,6 @@ class BuiltinTest(unittest.TestCase):
sys
.
stdout
=
savestdout
fp
.
close
()
@
unittest
.
skipUnless
(
pty
,
"the pty and signal modules must be available"
)
def
check_input_tty
(
self
,
prompt
,
terminal_input
,
stdio_encoding
=
None
):
if
not
sys
.
stdin
.
isatty
()
or
not
sys
.
stdout
.
isatty
():
self
.
skipTest
(
"stdin and stdout must be ttys"
)
r
,
w
=
os
.
pipe
()
try
:
pid
,
fd
=
pty
.
fork
()
except
(
OSError
,
AttributeError
)
as
e
:
os
.
close
(
r
)
os
.
close
(
w
)
self
.
skipTest
(
"pty.fork() raised {}"
.
format
(
e
))
if
pid
==
0
:
# Child
try
:
# Make sure we don't get stuck if there's a problem
signal
.
alarm
(
2
)
os
.
close
(
r
)
# Check the error handlers are accounted for
if
stdio_encoding
:
sys
.
stdin
=
io
.
TextIOWrapper
(
sys
.
stdin
.
detach
(),
encoding
=
stdio_encoding
,
errors
=
'surrogateescape'
)
sys
.
stdout
=
io
.
TextIOWrapper
(
sys
.
stdout
.
detach
(),
encoding
=
stdio_encoding
,
errors
=
'replace'
)
with
open
(
w
,
"w"
)
as
wpipe
:
print
(
"tty ="
,
sys
.
stdin
.
isatty
()
and
sys
.
stdout
.
isatty
(),
file
=
wpipe
)
print
(
ascii
(
input
(
prompt
)),
file
=
wpipe
)
except
:
traceback
.
print_exc
()
finally
:
# We don't want to return to unittest...
os
.
_exit
(
0
)
# Parent
os
.
close
(
w
)
os
.
write
(
fd
,
terminal_input
+
b"
\
r
\
n
"
)
# Get results from the pipe
with
open
(
r
,
"r"
)
as
rpipe
:
lines
=
[]
while
True
:
line
=
rpipe
.
readline
().
strip
()
if
line
==
""
:
# The other end was closed => the child exited
break
lines
.
append
(
line
)
# Check the result was got and corresponds to the user's terminal input
if
len
(
lines
)
!=
2
:
# Something went wrong, try to get at stderr
with
open
(
fd
,
"r"
,
encoding
=
"ascii"
,
errors
=
"ignore"
)
as
child_output
:
self
.
fail
(
"got %d lines in pipe but expected 2, child output was:
\
n
%s"
%
(
len
(
lines
),
child_output
.
read
()))
os
.
close
(
fd
)
# Check we did exercise the GNU readline path
self
.
assertIn
(
lines
[
0
],
{
'tty = True'
,
'tty = False'
})
if
lines
[
0
]
!=
'tty = True'
:
self
.
skipTest
(
"standard IO in should have been a tty"
)
input_result
=
eval
(
lines
[
1
])
# ascii() -> eval() roundtrip
if
stdio_encoding
:
expected
=
terminal_input
.
decode
(
stdio_encoding
,
'surrogateescape'
)
else
:
expected
=
terminal_input
.
decode
(
sys
.
stdin
.
encoding
)
# what else?
self
.
assertEqual
(
input_result
,
expected
)
def
test_input_tty
(
self
):
# Test input() functionality when wired to a tty (the code path
# is different and invokes GNU readline if available).
self
.
check_input_tty
(
"prompt"
,
b"quux"
)
def
test_input_tty_non_ascii
(
self
):
# Check stdin/stdout encoding is used when invoking GNU readline
self
.
check_input_tty
(
"prompté"
,
b"quux
\
xe9
"
,
"utf-8"
)
def
test_input_tty_non_ascii_unicode_errors
(
self
):
# Check stdin/stdout error handler is used when invoking GNU readline
self
.
check_input_tty
(
"prompté"
,
b"quux
\
xe9
"
,
"ascii"
)
# test_int(): see test_int.py for tests of built-in function int().
def
test_repr
(
self
):
...
...
@@ -1564,6 +1488,116 @@ class BuiltinTest(unittest.TestCase):
self
.
assertRaises
(
TypeError
,
tp
,
1
,
2
)
self
.
assertRaises
(
TypeError
,
tp
,
a
=
1
,
b
=
2
)
@
unittest
.
skipUnless
(
pty
,
"the pty and signal modules must be available"
)
class
PtyTests
(
unittest
.
TestCase
):
"""Tests that use a pseudo terminal to guarantee stdin and stdout are
terminals in the test environment"""
def
fork
(
self
):
try
:
return
pty
.
fork
()
except
(
OSError
,
AttributeError
)
as
e
:
self
.
skipTest
(
"pty.fork() raised {}"
.
format
(
e
))
def
check_input_tty
(
self
,
prompt
,
terminal_input
,
stdio_encoding
=
None
):
if
not
sys
.
stdin
.
isatty
()
or
not
sys
.
stdout
.
isatty
():
self
.
skipTest
(
"stdin and stdout must be ttys"
)
r
,
w
=
os
.
pipe
()
try
:
pid
,
fd
=
self
.
fork
()
except
:
os
.
close
(
r
)
os
.
close
(
w
)
raise
if
pid
==
0
:
# Child
try
:
# Make sure we don't get stuck if there's a problem
signal
.
alarm
(
2
)
os
.
close
(
r
)
# Check the error handlers are accounted for
if
stdio_encoding
:
sys
.
stdin
=
io
.
TextIOWrapper
(
sys
.
stdin
.
detach
(),
encoding
=
stdio_encoding
,
errors
=
'surrogateescape'
)
sys
.
stdout
=
io
.
TextIOWrapper
(
sys
.
stdout
.
detach
(),
encoding
=
stdio_encoding
,
errors
=
'replace'
)
with
open
(
w
,
"w"
)
as
wpipe
:
print
(
"tty ="
,
sys
.
stdin
.
isatty
()
and
sys
.
stdout
.
isatty
(),
file
=
wpipe
)
print
(
ascii
(
input
(
prompt
)),
file
=
wpipe
)
except
:
traceback
.
print_exc
()
finally
:
# We don't want to return to unittest...
os
.
_exit
(
0
)
# Parent
os
.
close
(
w
)
os
.
write
(
fd
,
terminal_input
+
b"
\
r
\
n
"
)
# Get results from the pipe
with
open
(
r
,
"r"
)
as
rpipe
:
lines
=
[]
while
True
:
line
=
rpipe
.
readline
().
strip
()
if
line
==
""
:
# The other end was closed => the child exited
break
lines
.
append
(
line
)
# Check the result was got and corresponds to the user's terminal input
if
len
(
lines
)
!=
2
:
# Something went wrong, try to get at stderr
with
open
(
fd
,
"r"
,
encoding
=
"ascii"
,
errors
=
"ignore"
)
as
child_output
:
self
.
fail
(
"got %d lines in pipe but expected 2, child output was:
\
n
%s"
%
(
len
(
lines
),
child_output
.
read
()))
os
.
close
(
fd
)
# Check we did exercise the GNU readline path
self
.
assertIn
(
lines
[
0
],
{
'tty = True'
,
'tty = False'
})
if
lines
[
0
]
!=
'tty = True'
:
self
.
skipTest
(
"standard IO in should have been a tty"
)
input_result
=
eval
(
lines
[
1
])
# ascii() -> eval() roundtrip
if
stdio_encoding
:
expected
=
terminal_input
.
decode
(
stdio_encoding
,
'surrogateescape'
)
else
:
expected
=
terminal_input
.
decode
(
sys
.
stdin
.
encoding
)
# what else?
self
.
assertEqual
(
input_result
,
expected
)
def
test_input_tty
(
self
):
# Test input() functionality when wired to a tty (the code path
# is different and invokes GNU readline if available).
self
.
check_input_tty
(
"prompt"
,
b"quux"
)
def
test_input_tty_non_ascii
(
self
):
# Check stdin/stdout encoding is used when invoking GNU readline
self
.
check_input_tty
(
"prompté"
,
b"quux
\
xe9
"
,
"utf-8"
)
def
test_input_tty_non_ascii_unicode_errors
(
self
):
# Check stdin/stdout error handler is used when invoking GNU readline
self
.
check_input_tty
(
"prompté"
,
b"quux
\
xe9
"
,
"ascii"
)
def
test_input_no_stdout_fileno
(
self
):
# Issue #24402: If stdin is the original terminal but stdout.fileno()
# fails, do not use the original stdout file descriptor
pid
,
pty
=
self
.
fork
()
if
pid
:
# Parent process
# Ideally this should read and write concurrently using select()
# or similar, to avoid the possibility of a deadlock.
os
.
write
(
pty
,
b"quux
\
r
"
)
_
,
status
=
os
.
waitpid
(
pid
,
0
)
output
=
os
.
read
(
pty
,
3000
).
decode
(
"ascii"
,
"backslashreplace"
)
os
.
close
(
pty
)
self
.
assertEqual
(
status
,
0
,
output
)
else
:
# Child process
try
:
self
.
assertTrue
(
sys
.
stdin
.
isatty
(),
"stdin not a terminal"
)
sys
.
stdout
=
io
.
StringIO
()
# Does not support fileno()
input
(
"prompt"
)
self
.
assertEqual
(
sys
.
stdout
.
getvalue
(),
"prompt"
)
os
.
_exit
(
0
)
# Success!
except
:
sys
.
excepthook
(
*
sys
.
exc_info
())
finally
:
os
.
_exit
(
1
)
# Failure
class
TestSorted
(
unittest
.
TestCase
):
def
test_basic
(
self
):
...
...
Misc/NEWS
View file @
e02f8fc4
...
...
@@ -11,6 +11,9 @@ Release date: TBA
Core and Builtins
-----------------
- Issue #24402: Fix input() to prompt to the redirected stdout when
sys.stdout.fileno() fails.
- Issue #24806: Prevent builtin types that are not allowed to be subclassed from
being subclassed through multiple inheritance.
...
...
Python/bltinmodule.c
View file @
e02f8fc4
...
...
@@ -1853,8 +1853,10 @@ builtin_input_impl(PyModuleDef *module, PyObject *prompt)
}
if
(
tty
)
{
tmp
=
_PyObject_CallMethodId
(
fout
,
&
PyId_fileno
,
""
);
if
(
tmp
==
NULL
)
if
(
tmp
==
NULL
)
{
PyErr_Clear
();
tty
=
0
;
}
else
{
fd
=
PyLong_AsLong
(
tmp
);
Py_DECREF
(
tmp
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment