[PATCH 1 of 2 V2] util: add a way to issue deprecation warning without a UI object

Yuya Nishihara yuya at tcha.org
Thu Apr 6 11:44:23 EDT 2017


On Thu, 6 Apr 2017 16:09:07 +0200, Pierre-Yves David wrote:
> 
> 
> On 04/06/2017 03:58 PM, Yuya Nishihara wrote:
> > On Tue, 04 Apr 2017 11:58:49 +0200, Pierre-Yves David wrote:
> >> # HG changeset patch
> >> # User Pierre-Yves David <pierre-yves.david at ens-lyon.org>
> >> # Date 1491296609 -7200
> >> #      Tue Apr 04 11:03:29 2017 +0200
> >> # Node ID 3992b843a7832bf23f2430dc2308907d1f5ba7f9
> >> # Parent  2632df096fc0ac7582382b1f94ea4b9ad0bce8f2
> >> # EXP-Topic vfs.cleanup
> >> # Available At https://www.mercurial-scm.org/repo/users/marmoute/mercurial/
> >> #              hg pull https://www.mercurial-scm.org/repo/users/marmoute/mercurial/ -r 3992b843a783
> >> util: add a way to issue deprecation warning without a UI object
> >>
> >> Our current deprecation warning mechanism rely on ui object. They are case where
> >> we cannot have access to the UI object. On a general basis we avoid using the
> >> python mechanism for deprecation warning because up to Python 2.6 it is exposing
> >> warning to unsuspecting user who cannot do anything to deal with them.
> >>
> >> So we build a "safe" strategy to hide this warnings behind a flag in an
> >> environment variable. The test runner set this flag so that tests show these
> >> warning.  This will help us marker API as deprecated for extensions to update
> >> their code.
> >>
> >> diff --git a/mercurial/util.py b/mercurial/util.py
> >> --- a/mercurial/util.py
> >> +++ b/mercurial/util.py
> >> @@ -38,6 +38,7 @@ import tempfile
> >>  import textwrap
> >>  import time
> >>  import traceback
> >> +import warnings
> >>  import zlib
> >>
> >>  from . import (
> >> @@ -155,6 +156,31 @@ def bitsfrom(container):
> >>          bits |= bit
> >>      return bits
> >>
> >> +# python 2.6 still have deprecation warning enabled by default. We do not want
> >> +# to display anything to standard user so detect if we are running test and
> >> +# only use python deprecation warning in this case.
> >> +_dowarn = bool(encoding.environ.get('HGEMITWARNINGS'))
> >> +if _dowarn:
> >> +    # explicitly unfilter our warning for python 2.7
> >> +    #
> >> +    # The option of setting PYTHONWARNINGS in the test runner was investigated.
> >> +    # However, module name set through PYTHONWARNINGS was exactly matched, so
> >> +    # we cannot set 'mercurial' and have it match eg: 'mercurial.scmutil'. This
> >> +    # makes the whole PYTHONWARNINGS thing useless for our usecase.
> >> +    warnings.filterwarnings('default', '', DeprecationWarning, 'mercurial')
> >> +    warnings.filterwarnings('default', '', DeprecationWarning, 'hgext')
> >> +    warnings.filterwarnings('default', '', DeprecationWarning, 'hgext3rd')
> >> +
> >> +def nouideprecwarn(msg, version, stacklevel=1):
> >> +    """Issue an python native deprecation warning
> >> +
> >> +    This is a noop outside of tests, use 'ui.deprecwarn' when possible.
> >> +    """
> >> +    if _dowarn:
> >> +        msg += ("\n(compatibility will be dropped after Mercurial-%s,"
> >> +                " update your code.)") % version
> >> +        warnings.warn(msg, DeprecationWarning, stacklevel + 1)
> >
> > Sorry for late reply, but can this DeprecationWarning really reach extension
> > authors who need the warning?
> 
> The test runner have been updated to make sure they appears and official 
> recommendation is to use the test runner from the core repository.
> 
> So extensions author following the good practice will get the warning 
> (I've caught a couple already in client extensions). The other one will 
> get bitten and have one extra incentive to follow the good practice :-)

You are the core developer. I believe many extensions wouldn't have tests,
and if they do, the authors wouldn't run tests unless they change their
code. But a develwarn will hopefully be noticed while running. For example,
you've fixed several opener uses in TortoiseHg probably because you'd see
warnings.

> > If dirty hack allowed, I would do something like the following:
> >
> >   # util.py
> >   def _deprecwarn(msg, version):
> >       pass
> >
> >   # somewhere ui is available, maybe in dispatch.py
> >   util._deprecwarn = ui.deprecwarn
> 
> That is a diry hack. I would prefer we did not used it.

Yeah, that is dirty and I don't like it. But I'm okay with it as long as
it is a temporary hack.


More information about the Mercurial-devel mailing list