Reputation: 13645
I'm working with a Python 2.x framework, and a recent version of the framework has moved some widely used base classes from module A
to module B
(and the classes have been renamed to a clearer names in the process). Module A
defines a backward compatible identifiers for the new class names.
B.py:
class BaseClass(object):
__metaclass__ = framework_meta # handles registration etc.
A.py:
import B
oldbase = B.BaseClass
Now in order to help people migrate their code, I would like to be able to issue a DeprecationWarning
(using warnings.warn) whenever code using the framework defines a class deriving from A.oldbase
telling the programmer to directly inherit from B.BaseClass
.
I expect this can be achieved with a metaclass. I tried to declare a new metaclass deriving from the framework metaclass
class deprecated_base_class(framework_meta):
def __new__(meta, name, bases, attrs):
warning = '%(class)s is deprecated'
for b in bases:
warning = getattr(b, '__deprecation_warning__', None) or warning
warn(warning % {'class': name}, DeprecationWarning, stacklevel=2)
return super(deprecated_base_class, meta).__new__(meta, name, bases, attrs)
together with:
A.py:
class oldbase(B.BaseClass):
__metaclass__ = deprecated_base_class
__deprecation_warning__ = 'class oldbase is deprecated. Use B.BaseClass instead'
clientcode.py
class FooBar(oldbase):
pass
The problem I have now, is that I get a DeprecationWarning
for the definition of oldbase
. How can I fix this?
Upvotes: 7
Views: 591
Reputation: 157464
You want to display the warning if any of the bases are deprecated:
class deprecated_base_class(framework_meta):
def __new__(meta, name, bases, attrs):
for b in bases:
if isinstance(b, deprecated_base_class):
warning = getattr(b, '__deprecation_warning__', '%(class)s is deprecated')
warn(warning % {'class': b.__name__}, DeprecationWarning, stacklevel=2)
return super(deprecated_base_class, meta).__new__(meta, name, bases, attrs)
Upvotes: 2