Skip to content

Commit 99a73c3

Browse files
gh-76912: Raise OSError from any failure in getpass.getuser() (#29739)
* bpo-32731: Raise OSError from any failure in getpass.getuser() Previously, if the username was not set in certain environment variables, ImportError escaped on Windows systems, and it was possible for KeyError to escape on other systems if getpwuid() failed.
1 parent 936c503 commit 99a73c3

File tree

5 files changed

+24
-7
lines changed

5 files changed

+24
-7
lines changed

Doc/library/getpass.rst

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,10 @@ The :mod:`getpass` module provides two functions:
4646
:envvar:`USER`, :envvar:`!LNAME` and :envvar:`USERNAME`, in order, and
4747
returns the value of the first one which is set to a non-empty string. If
4848
none are set, the login name from the password database is returned on
49-
systems which support the :mod:`pwd` module, otherwise, an exception is
50-
raised.
49+
systems which support the :mod:`pwd` module, otherwise, an :exc:`OSError`
50+
is raised.
5151

5252
In general, this function should be preferred over :func:`os.getlogin()`.
53+
54+
.. versionchanged:: 3.13
55+
Previously, various exceptions beyond just :exc:`OSError` were raised.

Doc/whatsnew/3.13.rst

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1032,6 +1032,10 @@ Changes in the Python API
10321032
recomended in the documentation.
10331033
(Contributed by Serhiy Storchaka in :gh:`106672`.)
10341034

1035+
* An :exc:`OSError` is now raised by :func:`getpass.getuser` for any failure to
1036+
retrieve a username, instead of :exc:`ImportError` on non-Unix platforms or
1037+
:exc:`KeyError` on Unix platforms where the password database is empty.
1038+
10351039

10361040
Build Changes
10371041
=============

Lib/getpass.py

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -156,17 +156,24 @@ def getuser():
156156
157157
First try various environment variables, then the password
158158
database. This works on Windows as long as USERNAME is set.
159+
Any failure to find a username raises OSError.
159160
161+
.. versionchanged:: 3.13
162+
Previously, various exceptions beyond just :exc:`OSError`
163+
were raised.
160164
"""
161165

162166
for name in ('LOGNAME', 'USER', 'LNAME', 'USERNAME'):
163167
user = os.environ.get(name)
164168
if user:
165169
return user
166170

167-
# If this fails, the exception will "explain" why
168-
import pwd
169-
return pwd.getpwuid(os.getuid())[0]
171+
try:
172+
import pwd
173+
return pwd.getpwuid(os.getuid())[0]
174+
except (ImportError, KeyError) as e:
175+
raise OSError('No username set in the environment') from e
176+
170177

171178
# Bind the name getpass to the appropriate function
172179
try:

Lib/test/test_getpass.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ def test_username_priorities_of_env_values(self, environ):
2626
environ.get.return_value = None
2727
try:
2828
getpass.getuser()
29-
except ImportError: # in case there's no pwd module
29+
except OSError: # in case there's no pwd module
3030
pass
3131
except KeyError:
3232
# current user has no pwd entry
@@ -47,7 +47,7 @@ def test_username_falls_back_to_pwd(self, environ):
4747
getpass.getuser())
4848
getpw.assert_called_once_with(42)
4949
else:
50-
self.assertRaises(ImportError, getpass.getuser)
50+
self.assertRaises(OSError, getpass.getuser)
5151

5252

5353
class GetpassRawinputTest(unittest.TestCase):
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
:func:`getpass.getuser` now raises :exc:`OSError` for all failures rather
2+
than :exc:`ImportError` on systems lacking the :mod:`pwd` module or
3+
:exc:`KeyError` if the password database is empty.

0 commit comments

Comments
 (0)