|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
""" |
|
|
Module with guards for optional libraries, that cannot be listed in `requirements.txt`. |
|
|
Provides helper constants and decorators to check if the library is available in the system. |
|
|
""" |
|
|
|
|
|
__all__ = ["KENLM_AVAILABLE", "K2_AVAILABLE", "TRITON_AVAILABLE", "kenlm_required", "k2_required", "triton_required"] |
|
|
|
|
|
import importlib.util |
|
|
from functools import wraps |
|
|
from nemo.core.utils.k2_utils import K2_INSTALLATION_MESSAGE |
|
|
|
|
|
|
|
|
def is_lib_available(name: str) -> bool: |
|
|
""" |
|
|
Checks if the library/package with `name` is available in the system |
|
|
NB: try/catch with importlib.import_module(name) requires importing the library, which can be slow. |
|
|
So, `find_spec` should be preferred |
|
|
""" |
|
|
return importlib.util.find_spec(name) is not None |
|
|
|
|
|
|
|
|
KENLM_AVAILABLE = is_lib_available("kenlm") |
|
|
KENLM_INSTALLATION_MESSAGE = "Try installing kenlm with `pip install kenlm`" |
|
|
|
|
|
TRITON_AVAILABLE = is_lib_available("triton") |
|
|
TRITON_INSTALLATION_MESSAGE = "Try installing triton with `pip install triton`" |
|
|
|
|
|
|
|
|
try: |
|
|
from nemo.core.utils.k2_guard import k2 as _ |
|
|
|
|
|
K2_AVAILABLE = True |
|
|
except (ImportError, ModuleNotFoundError): |
|
|
K2_AVAILABLE = False |
|
|
|
|
|
|
|
|
def identity_decorator(f): |
|
|
"""Identity decorator for further using in conditional decorators""" |
|
|
return f |
|
|
|
|
|
|
|
|
def _lib_required(is_available: bool, name: str, message: str | None = None): |
|
|
""" |
|
|
Decorator factory. Returns identity decorator if lib `is_available`, |
|
|
otherwise returns a decorator which returns a function that raises an error when called. |
|
|
Such decorator can be used for conditional checks for optional libraries in functions and methods |
|
|
with zero computational overhead. |
|
|
""" |
|
|
if is_available: |
|
|
return identity_decorator |
|
|
|
|
|
|
|
|
def function_stub_with_error_decorator(f): |
|
|
"""Decorator that replaces the function and raises an error when called""" |
|
|
|
|
|
@wraps(f) |
|
|
def wrapper(*args, **kwargs): |
|
|
error_msg = f"Module {name} required for the function {f.__name__} is not found." |
|
|
if message: |
|
|
error_msg += f" {message}" |
|
|
raise ModuleNotFoundError(error_msg) |
|
|
|
|
|
return wrapper |
|
|
|
|
|
return function_stub_with_error_decorator |
|
|
|
|
|
|
|
|
kenlm_required = _lib_required(is_available=KENLM_AVAILABLE, name="kenlm", message=KENLM_INSTALLATION_MESSAGE) |
|
|
triton_required = _lib_required(is_available=TRITON_AVAILABLE, name="triton", message=TRITON_INSTALLATION_MESSAGE) |
|
|
k2_required = _lib_required(is_available=K2_AVAILABLE, name="k2", message=K2_INSTALLATION_MESSAGE) |
|
|
|