|  | import keyword | 
|  | import unittest | 
|  | from test import support | 
|  | import filecmp | 
|  | import os | 
|  | import sys | 
|  | import subprocess | 
|  | import shutil | 
|  | import textwrap | 
|  |  | 
|  | KEYWORD_FILE             = support.findfile('keyword.py') | 
|  | GRAMMAR_FILE             = os.path.join(os.path.split(__file__)[0], | 
|  | '..', '..', 'Python', 'graminit.c') | 
|  | TEST_PY_FILE             = 'keyword_test.py' | 
|  | GRAMMAR_TEST_FILE        = 'graminit_test.c' | 
|  | PY_FILE_WITHOUT_KEYWORDS = 'minimal_keyword.py' | 
|  | NONEXISTENT_FILE         = 'not_here.txt' | 
|  |  | 
|  |  | 
|  | class Test_iskeyword(unittest.TestCase): | 
|  | def test_true_is_a_keyword(self): | 
|  | self.assertTrue(keyword.iskeyword('True')) | 
|  |  | 
|  | def test_uppercase_true_is_not_a_keyword(self): | 
|  | self.assertFalse(keyword.iskeyword('TRUE')) | 
|  |  | 
|  | def test_none_value_is_not_a_keyword(self): | 
|  | self.assertFalse(keyword.iskeyword(None)) | 
|  |  | 
|  | # This is probably an accident of the current implementation, but should be | 
|  | # preserved for backward compatibility. | 
|  | def test_changing_the_kwlist_does_not_affect_iskeyword(self): | 
|  | oldlist = keyword.kwlist | 
|  | self.addCleanup(setattr, keyword, 'kwlist', oldlist) | 
|  | keyword.kwlist = ['its', 'all', 'eggs', 'beans', 'and', 'a', 'slice'] | 
|  | self.assertFalse(keyword.iskeyword('eggs')) | 
|  |  | 
|  |  | 
|  | class TestKeywordGeneration(unittest.TestCase): | 
|  |  | 
|  | def _copy_file_without_generated_keywords(self, source_file, dest_file): | 
|  | with open(source_file, 'rb') as fp: | 
|  | lines = fp.readlines() | 
|  | nl = lines[0][len(lines[0].strip()):] | 
|  | with open(dest_file, 'wb') as fp: | 
|  | 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): | 
|  | proc = subprocess.Popen([sys.executable, | 
|  | KEYWORD_FILE, | 
|  | grammar_file, | 
|  | target_keyword_py_file], stderr=subprocess.PIPE) | 
|  | stderr = proc.communicate()[1] | 
|  | return proc.returncode, stderr | 
|  |  | 
|  | @unittest.skipIf(not os.path.exists(GRAMMAR_FILE), | 
|  | 'test only works from source build directory') | 
|  | def test_real_grammar_and_keyword_file(self): | 
|  | self._copy_file_without_generated_keywords(KEYWORD_FILE, TEST_PY_FILE) | 
|  | self.addCleanup(support.unlink, TEST_PY_FILE) | 
|  | self.assertFalse(filecmp.cmp(KEYWORD_FILE, TEST_PY_FILE)) | 
|  | self.assertEqual((0, b''), self._generate_keywords(GRAMMAR_FILE, | 
|  | TEST_PY_FILE)) | 
|  | self.assertTrue(filecmp.cmp(KEYWORD_FILE, TEST_PY_FILE)) | 
|  |  | 
|  | def test_grammar(self): | 
|  | self._copy_file_without_generated_keywords(KEYWORD_FILE, TEST_PY_FILE) | 
|  | self.addCleanup(support.unlink, TEST_PY_FILE) | 
|  | with open(GRAMMAR_TEST_FILE, 'w') as fp: | 
|  | # Some of these are probably implementation accidents. | 
|  | fp.writelines(textwrap.dedent("""\ | 
|  | {2, 1}, | 
|  | {11, "encoding_decl", 0, 2, states_79, | 
|  | "\000\000\040\000\000\000\000\000\000\000\000\000" | 
|  | "\000\000\000\000\000\000\000\000\000"}, | 
|  | {1, "jello"}, | 
|  | {326, 0}, | 
|  | {1, "turnip"}, | 
|  | \t{1, "This one is tab indented" | 
|  | {278, 0}, | 
|  | {1, "crazy but legal" | 
|  | "also legal" {1, " | 
|  | {1, "continue"}, | 
|  | {1, "lemon"}, | 
|  | {1, "tomato"}, | 
|  | {1, "wigii"}, | 
|  | {1, 'no good'} | 
|  | {283, 0}, | 
|  | {1,  "too many spaces"}""")) | 
|  | self.addCleanup(support.unlink, GRAMMAR_TEST_FILE) | 
|  | self._generate_keywords(GRAMMAR_TEST_FILE, TEST_PY_FILE) | 
|  | expected = [ | 
|  | "        'This one is tab indented',", | 
|  | "        'also legal',", | 
|  | "        'continue',", | 
|  | "        'crazy but legal',", | 
|  | "        'jello',", | 
|  | "        'lemon',", | 
|  | "        'tomato',", | 
|  | "        'turnip',", | 
|  | "        'wigii',", | 
|  | ] | 
|  | with open(TEST_PY_FILE) as fp: | 
|  | lines = fp.read().splitlines() | 
|  | start = lines.index("#--start keywords--") + 1 | 
|  | end = lines.index("#--end keywords--") | 
|  | actual = lines[start:end] | 
|  | self.assertEqual(actual, expected) | 
|  |  | 
|  | def test_empty_grammar_results_in_no_keywords(self): | 
|  | self._copy_file_without_generated_keywords(KEYWORD_FILE, | 
|  | PY_FILE_WITHOUT_KEYWORDS) | 
|  | self.addCleanup(support.unlink, PY_FILE_WITHOUT_KEYWORDS) | 
|  | shutil.copyfile(KEYWORD_FILE, TEST_PY_FILE) | 
|  | self.addCleanup(support.unlink, TEST_PY_FILE) | 
|  | self.assertEqual((0, b''), self._generate_keywords(os.devnull, | 
|  | TEST_PY_FILE)) | 
|  | self.assertTrue(filecmp.cmp(TEST_PY_FILE, PY_FILE_WITHOUT_KEYWORDS)) | 
|  |  | 
|  | def test_keywords_py_without_markers_produces_error(self): | 
|  | rc, stderr = self._generate_keywords(os.devnull, os.devnull) | 
|  | self.assertNotEqual(rc, 0) | 
|  | self.assertRegex(stderr, b'does not contain format markers') | 
|  |  | 
|  | def test_missing_grammar_file_produces_error(self): | 
|  | rc, stderr = self._generate_keywords(NONEXISTENT_FILE, KEYWORD_FILE) | 
|  | self.assertNotEqual(rc, 0) | 
|  | self.assertRegex(stderr, b'(?ms)' + NONEXISTENT_FILE.encode()) | 
|  |  | 
|  | def test_missing_keywords_py_file_produces_error(self): | 
|  | rc, stderr = self._generate_keywords(os.devnull, NONEXISTENT_FILE) | 
|  | self.assertNotEqual(rc, 0) | 
|  | self.assertRegex(stderr, b'(?ms)' + NONEXISTENT_FILE.encode()) | 
|  |  | 
|  |  | 
|  | if __name__ == "__main__": | 
|  | unittest.main() |