Commit 9df4e6f6 authored by Thomas Wouters's avatar Thomas Wouters

- Add new Warning class, ImportWarning

 - Warn-raise ImportWarning when importing would have picked up a directory
   as package, if only it'd had an __init__.py. This swaps two tests (for
   case-ness and __init__-ness), but case-test is not really more expensive,
   and it's not in a speed-critical section.

 - Test for the new warning by importing a common non-package directory on
   sys.path: site-packages

 - In regrtest.py, silence warnings generated by the build-environment
   because Modules/ (which is added to sys.path for Setup-created modules)
   has 'zlib' and '_ctypes' directories without __init__.py's.
parent 2c1e63f8
...@@ -108,6 +108,7 @@ PyAPI_DATA(PyObject *) PyExc_SyntaxWarning; ...@@ -108,6 +108,7 @@ PyAPI_DATA(PyObject *) PyExc_SyntaxWarning;
PyAPI_DATA(PyObject *) PyExc_OverflowWarning; PyAPI_DATA(PyObject *) PyExc_OverflowWarning;
PyAPI_DATA(PyObject *) PyExc_RuntimeWarning; PyAPI_DATA(PyObject *) PyExc_RuntimeWarning;
PyAPI_DATA(PyObject *) PyExc_FutureWarning; PyAPI_DATA(PyObject *) PyExc_FutureWarning;
PyAPI_DATA(PyObject *) PyExc_ImportWarning;
/* Convenience functions */ /* Convenience functions */
......
...@@ -44,3 +44,4 @@ BaseException ...@@ -44,3 +44,4 @@ BaseException
+-- UserWarning +-- UserWarning
+-- FutureWarning +-- FutureWarning
+-- OverflowWarning [not generated by the interpreter] +-- OverflowWarning [not generated by the interpreter]
+-- ImportWarning
...@@ -138,6 +138,12 @@ if sys.maxint > 0x7fffffff: ...@@ -138,6 +138,12 @@ if sys.maxint > 0x7fffffff:
warnings.filterwarnings("ignore", "hex/oct constants", FutureWarning, warnings.filterwarnings("ignore", "hex/oct constants", FutureWarning,
"<string>") "<string>")
# Ignore ImportWarnings that only occur in the source tree,
# (because of modules with the same name as source-directories in Modules/)
for mod in ("ctypes", "gzip", "test.test_zipimport", "test.test_zlib"):
warnings.filterwarnings(module=".*%s$" % (mod,),
action="ignore", category=ImportWarning)
# MacOSX (a.k.a. Darwin) has a default stack size that is too small # MacOSX (a.k.a. Darwin) has a default stack size that is too small
# for deeply recursive regular expressions. We see this as crashes in # for deeply recursive regular expressions. We see this as crashes in
# the Python test suite when running test_re.py and test_sre.py. The # the Python test suite when running test_re.py and test_sre.py. The
......
...@@ -205,3 +205,20 @@ def test_import_name_binding(): ...@@ -205,3 +205,20 @@ def test_import_name_binding():
assert y is test.test_support, y.__name__ assert y is test.test_support, y.__name__
test_import_name_binding() test_import_name_binding()
def test_import_initless_directory_warning():
import warnings
oldfilters = warnings.filters[:]
warnings.simplefilter('error', ImportWarning);
try:
# Just a random non-package directory we always expect to be
# somewhere in sys.path...
__import__("site-packages")
except ImportWarning:
pass
else:
raise AssertionError
finally:
warnings.filters = oldfilters
test_import_initless_directory_warning()
...@@ -1647,6 +1647,8 @@ PyDoc_STRVAR(FutureWarning__doc__, ...@@ -1647,6 +1647,8 @@ PyDoc_STRVAR(FutureWarning__doc__,
"Base class for warnings about constructs that will change semantically " "Base class for warnings about constructs that will change semantically "
"in the future."); "in the future.");
PyDoc_STRVAR(ImportWarning__doc__,
"Base class for warnings about probable mistakes in module imports");
/* module global functions */ /* module global functions */
...@@ -1719,6 +1721,7 @@ PyObject *PyExc_SyntaxWarning; ...@@ -1719,6 +1721,7 @@ PyObject *PyExc_SyntaxWarning;
PyObject *PyExc_OverflowWarning; PyObject *PyExc_OverflowWarning;
PyObject *PyExc_RuntimeWarning; PyObject *PyExc_RuntimeWarning;
PyObject *PyExc_FutureWarning; PyObject *PyExc_FutureWarning;
PyObject *PyExc_ImportWarning;
...@@ -1818,6 +1821,8 @@ static struct { ...@@ -1818,6 +1821,8 @@ static struct {
RuntimeWarning__doc__}, RuntimeWarning__doc__},
{"FutureWarning", &PyExc_FutureWarning, &PyExc_Warning, {"FutureWarning", &PyExc_FutureWarning, &PyExc_Warning,
FutureWarning__doc__}, FutureWarning__doc__},
{"ImportWarning", &PyExc_ImportWarning, &PyExc_Warning,
ImportWarning__doc__},
/* Sentinel */ /* Sentinel */
{NULL} {NULL}
}; };
......
...@@ -1271,19 +1271,42 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf, ...@@ -1271,19 +1271,42 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf,
#ifdef HAVE_STAT #ifdef HAVE_STAT
if (stat(buf, &statbuf) == 0 && /* it exists */ if (stat(buf, &statbuf) == 0 && /* it exists */
S_ISDIR(statbuf.st_mode) && /* it's a directory */ S_ISDIR(statbuf.st_mode) && /* it's a directory */
find_init_module(buf) && /* it has __init__.py */ case_ok(buf, len, namelen, name)) { /* case matches */
case_ok(buf, len, namelen, name)) { /* and case matches */ if (find_init_module(buf)) { /* and has __init__.py */
Py_XDECREF(copy); Py_XDECREF(copy);
return &fd_package; return &fd_package;
}
else {
char warnstr[MAXPATHLEN+80];
sprintf(warnstr, "Not importing directory "
"'%.*s': missing __init__.py",
MAXPATHLEN, buf);
if (PyErr_Warn(PyExc_ImportWarning,
warnstr)) {
Py_XDECREF(copy);
return NULL;
}
}
} }
#else #else
/* XXX How are you going to test for directories? */ /* XXX How are you going to test for directories? */
#ifdef RISCOS #ifdef RISCOS
if (isdir(buf) && if (isdir(buf) &&
find_init_module(buf) &&
case_ok(buf, len, namelen, name)) { case_ok(buf, len, namelen, name)) {
Py_XDECREF(copy); if (find_init_module(buf)) {
return &fd_package; Py_XDECREF(copy);
return &fd_package;
}
else {
char warnstr[MAXPATHLEN+80];
sprintf(warnstr, "Not importing directory "
"'%.*s': missing __init__.py",
MAXPATHLEN, buf);
if (PyErr_Warn(PyExc_ImportWarning,
warnstr)) {
Py_XDECREF(copy);
return NULL;
}
} }
#endif #endif
#endif #endif
......
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