]> git.ipfire.org Git - thirdparty/Python/cpython.git/commitdiff
[3.7] bpo-34589: Add -X coerce_c_locale option; C locale coercion off by default...
authorVictor Stinner <vstinner@redhat.com>
Tue, 18 Sep 2018 01:01:39 +0000 (18:01 -0700)
committerGitHub <noreply@github.com>
Tue, 18 Sep 2018 01:01:39 +0000 (18:01 -0700)
* bpo-34589: Make _PyCoreConfig.coerce_c_locale private (GH-9371)

_PyCoreConfig:

* Rename coerce_c_locale to _coerce_c_locale
* Rename coerce_c_locale_warn to _coerce_c_locale_warn

These fields are now private (name prefixed by "_").

(cherry picked from commit 188ebfa475a6f6aa2d0ea14ca8e1fbe7865b6d27)

* bpo-34589: C locale coercion off by default (GH-9073)

Py_Initialize() and Py_Main() cannot enable the C locale coercion
(PEP 538) anymore: it is always disabled. It can now only be enabled
by the Python program ("python3).

test_embed: get_filesystem_encoding() doesn't have to set PYTHONUTF8
nor PYTHONCOERCECLOCALE, these variables are already set in the
parent.

(cherry picked from commit 7a0791b6992d420dc52536257f2f093851ed7215)

* bpo-34589: Add -X coerce_c_locale command line option (GH-9378)

Add a new -X coerce_c_locale command line option to control C locale
coercion (PEP 538).

(cherry picked from commit dbdee0073cf0b88fe541980ace1f650900f455cc)

15 files changed:
Doc/using/cmdline.rst
Doc/whatsnew/3.7.rst
Include/pylifecycle.h
Include/pystate.h
Lib/test/test_c_locale_coercion.py
Lib/test/test_cmd_line.py
Lib/test/test_embed.py
Lib/test/test_sys.py
Lib/test/test_utf8_mode.py
Misc/NEWS.d/next/C API/2018-09-18-00-09-31.bpo-34589.C7bUpq.rst [new file with mode: 0644]
Misc/NEWS.d/next/Core and Builtins/2018-09-18-01-41-33.bpo-34589.lLVTYc.rst [new file with mode: 0644]
Modules/main.c
Programs/_testembed.c
Programs/python.c
Python/pylifecycle.c

index 70e8d1afb42a3a3728d1abcc81b079fa54eb0fae..29de155f2d1e45e6543020b1d3031a380a14e645 100644 (file)
@@ -438,10 +438,19 @@ Miscellaneous options
      * Set the :attr:`~sys.flags.dev_mode` attribute of :attr:`sys.flags` to
        ``True``
 
-   * ``-X utf8`` enables UTF-8 mode for operating system interfaces, overriding
+   * ``-X utf8`` enables UTF-8 mode (:pep:`540`) for operating system interfaces, overriding
      the default locale-aware mode. ``-X utf8=0`` explicitly disables UTF-8
      mode (even when it would otherwise activate automatically).
      See :envvar:`PYTHONUTF8` for more details.
+   * ``-X coerce_c_locale`` or ``-X coerce_c_locale=1`` tries to coerce the C
+     locale (:pep:`538`).
+     ``-X coerce_c_locale=0`` skips coercing the legacy ASCII-based C and POSIX
+     locales to a more capable UTF-8 based alternative.
+     ``-X coerce_c_locale=warn`` will cause Python to emit warning messages on
+     ``stderr`` if either the locale coercion activates, or else if a locale
+     that *would* have triggered coercion is still active when the Python
+     runtime is initialized.
+     See :envvar:`PYTHONCOERCECLOCALE` for more details.
 
    It also allows passing arbitrary values and retrieving them through the
    :data:`sys._xoptions` dictionary.
@@ -461,6 +470,9 @@ Miscellaneous options
    .. versionadded:: 3.7
       The ``-X importtime``, ``-X dev`` and ``-X utf8`` options.
 
+   .. versionadded:: 3.7.1
+      The ``-X coerce_c_locale`` option.
+
 
 Options you shouldn't use
 ~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -834,6 +846,8 @@ conflict.
    order to force the interpreter to use ``ASCII`` instead of ``UTF-8`` for
    system interfaces.
 
+   Also available as the :option:`-X` ``coerce_c_locale`` option.
+
    Availability: \*nix
 
    .. versionadded:: 3.7
index f53a0268738ad221b931ee2e823baa1122259a0e..6cd9d46a42b0ab23ce34d1e5de82055d88af9bd7 100644 (file)
@@ -2494,3 +2494,10 @@ versions, it respected an ill-defined subset of those environment variables,
 while in Python 3.7.0 it didn't read any of them due to :issue:`34247`). If
 this behavior is unwanted, set :c:data:`Py_IgnoreEnvironmentFlag` to 1 before
 calling :c:func:`Py_Initialize`.
+
+:c:func:`Py_Initialize` and :c:func:`Py_Main` cannot enable the C locale
+coercion (:pep:`538`) anymore: it is always disabled. It can now only be
+enabled by the Python program ("python3).
+
+New :option:`-X` ``coerce_c_locale`` command line option to control C locale
+coercion (:pep:`538`).
index 119296194934e907602a30023aec27995da7dccb..68fc036479fd961edbcfac9190ad6b82031acacb 100644 (file)
@@ -119,7 +119,11 @@ PyAPI_FUNC(int) Py_FdIsInteractive(FILE *, const char *);
 /* Bootstrap __main__ (defined in Modules/main.c) */
 PyAPI_FUNC(int) Py_Main(int argc, wchar_t **argv);
 #ifdef Py_BUILD_CORE
+#  ifdef MS_WINDOWS
+PyAPI_FUNC(int) _Py_WindowsMain(int argc, wchar_t **argv);
+#  else
 PyAPI_FUNC(int) _Py_UnixMain(int argc, char **argv);
+#  endif
 #endif
 
 /* In getpath.c */
index f16ffb8fd2aef180bedb204d37528dd81ff41718..c2ccb203db2007d1bf1022d7c111d667643dcc63 100644 (file)
@@ -41,8 +41,6 @@ typedef struct {
     int show_alloc_count;   /* -X showalloccount */
     int dump_refs;          /* PYTHONDUMPREFS */
     int malloc_stats;       /* PYTHONMALLOCSTATS */
-    int coerce_c_locale;    /* PYTHONCOERCECLOCALE, -1 means unknown */
-    int coerce_c_locale_warn; /* PYTHONCOERCECLOCALE=warn */
     int utf8_mode;          /* PYTHONUTF8, -X utf8; -1 means unknown */
 
     wchar_t *program_name;  /* Program name, see also Py_GetProgramName() */
@@ -74,6 +72,8 @@ typedef struct {
 
     /* Private fields */
     int _disable_importlib; /* Needed by freeze_importlib */
+    int _coerce_c_locale;    /* PYTHONCOERCECLOCALE, -1 means unknown */
+    int _coerce_c_locale_warn; /* PYTHONCOERCECLOCALE=warn */
 } _PyCoreConfig;
 
 #define _PyCoreConfig_INIT \
@@ -81,7 +81,8 @@ typedef struct {
         .install_signal_handlers = -1, \
         .ignore_environment = -1, \
         .use_hash_seed = -1, \
-        .coerce_c_locale = -1, \
+        ._coerce_c_locale = 0, \
+        ._coerce_c_locale_warn = 0, \
         .faulthandler = -1, \
         .tracemalloc = -1, \
         .utf8_mode = -1, \
index 1db293b9c37359be50c72e4b94f38823b2e9bfb5..f62208ab2006f3254137993e9ac3f481a4f28804 100644 (file)
@@ -139,7 +139,7 @@ class EncodingDetails(_EncodingDetails):
         return data
 
     @classmethod
-    def get_child_details(cls, env_vars):
+    def get_child_details(cls, env_vars, xoption=None):
         """Retrieves fsencoding and standard stream details from a child process
 
         Returns (encoding_details, stderr_lines):
@@ -150,10 +150,11 @@ class EncodingDetails(_EncodingDetails):
         The child is run in isolated mode if the current interpreter supports
         that.
         """
-        result, py_cmd = run_python_until_end(
-            "-X", "utf8=0", "-c", cls.CHILD_PROCESS_SCRIPT,
-            **env_vars
-        )
+        args = []
+        if xoption:
+            args.extend(("-X", f"coerce_c_locale={xoption}"))
+        args.extend(("-X", "utf8=0", "-c", cls.CHILD_PROCESS_SCRIPT))
+        result, py_cmd = run_python_until_end(*args, **env_vars)
         if not result.rc == 0:
             result.fail(py_cmd)
         # All subprocess outputs in this test case should be pure ASCII
@@ -212,7 +213,8 @@ class _LocaleHandlingTestCase(unittest.TestCase):
                                       expected_fs_encoding,
                                       expected_stream_encoding,
                                       expected_warnings,
-                                      coercion_expected):
+                                      coercion_expected,
+                                      xoption=None):
         """Check the C locale handling for the given process environment
 
         Parameters:
@@ -220,7 +222,7 @@ class _LocaleHandlingTestCase(unittest.TestCase):
             expected_stream_encoding: expected encoding for standard streams
             expected_warning: stderr output to expect (if any)
         """
-        result = EncodingDetails.get_child_details(env_vars)
+        result = EncodingDetails.get_child_details(env_vars, xoption)
         encoding_details, stderr_lines = result
         expected_details = EncodingDetails.get_expected_details(
             coercion_expected,
@@ -290,6 +292,7 @@ class LocaleCoercionTests(_LocaleHandlingTestCase):
                                  coerce_c_locale,
                                  expected_warnings=None,
                                  coercion_expected=True,
+                                 use_xoption=False,
                                  **extra_vars):
         """Check the C locale handling for various configurations
 
@@ -319,8 +322,12 @@ class LocaleCoercionTests(_LocaleHandlingTestCase):
             "PYTHONCOERCECLOCALE": "",
         }
         base_var_dict.update(extra_vars)
+        xoption = None
         if coerce_c_locale is not None:
-            base_var_dict["PYTHONCOERCECLOCALE"] = coerce_c_locale
+            if use_xoption:
+                xoption = coerce_c_locale
+            else:
+                base_var_dict["PYTHONCOERCECLOCALE"] = coerce_c_locale
 
         # Check behaviour for the default locale
         with self.subTest(default_locale=True,
@@ -342,7 +349,8 @@ class LocaleCoercionTests(_LocaleHandlingTestCase):
                                                fs_encoding,
                                                stream_encoding,
                                                _expected_warnings,
-                                               _coercion_expected)
+                                               _coercion_expected,
+                                               xoption=xoption)
 
         # Check behaviour for explicitly configured locales
         for locale_to_set in EXPECTED_C_LOCALE_EQUIVALENTS:
@@ -357,7 +365,8 @@ class LocaleCoercionTests(_LocaleHandlingTestCase):
                                                        fs_encoding,
                                                        stream_encoding,
                                                        expected_warnings,
-                                                       coercion_expected)
+                                                       coercion_expected,
+                                                       xoption=xoption)
 
     def test_PYTHONCOERCECLOCALE_not_set(self):
         # This should coerce to the first available target locale by default
@@ -404,6 +413,32 @@ class LocaleCoercionTests(_LocaleHandlingTestCase):
                                       expected_warnings=[LEGACY_LOCALE_WARNING],
                                       coercion_expected=False)
 
+    def test_xoption_set_to_1(self):
+        self._check_c_locale_coercion("utf-8", "utf-8", coerce_c_locale="1",
+                                      use_xoption=True)
+
+    def test_xoption_set_to_zero(self):
+        # The setting "0" should result in the locale coercion being disabled
+        self._check_c_locale_coercion(EXPECTED_C_LOCALE_FS_ENCODING,
+                                      EXPECTED_C_LOCALE_STREAM_ENCODING,
+                                      coerce_c_locale="0",
+                                      coercion_expected=False,
+                                      use_xoption=True)
+        # Setting LC_ALL=C shouldn't make any difference to the behaviour
+        self._check_c_locale_coercion(EXPECTED_C_LOCALE_FS_ENCODING,
+                                      EXPECTED_C_LOCALE_STREAM_ENCODING,
+                                      coerce_c_locale="0",
+                                      LC_ALL="C",
+                                      coercion_expected=False,
+                                      use_xoption=True)
+
+    def test_xoption_set_to_warn(self):
+        # -X coerce_c_locale=warn enables runtime warnings for legacy locales
+        self._check_c_locale_coercion("utf-8", "utf-8",
+                                      coerce_c_locale="warn",
+                                      expected_warnings=[CLI_COERCION_WARNING],
+                                      use_xoption=True)
+
 def test_main():
     test.support.run_unittest(
         LocaleConfigurationTests,
index 95cdc8db7efbcc1c1c2386a82bb993c6a171981b..0424f75b3b8c6d5477adf48170676d0a2e6b87fc 100644 (file)
@@ -159,13 +159,16 @@ class CmdLineTest(unittest.TestCase):
         env = os.environ.copy()
         # Use C locale to get ascii for the locale encoding
         env['LC_ALL'] = 'C'
-        env['PYTHONCOERCECLOCALE'] = '0'
         code = (
             b'import locale; '
             b'print(ascii("' + undecodable + b'"), '
                 b'locale.getpreferredencoding())')
         p = subprocess.Popen(
-            [sys.executable, "-c", code],
+            [sys.executable,
+             # Disable C locale coercion and UTF-8 Mode to not use UTF-8
+             "-X", "coerce_c_locale=0",
+             "-X", "utf8=0",
+             "-c", code],
             stdout=subprocess.PIPE, stderr=subprocess.STDOUT,
             env=env)
         stdout, stderr = p.communicate()
index 29274580339f0a01039358a146562a9dc9238633..79c34ec591a0e2afe526de79b10c31745d60cfc5 100644 (file)
@@ -267,9 +267,6 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
         'malloc_stats': 0,
         'utf8_mode': 0,
 
-        'coerce_c_locale': 0,
-        'coerce_c_locale_warn': 0,
-
         'program_name': './_testembed',
         'argc': 0,
         'argv': '[]',
@@ -290,6 +287,8 @@ class InitConfigTests(EmbeddingTestsMixin, unittest.TestCase):
 
         '_disable_importlib': 0,
         'Py_FrozenFlag': 0,
+        '_coerce_c_locale': 0,
+        '_coerce_c_locale_warn': 0,
     }
 
     def check_config(self, testname, expected):
index 27f75901c63fda4fbacaf5443e84dedecda60a85..9155afc069e1840985c7e97822e9b06818f30cbb 100644 (file)
@@ -656,9 +656,8 @@ class SysModuleTest(unittest.TestCase):
 
     def c_locale_get_error_handler(self, locale, isolated=False, encoding=None):
         # Force the POSIX locale
-        env = os.environ.copy()
+        env = dict(os.environ)
         env["LC_ALL"] = locale
-        env["PYTHONCOERCECLOCALE"] = "0"
         code = '\n'.join((
             'import sys',
             'def dump(name):',
@@ -668,7 +667,10 @@ class SysModuleTest(unittest.TestCase):
             'dump("stdout")',
             'dump("stderr")',
         ))
-        args = [sys.executable, "-c", code]
+        args = [sys.executable,
+                "-X", "utf8=0",
+                "-X", "coerce_c_locale=0",
+                "-c", code]
         if isolated:
             args.append("-I")
         if encoding is not None:
index 554abfab3163159ea021c6d181bcef8374bffa56..8c64276bcf68f585bd7322e40163a17a0c05d024 100644 (file)
@@ -27,6 +27,8 @@ class UTF8ModeTests(unittest.TestCase):
         return (loc in POSIX_LOCALES)
 
     def get_output(self, *args, failure=False, **kw):
+        # Always disable the C locale coercion (PEP 538)
+        args = ('-X', 'coerce_c_locale=0', *args)
         kw = dict(self.DEFAULT_ENV, **kw)
         if failure:
             out = assert_python_failure(*args, **kw)
@@ -116,7 +118,6 @@ class UTF8ModeTests(unittest.TestCase):
             # PYTHONLEGACYWINDOWSFSENCODING disables the UTF-8 mode
             # and has the priority over -X utf8 and PYTHONUTF8
             out = self.get_output('-X', 'utf8', '-c', code,
-                                  PYTHONUTF8='strict',
                                   PYTHONLEGACYWINDOWSFSENCODING='1')
             self.assertEqual(out, 'mbcs/replace')
 
diff --git a/Misc/NEWS.d/next/C API/2018-09-18-00-09-31.bpo-34589.C7bUpq.rst b/Misc/NEWS.d/next/C API/2018-09-18-00-09-31.bpo-34589.C7bUpq.rst
new file mode 100644 (file)
index 0000000..27b6a6e
--- /dev/null
@@ -0,0 +1,3 @@
+Py_Initialize() and Py_Main() cannot enable the C locale coercion (PEP 538)
+anymore: it is always disabled. It can now only be enabled by the Python
+program ("python3).
diff --git a/Misc/NEWS.d/next/Core and Builtins/2018-09-18-01-41-33.bpo-34589.lLVTYc.rst b/Misc/NEWS.d/next/Core and Builtins/2018-09-18-01-41-33.bpo-34589.lLVTYc.rst
new file mode 100644 (file)
index 0000000..618092d
--- /dev/null
@@ -0,0 +1,2 @@
+Add a new :option:`-X` ``coerce_c_locale`` command line option to control C
+locale coercion (:pep:`538`).
index 0f7498d6104fe44b46de56cb9419881da031b059..c6ffb15d9f995794878239aa79dc746865b7be0c 100644 (file)
@@ -1834,6 +1834,17 @@ config_init_utf8_mode(_PyCoreConfig *config)
         return _Py_INIT_OK();
     }
 
+#ifndef MS_WINDOWS
+    /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
+    const char *ctype_loc = setlocale(LC_CTYPE, NULL);
+    if (ctype_loc != NULL
+        && (strcmp(ctype_loc, "C") == 0 || strcmp(ctype_loc, "POSIX") == 0))
+    {
+        config->utf8_mode = 1;
+        return _Py_INIT_OK();
+    }
+#endif
+
     return _Py_INIT_OK();
 }
 
@@ -1857,16 +1868,18 @@ config_read_env_vars(_PyCoreConfig *config)
     const char *env = config_get_env_var("PYTHONCOERCECLOCALE");
     if (env) {
         if (strcmp(env, "0") == 0) {
-            if (config->coerce_c_locale < 0) {
-                config->coerce_c_locale = 0;
+            if (config->_coerce_c_locale < 0) {
+                config->_coerce_c_locale = 0;
             }
         }
         else if (strcmp(env, "warn") == 0) {
-            config->coerce_c_locale_warn = 1;
+            if (config->_coerce_c_locale_warn < 0) {
+                config->_coerce_c_locale_warn = 1;
+            }
         }
         else {
-            if (config->coerce_c_locale < 0) {
-                config->coerce_c_locale = 1;
+            if (config->_coerce_c_locale < 0) {
+                config->_coerce_c_locale = 1;
             }
         }
     }
@@ -2046,7 +2059,7 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline)
          * See the documentation of the PYTHONCOERCECLOCALE setting for more
          * details.
          */
-        if (config->coerce_c_locale && !locale_coerced) {
+        if (config->_coerce_c_locale && !locale_coerced) {
             locale_coerced = 1;
             _Py_CoerceLegacyLocale(config);
             encoding_changed = 1;
@@ -2073,7 +2086,7 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline)
            pymain_read_conf_impl(). Reset Py_IsolatedFlag and Py_NoSiteFlag
            modified by _PyCoreConfig_Read(). */
         int new_utf8_mode = config->utf8_mode;
-        int new_coerce_c_locale = config->coerce_c_locale;
+        int new_coerce_c_locale = config->_coerce_c_locale;
         Py_IgnoreEnvironmentFlag = init_ignore_env;
         if (_PyCoreConfig_Copy(config, &save_config) < 0) {
             pymain->err = _Py_INIT_NO_MEMORY();
@@ -2085,7 +2098,7 @@ pymain_read_conf(_PyMain *pymain, _Py_CommandLineDetails *cmdline)
         cmdline_get_global_config(cmdline);
         _PyCoreConfig_GetGlobalConfig(config);
         config->utf8_mode = new_utf8_mode;
-        config->coerce_c_locale = new_coerce_c_locale;
+        config->_coerce_c_locale = new_coerce_c_locale;
 
         /* The encoding changed: read again the configuration
            with the new encoding */
@@ -2103,28 +2116,76 @@ done:
 }
 
 
-static void
-config_init_locale(_PyCoreConfig *config)
+static _PyInitError
+config_init_coerce_c_locale(_PyCoreConfig *config)
 {
-    if (config->coerce_c_locale < 0) {
-        /* The C locale enables the C locale coercion (PEP 538) */
-        if (_Py_LegacyLocaleDetected()) {
-            config->coerce_c_locale = 1;
+    const wchar_t *xopt = config_get_xoption(config, L"coerce_c_locale");
+    if (xopt) {
+        wchar_t *sep = wcschr(xopt, L'=');
+        if (sep) {
+            xopt = sep + 1;
+            if (wcscmp(xopt, L"1") == 0) {
+                if (config->_coerce_c_locale < 0) {
+                    config->_coerce_c_locale = 1;
+                }
+            }
+            else if (wcscmp(xopt, L"0") == 0) {
+                if (config->_coerce_c_locale < 0) {
+                    config->_coerce_c_locale = 0;
+                }
+            }
+            else if (wcscmp(xopt, L"warn") == 0) {
+                if (config->_coerce_c_locale_warn < 0) {
+                    config->_coerce_c_locale_warn = 1;
+                }
+            }
+            else {
+                return _Py_INIT_USER_ERR("invalid -X coerce_c_locale option value");
+            }
+        }
+        else {
+            if (config->_coerce_c_locale < 0) {
+                config->_coerce_c_locale = 1;
+            }
+        }
+
+        if (config->_coerce_c_locale_warn < 0) {
+            config->_coerce_c_locale_warn = 0;
         }
     }
 
-#ifndef MS_WINDOWS
-    if (config->utf8_mode < 0) {
-        /* The C locale and the POSIX locale enable the UTF-8 Mode (PEP 540) */
-        const char *ctype_loc = setlocale(LC_CTYPE, NULL);
-        if (ctype_loc != NULL
-           && (strcmp(ctype_loc, "C") == 0
-               || strcmp(ctype_loc, "POSIX") == 0))
-        {
-            config->utf8_mode = 1;
+    const char *env = config_get_env_var("PYTHONCOERCECLOCALE");
+    if (env) {
+        if (strcmp(env, "0") == 0) {
+            if (config->_coerce_c_locale < 0) {
+                config->_coerce_c_locale = 0;
+            }
+        }
+        else if (strcmp(env, "warn") == 0) {
+            if (config->_coerce_c_locale_warn < 0) {
+                config->_coerce_c_locale_warn = 1;
+            }
+        }
+        else {
+            if (config->_coerce_c_locale < 0) {
+                config->_coerce_c_locale = 1;
+            }
+        }
+
+        if (config->_coerce_c_locale_warn < 0) {
+            config->_coerce_c_locale_warn = 0;
         }
     }
-#endif
+
+    if (config->_coerce_c_locale < 0) {
+        /* The C locale enables the C locale coercion (PEP 538) */
+        if (_Py_LegacyLocaleDetected()) {
+            config->_coerce_c_locale = 1;
+            return _Py_INIT_OK();
+        }
+    }
+
+    return _Py_INIT_OK();
 }
 
 
@@ -2284,8 +2345,11 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
         }
     }
 
-    if (config->utf8_mode < 0 || config->coerce_c_locale < 0) {
-        config_init_locale(config);
+    if (config->_coerce_c_locale < 0 || config->_coerce_c_locale_warn < 0) {
+        err = config_init_coerce_c_locale(config);
+        if (_Py_INIT_FAILED(err)) {
+            return err;
+        }
     }
 
     if (!config->_disable_importlib) {
@@ -2317,8 +2381,11 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
     if (config->tracemalloc < 0) {
         config->tracemalloc = 0;
     }
-    if (config->coerce_c_locale < 0) {
-        config->coerce_c_locale = 0;
+    if (config->_coerce_c_locale < 0) {
+        config->_coerce_c_locale = 0;
+    }
+    if (config->_coerce_c_locale_warn < 0) {
+        config->_coerce_c_locale_warn = 0;
     }
     if (config->utf8_mode < 0) {
         config->utf8_mode = 0;
@@ -2327,6 +2394,10 @@ _PyCoreConfig_Read(_PyCoreConfig *config)
         config->argc = 0;
     }
 
+    assert(config->_coerce_c_locale >= 0);
+    assert(config->_coerce_c_locale_warn >= 0);
+    assert(config->ignore_environment >= 0);
+
     return _Py_INIT_OK();
 }
 
@@ -2410,8 +2481,8 @@ _PyCoreConfig_Copy(_PyCoreConfig *config, const _PyCoreConfig *config2)
     COPY_ATTR(dump_refs);
     COPY_ATTR(malloc_stats);
 
-    COPY_ATTR(coerce_c_locale);
-    COPY_ATTR(coerce_c_locale_warn);
+    COPY_ATTR(_coerce_c_locale);
+    COPY_ATTR(_coerce_c_locale_warn);
     COPY_ATTR(utf8_mode);
 
     COPY_STR_ATTR(module_search_path_env);
@@ -2638,7 +2709,7 @@ pymain_run_python(_PyMain *pymain)
 
 
 static void
-pymain_init(_PyMain *pymain)
+pymain_init(_PyMain *pymain, int use_c_locale_coercion)
 {
     /* 754 requires that FP exceptions run in "no stop" mode by default,
      * and until C vendors implement C99's ways to control FP exceptions,
@@ -2651,6 +2722,11 @@ pymain_init(_PyMain *pymain)
 
     pymain->config._disable_importlib = 0;
     pymain->config.install_signal_handlers = 1;
+    if (use_c_locale_coercion) {
+        /* set to -1 to be able to enable the feature */
+        pymain->config._coerce_c_locale = -1;
+        pymain->config._coerce_c_locale_warn = -1;
+    }
 }
 
 
@@ -2751,9 +2827,9 @@ pymain_cmdline(_PyMain *pymain)
 
 
 static int
-pymain_main(_PyMain *pymain)
+pymain_main(_PyMain *pymain, int use_c_locale_coercion)
 {
-    pymain_init(pymain);
+    pymain_init(pymain, use_c_locale_coercion);
 
     int res = pymain_cmdline(pymain);
     if (res < 0) {
@@ -2802,10 +2878,22 @@ Py_Main(int argc, wchar_t **argv)
     pymain.argc = argc;
     pymain.wchar_argv = argv;
 
-    return pymain_main(&pymain);
+    return pymain_main(&pymain, 0);
 }
 
 
+#ifdef MS_WINDOWS
+int
+_Py_WindowsMain(int argc, wchar_t **argv)
+{
+    _PyMain pymain = _PyMain_INIT;
+    pymain.use_bytes_argv = 0;
+    pymain.argc = argc;
+    pymain.wchar_argv = argv;
+
+    return pymain_main(&pymain, 1);
+}
+#else
 int
 _Py_UnixMain(int argc, char **argv)
 {
@@ -2814,8 +2902,9 @@ _Py_UnixMain(int argc, char **argv)
     pymain.argc = argc;
     pymain.bytes_argv = argv;
 
-    return pymain_main(&pymain);
+    return pymain_main(&pymain, 1);
 }
+#endif
 
 
 /* this is gonna seem *real weird*, but if you put some other code between
index 6c35f9586bfe18029b5040be1e327d210bac6f9e..029f6ad4b680e42b1d98ba1473a8b746f6afb023 100644 (file)
@@ -328,8 +328,8 @@ dump_config(void)
     printf("dump_refs = %i\n", config->dump_refs);
     printf("malloc_stats = %i\n", config->malloc_stats);
 
-    printf("coerce_c_locale = %i\n", config->coerce_c_locale);
-    printf("coerce_c_locale_warn = %i\n", config->coerce_c_locale_warn);
+    printf("_coerce_c_locale = %i\n", config->_coerce_c_locale);
+    printf("_coerce_c_locale_warn = %i\n", config->_coerce_c_locale_warn);
     printf("utf8_mode = %i\n", config->utf8_mode);
 
     printf("program_name = %ls\n", config->program_name);
@@ -473,8 +473,6 @@ static int test_init_from_config(void)
     putenv("PYTHONMALLOCSTATS=0");
     config.malloc_stats = 1;
 
-    /* FIXME: test coerce_c_locale and coerce_c_locale_warn */
-
     putenv("PYTHONUTF8=0");
     Py_UTF8Mode = 0;
     config.utf8_mode = 1;
@@ -544,8 +542,7 @@ static int test_init_isolated(void)
     /* Test _PyCoreConfig.isolated=1 */
     _PyCoreConfig config = _PyCoreConfig_INIT;
 
-    /* Set coerce_c_locale and utf8_mode to not depend on the locale */
-    config.coerce_c_locale = 0;
+    /* Set utf8_mode to not depend on the locale */
     config.utf8_mode = 0;
     /* Use path starting with "./" avoids a search along the PATH */
     config.program_name = L"./_testembed";
index 78e48f800c950530e36d3712d9e2e89673f23562..c7697facbe3b044f0553d7a655643cdffd55726e 100644 (file)
@@ -6,7 +6,7 @@
 int
 wmain(int argc, wchar_t **argv)
 {
-    return Py_Main(argc, argv);
+    return _Py_WindowsMain(argc, argv);
 }
 #else
 int
index ba4b54864fd8e746f49ae20cb4925eb4f90fc4e2..ef742c16c014a59613626678cba6e87d1c4aed79 100644 (file)
@@ -400,7 +400,7 @@ static const char *_C_LOCALE_WARNING =
 static void
 _emit_stderr_warning_for_legacy_locale(const _PyCoreConfig *core_config)
 {
-    if (core_config->coerce_c_locale_warn) {
+    if (core_config->_coerce_c_locale_warn) {
         if (_Py_LegacyLocaleDetected()) {
             fprintf(stderr, "%s", _C_LOCALE_WARNING);
         }
@@ -462,7 +462,7 @@ _coerce_default_locale_settings(const _PyCoreConfig *config, const _LocaleCoerci
                 "Error setting LC_CTYPE, skipping C locale coercion\n");
         return;
     }
-    if (config->coerce_c_locale_warn) {
+    if (config->_coerce_c_locale_warn) {
         fprintf(stderr, C_LOCALE_COERCION_WARNING, newloc);
     }