Skip to content

Commit a124916

Browse files
authored
bpo-32381: pymain_run_command() uses PyCF_IGNORE_COOKIE (GH-23724)
The coding cookie (ex: "# coding: latin1") is now ignored in the command passed to the -c command line option. Since pymain_run_command() uses UTF-8, pass PyCF_IGNORE_COOKIE compiler flag to the parser. pymain_run_python() no longer propages compiler flags between function calls.
1 parent 41b223d commit a124916

File tree

3 files changed

+33
-19
lines changed

3 files changed

+33
-19
lines changed

Lib/test/test_cmd_line.py

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,14 @@ def test_non_ascii(self):
153153
% (os_helper.FS_NONASCII, ord(os_helper.FS_NONASCII)))
154154
assert_python_ok('-c', command)
155155

156+
@unittest.skipUnless(os_helper.FS_NONASCII, 'need os_helper.FS_NONASCII')
157+
def test_coding(self):
158+
# bpo-32381: the -c command ignores the coding cookie
159+
ch = os_helper.FS_NONASCII
160+
cmd = f"# coding: latin1\nprint(ascii('{ch}'))"
161+
res = assert_python_ok('-c', cmd)
162+
self.assertEqual(res.out.rstrip(), ascii(ch).encode('ascii'))
163+
156164
# On Windows, pass bytes to subprocess doesn't test how Python decodes the
157165
# command line, but how subprocess does decode bytes to unicode. Python
158166
# doesn't decode the command line because Windows provides directly the
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
The coding cookie (ex: ``# coding: latin1``) is now ignored in the command
2+
passed to the :option:`-c` command line option. Patch by Victor Stinner.

Modules/main.c

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -223,7 +223,7 @@ pymain_import_readline(const PyConfig *config)
223223

224224

225225
static int
226-
pymain_run_command(wchar_t *command, PyCompilerFlags *cf)
226+
pymain_run_command(wchar_t *command)
227227
{
228228
PyObject *unicode, *bytes;
229229
int ret;
@@ -243,7 +243,9 @@ pymain_run_command(wchar_t *command, PyCompilerFlags *cf)
243243
goto error;
244244
}
245245

246-
ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), cf);
246+
PyCompilerFlags cf = _PyCompilerFlags_INIT;
247+
cf.cf_flags |= PyCF_IGNORE_COOKIE;
248+
ret = PyRun_SimpleStringFlags(PyBytes_AsString(bytes), &cf);
247249
Py_DECREF(bytes);
248250
return (ret != 0);
249251

@@ -306,7 +308,7 @@ pymain_run_module(const wchar_t *modname, int set_argv0)
306308

307309
static int
308310
pymain_run_file_obj(PyObject *program_name, PyObject *filename,
309-
int skip_source_first_line, PyCompilerFlags *cf)
311+
int skip_source_first_line)
310312
{
311313
if (PySys_Audit("cpython.run_file", "O", filename) < 0) {
312314
return pymain_exit_err_print();
@@ -347,12 +349,13 @@ pymain_run_file_obj(PyObject *program_name, PyObject *filename,
347349
}
348350

349351
/* PyRun_AnyFileExFlags(closeit=1) calls fclose(fp) before running code */
350-
int run = _PyRun_AnyFileObject(fp, filename, 1, cf);
352+
PyCompilerFlags cf = _PyCompilerFlags_INIT;
353+
int run = _PyRun_AnyFileObject(fp, filename, 1, &cf);
351354
return (run != 0);
352355
}
353356

354357
static int
355-
pymain_run_file(const PyConfig *config, PyCompilerFlags *cf)
358+
pymain_run_file(const PyConfig *config)
356359
{
357360
PyObject *filename = PyUnicode_FromWideChar(config->run_filename, -1);
358361
if (filename == NULL) {
@@ -367,15 +370,15 @@ pymain_run_file(const PyConfig *config, PyCompilerFlags *cf)
367370
}
368371

369372
int res = pymain_run_file_obj(program_name, filename,
370-
config->skip_source_first_line, cf);
373+
config->skip_source_first_line);
371374
Py_DECREF(filename);
372375
Py_DECREF(program_name);
373376
return res;
374377
}
375378

