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

bpo-28334: fix netrc not working when $HOME is not set #123

Closed
wants to merge 1 commit into from

Conversation

@dmerejkowsky
Copy link

@dmerejkowsky dmerejkowsky commented Feb 15, 2017

@the-knights-who-say-ni
Copy link

@the-knights-who-say-ni the-knights-who-say-ni commented Feb 15, 2017

Hello, and thanks for your contribution!

I'm a bot set up to make sure that the project can legally accept your contribution by verifying you have signed the PSF contributor agreement (CLA).

Unfortunately we couldn't find an account corresponding to your GitHub username on bugs.python.org (b.p.o) to verify you have signed the CLA. This is necessary for legal reasons before we can look at your contribution. Please follow these steps to help rectify the issue:

  1. If you don't have an account on b.p.o, please create one
  2. Make sure your GitHub username is listed in "Your Details" at b.p.o
  3. If you have not already done so, please sign the PSF contributor agreement
  4. If you just signed the CLA, please wait at least one US business day and then check "Your Details" on bugs.python.org to see if your account has been marked as having signed the CLA (the delay is due to a person having to manually check your signed CLA)
  5. Reply here saying you have completed the above steps

Thanks again to your contribution and we look forward to looking at it!

@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Feb 15, 2017

As discussed during patch review, no tests were added, but doc was updated.

@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Feb 15, 2017

@the-knights-who-say-ni :
Added my github username on bugs.python.org as requested.

Copy link
Member

@berkerpeksag berkerpeksag left a comment

Thanks for the PR, but like I said in review we can't accept this without a test case.

It should be easy to test at least the FileNotFoundError case by changing $HOME env variable.

@@ -32,6 +32,10 @@ the Unix :program:`ftp` program and other FTP clients.

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

.. versionchanged:: 3.7 Now uses :func:`os.path.expanduser`, so if

This comment has been minimized.

@berkerpeksag

berkerpeksag Feb 19, 2017
Member

Style nit:

.. versionchanged:: 3.7
   Now uses :func:`os.path.expanduser`, so if [...]
@dmerejkowsky dmerejkowsky force-pushed the dmerejkowsky:netrc-home branch from f9e303b to cb9777b Feb 20, 2017
@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Feb 20, 2017

Rebased, added a test, and fix doc style as requested.

@zhangyangyu zhangyangyu self-requested a review Feb 22, 2017
@@ -123,6 +123,15 @@ def test_security(self):
os.chmod(fn, 0o622)
self.assertRaises(netrc.NetrcParseError, netrc.netrc)

def test_when_not_found(self):

This comment has been minimized.

@zhangyangyu

zhangyangyu Mar 8, 2017
Member

I would like the name just test_file_not_found.

This comment has been minimized.

with support.EnvironmentVarGuard() as environ:
environ.set('HOME', d)
self.assertRaises(FileNotFoundError, netrc.netrc)

This comment has been minimized.

@zhangyangyu

zhangyangyu Mar 8, 2017
Member

When you explicitly pass a not exist file, it could also raise the error.

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Mar 11, 2017
Author

OK. I wrote an other test for this. (I like to follow the 'one assert per test' rule)

@zhangyangyu zhangyangyu requested a review from terryjreedy Mar 8, 2017
@dmerejkowsky dmerejkowsky force-pushed the dmerejkowsky:netrc-home branch from cb9777b to 7119217 Mar 11, 2017
@zhangyangyu
Copy link
Member

@zhangyangyu zhangyangyu commented Mar 13, 2017

LGTM. But I'd wait for others' reviews for some time. And I want to treat this as an enhancement though it looks like a bug on Windows.

Copy link
Member

@berkerpeksag berkerpeksag left a comment

Thanks! Looks good to me, just left some minor comments. Also, since this a behavior change we need to add a note to Misc/NEWS.

@@ -32,6 +32,11 @@ the Unix :program:`ftp` program and other FTP clients.

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

.. versionchanged:: 3.7
Now uses :func:`os.path.expanduser`, so if :envvar:`HOME` is not

This comment has been minimized.

@berkerpeksag

berkerpeksag Mar 15, 2017
Member

I think the "if :envvar:HOME is not set [...]" part should be moved to the main documentation block and the versionchanged annotation should only mention that it now uses expanduser() to determine the location of the .netrc file if *file* is not passed.

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Mar 15, 2017
Author

Makes sense.

@@ -32,6 +32,11 @@ the Unix :program:`ftp` program and other FTP clients.

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

.. versionchanged:: 3.7
Now uses :func:`os.path.expanduser`, so if :envvar:`HOME` is not
set *and* ``~/.netrc`` not found, will raise

This comment has been minimized.

@berkerpeksag

berkerpeksag Mar 15, 2017
Member

Double spaces before "will".

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Mar 15, 2017
Author

oups, sorry :)

self.assertRaises(FileNotFoundError, netrc.netrc)

def test_file_not_found_explicit(self):
unlikely_file = "unlikely_netrc"

This comment has been minimized.

@berkerpeksag

berkerpeksag Mar 15, 2017
Member

No need to use unlikely_file here. Just pass "unlikely_netrc" to the constructor.

This comment has been minimized.

@dmerejkowsky dmerejkowsky force-pushed the dmerejkowsky:netrc-home branch from 7119217 to 62ff357 Mar 15, 2017
@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Mar 24, 2017

@berkerpeksag rebased and conformed with your latest comments

@dmerejkowsky dmerejkowsky force-pushed the dmerejkowsky:netrc-home branch from 62ff357 to 86a9333 Mar 24, 2017
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 returned by :func:`os.path.expanduser` -- will be read. If the file is not found, will raise

This comment has been minimized.

@zhangyangyu

zhangyangyu Apr 10, 2017
Member

Two spaces before "If the file ...".

This comment has been minimized.

Misc/NEWS Outdated
@@ -1046,6 +1046,8 @@ Core and Builtins
Library
-------

- bpo-28334: fix netrc not working when $HOME is not set

This comment has been minimized.

@zhangyangyu

zhangyangyu Apr 10, 2017
Member

Uppercase please and colon at end. And instead of fixing, I'd rather something like "Use os.path.expanduser rather than barely checking $HOME is set or not when no argument is given to netrc.netrc().". Ignore my wording, I am not a native speaker. :-(

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 10, 2017
Author

Also done. It's a bit long, but I hope it documents precisely the new behavior

@dmerejkowsky dmerejkowsky force-pushed the dmerejkowsky:netrc-home branch 2 times, most recently from df1f1bc to 09abcaf Apr 10, 2017
@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Apr 10, 2017

@zhangyangyu Thanks for the suggestions! It's worth making sure the documentation is as best as possible :)
Rebased and changed as requested.

Misc/NEWS Outdated
@@ -1125,6 +1125,11 @@ Core and Builtins
Library
-------

- bpo-28334: Use os.path.expanduser() to find the ~/.netrc file in netrc.netrc().

This comment has been minimized.

@zhangyangyu

zhangyangyu Apr 10, 2017
Member

Too wordy. Just

bpo-28334: Use os.path.expanduser() to find the ~/.netrc file in netrc.netrc().
If the file does not exist, a FileNotFoundError is raised.

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 returned by :func:`os.path.expanduser` -- will be read. If the file is
not found, will raise :exc:`FileNotFoundError`.

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 10, 2017
Member

There are many causes why the file can't be read. It can be a directory or broken symlink, or user can not have permissions to read it. Different OSError subclasses are raised in these cases. I think no need to specify this is explicitly. Exceptions that can be raised by the function are rarely documented in Python docs.

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 11, 2017
Author

Fair enough. I removed the sentence.

os.mkdir(d)
self.addCleanup(support.rmtree, d)
with support.EnvironmentVarGuard() as environ:
environ.set('HOME', d)

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 10, 2017
Member

This doesn't test a new behavior. Needed a test for the case when HOME is not set.

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 11, 2017
Author

This doesn't test a new behavior

I think it does. It checks the type of the exception raised, which is the whole point of this patch,
getting rid of the weird 'OSError' about HOME not set ...

Needed a test for the case when HOME is not set.

Yeah I was not sure about this one. I've added a test where I monkeypatch os.path.expanduser, but I'm not sure it's useful. My guts tell me such a test is too close to the implementation.

This comment has been minimized.

@berkerpeksag

berkerpeksag Apr 26, 2017
Member

Serhiy is right that we need a test for this case and unless I'm missing something you can do it without doing any mocking:

with support.EnvironmentVarGuard() as environ:
    environ.unset('HOME')
    self.assertRaises(FileNotFoundError, netrc.netrc)
@dmerejkowsky dmerejkowsky force-pushed the dmerejkowsky:netrc-home branch from 09abcaf to 1d544f5 Apr 11, 2017
@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Apr 11, 2017

