32
32
)
33
33
from pycommons .io .csv import CsvReader as CsvReaderBase
34
34
from pycommons .io .csv import CsvWriter as CsvWriterBase
35
- from pycommons .io .path import Path , file_path , line_writer
35
+ from pycommons .io .path import Path , file_path , write_lines
36
36
from pycommons .strings .string_conv import (
37
37
int_or_none_to_str ,
38
38
num_or_none_to_str ,
@@ -459,9 +459,7 @@ def to_csv(results: Iterable[EndResult], file: str) -> Path:
459
459
logger (f"Writing end results to CSV file { path !r} ." )
460
460
path .ensure_parent_dir_exists ()
461
461
with path .open_for_write () as wt :
462
- consumer : Final [Callable [[str ], None ]] = line_writer (wt )
463
- for r in CsvWriter .write (results ):
464
- consumer (r )
462
+ write_lines (CsvWriter .write (results ), wt )
465
463
logger (f"Done writing end results to CSV file { path !r} ." )
466
464
return path
467
465
@@ -722,12 +720,13 @@ def parse_row(self, data: list[str]) -> EndResult:
722
720
class EndResultLogParser [T ](SetupAndStateParser [T ]):
723
721
"""The internal log parser class."""
724
722
725
- def get_result (self ) -> T :
723
+ def _parse_file (self , file : Path ) -> T :
726
724
"""
727
725
Get the parsing result.
728
726
729
727
:returns: the :class:`EndResult` instance
730
728
"""
729
+ super ()._parse_file (file )
731
730
return cast (T , EndResult (self .algorithm ,
732
731
self .instance ,
733
732
self .objective ,
@@ -794,16 +793,13 @@ def __init__(
794
793
self .__hit_goal : bool = False
795
794
self .__state : int = 0
796
795
797
- def before_get_result (self ) -> None :
798
- """Before we get the result."""
796
+ def _parse_file (self , file : Path ) -> EndResult :
797
+ super (). _parse_file ( file )
799
798
if self .__state != 2 :
800
799
raise ValueError (
801
800
"Illegal state, log file must have a "
802
801
f"{ SECTION_PROGRESS !r} section." )
803
802
self .__state = 0
804
- return super ().before_get_result ()
805
-
806
- def get_result (self ) -> EndResult :
807
803
__hit_goal = self .__hit_goal
808
804
stop_fes : int = self .__stop_fes
809
805
stop_ms : int = self .__stop_ms
@@ -832,8 +828,12 @@ def get_result(self) -> EndResult:
832
828
max_time_millis = _join_goals (
833
829
self .__limit_ms_n , self .max_time_millis , min ))
834
830
835
- def after_get_result (self ) -> None :
836
- """Cleanup."""
831
+ def _end_parse_file (self , file : Path ) -> None :
832
+ """
833
+ Cleanup.
834
+
835
+ :param file: the file that was parsed.
836
+ """
837
837
self .__stop_fes = None
838
838
self .__stop_ms = None
839
839
self .__stop_f = None
@@ -846,65 +846,63 @@ def after_get_result(self) -> None:
846
846
self .__limit_f_n = None
847
847
self .__limit_f = - inf
848
848
self .__hit_goal = False
849
- super ().after_get_result ()
850
-
851
- def start_parse_file (self , root : Path , current : Path ) -> bool :
852
- if super ().start_parse_file (root , current ):
853
- if (self .algorithm is None ) or (self .instance is None ):
854
- raise ValueError (
855
- f"Invalid state: algorithm={ self .algorithm !r} , "
856
- f"instance={ self .instance !r} ." )
857
-
858
- fes = self .__src_limit_fes (self .algorithm , self .instance ) \
859
- if callable (self .__src_limit_fes ) else self .__src_limit_fes
860
- self .__limit_fes_n = None if fes is None else \
861
- check_int_range (fes , "limit_fes" , 1 , 1_000_000_000_000_000 )
862
- self .__limit_fes = inf if self .__limit_fes_n is None \
863
- else self .__limit_fes_n
864
-
865
- time = self .__src_limit_ms (self .algorithm , self .instance ) \
866
- if callable (self .__src_limit_ms ) else self .__src_limit_ms
867
- self .__limit_ms_n = None if time is None else \
868
- check_int_range (time , "__limit_ms" , 1 , 1_000_000_000_000 )
869
- self .__limit_ms = inf if self .__limit_ms_n is None \
870
- else self .__limit_ms_n
871
-
872
- self .__limit_f_n = self .__src_limit_f (
873
- self .algorithm , self .instance ) \
874
- if callable (self .__src_limit_f ) else self .__src_limit_f
875
- if self .__limit_f_n is not None :
876
- if not isinstance (self .__limit_f_n , int | float ):
877
- raise type_error (self .__limit_f_n , "limit_f" , (
878
- int , float ))
879
- if not isfinite (self .__limit_f_n ):
880
- if self .__limit_f_n <= - inf :
881
- self .__limit_f_n = None
882
- else :
883
- raise ValueError (
884
- f"invalid limit f={ self .__limit_f_n } for "
885
- f"{ self .algorithm } on { self .instance } " )
886
- self .__limit_f = - inf if self .__limit_f_n is None \
887
- else self .__limit_f_n
888
- return True
889
- return False
890
-
891
- def start_section (self , title : str ) -> bool :
849
+ super ()._end_parse_file (file )
850
+
851
+ def _start_parse_file (self , file : Path ) -> None :
852
+ super ()._start_parse_file (file )
853
+ a : Final [str | None ] = self .algorithm
854
+ i : Final [str | None ] = self .instance
855
+
856
+ fes = self .__src_limit_fes (a , i ) if (a and i and callable (
857
+ self .__src_limit_fes )) else (
858
+ self .__src_limit_fes if isinstance (self .__src_limit_fes , int )
859
+ else None )
860
+ self .__limit_fes_n = None if fes is None else \
861
+ check_int_range (fes , "limit_fes" , 1 , 1_000_000_000_000_000 )
862
+ self .__limit_fes = inf if self .__limit_fes_n is None \
863
+ else self .__limit_fes_n
864
+
865
+ time = self .__src_limit_ms (a , i ) if (a and i and callable (
866
+ self .__src_limit_ms )) else (
867
+ self .__src_limit_ms if isinstance (self .__src_limit_ms , int )
868
+ else None )
869
+ self .__limit_ms_n = None if time is None else \
870
+ check_int_range (time , "__limit_ms" , 1 , 1_000_000_000_000 )
871
+ self .__limit_ms = inf if self .__limit_ms_n is None \
872
+ else self .__limit_ms_n
873
+
874
+ self .__limit_f_n = self .__src_limit_f (a , i ) if (a and i and callable (
875
+ self .__src_limit_f )) else (
876
+ self .__src_limit_f if isinstance (self .__src_limit_f , int | float )
877
+ else None )
878
+ if self .__limit_f_n is not None :
879
+ if not isinstance (self .__limit_f_n , int | float ):
880
+ raise type_error (self .__limit_f_n , "limit_f" , (
881
+ int , float ))
882
+ if not isfinite (self .__limit_f_n ):
883
+ if self .__limit_f_n <= - inf :
884
+ self .__limit_f_n = None
885
+ else :
886
+ raise ValueError (
887
+ f"invalid limit f={ self .__limit_f_n } for "
888
+ f"{ self .algorithm } on { self .instance } " )
889
+ self .__limit_f = - inf if self .__limit_f_n is None \
890
+ else self .__limit_f_n
891
+
892
+ def _start_section (self , title : str ) -> bool :
892
893
if title == SECTION_PROGRESS :
893
894
if self .__state != 0 :
894
895
raise ValueError (f"Already did section { title } ." )
895
896
self .__state = 1
896
897
return True
897
- return super ().start_section (title )
898
-
899
- def needs_more_lines (self ) -> bool :
900
- return (self .__state < 2 ) or super ().needs_more_lines ()
898
+ return super ()._start_section (title )
901
899
902
- def lines (self , lines : list [str ]) -> bool :
903
- if not isinstance (lines , list ):
904
- raise type_error (lines , "lines" , list )
900
+ def _needs_more_lines (self ) -> bool :
901
+ return (self .__state < 2 ) or super ()._needs_more_lines ()
905
902
903
+ def _lines (self , lines : list [str ]) -> bool :
906
904
if self .__state != 1 :
907
- return super ().lines (lines )
905
+ return super ()._lines (lines )
908
906
self .__state = 2
909
907
910
908
n_rows = len (lines )
@@ -978,7 +976,7 @@ def lines(self, lines: list[str]) -> bool:
978
976
self .__stop_f = stop_f
979
977
self .__stop_li_fe = stop_li_fe
980
978
self .__stop_li_ms = stop_li_ms
981
- return self .needs_more_lines ()
979
+ return self ._needs_more_lines ()
982
980
983
981
984
982
def from_logs (
0 commit comments