diff options
-rw-r--r-- | doc/man/serd-pipe.1 | 9 | ||||
-rw-r--r-- | test/meson.build | 15 | ||||
-rwxr-xr-x | test/run_suite.py | 24 | ||||
-rw-r--r-- | test/serd_test_util/__init__.py | 4 | ||||
-rwxr-xr-x | test/test_base.py | 21 | ||||
-rwxr-xr-x | test/test_stdin.py | 2 | ||||
-rw-r--r-- | tools/serd-pipe.c | 16 |
7 files changed, 71 insertions, 20 deletions
diff --git a/doc/man/serd-pipe.1 b/doc/man/serd-pipe.1 index 32482c73..d335450f 100644 --- a/doc/man/serd-pipe.1 +++ b/doc/man/serd-pipe.1 @@ -9,6 +9,7 @@ .Sh SYNOPSIS .Nm serd-pipe .Op Fl abefhlqtv +.Op Fl B Ar base .Op Fl c Ar prefix .Op Fl i Ar syntax .Op Fl k Ar bytes @@ -17,7 +18,6 @@ .Op Fl r Ar root .Op Fl s Ar string .Ar input -.Op Ar base_uri .Sh DESCRIPTION .Nm is a fast command-line utility for streaming and processing RDF data. @@ -35,6 +35,13 @@ or transform URIs and blank node IDs. .Pp The options are as follows: .Bl -tag -width 3n +.It Fl B Ar base +Input base URI. +Relative URI references in the input will be resolved against this. +When the input is a file, +the URI of the file is automatically used as the base URI. +This option can be used to override that, +or to provide a base URI for input from stdin or a string. .It Fl a Write ASCII output. If this is enabled, all non-ASCII characters will be escaped, even if the output syntax allows them to be written in UTF-8. diff --git a/test/meson.build b/test/meson.build index 2178ce1f..3af7cd15 100644 --- a/test/meson.build +++ b/test/meson.build @@ -16,6 +16,7 @@ simple_script_paths = [ '../scripts/check_formatting.py', 'serd_test_util/__init__.py', 'run_suite.py', + 'test_base.py', 'test_empty.py', 'test_quiet.py', 'test_stdin.py', @@ -172,6 +173,8 @@ endif simple_command_tests = { 'pipe': { 'bad': [ + ['-B', 'nonuriorpath'], + ['-B'], ['-c'], ['-fi'], ['-i', 'turtle'], @@ -223,6 +226,18 @@ if is_variable('serd_pipe') test('none', serd_pipe, env: test_env, should_fail: true, suite: cmd_suite) + # Base URI options + + test( + 'base', + files('test_base.py'), + args: pipe_script_args, + env: test_env, + suite: cmd_suite, + ) + + # Log + test( 'quiet', files('test_quiet.py'), diff --git a/test/run_suite.py b/test/run_suite.py index fdda0625..ffc616a3 100755 --- a/test/run_suite.py +++ b/test/run_suite.py @@ -37,11 +37,11 @@ TEST_TYPES = [ ] -def run_eval_test(base_uri, command, in_path, good_path, out_path): +def run_eval_test(command, in_path, good_path, out_path): """Run a positive eval test and return whether the output matches.""" syntax = util.syntax_from_path(out_path) - command = command + ["-o", syntax, in_path, base_uri] + command = command + ["-o", syntax, in_path] with subprocess.Popen(command, stdout=PIPE, encoding="utf-8") as proc: out = list(proc.stdout) @@ -50,21 +50,21 @@ def run_eval_test(base_uri, command, in_path, good_path, out_path): return util.lines_equal(list(good), out, good_path, out_path) -def run_positive_test(base_uri, command, in_path): +def run_positive_test(command, in_path): """Run a positive syntax test and ensure no errors occur.""" - command = command + [in_path, base_uri] + command = command + [in_path] subprocess.check_call(command, encoding="utf-8", stdout=DEVNULL) return True -def run_negative_test(base_uri, command, in_path): +def run_negative_test(command, in_path): """Run a negative syntax test and return whether the error was detected.""" if not os.path.exists(in_path): raise RuntimeError("Input file missing: " + in_path) - command = command + [in_path, base_uri] + command = command + [in_path] proc = subprocess.run(command, check=False, stderr=PIPE, stdout=DEVNULL) if proc.returncode == 0: @@ -82,21 +82,21 @@ def run_entry(args, entry, command, out_dir, suite_dir): """Run a single test entry from the manifest.""" in_path = util.file_path(suite_dir, entry[NS_MF + "action"][0]) - base = args.base_uri + os.path.basename(in_path) + command = command + ["-B", args.base_uri + os.path.basename(in_path)] negative = "Negative" in entry[NS_RDF + "type"][0] if negative and not args.lax: - return run_negative_test(base, command, in_path) + return run_negative_test(command, in_path) if NS_MF + "result" not in entry: - return run_positive_test(base, command, in_path) + return run_positive_test(command, in_path) good_path = util.file_path(suite_dir, entry[NS_MF + "result"][0]) if args.reverse: in_path, good_path = good_path, in_path out_path = os.path.join(out_dir, os.path.basename(good_path)) - return run_eval_test(base, command, in_path, good_path, out_path) + return run_eval_test(command, in_path, good_path, out_path) def run_suite(args, command, out_dir): @@ -104,7 +104,9 @@ def run_suite(args, command, out_dir): # Load manifest model top = os.path.dirname(args.manifest) - model, instances = util.load_rdf(args.manifest, args.base_uri, command) + model, instances = util.load_rdf( + command + ["-B", args.base_uri], args.manifest + ) # Run all the listed tests that have known types command = command + args.arg diff --git a/test/serd_test_util/__init__.py b/test/serd_test_util/__init__.py index ac831054..f465a4b7 100644 --- a/test/serd_test_util/__init__.py +++ b/test/serd_test_util/__init__.py @@ -148,14 +148,14 @@ def earl_assertion(test, passed, asserter): ) -def load_rdf(filename, base_uri, command_prefix): +def load_rdf(command_prefix, filename): """Load an RDF file as dictionaries via serd-pipe (only supports URIs).""" rdf_type = "http://www.w3.org/1999/02/22-rdf-syntax-ns#type" model = {} instances = {} - cmd = command_prefix + [filename, base_uri] + cmd = command_prefix + [filename] proc = subprocess.run( cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE, check=True ) diff --git a/test/test_base.py b/test/test_base.py new file mode 100755 index 00000000..b63bb135 --- /dev/null +++ b/test/test_base.py @@ -0,0 +1,21 @@ +#!/usr/bin/env python3 + +# Copyright 2022 David Robillard <d@drobilla.net> +# SPDX-License-Identifier: ISC + +"""Test reading from stdin with serd-pipe.""" + +# pylint: disable=consider-using-f-string + +import serd_test_util as util + +args = util.wrapper_args(__doc__) +command = [args.tool, "-B", "http://example.org", "-i", "turtle", "-"] + +IN_DOC = "<s> <p> <o> ." +OUT_DOC = "<{0}s> <{0}p> <{0}o> .".format("http://example.org/") + +lines = util.command_output(args.wrapper, command, IN_DOC).splitlines(True) + +assert len(lines) == 1 +assert lines[0].strip() == OUT_DOC diff --git a/test/test_stdin.py b/test/test_stdin.py index 9975c547..9ffd19ff 100755 --- a/test/test_stdin.py +++ b/test/test_stdin.py @@ -10,7 +10,7 @@ import serd_test_util as util args = util.wrapper_args(__doc__) -command = [args.tool, "-i", "ntriples", "-", "http://example.org"] +command = [args.tool, "-i", "ntriples", "-B", "http://example.org", "-"] DOC = "<{0}s> <{0}p> <{0}o> .".format("http://example.org/") diff --git a/tools/serd-pipe.c b/tools/serd-pipe.c index 26a4a26a..a5f2a1b2 100644 --- a/tools/serd-pipe.c +++ b/tools/serd-pipe.c @@ -33,6 +33,7 @@ print_usage(const char* const name, const bool error) static const char* const description = "Read and write RDF syntax.\n" "Use - for INPUT to read from standard input.\n\n" + " -B BASE_URI Base URI.\n" " -a Write ASCII output.\n" " -b Write output in blocks for performance.\n" " -c PREFIX Chop PREFIX from matching blank node IDs.\n" @@ -52,7 +53,7 @@ print_usage(const char* const name, const bool error) FILE* const os = error ? stderr : stdout; fprintf(os, "%s", error ? "\n" : ""); - fprintf(os, "Usage: %s [OPTION]... INPUT [BASE_URI]\n", name); + fprintf(os, "Usage: %s [OPTION]... INPUT\n", name); fprintf(os, "%s", description); return error ? 1 : 0; } @@ -77,6 +78,7 @@ main(int argc, char** argv) { const char* const prog = argv[0]; + SerdNode* base = NULL; SerdSyntax input_syntax = SERD_SYNTAX_EMPTY; SerdSyntax output_syntax = SERD_SYNTAX_EMPTY; SerdReaderFlags reader_flags = 0; @@ -131,6 +133,13 @@ main(int argc, char** argv) } else if (opt == 's') { from_string = true; break; + } else if (argv[a][1] == 'B') { + if (++a == argc) { + return missing_arg(prog, 'B'); + } + + base = serd_new_uri(serd_string(argv[a])); + break; } else if (opt == 'c') { if (argv[a][o + 1] || ++a == argc) { return missing_arg(prog, 'c'); @@ -212,10 +221,7 @@ main(int argc, char** argv) output_syntax = input_has_graphs ? SERD_NQUADS : SERD_NTRIPLES; } - SerdNode* base = NULL; - if (a < argc) { // Base URI given on command line - base = serd_new_uri(serd_string(argv[a])); - } else if (!from_string && !from_stdin) { // Use input file URI + if (!base && !from_string && !from_stdin) { // Use input file URI base = serd_new_file_uri(serd_string(input), serd_empty_string()); } |