SSL utils.gi
Interaktion und Portierbarkeitunbekannt
|
|
#############################################################################
##
## utils.gi
## Copyright (C) 2013-19 James D. Mitchell
##
## Licensing information can be found in the README file of this package.
##
#############################################################################
##
## This file contains some utilities for use with the Digraphs package.
#############################################################################
# Internal stuff
#############################################################################
BindGlobal("DIGRAPHS_DocXMLFiles",
["../PackageInfo.g",
"attr.xml",
"cliques.xml",
"constructors.xml",
"digraph.xml",
"display.xml",
"examples.xml",
"grahom.xml",
"grape.xml",
"io.xml",
"isomorph.xml",
"labels.xml",
"oper.xml",
"orbits.xml",
"planar.xml",
"prop.xml",
"utils.xml",
"weights.xml"]);
BindGlobal("DIGRAPHS_TestRec", rec());
MakeReadWriteGlobal("DIGRAPHS_TestRec");
InstallGlobalFunction(DIGRAPHS_StartTest,
function()
DIGRAPHS_TestRec.InfoLevelInfoWarning := InfoLevel(InfoWarning);
DIGRAPHS_TestRec.InfoLevelInfoDigraphs := InfoLevel(InfoDigraphs);
SetInfoLevel(InfoWarning, 0);
SetInfoLevel(InfoDigraphs, 0);
return;
end);
InstallGlobalFunction(DIGRAPHS_StopTest,
function()
SetInfoLevel(InfoWarning, DIGRAPHS_TestRec.InfoLevelInfoWarning);
SetInfoLevel(InfoDigraphs, DIGRAPHS_TestRec.InfoLevelInfoDigraphs);
# Wipe internal structures for homos and cliques
DIGRAPHS_FREE_HOMOS_DATA();
DIGRAPHS_FREE_CLIQUES_DATA();
return;
end);
InstallGlobalFunction(DIGRAPHS_Test,
fname -> DIGRAPHS_RunTest({} -> Test(fname, rec(showProgress := false))));
# The parameter <func> should be a 0-argument function which returns true or
# false.
InstallGlobalFunction(DIGRAPHS_RunTest,
function(func)
local nauty, reset, pass;
nauty := not DIGRAPHS_UsingBliss;
reset := function()
local old_level;
old_level := InfoLevel(InfoWarning);
SetInfoLevel(InfoWarning, 0);
if nauty then
DigraphsUseNauty();
else
DigraphsUseBliss();
fi;
SetInfoLevel(InfoWarning, old_level);
end;
Print("\033[1m");
DigraphsUseBliss();
Print("\033[0m");
if not func() then
reset();
return false;
fi;
if DIGRAPHS_NautyAvailable then
Print("\033[1m");
DigraphsUseNauty();
Print("\033[0m");
if not func() then
reset();
return false;
fi;
Print("\033[1m");
DigraphsUseBliss();
Info(InfoWarning,
1,
". . . and pretending that NautyTracesInterface is not ",
"available . . .");
Print("\033[0m");
MakeReadWriteGlobal("DIGRAPHS_NautyAvailable");
DIGRAPHS_NautyAvailable := false;
MakeReadOnlyGlobal("DIGRAPHS_NautyAvailable");
pass := func();
MakeReadWriteGlobal("DIGRAPHS_NautyAvailable");
DIGRAPHS_NautyAvailable := true;
MakeReadOnlyGlobal("DIGRAPHS_NautyAvailable");
if not pass then
reset();
return false;
fi;
fi;
reset();
return true;
end);
InstallGlobalFunction(DIGRAPHS_ManualExamples,
function()
if Filename(DirectoriesPackageLibrary("digraphs", "doc"),
"main.xml") = fail then
# The file main.xml only exists if AutoDoc has been run.
DigraphsMakeDoc();
fi;
return ExtractExamples(DirectoriesPackageLibrary("digraphs", "doc"),
"main.xml", DIGRAPHS_DocXMLFiles, "Single");
end);
InstallGlobalFunction(DIGRAPHS_Dir, {} -> GAPInfo.PackagesLoaded.digraphs[1]);
#############################################################################
# User facing stuff
#############################################################################
InstallGlobalFunction(DigraphsTestAll,
function()
DigraphsMakeDoc();
Print("\n");
if not DigraphsTestInstall() then
Print("Abort: DigraphsTestInstall failed . . . \n");
return false;
elif not DigraphsTestStandard() then
Print("Abort: DigraphsTestStandard failed . . . \n");
return false;
fi;
return DIGRAPHS_RunTest(DigraphsTestManualExamples);
end);
InstallGlobalFunction(DigraphsTestInstall,
function()
return DIGRAPHS_RunTest(function()
return Test(Filename(DirectoriesPackageLibrary("digraphs", "tst"),
"testinstall.tst"));
end);
end);
InstallGlobalFunction(DigraphsTestStandard,
function(arg...)
local opts, dir;
if Length(arg) = 1 and IsRecord(arg[1]) then
opts := ShallowCopy(arg[1]);
elif Length(arg) <> 0 then
ErrorNoReturn("there must be no arguments, or the argument ",
"must be a record");
else
opts := rec();
fi;
if not IsBound(opts.suppressStatusMessage) then
opts.suppressStatusMessage := true;
fi;
if not IsBound(opts.earlyStop) then
opts.earlyStop := true;
fi;
if not IsBound(opts.testOptions) or not IsRecord(opts.testOptions) then
opts.testOptions := rec();
fi;
if not IsBound(opts.testOptions.showProgress) then
opts.testOptions.showProgress := false;
fi;
dir := DirectoriesPackageLibrary("digraphs", "tst/standard/");
return DIGRAPHS_RunTest({} -> TestDirectory(dir, opts));
end);
InstallGlobalFunction(DigraphsTestExtreme,
function(arg...)
local file, opts, dir;
file := Filename(DirectoriesPackageLibrary("digraphs", "digraphs-lib"),
"extreme.d6.gz");
if file = fail then
ErrorNoReturn("the file pkg/digraphs/digraphs-lib/extreme.d6.gz is ",
"required for these tests to run. Please install the ",
"'digraphs-lib' archive from ",
"https://digraphs.github.io/Digraphs/ ",
"and try again,");
fi;
if Length(arg) = 1 and IsRecord(arg[1]) then
opts := ShallowCopy(arg[1]);
elif Length(arg) <> 0 then
ErrorNoReturn("there must be no arguments, or the argument ",
"must be a record");
else
opts := rec();
fi;
if not IsBound(opts.suppressStatusMessage) then
opts.suppressStatusMessage := true;
fi;
if not IsBound(opts.earlyStop) then
opts.earlyStop := true;
fi;
if not IsBound(opts.testOptions) or not IsRecord(opts.testOptions) then
opts.testOptions := rec();
fi;
if not IsBound(opts.testOptions.showProgress) then
opts.testOptions.showProgress := false;
fi;
if not IsBound(opts.testOptions.showProgress) then
opts.suppressStatusMessage := "some";
fi;
dir := DirectoriesPackageLibrary("digraphs", "tst/extreme/");
return DIGRAPHS_RunTest({} -> TestDirectory(dir, opts));
end);
InstallGlobalFunction(DigraphsMakeDoc,
function()
local fname;
fname := Filename(DirectoriesPackageLibrary("digraphs", ""), "makedoc.g");
Read(fname);
end);
InstallGlobalFunction(DigraphsTestManualExamples,
function(arg...)
local exlists, indices, omit, oldscr, passed, pad, total, l, sp, bad, s,
start_time, test, end_time, elapsed, pex, str, j, ex, i, first;
exlists := DIGRAPHS_ManualExamples();
if Length(arg) > 0 then
if Length(arg) = 1 and IsList(arg[1]) then
return CallFuncList(DigraphsTestManualExamples, arg[1]);
elif ForAll(arg, x -> IsPosInt(x) and x <= Length(exlists)) then
indices := arg;
else
ErrorNoReturn("the arguments must be positive integers or a list of ",
"positive integers not greater than ", Length(exlists),
",");
fi;
else
omit := DIGRAPHS_OmitFromTests();
if Length(omit) > 0 then
if Length(omit) = 1 then
Print("# not testing examples containing the string ");
else
Print("# not testing examples containing the strings: ");
fi;
first := true;
for str in omit do
exlists := Filtered(exlists,
x -> PositionSublist(x[1][1], str) = fail);
if first then
first := false;
else
Print(", ");
fi;
Print("\"", str, "\"");
od;
Print(" . . .\n");
fi;
indices := [1 .. Length(exlists)];
fi;
DIGRAPHS_StartTest();
oldscr := SizeScreen();
SizeScreen([72, oldscr[2]]);
passed := true;
pad := function(nr)
nr := Length(String(Length(exlists))) - Length(String(nr)) + 1;
return List([1 .. nr], x -> ' ');
end;
total := 0;
for j in indices do
l := exlists[j];
Print("# Running example ", j, pad(j), " . . .");
START_TEST("");
l[1][1] := StripBeginEnd(l[1][1], "\n");
for ex in l do
sp := SplitString(ex[1], "\n", "");
bad := Filtered([1 .. Length(sp)], i -> Length(sp[i]) > 72);
s := InputTextString(ex[1]);
start_time := IO_gettimeofday();
test := Test(s, rec(compareFunction := "uptowhitespace",
ignoreComments := false,
width := 72,
EQ := EQ,
reportDiff := Ignore,
showProgress := false));
end_time := IO_gettimeofday();
CloseStream(s);
elapsed := (end_time.tv_sec - start_time.tv_sec) * 1000
+ Int((end_time.tv_usec - start_time.tv_usec) / 1000);
total := total + elapsed;
pex := TEST.lastTestData;
Print(" msecs: ", elapsed, "\n");
if Length(bad) > 0 then
Print("\033[31m# WARNING: Overlong lines ", bad, " in\n",
ex[2][1], ":", ex[2][2], "\033[0m\n");
passed := false;
fi;
if test = false then
for i in [1 .. Length(pex[1])] do
if EQ(pex[2][i], pex[4][i]) <> true then
Print("\033[31m########> Diff in:\n",
"# ", ex[2][1], ":", ex[2][2],
"\n# Input is:\n");
PrintFormattedString(pex[1][i]);
Print("# Expected output:\n");
PrintFormattedString(pex[2][i]);
Print("# But found:\n");
PrintFormattedString(pex[4][i]);
Print("########\033[0m\n");
passed := false;
fi;
od;
fi;
od;
od;
SizeScreen(oldscr);
DIGRAPHS_StopTest();
if Length(indices) > 1 then
Print("Total: ", total, " msecs\n");
fi;
return passed;
end);
# The following is based on doc/ref/testconsistency.g
# Detect which ManSection should be used to document obj. Returns one of
# "Func", "Oper", "Meth", "Filt", "Prop", "Attr", "Var", "Fam", "InfoClass"
# See PRINT_OPERATION where some of the code below is borrowed
DIGRAPHS_ManSectionType := function(op)
local class, flags, types, catok, repok, propok, seenprop, t;
if IsInfoClass(op) then
return "InfoClass";
elif IsFamily(op) then
return "Fam";
elif not IsFunction(op) then
return "Var";
elif IsFunction(op) and not IsOperation(op) then
return "Func";
elif IsOperation(op) then
class := "Oper";
if IS_IDENTICAL_OBJ(op, IS_OBJECT) then
class := "Filt";
elif IsFilter(op) then
class := "Filt";
flags := TRUES_FLAGS(FLAGS_FILTER(op));
types := INFO_FILTERS{flags};
catok := true;
repok := true;
propok := true;
seenprop := false;
for t in types do
if not t in FNUM_REPS then
repok := false;
fi;
if not t in FNUM_CATS then
catok := false;
fi;
if not t in FNUM_PROS and not t in FNUM_TPRS then
propok := false;
fi;
if t in FNUM_PROS then
seenprop := true;
fi;
od;
if seenprop and propok then
class := "Prop";
elif catok then
class := "Filt";
# in PRINT_OPERATION - "Category";
elif repok then
class := "Filt";
# in PRINT_OPERATION - "Representation";
fi;
elif Tester(op) <> false then
# op is an attribute
class := "Attr";
fi;
return class;
else
return fail;
fi;
end;
# Checks whether ManSections are using the right kind of elements
DIGRAPHS_CheckManSectionTypes := function(doc, verbose...)
local display_warnings, types, r, x, errcount, name, pos, obj, man, y, yint,
referrcount, warncount, type, matches, match, matches2, stats,
elt, t, s;
if Length(verbose) = 0 then
display_warnings := false;
else
display_warnings := verbose[1];
fi;
types := ["Func", "Oper", "Meth", "Filt", "Prop", "Attr", "Var", "Fam",
"InfoClass"];
r := ParseTreeXMLString(doc[1]);
CheckAndCleanGapDocTree(r);
x := XMLElements(r, types);
errcount := 0;
Print("****************************************************************\n");
Print("*** Checking types in ManSections \n");
Print("****************************************************************\n");
for elt in x do
name := elt.attributes.Name;
if not name in ["IsBound", "Unbind", "Info", "Assert", "TryNextMethod",
"QUIT", "-infinity"] then
if EvalString(Concatenation("IsBound(", name, ")")) <> true then
pos := OriginalPositionDocument(doc[2], elt.start);
Print(pos[1], ":", pos[2], " : ", name, " is unbound \n");
errcount := errcount + 1;
else
obj := EvalString(name);
man := DIGRAPHS_ManSectionType(obj);
# we allow to use "Meth" for "Oper" but probably should issue a warning
# if there is no at least one "Oper" for any "Meth"
if (man <> elt.name)
and not (man in ["Attr", "Prop", "Oper"] and elt.name = "Meth") then
pos := OriginalPositionDocument(doc[2], elt.start);
Print(pos[1], ":", pos[2], " : ", name, " uses ", elt.name,
" instead of ", man, "\n");
errcount := errcount + 1;
fi;
fi;
fi;
od;
Print("****************************************************************\n");
Print("*** Checking types in cross-references \n");
Print("****************************************************************\n");
y := XMLElements(r, ["Ref"]);
Print("Found ", Length(y), " Ref elements ");
yint := Filtered(y, elt ->
not IsBound(elt.attributes.BookName)
or (IsBound(elt.attributes.BookName)
and elt.attributes.BookName = "ref"));
Print("including ", Length(yint), " within the Reference manual\n");
y := Filtered(yint, elt -> ForAny(types, t -> IsBound(elt.attributes.(t))));
referrcount := 0;
warncount := 0;
for elt in y do
type := First(types, t -> IsBound(elt.attributes.(t)));
if type <> fail then
matches := Filtered(x, t -> t.attributes.Name = elt.attributes.(type));
if Length(matches) = 0 then
pos := OriginalPositionDocument(doc[2], elt.start);
Print(pos[1], ":", pos[2], " : no match for ", type, " := ",
elt.attributes.(type), "\n");
referrcount := referrcount + 1;
continue;
elif Length(matches) = 1 then
match := matches[1];
elif IsBound(elt.attributes.Label) then
matches := Filtered(matches, t -> IsBound(t.attributes.Label));
matches := Filtered(matches, t -> t.attributes.Label =
elt.attributes.Label);
if Length(matches) > 1 then
ErrorNoReturn("Multiple labels - this should not happen!");
fi;
match := matches[1];
else
matches2 := Filtered(matches, t -> not IsBound(t.attributes.Label));
if Length(matches2) = 0 then
pos := OriginalPositionDocument(doc[2], elt.start);
Print(pos[1], ":", pos[2],
" : no match <wrong type or missing label?> for ", type, " := ",
elt.attributes.(type), "\n");
Print(" Suggestions: \n");
matches := Filtered(matches, t -> IsBound(t.attributes.Label));
for t in matches do
Print("Use ", t.name, " with Label := \"", t.attributes.Label,
"\" <for Arg := \"", t.attributes.Arg, "\">\n");
od;
referrcount := referrcount + 1;
continue;
elif Length(matches2) > 1 then
ErrorNoReturn("Multiple labels - this should not happen!");
else
match := matches[1];
fi;
fi;
if match.name <> type then
pos := OriginalPositionDocument(doc[2], elt.start);
if display_warnings then
Print(pos[1], ":", pos[2], "\n\tRef to ", elt.attributes.(type),
" uses ", type, " instead of ", match.name, "\n");
fi;
warncount := warncount + 1;
fi;
fi;
od;
Print("****************************************************************\n");
stats := Collected(List(x, elt -> elt.name));
Print("Selected ", Length(x), " ManSections of the following types:\n");
for s in stats do
Print(s[1], " - ", s[2], "\n");
od;
Print("Found ", errcount, " errors in ManSection types \n");
Print("Selected ", Length(y), " Ref elements referring to ManSections \n");
Print("Found ", referrcount, " errors and ", warncount,
" warnings in Ref elements \n");
if display_warnings then
Print("To suppress warnings, use DIGRAPHS_CheckManSectionTypes<doc,false> ",
"or with one argument\n");
else
Print("To show warnings, use DIGRAPHS_CheckManSectionTypes<doc,true); \n");
fi;
Print("****************************************************************\n");
return errcount = 0;
end;
DIGRAPHS_CheckDocCoverage := function(doc)
local r, x, with, without, mansect, pos, y;
r := ParseTreeXMLString(doc[1]);
CheckAndCleanGapDocTree(r);
x := XMLElements(r, ["ManSection"]);
with := 0;
without := 0;
Print("****************************************************************\n");
Print("*** Looking for ManSections having no examples \n");
Print("****************************************************************\n");
for mansect in x do
pos := OriginalPositionDocument(doc[2], mansect.start);
y := XMLElements(mansect, ["Example"]);
if Length(y) = 0 then
if IsBound(mansect.content[1].attributes) and
IsBound(mansect.content[1].attributes.Name) then
Print(pos[1], ":", pos[2], " : ", mansect.content[1].attributes.Name);
elif IsBound(mansect.content[2].attributes) and
IsBound(mansect.content[2].attributes.Name) then
Print(pos[1], ":", pos[2], " : ", mansect.content[2].attributes.Name);
else
Print(pos[1], ":", pos[2], " : ",
mansect.content[1].content[1].content);
fi;
without := without + 1;
Print("\n");
else
with := with + 1;
fi;
od;
Print("****************************************************************\n");
Print("*** Doc coverage report \n");
Print("****************************************************************\n");
Print(Length(x), " mansections \n");
Print(with, " with examples \n");
Print(without, " without examples \n");
end;
DIGRAPHS_CheckManualConsistency := function()
local doc;
doc := ComposedXMLString(DirectoriesPackageLibrary("digraphs", "/doc"),
"main.xml",
DIGRAPHS_DocXMLFiles,
true);
DIGRAPHS_CheckDocCoverage(doc);
return DIGRAPHS_CheckManSectionTypes(doc, true);
end;
InstallGlobalFunction(DIGRAPHS_BlistNumber,
function(nr, n)
local x, q, i;
x := BlistList([1 .. n], []);
nr := nr - 1; # to be in [0 .. 2 ^ n - 1]
for i in [n, n - 1 .. 1] do
q := nr mod 2;
if q = 0 then
x[i] := false;
else
x[i] := true;
fi;
nr := (nr - q) / 2;
od;
return x;
end);
InstallGlobalFunction(DIGRAPHS_NumberBlist,
function(blist)
local n, nr, i;
n := Length(blist);
nr := 0;
for i in [1 .. n] do
if blist[i] then
nr := 2 * nr + 1;
else
nr := 2 * nr;
fi;
od;
return nr + 1; # to be in [1 .. 2 ^ n]
end);
InstallGlobalFunction(DError,
function(arg...)
local msg;
if not (IsString(arg[1]) or IsList(arg[1])) then
Error("expected a string or a list as the 1st argument");
elif IsList(arg[1]) and not ForAll(arg[1], IsString) then
Error("expected a list of strings as the 1st argument");
elif IsList(arg[1]) then
arg[1] := Concatenation(arg[1]);
fi;
msg := CallFuncList(StringFormatted, arg);
RemoveCharacters(msg, "\\\n");
ErrorInner(
rec(context := ParentLVars(GetCurrentLVars()),
mayReturnVoid := false,
mayReturnObj := false,
lateMessage := "type 'quit;' to quit to outer loop",
printThisStatement := false),
[msg]);
end);
[ Verzeichnis aufwärts0.57unsichere Verbindung
Übersetzung europäischer Sprachen durch Browser
]
|
2026-03-28
|