Compare two specs#
Diff two spec files so that the diff shows only what the specs state differently. A plain text diff also shows the order of declarations, spacing and the order of the terms in a sum. The canonical form is one fixed way to write a spec, and it removes those differences. Comparing two specs lists what the form sorts and what it keeps.
- Write one spec in the canonical form.
The command writes the form to stdout, or to a file with
-o canonical.yaml. A file the language refuses prints its message on
stderr and exits with status 1.
- Diff two files once. Give each file to the command, and diff the two outputs:
- Make
git diffshow the canonical form. Tell git which files are specs, and which command writes them out:
echo 'specs/*.yaml diff=mathspec' >> .gitattributes
git config diff.mathspec.textconv "python -m mathspec canonical"
The files in the repository stay as you wrote them, and only the diff
changes. A commit that writes sum(dispatch * cost) as
sum(cost * dispatch) then shows no difference, and a commit that changes a
coefficient shows one line:
objective:
sense: minimize
- expression: sum(cost * dispatch)
+ expression: sum((2 * cost) * dispatch)
Match only spec files in .gitattributes, because git runs the command on
every file the pattern matches, and a YAML file that is not a spec fails to
load.
- Keep specs in the canonical form in CI. Then a plain diff of the files
shows what the form shows, with no git setup.
--writerewrites a file in the form, and drops its YAML comments because the form holds none:
--check writes nothing, but exits with status 1 if the file is not in the
form, and names the rewrite:
spec.yaml is not in the canonical form. Run `python -m mathspec canonical --write spec.yaml` to rewrite it.
Check every spec, and fail the job if one of them fails:
status=0
for spec in specs/*.yaml; do python -m mathspec canonical --check "$spec" || status=1; done
exit $status
- Compare from Python where the comparison is one step of a longer
script.
to_yamlwrites the same text withcanonical=True: