Skip to content

Commit

Permalink
requires dependencies
Browse files Browse the repository at this point in the history
  • Loading branch information
Mihir Trivedi committed Feb 19, 2024
1 parent 9005344 commit 5955c20
Show file tree
Hide file tree
Showing 2 changed files with 57 additions and 1 deletion.
5 changes: 5 additions & 0 deletions alto/images/docker_image.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
_check_optional_key_in_conf
)
from alto.output import OutputManager
from alto.utils import requires_dependencies


##########
Expand All @@ -53,6 +54,10 @@ class Docker(BaseImage, ConfigMixin):
CLIENT: Any
image_version: Optional[str] = None

@requires_dependencies(
"docker",
"docker",
)
def __init__(self,
alto_wkdir: Path,
image_name: str,
Expand Down
53 changes: 52 additions & 1 deletion alto/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

# Imports
from dataclasses import dataclass
from typing import Any, Dict, Optional, List, Union
from functools import wraps
import importlib
from pathlib import Path
from typing import Any, Dict, Callable, Optional, List, Union


# Functions / Utils
Expand Down Expand Up @@ -167,3 +169,52 @@ def paths_flattener(list_of_paths: List[Union[str, Path]]) -> List[Path]:
flattened_paths.append(Path("/".join(spath)))

return flattened_paths


def requires_dependencies(
dependencies: Union[str, List[str]],
extras: Optional[str] = None,
):
"""
Wrapper used to prompt the user to `pip install` a package and/or Prism extracts in
order to run a function. Borrowed heavily from the `unstructured` library:
https://github.com/Unstructured-IO/unstructured/blob/main/unstructured/utils.py
args:
dependencies: required dependencies
extracts: list of Prism extras that the user can `pip install`
"""
if isinstance(dependencies, str):
dependencies = [dependencies]

def decorator(func: Callable[..., Any]) -> Callable[..., Any]:
@wraps(func)
def wrapper(*args, **kwargs):
missing_deps: List[str] = []
for dep in dependencies:
if not dependency_exists(dep):
missing_deps.append(dep)
if len(missing_deps) > 0:
raise ImportError(
f"""Following dependencies are missing: {', '.join(["`" + dep + "`" for dep in missing_deps])}. """ # noqa
+ ( # noqa
f"""Please install them using `pip install "alto-dev[{extras}]"`.""" # noqa
if extras
else f"Please install them using `pip install {' '.join(missing_deps)}`." # noqa
),
)
return func(*args, **kwargs)

return wrapper
return decorator


def dependency_exists(dependency: str):
try:
importlib.import_module(dependency)
except ImportError as e:
# Check to make sure this isn't some unrelated import error.
pkg = dependency.split(".")[0]
if pkg in repr(e):
return False
return True

0 comments on commit 5955c20

Please sign in to comment.