1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

205

206

207

208

209

210

211

212

213

214

215

216

217

218

219

220

221

222

223

224

225

226

227

228

229

230

231

232

233

234

235

236

237

238

239

240

241

242

243

244

245

246

247

248

249

250

251

252

253

254

255

256

257

258

259

260

261

262

263

264

import functools 

import textwrap 

import warnings 

 

 

class MatplotlibDeprecationWarning(UserWarning): 

""" 

A class for issuing deprecation warnings for Matplotlib users. 

 

In light of the fact that Python builtin DeprecationWarnings are ignored 

by default as of Python 2.7 (see link below), this class was put in to 

allow for the signaling of deprecation, but via UserWarnings which are not 

ignored by default. 

 

https://docs.python.org/dev/whatsnew/2.7.html#the-future-for-python-2-x 

""" 

 

 

mplDeprecation = MatplotlibDeprecationWarning 

"""mplDeprecation is deprecated. Use MatplotlibDeprecationWarning instead.""" 

 

 

def _generate_deprecation_message( 

since, message='', name='', alternative='', pending=False, 

obj_type='attribute', addendum='', *, removal=''): 

 

if removal == "": 

removal = {"2.2": "in 3.1", "3.0": "in 3.2"}.get( 

since, "two minor releases later") 

elif removal: 

if pending: 

raise ValueError( 

"A pending deprecation cannot have a scheduled removal") 

removal = "in {}".format(removal) 

 

if not message: 

message = ( 

"The %(name)s %(obj_type)s" 

+ (" will be deprecated in a future version" 

if pending else 

(" was deprecated in Matplotlib %(since)s" 

+ (" and will be removed %(removal)s" 

if removal else 

""))) 

+ "." 

+ (" Use %(alternative)s instead." if alternative else "") 

+ (" %(addendum)s" if addendum else "")) 

 

return message % dict( 

func=name, name=name, obj_type=obj_type, since=since, removal=removal, 

alternative=alternative, addendum=addendum) 

 

 

def warn_deprecated( 

since, message='', name='', alternative='', pending=False, 

obj_type='attribute', addendum='', *, removal=''): 

""" 

Used to display deprecation in a standard way. 

 

Parameters 

---------- 

since : str 

The release at which this API became deprecated. 

 

message : str, optional 

Override the default deprecation message. The format 

specifier `%(name)s` may be used for the name of the function, 

and `%(alternative)s` may be used in the deprecation message 

to insert the name of an alternative to the deprecated 

function. `%(obj_type)s` may be used to insert a friendly name 

for the type of object being deprecated. 

 

name : str, optional 

The name of the deprecated object. 

 

alternative : str, optional 

An alternative API that the user may use in place of the deprecated 

API. The deprecation warning will tell the user about this alternative 

if provided. 

 

pending : bool, optional 

If True, uses a PendingDeprecationWarning instead of a 

DeprecationWarning. Cannot be used together with *removal*. 

 

removal : str, optional 

The expected removal version. With the default (an empty string), a 

removal version is automatically computed from *since*. Set to other 

Falsy values to not schedule a removal date. Cannot be used together 

with *pending*. 

 

obj_type : str, optional 

The object type being deprecated. 

 

addendum : str, optional 

Additional text appended directly to the final message. 

 

Examples 

-------- 

 

Basic example:: 

 

# To warn of the deprecation of "matplotlib.name_of_module" 

warn_deprecated('1.4.0', name='matplotlib.name_of_module', 

obj_type='module') 

 

""" 

message = '\n' + _generate_deprecation_message( 

since, message, name, alternative, pending, obj_type, addendum, 

removal=removal) 

category = (PendingDeprecationWarning if pending 

else MatplotlibDeprecationWarning) 

warnings.warn(message, category, stacklevel=2) 

 

 

def deprecated(since, message='', name='', alternative='', pending=False, 

obj_type=None, addendum='', *, removal=''): 

