Repository: ipython/ipython

Issue:
DeprecationWarnings should be visible by default in interactive usage
DeprecationWarning and PendingDeprecationWarning are invisible by default. The rationale for this is that they are only useful to people who are writing code, so they should not be shown to end-users who are merely running code.

If someone is typing stuff into the interactive REPL or a notebook, though, and the code they type uses some deprecated functionality, then we should actually show them this warning. We know that the author is sitting right there. And they're probably going to take whatever they tested interactively and move it into a more permanent form and ugh.

This problem is particularly acute for packages that are primarily used through the interactive prompt, like numpy. I'm really tired of getting bugs like this: numpy/numpy#5919

The solution is simple: when entering interactive mode, IPython should do something like:

```
warnings.filterwarnings("default", category=DeprecationWarning, module="__main__")
warnings.filterwarnings("default", category=PendingDeprecationWarning, module="__main__")
```

This means "for any `DeprecationWarning` or `PendingDeprecation` warning which is caused by code running in the module with name `"__main__"`, use the `"default"` handler (which means: display once per line of code that triggered it). (Confusingly, the default handler for these warning messages is not `"default"`, but `"ignore"`. So overriding the default with `"default"` produces a non-default outcome.)



Discussion:
See also: https://bugs.python.org/issue24294

We already reset the warning filter in IPython so +1.
We could then turn our shims modules into Dreprecation warning and not User warning also maybe.

IIRC, the bug was introduced when Python made no DeprecationWarning the default in order to work around the mistake of backporting PyCapsule to 2.8 and raising DeprecationWarning for PyCObject.


Resolving patch:
diff --git a/IPython/core/interactiveshell.py b/IPython/core/interactiveshell.py
--- a/IPython/core/interactiveshell.py
+++ b/IPython/core/interactiveshell.py
@@ -25,6 +25,7 @@
 import traceback
 import types
 import subprocess
+import warnings
 from io import open as io_open
 
 from pickleshare import PickleShareDB
@@ -547,6 +548,7 @@ def __init__(self, ipython_dir=None, profile_dir=None,
         self.init_pdb()
         self.init_extension_manager()
         self.init_payload()
+        self.init_deprecation_warnings()
         self.hooks.late_startup_hook()
         self.events.trigger('shell_initialized', self)
         atexit.register(self.atexit_operations)
@@ -663,6 +665,15 @@ def init_logstart(self):
         elif self.logstart:
             self.magic('logstart')
 
+    def init_deprecation_warnings(self):
+        """
+        register default filter for deprecation warning.
+
+        This will allow deprecation warning of function used interactively to show
+        warning to users, and still hide deprecation warning from libraries import.
+        """
+        warnings.filterwarnings("default", category=DeprecationWarning, module=self.user_ns.get("__name__"))
+
     def init_builtins(self):
         # A single, static flag that we set to True.  Its presence indicates
         # that an IPython shell has been created, and we make no attempts at


Test patch:
diff --git a/IPython/core/tests/test_interactiveshell.py b/IPython/core/tests/test_interactiveshell.py
--- a/IPython/core/tests/test_interactiveshell.py
+++ b/IPython/core/tests/test_interactiveshell.py
@@ -901,3 +901,44 @@ def test_warning_suppression():
             ip.run_cell("warnings.warn('asdf')")
     finally:
         ip.run_cell("del warnings")
+
+
+def test_deprecation_warning():
+    ip.run_cell("""
+import warnings
+def wrn():
+    warnings.warn(
+        "I AM  A WARNING",
+        DeprecationWarning
+    )
+        """)
+    try:
+        with tt.AssertPrints("I AM  A WARNING", channel="stderr"):
+            ip.run_cell("wrn()")
+    finally:
+        ip.run_cell("del warnings")
+        ip.run_cell("del wrn")
+
+
+class TestImportNoDeprecate(tt.TempFileMixin):
+
+    def setup(self):
+        """Make a valid python temp file."""
+        self.mktmp("""
+import warnings
+def wrn():
+    warnings.warn(
+        "I AM  A WARNING",
+        DeprecationWarning
+    )
+""")
+
+    def test_no_dep(self):
+        """
+        No deprecation warning should be raised from imported functions
+        """
+        ip.run_cell("from {} import wrn".format(self.fname))
+
+        with tt.AssertNotPrints("I AM  A WARNING"):
+            ip.run_cell("wrn()")
+        ip.run_cell("del wrn")