diff --git a/wfcommons/wfchef/chef.py b/wfcommons/wfchef/chef.py index 9da4c81..517a79a 100644 --- a/wfcommons/wfchef/chef.py +++ b/wfcommons/wfchef/chef.py @@ -281,162 +281,6 @@ def install_recipe(recipe_path: Union[str, pathlib.Path], return False -def install_recipe(recipe_path: Union[str, pathlib.Path], - editable: bool = False, - verbose: bool = False): - """ - Installs a recipe from a local directory into the system. - - :param recipe_path: Path to the recipe directory (containing setup.py or pyproject.toml) - :param editable: If True, install in editable/development mode (-e flag). - Default is False for production installs. - :param verbose: If True, show detailed pip output - """ - recipeimport - sys - - -import subprocess -import pathlib -import json -import traceback -from typing import Union, Optional -from importlib.metadata import entry_points -import pandas as pd - - -def get_recipe(recipe: str) -> Optional[type]: - """ - Load a recipe by name from installed entry points. - - :param recipe: Name of the recipe to load - :return: Recipe class or None if not found - """ - # For Python 3.10+, entry_points() returns a more convenient interface - # For Python 3.9, you may need to use entry_points().get('workflow_recipes', []) - try: - eps = entry_points(group='workflow_recipes') - except TypeError: - # Python 3.9 compatibility - eps = entry_points().get('workflow_recipes', []) - - for entry_point in eps: - # In importlib.metadata, entry points have 'name' instead of 'attrs' - if entry_point.name == recipe: - return entry_point.load() - - return None - - -def get_recipes() -> pd.DataFrame: - """ - Get a DataFrame of all available workflow recipes. - - :return: DataFrame with columns: name, module, import command - """ - rows = [] - - try: - eps = entry_points(group='workflow_recipes') - except TypeError: - # Python 3.9 compatibility - eps = entry_points().get('workflow_recipes', []) - - for entry_point in eps: - try: - Recipe = entry_point.load() - # Extract module name from the entry point value - module_name = entry_point.value.split(':')[0] - class_name = Recipe.__name__ - rows.append([ - entry_point.name, # Use entry point name instead of class name - module_name, - f"from {module_name} import {class_name}" - ]) - except Exception as e: - # Try to get module name even if load fails - try: - module_name = entry_point.value.split(':')[0] - class_name = entry_point.value.split(':')[1] if ':' in entry_point.value else "Unknown" - rows.append([ - entry_point.name, - module_name, - f"from {module_name} import {class_name} (NOT LOADED: {e})" - ]) - except: - pass - print(f"Could not load {entry_point.name}: {e}") - if "--verbose" in sys.argv or os.environ.get("WFCHEF_DEBUG"): - traceback.print_exc() - - return pd.DataFrame(rows, columns=["name", "module", "import command"]) - - -def ls_recipe(): - """ - Inspired by UNIX `ls` command, it lists the recipes already installed - into the system and how to import it to use. - """ - print(get_recipes()) - - -def install_recipe(recipe_path: Union[str, pathlib.Path], - editable: bool = False, - verbose: bool = False): - """ - Installs a recipe from a local directory into the system. - - :param recipe_path: Path to the recipe directory (containing setup.py or pyproject.toml) - :param editable: If True, install in editable/development mode (-e flag) - :param verbose: If True, show detailed pip output - """ - recipe_path = pathlib.Path(recipe_path).resolve() - - if not recipe_path.exists(): - print(f"Error: Recipe path does not exist: {recipe_path}") - return False - - # Check for setup.py or pyproject.toml - has_setup = recipe_path.joinpath("setup.py").exists() - has_pyproject = recipe_path.joinpath("pyproject.toml").exists() - - if not (has_setup or has_pyproject): - print(f"Error: No setup.py or pyproject.toml found in {recipe_path}") - return False - - try: - cmd = [sys.executable, "-m", "pip", "install"] - - # Add verbose flag before -e if needed - if verbose: - cmd.append("-v") - - # Add editable flag and path together - if editable: - cmd.extend(["-e", str(recipe_path)]) - else: - cmd.append(str(recipe_path)) - - print(f"Installing recipe from: {recipe_path}") - print(f"Command: {' '.join(cmd)}") - - result = subprocess.run(cmd, capture_output=True, text=True) - - if result.returncode != 0: - print(f"Installation failed: {result.stderr}") - return False - else: - print(f"Successfully installed recipe from {recipe_path}") - if verbose: - print(result.stdout) - return True - - except Exception as e: - print(f"Could not install recipe from {recipe_path}: {e}") - traceback.print_exc() - return False - - def uninstall_recipe(recipe_name: str): """ Uninstalls a recipe installed in the system.