From 815b41b1cdb98686fc3f9cdf995b6983c12c04b3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20v=2E=20L=C3=B6wis?= Date: Fri, 28 Feb 2014 15:27:29 +0100 Subject: [PATCH] Issue #20731: Properly position in source code files even if they are opened in text mode. Patch by Serhiy Storchaka. --- .hgeol | 2 ++ Lib/test/coding20731.py | 4 ++++ Lib/test/test_coding.py | 9 ++++++++- Misc/NEWS | 3 +++ Parser/tokenizer.c | 14 ++++++++++++-- 5 files changed, 29 insertions(+), 3 deletions(-) create mode 100644 Lib/test/coding20731.py diff --git a/.hgeol b/.hgeol index 4e036906607..73a4770f320 100644 --- a/.hgeol +++ b/.hgeol @@ -37,6 +37,8 @@ Lib/test/xmltestdata/* = BIN Lib/venv/scripts/nt/* = BIN +Lib/test/coding20731.py = BIN + # All other files (which presumably are human-editable) are "native". # This must be the last rule! diff --git a/Lib/test/coding20731.py b/Lib/test/coding20731.py new file mode 100644 index 00000000000..ca4962ee8ef --- /dev/null +++ b/Lib/test/coding20731.py @@ -0,0 +1,4 @@ +#coding:latin1 + + + diff --git a/Lib/test/test_coding.py b/Lib/test/test_coding.py index 989c7a85d2f..760676750c4 100644 --- a/Lib/test/test_coding.py +++ b/Lib/test/test_coding.py @@ -1,6 +1,6 @@ import unittest from test.support import TESTFN, unlink, unload -import importlib, os, sys +import importlib, os, sys, subprocess class CodingTest(unittest.TestCase): def test_bad_coding(self): @@ -58,6 +58,13 @@ class CodingTest(unittest.TestCase): self.assertTrue(c.exception.args[0].startswith(expected), msg=c.exception.args[0]) + def test_20731(self): + sub = subprocess.Popen([sys.executable, + os.path.join(os.path.dirname(__file__), + 'coding20731.py')], + stderr=subprocess.PIPE) + err = sub.communicate()[1] + self.assertEquals(err, b'') if __name__ == "__main__": unittest.main() diff --git a/Misc/NEWS b/Misc/NEWS index 4c99dd33945..3b707839e2b 100644 --- a/Misc/NEWS +++ b/Misc/NEWS @@ -10,6 +10,9 @@ What's New in Python 3.3.5 release candidate 1? Core and Builtins ----------------- +- Issue #20731: Properly position in source code files even if they + are opened in text mode. Patch by Serhiy Storchaka. + - Issue #19619: str.encode, bytes.decode and bytearray.decode now use an internal API to throw LookupError for known non-text encodings, rather than attempting the encoding or decoding operation and then throwing a diff --git a/Parser/tokenizer.c b/Parser/tokenizer.c index 8530723c266..660c0f042bc 100644 --- a/Parser/tokenizer.c +++ b/Parser/tokenizer.c @@ -498,9 +498,13 @@ fp_setreadl(struct tok_state *tok, const char* enc) fd = fileno(tok->fp); /* Due to buffering the file offset for fd can be different from the file - * position of tok->fp. */ + * position of tok->fp. If tok->fp was opened in text mode on Windows, + * its file position counts CRLF as one char and can't be directly mapped + * to the file offset for fd. Instead we step back one byte and read to + * the end of line.*/ pos = ftell(tok->fp); - if (pos == -1 || lseek(fd, (off_t)pos, SEEK_SET) == (off_t)-1) { + if (pos == -1 || + lseek(fd, (off_t)(pos > 0 ? pos - 1 : pos), SEEK_SET) == (off_t)-1) { PyErr_SetFromErrnoWithFilename(PyExc_OSError, NULL); goto cleanup; } @@ -513,6 +517,12 @@ fp_setreadl(struct tok_state *tok, const char* enc) Py_XDECREF(tok->decoding_readline); readline = _PyObject_GetAttrId(stream, &PyId_readline); tok->decoding_readline = readline; + if (pos > 0) { + if (PyObject_CallObject(readline, NULL) == NULL) { + readline = NULL; + goto cleanup; + } + } cleanup: Py_XDECREF(stream);