summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristoph Reiter <creiter@src.gnome.org>2015-10-30 13:07:57 +0100
committerChristoph Reiter <creiter@src.gnome.org>2015-11-12 17:26:34 +0100
commit7d6fd305912c71761240cbdc0b1dbbe213e3bfa8 (patch)
treef0126ceeda5ca8fd9d80056f25c154869e6a4c62
parent5277f953cfc1ce1e42e536dfcc97169294315e00 (diff)
downloadpygobject-3-18.tar.gz
Fix import warnings pointing to the wrong code with CPython 3.3/3.5pygobject-3-18
For making warnings point to the code doing the import, the stack frames of the import system need to be skipped. The frame count number varries between CPython versions and in 3.5 all frames of the import system are skipped for warnings (https://bugs.python.org/issue24305). This hardcodes the frame counts for all supported CPython versions which fixes the import warning output for CPython 3.3 and 3.5. This also fixes/works around a bug in CPython 3 where if a too large stacklevel value was passed to warn(), CPython would try to interpret a file called "sys" in the same directory of the executed script (https://bugs.python.org/issue25493 and https://bugzilla.gnome.org/show_bug.cgi?id=757184). https://bugzilla.gnome.org/show_bug.cgi?id=757184
-rw-r--r--gi/importer.py28
-rw-r--r--tests/test_import_machinery.py4
2 files changed, 27 insertions, 5 deletions
diff --git a/gi/importer.py b/gi/importer.py
index 22c272b5..9c743c4e 100644
--- a/gi/importer.py
+++ b/gi/importer.py
@@ -78,6 +78,28 @@ def _check_require_version(namespace, stacklevel):
PyGIWarning, stacklevel=stacklevel)
+def get_import_stacklevel(import_hook):
+ """Returns the stacklevel value for warnings.warn() for when the warning
+ gets emitted by an imported module, but the warning should point at the
+ code doing the import.
+
+ Pass import_hook=True if the warning gets generated by an import hook
+ (warn() gets called in load_module(), see PEP302)
+ """
+
+ py_version = sys.version_info[:2]
+ if py_version <= (3, 2):
+ # 2.7 included
+ return 4 if import_hook else 2
+ elif py_version == (3, 3):
+ return 8 if import_hook else 10
+ elif py_version == (3, 4):
+ return 10 if import_hook else 8
+ else:
+ # fixed again in 3.5+, see https://bugs.python.org/issue24305
+ return 4 if import_hook else 2
+
+
class DynamicImporter(object):
# Note: see PEP302 for the Importer Protocol implemented below.
@@ -105,11 +127,7 @@ class DynamicImporter(object):
path, namespace = fullname.rsplit('.', 1)
- # we want the warning to point to the line doing the import
- if sys.version_info >= (3, 0):
- stacklevel = 10
- else:
- stacklevel = 4
+ stacklevel = get_import_stacklevel(import_hook=True)
with _check_require_version(namespace, stacklevel=stacklevel):
introspection_module = get_introspection_module(namespace)
dynamic_module = load_overrides(introspection_module)
diff --git a/tests/test_import_machinery.py b/tests/test_import_machinery.py
index de9f1e94..3c2572da 100644
--- a/tests/test_import_machinery.py
+++ b/tests/test_import_machinery.py
@@ -131,3 +131,7 @@ class TestImporter(unittest.TestCase):
with check("InvalidGObjectRepositoryModuleName", 1):
from gi.repository import InvalidGObjectRepositoryModuleName
InvalidGObjectRepositoryModuleName
+
+ def test_get_import_stacklevel(self):
+ gi.importer.get_import_stacklevel(import_hook=True)
+ gi.importer.get_import_stacklevel(import_hook=False)