28
28
29
29
from . import config
30
30
from . import languages
31
- from . import formatversion
32
31
from . import metadata
33
32
from . import problem2html
34
33
from . import problem2pdf
35
34
from . import run
36
35
from . import statement_util
36
+ from .formatversion import FormatVersion , get_format_version
37
37
38
38
from abc import ABC
39
39
from typing import Any , Callable , ClassVar , Literal , Pattern , Match , ParamSpec , Type , TypeVar
@@ -819,16 +819,12 @@ def setup(self):
819
819
error_str = '\n ' .join ([f' { "->" .join ((str (loc ) for loc in err ["loc" ]))} : { err ["msg" ]} ' for err in e .errors ()])
820
820
self .error (f'Failed parsing problem.yaml. Found { len (e .errors ())} errors:\n { error_str } ' )
821
821
# For now, set metadata to an empty legacy config to avoid crashing.
822
- self .problem .setMetadata (
823
- metadata .parse_metadata (formatversion .get_format_data_by_name (formatversion .VERSION_LEGACY ), {})
824
- )
822
+ self .problem .setMetadata (metadata .parse_metadata (FormatVersion .LEGACY , {}))
825
823
except Exception as e :
826
824
# This should likely be a fatal error, but I'm not sure there's a clean way to fail from setup
827
825
self .error (f'Failed loading problem configuration: { e } ' )
828
826
# For now, set metadata to an empty legacy config to avoid crashing.
829
- self .problem .setMetadata (
830
- metadata .parse_metadata (formatversion .get_format_data_by_name (formatversion .VERSION_LEGACY ), {})
831
- )
827
+ self .problem .setMetadata (metadata .parse_metadata (FormatVersion .LEGACY , {}))
832
828
return {}
833
829
834
830
def __str__ (self ) -> str :
@@ -853,7 +849,7 @@ def check(self, context: Context) -> bool:
853
849
854
850
if self ._metadata .uuid is None :
855
851
uuid_msg = f'Missing uuid from problem.yaml. Add "uuid: { uuid .uuid4 ()} " to problem.yaml.'
856
- if self .problem .format . name == formatversion . VERSION_LEGACY :
852
+ if self .problem .format is FormatVersion . LEGACY :
857
853
self .warning (uuid_msg )
858
854
else :
859
855
self .error (uuid_msg )
@@ -864,7 +860,7 @@ def check(self, context: Context) -> bool:
864
860
not self ._metadata .is_pass_fail ()
865
861
and self .problem .get (ProblemTestCases )['root_group' ].has_custom_groups ()
866
862
and 'show_test_data_groups' not in self ._origdata .get ('grading' , {})
867
- and self .problem .format . name == formatversion . VERSION_LEGACY
863
+ and self .problem .format is FormatVersion . LEGACY
868
864
):
869
865
self .warning (
870
866
'Problem has custom testcase groups, but does not specify a value for grading.show_test_data_groups; defaulting to false'
@@ -1217,10 +1213,7 @@ class OutputValidators(ProblemPart):
1217
1213
PART_NAME = 'output_validator'
1218
1214
1219
1215
def setup (self ):
1220
- if (
1221
- self .problem .format .name != formatversion .VERSION_LEGACY
1222
- and (Path (self .problem .probdir ) / 'output_validators' ).exists ()
1223
- ):
1216
+ if self .problem .format is FormatVersion .LEGACY and (Path (self .problem .probdir ) / 'output_validators' ).exists ():
1224
1217
self .error ('output_validators is not supported after Legacy; please use output_validator instead' )
1225
1218
1226
1219
self ._validators = run .find_programs (
@@ -1351,7 +1344,7 @@ def _parse_validator_results(self, val, status: int, feedbackdir, testcase: Test
1351
1344
def _actual_validators (self ) -> list :
1352
1345
vals = self ._validators
1353
1346
if self .problem .getMetadata ().legacy_validation == 'default' or (
1354
- self .problem .format . name == formatversion . VERSION_2023_07 and not vals
1347
+ self .problem .format is FormatVersion . V_2023_07 and not vals
1355
1348
):
1356
1349
vals = [self ._default_validator ]
1357
1350
return [val for val in vals if val is not None ]
@@ -1739,16 +1732,16 @@ def check(self, context: Context) -> bool:
1739
1732
return self ._check_res
1740
1733
1741
1734
1742
- PROBLEM_FORMATS : dict [str , dict [str , list [Type [ProblemPart ]]]] = {
1743
- formatversion . VERSION_LEGACY : {
1735
+ PROBLEM_FORMATS : dict [FormatVersion , dict [str , list [Type [ProblemPart ]]]] = {
1736
+ FormatVersion . LEGACY : {
1744
1737
'config' : [ProblemConfig ],
1745
1738
'statement' : [ProblemStatement , Attachments ],
1746
1739
'validators' : [InputValidators , OutputValidators ],
1747
1740
'graders' : [Graders ],
1748
1741
'data' : [ProblemTestCases ],
1749
1742
'submissions' : [Submissions ],
1750
1743
},
1751
- formatversion . VERSION_2023_07 : { # TODO: Add all the parts
1744
+ FormatVersion . V_2023_07 : { # TODO: Add all the parts
1752
1745
'config' : [ProblemConfig ],
1753
1746
'statement' : [ProblemStatement , Attachments ],
1754
1747
'validators' : [InputValidators , OutputValidators ],
@@ -1773,14 +1766,14 @@ class Problem(ProblemAspect):
1773
1766
of category -> part-types. You could for example have 'validators' -> [InputValidators, OutputValidators].
1774
1767
"""
1775
1768
1776
- def __init__ (self , probdir : str , parts : dict [str , list [type ]] = PROBLEM_FORMATS [formatversion . VERSION_LEGACY ]):
1769
+ def __init__ (self , probdir : str , parts : dict [str , list [type ]] = PROBLEM_FORMATS [FormatVersion . LEGACY ]):
1777
1770
self .part_mapping : dict [str , list [Type [ProblemPart ]]] = parts
1778
1771
self .aspects : set [type ] = {v for s in parts .values () for v in s }
1779
1772
self .probdir = os .path .realpath (probdir )
1780
1773
self .shortname : str | None = os .path .basename (self .probdir )
1781
1774
super ().__init__ (self .shortname )
1782
1775
self .language_config = languages .load_language_config ()
1783
- self .format = formatversion . get_format_data ( self .probdir )
1776
+ self .format = get_format_version ( Path ( self .probdir ) )
1784
1777
self ._data : dict [str , dict ] = {}
1785
1778
self ._metadata : metadata .Metadata | None = None
1786
1779
self .debug (f'Problem-format: { parts } ' )
@@ -1860,8 +1853,8 @@ def check(self, args: argparse.Namespace) -> tuple[int, int]:
1860
1853
try :
1861
1854
if not re .match ('^[a-z0-9]+$' , self .shortname ):
1862
1855
self .error (f"Invalid shortname '{ self .shortname } ' (must be [a-z0-9]+)" )
1863
- if self .format . name == formatversion . VERSION_2023_07 :
1864
- self .warning (f'Support for version { self .format . name } is very incomplete. Verification may not work as expected.' )
1856
+ if self .format is FormatVersion . V_2023_07 :
1857
+ self .warning (f'Support for version { self .format } is very incomplete. Verification may not work as expected.' )
1865
1858
1866
1859
self ._check_symlinks ()
1867
1860
@@ -2007,17 +2000,16 @@ def main() -> None:
2007
2000
for problemdir in args .problemdir :
2008
2001
try :
2009
2002
if args .problem_format == 'automatic' :
2010
- version_data = formatversion . get_format_data ( problemdir )
2003
+ formatversion = get_format_version ( Path ( problemdir ) )
2011
2004
else :
2012
- version_data = formatversion . get_format_data_by_name (args .problem_format )
2013
- except formatversion . VersionError as e :
2005
+ formatversion = FormatVersion (args .problem_format )
2006
+ except Exception as e :
2014
2007
total_errors += 1
2015
2008
print (f'ERROR: problem version could not be decided for { os .path .basename (os .path .realpath (problemdir ))} : { e } ' )
2016
2009
continue
2017
2010
2018
- print (f'Loading problem { os .path .basename (os .path .realpath (problemdir ))} with format version { version_data .name } ' )
2019
- format = PROBLEM_FORMATS [version_data .name ]
2020
- with Problem (problemdir , format ) as prob :
2011
+ print (f'Loading problem { os .path .basename (os .path .realpath (problemdir ))} with format version { formatversion } ' )
2012
+ with Problem (problemdir , PROBLEM_FORMATS [formatversion ]) as prob :
2021
2013
errors , warnings = prob .check (args )
2022
2014
2023
2015
def p (x : int ) -> str :
0 commit comments