From 6ca305d000360de74e686d801c638086c876d08a Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 20 May 2020 08:25:56 +0300 Subject: feat!: allow multiple bindings and functions files Where previously the document metadata could specify a single bindings file, and a single functions file, it can now specify one or more. If a single value is given, that's the filename. Otherwise, it can be a YAML list of filenames. Drop the functions_filename template variable, which was effectively unused, and for which there is no recorded use case at this time. --- runcmd.py | 0 runcmd.yaml | 1 + src/ast.rs | 70 +++++++++++++++++++++----------------------- src/bin/sp-meta.rs | 11 +++++-- src/codegen.rs | 10 +++---- subplot.md | 28 +++++++++++++++--- templates/bash/template.sh | 2 +- templates/python/template.py | 2 +- 8 files changed, 74 insertions(+), 50 deletions(-) create mode 100644 runcmd.py create mode 100644 runcmd.yaml diff --git a/runcmd.py b/runcmd.py new file mode 100644 index 0000000..e69de29 diff --git a/runcmd.yaml b/runcmd.yaml new file mode 100644 index 0000000..fe51488 --- /dev/null +++ b/runcmd.yaml @@ -0,0 +1 @@ +[] diff --git a/src/ast.rs b/src/ast.rs index bd6640b..012e05a 100644 --- a/src/ast.rs +++ b/src/ast.rs @@ -143,11 +143,11 @@ impl<'a> Document { pub fn sources(&mut self) -> Vec { let mut names = vec![]; - if let Some(x) = self.meta().bindings_filename() { + for x in self.meta().bindings_filenames() { names.push(PathBuf::from(x)) } - if let Some(x) = self.meta().functions_filename() { + for x in self.meta().functions_filenames() { names.push(PathBuf::from(x)) } @@ -426,9 +426,9 @@ mod test_extract { pub struct Metadata { title: String, date: Option, - bindings_filename: Option, + bindings_filenames: Vec, bindings: Bindings, - functions_filename: Option, + functions_filenames: Vec, template: Option, bibliographies: Vec, /// Extra class names which should be considered 'correct' for this document @@ -443,21 +443,21 @@ impl Metadata { { let title = get_title(&doc.meta)?; let date = get_date(&doc.meta); - let bindings_filename = get_bindings_filename(basedir.as_ref(), &doc.meta)?; - let functions_filename = get_functions_filename(basedir.as_ref(), &doc.meta)?; + let bindings_filenames = get_bindings_filenames(basedir.as_ref(), &doc.meta); + let functions_filenames = get_functions_filenames(basedir.as_ref(), &doc.meta); let template = get_template_name(&doc.meta)?; let mut bindings = Bindings::new(); - if let Some(ref filename) = bindings_filename { - get_bindings(filename, &mut bindings)?; - } + let bibliographies = get_bibliographies(basedir.as_ref(), &doc.meta); let classes = get_classes(&doc.meta); + + get_bindings(&bindings_filenames, &mut bindings)?; Ok(Metadata { title, date, - bindings_filename, + bindings_filenames, bindings, - functions_filename, + functions_filenames, template, bibliographies, classes, @@ -479,19 +479,16 @@ impl Metadata { } /// Return filename where bindings are specified. - pub fn bindings_filename(&self) -> Option<&Path> { - match &self.bindings_filename { - Some(filename) => Some(&filename), - None => None, - } + pub fn bindings_filenames(&self) -> Vec<&Path> { + self.bindings_filenames.iter().map(|f| f.as_ref()).collect() } /// Return filename where functions are specified. - pub fn functions_filename(&self) -> Option<&Path> { - match &self.functions_filename { - Some(filename) => Some(&filename), - None => None, - } + pub fn functions_filenames(&self) -> Vec<&Path> { + self.functions_filenames + .iter() + .map(|f| f.as_ref()) + .collect() } /// Return the name of the code template, if specified. @@ -536,24 +533,18 @@ fn get_date(map: &Mapp) -> Option { } } -fn get_bindings_filename

(basedir: P, map: &Mapp) -> Result> +fn get_bindings_filenames

(basedir: P, map: &Mapp) -> Vec where P: AsRef, { - match get_path(map, "bindings") { - None => Ok(None), - Some(path) => Ok(Some(basedir.as_ref().join(path))), - } + get_paths(basedir, map, "bindings") } -fn get_functions_filename

(basedir: P, map: &Mapp) -> Result> +fn get_functions_filenames

(basedir: P, map: &Mapp) -> Vec where P: AsRef, { - match get_path(map, "functions") { - None => Ok(None), - Some(path) => Ok(Some(basedir.as_ref().join(path))), - } + get_paths(basedir, map, "functions") } fn get_template_name(map: &Mapp) -> Result> { @@ -563,10 +554,13 @@ fn get_template_name(map: &Mapp) -> Result> { } } -fn get_path(map: &Mapp, field: &str) -> Option { - match get_string(map, field) { - None => None, - Some(s) => Some(Path::new(&s).to_path_buf()), +fn get_paths

(basedir: P, map: &Mapp, field: &str) -> Vec +where + P: AsRef, +{ + match map.get(field) { + None => vec![], + Some(v) => pathbufs(basedir, v), } } @@ -687,11 +681,13 @@ mod test_join { } } -fn get_bindings

(filename: P, bindings: &mut Bindings) -> Result<()> +fn get_bindings

(filenames: &[P], bindings: &mut Bindings) -> Result<()> where P: AsRef, { - bindings.add_from_file(filename)?; + for filename in filenames { + bindings.add_from_file(filename)?; + } Ok(()) } diff --git a/src/bin/sp-meta.rs b/src/bin/sp-meta.rs index 979f18a..cfa3b3d 100644 --- a/src/bin/sp-meta.rs +++ b/src/bin/sp-meta.rs @@ -22,8 +22,15 @@ fn main() -> Result<()> { } println!("title: {}", doc.meta().title()); - println!("bindings: {}", filename(doc.meta().bindings_filename())); - println!("functions: {}", filename(doc.meta().functions_filename())); + + for filename in doc.meta().bindings_filenames() { + println!("bindings: {}", filename.display()); + } + + for filename in doc.meta().functions_filenames() { + println!("functions: {}", filename.display()); + } + for bib in doc.meta().bibliographies().iter() { println!("bibliography: {}", filename(Some(bib))); } diff --git a/src/codegen.rs b/src/codegen.rs index 70d1966..db31765 100644 --- a/src/codegen.rs +++ b/src/codegen.rs @@ -41,12 +41,12 @@ fn context(doc: &mut Document) -> Result { context.insert("scenarios", &doc.matched_scenarios()?); context.insert("files", doc.files()); - let (funcs_filename, funcs) = match doc.meta().functions_filename() { - Some(filename) => (filename, cat(filename)?), - None => (Path::new(""), "".to_string()), - }; + let funcs_filenames = doc.meta().functions_filenames(); + let mut funcs = String::new(); + for filename in funcs_filenames { + funcs.push_str(&cat(filename)?); + } context.insert("functions", &funcs); - context.insert("functions_filename", funcs_filename); Ok(context) } diff --git a/subplot.md b/subplot.md index f0dfa9b..6459e5f 100644 --- a/subplot.md +++ b/subplot.md @@ -1456,17 +1456,22 @@ or functions files. ~~~scenario given file images.md and file b.yaml +and file other.yaml and file f.py +and file other.py and file foo.bib and file bar.bib when I run sp-meta images.md then output matches /source: images.md/ and output matches /source: b.yaml/ +and output matches /source: other.yaml/ and output matches /source: f.py/ +and output matches /source: other.py/ and output matches /source: foo.bib/ and output matches /source: bar.bib/ and output matches /source: image.gif/ and output matches /bindings: b.yaml/ +and output matches /bindings: other.yaml/ and output matches /functions: f.py/ ~~~ @@ -1474,14 +1479,25 @@ and output matches /functions: f.py/ ~~~{#images.md .file .markdown .numberLines} --- title: Document refers to external images -bindings: b.yaml -functions: f.py +bindings: +- b.yaml +- other.yaml +functions: +- f.py +- other.py bibliography: [foo.bib, bar.bib] ... ![alt text](image.gif) ~~~ +~~~{#other.yaml .file .yaml .numberLines} +[] +~~~ + +~~~{#other.py .file .python .numberLines} +~~~ + ~~~{#foo.bib .file .numberLines} @book{foo2020, author = "James Random", @@ -1827,6 +1843,10 @@ This content is foobarish title: "Subplot" author: The Subplot project date: work in progress -bindings: subplot.yaml -functions: subplot.py +bindings: +- subplot.yaml +- runcmd.yaml +functions: +- subplot.py +- runcmd.py ... diff --git a/templates/bash/template.sh b/templates/bash/template.sh index bc6a51e..286e56f 100644 --- a/templates/bash/template.sh +++ b/templates/bash/template.sh @@ -3,7 +3,7 @@ set -eu -o pipefail ############################################################################# -# Functions that implement steps. From {{ functions_filename }}. +# Functions that implement steps. {{ functions }} diff --git a/templates/python/template.py b/templates/python/template.py index 76d8239..e430b1b 100644 --- a/templates/python/template.py +++ b/templates/python/template.py @@ -1,5 +1,5 @@ ############################################################################# -# Functions that implement steps. From {{ functions_filename }}. +# Functions that implement steps. {{ functions }} -- cgit v1.2.1 From 0a073fa0b2a7e456d3bff9c9bfe930e8b3ee7449 Mon Sep 17 00:00:00 2001 From: Lars Wirzenius Date: Wed, 20 May 2020 10:14:00 +0300 Subject: refactor: move things from subplot.{py,yaml} to separate files files.{py,yaml} contain re-usable steps for handling files. runcmd.{py,yaml} contain re-usable steps for running commands and inspecting results. --- files.py | 81 +++++++++++++++++++++++++++++++++ files.yaml | 36 +++++++++++++++ runcmd.py | 84 ++++++++++++++++++++++++++++++++++ runcmd.yaml | 14 +++++- subplot.md | 2 + subplot.py | 145 ++++++----------------------------------------------------- subplot.yaml | 51 --------------------- 7 files changed, 230 insertions(+), 183 deletions(-) create mode 100644 files.py create mode 100644 files.yaml diff --git a/files.py b/files.py new file mode 100644 index 0000000..9ee1739 --- /dev/null +++ b/files.py @@ -0,0 +1,81 @@ +# Some generic file handling step implementations. + +import os +import re +import time + + +# Create a file on disk from an embedded file. +def create_file(ctx, filename=None): + with open(filename, "wb") as f: + f.write(get_file(filename)) + + +# Update mtime of a file in datadir to a specific time. +def touch_file(ctx, filename=None, y=None, mon=None, d=None, h=None, min=None, s=None): + t = (int(y), int(mon), int(d), int(h), int(min), int(s), -1, -1, -1) + ts = time.mktime(t) + os.utime(filename, times=(ts, ts)) + + +# Update mtime of a file in datadir to current time. +def update_mtime(ctx, filename=None): + os.utime(filename) + + +# Check that a file exists. +def file_exists(ctx, filename=None): + assert_eq(os.path.exists(filename), True) + + +# Check that a file does not exist. +def file_does_not_exist(ctx, filename=None): + assert_eq(os.path.exists(filename), False) + + +# Check that only specific files exist in the current working directory. +def only_these_files_exist(ctx, filenames=None): + filenames = filenames.replace(",", "").split() + assert_eq(set(os.listdir(".")), set(filenames)) + + +# Check that a file contents match a regex. +def file_matches(ctx, filename=None, regex=None): + with open(filename) as f: + content = f.read() + m = re.search(regex, content) + if m is None: + print("content:", repr(content)) + print("regex:", repr(regex)) + assert_eq(bool(m), True) + + +# Check that a file contains a fixed string. +def file_contains(ctx, filename=None, pattern=None): + with open(filename) as f: + content = f.read() + assert_eq(pattern in content, True) + + +# Retrieve metadata for a file as a struct so it can be easily inspected. +def _get_metadata(filename): + st = os.lstat(filename) + keys = ["st_dev", "st_gid", "st_ino", "st_mode", "st_mtime", "st_size", "st_uid"] + return {key: getattr(st, key) for key in keys} + + +# Store in the context current metdata for a file. +def remember_metadata(ctx, filename=None): + meta = ctx.get("remembered-metadata", {}) + meta[filename] = _get_metadata(filename) + ctx["remembered-metadata"] = meta + + +# Check that current metadata of a file is as stored in the context. +def has_same_metadata_as_remembered(ctx, filename=None): + assert_eq(ctx["remembered-metadata"][filename], _get_metadata(filename)) + + +# Check that current metadata of a file is different than stored in the context. +def has_diff_metadata_than_remembered(ctx, filename=None): + assert_ne(ctx["remembered-metadata"][filename], _get_metadata(filename)) diff --git a/files.yaml b/files.yaml new file mode 100644 index 0000000..2cc53e1 --- /dev/null +++ b/files.yaml @@ -0,0 +1,36 @@ +- given: file {filename} + function: create_file + +- given: file (?P\S+) has modification time (?P\d+)-(?P\d+)-(?P\d+) (?P\d+):(?P\d+):(?P\d+) + function: touch_file + regex: true + +- when: I remember the metadata for {filename} + function: remember_metadata + +- when: I touch {filename} + function: update_mtime + +- then: file {filename} exists + function: file_exists + +- then: file {filename} does not exist + function: file_does_not_exist + +- then: file (?P\S+) matches /(?P.+)/ + function: file_matches + regex: true + +- then: file (?P\S+) contains "(?P.+)" + function: file_contains + regex: true + +- then: "{filename} has the same metadata as before" + function: has_same_metadata_as_remembered + +- then: "{filename} has changed from before" + function: has_diff_metadata_than_remembered + +- then: only files (?P.+) exist + function: only_these_files_exist + regex: true diff --git a/runcmd.py b/runcmd.py index e69de29..b67c6bb 100644 --- a/runcmd.py +++ b/runcmd.py @@ -0,0 +1,84 @@ +# Some step implementations for running commands and capturing the result. + +import subprocess + + +# Run a command, capture its stdout, stderr, and exit code in context. +def runcmd(ctx, argv, **kwargs): + p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE, **kwargs) + stdout, stderr = p.communicate("") + ctx["argv"] = argv + ctx["stdout"] = stdout.decode("utf-8") + ctx["stderr"] = stderr.decode("utf-8") + ctx["exit"] = p.returncode + + +# Check that latest exit code captured by runcmd was a specific one. +def exit_code_is(ctx, wanted): + if ctx.get("exit") != wanted: + print("context:", ctx.as_dict()) + assert_eq(ctx.get("exit"), wanted) + + +# Check that latest exit code captured by runcmd was not a specific one. +def exit_code_is_not(ctx, unwanted): + if ctx.get("exit") == wanted: + print("context:", ctx.as_dict()) + assert_ne(ctx.get("exit"), wanted) + + +# Check that latest exit code captured by runcmd was not a specific one. +def exit_code_is_not(ctx, unwanted): + if ctx.get("exit") == unwanted: + print("context:", ctx.as_dict()) + assert_ne(ctx.get("exit"), unwanted) + + +# Check that latest exit code captured by runcmd was zero. +def exit_code_zero(ctx): + exit_code_is(ctx, 0) + + +# Check that latest exit code captured by runcmd was not zero. +def exit_code_nonzero(ctx): + exit_code_is_not(ctx, 0) + + +# Check that stdout of latest runcmd contains a specific string. +def stdout_contains(ctx, pattern=None): + stdout = ctx.get("stdout", "") + if pattern not in stdout: + print("pattern:", repr(pattern)) + print("stdout:", repr(stdout)) + print("ctx:", ctx.as_dict()) + assert_eq(pattern in stdout, True) + + +# Check that stdout of latest runcmd does not contain a specific string. +def stdout_does_not_contain(ctx, pattern=None): + stdout = ctx.get("stdout", "") + if pattern in stdout: + print("pattern:", repr(pattern)) + print("stdout:", repr(stdout)) + print("ctx:", ctx.as_dict()) + assert_eq(pattern not in stdout, True) + + +# Check that stderr of latest runcmd does contains a specific string. +def stderr_contains(ctx, pattern=None): + stderr = ctx.get("stderr", "") + if pattern not in stderr: + print("pattern:", repr(pattern)) + print("stderr:", repr(stderr)) + print("ctx:", ctx.as_dict()) + assert_eq(pattern in stderr, True) + + +# Check that stderr of latest runcmd does not contain a specific string. +def stderr_does_not_contain(ctx, pattern=None): + stderr = ctx.get("stderr", "") + if pattern not in stderr: + print("pattern:", repr(pattern)) + print("stderr:", repr(stderr)) + print("ctx:", ctx.as_dict()) + assert_eq(pattern not in stderr, True) diff --git a/runcmd.yaml b/runcmd.yaml index fe51488..02e5ee1 100644 --- a/runcmd.yaml +++ b/runcmd.yaml @@ -1 +1,13 @@ -[] +- then: exit code is non-zero + function: exit_code_nonzero + +- then: output matches /(?P.+)/ + function: stdout_contains + regex: true + +- then: stderr matches /(?P.+)/ + function: stderr_contains + regex: true + +- then: program finished successfully + function: exit_code_zero diff --git a/subplot.md b/subplot.md index 6459e5f..ff1d702 100644 --- a/subplot.md +++ b/subplot.md @@ -1846,7 +1846,9 @@ date: work in progress bindings: - subplot.yaml - runcmd.yaml +- files.yaml functions: - subplot.py - runcmd.py +- files.py ... diff --git a/subplot.py b/subplot.py index e586b53..9e16168 100644 --- a/subplot.py +++ b/subplot.py @@ -4,21 +4,6 @@ import subprocess import time -def create_file(ctx, filename=None): - with open(filename, "wb") as f: - f.write(get_file(filename)) - - -def touch_file(ctx, filename=None, y=None, mon=None, d=None, h=None, min=None, s=None): - t = (int(y), int(mon), int(d), int(h), int(min), int(s), -1, -1, -1) - ts = time.mktime(t) - os.utime(filename, times=(ts, ts)) - - -def update_mtime(ctx, filename=None): - os.utime(filename) - - def try_docgen(ctx, md=None, output=None): docgen = binary("sp-docgen") runcmd(ctx, [docgen, md, "-o", output]) @@ -26,13 +11,13 @@ def try_docgen(ctx, md=None, output=None): def run_docgen(ctx, md=None, output=None): try_docgen(ctx, md=md, output=output) - exit_code_zero(ctx) + exit_code_is(ctx, 0) def run_docgen_with_date(ctx, md=None, output=None, date=None): docgen = binary("sp-docgen") runcmd(ctx, [docgen, md, "-o", output, "--date", date]) - exit_code_zero(ctx) + exit_code_is(ctx, 0) def try_codegen_and_program(ctx, filename=None, testprog=None): @@ -43,76 +28,52 @@ def try_codegen_and_program(ctx, filename=None, testprog=None): def run_codegen_and_program(ctx, filename=None, testprog=None): try_codegen_and_program(ctx, filename=filename, testprog=testprog) - exit_code_zero(ctx) + exit_code_is(ctx, 0) def run_codegen(ctx, filename=None, testprog=None): codegen = binary("sp-codegen") tmpldir = os.path.join(srcdir, "templates") runcmd(ctx, [codegen, filename, "-o", testprog, "--templates", tmpldir]) - exit_code_zero(ctx) + exit_code_is(ctx, 0) def run_python_test_program(ctx, testprog=None, pattern=None): runcmd(ctx, ["python3", testprog, pattern]) - exit_code_zero(ctx) + exit_code_is(ctx, 0) def run_bash_test_program(ctx, testprog=None, pattern=None): runcmd(ctx, ["bash", testprog, pattern]) - exit_code_zero(ctx) + exit_code_is(ctx, 0) def run_meta(ctx, filename=None): meta = binary("sp-meta") runcmd(ctx, [meta, filename]) - exit_code_zero(ctx) + exit_code_is(ctx, 0) def run_pandoc_with_filter(ctx, filename=None, output=None): sp_filter = binary("sp-filter") runcmd(ctx, ["pandoc", "--filter", sp_filter, filename, "-o", output]) - exit_code_zero(ctx) - - -def file_exists(ctx, filename=None): - assert_eq(os.path.exists(filename), True) - - -def file_does_not_exist(ctx, filename=None): - assert_eq(os.path.exists(filename), False) - - -def file_matches(ctx, filename=None, regex=None): - with open(filename) as f: - content = f.read() - m = re.search(regex, content) - if m is None: - print("content:", repr(content)) - print("regex:", repr(regex)) - assert_eq(bool(m), True) - - -def file_contains(ctx, filename=None, pattern=None): - with open(filename) as f: - content = f.read() - assert_eq(pattern in content, True) + exit_code_is(ctx, 0) def scenario_was_run(ctx, name=None): - stdout_matches(ctx, pattern="\nscenario: {}\n".format(name)) + stdout_contains(ctx, pattern="\nscenario: {}\n".format(name)) def scenario_was_not_run(ctx, name=None): - stdout_does_not_match(ctx, pattern="\nscenario: {}\n".format(name)) + stdout_does_not_contain(ctx, pattern="\nscenario: {}\n".format(name)) def step_was_run(ctx, keyword=None, name=None): - stdout_matches(ctx, pattern="\n step: {} {}\n".format(keyword, name)) + stdout_contains(ctx, pattern="\n step: {} {}\n".format(keyword, name)) def step_was_run_and_then(ctx, keyword1=None, name1=None, keyword2=None, name2=None): - stdout_matches( + stdout_contains( ctx, pattern="\n step: {} {}\n step: {} {}".format( keyword1, name1, keyword2, name2 @@ -121,7 +82,7 @@ def step_was_run_and_then(ctx, keyword1=None, name1=None, keyword2=None, name2=N def cleanup_was_run(ctx, keyword1=None, name1=None, keyword2=None, name2=None): - stdout_matches( + stdout_contains( ctx, pattern="\n cleanup: {} {}\n cleanup: {} {}\n".format( keyword1, name1, keyword2, name2 @@ -130,86 +91,8 @@ def cleanup_was_run(ctx, keyword1=None, name1=None, keyword2=None, name2=None): def cleanup_was_not_run(ctx, keyword=None, name=None): - stdout_does_not_match(ctx, pattern="\n cleanup: {} {}\n".format(keyword, name)) - - -def exit_code_zero(ctx): - if ctx.get("exit") != 0: - print("context:", ctx.as_dict()) - assert_eq(ctx.get("exit"), 0) - - -def exit_code_nonzero(ctx): - assert_ne(ctx.get("exit"), 0) + stdout_does_not_contain(ctx, pattern="\n cleanup: {} {}\n".format(keyword, name)) def binary(basename): return os.path.join(srcdir, "target", "debug", basename) - - -def stdout_matches(ctx, pattern=None): - stdout = ctx.get("stdout", "") - if pattern not in stdout: - print("pattern:", repr(pattern)) - print("stdout:", repr(stdout)) - print("ctx:", ctx.as_dict()) - assert_eq(pattern in stdout, True) - - -def stdout_does_not_match(ctx, pattern=None): - stdout = ctx.get("stdout", "") - if pattern in stdout: - print("pattern:", repr(pattern)) - print("stdout:", repr(stdout)) - print("ctx:", ctx.as_dict()) - assert_eq(pattern not in stdout, True) - - -def stderr_matches(ctx, pattern=None): - stderr = ctx.get("stderr", "") - if pattern not in stderr: - print("pattern:", repr(pattern)) - print("stderr:", repr(stderr)) - print("ctx:", ctx.as_dict()) - assert_eq(pattern in stderr, True) - - -def stderr_does_not_match(ctx, pattern=None): - stderr = ctx.get("stderr", "") - if pattern not in stderr: - print("pattern:", repr(pattern)) - print("stderr:", repr(stderr)) - print("ctx:", ctx.as_dict()) - assert_eq(pattern not in stderr, True) - - -def _get_metadata(filename): - st = os.lstat(filename) - keys = ["st_dev", "st_gid", "st_ino", "st_mode", "st_mtime", "st_size", "st_uid"] - return {key: getattr(st, key) for key in keys} - - -def remember_metadata(ctx, filename=None): - ctx["remembered-metadata"] = _get_metadata(filename) - - -def has_same_metadata_as_remembered(ctx, filename=None): - assert_eq(ctx["remembered-metadata"], _get_metadata(filename)) - - -def has_diff_metadata_than_remembered(ctx, filename=None): - assert_ne(ctx["remembered-metadata"], _get_metadata(filename)) - - -def only_these_files_exist(ctx, filenames=None): - filenames = filenames.replace(",", "").split() - assert_eq(set(os.listdir(".")), set(filenames)) - - -def runcmd(ctx, argv): - p = subprocess.Popen(argv, stdout=subprocess.PIPE, stderr=subprocess.PIPE) - stdout, stderr = p.communicate("") - ctx["argv"] = argv - ctx["stdout"] = stdout.decode("utf-8") - ctx["stderr"] = stderr.decode("utf-8") - ctx["exit"] = p.returncode diff --git a/subplot.yaml b/subplot.yaml index 8d4187f..f35cdef 100644 --- a/subplot.yaml +++ b/subplot.yaml @@ -1,13 +1,3 @@ -- given: file {filename} - function: create_file - -- given: file (?P\S+) has modification time (?P\d+)-(?P\d+)-(?P\d+) (?P\d+):(?P\d+):(?P\d+) - function: touch_file - regex: true - -- when: I remember the metadata for {filename} - function: remember_metadata - - when: I run sp-docgen {md} -o {output} function: run_docgen @@ -35,43 +25,9 @@ - when: I run sp-meta {filename} function: run_meta -- when: I touch {filename} - function: update_mtime - - when: I run pandoc --filter sp-filter {filename} -o {output} function: run_pandoc_with_filter -- then: exit code is non-zero - function: exit_code_nonzero - -- then: file {filename} exists - function: file_exists - -- then: file {filename} does not exist - function: file_does_not_exist - -- then: file (?P\S+) matches /(?P.+)/ - function: file_matches - regex: true - -- then: file (?P\S+) contains "(?P.+)" - function: file_contains - regex: true - -- then: "{filename} has the same metadata as before" - function: has_same_metadata_as_remembered - -- then: "{filename} has changed from before" - function: has_diff_metadata_than_remembered - -- then: output matches /(?P.+)/ - function: stdout_matches - regex: true - -- then: stderr matches /(?P.+)/ - function: stderr_matches - regex: true - - then: scenario "(?P.+)" was run function: scenario_was_run regex: true @@ -95,10 +51,3 @@ - then: cleanup for "(?Pgiven|when|then) (?P.+)" was not run function: cleanup_was_not_run regex: true - -- then: program finished successfully - function: exit_code_zero - -- then: only files (?P.+) exist - function: only_these_files_exist - regex: true -- cgit v1.2.1