This issue tracker has been migrated to GitHub, and is currently read-only.
For more information, see the GitHub FAQs in the Python's Developer Guide.

Author njs
Recipients njs
Date 2015-05-27.23:36:49
SpamBayes Score -1.0
Marked as misclassified Yes
Message-id <1432769809.77.0.211799866082.issue24305@psf.upfronthosting.co.za>
In-reply-to
Content
(Noticed while fixing the IPython equivalent of issue 24294)

The obvious way to deprecate a module is to issue a DeprecationWarning inside the main body of the module, i.e.

# thirdpartymodule.py
import warnings
warnings.warn("{} is deprecated".format(__name__), DeprecationWarning)

# mymodule.py
import thirdpartymodule

But this is problematic, because the resulting message will claim that the problem is in thirdpartymodule.py, not in mymodule.py. And this is especially bad if I am doing things correctly (!) and using a warnings filter that enables display of DeprecationWarnings for mymodule, but not for third-party modules. (This need for correct attribution comes up in the interactive use case cited above, but I actually have packages where the CI infrastructure requires the elimination of DeprecationWarnings triggered by my own code -- for this to work it's crucial that warnings be attributed correctly.)

So the obvious fix is to instead write:

# thirdpartymodule.py
import warnings
warnings.warn("{} is deprecated".format(__name__), DeprecationWarning,
              stacklevel=2)

which says "the code that needs fixing is the code that called me".

On Python 2.7, this works, because all the code that executes in between 'import thirdpartymodule' and the call to 'warnings.warn' is C code, so it doesn't create any intermediate stack frames.

On more recent versions of Python, the import system itself is written in Python, so this doesn't work at all.

On Python 3.3, the correct way to deprecate a module is:

warnings.warn("this module is deprecated", DeprecationWarning,
              stacklevel=10)

and on Python 3.4, the correct way to deprecate a module is:

warnings.warn("this module is deprecated", DeprecationWarning,
              stacklevel=8)

(See https://github.com/ipython/ipython/pull/8480#issuecomment-106107638 for test code.)

Obviously this is not desireable.

I'm not sure what best solution is. Maybe there should be some collaboration between the import code and the warnings module, so that when the warnings module walks the stack, it skips over stack frames that come from inside the guts of import system?
History
Date User Action Args
2015-05-27 23:36:49njssetrecipients: + njs
2015-05-27 23:36:49njssetmessageid: <1432769809.77.0.211799866082.issue24305@psf.upfronthosting.co.za>
2015-05-27 23:36:49njslinkissue24305 messages
2015-05-27 23:36:49njscreate