/usr/lib/python2.7/dist-packages/debtcollector/removals.py is in python-debtcollector 1.3.0-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 | # Copyright 2014 Hewlett-Packard Development Company, L.P.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import functools
import inspect
import six
import wrapt
from debtcollector import _utils
def _get_qualified_name(obj):
return _utils.get_qualified_name(obj)[1]
def _fetch_first_result(fget, fset, fdel, apply_func, value_not_found=None):
"""Fetch first non-none/empty result of applying ``apply_func``."""
for f in filter(None, (fget, fset, fdel)):
result = apply_func(f)
if result:
return result
return value_not_found
class removed_property(object):
"""Property descriptor that deprecates a property.
This works like the ``@property`` descriptor but can be used instead to
provide the same functionality and also interact with the :mod:`warnings`
module to warn when a property is accessed, set and/or deleted.
:param message: string used as ending contents of the deprecate message
:param version: version string (represents the version this deprecation
was created in)
:param removal_version: version string (represents the version this
deprecation will be removed in); a string
of '?' will denote this will be removed in
some future unknown version
:param stacklevel: stacklevel used in the :func:`warnings.warn` function
to locate where the users code is when reporting the
deprecation call (the default being 3)
:param category: the :mod:`warnings` category to use, defaults to
:py:class:`DeprecationWarning` if not provided
"""
# Message templates that will be turned into real messages as needed.
_PROPERTY_GONE_TPLS = {
'set': "Setting the '%s' property is deprecated",
'get': "Reading the '%s' property is deprecated",
'delete': "Deleting the '%s' property is deprecated",
}
def __init__(self, fget=None, fset=None, fdel=None, doc=None,
stacklevel=3, category=DeprecationWarning,
version=None, removal_version=None, message=None):
self.fset = fset
self.fget = fget
self.fdel = fdel
self.stacklevel = stacklevel
self.category = category
self.version = version
self.removal_version = removal_version
self.message = message
if doc is None and inspect.isfunction(fget):
doc = getattr(fget, '__doc__', None)
self._message_cache = {}
self.__doc__ = doc
def _fetch_message_from_cache(self, kind):
try:
out_message = self._message_cache[kind]
except KeyError:
prefix_tpl = self._PROPERTY_GONE_TPLS[kind]
prefix = prefix_tpl % _fetch_first_result(
self.fget, self.fset, self.fdel, _get_qualified_name,
value_not_found="???")
out_message = _utils.generate_message(
prefix, message=self.message, version=self.version,
removal_version=self.removal_version)
self._message_cache[kind] = out_message
return out_message
def __call__(self, fget, **kwargs):
self.fget = fget
self.message = kwargs.get('message', self.message)
self.version = kwargs.get('version', self.version)
self.removal_version = kwargs.get('removal_version',
self.removal_version)
self.stacklevel = kwargs.get('stacklevel', self.stacklevel)
self.category = kwargs.get('category', self.category)
self.__doc__ = kwargs.get('doc',
getattr(fget, '__doc__', self.__doc__))
# Regenerate all the messages...
self._message_cache.clear()
return self
def __delete__(self, obj):
if self.fdel is None:
raise AttributeError("can't delete attribute")
out_message = self._fetch_message_from_cache('delete')
_utils.deprecation(out_message, stacklevel=self.stacklevel,
category=self.category)
self.fdel(obj)
def __set__(self, obj, value):
if self.fset is None:
raise AttributeError("can't set attribute")
out_message = self._fetch_message_from_cache('set')
_utils.deprecation(out_message, stacklevel=self.stacklevel,
category=self.category)
self.fset(obj, value)
def __get__(self, obj, value):
if obj is None:
return self
if self.fget is None:
raise AttributeError("unreadable attribute")
out_message = self._fetch_message_from_cache('get')
_utils.deprecation(out_message, stacklevel=self.stacklevel,
category=self.category)
return self.fget(obj)
def getter(self, fget):
o = type(self)(fget, self.fset, self.fdel, self.__doc__)
o.message = self.message
o.version = self.version
o.stacklevel = self.stacklevel
o.removal_version = self.removal_version
o.category = self.category
return o
def setter(self, fset):
o = type(self)(self.fget, fset, self.fdel, self.__doc__)
o.message = self.message
o.version = self.version
o.stacklevel = self.stacklevel
o.removal_version = self.removal_version
o.category = self.category
return o
def deleter(self, fdel):
o = type(self)(self.fget, self.fset, fdel, self.__doc__)
o.message = self.message
o.version = self.version
o.stacklevel = self.stacklevel
o.removal_version = self.removal_version
o.category = self.category
return o
def remove(f=None, message=None, version=None, removal_version=None,
stacklevel=3, category=None):
"""Decorates a function, method, or class to emit a deprecation warning
Due to limitations of the wrapt library (and python) itself, if this
is applied to subclasses of metaclasses then it likely will not work
as expected. More information can be found at bug #1520397 to see if
this situation affects your usage of this *universal* decorator, for
this specific scenario please use :py:func:`.removed_class` instead.
:param str message: A message to include in the deprecation warning
:param str version: Specify what version the removed function is present in
:param str removal_version: What version the function will be removed. If
'?' is used this implies an undefined future
version
:param int stacklevel: How many entries deep in the call stack before
ignoring
:param type category: warnings message category (this defaults to
``DeprecationWarning`` when none is provided)
"""
if f is None:
return functools.partial(remove, message=message,
version=version,
removal_version=removal_version,
stacklevel=stacklevel,
category=category)
@wrapt.decorator
def wrapper(f, instance, args, kwargs):
qualified, f_name = _utils.get_qualified_name(f)
if qualified:
if inspect.isclass(f):
prefix_pre = "Using class"
thing_post = ''
else:
prefix_pre = "Using function/method"
thing_post = '()'
if not qualified:
prefix_pre = "Using function/method"
base_name = None
if instance is None:
# Decorator was used on a class
if inspect.isclass(f):
prefix_pre = "Using class"
thing_post = ''
module_name = _get_qualified_name(inspect.getmodule(f))
if module_name == '__main__':
f_name = _utils.get_class_name(
f, fully_qualified=False)
else:
f_name = _utils.get_class_name(
f, fully_qualified=True)
# Decorator was a used on a function
else:
thing_post = '()'
module_name = _get_qualified_name(inspect.getmodule(f))
if module_name != '__main__':
f_name = _utils.get_callable_name(f)
# Decorator was used on a classmethod or instancemethod
else:
thing_post = '()'
base_name = _utils.get_class_name(instance,
fully_qualified=False)
if base_name:
thing_name = ".".join([base_name, f_name])
else:
thing_name = f_name
else:
thing_name = f_name
if thing_post:
thing_name += thing_post
prefix = prefix_pre + " '%s' is deprecated" % (thing_name)
out_message = _utils.generate_message(
prefix,
version=version,
removal_version=removal_version,
message=message)
_utils.deprecation(out_message,
stacklevel=stacklevel, category=category)
return f(*args, **kwargs)
return wrapper(f)
def removed_kwarg(old_name, message=None,
version=None, removal_version=None, stacklevel=3,
category=None):
"""Decorates a kwarg accepting function to deprecate a removed kwarg."""
prefix = "Using the '%s' argument is deprecated" % old_name
out_message = _utils.generate_message(
prefix, postfix=None, message=message, version=version,
removal_version=removal_version)
@wrapt.decorator
def wrapper(f, instance, args, kwargs):
if old_name in kwargs:
_utils.deprecation(out_message,
stacklevel=stacklevel, category=category)
return f(*args, **kwargs)
return wrapper
def removed_class(cls_name, replacement=None, message=None,
version=None, removal_version=None, stacklevel=3,
category=None):
"""Decorates a class to denote that it will be removed at some point."""
def _wrap_it(old_init, out_message):
@six.wraps(old_init, assigned=_utils.get_assigned(old_init))
def new_init(self, *args, **kwargs):
_utils.deprecation(out_message, stacklevel=stacklevel,
category=category)
return old_init(self, *args, **kwargs)
return new_init
def _check_it(cls):
if not inspect.isclass(cls):
_qual, type_name = _utils.get_qualified_name(type(cls))
raise TypeError("Unexpected class type '%s' (expected"
" class type only)" % type_name)
def _cls_decorator(cls):
_check_it(cls)
out_message = _utils.generate_message(
"Using class '%s' (either directly or via inheritance)"
" is deprecated" % cls_name, postfix=None, message=message,
version=version, removal_version=removal_version)
cls.__init__ = _wrap_it(cls.__init__, out_message)
return cls
return _cls_decorator
def removed_module(module, replacement=None, message=None,
version=None, removal_version=None, stacklevel=3,
category=None):
"""Helper to be called inside a module to emit a deprecation warning
:param str replacment: A location (or information about) of any potential
replacement for the removed module (if applicable)
:param str message: A message to include in the deprecation warning
:param str version: Specify what version the removed module is present in
:param str removal_version: What version the module will be removed. If
'?' is used this implies an undefined future
version
:param int stacklevel: How many entries deep in the call stack before
ignoring
:param type category: warnings message category (this defaults to
``DeprecationWarning`` when none is provided)
"""
if inspect.ismodule(module):
module_name = _get_qualified_name(module)
elif isinstance(module, six.string_types):
module_name = module
else:
_qual, type_name = _utils.get_qualified_name(type(module))
raise TypeError("Unexpected module type '%s' (expected string or"
" module type only)" % type_name)
prefix = "The '%s' module usage is deprecated" % module_name
if replacement:
postfix = ", please use %s instead" % replacement
else:
postfix = None
out_message = _utils.generate_message(prefix,
postfix=postfix, message=message,
version=version,
removal_version=removal_version)
_utils.deprecation(out_message,
stacklevel=stacklevel, category=category)
|