Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
180 views
unlisted
ubuntu2004
1
# -*- coding: utf-8 -*-
2
r"""
3
Convenience tools for handling deprecations.
4
5
Most of the code is taken from the SageMath source code in misc/superseded.py
6
"""
7
########################################################################
8
# Copyright (C) 2012 William Stein <[email protected]>
9
# 2009 Mike Hansen
10
# 2009 Florent Hivert
11
# 2011 Luca De Feo
12
# 2021 Vincent Delecroix <[email protected]>
13
#
14
# Distributed under the terms of the GNU General Public License (GPL)
15
#
16
# https://www.gnu.org/licenses/
17
########################################################################
18
19
from warnings import warn
20
import inspect
21
22
from sage.misc.lazy_attribute import lazy_attribute
23
24
25
def merge_request_url(num):
26
return "https://gitlab.com/modulispaces/admcycles/-/merge_requests/{}".format(num)
27
28
29
def deprecation(merge_request, message, stacklevel=3):
30
message += '\n'
31
message += 'See {} for details.'.format(merge_request_url(merge_request))
32
33
# Stack level 3 to get the line number of the code which called
34
# the deprecated function which called this function.
35
warn(message, DeprecationWarning, stacklevel)
36
37
38
class DeprecatedFunctionAlias:
39
"""
40
A wrapper around methods or functions which automatically prints a
41
deprecation message.
42
"""
43
44
def __init__(self, merge_request, func, module, instance=None, unbound=None):
45
try:
46
self.__dict__.update(func.__dict__)
47
except AttributeError:
48
pass # Cython classes don't have __dict__
49
self.merge_request = merge_request
50
self.func = func
51
self.instance = instance # for use with methods
52
self.unbound = unbound
53
self.__module__ = module
54
if isinstance(func, type(deprecation)):
55
sphinxrole = "func"
56
else:
57
sphinxrole = "meth"
58
doc = 'Deprecated: '
59
doc += 'Use :' + sphinxrole + ':`' + self.func.__name__ + '` instead.\n'
60
doc += 'See {} for details.\n\n'.format(merge_request_url(merge_request))
61
self.__doc__ = doc
62
63
@lazy_attribute
64
def __name__(self):
65
# first look through variables in stack frames
66
for frame in inspect.stack():
67
for name, obj in frame[0].f_globals.items():
68
if obj is self:
69
return name
70
# then search object that contains self as method
71
import gc
72
import copy
73
gc.collect()
74
75
def is_class(gc_ref):
76
if not isinstance(gc_ref, dict):
77
return False
78
is_python_class = '__module__' in gc_ref or '__package__' in gc_ref
79
is_cython_class = '__new__' in gc_ref
80
return is_python_class or is_cython_class
81
search_for = self if (self.unbound is None) else self.unbound
82
for ref in gc.get_referrers(search_for):
83
if is_class(ref) and ref is not self.__dict__:
84
ref_copy = copy.copy(ref)
85
for key, val in ref_copy.items():
86
if val is search_for:
87
return key
88
raise AttributeError("The name of this deprecated function cannot be determined")
89
90
def __call__(self, *args, **kwds):
91
if self.instance is None and self.__module__ != self.func.__module__:
92
other = self.func.__module__ + "." + self.func.__name__
93
else:
94
other = self.func.__name__
95
96
deprecation(self.merge_request,
97
"{} is deprecated. Please use {} instead.".format(
98
self.__name__, other))
99
if self.instance is None:
100
return self.func(*args, **kwds)
101
else:
102
return self.func(self.instance, *args, **kwds)
103
104
def __get__(self, inst, cls=None):
105
if inst is None:
106
return self # Unbound method lookup on class
107
else:
108
# Return a bound method wrapper
109
return DeprecatedFunctionAlias(self.merge_request, self.func,
110
self.__module__, instance=inst,
111
unbound=self)
112
113
114
def deprecated_function_alias(merge_request, func):
115
"""
116
Create an aliased version of a function or a method which raises a
117
deprecation warning message.
118
119
If f is a function or a method, write
120
``g = deprecated_function_alias(merge_request, f)``
121
to make a deprecated aliased version of f.
122
123
INPUT:
124
125
- ``merge_request`` -- integer. The merge request number where the
126
deprecation is introduced.
127
128
- ``func`` -- the function or method to be aliased
129
130
EXAMPLES::
131
132
sage: from admcycles.superseded import deprecated_function_alias
133
sage: g = deprecated_function_alias(13, number_of_partitions)
134
sage: g(5)
135
doctest:...: DeprecationWarning: g is deprecated. Please use sage.combinat.partition.number_of_partitions instead.
136
See https://gitlab.com/modulispaces/admcycles/-/merge_requests/13 for details.
137
7
138
"""
139
module_name = None
140
frame0 = inspect.currentframe()
141
if frame0:
142
frame1 = frame0.f_back
143
if frame1:
144
module_name = inspect.getmodulename(frame1.f_code.co_filename)
145
if module_name is None:
146
module_name = '__main__'
147
return DeprecatedFunctionAlias(merge_request, func, module_name)
148
149