@@ -342,8 +342,73 @@ def compatible_workflows(self, feature: str) -> Dict[str, Dict]:
342342 }
343343
344344
345- def workflow_path (self , workflow : str ) -> Path :
346- return self .path / workflow
345+ def workflow_registration (self , name : str ) -> Optional [dict ]:
346+ """
347+ Returns the registration dictionary for the workflow *name*.
348+
349+ Returns ``None`` if the workflow is not registered, does not have
350+ registration information, or the registered information is not a
351+ dictionary.
352+ """
353+ if (info := self .registered_workflows ().get (name )) and not isinstance (info , dict ):
354+ debug (f"pathogen registration.workflows[{ name !r} ] is not a dict (got a { type (info ).__name__ } )" )
355+ return None
356+
357+ return info
358+
359+
360+ def workflow_path (self , name : str ) -> Path :
361+ if (info := self .workflow_registration (name )) and (path := info .get ("path" )):
362+ debug (f"pathogen registration specifies { path !r} for workflow { name !r} " )
363+
364+ # Forbid anchored paths in registration info, as it's never correct
365+ # practice. An anchored path is just an absolute path on POSIX
366+ # systems but covers more "absolute-like" cases on Windows systems
367+ # too.
368+ if PurePath (path ).anchor :
369+ raise UserError (f"""
370+ The { self .registration_path .name } file for { str (self )!r}
371+ registers an anchored path for the workflow { name !r} :
372+
373+ { path }
374+
375+ Registered workflow paths must be relative to (and within)
376+ the pathogen source itself. This is a mistake that the
377+ pathogen author(s) must fix.
378+ """ )
379+
380+ # Ensure the relative path resolves _within_ the pathogen repo to
381+ # avoid shenanigans.
382+ resolved_pathogen_path = self .path .resolve ()
383+ resolved_workflow_path = (resolved_pathogen_path / path ).resolve ()
384+
385+ # Path.is_relative_to() was added in Python 3.9, so implement it
386+ # ourselves around .relative_to().
387+ try :
388+ resolved_workflow_path .relative_to (resolved_pathogen_path )
389+ except ValueError :
390+ raise UserError (f"""
391+ The { self .registration_path .name } file for { str (self )!r}
392+ registers an out-of-bounds path for the workflow { name !r} :
393+
394+ { path }
395+
396+ which resolves to:
397+
398+ { str (resolved_workflow_path )}
399+
400+ which is outside of the pathogen's source.
401+
402+ Registered workflow paths must be within the pathogen
403+ source itself. This is a mistake that the pathogen
404+ author(s) must fix.
405+ """ )
406+
407+ debug (f"resolved workflow { name !r} to { str (resolved_workflow_path )!r} " )
408+ return resolved_workflow_path
409+
410+ debug (f"pathogen registration does not specify path for workflow { name !r} ; using name as path" )
411+ return self .path / name
347412
348413
349414 def setup (self , dry_run : bool = False , force : bool = False ) -> SetupStatus :
@@ -747,6 +812,7 @@ def __init__(self, path: str):
747812
748813 registered_workflows = PathogenVersion .registered_workflows
749814 compatible_workflows = PathogenVersion .compatible_workflows
815+ workflow_registration = PathogenVersion .workflow_registration
750816 workflow_path = PathogenVersion .workflow_path
751817
752818 def __str__ (self ) -> str :
0 commit comments