@@ -281,162 +281,6 @@ def install_recipe(recipe_path: Union[str, pathlib.Path],
281281 return False
282282
283283
284- def install_recipe (recipe_path : Union [str , pathlib .Path ],
285- editable : bool = False ,
286- verbose : bool = False ):
287- """
288- Installs a recipe from a local directory into the system.
289-
290- :param recipe_path: Path to the recipe directory (containing setup.py or pyproject.toml)
291- :param editable: If True, install in editable/development mode (-e flag).
292- Default is False for production installs.
293- :param verbose: If True, show detailed pip output
294- """
295- recipeimport
296- sys
297-
298-
299- import subprocess
300- import pathlib
301- import json
302- import traceback
303- from typing import Union , Optional
304- from importlib .metadata import entry_points
305- import pandas as pd
306-
307-
308- def get_recipe (recipe : str ) -> Optional [type ]:
309- """
310- Load a recipe by name from installed entry points.
311-
312- :param recipe: Name of the recipe to load
313- :return: Recipe class or None if not found
314- """
315- # For Python 3.10+, entry_points() returns a more convenient interface
316- # For Python 3.9, you may need to use entry_points().get('workflow_recipes', [])
317- try :
318- eps = entry_points (group = 'workflow_recipes' )
319- except TypeError :
320- # Python 3.9 compatibility
321- eps = entry_points ().get ('workflow_recipes' , [])
322-
323- for entry_point in eps :
324- # In importlib.metadata, entry points have 'name' instead of 'attrs'
325- if entry_point .name == recipe :
326- return entry_point .load ()
327-
328- return None
329-
330-
331- def get_recipes () -> pd .DataFrame :
332- """
333- Get a DataFrame of all available workflow recipes.
334-
335- :return: DataFrame with columns: name, module, import command
336- """
337- rows = []
338-
339- try :
340- eps = entry_points (group = 'workflow_recipes' )
341- except TypeError :
342- # Python 3.9 compatibility
343- eps = entry_points ().get ('workflow_recipes' , [])
344-
345- for entry_point in eps :
346- try :
347- Recipe = entry_point .load ()
348- # Extract module name from the entry point value
349- module_name = entry_point .value .split (':' )[0 ]
350- class_name = Recipe .__name__
351- rows .append ([
352- entry_point .name , # Use entry point name instead of class name
353- module_name ,
354- f"from { module_name } import { class_name } "
355- ])
356- except Exception as e :
357- # Try to get module name even if load fails
358- try :
359- module_name = entry_point .value .split (':' )[0 ]
360- class_name = entry_point .value .split (':' )[1 ] if ':' in entry_point .value else "Unknown"
361- rows .append ([
362- entry_point .name ,
363- module_name ,
364- f"from { module_name } import { class_name } (NOT LOADED: { e } )"
365- ])
366- except :
367- pass
368- print (f"Could not load { entry_point .name } : { e } " )
369- if "--verbose" in sys .argv or os .environ .get ("WFCHEF_DEBUG" ):
370- traceback .print_exc ()
371-
372- return pd .DataFrame (rows , columns = ["name" , "module" , "import command" ])
373-
374-
375- def ls_recipe ():
376- """
377- Inspired by UNIX `ls` command, it lists the recipes already installed
378- into the system and how to import it to use.
379- """
380- print (get_recipes ())
381-
382-
383- def install_recipe (recipe_path : Union [str , pathlib .Path ],
384- editable : bool = False ,
385- verbose : bool = False ):
386- """
387- Installs a recipe from a local directory into the system.
388-
389- :param recipe_path: Path to the recipe directory (containing setup.py or pyproject.toml)
390- :param editable: If True, install in editable/development mode (-e flag)
391- :param verbose: If True, show detailed pip output
392- """
393- recipe_path = pathlib .Path (recipe_path ).resolve ()
394-
395- if not recipe_path .exists ():
396- print (f"Error: Recipe path does not exist: { recipe_path } " )
397- return False
398-
399- # Check for setup.py or pyproject.toml
400- has_setup = recipe_path .joinpath ("setup.py" ).exists ()
401- has_pyproject = recipe_path .joinpath ("pyproject.toml" ).exists ()
402-
403- if not (has_setup or has_pyproject ):
404- print (f"Error: No setup.py or pyproject.toml found in { recipe_path } " )
405- return False
406-
407- try :
408- cmd = [sys .executable , "-m" , "pip" , "install" ]
409-
410- # Add verbose flag before -e if needed
411- if verbose :
412- cmd .append ("-v" )
413-
414- # Add editable flag and path together
415- if editable :
416- cmd .extend (["-e" , str (recipe_path )])
417- else :
418- cmd .append (str (recipe_path ))
419-
420- print (f"Installing recipe from: { recipe_path } " )
421- print (f"Command: { ' ' .join (cmd )} " )
422-
423- result = subprocess .run (cmd , capture_output = True , text = True )
424-
425- if result .returncode != 0 :
426- print (f"Installation failed: { result .stderr } " )
427- return False
428- else :
429- print (f"Successfully installed recipe from { recipe_path } " )
430- if verbose :
431- print (result .stdout )
432- return True
433-
434- except Exception as e :
435- print (f"Could not install recipe from { recipe_path } : { e } " )
436- traceback .print_exc ()
437- return False
438-
439-
440284def uninstall_recipe (recipe_name : str ):
441285 """
442286 Uninstalls a recipe installed in the system.
0 commit comments