]> granicus.if.org Git - python/commitdiff
- Add new Warning class, ImportWarning
authorThomas Wouters <thomas@python.org>
Thu, 27 Apr 2006 23:13:20 +0000 (23:13 +0000)
committerThomas Wouters <thomas@python.org>
Thu, 27 Apr 2006 23:13:20 +0000 (23:13 +0000)
 - 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.

Include/pyerrors.h
Lib/test/exception_hierarchy.txt
Lib/test/regrtest.py
Lib/test/test_import.py
Python/exceptions.c
Python/import.c

index 1fe2e4541e3289925b629568074da7a97ce9d123..edf3efd1b59bfb87325b2e0eabc5cbeae914f976 100644 (file)
@@ -108,6 +108,7 @@ PyAPI_DATA(PyObject *) PyExc_SyntaxWarning;
 PyAPI_DATA(PyObject *) PyExc_OverflowWarning;
 PyAPI_DATA(PyObject *) PyExc_RuntimeWarning;
 PyAPI_DATA(PyObject *) PyExc_FutureWarning;
+PyAPI_DATA(PyObject *) PyExc_ImportWarning;
 
 
 /* Convenience functions */
index 9ed92d0a9f789160307479f8e486845835a779ea..5fff7d92b3045ee8ed7c00280091e9af3d72bf61 100644 (file)
@@ -44,3 +44,4 @@ BaseException
            +-- UserWarning
            +-- FutureWarning
           +-- OverflowWarning [not generated by the interpreter]
+          +-- ImportWarning
index 7db94aaad35452cf1ad19c1a0fd704f9433236c5..be06d9dad0c1aead7094b51eaf55bdbe1e8bdfd8 100755 (executable)
@@ -138,6 +138,12 @@ if sys.maxint > 0x7fffffff:
     warnings.filterwarnings("ignore", "hex/oct constants", FutureWarning,
                             "<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
 # 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
index a72b8bd072d8d7141e8c47c1d4c4db7302d8f843..effba3cc1174c80441b1844d8c40dbe9e49606a3 100644 (file)
@@ -205,3 +205,20 @@ def test_import_name_binding():
     assert y is test.test_support, y.__name__
 
 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()
index 5c824e650cf9c73001ec0b7186dbef4d87f301d1..31fb53e6b3b942b3e4826b53572fed175aea70ac 100644 (file)
@@ -1647,6 +1647,8 @@ PyDoc_STRVAR(FutureWarning__doc__,
 "Base class for warnings about constructs that will change semantically "
 "in the future.");
 
+PyDoc_STRVAR(ImportWarning__doc__,
+"Base class for warnings about probable mistakes in module imports");
 
 \f
 /* module global functions */
@@ -1719,6 +1721,7 @@ PyObject *PyExc_SyntaxWarning;
 PyObject *PyExc_OverflowWarning;
 PyObject *PyExc_RuntimeWarning;
 PyObject *PyExc_FutureWarning;
+PyObject *PyExc_ImportWarning;
 
 
 \f
@@ -1818,6 +1821,8 @@ static struct {
   RuntimeWarning__doc__},
  {"FutureWarning", &PyExc_FutureWarning, &PyExc_Warning,
   FutureWarning__doc__},
+ {"ImportWarning", &PyExc_ImportWarning, &PyExc_Warning,
+  ImportWarning__doc__},
  /* Sentinel */
  {NULL}
 };
index 81027d88879430b45434f55f3e6fa83c9539eea6..6642082eb5953d142054f1e6859250c6018bd315 100644 (file)
@@ -1271,19 +1271,42 @@ find_module(char *fullname, char *subname, PyObject *path, char *buf,
 #ifdef HAVE_STAT
                if (stat(buf, &statbuf) == 0 &&         /* it exists */
                    S_ISDIR(statbuf.st_mode) &&         /* it's a directory */
-                   find_init_module(buf) &&            /* it has __init__.py */
-                   case_ok(buf, len, namelen, name)) { /* and case matches */
-                       Py_XDECREF(copy);
-                       return &fd_package;
+                   case_ok(buf, len, namelen, name)) { /* case matches */
+                       if (find_init_module(buf)) { /* and has __init__.py */
+                               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;
+                               }
+                       }
                }
 #else
                /* XXX How are you going to test for directories? */
 #ifdef RISCOS
                if (isdir(buf) &&
-                   find_init_module(buf) &&
                    case_ok(buf, len, namelen, name)) {
-                       Py_XDECREF(copy);
-                       return &fd_package;
+                       if (find_init_module(buf)) {
+                               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