Skip to content

Commit 851467f

Browse files
[Refactor] Helper for reading yaml header (#7552)
* helper for reading yaml header * nocov
1 parent e09d912 commit 851467f

File tree

1 file changed

+39
-32
lines changed

1 file changed

+39
-32
lines changed

R/fread.R

Lines changed: 39 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -182,39 +182,8 @@ yaml=FALSE, tmpdir=tempdir(), tz="UTC")
182182
call_args = names(match.call())
183183
if (is.character(skip))
184184
warningf("Combining a search string as 'skip' and reading a YAML header may not work as expected -- currently, reading will proceed to search for 'skip' from the beginning of the file, NOT from the end of the metadata; please file an issue on GitHub if you'd like to see more intuitive behavior supported.")
185-
# create connection to stream header lines from file:
186-
# https://stackoverflow.com/questions/9871307
187-
f = base::file(input, 'r')
188-
first_line = readLines(f, n=1L)
189-
n_read = 1L
190-
yaml_border_re = '^#?---'
191-
if (!grepl(yaml_border_re, first_line)) {
192-
close(f)
193-
stopf(
194-
'Encountered <%s%s> at the first unskipped line (%d), which does not constitute the start to a valid YAML header (expecting something matching regex "%s"); please check your input and try again.',
195-
substr(first_line, 1L, 50L), if (nchar(first_line) > 50L) '...' else '', 1L+skip, yaml_border_re
196-
)
197-
}
198-
199-
yaml_comment_re = '^#'
200-
yaml_string = character(0L)
201-
repeat {
202-
this_line = readLines(f, n=1L)
203-
n_read = n_read + 1L
204-
if (!length(this_line)){
205-
close(f)
206-
stopf('Reached the end of the file before finding a completion to the YAML header. A valid YAML header is bookended by lines matching the regex "%s". Please double check the input file is a valid csvy.', yaml_border_re)
207-
}
208-
if (grepl(yaml_border_re, this_line)) break
209-
if (grepl(yaml_comment_re, this_line))
210-
this_line = sub(yaml_comment_re, '', this_line)
211-
yaml_string = paste(yaml_string, this_line, sep='\n')
212-
}
213-
close(f) # when #561 is implemented, no need to close f.
214-
215-
yaml_header = yaml::yaml.load(yaml_string)
185+
yaml_header = .read_yaml_header(input, skip, verbose)
216186
yaml_names = names(yaml_header)
217-
if (verbose) catf('Processed %d lines of YAML metadata with the following top-level fields: %s\n', n_read, brackify(yaml_names))
218187
# process header first since it impacts how to handle colClasses
219188
if ('header' %chin% yaml_names) {
220189
if ('header' %chin% call_args) messagef("User-supplied 'header' will override that found in metadata.")
@@ -384,6 +353,44 @@ yaml=FALSE, tmpdir=tempdir(), tz="UTC")
384353
ans
385354
}
386355

356+
# nocov start. Covered only in other.Rraw
357+
.read_yaml_header = function(f, skip, verbose) {
358+
# create connection to stream header lines from file:
359+
# https://stackoverflow.com/questions/9871307
360+
con = base::file(f, 'r')
361+
# NB: close() won't be right if 'f' itself can be a file connection (#561)
362+
on.exit(close(con))
363+
364+
first_line = readLines(con, n=1L)
365+
n_read = 1L
366+
yaml_border_re = '^#?---'
367+
if (!grepl(yaml_border_re, first_line)) {
368+
stopf(
369+
'Encountered <%s%s> at the first unskipped line (%d), which does not constitute the start to a valid YAML header (expecting something matching regex "%s"); please check your input and try again.',
370+
substr(first_line, 1L, 50L), if (nchar(first_line) > 50L) '...' else '', 1L+skip, yaml_border_re
371+
)
372+
}
373+
374+
yaml_comment_re = '^#'
375+
yaml_string = character(0L)
376+
repeat {
377+
this_line = readLines(con, n=1L)
378+
n_read = n_read + 1L
379+
if (!length(this_line)){
380+
stopf('Reached the end of the file before finding a completion to the YAML header. A valid YAML header is bookended by lines matching the regex "%s". Please double check the input file is a valid csvy.', yaml_border_re)
381+
}
382+
if (grepl(yaml_border_re, this_line)) break
383+
if (grepl(yaml_comment_re, this_line))
384+
this_line = sub(yaml_comment_re, '', this_line)
385+
yaml_string = paste(yaml_string, this_line, sep='\n')
386+
}
387+
388+
yaml_header = yaml::yaml.load(yaml_string)
389+
if (verbose) catf('Processed %d lines of YAML metadata with the following top-level fields: %s\n', n_read, brackify(names(yaml_header)))
390+
yaml_header
391+
}
392+
# nocov end.
393+
387394
known_signatures = list(
388395
zip = as.raw(c(0x50, 0x4b, 0x03, 0x04)), # charToRaw("PK\x03\x04")
389396
gzip = as.raw(c(0x1F, 0x8B)),

0 commit comments

Comments
 (0)