@@ -130,6 +130,7 @@ class PathogenVersion:
130130
131131 setup_receipt : Optional [dict ] = None
132132 url : Optional [URL ] = None
133+ registration : Optional [dict ] = None
133134
134135
135136 def __init__ (self , name_version_url : str , new_setup : bool = False ):
@@ -243,6 +244,9 @@ def __init__(self, name_version_url: str, new_setup: bool = False):
243244 self .registration_path = self .path / "nextstrain-pathogen.yaml"
244245 self .setup_receipt_path = self .path .with_suffix (self .path .suffix + ".json" )
245246
247+ if self .registration_path .exists ():
248+ self .registration = read_pathogen_registration (self .registration_path )
249+
246250 if not new_setup :
247251 if not self .path .is_dir ():
248252 # XXX TODO: This error case should maybe be handled outside of
@@ -301,6 +305,23 @@ def __init__(self, name_version_url: str, new_setup: bool = False):
301305 self .url = url
302306
303307
308+ def registered_workflows (self ) -> Dict [str , Dict ]:
309+ """
310+ Parses :attr:`.registration` to return a dict of registered
311+ compatible workflows, where the keys are workflow names.
312+ """
313+ if self .registration is None :
314+ debug ("pathogen does not have a registration" )
315+ return {}
316+
317+ workflows = self .registration .get ("compatibility" , {}).get ("nextstrain run" )
318+ if not isinstance (workflows , dict ):
319+ debug (f"pathogen registration.compatibility['nextstrain runs'] is not a dict (got a { type (workflows ).__name__ } )" )
320+ return {}
321+
322+ return workflows
323+
324+
304325 def workflow_path (self , workflow : str ) -> Path :
305326 return self .path / workflow
306327
@@ -448,27 +469,31 @@ def setup(self, dry_run: bool = False, force: bool = False) -> SetupStatus:
448469 json .dump (self .setup_receipt , f , indent = " " )
449470 print (file = f )
450471
472+ self .registration = read_pathogen_registration (self .registration_path )
473+
451474 return True
452475
453476
454477 def test_setup (self ) -> SetupTestResults :
455478 def test_compatibility () -> SetupTestResult :
456479 msg = "nextstrain-pathogen.yaml declares `nextstrain run` compatibility"
457480
458- try :
459- registration = read_pathogen_registration (self .registration_path )
460- except (OSError , yaml .YAMLError , ValueError ):
461- if DEBUGGING :
462- traceback .print_exc ()
481+ if self .registration is None :
463482 return msg + "\n (couldn't read registration)" , False
464483
465484 try :
466- compatibility = registration ["compatibility" ]["nextstrain run" ]
485+ compatibility = self . registration ["compatibility" ]["nextstrain run" ]
467486 except (KeyError , IndexError , TypeError ):
468487 if DEBUGGING :
469488 traceback .print_exc ()
470489 return msg + "\n (couldn't find 'compatibility: nextstrain run: …' field)" , False
471490
491+ if compatibility :
492+ if workflows := self .registered_workflows ():
493+ msg += f"\n Available workflows: { list (workflows .keys ())} "
494+ else :
495+ msg += f"\n No workflows listed, please refer to pathogen docs."
496+
472497 return msg , bool (compatibility )
473498
474499 return [
@@ -841,21 +866,28 @@ def sorted_versions(vs: Iterable[str]) -> List[str]:
841866 return [v .original for v in [* reversed (compliant ), * non_compliant ]]
842867
843868
844- def read_pathogen_registration (path : Path ) -> Dict :
869+ def read_pathogen_registration (path : Path ) -> Optional [ Dict ] :
845870 """
846871 Reads a ``nextstrain-pathogen.yaml`` file at *path* and returns a dict of
847872 its deserialized contents.
848- """
849- with path .open ("r" , encoding = "utf-8" ) as f :
850- registration = yaml .safe_load (f )
851873
852- # XXX TODO SOON: Consider doing actual schema validation here in the
853- # future.
854- # -trs, 12 Dec 2024
855- if not isinstance (registration , dict ):
856- raise ValueError (f"pathogen registration not a dict (got a { type (registration ).__name__ } ): { str (path )!r} " )
857-
858- return registration
874+ Returns ``None`` if there was an issue reading the registration.
875+ """
876+ try :
877+ with path .open ("r" , encoding = "utf-8" ) as f :
878+ registration = yaml .safe_load (f )
879+
880+ # XXX TODO SOON: Consider doing actual schema validation here in the
881+ # future.
882+ # -trs, 12 Dec 2024
883+ if not isinstance (registration , dict ):
884+ raise ValueError (f"pathogen registration not a dict (got a { type (registration ).__name__ } ): { str (path )!r} " )
885+
886+ return registration
887+ except (OSError , yaml .YAMLError , ValueError ):
888+ if DEBUGGING :
889+ traceback .print_exc ()
890+ return None
859891
860892
861893# We query a nextstrain.org API instead of querying GitHub's API directly for a
0 commit comments