376379

377380
static int
378-
pymain_run_startup(PyConfig *config, PyCompilerFlags *cf, int *exitcode)
381+
pymain_run_startup(PyConfig *config, int *exitcode)
379382
{
380383
int ret;
381384
if (!config->use_environment) {
@@ -416,7 +419,8 @@ pymain_run_startup(PyConfig *config, PyCompilerFlags *cf, int *exitcode)
416419
goto error;
417420
}
418421

419-
(void) _PyRun_SimpleFileObject(fp, startup, 0, cf);
422+
PyCompilerFlags cf = _PyCompilerFlags_INIT;
423+
(void) _PyRun_SimpleFileObject(fp, startup, 0, &cf);
420424
PyErr_Clear();
421425
fclose(fp);
422426
ret = 0;
@@ -469,14 +473,14 @@ pymain_run_interactive_hook(int *exitcode)
469473

470474

471475
static int
472-
pymain_run_stdin(PyConfig *config, PyCompilerFlags *cf)
476+
pymain_run_stdin(PyConfig *config)
473477
{
474478
if (stdin_is_interactive(config)) {
475479
config->inspect = 0;
476480
Py_InspectFlag = 0; /* do exit on SystemExit */
477481

478482
int exitcode;
479-
if (pymain_run_startup(config, cf, &exitcode)) {
483+
if (pymain_run_startup(config, &exitcode)) {
480484
return exitcode;
481485
}
482486

@@ -494,13 +498,14 @@ pymain_run_stdin(PyConfig *config, PyCompilerFlags *cf)
494498
return pymain_exit_err_print();
495499
}
496500

497-
int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, cf);
501+
PyCompilerFlags cf = _PyCompilerFlags_INIT;
502+
int run = PyRun_AnyFileExFlags(stdin, "<stdin>", 0, &cf);
498503
return (run != 0);
499504
}
500505

501506

502507
static void
503-
pymain_repl(PyConfig *config, PyCompilerFlags *cf, int *exitcode)
508+
pymain_repl(PyConfig *config, int *exitcode)
504509
{
505510
/* Check this environment variable at the end, to give programs the
506511
opportunity to set it from Python. */
@@ -519,7 +524,8 @@ pymain_repl(PyConfig *config, PyCompilerFlags *cf, int *exitcode)
519524
return;
520525
}
521526

522-
int res = PyRun_AnyFileFlags(stdin, "<stdin>", cf);
527+
PyCompilerFlags cf = _PyCompilerFlags_INIT;
528+
int res = PyRun_AnyFileFlags(stdin, "<stdin>", &cf);
523529
*exitcode = (res != 0);
524530
}
525531

@@ -565,13 +571,11 @@ pymain_run_python(int *exitcode)
565571
}
566572
}
567573

568-
PyCompilerFlags cf = _PyCompilerFlags_INIT;
569-
570574
pymain_header(config);
571575
pymain_import_readline(config);
572576

573577
if (config->run_command) {
574-
*exitcode = pymain_run_command(config->run_command, &cf);
578+
*exitcode = pymain_run_command(config->run_command);
575579
}
576580
else if (config->run_module) {
577581
*exitcode = pymain_run_module(config->run_module, 1);
@@ -580,13 +584,13 @@ pymain_run_python(int *exitcode)
580584
*exitcode = pymain_run_module(L"__main__", 0);
581585
}
582586
else if (config->run_filename != NULL) {
583-
*exitcode = pymain_run_file(config, &cf);
587+
*exitcode = pymain_run_file(config);
584588
}
585589
else {
586-
*exitcode = pymain_run_stdin(config, &cf);
590+
*exitcode = pymain_run_stdin(config);
587591
}
588592

589-
pymain_repl(config, &cf, exitcode);
593+
pymain_repl(config, exitcode);
590594
goto done;
591595

592596
error:

0 commit comments

Comments
 (0)