register a class to be injectable
    classkey is a key that identifies the injected class
    REMEMBER to call inject_instance in __init__

    Args:
        classkey : the class to be injected into
        modname : the global __name__ of the module youa re injecting from

    Returns:
        closure_decorate_class_method (func): decorator for injectable methods

    Example:
        >>> # ENABLE_DOCTEST
        >>> import utool as ut
        >>> class CheeseShop(object):
        ...     def __init__(self):
        ...         import utool as ut
        ...         ut.inject_all_external_modules(self)
        >>> cheeseshop_method = ut.make_class_method_decorator(CheeseShop)
        >>> shop1 = CheeseShop()
        >>> assert not hasattr(shop1, 'has_cheese'), 'have not injected yet'
        >>> @cheeseshop_method
        >>> def has_cheese(self):
        >>>     return False
        >>> shop2 = CheeseShop()
        >>> assert shop2.has_cheese() is False, 'external method not injected'
        >>> print('Cheese shop does not have cheese. All is well.')

def make_class_method_decorator(classkey, modname=None):
    """
    register a class to be injectable
    classkey is a key that identifies the injected class
    REMEMBER to call inject_instance in __init__

    Args:
        classkey : the class to be injected into
        modname : the global __name__ of the module youa re injecting from

    Returns:
        closure_decorate_class_method (func): decorator for injectable methods

    Example:
        >>> # ENABLE_DOCTEST
        >>> import utool as ut
        >>> class CheeseShop(object):
        ...     def __init__(self):
        ...         import utool as ut
        ...         ut.inject_all_external_modules(self)
        >>> cheeseshop_method = ut.make_class_method_decorator(CheeseShop)
        >>> shop1 = CheeseShop()
        >>> assert not hasattr(shop1, 'has_cheese'), 'have not injected yet'
        >>> @cheeseshop_method
        >>> def has_cheese(self):
        >>>     return False
        >>> shop2 = CheeseShop()
        >>> assert shop2.has_cheese() is False, 'external method not injected'
        >>> print('Cheese shop does not have cheese. All is well.')
    """
    global __APP_MODNAME_REGISTER__
    #if util_arg.VERBOSE or VERBOSE_CLASS:
    if VERBOSE_CLASS:
        print('[util_class] register via make_class_method_decorator classkey=%r, modname=%r'
              % (classkey, modname))
    if modname == '__main__':
        # skips reinjects into main
        print('WARNING: cannot register classkey=%r functions as __main__' % (classkey,))
        return lambda func: func
    # register that this module was injected into
    if isinstance(classkey, tuple):
        classname, _ = classkey
        __CLASSNAME_CLASSKEY_REGISTER__[classname].append(modname)
    elif isinstance(classkey, type):
        classname = classkey.__name__
        if modname is not None:
            assert modname == classkey.__module__, (
                'modname=%r does not agree with __module__=%r' % (
                    modname, classkey.__module__))
        modname = classkey.__module__
        # Convert to new classkey format
        classkey = (classname, modname)
        __CLASSNAME_CLASSKEY_REGISTER__[classname].append(modname)
    else:
        print('Warning not using classkey for %r %r' % (classkey, modname))
        raise AssertionError('classkey no longer supported. Use class_inject_key instead')
    closure_decorate_class_method = functools.partial(decorate_class_method,
                                                      classkey=classkey)
    return closure_decorate_class_method