Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 1a4d12d

Browse files
author
Victor Stinner
committed
Issue #9425: NullImporter constructor is fully unicode compliant
* On non-Windows OSes: the constructor accepts bytes filenames and use surrogateescape for unicode filenames * On Windows: use GetFileAttributesW() instead of GetFileAttributesA()
1 parent 3d85a6f commit 1a4d12d

2 files changed

Lines changed: 65 additions & 38 deletions

File tree

Lib/test/test_imp.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -306,11 +306,24 @@ def cleanup():
306306
os.sep.join(('.', 'pep3147', '__init__.py')))
307307

308308

309+
class NullImporterTests(unittest.TestCase):
310+
@unittest.skipIf(support.TESTFN_UNENCODEABLE is None,
311+
"Need an undecodeable filename")
312+
def test_unencodeable(self):
313+
name = support.TESTFN_UNENCODEABLE
314+
os.mkdir(name)
315+
try:
316+
self.assertRaises(ImportError, imp.NullImporter, name)
317+
finally:
318+
os.rmdir(name)
319+
320+
309321
def test_main():
310322
tests = [
311323
ImportTests,
312324
PEP3147Tests,
313325
ReloadTests,
326+
NullImporterTests,
314327
]
315328
try:
316329
import _thread

Python/import.c

Lines changed: 52 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -3623,56 +3623,70 @@ typedef struct {
36233623
static int
36243624
NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds)
36253625
{
3626-
char *path;
3627-
Py_ssize_t pathlen;
3626+
#ifndef MS_WINDOWS
3627+
PyObject *path;
3628+
struct stat statbuf;
3629+
int rv;
36283630

36293631
if (!_PyArg_NoKeywords("NullImporter()", kwds))
36303632
return -1;
36313633

3632-
if (!PyArg_ParseTuple(args, "es:NullImporter",
3633-
Py_FileSystemDefaultEncoding, &path))
3634+
if (!PyArg_ParseTuple(args, "O&:NullImporter",
3635+
PyUnicode_FSConverter, &path))
36343636
return -1;
36353637

3636-
pathlen = strlen(path);
3637-
if (pathlen == 0) {
3638-
PyMem_Free(path);
3638+
if (PyBytes_GET_SIZE(path) == 0) {
3639+
Py_DECREF(path);
36393640
PyErr_SetString(PyExc_ImportError, "empty pathname");
36403641
return -1;
3641-
} else {
3642-
#ifndef MS_WINDOWS
3643-
struct stat statbuf;
3644-
int rv;
3645-
3646-
rv = stat(path, &statbuf);
3647-
PyMem_Free(path);
3648-
if (rv == 0) {
3649-
/* it exists */
3650-
if (S_ISDIR(statbuf.st_mode)) {
3651-
/* it's a directory */
3652-
PyErr_SetString(PyExc_ImportError,
3653-
"existing directory");
3654-
return -1;
3655-
}
3642+
}
3643+
3644+
rv = stat(PyBytes_AS_STRING(path), &statbuf);
3645+
Py_DECREF(path);
3646+
if (rv == 0) {
3647+
/* it exists */
3648+
if (S_ISDIR(statbuf.st_mode)) {
3649+
/* it's a directory */
3650+
PyErr_SetString(PyExc_ImportError, "existing directory");
3651+
return -1;
36563652
}
3653+
}
36573654
#else /* MS_WINDOWS */
3658-
DWORD rv;
3659-
/* see issue1293 and issue3677:
3660-
* stat() on Windows doesn't recognise paths like
3661-
* "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs.
3662-
*/
3663-
rv = GetFileAttributesA(path);
3664-
PyMem_Free(path);
3665-
if (rv != INVALID_FILE_ATTRIBUTES) {
3666-
/* it exists */
3667-
if (rv & FILE_ATTRIBUTE_DIRECTORY) {
3668-
/* it's a directory */
3669-
PyErr_SetString(PyExc_ImportError,
3670-
"existing directory");
3671-
return -1;
3672-
}
3655+
PyObject *pathobj;
3656+
DWORD rv;
3657+
wchar_t path[MAXPATHLEN+1];
3658+
Py_ssize_t len;
3659+
3660+
if (!_PyArg_NoKeywords("NullImporter()", kwds))
3661+
return -1;
3662+
3663+
if (!PyArg_ParseTuple(args, "U:NullImporter",
3664+
&pathobj))
3665+
return -1;
3666+
3667+
if (PyUnicode_GET_SIZE(pathobj) == 0) {
3668+
PyErr_SetString(PyExc_ImportError, "empty pathname");
3669+
return -1;
3670+
}
3671+
3672+
len = PyUnicode_AsWideChar((PyUnicodeObject*)pathobj,
3673+
path, sizeof(path) / sizeof(path[0]));
3674+
if (len == -1)
3675+
return -1;
3676+
/* see issue1293 and issue3677:
3677+
* stat() on Windows doesn't recognise paths like
3678+
* "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs.
3679+
*/
3680+
rv = GetFileAttributesW(path);
3681+
if (rv != INVALID_FILE_ATTRIBUTES) {
3682+
/* it exists */
3683+
if (rv & FILE_ATTRIBUTE_DIRECTORY) {
3684+
/* it's a directory */
3685+
PyErr_SetString(PyExc_ImportError, "existing directory");
3686+
return -1;
36733687
}
3674-
#endif
36753688
}
3689+
#endif
36763690
return 0;
36773691
}
36783692

0 commit comments

Comments
 (0)