Wrote a test monkeypatching os.path.expanduser. Maybe we can keep it after all.
You tell me ;)

@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Apr 26, 2017

@louisom
Copy link
Contributor

@louisom louisom commented Apr 26, 2017

@dmerejkowsky For reminding, you don't need to squash your commit every change makes, all commit will be squash when the PR is merged. See devguide last paragraph.

os.chmod(fake_netrc_path, 0o600)
with support.EnvironmentVarGuard() as environ:
environ.unset('HOME')
with mock.patch('os.path.expanduser') as mock_expanduser:

This comment has been minimized.

@berkerpeksag

berkerpeksag Apr 26, 2017
Member

Mocking os.path.expanduser is not needed here in my opinion. If you can change the test to

def test_home_not_set(self):
    with support.EnvironmentVarGuard() as environ:
        environ.unset('HOME')
        self.assertRaises(FileNotFoundError, netrc.netrc)

then we are good to go! :)

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 27, 2017
Author

I'm afraid not. If we unset HOME and ~/.netrc does exist on the developer box, os.path.expanduser will read /etc/passwd using pwd (see [1]) and no exception will be raised. I'd prefer the tests to not depend on what's on the home directory of the user running the tests.

[1]: https://github.com/python/cpython/blob/master/Lib/posixpath.py#L245-L247

Misc/NEWS Outdated
@@ -1125,6 +1125,9 @@ Core and Builtins
Library
-------

- bpo-28334: Use os.path.expanduser() to find the ~/.netrc file in netrc.netrc().

This comment has been minimized.

@berkerpeksag

berkerpeksag Apr 26, 2017
Member

~/.netrc -> ``~/.netrc``

(otherwise our doc build will complain)

This comment has been minimized.

@berkerpeksag
Copy link
Member

@berkerpeksag berkerpeksag commented Apr 26, 2017

@dmerejkowsky and just one more comment: Please add your name to Misc/ACKS.

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 returned by :func:`os.path.expanduser` -- will be read.

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 27, 2017
Member

Maybe "as determined"? expanduser() itself doesn't return the user's home directory.

Or "as returned by os.path.expanduser('~') ", but this exposes more implementation details and is harder to format as a reference.

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 28, 2017
Author

I like 'determined', thanks :)

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.expanduser("~/.netrc")

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 27, 2017
Member

'/' is Posix specific pathname separator. Windows accepts it too, but it is better to use the native pathname separator, os.sep. Or use os.path.join():

os.path.expanduser(os.path.join("~", ".netrc"))

or

os.path.join(os.path.expanduser("~"), ".netrc")

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 28, 2017
Author

ok.

@@ -32,6 +33,10 @@ the Unix :program:`ftp` program and other FTP clients.

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

.. versionchanged:: 3.7
Now uses :func:`os.path.expanduser` to determine the location
of ``~/.netrc`` if *file* is not passed as argument.

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 27, 2017
Member

~/.netrc is Posix-specific syntax. Windows users of netrc can even not know what ~/ means. Maybe "of the file :file:'.netrc'" of "of the default netrc file"?

This comment has been minimized.

environ.unset('HOME')
with mock.patch('os.path.expanduser') as mock_expanduser:
mock_expanduser.return_value = fake_netrc_path
nrc = netrc.netrc()

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 27, 2017
Member

Check the content of nrc for testing that the configuration is read from the right file. Add a random data in the fake .netrc.

Misc/NEWS Outdated
@@ -1125,6 +1125,9 @@ Core and Builtins
Library
-------

- bpo-28334: Use os.path.expanduser() to find the ``~/.netrc`` file in netrc.netrc().

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 27, 2017
Member

Too long line.

Add "Patch by Dimitri Merejkowsky."

This comment has been minimized.

Misc/NEWS Outdated
@@ -1125,6 +1125,9 @@ Core and Builtins
Library
-------

- bpo-28334: Use os.path.expanduser() to find the ``~/.netrc`` file in netrc.netrc().
If the file does not exist, a FileNotFoundError is raised.

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 27, 2017
Member

Is this a new behavior?

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 28, 2017
Author

Nope, fixed

os.chmod(fake_netrc_path, 0o600)
with support.EnvironmentVarGuard() as environ:
environ.unset('HOME')
with mock.patch('os.path.expanduser') as mock_expanduser:

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Apr 27, 2017
Member

This is too fragile. If rather than os.path.expanduser("~/.netrc") use one of variants suggested by me, the test will be broken.

