Ticket #13109: trac_13109_deprecation.patch

File trac_13109_deprecation.patch, 28.5 KB (added by vbraun, 8 years ago)

Updated patch

  • sage/misc/decorators.py

    # HG changeset patch
    # User Volker Braun <vbraun@stp.dias.ie>
    # Date 1341049567 -3600
    # Node ID 443bd5cfb028fc75f3f260b2e9dc76d0e85f1b0e
    # Parent  f188921de566feead2376b16e58f5c633d05c224
    Change the deprecation() function to have a mandatory trac_number argument
    
    diff --git a/sage/misc/decorators.py b/sage/misc/decorators.py
    a b  
    1515from functools import partial, update_wrapper, WRAPPER_ASSIGNMENTS, WRAPPER_UPDATES
    1616from copy import copy
    1717from sage.misc.sageinspect import sage_getsource, sage_getsourcelines, sage_getargspec
    18 from sage.misc.misc import verbose, deprecation
     18from sage.misc.misc import verbose
    1919from inspect import ArgSpec
    2020
    2121def sage_wraps(wrapped, assigned = WRAPPER_ASSIGNMENTS, updated = WRAPPER_UPDATES):
     
    608608
    609609
    610610class rename_keyword(object):
    611     def __init__(self, deprecated=None, **renames):
     611    def __init__(self, deprecated=None, deprecation=None, **renames):
    612612        """
    613613        A decorator which renames keyword arguments and optionally
    614614        deprecates the new keyword.
    615615       
    616616        INPUT:
    617617       
    618         - ``deprecated`` - If the option being renamed is deprecated, this
    619           is the Sage version where the deprecation initially occurs.
     618        - ``deprecation`` -- integer. The trac ticket number where the
     619          deprecation was introduced.
    620620
    621621        - the rest of the arguments is a list of keyword arguments in the
    622622          form ``renamed_option='existing_option'``.  This will have the
     
    636636           
    637637        To deprecate an old keyword::
    638638
    639             sage: r = rename_keyword(deprecated='Sage version 4.2', color='rgbcolor')       
     639            sage: r = rename_keyword(deprecation=13109, color='rgbcolor')
    640640        """
     641        assert deprecated is None, 'Use @rename_keyword(deprecation=<trac_number>, ...)'
    641642        self.renames = renames
    642         self.deprecated=deprecated
     643        self.renames = renames
     644        self.deprecation = deprecation
    643645
    644646    def __call__(self, func):
    645647        """
     
    662664
    663665        We can also deprecate the renamed keyword::
    664666           
    665             sage: r = rename_keyword(deprecated='Sage version 4.2', deprecated_option='new_option')           
     667            sage: r = rename_keyword(deprecation=13109, deprecated_option='new_option')
    666668            sage: def f(*args, **kwds): print args, kwds
    667669            sage: f = r(f)
    668670            sage: f()
     
    672674            sage: f(new_option=1)
    673675            () {'new_option': 1}
    674676            sage: f(deprecated_option=1)
    675             doctest:...: DeprecationWarning: (Since Sage version 4.2) use the option 'new_option' instead of 'deprecated_option'
     677            doctest:...: DeprecationWarning: use the option 'new_option' instead of 'deprecated_option'
     678            See http://trac.sagemath.org/13109 for details.
    676679            () {'new_option': 1}
    677680        """
    678681        @sage_wraps(func)
    679682        def wrapper(*args, **kwds):
    680683            for old_name, new_name in self.renames.items():
    681684                if old_name in kwds and new_name not in kwds:
    682                     if self.deprecated is not None:
    683                         deprecation("use the option %r instead of %r"%(new_name,old_name),
    684                             version=self.deprecated)
     685                    if self.deprecation is not None:
     686                        from sage.misc.superseded import deprecation
     687                        deprecation(self.deprecation,
     688                                    "use the option %r instead of %r"%(new_name,old_name))
    685689                    kwds[new_name] = kwds[old_name]
    686690                    del kwds[old_name]
    687691            return func(*args, **kwds)
  • sage/misc/misc.py

    diff --git a/sage/misc/misc.py b/sage/misc/misc.py
    a b  
    3434               "typecheck", "prop", "strunc",
    3535               "assert_attribute", "LOGFILE"]
    3636
     37from warnings import warn
    3738import operator, os, stat, socket, sys, signal, time, weakref, resource, math
    3839import sage.misc.prandom as random
    3940
     
    768769    For backward compatibility (will be deprecated)::
    769770
    770771        sage: repr_lincomb(['a','b','c'], [1,2,3])
    771         doctest:...: DeprecationWarning: (Since Sage Version 5.0) calling `repr_lincomb(monoms, coeffs)` is deprecated; please specify a list of tuples (monom, coeff) instead
     772        doctest:...: DeprecationWarning: calling `repr_lincomb(monoms, coeffs)` is deprecated; please specify a list of tuples (monom, coeff) instead
     773        See http://trac.sagemath.org/12484 for details.
    772774        'a + 2*b + 3*c'
    773 
    774775    """
    775776    # For backward compatibility
    776777    if coeffs is not None:
    777         from sage.misc.misc import deprecation
    778         deprecation("calling `repr_lincomb(monoms, coeffs)` is deprecated; please specify a list of tuples (monom, coeff) instead", "Sage Version 5.0")
     778        from sage.misc.superseded import deprecation
     779        deprecation(12484, "calling `repr_lincomb(monoms, coeffs)` is deprecated; please specify a list of tuples (monom, coeff) instead")
    779780        terms = zip(terms, coeffs)
    780781
    781782    # Setting scalar_mult: symbol used for scalar multiplication
     
    21742175    """
    21752176    return sage.server.support.EMBEDDED_MODE
    21762177
    2177 #################################################################
    2178 # Deprecation
    2179 #################################################################
    2180 from warnings import warn, resetwarnings
    2181 
    2182 def deprecation(message, version=None):
    2183     r"""
    2184     Issue a deprecation warning.
    2185 
    2186     INPUT:
    2187 
    2188      - ``message`` - an explanation why things are deprecated and by what it
    2189                   should be replaced.
    2190 
    2191      - ``version`` - (optional) on which version and when the deprecation
    2192                   occurred. Please put there the version of sage at the time of deprecation.
    2193 
    2194     EXAMPLES::
    2195 
    2196         sage: def foo():
    2197         ...    sage.misc.misc.deprecation("The function foo is replaced by bar.")
    2198         sage: foo()
    2199         doctest:...: DeprecationWarning: The function foo is replaced by bar.
    2200 
    2201         sage: def bar():
    2202         ...    sage.misc.misc.deprecation("The function bar is removed.",
    2203         ...         'Sage Version 4.2')
    2204         sage: bar()
    2205         doctest:...: DeprecationWarning: (Since Sage Version 4.2) The function bar is removed.
    2206     """
    2207     # Stack level 3 to get the line number of the code which called
    2208     # the deprecated function which called this function.
    2209     resetwarnings()
    2210     if version is not None:
    2211         message = "(Since " + version + ") " + message
    2212     warn(message, DeprecationWarning, stacklevel=3)
    2213 
    2214 
    2215 
    2216 from sage.misc.lazy_attribute import lazy_attribute
    2217 import inspect
    2218 
    2219 class DeprecatedFunctionAlias(object):
    2220     """
    2221     A wrapper around methods or functions which automatically print the correct
    2222     deprecation message. See :func:`deprecated_function_alias`.
    2223 
    2224     AUTHORS:
    2225 
    2226      - Florent Hivert (2009-11-23), with the help of Mike Hansen.
    2227      - Luca De Feo (2011-07-11), printing the full module path when different from old path
    2228     """
    2229     def __init__(self, func, version, module):
    2230         """
    2231         TESTS::
    2232 
    2233             sage: from sage.misc.misc import deprecated_function_alias
    2234             sage: g = deprecated_function_alias(number_of_partitions,
    2235             ...     'Sage Version 42.132')
    2236             sage: g.__doc__
    2237             '.. deprecated:: Sage Version 42.132. Use :func:`number_of_partitions` instead.\n\n'
    2238         """
    2239         try:
    2240             self.__dict__.update(func.__dict__)
    2241         except AttributeError:
    2242             pass # Cython classes don't have __dict__
    2243         self.func = func
    2244         self.version  = version
    2245         self.instance = None # for use with methods
    2246         self.__module__ = module
    2247         if type(func) == type(deprecation):
    2248             sphinxrole = "func"
    2249         else:
    2250             sphinxrole = "meth"
    2251         self.__doc__ = (".. deprecated:: %s. Use :%s:`%s` instead.\n\n"%(
    2252                 self.version, sphinxrole, self.func.__name__))
    2253 
    2254     @lazy_attribute
    2255     def __name__(self):
    2256         """
    2257         TESTS::
    2258 
    2259             sage: from sage.misc.misc import deprecated_function_alias
    2260             sage: g = deprecated_function_alias(number_of_partitions,
    2261             ...     'Sage Version 42.132')
    2262             sage: g.__name__
    2263             'g'
    2264 
    2265             sage: from sage.misc.misc import deprecated_function_alias
    2266             sage: class cls(object):
    2267             ...      def new_meth(self): return 42
    2268             ...      old_meth = deprecated_function_alias(new_meth,
    2269             ...            'Sage Version 42.132')
    2270             ...
    2271             sage: cls().old_meth.__name__
    2272             'old_meth'
    2273 
    2274             sage: cython('\n'.join([
    2275             ...       r"from sage.misc.misc import deprecated_function_alias",
    2276             ...       r"cdef class cython_cls(object):",
    2277             ...       r"    def new_cython_meth(self):",
    2278             ...       r"        return 1",
    2279             ...       r"    old_cython_meth = deprecated_function_alias(new_cython_meth, 'Sage 42.132')"
    2280             ...   ]))
    2281             ...
    2282             sage: cython_cls().old_cython_meth.__name__
    2283             'old_cython_meth'
    2284         """
    2285         # first look through variables in stack frames
    2286         for frame in inspect.stack():
    2287             for name, obj in frame[0].f_globals.iteritems():
    2288                 if obj is self:
    2289                     return name
    2290         # then search object that contains self as method
    2291         import gc, copy
    2292         gc.collect()
    2293         def is_class(gc_ref):
    2294             if not isinstance(gc_ref, dict):
    2295                 return False
    2296             is_python_class = '__module__' in gc_ref
    2297             is_cython_class = '__new__' in gc_ref
    2298             return is_python_class or is_cython_class
    2299         for ref in gc.get_referrers(self):
    2300             if is_class(ref):
    2301                 ref_copy = copy.copy(ref)
    2302                 for key, val in ref_copy.iteritems():
    2303                     if val is self:
    2304                         return key
    2305         raise AttributeError, "The name of this deprecated function can not be determined"
    2306 
    2307     def __call__(self, *args, **kwds):
    2308         """
    2309         TESTS::
    2310 
    2311             sage: from sage.misc.misc import deprecated_function_alias
    2312             sage: def bla(): return 42
    2313             sage: blo = deprecated_function_alias(bla,
    2314             ...     'Sage Version 42.132')
    2315             sage: blo()
    2316             doctest:1: DeprecationWarning: (Since Sage Version 42.132) blo is deprecated. Please use bla instead.
    2317             42
    2318         """
    2319         if self.instance is None and self.__module__ != self.func.__module__:
    2320             other = self.func.__module__ + "." + self.func.__name__
    2321         else:
    2322             other = self.func.__name__
    2323            
    2324         deprecation("%s is deprecated. Please use %s instead."%(self.__name__,
    2325                                                                 other),
    2326                     self.version)
    2327         if self.instance is None:
    2328             return self.func(*args, **kwds)
    2329         else:
    2330             return self.func(self.instance, *args, **kwds)
    2331 
    2332     def __get__(self, inst, cls = None):
    2333         """
    2334         TESTS::
    2335 
    2336             sage: from sage.misc.misc import deprecated_function_alias
    2337             sage: class cls(object):
    2338             ...      def new_meth(self): return 42
    2339             ...      old_meth = deprecated_function_alias(new_meth,
    2340             ...            'Sage Version 42.132')
    2341             sage: obj = cls()
    2342             sage: obj.old_meth.instance is obj
    2343             True
    2344         """
    2345         self.instance = inst
    2346         return self
    2347 
    2348 
    2349 def deprecated_function_alias(func, version):
    2350     """
    2351     Create an aliased version of a function or a method which raise a
    2352     deprecation warning message.
    2353 
    2354     If f is a function or a method, write
    2355     ``g = deprecated_function_alias(f, "Sage version")``
    2356     to make a deprecated aliased version of f.
    2357 
    2358     INPUT:
    2359 
    2360      - ``func`` - the function or method to be aliased
    2361 
    2362      - ``version`` - the version of sage when the function is deprecated
    2363 
    2364     EXAMPLES::
    2365 
    2366         sage: from sage.misc.misc import deprecated_function_alias
    2367         sage: g = deprecated_function_alias(number_of_partitions,
    2368         ...     'Sage Version 42.132')
    2369         sage: g(5)
    2370         doctest:...: DeprecationWarning: (Since Sage Version 42.132) g is deprecated. Please use sage.combinat.partition.number_of_partitions instead.
    2371         7
    2372 
    2373     This also works for methods::
    2374 
    2375         sage: class cls(object):
    2376         ...      def new_meth(self): return 42
    2377         ...      old_meth = deprecated_function_alias(new_meth,
    2378         ...            'Sage Version 42.132')
    2379         sage: cls().old_meth()
    2380         doctest:...: DeprecationWarning: (Since Sage Version 42.132) old_meth is deprecated. Please use new_meth instead.
    2381         42
    2382        
    2383     Trac #11585::
    2384    
    2385         sage: def a(): pass
    2386         sage: b = deprecated_function_alias(a, 'Sage Version 42.132')
    2387         sage: b()
    2388         doctest:...: DeprecationWarning: (Since Sage Version 42.132) b is deprecated. Please use a instead.
    2389 
    2390     AUTHORS:
    2391 
    2392      - Florent Hivert (2009-11-23), with the help of Mike Hansen.
    2393      - Luca De Feo (2011-07-11), printing the full module path when different from old path
    2394     """
    2395     module_name = inspect.getmodulename(
    2396         inspect.currentframe(1).f_code.co_filename)
    2397     if module_name is None:
    2398         module_name = '__main__'
    2399     return DeprecatedFunctionAlias(func, version, module_name)
    2400 
    2401 def deprecated_callable_import(module_name, globs, locs, fromlist, message=None):
    2402     """
    2403     Imports a list of callables into the namespace from
    2404     which it is called.  These callables however give a deprecation
    2405     warning whenever they are called.  This is primarily used from
    2406     deprecating things from Sage's all.py files.
    2407    
    2408     :param module_name: The name of the module from which to import the callables or None.
    2409     :type module_name: string or None
    2410     :param globs: ``globals()`` from where this is being called.
    2411     :param locs:  ``locals()`` from where this is being called.
    2412     :param fromlist: a list the names of the callables to deprecate
    2413     :type fromlist: list of strings
    2414     :param message: A message to display when the deprecated functions are called.
    2415     :type message: string
    2416 
    2417     .. note::
    2418 
    2419        If *module_name* is *None*, then no importing will be done, and
    2420        it will be assumed that the functions have already been
    2421        imported and are present in *globs*
    2422    
    2423     .. warning::
    2424 
    2425        This should really only be used for functions.
    2426 
    2427     EXAMPLES::
    2428    
    2429        sage: from sage.misc.misc import deprecated_callable_import
    2430        sage: is_prime(3)
    2431        True
    2432        sage: message = "Using %(name)s from here is deprecated."
    2433        sage: deprecated_callable_import(None, globals(), locals(), ['is_prime'], message)
    2434        sage: is_prime(3)
    2435        doctest:...: DeprecationWarning:
    2436        Using is_prime from here is deprecated.
    2437        True
    2438        sage: del is_prime
    2439        sage: deprecated_callable_import('sage.rings.arith', globals(), locals(), ['is_prime'])
    2440        sage: is_prime(3)
    2441        doctest:...: DeprecationWarning:
    2442        Using is_prime from here is deprecated.  If you need to use it, please import it directly from sage.rings.arith.
    2443        True
    2444     """
    2445     if message is None:
    2446         message = "\nUsing %(name)s from here is deprecated.  If you need to use it, please import it directly from %(module_name)s."
    2447     from functools import partial
    2448     from sage.misc.misc import sage_wraps
    2449     if module_name is None:
    2450         mod_dict = globs
    2451     else:
    2452         mod_dict = __import__(module_name, globs, locs, fromlist).__dict__
    2453     for name in fromlist:
    2454         func = mod_dict[name]
    2455         def wrapper(func, name, *args, **kwds):
    2456             from sage.misc.misc import deprecation
    2457             deprecation(message%{'name': name, 'module_name': module_name})
    2458             return func(*args, **kwds)
    2459         globs[name] = sage_wraps(func)(partial(wrapper, func, name))
    2460     del name
    2461 
    24622178
    24632179#############################################
    24642180# Operators
  • new file sage/misc/superseded.py

    diff --git a/sage/misc/superseded.py b/sage/misc/superseded.py
    new file mode 100644
    - +  
     1"""
     2Handling Superseded Functionality
     3
     4The main mechanism in Sage to deal with superseded functionality is to
     5add a deprecation warning. This will be shown once, the first time
     6that the deprecated function is called.
     7
     8Note that all doctests in the following use the trac ticket number
     9#13109, which is where this mandatory argument to :func:`deprecation`
     10was introduced.
     11"""
     12
     13
     14
     15########################################################################
     16#       Copyright (C) 2012 William Stein <wstein@gmail.com>
     17#
     18#  Distributed under the terms of the GNU General Public License (GPL)
     19#
     20#                  http://www.gnu.org/licenses/
     21########################################################################
     22
     23from warnings import warn, resetwarnings
     24import inspect
     25
     26from sage.misc.lazy_attribute import lazy_attribute
     27
     28
     29def _check_trac_number(trac_number):
     30    """
     31    Check that the argument is likely to be a valid trac issue number.
     32
     33    INPUT:
     34   
     35    - ``trac_number`` -- anything.
     36
     37    OUTPUT:
     38
     39    This function returns nothing. A ``ValueError`` is raised if the
     40    argument can not be a valid trac number.
     41
     42    EXAMPLES::
     43
     44        sage: from sage.misc.superseded import _check_trac_number
     45        sage: _check_trac_number(1)
     46        sage: _check_trac_number(int(10))
     47        sage: _check_trac_number(long(1000))
     48        sage: _check_trac_number('1')
     49        Traceback (most recent call last):
     50        ...
     51        ValueError: The argument "1" is not a valid trac issue number.
     52    """
     53    from sage.rings.integer import is_Integer
     54    err = ValueError('The argument "'+str(trac_number)+'" is not a valid trac issue number.')
     55    if not (is_Integer(trac_number) or isinstance(trac_number, (int,long))):
     56        raise err
     57    if trac_number < 0:
     58        raise err
     59
     60def deprecation(trac_number, message):
     61    r"""
     62    Issue a deprecation warning.
     63
     64    INPUT:
     65
     66    - ``trac_number`` -- integer. The trac ticket number where the
     67      deprecation is introduced.
     68
     69    - ``message`` -- string. an explanation why things are deprecated
     70      and by what it should be replaced.
     71
     72    EXAMPLES::
     73
     74        sage: def foo():
     75        ...    sage.misc.superseded.deprecation(13109, 'the function foo is replaced by bar')
     76        sage: foo()
     77        doctest:1: DeprecationWarning: the function foo is replaced by bar
     78        See http://trac.sagemath.org/13109 for details.
     79    """
     80    _check_trac_number(trac_number)
     81    if trac_number is not None:
     82        message += '\n'
     83        message += 'See http://trac.sagemath.org/'+ str(trac_number) + ' for details.'
     84    resetwarnings()
     85    # Stack level 3 to get the line number of the code which called
     86    # the deprecated function which called this function.
     87    warn(message, DeprecationWarning, stacklevel=3)
     88
     89
     90
     91class DeprecatedFunctionAlias(object):
     92    """
     93    A wrapper around methods or functions which automatically print
     94    the correct deprecation message. See
     95    :func:`deprecated_function_alias`.
     96
     97    AUTHORS:
     98
     99    - Florent Hivert (2009-11-23), with the help of Mike Hansen.
     100    - Luca De Feo (2011-07-11), printing the full module path when different from old path
     101    """
     102    def __init__(self, trac_number, func, module):
     103        r"""
     104        TESTS::
     105
     106            sage: from sage.misc.superseded import deprecated_function_alias
     107            sage: g = deprecated_function_alias(13109, number_of_partitions)
     108            sage: g.__doc__
     109            'Deprecated: Use :func:`number_of_partitions` instead.\nSee :trac:`13109` for details.\n\n'
     110        """
     111        _check_trac_number(trac_number)
     112        try:
     113            self.__dict__.update(func.__dict__)
     114        except AttributeError:
     115            pass # Cython classes don't have __dict__
     116        self.func = func
     117        self.trac_number  = trac_number
     118        self.instance = None # for use with methods
     119        self.__module__ = module
     120        if type(func) == type(deprecation):
     121            sphinxrole = "func"
     122        else:
     123            sphinxrole = "meth"
     124        doc = 'Deprecated: '
     125        doc += 'Use :' + sphinxrole + ':`' + self.func.__name__ + '` instead.\n'
     126        doc += 'See :trac:`' + str(self.trac_number) + '` for details.\n\n'
     127        self.__doc__ = doc
     128
     129    @lazy_attribute
     130    def __name__(self):
     131        """
     132        TESTS::
     133
     134            sage: from sage.misc.superseded import deprecated_function_alias
     135            sage: g = deprecated_function_alias(13109, number_of_partitions)
     136            sage: g.__name__
     137            'g'
     138
     139            sage: from sage.misc.superseded import deprecated_function_alias
     140            sage: class cls(object):
     141            ...      def new_meth(self): return 42
     142            ...      old_meth = deprecated_function_alias(13109, new_meth)
     143            ...
     144            sage: cls().old_meth.__name__
     145            'old_meth'
     146
     147            sage: cython('\n'.join([
     148            ...       r"from sage.misc.superseded import deprecated_function_alias",
     149            ...       r"cdef class cython_cls(object):",
     150            ...       r"    def new_cython_meth(self):",
     151            ...       r"        return 1",
     152            ...       r"    old_cython_meth = deprecated_function_alias(13109, new_cython_meth)"
     153            ...   ]))
     154            ...
     155            sage: cython_cls().old_cython_meth.__name__
     156            'old_cython_meth'
     157        """
     158        # first look through variables in stack frames
     159        for frame in inspect.stack():
     160            for name, obj in frame[0].f_globals.iteritems():
     161                if obj is self:
     162                    return name
     163        # then search object that contains self as method
     164        import gc, copy
     165        gc.collect()
     166        def is_class(gc_ref):
     167            if not isinstance(gc_ref, dict):
     168                return False
     169            is_python_class = '__module__' in gc_ref
     170            is_cython_class = '__new__' in gc_ref
     171            return is_python_class or is_cython_class
     172        for ref in gc.get_referrers(self):
     173            if is_class(ref):
     174                ref_copy = copy.copy(ref)
     175                for key, val in ref_copy.iteritems():
     176                    if val is self:
     177                        return key
     178        raise AttributeError, "The name of this deprecated function can not be determined"
     179
     180    def __call__(self, *args, **kwds):
     181        """
     182        TESTS::
     183
     184            sage: from sage.misc.superseded import deprecated_function_alias
     185            sage: def bla(): return 42
     186            sage: blo = deprecated_function_alias(13109, bla)
     187            sage: blo()
     188            doctest:1: DeprecationWarning: blo is deprecated. Please use bla instead.
     189            See http://trac.sagemath.org/13109 for details.
     190            42
     191        """
     192        if self.instance is None and self.__module__ != self.func.__module__:
     193            other = self.func.__module__ + "." + self.func.__name__
     194        else:
     195            other = self.func.__name__
     196
     197        deprecation(self.trac_number,
     198                    "%s is deprecated. Please use %s instead."%(self.__name__, other))
     199        if self.instance is None:
     200            return self.func(*args, **kwds)
     201        else:
     202            return self.func(self.instance, *args, **kwds)
     203
     204    def __get__(self, inst, cls = None):
     205        """
     206        TESTS::
     207
     208            sage: from sage.misc.superseded import deprecated_function_alias
     209            sage: class cls(object):
     210            ...      def new_meth(self): return 42
     211            ...      old_meth = deprecated_function_alias(13109, new_meth)
     212            sage: obj = cls()
     213            sage: obj.old_meth.instance is obj
     214            True
     215        """
     216        self.instance = inst
     217        return self
     218
     219
     220def deprecated_function_alias(trac_number, func):
     221    """
     222    Create an aliased version of a function or a method which raise a
     223    deprecation warning message.
     224
     225    If f is a function or a method, write
     226    ``g = deprecated_function_alias(trac_number, f)``
     227    to make a deprecated aliased version of f.
     228
     229    INPUT:
     230
     231    - ``trac_number`` -- integer. The trac ticket number where the
     232      deprecation is introduced.
     233
     234    - ``func`` -- the function or method to be aliased
     235
     236    EXAMPLES::
     237
     238        sage: from sage.misc.superseded import deprecated_function_alias
     239        sage: g = deprecated_function_alias(13109, number_of_partitions)
     240        sage: g(5)
     241        doctest:...: DeprecationWarning: g is deprecated. Please use sage.combinat.partition.number_of_partitions instead.
     242        See http://trac.sagemath.org/13109 for details.
     243        7
     244
     245    This also works for methods::
     246
     247        sage: class cls(object):
     248        ...      def new_meth(self): return 42
     249        ...      old_meth = deprecated_function_alias(13109, new_meth)
     250        sage: cls().old_meth()
     251        doctest:...: DeprecationWarning: old_meth is deprecated. Please use new_meth instead.
     252        See http://trac.sagemath.org/13109 for details.
     253        42
     254
     255    Trac #11585::
     256
     257        sage: def a(): pass
     258        sage: b = deprecated_function_alias(13109, a)
     259        sage: b()
     260        doctest:...: DeprecationWarning: b is deprecated. Please use a instead.
     261        See http://trac.sagemath.org/13109 for details.
     262
     263    AUTHORS:
     264
     265     - Florent Hivert (2009-11-23), with the help of Mike Hansen.
     266     - Luca De Feo (2011-07-11), printing the full module path when different from old path
     267    """
     268    _check_trac_number(trac_number)
     269    module_name = inspect.getmodulename(
     270        inspect.currentframe(1).f_code.co_filename)
     271    if module_name is None:
     272        module_name = '__main__'
     273    return DeprecatedFunctionAlias(trac_number, func, module_name)
     274
     275
     276def deprecated_callable_import(trac_number, module_name, globs, locs, fromlist, message=None):
     277    """
     278    Imports a list of callables into the namespace from
     279    which it is called.  These callables however give a deprecation
     280    warning whenever they are called.  This is primarily used from
     281    deprecating things from Sage's ``all.py`` files.
     282
     283    INPUT:
     284
     285    - ``trac_number`` -- integer. The trac ticket number where the
     286      deprecation is introduced.
     287
     288    - ``param module_name`` -- string or ``None``. The name of the
     289      module from which to import the callables or ``None``.
     290
     291    - ``globs`` -- dictionary. The ``globals()`` from where this is being called.
     292
     293    - ``locs`` -- dictionary. The ``locals()`` from where this is being called.
     294
     295    - ``param fromlist: -- list of strings. The list the names of the
     296      callables to deprecate
     297
     298    - ``message`` --` string. Message to display when the deprecated functions are called.
     299
     300    .. note::
     301
     302       If ``module_name`` is ``None``, then no importing will be done, and
     303       it will be assumed that the functions have already been
     304       imported and are present in ``globs``
     305
     306    .. warning::
     307
     308       This should really only be used for functions.
     309
     310    EXAMPLES::
     311
     312       sage: from sage.misc.superseded import deprecated_callable_import
     313       sage: is_prime(3)
     314       True
     315       sage: message = "Using %(name)s from here is deprecated."
     316       sage: deprecated_callable_import(13109, None, globals(), locals(), ['is_prime'], message)
     317       sage: is_prime(3)
     318       doctest:...: DeprecationWarning:
     319       Using is_prime from here is deprecated.
     320       See http://trac.sagemath.org/13109 for details.
     321       True
     322       sage: del is_prime
     323       sage: deprecated_callable_import(13109, 'sage.rings.arith', globals(), locals(), ['is_prime'])
     324       sage: is_prime(3)
     325       doctest:...: DeprecationWarning:
     326       Using is_prime from here is deprecated.  If you need to use it, please import it directly from sage.rings.arith.
     327       See http://trac.sagemath.org/13109 for details.
     328       True
     329    """
     330    _check_trac_number(trac_number)
     331    if message is None:
     332        message = '\nUsing %(name)s from here is deprecated. ' + \
     333            'If you need to use it, please import it directly from %(module_name)s.'
     334    from functools import partial
     335    from sage.misc.misc import sage_wraps
     336    if module_name is None:
     337        mod_dict = globs
     338    else:
     339        mod_dict = __import__(module_name, globs, locs, fromlist).__dict__
     340    for name in fromlist:
     341        func = mod_dict[name]
     342        def wrapper(func, name, *args, **kwds):
     343            from sage.misc.superseded import deprecation
     344            deprecation(trac_number, message%{'name': name, 'module_name': module_name})
     345            return func(*args, **kwds)
     346        globs[name] = sage_wraps(func)(partial(wrapper, func, name))
     347    del name