1- import re
21from dataclasses import dataclass
3- from typing import Optional
2+
3+ from bughog .version_control .version import Version
44
55
66@dataclass (frozen = True )
77class ExperimentResult :
8- executable_version : Optional [ str ]
9- executable_origin : Optional [ str ]
8+ executable_version : Version | None
9+ executable_origin : str | None
1010 state : dict
1111 raw_results : dict
1212 result_variables : set [tuple [str , str ]]
@@ -17,7 +17,7 @@ def is_reproduced(self) -> bool:
1717 return self .poc_is_reproduced (self .result_variables )
1818
1919 @staticmethod
20- def poc_is_reproduced (result_variables : Optional [ set [tuple [str , str ]]] ) -> bool :
20+ def poc_is_reproduced (result_variables : set [tuple [str , str ]] | None ) -> bool :
2121 if result_variables is None :
2222 return False
2323 for key , value in result_variables :
@@ -26,7 +26,7 @@ def poc_is_reproduced(result_variables: Optional[set[tuple[str, str]]]) -> bool:
2626 return False
2727
2828 @staticmethod
29- def poc_passed_sanity_check (result_variables : Optional [ set [tuple [str , str ]]] ) -> bool :
29+ def poc_passed_sanity_check (result_variables : set [tuple [str , str ]] | None ) -> bool :
3030 if result_variables is None :
3131 return False
3232 for key , value in result_variables :
@@ -35,7 +35,7 @@ def poc_passed_sanity_check(result_variables: Optional[set[tuple[str, str]]]) ->
3535 return False
3636
3737 @staticmethod
38- def poc_is_dirty (result_variables : Optional [ set [tuple [str , str ]]] ) -> bool :
38+ def poc_is_dirty (result_variables : set [tuple [str , str ]] | None ) -> bool :
3939 """
4040 Returns whether the poc is dirty: it is not reproduced and the sanity check did not succeed.
4141 """
@@ -48,32 +48,14 @@ def padded_subject_version(self) -> str:
4848 """
4949 Returns a zero-padded version string derived from the executable's version,
5050 suitable for lexicographic comparison.
51-
52- Each dot-separated numeric segment is left-padded with zeros to 4 digits.
53- A trailing build-metadata suffix (e.g. the '-<hash>' in '0.0.1-abc123f')
54- is stripped from the last segment before padding and then re-attached, so
55- both 'M.m.p' and 'M.m.p-hash' version formats are handled uniformly.
56- The result for '0.0.1-abc123f' would be '0000.0000.0001-abc123f'.
57-
58- Raises ValueError if executable_version is None or does not match the
59- expected format (1-4 digit dot-separated segments with an optional
60- trailing '-<suffix>').
6151 """
62- if self .executable_version is None or not re .fullmatch (r'\d{1,4}(\.\d{1,4})*(-\w+)?' , self .executable_version ):
63- raise ValueError (f"Unsupported version format: '{ self .executable_version } '" )
64- padding_target = 4
65- padded_version = []
66- for sub in self .executable_version .split ('.' ):
67- numeric , _ , suffix = sub .partition ('-' )
68- padded = '0' * (padding_target - len (numeric )) + numeric
69- if suffix :
70- padded += '-' + suffix
71- padded_version .append (padded )
72- return '.' .join (padded_version )
52+ if self .executable_version is None :
53+ raise ValueError ('executable_version is None' )
54+ return self .executable_version .padded ()
7355
7456 def to_dict (self ) -> dict :
7557 return {
76- 'executable_version' : self .executable_version ,
58+ 'executable_version' : str ( self .executable_version ) if self . executable_version else None ,
7759 'executable_origin' : self .executable_origin ,
7860 'state' : self .state ,
7961 'raw_results' : self .raw_results ,
0 commit comments