Coverage for /home/martinb/.local/share/virtualenvs/camcops/lib/python3.6/site-packages/zope/deprecation/deprecation.py : 46%

Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1##############################################################################
2#
3# Copyright (c) 2005 Zope Foundation and Contributors.
4# All Rights Reserved.
5#
6# This software is subject to the provisions of the Zope Public License,
7# Version 2.1 (ZPL). A copy of the ZPL should accompany this distribution.
8# THIS SOFTWARE IS PROVIDED "AS IS" AND ANY AND ALL EXPRESS OR IMPLIED
9# WARRANTIES ARE DISCLAIMED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
10# WARRANTIES OF TITLE, MERCHANTABILITY, AGAINST INFRINGEMENT, AND FITNESS
11# FOR A PARTICULAR PURPOSE.
12#
13##############################################################################
14"""Deprecation Support
16This module provides utilities to ease the development of backward-compatible
17code.
18"""
19__docformat__ = "reStructuredText"
20import sys
21import types
22import warnings
24str_and_sequence_types = (str if str is not bytes else basestring, list, tuple)
26class ShowSwitch(object):
27 """Simple stack-based switch."""
29 def __init__(self):
30 self.stack = []
32 def on(self):
33 self.stack.pop()
35 def off(self):
36 self.stack.append(False)
38 def reset(self):
39 self.stack = []
41 def __call__(self):
42 return self.stack == []
44 def __repr__(self):
45 return '<ShowSwitch %s>' %(self() and 'on' or 'off')
48# This attribute can be used to temporarly deactivate deprecation
49# warnings, so that backward-compatibility code can import other
50# backward-compatiblity components without warnings being produced.
51__show__ = ShowSwitch()
53class Suppressor(object):
55 def __enter__(self):
56 __show__.off()
58 def __exit__(self, *ignored):
59 __show__.on()
61ogetattr = object.__getattribute__
62class DeprecationProxy(object):
64 def __init__(self, module):
65 self.__original_module = module
66 self.__deprecated = {}
68 def deprecate(self, names, message, cls=DeprecationWarning):
69 """Deprecate the given names."""
70 if not isinstance(names, (tuple, list)):
71 names = (names,)
72 for name in names:
73 self.__deprecated[name] = (message, cls)
75 def __getattribute__(self, name):
76 if name == 'deprecate' or name.startswith('_DeprecationProxy__'):
77 return ogetattr(self, name)
79 if name == '__class__':
80 return types.ModuleType
82 if name in ogetattr(self, '_DeprecationProxy__deprecated'):
83 if __show__():
84 msg, cls = self.__deprecated[name]
85 warnings.warn(name + ': ' + msg, cls, 2)
87 return getattr(ogetattr(self, '_DeprecationProxy__original_module'),
88 name)
90 def __setattr__(self, name, value):
91 if name.startswith('_DeprecationProxy__'):
92 return object.__setattr__(self, name, value)
94 setattr(self.__original_module, name, value)
96 def __delattr__(self, name):
97 if name.startswith('_DeprecationProxy__'):
98 return object.__delattr__(self, name)
100 delattr(self.__original_module, name)
102class DeprecatedModule(object):
104 def __init__(self, module, msg, cls=DeprecationWarning):
105 self.__original_module = module
106 self.__msg = msg
107 self.__cls = cls
109 def __getattribute__(self, name):
110 if name.startswith('_DeprecatedModule__'):
111 return ogetattr(self, name)
113 if name == '__class__':
114 return types.ModuleType
116 if __show__():
117 warnings.warn(self.__msg, self.__cls, 2)
119 return getattr(ogetattr(self, '_DeprecatedModule__original_module'),
120 name)
122 def __setattr__(self, name, value):
123 if name.startswith('_DeprecatedModule__'):
124 return object.__setattr__(self, name, value)
125 setattr(self.__original_module, name, value)
127 def __delattr__(self, name):
128 if name.startswith('_DeprecatedModule__'):
129 return object.__delattr__(self, name)
130 delattr(self.__original_module, name)
132class DeprecatedGetProperty(object):
134 def __init__(self, prop, message, cls=DeprecationWarning):
135 self.message = message
136 self.prop = prop
137 self.cls = cls
139 def __get__(self, inst, klass):
140 if __show__():
141 warnings.warn(self.message, self.cls, 2)
142 return self.prop.__get__(inst, klass)
144class DeprecatedGetSetProperty(DeprecatedGetProperty):
146 def __set__(self, inst, prop):
147 if __show__():
148 warnings.warn(self.message, self.cls, 2)
149 self.prop.__set__(inst, prop)
151class DeprecatedGetSetDeleteProperty(DeprecatedGetSetProperty):
153 def __delete__(self, inst):
154 if __show__():
155 warnings.warn(self.message, self.cls, 2)
156 self.prop.__delete__(inst)
158def DeprecatedMethod(method, message, cls=DeprecationWarning):
160 def deprecated_method(*args, **kw):
161 if __show__():
162 warnings.warn(message, cls, 2)
163 return method(*args, **kw)
165 return deprecated_method
167def deprecated(specifier, message, cls=DeprecationWarning):
168 """Deprecate the given names."""
170 # A string specifier (or list of strings) means we're called
171 # top-level in a module and are to deprecate things inside this
172 # module
173 if isinstance(specifier, str_and_sequence_types):
174 globals = sys._getframe(1).f_globals
175 modname = globals['__name__']
177 if not isinstance(sys.modules[modname], DeprecationProxy):
178 sys.modules[modname] = DeprecationProxy(sys.modules[modname])
179 sys.modules[modname].deprecate(specifier, message, cls)
182 # Anything else can mean the specifier is a function/method,
183 # module, or just an attribute of a class
184 elif isinstance(specifier, types.FunctionType):
185 return DeprecatedMethod(specifier, message, cls)
186 elif isinstance(specifier, types.ModuleType):
187 return DeprecatedModule(specifier, message, cls)
188 else:
189 prop = specifier
190 if hasattr(prop, '__get__') and hasattr(prop, '__set__') and \
191 hasattr(prop, '__delete__'):
192 return DeprecatedGetSetDeleteProperty(prop, message, cls)
193 elif hasattr(prop, '__get__') and hasattr(prop, '__set__'):
194 return DeprecatedGetSetProperty(prop, message, cls)
195 elif hasattr(prop, '__get__'):
196 return DeprecatedGetProperty(prop, message, cls)
198class deprecate(object):
199 """Deprecation decorator"""
201 def __init__(self, msg, cls=DeprecationWarning):
202 self.msg = msg
203 self.cls = cls
205 def __call__(self, func):
206 return DeprecatedMethod(func, self.msg, self.cls)
208def moved(to_location, unsupported_in=None, cls=DeprecationWarning):
209 old = sys._getframe(1).f_globals['__name__']
210 message = '%s has moved to %s.' % (old, to_location)
211 if unsupported_in:
212 message += " Import of %s will become unsupported in %s" % (
213 old, unsupported_in)
215 warnings.warn(message, cls, 3)
216 __import__(to_location)
218 fromdict = sys.modules[to_location].__dict__
219 tomod = sys.modules[old]
220 tomod.__doc__ = message
222 for name, v in fromdict.items():
223 if name not in tomod.__dict__:
224 setattr(tomod, name, v)