diff --git a/Lib/netrc.py b/Lib/netrc.py index b285fd8e357ddb..52a9b4ddbe6283 100644 --- a/Lib/netrc.py +++ b/Lib/netrc.py @@ -25,13 +25,25 @@ def __init__(self, fp): self.instream = fp self.whitespace = "\n\t\r " self.pushback = [] + self.char_pushback = [] def _read_char(self): + if self.char_pushback: + return self.char_pushback.pop(0) ch = self.instream.read(1) if ch == "\n": self.lineno += 1 return ch + def skip_blank_lines(self): + fiter = iter(self._read_char, "") + for ch in fiter: + if ch == '\n': + self.lineno += 1 + else: + self.char_pushback.append(ch) + return + def get_token(self): if self.pushback: return self.pushback.pop(0) @@ -81,6 +93,7 @@ def _parse(self, file, fp, default_netrc): lexer = _netrclex(fp) while 1: # Look for a machine, default, or macdef top-level keyword + lexer.skip_blank_lines() saved_lineno = lexer.lineno toplevel = tt = lexer.get_token() if not tt: @@ -120,6 +133,9 @@ def _parse(self, file, fp, default_netrc): login = account = password = '' self.hosts[entryname] = {} while 1: + # Trailing blank lines would break the checks that determine if the token + # is the last one on its line. + lexer.skip_blank_lines() prev_lineno = lexer.lineno tt = lexer.get_token() if tt.startswith('#'): diff --git a/Lib/test/test_netrc.py b/Lib/test/test_netrc.py index 81e11a293cc4c8..774fccd40d251f 100644 --- a/Lib/test/test_netrc.py +++ b/Lib/test/test_netrc.py @@ -215,6 +215,14 @@ def test_comment_before_machine_line_hash_only(self): machine bar.domain.com login foo password pass """) + def test_comment_after_new_line(self): + self._test_comment("""\ + machine foo.domain.com login bar password pass + + # TEST + machine bar.domain.com login foo password pass + """) + def test_comment_after_machine_line(self): self._test_comment("""\ machine foo.domain.com login bar password pass @@ -251,6 +259,24 @@ def test_comment_after_machine_line_hash_only(self): # """) + def test_comment_at_first_line_trailing_new_line(self): + self._test_comment(""" + # TEST + machine foo.domain.com login bar password pass + machine bar.domain.com login foo password pass + """) + + def test_comment_multiple_trailing_new_lines(self): + self._test_comment(""" + # TEST + machine foo.domain.com login bar password pass + + + #FTP + + machine bar.domain.com login foo password pass + """) + def test_comment_at_end_of_machine_line(self): self._test_comment("""\ machine foo.domain.com login bar password pass # comment diff --git a/Misc/NEWS.d/next/Library/2023-05-15-17-22-53.gh-issue-104306.YMiegg.rst b/Misc/NEWS.d/next/Library/2023-05-15-17-22-53.gh-issue-104306.YMiegg.rst new file mode 100644 index 00000000000000..60e75d1b64aa43 --- /dev/null +++ b/Misc/NEWS.d/next/Library/2023-05-15-17-22-53.gh-issue-104306.YMiegg.rst @@ -0,0 +1 @@ +Fix incorrect comment parsing in the :mod:`netrc` module.