Skip to content

Commit

Permalink
bpo-28334: netrc() now uses expanduser() to find .netrc file (GH-4537)
Browse files Browse the repository at this point in the history
Previously, netrc.netrc() was raised an exception if $HOME is not set.

Authored-By: Dimitri Merejkowsky <dimitri.merejkowsky@tanker.io>
  • Loading branch information
berkerpeksag committed Nov 25, 2017
1 parent 9d5ec80 commit 8d9bb11
Show file tree
Hide file tree
Showing 5 changed files with 53 additions and 10 deletions.
11 changes: 8 additions & 3 deletions Doc/library/netrc.rst
Expand Up @@ -20,8 +20,10 @@ the Unix :program:`ftp` program and other FTP clients.

A :class:`~netrc.netrc` instance or subclass instance encapsulates data from a netrc
file. The initialization argument, if present, specifies the file to parse. If
no argument is given, the file :file:`.netrc` in the user's home directory will
be read. Parse errors will raise :exc:`NetrcParseError` with diagnostic
no argument is given, the file :file:`.netrc` in the user's home directory --
as determined by :func:`os.path.expanduser` -- will be read. Otherwise,
a :exc:`FileNotFoundError` exception will be raised.
Parse errors will raise :exc:`NetrcParseError` with diagnostic
information including the file name, line number, and terminating token.
If no argument is specified on a POSIX system, the presence of passwords in
the :file:`.netrc` file will raise a :exc:`NetrcParseError` if the file
Expand All @@ -32,6 +34,10 @@ the Unix :program:`ftp` program and other FTP clients.

.. versionchanged:: 3.4 Added the POSIX permission check.

.. versionchanged:: 3.7
:func:`os.path.expanduser` is used to find the location of the
:file:`.netrc` file when *file* is not passed as argument.


.. exception:: NetrcParseError

Expand Down Expand Up @@ -82,4 +88,3 @@ Instances of :class:`~netrc.netrc` have public instance variables:
punctuation is allowed in passwords, however, note that whitespace and
non-printable characters are not allowed in passwords. This is a limitation
of the way the .netrc file is parsed and may be removed in the future.

5 changes: 1 addition & 4 deletions Lib/netrc.py
Expand Up @@ -23,10 +23,7 @@ class netrc:
def __init__(self, file=None):
default_netrc = file is None
if file is None:
try:
file = os.path.join(os.environ['HOME'], ".netrc")
except KeyError:
raise OSError("Could not find .netrc: $HOME is not set") from None
file = os.path.join(os.path.expanduser("~"), ".netrc")
self.hosts = {}
self.macros = {}
with open(file) as fp:
Expand Down
43 changes: 40 additions & 3 deletions Lib/test/test_netrc.py
@@ -1,4 +1,5 @@
import netrc, os, unittest, sys, tempfile, textwrap
from unittest import mock
from test import support


Expand Down Expand Up @@ -126,8 +127,44 @@ def test_security(self):
os.chmod(fn, 0o622)
self.assertRaises(netrc.NetrcParseError, netrc.netrc)

def test_main():
support.run_unittest(NetrcTestCase)
def test_file_not_found_in_home(self):
d = support.TESTFN
os.mkdir(d)
self.addCleanup(support.rmtree, d)
with support.EnvironmentVarGuard() as environ:
environ.set('HOME', d)
self.assertRaises(FileNotFoundError, netrc.netrc)

def test_file_not_found_explicit(self):
self.assertRaises(FileNotFoundError, netrc.netrc,
file='unlikely_netrc')

def test_home_not_set(self):
fake_home = support.TESTFN
os.mkdir(fake_home)
self.addCleanup(support.rmtree, fake_home)
fake_netrc_path = os.path.join(fake_home, '.netrc')
with open(fake_netrc_path, 'w') as f:
f.write('machine foo.domain.com login bar password pass')
os.chmod(fake_netrc_path, 0o600)

orig_expanduser = os.path.expanduser
called = []

def fake_expanduser(s):
called.append(s)
with support.EnvironmentVarGuard() as environ:
environ.set('HOME', fake_home)
result = orig_expanduser(s)
return result

with support.swap_attr(os.path, 'expanduser', fake_expanduser):
nrc = netrc.netrc()
login, account, password = nrc.authenticators('foo.domain.com')
self.assertEqual(login, 'bar')

self.assertTrue(called)


if __name__ == "__main__":
test_main()
unittest.main()
1 change: 1 addition & 0 deletions Misc/ACKS
Expand Up @@ -1031,6 +1031,7 @@ Bill van Melle
Lucas Prado Melo
Ezio Melotti
Doug Mennella
Dimitri Merejkowsky
Brian Merrell
Alexis Métaireau
Luke Mewburn
Expand Down
@@ -0,0 +1,3 @@
Use :func:`os.path.expanduser` to find the ``~/.netrc`` file in
:class:`netrc.netrc`. If it does not exist, :exc:`FileNotFoundError`
is raised. Patch by Dimitri Merejkowsky.

0 comments on commit 8d9bb11

Please sign in to comment.