@@ -112,12 +112,16 @@ class EncodingDetails(_EncodingDetails):
112
112
])
113
113
114
114
@classmethod
115
- def get_expected_details (cls , coercion_expected , fs_encoding , stream_encoding , env_vars ):
115
+ def get_expected_details (cls , coercion_expected , fs_encoding , stream_encoding , stream_errors , env_vars ):
116
116
"""Returns expected child process details for a given encoding"""
117
117
_stream = stream_encoding + ":{}"
118
- # stdin and stdout should use surrogateescape either because the
119
- # coercion triggered, or because the C locale was detected
120
- stream_info = 2 * [_stream .format ("surrogateescape" )]
118
+ if stream_errors is None :
119
+ # stdin and stdout should use surrogateescape either because the
120
+ # coercion triggered, or because the C locale was detected
121
+ stream_errors = "surrogateescape"
122
+
123
+ stream_info = [_stream .format (stream_errors )] * 2
124
+
121
125
# stderr should always use backslashreplace
122
126
stream_info .append (_stream .format ("backslashreplace" ))
123
127
expected_lang = env_vars .get ("LANG" , "not set" )
@@ -210,6 +214,7 @@ def _check_child_encoding_details(self,
210
214
env_vars ,
211
215
expected_fs_encoding ,
212
216
expected_stream_encoding ,
217
+ expected_stream_errors ,
213
218
expected_warnings ,
214
219
coercion_expected ):
215
220
"""Check the C locale handling for the given process environment
@@ -225,6 +230,7 @@ def _check_child_encoding_details(self,
225
230
coercion_expected ,
226
231
expected_fs_encoding ,
227
232
expected_stream_encoding ,
233
+ expected_stream_errors ,
228
234
env_vars
229
235
)
230
236
self .assertEqual (encoding_details , expected_details )
@@ -257,6 +263,7 @@ def test_external_target_locale_configuration(self):
257
263
"LC_CTYPE" : "" ,
258
264
"LC_ALL" : "" ,
259
265
"PYTHONCOERCECLOCALE" : "" ,
266
+ "PYTHONIOENCODING" : "" ,
260
267
}
261
268
for env_var in ("LANG" , "LC_CTYPE" ):
262
269
for locale_to_set in AVAILABLE_TARGETS :
@@ -273,10 +280,43 @@ def test_external_target_locale_configuration(self):
273
280
self ._check_child_encoding_details (var_dict ,
274
281
expected_fs_encoding ,
275
282
expected_stream_encoding ,
283
+ expected_stream_errors = None ,
276
284
expected_warnings = None ,
277
285
coercion_expected = False )
278
286
287
+ def test_with_ioencoding (self ):
288
+ # Explicitly setting a target locale should give the same behaviour as
289
+ # is seen when implicitly coercing to that target locale
290
+ self .maxDiff = None
291
+
292
+ expected_fs_encoding = "utf-8"
293
+ expected_stream_encoding = "utf-8"
279
294
295
+ base_var_dict = {
296
+ "LANG" : "" ,
297
+ "LC_CTYPE" : "" ,
298
+ "LC_ALL" : "" ,
299
+ "PYTHONCOERCECLOCALE" : "" ,
300
+ "PYTHONIOENCODING" : "UTF-8" ,
301
+ }
302
+ for env_var in ("LANG" , "LC_CTYPE" ):
303
+ for locale_to_set in AVAILABLE_TARGETS :
304
+ # XXX (ncoghlan): LANG=UTF-8 doesn't appear to work as
305
+ # expected, so skip that combination for now
306
+ # See https://bugs.python.org/issue30672 for discussion
307
+ if env_var == "LANG" and locale_to_set == "UTF-8" :
308
+ continue
309
+
310
+ with self .subTest (env_var = env_var ,
311
+ configured_locale = locale_to_set ):
312
+ var_dict = base_var_dict .copy ()
313
+ var_dict [env_var ] = locale_to_set
314
+ self ._check_child_encoding_details (var_dict ,
315
+ expected_fs_encoding ,
316
+ expected_stream_encoding ,
317
+ expected_stream_errors = "strict" ,
318
+ expected_warnings = None ,
319
+ coercion_expected = False )
280
320
281
321
@support .cpython_only
282
322
@unittest .skipUnless (sysconfig .get_config_var ("PY_COERCE_C_LOCALE" ),
@@ -316,6 +356,7 @@ def _check_c_locale_coercion(self,
316
356
"LC_CTYPE" : "" ,
317
357
"LC_ALL" : "" ,
318
358
"PYTHONCOERCECLOCALE" : "" ,
359
+ "PYTHONIOENCODING" : "" ,
319
360
}
320
361
base_var_dict .update (extra_vars )
321
362
if coerce_c_locale is not None :
@@ -340,6 +381,7 @@ def _check_c_locale_coercion(self,
340
381
self ._check_child_encoding_details (base_var_dict ,
341
382
fs_encoding ,
342
383
stream_encoding ,
384
+ None ,
343
385
_expected_warnings ,
344
386
_coercion_expected )
345
387
@@ -348,13 +390,15 @@ def _check_c_locale_coercion(self,
348
390
for env_var in ("LANG" , "LC_CTYPE" ):
349
391
with self .subTest (env_var = env_var ,
350
392
nominal_locale = locale_to_set ,
351
- PYTHONCOERCECLOCALE = coerce_c_locale ):
393
+ PYTHONCOERCECLOCALE = coerce_c_locale ,
394
+ PYTHONIOENCODING = "" ):
352
395
var_dict = base_var_dict .copy ()
353
396
var_dict [env_var ] = locale_to_set
354
397
# Check behaviour on successful coercion
355
398
self ._check_child_encoding_details (var_dict ,
356
399
fs_encoding ,
357
400
stream_encoding ,
401
+ None ,
358
402
expected_warnings ,
359
403
coercion_expected )
360
404
0 commit comments