I would monkey-patch expanduser with a code like the following:

orig_expanduser = os.path.expanduser
called = []
def fake_expanduser(s):
    called.append(s)
    environ.set('HOME', d)
    result = orig_expanduser(s)
    environ.unset('HOME')
    return result
with test.support.swap_attr(os.path, 'expanduser', fake_expanduser):
    nrc = netrc.netrc()
self.assertTrue(called)

This comment has been minimized.

@dmerejkowsky

dmerejkowsky Apr 28, 2017
Author

You're right, test is less likely to break this way.

yan12125 added a commit to ytdl-org/youtube-dl that referenced this pull request May 29, 2017
That's a Python bug: http://bugs.python.org/issue28334
Most likely it will be fixed in Python 3.7: python/cpython#123
akruis pushed a commit to akruis/cpython that referenced this pull request Sep 9, 2017
akruis pushed a commit to akruis/cpython that referenced this pull request Sep 9, 2017
During interpreter shutdown Stackless kills tasklets on daemon threads, if they
have a non-trivial C-stack. This caused an assertion violation.

https://bitbucket.org/stackless-dev/stackless/issues/123
(grafted from 9fd4f6a9d266250bef5baa692b89516e73b00e62)
akruis pushed a commit to akruis/cpython that referenced this pull request Sep 9, 2017
@Mariatta Mariatta added needs rebase and removed needs rebase labels Oct 9, 2017
@berkerpeksag
Copy link
Member

@berkerpeksag berkerpeksag commented Nov 24, 2017

I've fixed merge conflicts, created NEWS entry with blurb and made some cosmetic changes. Is there anything left to do here?

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

def test_home_not_set(self):

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Nov 24, 2017
Member

Sorry, I don't understand how this test is related to the case when HOME is not set. Why not use the simple test suggested by @berkerpeksag above?

This comment has been minimized.

@berkerpeksag

berkerpeksag Nov 24, 2017
Member

My suggested test won't work, because of the following code in expanduser:

if 'HOME' not in os.environ:
    import pwd
    userhome = pwd.getpwuid(os.getuid()).pw_dir

I have a .netrc file in my HOME directory so the test won't pass:

def test_foo(self):
    with support.EnvironmentVarGuard() as environ:
        environ.unset('HOME')
        self.assertRaises(FileNotFoundError, netrc.netrc)
======================================================================
FAIL: test_foo (test.test_netrc.NetrcTestCase)
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/berker/projects/cpython/master/Lib/test/test_netrc.py", line 34, in test_foo
    self.assertRaises(FileNotFoundError, netrc.netrc)
AssertionError: FileNotFoundError not raised by netrc

This comment has been minimized.

@serhiy-storchaka

serhiy-storchaka Nov 24, 2017
Member

Thanks, now I see that this is the simplest platform-independent test.

Also add more tests to check that proper exceptions are raised
@berkerpeksag berkerpeksag force-pushed the dmerejkowsky:netrc-home branch from 4605b07 to e8dde32 Nov 24, 2017
@berkerpeksag
Copy link
Member

@berkerpeksag berkerpeksag commented Nov 24, 2017

For some reason, Travis CI didn't pick up latest changes:

/home/travis/build/python/cpython/Doc/library/pyexpat.rst:872:Footnote [#] is not referenced.

Serhiy fixed it a while ago and I don't get any warnings in my development environment.

@berkerpeksag
Copy link
Member

@berkerpeksag berkerpeksag commented Nov 24, 2017

Ok, this looks like a Travis bug to me. I've opened PR #4537 and documentation build passed there.

@dmerejkowsky could you please create a new PR? If I merge PR #4537, GitHub overwrite author information and set me as author.

@dmerejkowsky
Copy link
Author

@dmerejkowsky dmerejkowsky commented Nov 24, 2017

@dmerejkowsky could you please create a new PR? If I merge PR #4537, GitHub overwrite author information and set me as author.

It's not a problem for me :) It was very nice of you to finish up my pull request, so by all means just merge your own and let GitHub set you as author of the patch, you deserve it.

What matters to me is to be listed in the ACKS file 😛

@berkerpeksag
Copy link
Member

@berkerpeksag berkerpeksag commented Nov 25, 2017

I've just merged PR #4537. Thank you for your work again, @dmerejkowsky. It took more than a year but we eventually fixed the bug :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Linked issues

Successfully merging this pull request may close these issues.

None yet

8 participants