1+ import json
12from pathlib import Path
23
4+ import jsonschema .validators
35import yaml
46
57from nf_core .modules .modules_differ import ModulesDiffer
@@ -10,17 +12,15 @@ def meta_yml(module_lint_object, module):
1012 Lint a ``meta.yml`` file
1113
1214 The lint test checks that the module has
13- a ``meta.yml`` file and that it contains
14- the required keys: ``name``, input`` and
15- ``output`` .
15+ a ``meta.yml`` file and that it follows the
16+ JSON schema defined in the ``modules/yaml-schema.json``
17+ file in the nf-core/modules repository .
1618
1719 In addition it checks that the module name
1820 and module input is consistent between the
1921 ``meta.yml`` and the ``main.nf``.
2022
2123 """
22- required_keys = ["name" , "output" ]
23- required_keys_lists = ["input" , "output" ]
2424 # Check if we have a patch file, get original file in that case
2525 meta_yaml = None
2626 if module .is_patched :
@@ -42,21 +42,31 @@ def meta_yml(module_lint_object, module):
4242 module .failed .append (("meta_yml_exists" , "Module `meta.yml` does not exist" , module .meta_yml ))
4343 return
4444
45- # Confirm that all required keys are given
46- contains_required_keys = True
47- all_list_children = True
48- for rk in required_keys :
49- if rk not in meta_yaml .keys ():
50- module .failed .append (("meta_required_keys" , f"`{ rk } ` not specified in YAML" , module .meta_yml ))
51- contains_required_keys = False
52- elif rk in meta_yaml .keys () and not isinstance (meta_yaml [rk ], list ) and rk in required_keys_lists :
53- module .failed .append (("meta_required_keys" , f"`{ rk } ` is not a list" , module .meta_yml ))
54- all_list_children = False
55- if contains_required_keys :
56- module .passed .append (("meta_required_keys" , "`meta.yml` contains all required keys" , module .meta_yml ))
45+ # Confirm that the meta.yml file is valid according to the JSON schema
46+ valid_meta_yml = True
47+ try :
48+ with open (Path (module_lint_object .modules_repo .local_repo_dir , "modules/yaml-schema.json" ), "r" ) as fh :
49+ schema = json .load (fh )
50+ jsonschema .validators .validate (instance = meta_yaml , schema = schema )
51+ module .passed .append (("meta_yml_valid" , "Module `meta.yml` is valid" , module .meta_yml ))
52+ except jsonschema .exceptions .ValidationError as e :
53+ valid_meta_yml = False
54+ hint = ""
55+ if len (e .path ) > 0 :
56+ hint = f"\n Check the entry for `{ e .path [0 ]} `."
57+ if e .message .startswith ("None is not of type 'object'" ) and len (e .path ) > 2 :
58+ hint = f"\n Check that the child entries of { e .path [0 ]+ '.' + e .path [2 ]} are indented correctly."
59+ module .failed .append (
60+ (
61+ "meta_yml_valid" ,
62+ f"The `meta.yml` of the module { module .module_name } is not valid: { e .message } .{ hint } " ,
63+ module .meta_yml ,
64+ )
65+ )
66+ return
5767
5868 # Confirm that all input and output channels are specified
59- if contains_required_keys and all_list_children :
69+ if valid_meta_yml :
6070 if "input" in meta_yaml :
6171 meta_input = [list (x .keys ())[0 ] for x in meta_yaml ["input" ]]
6272 for input in module .inputs :
0 commit comments