Skip to content

Commit d7a8f3a

Browse files
authored
Remove extraneous CR characters from normalized code snippets. (microsoft#2927)
Remove extraneous CR characters from normalized code snippets. - Correct normalization python script to use LF instead of CRLF to split lines. - On windows, Python will inject CR whenever it sees an LF written to stdout. - This was the root cause of the CRCRLF coming back from normalization. - Change helper.unit.test to helper.test, it shells out to Python and is not a unit test suite. - Re-enable tests for helper.
1 parent 55a8f51 commit d7a8f3a

4 files changed

Lines changed: 19 additions & 6 deletions

File tree

news/2 Fixes/2857.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Stop `normalizationForInterpreter.py` script from returning CRCRLF line-endings.

pythonFiles/normalizeForInterpreter.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -81,10 +81,10 @@ def normalize_lines(source):
8181
# we have indented code.
8282
if (len(lines) > 1 and len(''.join(lines[-2:])) == 0) \
8383
or source.endswith(('\n\n', '\r\n\r\n')):
84-
trailing_newline = os.linesep * 2
84+
trailing_newline = '\n' * 2
8585
# Find out if we have any trailing blank lines
8686
elif len(lines[-1].strip()) == 0 or source.endswith(('\n', '\r\n')):
87-
trailing_newline = os.linesep
87+
trailing_newline = '\n'
8888
else:
8989
trailing_newline = ''
9090

@@ -101,7 +101,7 @@ def normalize_lines(source):
101101
# Step 2: Add blank lines between each global statement block.
102102
# A consequtive single lines blocks of code will be treated as a single statement,
103103
# just to ensure we do not unnecessarily add too many blank lines.
104-
source = os.linesep.join(lines)
104+
source = '\n'.join(lines)
105105
tokens = _tokenize(source)
106106
dedent_indexes = (spos[0] for (toknum, tokval, spos, epos, line) in tokens
107107
if toknum == token.DEDENT and _indent_size(line) == 0)
@@ -111,7 +111,7 @@ def normalize_lines(source):
111111
for line_number in filter(lambda x: x > 1, start_positions):
112112
lines.insert(line_number-1, '')
113113

114-
sys.stdout.write(os.linesep.join(lines) + trailing_newline)
114+
sys.stdout.write('\n'.join(lines) + trailing_newline)
115115
sys.stdout.flush()
116116

117117

src/client/terminals/codeExecution/helper.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ export class CodeExecutionHelper implements ICodeExecutionHelper {
3333
const args = [path.join(EXTENSION_ROOT_DIR, 'pythonFiles', 'normalizeForInterpreter.py'), code];
3434
const processService = await this.processServiceFactory.create(resource);
3535
const proc = await processService.exec(pythonPath, args, { throwOnStdErr: true });
36+
3637
return proc.stdout;
3738
} catch (ex) {
3839
console.error(ex, 'Python: Failed to normalize code for execution in terminal');

src/test/terminals/codeExecution/helper.unit.test.ts renamed to src/test/terminals/codeExecution/helper.test.ts

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ suite('Terminal - Code Execution Helper', () => {
3232
let editor: TypeMoq.IMock<TextEditor>;
3333
let processService: TypeMoq.IMock<IProcessService>;
3434
let configService: TypeMoq.IMock<IConfigurationService>;
35-
setup(function () {
35+
setup(() => {
3636
const serviceContainer = TypeMoq.Mock.ofType<IServiceContainer>();
3737
documentManager = TypeMoq.Mock.ofType<IDocumentManager>();
3838
applicationShell = TypeMoq.Mock.ofType<IApplicationShell>();
@@ -58,7 +58,7 @@ suite('Terminal - Code Execution Helper', () => {
5858
editor.setup(e => e.document).returns(() => document.object);
5959

6060
// tslint:disable-next-line:no-invalid-this
61-
this.skip();
61+
// this.skip();
6262
});
6363

6464
async function ensureBlankLinesAreRemoved(source: string, expectedSource: string) {
@@ -77,6 +77,17 @@ suite('Terminal - Code Execution Helper', () => {
7777
const expectedCode = code.filter(line => line.trim().length > 0).join(EOL);
7878
await ensureBlankLinesAreRemoved(code.join(EOL), expectedCode);
7979
});
80+
test('Ensure there are no multiple-CR elements in the normalized code.', async () => {
81+
const code = ['import sys', '', '', '', 'print(sys.executable)', '', 'print("1234")', '', '', 'print(1)', 'print(2)'];
82+
const actualProcessService = new ProcessService(new BufferDecoder());
83+
processService.setup(p => p.exec(TypeMoq.It.isAny(), TypeMoq.It.isAny(), TypeMoq.It.isAny()))
84+
.returns((file, args, options) => {
85+
return actualProcessService.exec.apply(actualProcessService, [file, args, options]);
86+
});
87+
const normalizedCode = await helper.normalizeLines(code.join(EOL));
88+
const doubleCrIndex = normalizedCode.indexOf('\r\r');
89+
expect(doubleCrIndex).to.be.equal(-1, 'Double CR (CRCRLF) line endings detected in normalized code snippet.');
90+
});
8091
['', '1', '2', '3', '4', '5', '6', '7'].forEach(fileNameSuffix => {
8192
test(`Ensure blank lines are removed (Sample${fileNameSuffix})`, async () => {
8293
const code = await fs.readFile(path.join(TEST_FILES_PATH, `sample${fileNameSuffix}_raw.py`), 'utf8');

0 commit comments

Comments
 (0)