120
120
121
121
MetricType = TypeVar ("MetricType" , bound = "Metric" )
122
122
123
+ DEFAULT_HEADER_COMMENT_CHAR = "#"
124
+
123
125
124
126
@attr .s
125
127
class Metric (ABC , Generic [MetricType ]):
@@ -153,6 +155,7 @@ def read(
153
155
cls ,
154
156
path : Path ,
155
157
ignore_extra_fields : bool = True ,
158
+ header_comment_char : str = DEFAULT_HEADER_COMMENT_CHAR ,
156
159
) -> Iterator [Any ]:
157
160
"""Reads in zero or more metrics from the given path.
158
161
@@ -164,10 +167,12 @@ def read(
164
167
Args:
165
168
path: the path to the metrics file.
166
169
ignore_extra_fields: True to ignore any extra columns, False to raise an exception.
170
+ header_comment_char: Any lines beginning with this character will be ignored before
171
+ parsing the header.
167
172
"""
168
173
parsers = cls ._parsers ()
169
174
with io .to_reader (path ) as reader :
170
- header : List [str ] = Metric .read_header (reader )
175
+ header : List [str ] = Metric .read_header (reader , comment_char = header_comment_char )
171
176
172
177
# check the header
173
178
class_fields = set (cls .header ())
@@ -329,8 +334,27 @@ def fast_concat(*inputs: Path, output: Path) -> None:
329
334
)
330
335
331
336
@staticmethod
332
- def read_header (reader : io .Reader ) -> List [str ]:
337
+ def read_header (
338
+ reader : io .Reader ,
339
+ comment_char : str = "#" ,
340
+ ) -> List [str ]:
333
341
"""
334
342
Read the header from an open file.
343
+
344
+ Comment and empty lines will be ignored.
345
+
346
+ Args:
347
+ reader: An open, readable file
348
+ comment_char: The character which indicates the start of a comment line.
349
+
350
+ Returns:
351
+ A list of field names found in the header line.
335
352
"""
336
- return reader .readline ().rstrip ("\r \n " ).split ("\t " )
353
+
354
+ for line in reader :
355
+ if not line .startswith (comment_char ) and not line .strip () == "" :
356
+ break
357
+ else :
358
+ raise ValueError ("No header found" )
359
+
360
+ return line .rstrip ("\r \n " ).split ("\t " )
0 commit comments