unlisted
ubuntu2004# -*- coding: utf-8 -*-1r"""2Convenience tools for handling deprecations.34Most of the code is taken from the SageMath source code in misc/superseded.py5"""6########################################################################7# Copyright (C) 2012 William Stein <[email protected]>8# 2009 Mike Hansen9# 2009 Florent Hivert10# 2011 Luca De Feo11# 2021 Vincent Delecroix <[email protected]>12#13# Distributed under the terms of the GNU General Public License (GPL)14#15# https://www.gnu.org/licenses/16########################################################################1718from warnings import warn19import inspect2021from sage.misc.lazy_attribute import lazy_attribute222324def merge_request_url(num):25return "https://gitlab.com/modulispaces/admcycles/-/merge_requests/{}".format(num)262728def deprecation(merge_request, message, stacklevel=3):29message += '\n'30message += 'See {} for details.'.format(merge_request_url(merge_request))3132# Stack level 3 to get the line number of the code which called33# the deprecated function which called this function.34warn(message, DeprecationWarning, stacklevel)353637class DeprecatedFunctionAlias:38"""39A wrapper around methods or functions which automatically prints a40deprecation message.41"""4243def __init__(self, merge_request, func, module, instance=None, unbound=None):44try:45self.__dict__.update(func.__dict__)46except AttributeError:47pass # Cython classes don't have __dict__48self.merge_request = merge_request49self.func = func50self.instance = instance # for use with methods51self.unbound = unbound52self.__module__ = module53if isinstance(func, type(deprecation)):54sphinxrole = "func"55else:56sphinxrole = "meth"57doc = 'Deprecated: '58doc += 'Use :' + sphinxrole + ':`' + self.func.__name__ + '` instead.\n'59doc += 'See {} for details.\n\n'.format(merge_request_url(merge_request))60self.__doc__ = doc6162@lazy_attribute63def __name__(self):64# first look through variables in stack frames65for frame in inspect.stack():66for name, obj in frame[0].f_globals.items():67if obj is self:68return name69# then search object that contains self as method70import gc71import copy72gc.collect()7374def is_class(gc_ref):75if not isinstance(gc_ref, dict):76return False77is_python_class = '__module__' in gc_ref or '__package__' in gc_ref78is_cython_class = '__new__' in gc_ref79return is_python_class or is_cython_class80search_for = self if (self.unbound is None) else self.unbound81for ref in gc.get_referrers(search_for):82if is_class(ref) and ref is not self.__dict__:83ref_copy = copy.copy(ref)84for key, val in ref_copy.items():85if val is search_for:86return key87raise AttributeError("The name of this deprecated function cannot be determined")8889def __call__(self, *args, **kwds):90if self.instance is None and self.__module__ != self.func.__module__:91other = self.func.__module__ + "." + self.func.__name__92else:93other = self.func.__name__9495deprecation(self.merge_request,96"{} is deprecated. Please use {} instead.".format(97self.__name__, other))98if self.instance is None:99return self.func(*args, **kwds)100else:101return self.func(self.instance, *args, **kwds)102103def __get__(self, inst, cls=None):104if inst is None:105return self # Unbound method lookup on class106else:107# Return a bound method wrapper108return DeprecatedFunctionAlias(self.merge_request, self.func,109self.__module__, instance=inst,110unbound=self)111112113def deprecated_function_alias(merge_request, func):114"""115Create an aliased version of a function or a method which raises a116deprecation warning message.117118If f is a function or a method, write119``g = deprecated_function_alias(merge_request, f)``120to make a deprecated aliased version of f.121122INPUT:123124- ``merge_request`` -- integer. The merge request number where the125deprecation is introduced.126127- ``func`` -- the function or method to be aliased128129EXAMPLES::130131sage: from admcycles.superseded import deprecated_function_alias132sage: g = deprecated_function_alias(13, number_of_partitions)133sage: g(5)134doctest:...: DeprecationWarning: g is deprecated. Please use sage.combinat.partition.number_of_partitions instead.135See https://gitlab.com/modulispaces/admcycles/-/merge_requests/13 for details.1367137"""138module_name = None139frame0 = inspect.currentframe()140if frame0:141frame1 = frame0.f_back142if frame1:143module_name = inspect.getmodulename(frame1.f_code.co_filename)144if module_name is None:145module_name = '__main__'146return DeprecatedFunctionAlias(merge_request, func, module_name)147148149