OLD | NEW |
| (Empty) |
1 # -*- test-case-name: twisted.python.test.test_deprecate -*- | |
2 | |
3 # Copyright (c) 2008 Twisted Matrix Laboratories. | |
4 # See LICENSE for details. | |
5 | |
6 | |
7 """ | |
8 Deprecation framework for Twisted. | |
9 | |
10 To mark a method or function as being deprecated do this:: | |
11 | |
12 def badAPI(self, first, second): | |
13 ''' | |
14 Docstring for badAPI. | |
15 ''' | |
16 ... | |
17 badAPI = deprecate(Version("Twisted", 8, 0, 0))(badAPI) | |
18 | |
19 The newly-decorated badAPI will issue a warning when called. It will also have | |
20 a deprecation notice appended to its docstring. | |
21 | |
22 See also L{Version}. | |
23 """ | |
24 | |
25 | |
26 __all__ = [ | |
27 'deprecated', | |
28 'getDeprecationWarningString', | |
29 'getWarningMethod', | |
30 'setWarningMethod', | |
31 ] | |
32 | |
33 | |
34 from warnings import warn | |
35 | |
36 from twisted.python.versions import getVersionString, Version | |
37 from twisted.python.reflect import qual | |
38 from twisted.python.util import mergeFunctionMetadata | |
39 | |
40 | |
41 def getWarningMethod(): | |
42 """ | |
43 Return the warning method currently used to record deprecation warnings. | |
44 """ | |
45 return warn | |
46 | |
47 | |
48 | |
49 def setWarningMethod(newMethod): | |
50 """ | |
51 Set the warning method to use to record deprecation warnings. | |
52 | |
53 The callable should take message, category and stacklevel. The return | |
54 value is ignored. | |
55 """ | |
56 global warn | |
57 warn = newMethod | |
58 | |
59 | |
60 | |
61 def _getDeprecationDocstring(version): | |
62 return "Deprecated in %s." % getVersionString(version) | |
63 | |
64 | |
65 | |
66 def getDeprecationWarningString(callableThing, version): | |
67 """ | |
68 Return a string indicating that the callable was deprecated in the given | |
69 version. | |
70 | |
71 @param callableThing: A callable to be deprecated. | |
72 @param version: The L{twisted.python.versions.Version} that the callable | |
73 was deprecated in. | |
74 @return: A string describing the deprecation. | |
75 """ | |
76 return "%s was deprecated in %s" % ( | |
77 qual(callableThing), getVersionString(version)) | |
78 | |
79 | |
80 | |
81 def deprecated(version): | |
82 """ | |
83 Return a decorator that marks callables as deprecated. | |
84 """ | |
85 | |
86 def deprecationDecorator(function): | |
87 """ | |
88 Decorator that marks C{function} as deprecated. | |
89 """ | |
90 | |
91 warningString = getDeprecationWarningString(function, version) | |
92 | |
93 def deprecatedFunction(*args, **kwargs): | |
94 warn( | |
95 warningString, | |
96 DeprecationWarning, | |
97 stacklevel=2) | |
98 return function(*args, **kwargs) | |
99 | |
100 deprecatedFunction = mergeFunctionMetadata( | |
101 function, deprecatedFunction) | |
102 _appendToDocstring(deprecatedFunction, | |
103 _getDeprecationDocstring(version)) | |
104 deprecatedFunction.deprecatedVersion = version | |
105 return deprecatedFunction | |
106 | |
107 return deprecationDecorator | |
108 | |
109 | |
110 | |
111 def _appendToDocstring(thingWithDoc, textToAppend): | |
112 """ | |
113 Append the given text to the docstring of C{thingWithDoc}. | |
114 | |
115 If C{thingWithDoc} has no docstring, then the text just replaces the | |
116 docstring. If it has a single-line docstring then it appends a blank line | |
117 and the message text. If it has a multi-line docstring, then in appends a | |
118 blank line a the message text, and also does the indentation correctly. | |
119 """ | |
120 if thingWithDoc.__doc__: | |
121 docstringLines = thingWithDoc.__doc__.splitlines() | |
122 else: | |
123 docstringLines = [] | |
124 | |
125 if len(docstringLines) == 0: | |
126 docstringLines.append(textToAppend) | |
127 elif len(docstringLines) == 1: | |
128 docstringLines.extend(['', textToAppend, '']) | |
129 else: | |
130 spaces = docstringLines.pop() | |
131 docstringLines.extend(['', | |
132 spaces + textToAppend, | |
133 spaces]) | |
134 thingWithDoc.__doc__ = '\n'.join(docstringLines) | |
OLD | NEW |