Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

gh-76912: Raise OSError from any failure in getpass.getuser() #29739

Merged
merged 11 commits into from
Nov 27, 2023
4 changes: 2 additions & 2 deletions Doc/library/getpass.rst
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ The :mod:`getpass` module provides two functions:
:envvar:`USER`, :envvar:`!LNAME` and :envvar:`USERNAME`, in order, and
returns the value of the first one which is set to a non-empty string. If
none are set, the login name from the password database is returned on
systems which support the :mod:`pwd` module, otherwise, an exception is
raised.
systems which support the :mod:`pwd` module, otherwise, an :exc:`OSError`
is raised.
gpshead marked this conversation as resolved.
Show resolved Hide resolved

In general, this function should be preferred over :func:`os.getlogin()`.
4 changes: 4 additions & 0 deletions Doc/whatsnew/3.13.rst
Original file line number Diff line number Diff line change
Expand Up @@ -1017,6 +1017,10 @@ Changes in the Python API
recomended in the documentation.
(Contributed by Serhiy Storchaka in :gh:`106672`.)

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


Build Changes
=============
Expand Down
14 changes: 11 additions & 3 deletions Lib/getpass.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,17 +156,25 @@ def getuser():

First try various environment variables, then the password
database. This works on Windows as long as USERNAME is set.
Any failure to find a username raises OSError.

.. versionchanged:: 3.13
gpshead marked this conversation as resolved.
Show resolved Hide resolved
Failure to find a username raises :exc:`OSError` instead of
:exc:`ImportError` on non-Unix platforms and instead of
:exc:`KeyError` on Unix platforms if the password database is empty.
"""

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

# If this fails, the exception will "explain" why
import pwd
return pwd.getpwuid(os.getuid())[0]
try:
import pwd
return pwd.getpwuid(os.getuid())[0]
except (ImportError, KeyError) as e:
raise OSError('No username set in the environment') from e


# Bind the name getpass to the appropriate function
try:
Expand Down
4 changes: 2 additions & 2 deletions Lib/test/test_getpass.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ def test_username_priorities_of_env_values(self, environ):
environ.get.return_value = None
try:
getpass.getuser()
except ImportError: # in case there's no pwd module
except OSError: # in case there's no pwd module
pass
except KeyError:
# current user has no pwd entry
Expand All @@ -47,7 +47,7 @@ def test_username_falls_back_to_pwd(self, environ):
getpass.getuser())
getpw.assert_called_once_with(42)
else:
self.assertRaises(ImportError, getpass.getuser)
self.assertRaises(OSError, getpass.getuser)


class GetpassRawinputTest(unittest.TestCase):
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
:func:`getpass.getuser` now raises :exc:`OSError` for all failures rather
than :exc:`ImportError` on systems lacking the :mod:`pwd` module or
:exc:`KeyError` if the password database is empty.
Loading