Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitdb03c80

Browse files
authored
gh-98393: os module reject bytes-like, only accept bytes (#98394)
The os module and the PyUnicode_FSDecoder() function no longer acceptbytes-like paths, like bytearray and memoryview types: only the exactbytes type is accepted for bytes strings.
1 parent9da5215 commitdb03c80

File tree

9 files changed

+48
-89
lines changed

9 files changed

+48
-89
lines changed

‎Doc/whatsnew/3.12.rst

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,11 @@ Changes in the Python API
515515
in Python 3.9.
516516
(Contributed by Victor Stinner in:gh:`94352`.)
517517

518+
* The:mod:`os` module no longer accepts bytes-like paths, like
519+
:class:`bytearray` and:class:`memoryview` types: only the exact
520+
:class:`bytes` type is accepted for bytes strings.
521+
(Contributed by Victor Stinner in:gh:`98393`.)
522+
518523

519524
Build Changes
520525
=============
@@ -631,6 +636,11 @@ Porting to Python 3.12
631636
to traverse and clear their instance's dictionaries.
632637
To clear weakrefs, call:c:func:`PyObject_ClearWeakRefs`, as before.
633638

639+
* The:c:func:`PyUnicode_FSDecoder` function no longer accepts bytes-like
640+
paths, like:class:`bytearray` and:class:`memoryview` types: only the exact
641+
:class:`bytes` type is accepted for bytes strings.
642+
(Contributed by Victor Stinner in:gh:`98393`.)
643+
634644
Deprecated
635645
----------
636646

‎Lib/test/test_compile.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -494,9 +494,8 @@ def test_compile_filename(self):
494494
code=compile('pass',filename,'exec')
495495
self.assertEqual(code.co_filename,'file.py')
496496
forfilenameinbytearray(b'file.py'),memoryview(b'file.py'):
497-
withself.assertWarns(DeprecationWarning):
498-
code=compile('pass',filename,'exec')
499-
self.assertEqual(code.co_filename,'file.py')
497+
withself.assertRaises(TypeError):
498+
compile('pass',filename,'exec')
500499
self.assertRaises(TypeError,compile,'pass',list(b'file.py'),'exec')
501500

502501
@support.cpython_only

‎Lib/test/test_os.py

Lines changed: 12 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3860,18 +3860,18 @@ def test_oserror_filename(self):
38603860

38613861
forfilenames,func,*func_argsinfuncs:
38623862
fornameinfilenames:
3863-
try:
3864-
ifisinstance(name, (str,bytes)):
3863+
ifnotisinstance(name, (str,bytes)):
3864+
withself.assertRaises(TypeError):
38653865
func(name,*func_args)
3866-
else:
3867-
withself.assertWarnsRegex(DeprecationWarning,'should be'):
3868-
func(name,*func_args)
3869-
exceptOSErroraserr:
3870-
self.assertIs(err.filename,name,str(func))
3871-
exceptUnicodeDecodeError:
3872-
pass
38733866
else:
3874-
self.fail("No exception thrown by {}".format(func))
3867+
try:
3868+
func(name,*func_args)
3869+
exceptOSErroraserr:
3870+
self.assertIs(err.filename,name,str(func))
3871+
exceptUnicodeDecodeError:
3872+
pass
3873+
else:
3874+
self.fail("No exception thrown by {}".format(func))
38753875

38763876
classCPUCountTests(unittest.TestCase):
38773877
deftest_cpu_count(self):
@@ -4350,16 +4350,8 @@ def test_bytes_like(self):
43504350

43514351
forclsinbytearray,memoryview:
43524352
path_bytes=cls(os.fsencode(self.path))
4353-
withself.assertWarns(DeprecationWarning):
4354-
entries=list(os.scandir(path_bytes))
4355-
self.assertEqual(len(entries),1,entries)
4356-
entry=entries[0]
4357-
4358-
self.assertEqual(entry.name,b'file.txt')
4359-
self.assertEqual(entry.path,
4360-
os.fsencode(os.path.join(self.path,'file.txt')))
4361-
self.assertIs(type(entry.name),bytes)
4362-
self.assertIs(type(entry.path),bytes)
4353+
withself.assertRaises(TypeError):
4354+
list(os.scandir(path_bytes))
43634355

43644356
@unittest.skipUnless(os.listdirinos.supports_fd,
43654357
'fd support for listdir required for this test.')

‎Lib/test/test_posix.py

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -634,7 +634,7 @@ def test_stat(self):
634634
self.assertTrue(posix.stat(os_helper.TESTFN))
635635
self.assertTrue(posix.stat(os.fsencode(os_helper.TESTFN)))
636636

637-
self.assertWarnsRegex(DeprecationWarning,
637+
self.assertRaisesRegex(TypeError,
638638
'should be string, bytes, os.PathLike or integer, not',
639639
posix.stat,bytearray(os.fsencode(os_helper.TESTFN)))
640640
self.assertRaisesRegex(TypeError,
@@ -841,11 +841,8 @@ def test_listdir_bytes(self):
841841

842842
deftest_listdir_bytes_like(self):
843843
forclsinbytearray,memoryview:
844-
withself.assertWarns(DeprecationWarning):
845-
names=posix.listdir(cls(b'.'))
846-
self.assertIn(os.fsencode(os_helper.TESTFN),names)
847-
fornameinnames:
848-
self.assertIs(type(name),bytes)
844+
withself.assertRaises(TypeError):
845+
posix.listdir(cls(b'.'))
849846

850847
@unittest.skipUnless(posix.listdirinos.supports_fd,
851848
"test needs fd support for posix.listdir()")

‎Lib/test/test_symtable.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -222,10 +222,9 @@ def checkfilename(brokencode, offset):
222222
checkfilename("def f(x): foo)(",14)# parse-time
223223
checkfilename("def f(x): global x",11)# symtable-build-time
224224
symtable.symtable("pass",b"spam","exec")
225-
withself.assertWarns(DeprecationWarning), \
226-
self.assertRaises(TypeError):
225+
withself.assertRaises(TypeError):
227226
symtable.symtable("pass",bytearray(b"spam"),"exec")
228-
withself.assertWarns(DeprecationWarning):
227+
withself.assertRaises(TypeError):
229228
symtable.symtable("pass",memoryview(b"spam"),"exec")
230229
withself.assertRaises(TypeError):
231230
symtable.symtable("pass",list(b"spam"),"exec")
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The:c:func:`PyUnicode_FSDecoder` function no longer accepts bytes-like
2+
paths, like:class:`bytearray` and:class:`memoryview` types: only the exact
3+
:class:`bytes` type is accepted for bytes strings. Patch by Victor Stinner.
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
The:mod:`os` module no longer accepts bytes-like paths, like
2+
:class:`bytearray` and:class:`memoryview` types: only the exact
3+
:class:`bytes` type is accepted for bytes strings. Patch by Victor Stinner.

‎Modules/posixmodule.c

Lines changed: 5 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1120,7 +1120,7 @@ path_converter(PyObject *o, void *p)
11201120
path_t*path= (path_t*)p;
11211121
PyObject*bytes=NULL;
11221122
Py_ssize_tlength=0;
1123-
intis_index,is_buffer,is_bytes,is_unicode;
1123+
intis_index,is_bytes,is_unicode;
11241124
constchar*narrow;
11251125
#ifdefMS_WINDOWS
11261126
PyObject*wo=NULL;
@@ -1158,11 +1158,10 @@ path_converter(PyObject *o, void *p)
11581158
/* Only call this here so that we don't treat the return value of
11591159
os.fspath() as an fd or buffer. */
11601160
is_index=path->allow_fd&&PyIndex_Check(o);
1161-
is_buffer=PyObject_CheckBuffer(o);
11621161
is_bytes=PyBytes_Check(o);
11631162
is_unicode=PyUnicode_Check(o);
11641163

1165-
if (!is_index&& !is_buffer&& !is_unicode&& !is_bytes) {
1164+
if (!is_index&& !is_unicode&& !is_bytes) {
11661165
/* Inline PyOS_FSPath() for better error messages. */
11671166
PyObject*func,*res;
11681167

@@ -1225,27 +1224,6 @@ path_converter(PyObject *o, void *p)
12251224
bytes=o;
12261225
Py_INCREF(bytes);
12271226
}
1228-
elseif (is_buffer) {
1229-
/* XXX Replace PyObject_CheckBuffer with PyBytes_Check in other code
1230-
after removing support of non-bytes buffer objects. */
1231-
if (PyErr_WarnFormat(PyExc_DeprecationWarning,1,
1232-
"%s%s%s should be %s, not %.200s",
1233-
path->function_name ?path->function_name :"",
1234-
path->function_name ?": " :"",
1235-
path->argument_name ?path->argument_name :"path",
1236-
path->allow_fd&&path->nullable ?"string, bytes, os.PathLike, "
1237-
"integer or None" :
1238-
path->allow_fd ?"string, bytes, os.PathLike or integer" :
1239-
path->nullable ?"string, bytes, os.PathLike or None" :
1240-
"string, bytes or os.PathLike",
1241-
_PyType_Name(Py_TYPE(o)))) {
1242-
gotoerror_exit;
1243-
}
1244-
bytes=PyBytes_FromObject(o);
1245-
if (!bytes) {
1246-
gotoerror_exit;
1247-
}
1248-
}
12491227
elseif (is_index) {
12501228
if (!_fd_converter(o,&path->fd)) {
12511229
gotoerror_exit;
@@ -4126,8 +4104,8 @@ _posix_listdir(path_t *path, PyObject *list)
41264104
constchar*name;
41274105
if (path->narrow) {
41284106
name=path->narrow;
4129-
/* only return bytes if they specified a bytes-like object */
4130-
return_str= !PyObject_CheckBuffer(path->object);
4107+
/* only return bytes if they specified a bytes object */
4108+
return_str= !PyBytes_Check(path->object);
41314109
}
41324110
else {
41334111
name=".";
@@ -14049,7 +14027,7 @@ DirEntry_from_posix_info(PyObject *module, path_t *path, const char *name,
1404914027
gotoerror;
1405014028
}
1405114029

14052-
if (!path->narrow|| !PyObject_CheckBuffer(path->object)) {
14030+
if (!path->narrow|| !PyBytes_Check(path->object)) {
1405314031
entry->name=PyUnicode_DecodeFSDefaultAndSize(name,name_len);
1405414032
if (joined_path)
1405514033
entry->path=PyUnicode_DecodeFSDefault(joined_path);

‎Objects/unicodeobject.c

Lines changed: 8 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -3619,48 +3619,25 @@ PyUnicode_FSConverter(PyObject* arg, void* addr)
36193619
int
36203620
PyUnicode_FSDecoder(PyObject*arg,void*addr)
36213621
{
3622-
intis_buffer=0;
3623-
PyObject*path=NULL;
3624-
PyObject*output=NULL;
36253622
if (arg==NULL) {
36263623
Py_DECREF(*(PyObject**)addr);
36273624
*(PyObject**)addr=NULL;
36283625
return1;
36293626
}
36303627

3631-
is_buffer=PyObject_CheckBuffer(arg);
3632-
if (!is_buffer) {
3633-
path=PyOS_FSPath(arg);
3634-
if (path==NULL) {
3635-
return0;
3636-
}
3637-
}
3638-
else {
3639-
path=arg;
3640-
Py_INCREF(arg);
3628+
PyObject*path=PyOS_FSPath(arg);
3629+
if (path==NULL) {
3630+
return0;
36413631
}
36423632

3633+
PyObject*output=NULL;
36433634
if (PyUnicode_Check(path)) {
36443635
output=path;
36453636
}
3646-
elseif (PyBytes_Check(path)||is_buffer) {
3647-
PyObject*path_bytes=NULL;
3648-
3649-
if (!PyBytes_Check(path)&&
3650-
PyErr_WarnFormat(PyExc_DeprecationWarning,1,
3651-
"path should be string, bytes, or os.PathLike, not %.200s",
3652-
Py_TYPE(arg)->tp_name)) {
3653-
Py_DECREF(path);
3654-
return0;
3655-
}
3656-
path_bytes=PyBytes_FromObject(path);
3637+
elseif (PyBytes_Check(path)) {
3638+
output=PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(path),
3639+
PyBytes_GET_SIZE(path));
36573640
Py_DECREF(path);
3658-
if (!path_bytes) {
3659-
return0;
3660-
}
3661-
output=PyUnicode_DecodeFSDefaultAndSize(PyBytes_AS_STRING(path_bytes),
3662-
PyBytes_GET_SIZE(path_bytes));
3663-
Py_DECREF(path_bytes);
36643641
if (!output) {
36653642
return0;
36663643
}
@@ -3672,6 +3649,7 @@ PyUnicode_FSDecoder(PyObject* arg, void* addr)
36723649
Py_DECREF(path);
36733650
return0;
36743651
}
3652+
36753653
if (findchar(PyUnicode_DATA(output),PyUnicode_KIND(output),
36763654
PyUnicode_GET_LENGTH(output),0,1) >=0) {
36773655
PyErr_SetString(PyExc_ValueError,"embedded null character");

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp