Skip to content

Commit 45985bf

Browse files
Always close files (ReadDigraphs, WriteDigraphs) (#757)
* fix issues for read, add tests * add tests * close files with WriteDigraphs * fix ci * a little tidier * implement max's suggestion * fix tests * rm debugging lines
1 parent c8f001c commit 45985bf

2 files changed

Lines changed: 51 additions & 19 deletions

File tree

gap/io.gi

Lines changed: 27 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -402,7 +402,7 @@ end);
402402

403403
InstallGlobalFunction(ReadDigraphs,
404404
function(arg...)
405-
local nr, decoder, name, file, i, next, out;
405+
local nr, decoder, name, file, i, next, out, line;
406406

407407
# defaults
408408
nr := infinity;
@@ -474,8 +474,12 @@ function(arg...)
474474

475475
out := [];
476476
if NameFunction(decoder) in WholeFileDecoders then
477-
Add(out, decoder(IO_ReadUntilEOF(file)));
478-
next := IO_Nothing;
477+
line := IO_ReadUntilEOF(file);
478+
if IsString(arg[1]) then
479+
IO_Close(file);
480+
fi;
481+
Add(out, decoder(line));
482+
return out;
479483
else
480484
next := decoder(file);
481485
fi;
@@ -495,7 +499,7 @@ end);
495499
InstallGlobalFunction(WriteDigraphs,
496500
function(arg...)
497501
local name, digraphs, encoder, mode, splitname, compext, g6sum, s6sum, v, e,
498-
dg6sum, ds6sum, file, D, i;
502+
dg6sum, ds6sum, file, i, D, oldOnBreak, CloseAndCleanup, OnBreakWithCleanup;
499503

500504
# defaults
501505
encoder := fail;
@@ -606,6 +610,9 @@ function(arg...)
606610
fi;
607611
file := DigraphFile(name, encoder, mode);
608612
if NameFunction(file!.coder) in WholeFileEncoders and file!.mode <> "w" then
613+
if IsString(arg[1]) then
614+
IO_Close(file);
615+
fi;
609616
ErrorNoReturn(NameFunction(file!.coder), " is a whole file ",
610617
"encoder and so the argument <mode> must be \"w\".");
611618
fi;
@@ -619,8 +626,21 @@ function(arg...)
619626
fi;
620627
fi;
621628

622-
encoder := file!.coder;
629+
oldOnBreak := OnBreak;
630+
CloseAndCleanup := function()
631+
if IsString(arg[1]) then
632+
IO_Close(file);
633+
fi;
634+
OnBreak := oldOnBreak;
635+
end;
636+
637+
OnBreakWithCleanup := function()
638+
CloseAndCleanup();
639+
OnBreak();
640+
end;
641+
OnBreak := OnBreakWithCleanup;
623642

643+
encoder := file!.coder;
624644
if NameFunction(encoder) in WholeFileEncoders then
625645
if Length(digraphs) > 1 then
626646
Info(InfoWarning, 1, "the encoder ", NameFunction(encoder),
@@ -634,10 +654,7 @@ function(arg...)
634654
od;
635655
fi;
636656

637-
if IsString(arg[1]) then
638-
IO_Close(file);
639-
fi;
640-
657+
CloseAndCleanup();
641658
return IO_OK;
642659
end);
643660

@@ -2020,16 +2037,7 @@ end);
20202037
# 4. Encoders
20212038
################################################################################
20222039
InstallMethod(WriteDIMACSDigraph, "for a digraph", [IsString, IsDigraph],
2023-
function(name, D)
2024-
local file;
2025-
file := IO_CompressedFile(UserHomeExpand(name), "w");
2026-
if file = fail then
2027-
ErrorNoReturn("cannot open the file given as the 1st argument <name>,");
2028-
fi;
2029-
IO_Write(file, DIMACSString(D));
2030-
IO_Close(file);
2031-
return IO_OK;
2032-
end);
2040+
{name, D} -> WriteDigraphs(name, D, DIMACSString, "w"));
20332041

20342042
InstallMethod(DIMACSString, "for a digraph", [IsDigraph],
20352043
function(D)

tst/standard/io.tst

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,8 @@ gap> LoadPackage("digraphs", false);;
1212

1313
#
1414
gap> DIGRAPHS_StartTest();
15+
gap> files := ShallowCopy(IO.OpenFiles);;
16+
gap> oldOnBreak := OnBreak;;
1517

1618
# DigraphFromGraph6String and Graph6String
1719
gap> DigraphFromGraph6String("?");
@@ -276,6 +278,11 @@ gap> gr = ReadDigraphs(filename);
276278
true
277279
gap> gr[3] := Digraph([[1, 2], [1, 2]]);
278280
<immutable digraph with 2 vertices, 4 edges>
281+
gap> WriteDigraphs(filename, Digraph([[2], []]), Graph6String);
282+
Error, the argument <D> must be a symmetric digraph with no loops or multiple \
283+
edges,
284+
gap> OnBreak := oldOnBreak;;
285+
gap> IO_Close(IO.OpenFiles[Length(IO.OpenFiles)]);;
279286
gap> filename := Concatenation(DIGRAPHS_Dir(), "/tst/out/test.s6.bz2");;
280287
gap> WriteDigraphs(filename, gr, "w");
281288
IO_OK
@@ -676,6 +683,8 @@ Error, no method found! For debugging hints type ?Recovery from NoMethodFound
676683
Error, no 1st choice method found for `WriteDIMACSDigraph' on 2 arguments
677684
gap> WriteDIMACSDigraph("file", ChainDigraph(2));
678685
Error, the argument <D> must be a symmetric digraph,
686+
gap> OnBreak := oldOnBreak;;
687+
gap> IO_Close(IO.OpenFiles[Length(IO.OpenFiles)]);;
679688
gap> WriteDIMACSDigraph(filename, gr);
680689
Error, cannot open the file given as the 1st argument <name>,
681690
gap> filename := "tmp.gz";;
@@ -892,6 +901,9 @@ gap> filename := Concatenation(DIGRAPHS_Dir(), "/tst/out/more.dimacs");;
892901
gap> WriteDigraphs(filename, gr, "w");;
893902
gap> ReadDigraphs(filename)[1] = gr;
894903
true
904+
gap> WriteDigraphs(filename, gr);
905+
Error, DIMACSString is a whole file encoder and so the argument <mode> must be\
906+
"w".
895907
gap> DigraphVertexLabels(gr) = [1 .. 3];
896908
true
897909

@@ -950,6 +962,10 @@ gap> DreadnautString(1);
950962
Error, the first argument <D> must be a digraph
951963
gap> DreadnautString(D, 1);
952964
Error, the second argument <partition> must be a list
965+
gap> WriteDigraphs(filename, Digraph([]), "w");
966+
Error, the argument <D> must be a digraph with at least one vertex
967+
gap> OnBreak := oldOnBreak;;
968+
gap> IO_Close(IO.OpenFiles[Length(IO.OpenFiles)]);;
953969
gap> WriteDigraphs(filename, D, "w");
954970
IO_OK
955971

@@ -1045,6 +1061,13 @@ gap> DigraphFromDreadnautString("$=1n3dg\n1 : 2 3.\nf=[1:\n:]");
10451061
Error, Invalid range 1 : ':' in partition specification (line 3)
10461062
gap> DigraphFromDreadnautString("$=1n3dg\n1 : 2 3.\nf=[1\nf=2");
10471063
Error, Unexpected character 'f' in partition specification (line 4)
1064+
gap> IO_Close(file);;
1065+
1066+
# Ensure all files introduced by tests are closed
1067+
gap> IO.OpenFiles = files;
1068+
true
1069+
gap> OnBreak = oldOnBreak;
1070+
true
10481071
10491072
# DIGRAPHS_UnbindVariables
10501073
gap> Unbind(D);
@@ -1066,6 +1089,7 @@ gap> Unbind(rdgr);
10661089
gap> Unbind(read);
10671090
gap> Unbind(str);
10681091
gap> Unbind(x);
1092+
gap> Unbind(files);
10691093
10701094
#
10711095
gap> DIGRAPHS_StopTest();

0 commit comments

Comments
 (0)