Used by functions in package.py that are evaluated lazily.

    The term 'late' refers to the fact these package attributes are evaluated
    late, ie when the attribute is queried for the first time.

    If you want to implement a package.py attribute as a function, you MUST use
    this decorator - otherwise it is understood that you want your attribute to
    be a function, not the return value of that function.

def late():
    """Used by functions in package.py that are evaluated lazily.

    The term 'late' refers to the fact these package attributes are evaluated
    late, ie when the attribute is queried for the first time.

    If you want to implement a package.py attribute as a function, you MUST use
    this decorator - otherwise it is understood that you want your attribute to
    be a function, not the return value of that function.
    """
    from rez.package_resources_ import package_rex_keys

    def decorated(fn):

        # this is done here rather than in standard schema validation because
        # the latter causes a very obfuscated error message
        if fn.__name__ in package_rex_keys:
            raise ValueError("Cannot use @late decorator on function '%s'"
                             % fn.__name__)

        setattr(fn, "_late", True)
        _add_decorator(fn, "late")
        return fn

    return decorated