Commit 1a4d12d7 authored by Victor Stinner's avatar Victor Stinner

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()
parent 3d85a6fa
...@@ -306,11 +306,24 @@ class PEP3147Tests(unittest.TestCase): ...@@ -306,11 +306,24 @@ class PEP3147Tests(unittest.TestCase):
os.sep.join(('.', 'pep3147', '__init__.py'))) os.sep.join(('.', 'pep3147', '__init__.py')))
class NullImporterTests(unittest.TestCase):
@unittest.skipIf(support.TESTFN_UNENCODEABLE is None,
"Need an undecodeable filename")
def test_unencodeable(self):
name = support.TESTFN_UNENCODEABLE
os.mkdir(name)
try:
self.assertRaises(ImportError, imp.NullImporter, name)
finally:
os.rmdir(name)
def test_main(): def test_main():
tests = [ tests = [
ImportTests, ImportTests,
PEP3147Tests, PEP3147Tests,
ReloadTests, ReloadTests,
NullImporterTests,
] ]
try: try:
import _thread import _thread
......
...@@ -3623,56 +3623,70 @@ typedef struct { ...@@ -3623,56 +3623,70 @@ typedef struct {
static int static int
NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds) NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds)
{ {
char *path; #ifndef MS_WINDOWS
Py_ssize_t pathlen; PyObject *path;
struct stat statbuf;
int rv;
if (!_PyArg_NoKeywords("NullImporter()", kwds)) if (!_PyArg_NoKeywords("NullImporter()", kwds))
return -1; return -1;
if (!PyArg_ParseTuple(args, "es:NullImporter", if (!PyArg_ParseTuple(args, "O&:NullImporter",
Py_FileSystemDefaultEncoding, &path)) PyUnicode_FSConverter, &path))
return -1; return -1;
pathlen = strlen(path); if (PyBytes_GET_SIZE(path) == 0) {
if (pathlen == 0) { Py_DECREF(path);
PyMem_Free(path);
PyErr_SetString(PyExc_ImportError, "empty pathname"); PyErr_SetString(PyExc_ImportError, "empty pathname");
return -1; return -1;
} else { }
#ifndef MS_WINDOWS
struct stat statbuf; rv = stat(PyBytes_AS_STRING(path), &statbuf);
int rv; Py_DECREF(path);
if (rv == 0) {
rv = stat(path, &statbuf); /* it exists */
PyMem_Free(path); if (S_ISDIR(statbuf.st_mode)) {
if (rv == 0) { /* it's a directory */
/* it exists */ PyErr_SetString(PyExc_ImportError, "existing directory");
if (S_ISDIR(statbuf.st_mode)) { return -1;
/* it's a directory */
PyErr_SetString(PyExc_ImportError,
"existing directory");
return -1;
}
} }
}
#else /* MS_WINDOWS */ #else /* MS_WINDOWS */
DWORD rv; PyObject *pathobj;
/* see issue1293 and issue3677: DWORD rv;
* stat() on Windows doesn't recognise paths like wchar_t path[MAXPATHLEN+1];
* "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs. Py_ssize_t len;
*/
rv = GetFileAttributesA(path); if (!_PyArg_NoKeywords("NullImporter()", kwds))
PyMem_Free(path); return -1;
if (rv != INVALID_FILE_ATTRIBUTES) {
/* it exists */ if (!PyArg_ParseTuple(args, "U:NullImporter",
if (rv & FILE_ATTRIBUTE_DIRECTORY) { &pathobj))
/* it's a directory */ return -1;
PyErr_SetString(PyExc_ImportError,
"existing directory"); if (PyUnicode_GET_SIZE(pathobj) == 0) {
return -1; PyErr_SetString(PyExc_ImportError, "empty pathname");
} return -1;
}
len = PyUnicode_AsWideChar((PyUnicodeObject*)pathobj,
path, sizeof(path) / sizeof(path[0]));
if (len == -1)
return -1;
/* see issue1293 and issue3677:
* stat() on Windows doesn't recognise paths like
* "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs.
*/
rv = GetFileAttributesW(path);
if (rv != INVALID_FILE_ATTRIBUTES) {
/* it exists */
if (rv & FILE_ATTRIBUTE_DIRECTORY) {
/* it's a directory */
PyErr_SetString(PyExc_ImportError, "existing directory");
return -1;
} }
#endif
} }
#endif
return 0; return 0;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment