[docs]
class SupressPrint(object):
"""
Temporarily replace the print function in a module with a noop
Args:
*mods: the modules to disable print in
**kw: only accepts "enabled"
enabled (bool, default=True): enables or disables this context
"""
def __init__(self, *mods, **kw):
enabled = kw.get('enabled', True)
self.mods = mods
self.enabled = enabled
self.oldprints = {}
def __enter__(self):
if self.enabled:
for mod in self.mods:
oldprint = getattr(self.mods, 'print', print)
self.oldprints[mod] = oldprint
mod.print = lambda *args, **kw: None
def __exit__(self, a, b, c):
if self.enabled:
for mod in self.mods:
mod.print = self.oldprints[mod]
[docs]
class Reloadable(type):
"""
This is a metaclass that overrides the behavior of isinstance and
issubclass when invoked on classes derived from this such that they only
check that the module and class names agree, which are preserved through
module reloads, whereas class instances are not.
This is useful for interactive develoment, but should be removed in
production.
Example:
>>> from kwcoco.util.util_monkey import * # NOQA
>>> # Illustrate what happens with a reload when using this utility
>>> # versus without it.
>>> class Base1:
>>> ...
>>> class Derived1(Base1):
>>> ...
>>> @Reloadable.add_metaclass
>>> class Base2:
>>> ...
>>> class Derived2(Base2):
>>> ...
>>> inst1 = Derived1()
>>> inst2 = Derived2()
>>> assert isinstance(inst1, Derived1)
>>> assert isinstance(inst2, Derived2)
>>> # Simulate reload
>>> class Base1:
>>> ...
>>> class Derived1(Base1):
>>> ...
>>> @Reloadable.add_metaclass
>>> class Base2:
>>> ...
>>> class Derived2(Base2):
>>> ...
>>> assert not isinstance(inst1, Derived1)
>>> assert isinstance(inst2, Derived2)
"""
def __subclasscheck__(cls, sub):
"""
Is ``sub`` a subclass of ``cls``
"""
cls_mod_name = (cls.__module__, cls.__name__)
for b in sub.__mro__:
b_mod_name = (b.__module__, b.__name__)
if cls_mod_name == b_mod_name:
return True
def __instancecheck__(cls, inst):
"""
Is ``inst`` an instance of ``cls``
"""
return cls.__subclasscheck__(inst.__class__)
[docs]
@classmethod
def developing(metaclass, cls):
"""
Like add_metaclass, but warns the user that they are developing.
This helps remind them to remove this in production
"""
import warnings
warnings.warn(f'Adding the Reloadable metaclass to {cls}. Dont forget to remove')
return metaclass.add_metaclass(cls)