summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDaniel Silverstone <dsilvers+gitlab@digital-scurf.org>2020-05-21 07:27:38 +0000
committerDaniel Silverstone <dsilvers+gitlab@digital-scurf.org>2020-05-21 07:27:38 +0000
commit576aa3bcbb6615f4fef73264029fc22af78fdfdc (patch)
treeec50e222e1c9b139d08a0eae6911cbe87e0fb485
parent6d77fdedd7fd0f832a543b7eb530ae15984aa377 (diff)
parent0a073fa0b2a7e456d3bff9c9bfe930e8b3ee7449 (diff)
downloadsubplot-576aa3bcbb6615f4fef73264029fc22af78fdfdc.tar.gz
Merge branch 'multi' into 'master'
Add support for multiple bindings and functions files See merge request larswirzenius/subplot!43
-rw-r--r--files.py81
-rw-r--r--files.yaml36
-rw-r--r--runcmd.py84
-rw-r--r--runcmd.yaml13
-rw-r--r--src/ast.rs70
-rw-r--r--src/bin/sp-meta.rs11
-rw-r--r--src/codegen.rs10
-rw-r--r--subplot.md30
-rw-r--r--subplot.py145
-rw-r--r--subplot.yaml51
-rw-r--r--templates/bash/template.sh2
-rw-r--r--templates/python/template.py2
12 files changed, 303 insertions, 232 deletions
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<filename>\S+) has modification time (?P<y>\d+)-(?P<mon>\d+)-(?P<d>\d+) (?P<h>\d+):(?P<min>\d+):(?P<s>\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<filename>\S+) matches /(?P<regex>.+)/
+ function: file_matches
+ regex: true
+
+- then: file (?P<filename>\S+) contains "(?P<pattern>.+)"
+ 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<filenames>.+) exist
+ function: only_these_files_exist
+ regex: true
diff --git a/runcmd.py b/runcmd.py
new file mode 100644
index 0000000..b67c6bb
--- /dev/null
+++ 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
new file mode 100644
index 0000000..02e5ee1
--- /dev/null
+++ b/runcmd.yaml
@@ -0,0 +1,13 @@
+- then: exit code is non-zero
+ function: exit_code_nonzero
+
+- then: output matches /(?P<pattern>.+)/
+ function: stdout_contains
+ regex: true
+
+- then: stderr matches /(?P<pattern>.+)/
+ function: stderr_contains
+ regex: true
+
+- then: program finished successfully
+ function: exit_code_zero
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<PathBuf> {
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<String>,
- bindings_filename: Option<PathBuf>,
+ bindings_filenames: Vec<PathBuf>,
bindings: Bindings,
- functions_filename: Option<PathBuf>,
+ functions_filenames: Vec<PathBuf>,
template: Option<String>,
bibliographies: Vec<PathBuf>,
/// 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<String> {
}
}
-fn get_bindings_filename<P>(basedir: P, map: &Mapp) -> Result<Option<PathBuf>>
+fn get_bindings_filenames<P>(basedir: P, map: &Mapp) -> Vec<PathBuf>
where
P: AsRef<Path>,
{
- 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<P>(basedir: P, map: &Mapp) -> Result<Option<PathBuf>>
+fn get_functions_filenames<P>(basedir: P, map: &Mapp) -> Vec<PathBuf>
where
P: AsRef<Path>,
{
- 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<Option<String>> {
@@ -563,10 +554,13 @@ fn get_template_name(map: &Mapp) -> Result<Option<String>> {
}
}
-fn get_path(map: &Mapp, field: &str) -> Option<PathBuf> {
- match get_string(map, field) {
- None => None,
- Some(s) => Some(Path::new(&s).to_path_buf()),
+fn get_paths<P>(basedir: P, map: &Mapp, field: &str) -> Vec<PathBuf>
+where
+ P: AsRef<Path>,
+{
+ match map.get(field) {
+ None => vec![],
+ Some(v) => pathbufs(basedir, v),
}
}
@@ -687,11 +681,13 @@ mod test_join {
}
}
-fn get_bindings<P>(filename: P, bindings: &mut Bindings) -> Result<()>
+fn get_bindings<P>(filenames: &[P], bindings: &mut Bindings) -> Result<()>
where
P: AsRef<Path>,
{
- 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> {
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..ff1d702 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,12 @@ 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
+- 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<filename>\S+) has modification time (?P<y>\d+)-(?P<mon>\d+)-(?P<d>\d+) (?P<h>\d+):(?P<min>\d+):(?P<s>\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<filename>\S+) matches /(?P<regex>.+)/
- function: file_matches
- regex: true
-
-- then: file (?P<filename>\S+) contains "(?P<pattern>.+)"
- 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<pattern>.+)/
- function: stdout_matches
- regex: true
-
-- then: stderr matches /(?P<pattern>.+)/
- function: stderr_matches
- regex: true
-
- then: scenario "(?P<name>.+)" was run
function: scenario_was_run
regex: true
@@ -95,10 +51,3 @@
- then: cleanup for "(?P<keyword>given|when|then) (?P<name>.+)" was not run
function: cleanup_was_not_run
regex: true
-
-- then: program finished successfully
- function: exit_code_zero
-
-- then: only files (?P<filenames>.+) exist
- function: only_these_files_exist
- regex: true
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 }}