Deprecate the usage of an engines 'task_notifier' in favor of the more appropriately named 'atom_notifier' and mark the 'task_notifier' property as subject to removal in a future version. This makes the usage of this notifier more clear since it is not only used for task notification but also for retry notification (which is why naming it atom notifier is more suited to its actual usage). Change-Id: I79d58a08fd8e6d7c8990e70bdfaae415202aa929
165 lines
6.1 KiB
Python
165 lines
6.1 KiB
Python
# -*- coding: utf-8 -*-
|
|
|
|
# Copyright (C) 2014 Yahoo! Inc. All Rights Reserved.
|
|
#
|
|
# 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 warnings
|
|
|
|
import six
|
|
|
|
from taskflow.utils import reflection
|
|
|
|
|
|
def deprecation(message, stacklevel=2):
|
|
"""Warns about some type of deprecation that has been made."""
|
|
warnings.warn(message, category=DeprecationWarning, stacklevel=stacklevel)
|
|
|
|
|
|
# Helper accessors for the moved proxy (since it will not have easy access
|
|
# to its own getattr and setattr functions).
|
|
_setattr = object.__setattr__
|
|
_getattr = object.__getattribute__
|
|
|
|
|
|
class MovedClassProxy(object):
|
|
"""Acts as a proxy to a class that was moved to another location.
|
|
|
|
Partially based on:
|
|
|
|
http://code.activestate.com/recipes/496741-object-proxying/ and other
|
|
various examination of how to make a good enough proxy for our usage to
|
|
move the various types we want to move during the deprecation process.
|
|
|
|
And partially based on the wrapt object proxy (which we should just use
|
|
when it becomes available @ http://review.openstack.org/#/c/94754/).
|
|
"""
|
|
|
|
__slots__ = [
|
|
'__wrapped__', '__message__', '__stacklevel__',
|
|
# Ensure weakrefs can be made,
|
|
# https://docs.python.org/2/reference/datamodel.html#slots
|
|
'__weakref__',
|
|
]
|
|
|
|
def __init__(self, wrapped, message, stacklevel):
|
|
# We can't assign to these directly, since we are overriding getattr
|
|
# and setattr and delattr so we have to do this hoop jump to ensure
|
|
# that we don't invoke those methods (and cause infinite recursion).
|
|
_setattr(self, '__wrapped__', wrapped)
|
|
_setattr(self, '__message__', message)
|
|
_setattr(self, '__stacklevel__', stacklevel)
|
|
try:
|
|
_setattr(self, '__qualname__', wrapped.__qualname__)
|
|
except AttributeError:
|
|
pass
|
|
|
|
def __instancecheck__(self, instance):
|
|
deprecation(
|
|
_getattr(self, '__message__'), _getattr(self, '__stacklevel__'))
|
|
return isinstance(instance, _getattr(self, '__wrapped__'))
|
|
|
|
def __subclasscheck__(self, instance):
|
|
deprecation(
|
|
_getattr(self, '__message__'), _getattr(self, '__stacklevel__'))
|
|
return issubclass(instance, _getattr(self, '__wrapped__'))
|
|
|
|
def __call__(self, *args, **kwargs):
|
|
deprecation(
|
|
_getattr(self, '__message__'), _getattr(self, '__stacklevel__'))
|
|
return _getattr(self, '__wrapped__')(*args, **kwargs)
|
|
|
|
def __getattribute__(self, name):
|
|
return getattr(_getattr(self, '__wrapped__'), name)
|
|
|
|
def __setattr__(self, name, value):
|
|
setattr(_getattr(self, '__wrapped__'), name, value)
|
|
|
|
def __delattr__(self, name):
|
|
delattr(_getattr(self, '__wrapped__'), name)
|
|
|
|
def __repr__(self):
|
|
wrapped = _getattr(self, '__wrapped__')
|
|
return "<%s at 0x%x for %r at 0x%x>" % (
|
|
type(self).__name__, id(self), wrapped, id(wrapped))
|
|
|
|
|
|
def _generate_moved_message(kind, old_name, new_name,
|
|
message=None, version=None, removal_version=None):
|
|
message_components = [
|
|
"%s '%s' has moved to '%s'" % (kind, old_name, new_name),
|
|
]
|
|
if version:
|
|
message_components.append(" in version '%s'" % version)
|
|
if removal_version:
|
|
if removal_version == "?":
|
|
message_components.append(" and will be removed in a future"
|
|
" version")
|
|
else:
|
|
message_components.append(" and will be removed in version '%s'"
|
|
% removal_version)
|
|
if message:
|
|
message_components.append(": %s" % message)
|
|
return ''.join(message_components)
|
|
|
|
|
|
def _moved_decorator(kind, new_attribute_name, message=None,
|
|
version=None, removal_version=None):
|
|
"""Decorates a method/property that was moved to another location."""
|
|
|
|
def decorator(f):
|
|
try:
|
|
old_attribute_name = f.__qualname__
|
|
fully_qualified = True
|
|
except AttributeError:
|
|
old_attribute_name = f.__name__
|
|
fully_qualified = False
|
|
|
|
@six.wraps(f)
|
|
def wrapper(self, *args, **kwargs):
|
|
base_name = reflection.get_class_name(self, fully_qualified=False)
|
|
if fully_qualified:
|
|
old_name = old_attribute_name
|
|
else:
|
|
old_name = ".".join((base_name, old_attribute_name))
|
|
new_name = ".".join((base_name, new_attribute_name))
|
|
out_message = _generate_moved_message(
|
|
kind, old_name=old_name, new_name=new_name, message=message,
|
|
version=version, removal_version=removal_version)
|
|
deprecation(out_message, 3)
|
|
return f(self, *args, **kwargs)
|
|
|
|
return wrapper
|
|
|
|
return decorator
|
|
|
|
|
|
"""Decorates a *instance* property that was moved to another location."""
|
|
moved_property = functools.partial(_moved_decorator, 'Property')
|
|
|
|
|
|
def moved_class(new_class, old_class_name, old_module_name, message=None,
|
|
version=None, removal_version=None):
|
|
"""Deprecates a class that was moved to another location.
|
|
|
|
This will emit warnings when the old locations class is initialized,
|
|
telling where the new and improved location for the old class now is.
|
|
"""
|
|
old_name = ".".join((old_module_name, old_class_name))
|
|
new_name = reflection.get_class_name(new_class)
|
|
out_message = _generate_moved_message('Class', old_name, new_name,
|
|
message=message, version=version,
|
|
removal_version=removal_version)
|
|
return MovedClassProxy(new_class, out_message, 3)
|