4
from io import BytesIO, StringIO
5
from unittest import mock
6
from test import support
17
@mock.patch('os.environ')
18
class GetpassGetuserTest(unittest.TestCase):
20
def test_username_takes_username_from_env(self, environ):
21
expected_name = 'some_name'
22
environ.get.return_value = expected_name
23
self.assertEqual(expected_name, getpass.getuser())
25
def test_username_priorities_of_env_values(self, environ):
26
environ.get.return_value = None
29
except ImportError: # in case there's no pwd module
32
environ.get.call_args_list,
33
[mock.call(x) for x in ('LOGNAME', 'USER', 'LNAME', 'USERNAME')])
35
def test_username_falls_back_to_pwd(self, environ):
36
expected_name = 'some_name'
37
environ.get.return_value = None
39
with mock.patch('os.getuid') as uid, \
40
mock.patch('pwd.getpwuid') as getpw:
42
getpw.return_value = [expected_name]
43
self.assertEqual(expected_name,
45
getpw.assert_called_once_with(42)
47
self.assertRaises(ImportError, getpass.getuser)
50
class GetpassRawinputTest(unittest.TestCase):
52
def test_flushes_stream_after_prompt(self):
54
stream = mock.Mock(spec=StringIO)
55
input = StringIO('input_string')
56
getpass._raw_input('some_prompt', stream, input=input)
57
stream.flush.assert_called_once_with()
59
def test_uses_stderr_as_default(self):
60
input = StringIO('input_string')
61
prompt = 'some_prompt'
62
with mock.patch('sys.stderr') as stderr:
63
getpass._raw_input(prompt, input=input)
64
stderr.write.assert_called_once_with(prompt)
66
@mock.patch('sys.stdin')
67
def test_uses_stdin_as_default_input(self, mock_input):
68
mock_input.readline.return_value = 'input_string'
69
getpass._raw_input(stream=StringIO())
70
mock_input.readline.assert_called_once_with()
72
def test_raises_on_empty_input(self):
74
self.assertRaises(EOFError, getpass._raw_input, input=input)
76
def test_trims_trailing_newline(self):
77
input = StringIO('test\n')
78
self.assertEqual('test', getpass._raw_input(input=input))
81
# Some of these tests are a bit white-box. The functional requirement is that
82
# the password input be taken directly from the tty, and that it not be echoed
83
# on the screen, unless we are falling back to stderr/stdin.
85
# Some of these might run on platforms without termios, but play it safe.
86
@unittest.skipUnless(termios, 'tests require system with termios')
87
class UnixGetpassTest(unittest.TestCase):
89
def test_uses_tty_directly(self):
90
with mock.patch('os.open') as open, \
91
mock.patch('io.FileIO') as fileio, \
92
mock.patch('io.TextIOWrapper') as textio:
93
# By setting open's return value to None the implementation will
94
# skip code we don't care about in this test. We can mock this out
95
# fully if an alternate implementation works differently.
96
open.return_value = None
97
getpass.unix_getpass()
98
open.assert_called_once_with('/dev/tty',
99
os.O_RDWR | os.O_NOCTTY)
100
fileio.assert_called_once_with(open.return_value, 'w+')
101
textio.assert_called_once_with(fileio.return_value)
103
def test_resets_termios(self):
104
with mock.patch('os.open') as open, \
105
mock.patch('io.FileIO'), \
106
mock.patch('io.TextIOWrapper'), \
107
mock.patch('termios.tcgetattr') as tcgetattr, \
108
mock.patch('termios.tcsetattr') as tcsetattr:
109
open.return_value = 3
110
fake_attrs = [255, 255, 255, 255, 255]
111
tcgetattr.return_value = list(fake_attrs)
112
getpass.unix_getpass()
113
tcsetattr.assert_called_with(3, mock.ANY, fake_attrs)
115
def test_falls_back_to_fallback_if_termios_raises(self):
116
with mock.patch('os.open') as open, \
117
mock.patch('io.FileIO') as fileio, \
118
mock.patch('io.TextIOWrapper') as textio, \
119
mock.patch('termios.tcgetattr'), \
120
mock.patch('termios.tcsetattr') as tcsetattr, \
121
mock.patch('getpass.fallback_getpass') as fallback:
122
open.return_value = 3
123
fileio.return_value = BytesIO()
124
tcsetattr.side_effect = termios.error
125
getpass.unix_getpass()
126
fallback.assert_called_once_with('Password: ',
129
def test_flushes_stream_after_input(self):
131
with mock.patch('os.open') as open, \
132
mock.patch('io.FileIO'), \
133
mock.patch('io.TextIOWrapper'), \
134
mock.patch('termios.tcgetattr'), \
135
mock.patch('termios.tcsetattr'):
136
open.return_value = 3
137
mock_stream = mock.Mock(spec=StringIO)
138
getpass.unix_getpass(stream=mock_stream)
139
mock_stream.flush.assert_called_with()
141
def test_falls_back_to_stdin(self):
142
with mock.patch('os.open') as os_open, \
143
mock.patch('sys.stdin', spec=StringIO) as stdin:
144
os_open.side_effect = IOError
145
stdin.fileno.side_effect = AttributeError
146
with support.captured_stderr() as stderr:
147
with self.assertWarns(getpass.GetPassWarning):
148
getpass.unix_getpass()
149
stdin.readline.assert_called_once_with()
150
self.assertIn('Warning', stderr.getvalue())
151
self.assertIn('Password:', stderr.getvalue())
154
if __name__ == "__main__":