Kaydet (Commit) f0f7ceae authored tarafından R David Murray's avatar R David Murray

17830: preserve line endings of original file when updating keywords.

This fixes the test failures on Windows from the new tests, and
includes test fixes as well as the module fix.
üst 52380925
...@@ -60,6 +60,12 @@ def main(): ...@@ -60,6 +60,12 @@ def main():
if len(args) > 1: optfile = args[1] if len(args) > 1: optfile = args[1]
else: optfile = "Lib/keyword.py" else: optfile = "Lib/keyword.py"
# load the output skeleton from the target, taking care to preserve its
# newline convention.
with open(optfile, newline='') as fp:
format = fp.readlines()
nl = format[0][len(format[0].strip()):] if format else '\n'
# scan the source file for keywords # scan the source file for keywords
with open(iptfile) as fp: with open(iptfile) as fp:
strprog = re.compile('"([^"]+)"') strprog = re.compile('"([^"]+)"')
...@@ -68,25 +74,21 @@ def main(): ...@@ -68,25 +74,21 @@ def main():
if '{1, "' in line: if '{1, "' in line:
match = strprog.search(line) match = strprog.search(line)
if match: if match:
lines.append(" '" + match.group(1) + "',\n") lines.append(" '" + match.group(1) + "'," + nl)
lines.sort() lines.sort()
# load the output skeleton from the target # insert the lines of keywords into the skeleton
with open(optfile) as fp:
format = fp.readlines()
# insert the lines of keywords
try: try:
start = format.index("#--start keywords--\n") + 1 start = format.index("#--start keywords--" + nl) + 1
end = format.index("#--end keywords--\n") end = format.index("#--end keywords--" + nl)
format[start:end] = lines format[start:end] = lines
except ValueError: except ValueError:
sys.stderr.write("target does not contain format markers\n") sys.stderr.write("target does not contain format markers\n")
sys.exit(1) sys.exit(1)
# write the output file # write the output file
with open(optfile, 'w') as fp: with open(optfile, 'w', newline='') as fp:
fp.write(''.join(format)) fp.writelines(format)
if __name__ == "__main__": if __name__ == "__main__":
main() main()
...@@ -9,7 +9,8 @@ import shutil ...@@ -9,7 +9,8 @@ import shutil
import textwrap import textwrap
KEYWORD_FILE = support.findfile('keyword.py') KEYWORD_FILE = support.findfile('keyword.py')
GRAMMAR_FILE = os.path.join('..', '..', 'Python', 'graminit.c') GRAMMAR_FILE = os.path.join(os.path.split(__file__)[0],
'..', '..', 'Python', 'graminit.c')
TEST_PY_FILE = 'keyword_test.py' TEST_PY_FILE = 'keyword_test.py'
GRAMMAR_TEST_FILE = 'graminit_test.c' GRAMMAR_TEST_FILE = 'graminit_test.c'
PY_FILE_WITHOUT_KEYWORDS = 'minimal_keyword.py' PY_FILE_WITHOUT_KEYWORDS = 'minimal_keyword.py'
...@@ -30,7 +31,7 @@ class Test_iskeyword(unittest.TestCase): ...@@ -30,7 +31,7 @@ class Test_iskeyword(unittest.TestCase):
# preserved for backward compatibility. # preserved for backward compatibility.
def test_changing_the_kwlist_does_not_affect_iskeyword(self): def test_changing_the_kwlist_does_not_affect_iskeyword(self):
oldlist = keyword.kwlist oldlist = keyword.kwlist
self.addCleanup(lambda: setattr(keyword, 'kwlist', oldlist)) self.addCleanup(setattr, keyword, 'kwlist', oldlist)
keyword.kwlist = ['its', 'all', 'eggs', 'beans', 'and', 'a', 'slice'] keyword.kwlist = ['its', 'all', 'eggs', 'beans', 'and', 'a', 'slice']
self.assertFalse(keyword.iskeyword('eggs')) self.assertFalse(keyword.iskeyword('eggs'))
...@@ -38,11 +39,12 @@ class Test_iskeyword(unittest.TestCase): ...@@ -38,11 +39,12 @@ class Test_iskeyword(unittest.TestCase):
class TestKeywordGeneration(unittest.TestCase): class TestKeywordGeneration(unittest.TestCase):
def _copy_file_without_generated_keywords(self, source_file, dest_file): def _copy_file_without_generated_keywords(self, source_file, dest_file):
with open(source_file) as fp: with open(source_file, 'rb') as fp:
lines = fp.readlines() lines = fp.readlines()
with open(dest_file, 'w') as fp: nl = lines[0][len(lines[0].strip()):]
fp.writelines(lines[:lines.index("#--start keywords--\n") + 1]) with open(dest_file, 'wb') as fp:
fp.writelines(lines[lines.index("#--end keywords--\n"):]) fp.writelines(lines[:lines.index(b"#--start keywords--" + nl) + 1])
fp.writelines(lines[lines.index(b"#--end keywords--" + nl):])
def _generate_keywords(self, grammar_file, target_keyword_py_file): def _generate_keywords(self, grammar_file, target_keyword_py_file):
proc = subprocess.Popen([sys.executable, proc = subprocess.Popen([sys.executable,
...@@ -56,15 +58,15 @@ class TestKeywordGeneration(unittest.TestCase): ...@@ -56,15 +58,15 @@ class TestKeywordGeneration(unittest.TestCase):
'test only works from source build directory') 'test only works from source build directory')
def test_real_grammar_and_keyword_file(self): def test_real_grammar_and_keyword_file(self):
self._copy_file_without_generated_keywords(KEYWORD_FILE, TEST_PY_FILE) self._copy_file_without_generated_keywords(KEYWORD_FILE, TEST_PY_FILE)
self.addCleanup(lambda: support.unlink(TEST_PY_FILE)) self.addCleanup(support.unlink, TEST_PY_FILE)
self.assertFalse(filecmp.cmp(KEYWORD_FILE, TEST_PY_FILE)) self.assertFalse(filecmp.cmp(KEYWORD_FILE, TEST_PY_FILE))
self.assertEqual(0, self._generate_keywords(GRAMMAR_FILE, self.assertEqual((0, b''), self._generate_keywords(GRAMMAR_FILE,
TEST_PY_FILE)[0]) TEST_PY_FILE))
self.assertTrue(filecmp.cmp(KEYWORD_FILE, TEST_PY_FILE)) self.assertTrue(filecmp.cmp(KEYWORD_FILE, TEST_PY_FILE))
def test_grammar(self): def test_grammar(self):
self._copy_file_without_generated_keywords(KEYWORD_FILE, TEST_PY_FILE) self._copy_file_without_generated_keywords(KEYWORD_FILE, TEST_PY_FILE)
self.addCleanup(lambda: support.unlink(TEST_PY_FILE)) self.addCleanup(support.unlink, TEST_PY_FILE)
with open(GRAMMAR_TEST_FILE, 'w') as fp: with open(GRAMMAR_TEST_FILE, 'w') as fp:
# Some of these are probably implementation accidents. # Some of these are probably implementation accidents.
fp.writelines(textwrap.dedent("""\ fp.writelines(textwrap.dedent("""\
...@@ -86,40 +88,40 @@ class TestKeywordGeneration(unittest.TestCase): ...@@ -86,40 +88,40 @@ class TestKeywordGeneration(unittest.TestCase):
{1, 'no good'} {1, 'no good'}
{283, 0}, {283, 0},
{1, "too many spaces"}""")) {1, "too many spaces"}"""))
self.addCleanup(lambda: support.unlink(GRAMMAR_TEST_FILE)) self.addCleanup(support.unlink, GRAMMAR_TEST_FILE)
self._generate_keywords(GRAMMAR_TEST_FILE, TEST_PY_FILE) self._generate_keywords(GRAMMAR_TEST_FILE, TEST_PY_FILE)
expected = [ expected = [
" 'This one is tab indented',\n", " 'This one is tab indented',",
" 'also legal',\n", " 'also legal',",
" 'continue',\n", " 'continue',",
" 'crazy but legal',\n", " 'crazy but legal',",
" 'jello',\n", " 'jello',",
" 'lemon',\n", " 'lemon',",
" 'tomato',\n", " 'tomato',",
" 'turnip',\n", " 'turnip',",
" 'wigii',\n", " 'wigii',",
] ]
with open(TEST_PY_FILE) as fp: with open(TEST_PY_FILE) as fp:
lines = fp.readlines() lines = fp.read().splitlines()
start = lines.index("#--start keywords--\n") + 1 start = lines.index("#--start keywords--") + 1
end = lines.index("#--end keywords--\n") end = lines.index("#--end keywords--")
actual = lines[start:end] actual = lines[start:end]
self.assertEqual(actual, expected) self.assertEqual(actual, expected)
def test_empty_grammar_results_in_no_keywords(self): def test_empty_grammar_results_in_no_keywords(self):
self._copy_file_without_generated_keywords(KEYWORD_FILE, self._copy_file_without_generated_keywords(KEYWORD_FILE,
PY_FILE_WITHOUT_KEYWORDS) PY_FILE_WITHOUT_KEYWORDS)
self.addCleanup(lambda: support.unlink(PY_FILE_WITHOUT_KEYWORDS)) self.addCleanup(support.unlink, PY_FILE_WITHOUT_KEYWORDS)
shutil.copyfile(KEYWORD_FILE, TEST_PY_FILE) shutil.copyfile(KEYWORD_FILE, TEST_PY_FILE)
self.addCleanup(lambda: support.unlink(TEST_PY_FILE)) self.addCleanup(support.unlink, TEST_PY_FILE)
self.assertEqual(0, self._generate_keywords(os.devnull, self.assertEqual((0, b''), self._generate_keywords(os.devnull,
TEST_PY_FILE)[0]) TEST_PY_FILE))
self.assertTrue(filecmp.cmp(TEST_PY_FILE, PY_FILE_WITHOUT_KEYWORDS)) self.assertTrue(filecmp.cmp(TEST_PY_FILE, PY_FILE_WITHOUT_KEYWORDS))
def test_keywords_py_without_markers_produces_error(self): def test_keywords_py_without_markers_produces_error(self):
rc, stderr = self._generate_keywords(os.devnull, os.devnull) rc, stderr = self._generate_keywords(os.devnull, os.devnull)
self.assertNotEqual(rc, 0) self.assertNotEqual(rc, 0)
self.assertEqual(stderr, b'target does not contain format markers\n') self.assertRegex(stderr, b'does not contain format markers')
def test_missing_grammar_file_produces_error(self): def test_missing_grammar_file_produces_error(self):
rc, stderr = self._generate_keywords(NONEXISTENT_FILE, KEYWORD_FILE) rc, stderr = self._generate_keywords(NONEXISTENT_FILE, KEYWORD_FILE)
......
...@@ -49,6 +49,9 @@ Core and Builtins ...@@ -49,6 +49,9 @@ Core and Builtins
Library Library
------- -------
- Issue #17830: When keyword.py is used to update a keyword file, it now
preserves the line endings of the original file.
- Issue #17272: Making the urllib.request's Request.full_url a descriptor. - Issue #17272: Making the urllib.request's Request.full_url a descriptor.
Fixes bugs with assignment to full_url. Patch by Demian Brecht. Fixes bugs with assignment to full_url. Patch by Demian Brecht.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment