Test roundtrip for `untokenize`. `f` is an open file or a string. The source code in f is tokenized to both 5- and 2-tuples. Both sequences are converted back to source code via tokenize.untokenize(), and the latter tokenized again to 2-tuples. The test fails
(self, f)
| 1994 | class TestRoundtrip(TestCase): |
| 1995 | |
| 1996 | def check_roundtrip(self, f): |
| 1997 | """ |
| 1998 | Test roundtrip for `untokenize`. `f` is an open file or a string. |
| 1999 | The source code in f is tokenized to both 5- and 2-tuples. |
| 2000 | Both sequences are converted back to source code via |
| 2001 | tokenize.untokenize(), and the latter tokenized again to 2-tuples. |
| 2002 | The test fails if the 3 pair tokenizations do not match. |
| 2003 | |
| 2004 | If the source code can be untokenized unambiguously, the |
| 2005 | untokenized code must match the original code exactly. |
| 2006 | |
| 2007 | When untokenize bugs are fixed, untokenize with 5-tuples should |
| 2008 | reproduce code that does not contain a backslash continuation |
| 2009 | following spaces. A proper test should test this. |
| 2010 | """ |
| 2011 | # Get source code and original tokenizations |
| 2012 | if isinstance(f, str): |
| 2013 | code = f.encode('utf-8') |
| 2014 | else: |
| 2015 | code = f.read() |
| 2016 | readline = iter(code.splitlines(keepends=True)).__next__ |
| 2017 | tokens5 = list(tokenize.tokenize(readline)) |
| 2018 | tokens2 = [tok[:2] for tok in tokens5] |
| 2019 | # Reproduce tokens2 from pairs |
| 2020 | bytes_from2 = tokenize.untokenize(tokens2) |
| 2021 | readline2 = iter(bytes_from2.splitlines(keepends=True)).__next__ |
| 2022 | tokens2_from2 = [tok[:2] for tok in tokenize.tokenize(readline2)] |
| 2023 | self.assertEqual(tokens2_from2, tokens2) |
| 2024 | # Reproduce tokens2 from 5-tuples |
| 2025 | bytes_from5 = tokenize.untokenize(tokens5) |
| 2026 | readline5 = iter(bytes_from5.splitlines(keepends=True)).__next__ |
| 2027 | tokens2_from5 = [tok[:2] for tok in tokenize.tokenize(readline5)] |
| 2028 | self.assertEqual(tokens2_from5, tokens2) |
| 2029 | |
| 2030 | if not contains_ambiguous_backslash(code): |
| 2031 | # The BOM does not produce a token so there is no way to preserve it. |
| 2032 | code_without_bom = code.removeprefix(b'\xef\xbb\xbf') |
| 2033 | readline = iter(code_without_bom.splitlines(keepends=True)).__next__ |
| 2034 | untokenized_code = tokenize.untokenize(tokenize.tokenize(readline)) |
| 2035 | self.assertEqual(code_without_bom, untokenized_code) |
| 2036 | |
| 2037 | def check_line_extraction(self, f): |
| 2038 | if isinstance(f, str): |
no test coverage detected