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()
This commit is contained in:
Victor Stinner 2010-08-13 13:07:29 +00:00
parent 3d85a6fa04
commit 1a4d12d746
2 changed files with 68 additions and 41 deletions

View File

@ -306,11 +306,24 @@ class PEP3147Tests(unittest.TestCase):
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():
tests = [
ImportTests,
PEP3147Tests,
ReloadTests,
NullImporterTests,
]
try:
import _thread

View File

@ -3623,56 +3623,70 @@ typedef struct {
static int
NullImporter_init(NullImporter *self, PyObject *args, PyObject *kwds)
{
char *path;
Py_ssize_t pathlen;
#ifndef MS_WINDOWS
PyObject *path;
struct stat statbuf;
int rv;
if (!_PyArg_NoKeywords("NullImporter()", kwds))
return -1;
if (!PyArg_ParseTuple(args, "es:NullImporter",
Py_FileSystemDefaultEncoding, &path))
if (!PyArg_ParseTuple(args, "O&:NullImporter",
PyUnicode_FSConverter, &path))
return -1;
pathlen = strlen(path);
if (pathlen == 0) {
PyMem_Free(path);
if (PyBytes_GET_SIZE(path) == 0) {
Py_DECREF(path);
PyErr_SetString(PyExc_ImportError, "empty pathname");
return -1;
} else {
#ifndef MS_WINDOWS
struct stat statbuf;
int rv;
rv = stat(path, &statbuf);
PyMem_Free(path);
if (rv == 0) {
/* it exists */
if (S_ISDIR(statbuf.st_mode)) {
/* it's a directory */
PyErr_SetString(PyExc_ImportError,
"existing directory");
return -1;
}
}
#else /* MS_WINDOWS */
DWORD rv;
/* see issue1293 and issue3677:
* stat() on Windows doesn't recognise paths like
* "e:\\shared\\" and "\\\\whiterab-c2znlh\\shared" as dirs.
*/
rv = GetFileAttributesA(path);
PyMem_Free(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
}
rv = stat(PyBytes_AS_STRING(path), &statbuf);
Py_DECREF(path);
if (rv == 0) {
/* it exists */
if (S_ISDIR(statbuf.st_mode)) {
/* it's a directory */
PyErr_SetString(PyExc_ImportError, "existing directory");
return -1;
}
}
#else /* MS_WINDOWS */
PyObject *pathobj;
DWORD rv;
wchar_t path[MAXPATHLEN+1];
Py_ssize_t len;
if (!_PyArg_NoKeywords("NullImporter()", kwds))
return -1;
if (!PyArg_ParseTuple(args, "U:NullImporter",
&pathobj))
return -1;
if (PyUnicode_GET_SIZE(pathobj) == 0) {
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
return 0;
}