1
+ from __future__ import annotations
2
+
3
+ from collections .abc import Iterable
1
4
import logging
2
5
import os
3
- from typing import List , cast
6
+ import re
7
+ from typing import List , Optional , cast
4
8
import warnings
5
9
6
10
import click
7
11
8
12
from .base import devel_debug_option , devel_option , map_to_click_exceptions
9
13
from ..utils import pluralize
10
- from ..validate_types import Severity
14
+ from ..validate_types import Severity , ValidationResult
11
15
12
16
13
17
@click .command ()
@@ -74,16 +78,18 @@ def validate_bids(
74
78
type = click .Choice (["none" , "path" ], case_sensitive = False ),
75
79
default = "none" ,
76
80
)
81
+ @click .option ("--ignore" , metavar = "REGEX" , help = "Regex matching error IDs to ignore" )
77
82
@click .argument ("paths" , nargs = - 1 , type = click .Path (exists = True , dir_okay = True ))
78
83
@devel_debug_option ()
79
84
@map_to_click_exceptions
80
85
def validate (
81
- paths ,
82
- schema = None ,
83
- devel_debug = False ,
84
- allow_any_path = False ,
85
- grouping = "none" ,
86
- ):
86
+ paths : tuple [str , ...],
87
+ ignore : Optional [str ],
88
+ grouping : str ,
89
+ schema : Optional [str ] = None ,
90
+ devel_debug : bool = False ,
91
+ allow_any_path : bool = False ,
92
+ ) -> None :
87
93
"""Validate files for NWB and DANDI compliance.
88
94
89
95
Exits with non-0 exit code if any file is not compliant.
@@ -98,7 +104,7 @@ def validate(
98
104
h .addFilter (lambda r : not getattr (r , "validating" , False ))
99
105
100
106
if not paths :
101
- paths = [ os .curdir ]
107
+ paths = ( os .curdir ,)
102
108
# below we are using load_namespaces but it causes HDMF to whine if there
103
109
# is no cached name spaces in the file. It is benign but not really useful
104
110
# at this point, so we ignore it although ideally there should be a formal
@@ -111,50 +117,44 @@ def validate(
111
117
devel_debug = devel_debug ,
112
118
allow_any_path = allow_any_path ,
113
119
)
120
+ _process_issues (validator_result , grouping , ignore )
114
121
115
- _process_issues (validator_result , grouping )
116
-
117
-
118
- def _process_issues (validator_result , grouping ):
119
122
120
- issues = [i for i in validator_result if i .severity ]
121
-
122
- purviews = [
123
- list (filter (bool , [i .path , i .path_regex , i .dataset_path ]))[0 ] for i in issues
124
- ]
123
+ def _process_issues (
124
+ validator_result : Iterable [ValidationResult ], grouping : str , ignore : Optional [str ]
125
+ ) -> None :
126
+ issues = [i for i in validator_result if i .severity is not None ]
127
+ if ignore is not None :
128
+ issues = [i for i in issues if not re .search (ignore , i .id )]
129
+ purviews = [i .purview for i in issues ]
125
130
if grouping == "none" :
126
131
display_errors (
127
132
purviews ,
128
133
[i .id for i in issues ],
129
- [ i .severity for i in issues ],
134
+ cast ( List [ Severity ], [ i .severity for i in issues ]) ,
130
135
[i .message for i in issues ],
131
136
)
132
137
elif grouping == "path" :
133
138
for purview in purviews :
134
- applies_to = [
135
- i for i in issues if purview in [i .path , i .path_regex , i .dataset_path ]
136
- ]
139
+ applies_to = [i for i in issues if purview == i .purview ]
137
140
display_errors (
138
141
[purview ],
139
142
[i .id for i in applies_to ],
140
- [ i .severity for i in applies_to ],
143
+ cast ( List [ Severity ], [ i .severity for i in applies_to ]) ,
141
144
[i .message for i in applies_to ],
142
145
)
143
146
else :
144
147
raise NotImplementedError (
145
- "The `grouping` parameter values currently supported are " "path or None."
148
+ "The `grouping` parameter values currently supported are 'path' and"
149
+ " 'none'."
146
150
)
147
-
148
- validation_errors = [i for i in issues if i .severity == Severity .ERROR ]
149
-
150
- if validation_errors :
151
+ if any (i .severity is Severity .ERROR for i in issues ):
151
152
raise SystemExit (1 )
152
153
else :
153
154
click .secho ("No errors found." , fg = "green" )
154
155
155
156
156
- def _get_severity_color (severities ):
157
-
157
+ def _get_severity_color (severities : list [Severity ]) -> str :
158
158
if Severity .ERROR in severities :
159
159
return "red"
160
160
elif Severity .WARNING in severities :
@@ -164,23 +164,22 @@ def _get_severity_color(severities):
164
164
165
165
166
166
def display_errors (
167
- purviews : List [ str ],
168
- errors : List [str ],
169
- severities : List [Severity ],
170
- messages : List [ str ],
167
+ purviews : list [ Optional [ str ] ],
168
+ errors : list [str ],
169
+ severities : list [Severity ],
170
+ messages : list [ Optional [ str ] ],
171
171
) -> None :
172
172
"""
173
- Unified error display for validation CLI, which auto-resolves grouping logic based on
174
- the length of input lists.
175
-
173
+ Unified error display for validation CLI, which auto-resolves grouping
174
+ logic based on the length of input lists.
176
175
177
176
Notes
178
177
-----
179
- * There is a bit of roundabout and currently untestable logic to deal with potential cases
180
- where the same error has multiple error message, could be removed in the future and removed
181
- by assert if this won't ever be the case.
178
+ * There is a bit of roundabout and currently untestable logic to deal with
179
+ potential cases where the same error has multiple error message, could be
180
+ removed in the future and removed by assert if this won't ever be the
181
+ case.
182
182
"""
183
-
184
183
if all (len (cast (list , i )) == 1 for i in [purviews , errors , severities , messages ]):
185
184
fg = _get_severity_color (severities )
186
185
error_message = f"[{ errors [0 ]} ] { purviews [0 ]} — { messages [0 ]} "
0 commit comments