""" 

Decorator to mark a function or a class as deprecated. 

 

Parameters 

---------- 

since : str 

The release at which this API became deprecated. This is 

required. 

 

message : str, optional 

Override the default deprecation message. The format 

specifier `%(name)s` may be used for the name of the object, 

and `%(alternative)s` may be used in the deprecation message 

to insert the name of an alternative to the deprecated 

object. 

 

name : str, optional 

The name of the deprecated object; if not provided the name 

is automatically determined from the passed in object, 

though this is useful in the case of renamed functions, where 

the new function is just assigned to the name of the 

deprecated function. For example:: 

 

def new_function(): 

... 

oldFunction = new_function 

 

alternative : str, optional 

An alternative API that the user may use in place of the deprecated 

API. The deprecation warning will tell the user about this alternative 

if provided. 

 

pending : bool, optional 

If True, uses a PendingDeprecationWarning instead of a 

DeprecationWarning. Cannot be used together with *removal*. 

 

removal : str, optional 

The expected removal version. With the default (an empty string), a 

removal version is automatically computed from *since*. Set to other 

Falsy values to not schedule a removal date. Cannot be used together 

with *pending*. 

 

addendum : str, optional 

Additional text appended directly to the final message. 

 

Examples 

-------- 

 

Basic example:: 

 

@deprecated('1.4.0') 

def the_function_to_deprecate(): 

pass 

""" 

 

if obj_type is not None: 

warn_deprecated( 

"3.0", "Passing 'obj_type' to the 'deprecated' decorator has no " 

"effect, and is deprecated since Matplotlib %(since)s; support " 

"for it will be removed %(removal)s.") 

 

def deprecate(obj, message=message, name=name, alternative=alternative, 

pending=pending, addendum=addendum): 

 

if not name: 

name = obj.__name__ 

 

if isinstance(obj, type): 

obj_type = "class" 

old_doc = obj.__doc__ 

func = obj.__init__ 

 

def finalize(wrapper, new_doc): 

obj.__doc__ = new_doc 

obj.__init__ = wrapper 

return obj 

 

elif isinstance(obj, property): 

obj_type = "attribute" 

func = None 

name = name or obj.fget.__name__ 

old_doc = obj.__doc__ 

 

class _deprecated_property(property): 

def __get__(self, instance, owner): 

if instance is not None: 

from . import _warn_external 

_warn_external(message, category) 

return super().__get__(instance, owner) 

 

def __set__(self, instance, value): 

if instance is not None: 

from . import _warn_external 

_warn_external(message, category) 

return super().__set__(instance, value) 

 

def __delete__(self, instance): 

if instance is not None: 

from . import _warn_external 

_warn_external(message, category) 

return super().__delete__(instance) 

 

def finalize(_, new_doc): 

return _deprecated_property( 

fget=obj.fget, fset=obj.fset, fdel=obj.fdel, doc=new_doc) 

 

else: 

obj_type = "function" 

if isinstance(obj, classmethod): 

func = obj.__func__ 

old_doc = func.__doc__ 

 

def finalize(wrapper, new_doc): 

wrapper = functools.wraps(func)(wrapper) 

wrapper.__doc__ = new_doc 

return classmethod(wrapper) 

else: 

func = obj 

old_doc = func.__doc__ 

 

def finalize(wrapper, new_doc): 

wrapper = functools.wraps(func)(wrapper) 

wrapper.__doc__ = new_doc 

return wrapper 

 

message = _generate_deprecation_message( 

since, message, name, alternative, pending, obj_type, addendum, 

removal=removal) 

category = (PendingDeprecationWarning if pending 

else MatplotlibDeprecationWarning) 

 

def wrapper(*args, **kwargs): 

warnings.warn(message, category, stacklevel=2) 

return func(*args, **kwargs) 

 

old_doc = textwrap.dedent(old_doc or '').strip('\n') 

message = message.strip() 

new_doc = (('\n.. deprecated:: %(since)s' 

'\n %(message)s\n\n' % 

{'since': since, 'message': message}) + old_doc) 

if not old_doc: 

# This is to prevent a spurious 'unexected unindent' warning from 

# docutils when the original docstring was blank. 

new_doc += r'\ ' 

 

return finalize(wrapper, new_doc) 

 

return deprecate