From 122f0bc4c82de08c8e87c639224c1871afc67014 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Tue, 18 Mar 2025 20:35:23 +0100 Subject: [PATCH 01/17] Make cls templates able work with either problem format --- problemtools/templates/latex/problemset.cls | 7 ++++++- problemtools/templates/latex/problemset_0.1.cls | 7 ++++++- 2 files changed, 12 insertions(+), 2 deletions(-) diff --git a/problemtools/templates/latex/problemset.cls b/problemtools/templates/latex/problemset.cls index 8c198243..1700901e 100644 --- a/problemtools/templates/latex/problemset.cls +++ b/problemtools/templates/latex/problemset.cls @@ -163,7 +163,12 @@ %% Problem inclusion \newcommand{\includeproblem}[1]{ \startproblem{#1} - \import{#1/problem_statement/}{problem\@problemlanguage.tex} +\IfFileExists{#1/statement/problem\@problemlanguage.tex}{% + \import{#1/statement/}{problem\@problemlanguage.tex}% +}{% + \import{#1/problem_statement/}{problem\@problemlanguage.tex}% +} + %% Automatically include samples 1..9, if enabled \ifplastex\else diff --git a/problemtools/templates/latex/problemset_0.1.cls b/problemtools/templates/latex/problemset_0.1.cls index 8501dea1..edf8062f 100644 --- a/problemtools/templates/latex/problemset_0.1.cls +++ b/problemtools/templates/latex/problemset_0.1.cls @@ -138,7 +138,12 @@ %% Problem inclusion \newcommand{\includeproblem}[3]{ \startproblem{#1}{#2}{#3} - \import{#1/problem_statement/}{problem\@problemlanguage.tex} +\IfFileExists{#1/statement/problem\@problemlanguage.tex}{% + \import{#1/statement/}{problem\@problemlanguage.tex}% +}{% + \import{#1/problem_statement/}{problem\@problemlanguage.tex}% +} + } \newcommand{\startproblem}[3]{ From 4738fc1cb80192a183fafb6fb56e2b9ab6e88ccc Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Tue, 18 Mar 2025 20:36:40 +0100 Subject: [PATCH 02/17] Allow problem statement to use either problem format --- problemtools/verifyproblem.py | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 646e262f..65fe32b0 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -711,15 +711,22 @@ def all_datasets(self) -> list: class ProblemStatement(ProblemPart): PART_NAME = 'statement' - EXTENSIONS: list[str] = [] + DIR_END = "" + FORMAT_VERSION = "" def setup(self): if not self.EXTENSIONS: raise NotImplementedError('Need to override class and set EXTENSIONS class-variable') + if not self.DIR_END: + raise NotImplementedError('Need to override class and set DIR_END class-variable') self.debug(' Loading problem statement') self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(self.EXTENSIONS))) - dir = os.path.join(self.problem.probdir, 'problem_statement') - self.statements = [(m.group(0), m.group(2) or '') for file in os.listdir(dir) if (m := re.search(self.statement_regex, file))] + dir = os.path.join(self.problem.probdir, self.DIR_END) + if os.path.isdir(dir): + self.statements = [(m.group(0), m.group(2) or '') for file in os.listdir(dir) if (m := re.search(self.statement_regex, file))] + else: + self.error(f"No directory named {self.DIR_END} found") + self.statements = [] return self.get_config() @@ -730,7 +737,7 @@ def check(self, context: Context) -> bool: if not self.statements: allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in self.EXTENSIONS) - self.error(f'No problem statements found (expected file of one of following forms in folder problem_statement/: {allowed_statements}') + self.error(f'No problem statements found (expected file of one of following forms in directory {self.DIR_END}/: {allowed_statements})') langs = [lang or 'en' for _, lang in self.statements] for lang, count in collections.Counter(langs).items(): @@ -744,6 +751,7 @@ def check(self, context: Context) -> bool: options.language = lang options.nopdf = True options.quiet = True + options.format_version = self.FORMAT_VERSION if not problem2pdf.convert(options): langparam = f' --language {lang}' if lang != '' else '' self.error(f'Could not compile problem statement for language "{lang}". Run problem2pdf{langparam} on the problem to diagnose.') @@ -755,6 +763,7 @@ def check(self, context: Context) -> bool: options.destdir = os.path.join(self.problem.tmpdir, 'html') options.language = lang options.quiet = True + options.format_version = self.FORMAT_VERSION problem2html.convert(options) except Exception as e: langparam = f' --language {lang}' if lang != '' else '' @@ -767,7 +776,8 @@ def __str__(self) -> str: def get_config(self) -> dict[str, dict[str, str]]: ret: dict[str, dict[str, str]] = {'name':{}} for filename, lang in self.statements: - with open(os.path.join(self.problem.probdir, 'problem_statement', filename)) as f: + dir = os.path.join(self.problem.probdir, self.DIR_END) + with open(os.path.join(dir, filename)) as f: stmt = f.read() hit = re.search(r'\\problemname{(.*)}', stmt, re.MULTILINE) if hit: @@ -777,9 +787,13 @@ def get_config(self) -> dict[str, dict[str, str]]: class ProblemStatementLegacy(ProblemStatement): EXTENSIONS = ['tex'] + DIR_END = "problem_statement" + FORMAT_VERSION = "legacy" class ProblemStatement2023_07(ProblemStatement): EXTENSIONS = ['md', 'tex'] + DIR_END = "statement" + FORMAT_VERSION = "2023-07" class ProblemConfig(ProblemPart): PART_NAME = 'config' From ab5f2b5820e4990da16e63fa1b15e5a09b3f3b9e Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Thu, 20 Mar 2025 16:26:24 +0100 Subject: [PATCH 03/17] Make template.py detect format version instead --- problemtools/problem2html.py | 1 + problemtools/problem2pdf.py | 1 + problemtools/template.py | 25 +++++++++++++++++++++++-- problemtools/verifyproblem.py | 1 - 4 files changed, 25 insertions(+), 3 deletions(-) diff --git a/problemtools/problem2html.py b/problemtools/problem2html.py index 6bf56192..cf345bea 100644 --- a/problemtools/problem2html.py +++ b/problemtools/problem2html.py @@ -123,6 +123,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument('-L', '--log-level', dest='loglevel', help='set log level (debug, info, warning, error, critical)', default='warning') parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False) parser.add_argument('-i', '--imgbasedir', dest='imgbasedir', default='') + parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="legacy") parser.add_argument('problem', help='the problem to convert') return parser diff --git a/problemtools/problem2pdf.py b/problemtools/problem2pdf.py index 0f6fc452..219bdd99 100644 --- a/problemtools/problem2pdf.py +++ b/problemtools/problem2pdf.py @@ -50,6 +50,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False) parser.add_argument('-l', '--language', dest='language', help='choose alternate language (2-letter code)', default=None) parser.add_argument('-n', '--no-pdf', dest='nopdf', action='store_true', help='run pdflatex in -draftmode', default=False) + parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="legacy") parser.add_argument('problem', help='the problem to convert') return parser diff --git a/problemtools/template.py b/problemtools/template.py index 0d5951f7..ff698315 100644 --- a/problemtools/template.py +++ b/problemtools/template.py @@ -3,6 +3,7 @@ import glob import tempfile import shutil +import yaml # For backwards compatibility, remove in bright and shiny future. @@ -14,13 +15,24 @@ def detect_version(problemdir, problemtex): class Template: - def __init__(self, problemdir, language=None, force_copy_cls=False): + def __init__(self, problemdir, language=None, force_copy_cls=False, version="default"): if not os.path.isdir(problemdir): raise Exception('%s is not a directory' % problemdir) if problemdir[-1] == '/': problemdir = problemdir[:-1] - stmtdir = os.path.join(problemdir, 'problem_statement') + + if version == "default": + version = self.detect_problem_version(problemdir) + + if version == "2023-07": + statement_directory = "statement" + else: + statement_directory = "problem_statement" + + stmtdir = os.path.join(problemdir, statement_directory) + + langs = [] if glob.glob(os.path.join(stmtdir, 'problem.tex')): @@ -115,3 +127,12 @@ def __exit__(self, exc_type, exc_value, exc_traceback): def get_file_name(self): assert os.path.isfile(self.filename) return self.filename + + def detect_problem_version(self, path) -> str: + config_path = os.path.join(path, 'problem.yaml') + try: + with open(config_path) as f: + config: dict = yaml.safe_load(f) or {} + except Exception as e: + raise RuntimeError(f"Error reading problem.yaml: {e}") + return config.get('problem_format_version', 'legacy') diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 65fe32b0..2c817d19 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -751,7 +751,6 @@ def check(self, context: Context) -> bool: options.language = lang options.nopdf = True options.quiet = True - options.format_version = self.FORMAT_VERSION if not problem2pdf.convert(options): langparam = f' --language {lang}' if lang != '' else '' self.error(f'Could not compile problem statement for language "{lang}". Run problem2pdf{langparam} on the problem to diagnose.') From 60c75041cdca40065b49c1d4b3d0f1ca160212a1 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Sun, 23 Mar 2025 21:11:35 +0100 Subject: [PATCH 04/17] Provisional updates --- problemtools/problem2html.py | 2 +- problemtools/problem2pdf.py | 2 +- problemtools/template.py | 4 ++-- problemtools/verifyproblem.py | 18 +++++++++++------- 4 files changed, 15 insertions(+), 11 deletions(-) diff --git a/problemtools/problem2html.py b/problemtools/problem2html.py index cf345bea..e0920b21 100644 --- a/problemtools/problem2html.py +++ b/problemtools/problem2html.py @@ -123,7 +123,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument('-L', '--log-level', dest='loglevel', help='set log level (debug, info, warning, error, critical)', default='warning') parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False) parser.add_argument('-i', '--imgbasedir', dest='imgbasedir', default='') - parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="legacy") + parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="automatic") parser.add_argument('problem', help='the problem to convert') return parser diff --git a/problemtools/problem2pdf.py b/problemtools/problem2pdf.py index 219bdd99..de955341 100644 --- a/problemtools/problem2pdf.py +++ b/problemtools/problem2pdf.py @@ -50,7 +50,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False) parser.add_argument('-l', '--language', dest='language', help='choose alternate language (2-letter code)', default=None) parser.add_argument('-n', '--no-pdf', dest='nopdf', action='store_true', help='run pdflatex in -draftmode', default=False) - parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="legacy") + parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="automatic") parser.add_argument('problem', help='the problem to convert') return parser diff --git a/problemtools/template.py b/problemtools/template.py index ff698315..48f6059d 100644 --- a/problemtools/template.py +++ b/problemtools/template.py @@ -15,14 +15,14 @@ def detect_version(problemdir, problemtex): class Template: - def __init__(self, problemdir, language=None, force_copy_cls=False, version="default"): + def __init__(self, problemdir, language=None, force_copy_cls=False, version="automatic"): if not os.path.isdir(problemdir): raise Exception('%s is not a directory' % problemdir) if problemdir[-1] == '/': problemdir = problemdir[:-1] - if version == "default": + if version == "automatic": version = self.detect_problem_version(problemdir) if version == "2023-07": diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 2c817d19..55795ba1 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -20,6 +20,7 @@ import copy import random import traceback +import formatversion import argparse import shlex @@ -715,17 +716,16 @@ class ProblemStatement(ProblemPart): FORMAT_VERSION = "" def setup(self): - if not self.EXTENSIONS: - raise NotImplementedError('Need to override class and set EXTENSIONS class-variable') - if not self.DIR_END: - raise NotImplementedError('Need to override class and set DIR_END class-variable') + STATEMENT_DATA = formatversion.get_statement_data(self.problem.probdir) + if not STATEMENT_DATA: + raise NotImplementedError('No version selected.') self.debug(' Loading problem statement') - self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(self.EXTENSIONS))) - dir = os.path.join(self.problem.probdir, self.DIR_END) + self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(STATEMENT_DATA.get_statement_extensions()))) + dir = os.path.join(self.problem.probdir, STATEMENT_DATA.get_statement_directory()) if os.path.isdir(dir): self.statements = [(m.group(0), m.group(2) or '') for file in os.listdir(dir) if (m := re.search(self.statement_regex, file))] else: - self.error(f"No directory named {self.DIR_END} found") + self.error(f"No directory named {STATEMENT_DATA.get_statement_directory()} found") self.statements = [] return self.get_config() @@ -772,6 +772,10 @@ def check(self, context: Context) -> bool: def __str__(self) -> str: return 'problem statement' + def __init__(self, problem: Problem): + super().__init__(problem) + STATEMENT_DATA = formatversion.get_statement_data(self.problem.probdir) + def get_config(self) -> dict[str, dict[str, str]]: ret: dict[str, dict[str, str]] = {'name':{}} for filename, lang in self.statements: From a7676d949270a24b14b2f3972447cb9fb226c5cc Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Sun, 23 Mar 2025 21:21:09 +0100 Subject: [PATCH 05/17] Add formatversion.py --- problemtools/formatversion.py | 55 +++++++++++++++++++++++++++++++++++ 1 file changed, 55 insertions(+) create mode 100644 problemtools/formatversion.py diff --git a/problemtools/formatversion.py b/problemtools/formatversion.py new file mode 100644 index 00000000..4922e232 --- /dev/null +++ b/problemtools/formatversion.py @@ -0,0 +1,55 @@ +import os + +import yaml + + +def detect_problem_version(path) -> str: + config_path = os.path.join(path, 'problem.yaml') + try: + with open(config_path) as f: + config: dict = yaml.safe_load(f) or {} + except Exception as e: + raise VersionError(f"Error reading problem.yaml: {e}") + return config.get('problem_format_version', 'legacy') + + +class FormatVersionData: + STATEMENT_DIRECTORY = "" + STATEMENT_EXTENSIONS = [] + + def get_statement_directory(self): + if self.STATEMENT_DIRECTORY == "": + raise NotImplementedError() + else: + return self.STATEMENT_DIRECTORY + + def get_statement_extensions(self): + if not self.STATEMENT_EXTENSIONS: + raise NotImplementedError() + else: + return self.STATEMENT_EXTENSIONS + + @staticmethod + def get_statement_data(path): + version = detect_problem_version(path) + if version == "legacy": + return StatementLegacyData + elif version == "2023-07": + return Statement2023_07Data + + +class StatementLegacyData(FormatVersionData): + EXTENSIONS = ['tex'] + STATEMENT_DIRECTORY = "problem_statement" + FORMAT_VERSION = "legacy" + + +class Statement2023_07Data(FormatVersionData): + EXTENSIONS = ['md', 'tex'] + DIR_END = "statement" + FORMAT_VERSION = "2023-07" + + +class VersionError(Exception): + pass + From be21d6f68a3f93203a3a7a886be1010b386387bc Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Sun, 23 Mar 2025 21:21:24 +0100 Subject: [PATCH 06/17] Minor fixes in imports --- problemtools/verifyproblem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 55795ba1..92510f32 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -20,7 +20,6 @@ import copy import random import traceback -import formatversion import argparse import shlex @@ -29,6 +28,7 @@ from . import problem2pdf from . import problem2html +from . import formatversion from . import config from . import languages From 9a9cc38ba390938bbb222cca87992362ae3e6119 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Sun, 23 Mar 2025 23:22:06 +0100 Subject: [PATCH 07/17] Move version specific functionality to separate file --- problemtools/formatversion.py | 59 +++++++++++++++++++++++++---------- problemtools/template.py | 19 +++-------- problemtools/verifyproblem.py | 38 +++++++++------------- 3 files changed, 62 insertions(+), 54 deletions(-) diff --git a/problemtools/formatversion.py b/problemtools/formatversion.py index 4922e232..bcba99f1 100644 --- a/problemtools/formatversion.py +++ b/problemtools/formatversion.py @@ -1,8 +1,11 @@ import os - import yaml +""" +Returns the problem version value of problem.yaml or throws an error if it is unable to read the file. +""" + def detect_problem_version(path) -> str: config_path = os.path.join(path, 'problem.yaml') try: @@ -13,10 +16,42 @@ def detect_problem_version(path) -> str: return config.get('problem_format_version', 'legacy') +""" +Returns a FormatVersionData object based on the format version found in problem.yaml +""" + +def get_format_version_data_by_dir(path): + version = detect_problem_version(path) + return get_format_version_data_by_name(version) + + +""" +Returns a FormatVersionData object based on the format version found in problem.yaml +""" + +def get_format_version_data_by_name(version_name): + if version_name == "legacy": + return DataLegacy() + elif version_name == "2023-07": + return Data2023_07() + else: + raise VersionError(f"Unknown version {version_name}") + + +""" +A superclass for all the format version-specific variables and information +""" class FormatVersionData: + FORMAT_VERSION = "" STATEMENT_DIRECTORY = "" STATEMENT_EXTENSIONS = [] + def get_format_version(self): + if self.FORMAT_VERSION == "": + raise NotImplementedError() + else: + return self.FORMAT_VERSION + def get_statement_directory(self): if self.STATEMENT_DIRECTORY == "": raise NotImplementedError() @@ -29,25 +64,17 @@ def get_statement_extensions(self): else: return self.STATEMENT_EXTENSIONS - @staticmethod - def get_statement_data(path): - version = detect_problem_version(path) - if version == "legacy": - return StatementLegacyData - elif version == "2023-07": - return Statement2023_07Data - -class StatementLegacyData(FormatVersionData): - EXTENSIONS = ['tex'] - STATEMENT_DIRECTORY = "problem_statement" +class DataLegacy(FormatVersionData): FORMAT_VERSION = "legacy" - + STATEMENT_DIRECTORY = "problem_statement" + STATEMENT_EXTENSIONS = ['tex'] + -class Statement2023_07Data(FormatVersionData): - EXTENSIONS = ['md', 'tex'] - DIR_END = "statement" +class Data2023_07(FormatVersionData): FORMAT_VERSION = "2023-07" + STATEMENT_DIRECTORY = "statement" + STATEMENT_EXTENSIONS = ['md', 'tex'] class VersionError(Exception): diff --git a/problemtools/template.py b/problemtools/template.py index 48f6059d..3f4f0ad9 100644 --- a/problemtools/template.py +++ b/problemtools/template.py @@ -3,7 +3,8 @@ import glob import tempfile import shutil -import yaml + +from . import formatversion # For backwards compatibility, remove in bright and shiny future. @@ -23,14 +24,12 @@ def __init__(self, problemdir, language=None, force_copy_cls=False, version="aut problemdir = problemdir[:-1] if version == "automatic": - version = self.detect_problem_version(problemdir) + version_data = formatversion.get_format_version_data_by_dir(problemdir) - if version == "2023-07": - statement_directory = "statement" else: - statement_directory = "problem_statement" + version_data = formatversion.get_format_version_data_by_name(version) - stmtdir = os.path.join(problemdir, statement_directory) + stmtdir = os.path.join(problemdir, version_data.get_statement_directory()) @@ -128,11 +127,3 @@ def get_file_name(self): assert os.path.isfile(self.filename) return self.filename - def detect_problem_version(self, path) -> str: - config_path = os.path.join(path, 'problem.yaml') - try: - with open(config_path) as f: - config: dict = yaml.safe_load(f) or {} - except Exception as e: - raise RuntimeError(f"Error reading problem.yaml: {e}") - return config.get('problem_format_version', 'legacy') diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 92510f32..8784ad67 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -711,33 +711,33 @@ def all_datasets(self) -> list: return res class ProblemStatement(ProblemPart): - PART_NAME = 'statement' - DIR_END = "" - FORMAT_VERSION = "" + STATEMENT_DATA = None def setup(self): - STATEMENT_DATA = formatversion.get_statement_data(self.problem.probdir) - if not STATEMENT_DATA: + if not self.STATEMENT_DATA: raise NotImplementedError('No version selected.') self.debug(' Loading problem statement') - self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(STATEMENT_DATA.get_statement_extensions()))) - dir = os.path.join(self.problem.probdir, STATEMENT_DATA.get_statement_directory()) + self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(self.STATEMENT_DATA.get_statement_extensions()))) + dir = os.path.join(self.problem.probdir, self.STATEMENT_DATA.get_statement_directory()) if os.path.isdir(dir): self.statements = [(m.group(0), m.group(2) or '') for file in os.listdir(dir) if (m := re.search(self.statement_regex, file))] else: - self.error(f"No directory named {STATEMENT_DATA.get_statement_directory()} found") + self.error(f"No directory named {self.STATEMENT_DATA.get_statement_directory()} found") self.statements = [] return self.get_config() def check(self, context: Context) -> bool: + STATEMENT_DATA = self.STATEMENT_DATA + if not STATEMENT_DATA: + raise NotImplementedError('No version selected.') if self._check_res is not None: return self._check_res self._check_res = True if not self.statements: - allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in self.EXTENSIONS) - self.error(f'No problem statements found (expected file of one of following forms in directory {self.DIR_END}/: {allowed_statements})') + allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in STATEMENT_DATA.get_statement_extensions) + self.error(f'No problem statements found (expected file of one of following forms in directory {STATEMENT_DATA.get_statement_directory()}/: {allowed_statements})') langs = [lang or 'en' for _, lang in self.statements] for lang, count in collections.Counter(langs).items(): @@ -762,7 +762,6 @@ def check(self, context: Context) -> bool: options.destdir = os.path.join(self.problem.tmpdir, 'html') options.language = lang options.quiet = True - options.format_version = self.FORMAT_VERSION problem2html.convert(options) except Exception as e: langparam = f' --language {lang}' if lang != '' else '' @@ -774,12 +773,12 @@ def __str__(self) -> str: def __init__(self, problem: Problem): super().__init__(problem) - STATEMENT_DATA = formatversion.get_statement_data(self.problem.probdir) + self.STATEMENT_DATA = formatversion.get_format_version_data_by_dir(self.problem.probdir) def get_config(self) -> dict[str, dict[str, str]]: ret: dict[str, dict[str, str]] = {'name':{}} for filename, lang in self.statements: - dir = os.path.join(self.problem.probdir, self.DIR_END) + dir = os.path.join(self.problem.probdir, self.STATEMENT_DATA.get_statement_directory()) with open(os.path.join(dir, filename)) as f: stmt = f.read() hit = re.search(r'\\problemname{(.*)}', stmt, re.MULTILINE) @@ -788,15 +787,6 @@ def get_config(self) -> dict[str, dict[str, str]]: ret['name'][lang] = problem_name return ret if ret['name'] else {} -class ProblemStatementLegacy(ProblemStatement): - EXTENSIONS = ['tex'] - DIR_END = "problem_statement" - FORMAT_VERSION = "legacy" - -class ProblemStatement2023_07(ProblemStatement): - EXTENSIONS = ['md', 'tex'] - DIR_END = "statement" - FORMAT_VERSION = "2023-07" class ProblemConfig(ProblemPart): PART_NAME = 'config' @@ -1747,14 +1737,14 @@ def check(self, context: Context) -> bool: PROBLEM_FORMATS: dict[str, dict[str, list[Type[ProblemPart]]]] = { 'legacy': { 'config': [ProblemConfig], - 'statement': [ProblemStatementLegacy, Attachments], + 'statement': [ProblemStatement, Attachments], 'validators': [InputValidators, OutputValidators], 'graders': [Graders], 'data': [ProblemTestCases], 'submissions': [Submissions], }, '2023-07': { # TODO: Add all the parts - 'statement': [ProblemStatement2023_07, Attachments], + 'statement': [ProblemStatement, Attachments], } } From c531bc36e6379295128fa8100609ad9e03dbf694 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Sun, 23 Mar 2025 23:28:31 +0100 Subject: [PATCH 08/17] Change to flag '-v' for format-version --- problemtools/problem2pdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problemtools/problem2pdf.py b/problemtools/problem2pdf.py index de955341..ec2b3ad1 100644 --- a/problemtools/problem2pdf.py +++ b/problemtools/problem2pdf.py @@ -50,7 +50,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False) parser.add_argument('-l', '--language', dest='language', help='choose alternate language (2-letter code)', default=None) parser.add_argument('-n', '--no-pdf', dest='nopdf', action='store_true', help='run pdflatex in -draftmode', default=False) - parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="automatic") + parser.add_argument('-v', '--format-version', dest='format_version', help='choose format version', default="automatic") parser.add_argument('problem', help='the problem to convert') return parser From d235ba02aca6d970e2c0ca16dd30a1030e7e2cdb Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Mon, 24 Mar 2025 13:54:40 +0100 Subject: [PATCH 09/17] Add missing parentheses --- problemtools/verifyproblem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 8784ad67..ce05392d 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -736,7 +736,7 @@ def check(self, context: Context) -> bool: self._check_res = True if not self.statements: - allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in STATEMENT_DATA.get_statement_extensions) + allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in STATEMENT_DATA.get_statement_extensions()) self.error(f'No problem statements found (expected file of one of following forms in directory {STATEMENT_DATA.get_statement_directory()}/: {allowed_statements})') langs = [lang or 'en' for _, lang in self.statements] From 44969183ca23cefe62e24cae2de50bfb03a97bbd Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Mon, 24 Mar 2025 18:07:44 +0100 Subject: [PATCH 10/17] Use dictionary instead of data objects for format data --- problemtools/formatversion.py | 83 +++++++++++++---------------------- problemtools/template.py | 9 ++-- problemtools/verifyproblem.py | 23 +++++----- 3 files changed, 43 insertions(+), 72 deletions(-) diff --git a/problemtools/formatversion.py b/problemtools/formatversion.py index bcba99f1..4cda5c8f 100644 --- a/problemtools/formatversion.py +++ b/problemtools/formatversion.py @@ -3,9 +3,25 @@ """ -Returns the problem version value of problem.yaml or throws an error if it is unable to read the file. +The data specific to any given format version. """ +FORMAT_DATA = { + "legacy": { + "name": "legacy", + "statement_directory": "problem_statement", + "statement_extensions": ["tex"] + }, + "2023-07": { + "name": "2023-07", + "statement_directory": "statement", + "statement_extensions": ["md", "tex"], + } +} + +""" +Returns the problem version value of problem.yaml or throws an error if it is unable to read the file. +""" def detect_problem_version(path) -> str: config_path = os.path.join(path, 'problem.yaml') try: @@ -17,65 +33,26 @@ def detect_problem_version(path) -> str: """ -Returns a FormatVersionData object based on the format version found in problem.yaml +Returns a dictionary containing the necessary data for a file format. """ - -def get_format_version_data_by_dir(path): +def get_format_data(path): version = detect_problem_version(path) - return get_format_version_data_by_name(version) - - -""" -Returns a FormatVersionData object based on the format version found in problem.yaml -""" - -def get_format_version_data_by_name(version_name): - if version_name == "legacy": - return DataLegacy() - elif version_name == "2023-07": - return Data2023_07() + data = FORMAT_DATA.get(version) + if not data: + raise VersionError(f"No version found with name {version}") else: - raise VersionError(f"Unknown version {version_name}") + return data """ -A superclass for all the format version-specific variables and information +Returns a dictionary containing the necessary data for a file format given the format's name. """ -class FormatVersionData: - FORMAT_VERSION = "" - STATEMENT_DIRECTORY = "" - STATEMENT_EXTENSIONS = [] - - def get_format_version(self): - if self.FORMAT_VERSION == "": - raise NotImplementedError() - else: - return self.FORMAT_VERSION - - def get_statement_directory(self): - if self.STATEMENT_DIRECTORY == "": - raise NotImplementedError() - else: - return self.STATEMENT_DIRECTORY - - def get_statement_extensions(self): - if not self.STATEMENT_EXTENSIONS: - raise NotImplementedError() - else: - return self.STATEMENT_EXTENSIONS - - -class DataLegacy(FormatVersionData): - FORMAT_VERSION = "legacy" - STATEMENT_DIRECTORY = "problem_statement" - STATEMENT_EXTENSIONS = ['tex'] - - -class Data2023_07(FormatVersionData): - FORMAT_VERSION = "2023-07" - STATEMENT_DIRECTORY = "statement" - STATEMENT_EXTENSIONS = ['md', 'tex'] - +def get_format_data_by_name(name): + data = FORMAT_DATA.get(name) + if not data: + raise VersionError(f"No version found with name {name}") + else: + return data class VersionError(Exception): pass diff --git a/problemtools/template.py b/problemtools/template.py index 3f4f0ad9..c173c11a 100644 --- a/problemtools/template.py +++ b/problemtools/template.py @@ -24,15 +24,12 @@ def __init__(self, problemdir, language=None, force_copy_cls=False, version="aut problemdir = problemdir[:-1] if version == "automatic": - version_data = formatversion.get_format_version_data_by_dir(problemdir) + version_data = formatversion.get_format_data(problemdir) else: - version_data = formatversion.get_format_version_data_by_name(version) - - stmtdir = os.path.join(problemdir, version_data.get_statement_directory()) - - + version_data = formatversion.get_format_data_by_name(version) + stmtdir = os.path.join(problemdir, version_data.get('statement_directory')) langs = [] if glob.glob(os.path.join(stmtdir, 'problem.tex')): langs.append('') diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index ce05392d..84e420e1 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -703,41 +703,38 @@ def aggregate_results(self, sub, sub_results: list[SubmissionResult], shadow_res self.error(f'submission {sub} got {res} on group {groupname}, which is outside of expected score range [{min_score}, {max_score}]') return res - def all_datasets(self) -> list: res: list = [] for child in self._items: res += child.all_datasets() return res + class ProblemStatement(ProblemPart): - STATEMENT_DATA = None + FORMAT_DATA = None def setup(self): - if not self.STATEMENT_DATA: + if not self.FORMAT_DATA: raise NotImplementedError('No version selected.') self.debug(' Loading problem statement') - self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(self.STATEMENT_DATA.get_statement_extensions()))) - dir = os.path.join(self.problem.probdir, self.STATEMENT_DATA.get_statement_directory()) + self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(self.FORMAT_DATA.get("statement_extensions")))) + dir = os.path.join(self.problem.probdir, self.FORMAT_DATA.get("statement_directory")) if os.path.isdir(dir): self.statements = [(m.group(0), m.group(2) or '') for file in os.listdir(dir) if (m := re.search(self.statement_regex, file))] else: - self.error(f"No directory named {self.STATEMENT_DATA.get_statement_directory()} found") + self.error(f"No directory named {self.FORMAT_DATA.get('statement_directory')} found") self.statements = [] return self.get_config() def check(self, context: Context) -> bool: - STATEMENT_DATA = self.STATEMENT_DATA - if not STATEMENT_DATA: - raise NotImplementedError('No version selected.') if self._check_res is not None: return self._check_res self._check_res = True if not self.statements: - allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in STATEMENT_DATA.get_statement_extensions()) - self.error(f'No problem statements found (expected file of one of following forms in directory {STATEMENT_DATA.get_statement_directory()}/: {allowed_statements})') + allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in self.FORMAT_DATA.get("statement_extensions")) + self.error(f'No problem statements found (expected file of one of following forms in directory {self.FORMAT_DATA.get("statement_directory")}/: {allowed_statements})') langs = [lang or 'en' for _, lang in self.statements] for lang, count in collections.Counter(langs).items(): @@ -773,12 +770,12 @@ def __str__(self) -> str: def __init__(self, problem: Problem): super().__init__(problem) - self.STATEMENT_DATA = formatversion.get_format_version_data_by_dir(self.problem.probdir) + self.FORMAT_DATA = formatversion.get_format_data(self.problem.probdir) def get_config(self) -> dict[str, dict[str, str]]: ret: dict[str, dict[str, str]] = {'name':{}} for filename, lang in self.statements: - dir = os.path.join(self.problem.probdir, self.STATEMENT_DATA.get_statement_directory()) + dir = os.path.join(self.problem.probdir, self.FORMAT_DATA.get("statement_directory")) with open(os.path.join(dir, filename)) as f: stmt = f.read() hit = re.search(r'\\problemname{(.*)}', stmt, re.MULTILINE) From e71dbf976eec9111f1ad6eca431e31c7a23279e6 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Mon, 24 Mar 2025 18:08:19 +0100 Subject: [PATCH 11/17] Make problem2html.py use -v to specify format version --- problemtools/problem2html.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/problemtools/problem2html.py b/problemtools/problem2html.py index e0920b21..86137a59 100644 --- a/problemtools/problem2html.py +++ b/problemtools/problem2html.py @@ -123,7 +123,7 @@ def get_parser() -> argparse.ArgumentParser: parser.add_argument('-L', '--log-level', dest='loglevel', help='set log level (debug, info, warning, error, critical)', default='warning') parser.add_argument('-q', '--quiet', dest='quiet', action='store_true', help="quiet", default=False) parser.add_argument('-i', '--imgbasedir', dest='imgbasedir', default='') - parser.add_argument('-F', '--format-version', dest='format_version', help='choose format version', default="automatic") + parser.add_argument('-v', '--format-version', dest='format_version', help='choose format version', default="automatic") parser.add_argument('problem', help='the problem to convert') return parser From b59ce650b07325346025867436414f02fbf19633 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Mon, 24 Mar 2025 22:53:33 +0100 Subject: [PATCH 12/17] Add constants for version names --- problemtools/formatversion.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/problemtools/formatversion.py b/problemtools/formatversion.py index 4cda5c8f..f5a57086 100644 --- a/problemtools/formatversion.py +++ b/problemtools/formatversion.py @@ -18,6 +18,9 @@ } } +VERSION_LEGACY = "legacy" +VERSION_2023_07 = "2023-07" + """ Returns the problem version value of problem.yaml or throws an error if it is unable to read the file. From b805d01d2516a1b5a4654746bd2e0924a5ebf6d1 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Mon, 24 Mar 2025 22:55:26 +0100 Subject: [PATCH 13/17] Rollback problemset_0.1.cls --- problemtools/templates/latex/problemset_0.1.cls | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/problemtools/templates/latex/problemset_0.1.cls b/problemtools/templates/latex/problemset_0.1.cls index edf8062f..8501dea1 100644 --- a/problemtools/templates/latex/problemset_0.1.cls +++ b/problemtools/templates/latex/problemset_0.1.cls @@ -138,12 +138,7 @@ %% Problem inclusion \newcommand{\includeproblem}[3]{ \startproblem{#1}{#2}{#3} -\IfFileExists{#1/statement/problem\@problemlanguage.tex}{% - \import{#1/statement/}{problem\@problemlanguage.tex}% -}{% - \import{#1/problem_statement/}{problem\@problemlanguage.tex}% -} - + \import{#1/problem_statement/}{problem\@problemlanguage.tex} } \newcommand{\startproblem}[3]{ From 2aa9be088b31e11743a20613b3ea572e0821df59 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Mon, 24 Mar 2025 23:03:30 +0100 Subject: [PATCH 14/17] Move initialisation of FORMAT_DATA to setup --- problemtools/verifyproblem.py | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 84e420e1..3b2cea14 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -714,6 +714,7 @@ class ProblemStatement(ProblemPart): FORMAT_DATA = None def setup(self): + self.FORMAT_DATA = formatversion.get_format_data(self.problem.probdir) if not self.FORMAT_DATA: raise NotImplementedError('No version selected.') self.debug(' Loading problem statement') @@ -768,10 +769,6 @@ def check(self, context: Context) -> bool: def __str__(self) -> str: return 'problem statement' - def __init__(self, problem: Problem): - super().__init__(problem) - self.FORMAT_DATA = formatversion.get_format_data(self.problem.probdir) - def get_config(self) -> dict[str, dict[str, str]]: ret: dict[str, dict[str, str]] = {'name':{}} for filename, lang in self.statements: From 470fbb899d79167a20210c4d45e4533ca36828d3 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Thu, 27 Mar 2025 15:02:49 +0100 Subject: [PATCH 15/17] Make formatversion.py use dataobjects instead of dicts --- problemtools/formatversion.py | 41 +++++++++++++++++------------------ problemtools/template.py | 2 +- problemtools/verifyproblem.py | 19 ++++++++-------- 3 files changed, 31 insertions(+), 31 deletions(-) diff --git a/problemtools/formatversion.py b/problemtools/formatversion.py index f5a57086..258f0c1d 100644 --- a/problemtools/formatversion.py +++ b/problemtools/formatversion.py @@ -1,27 +1,25 @@ import os import yaml +from dataclasses import dataclass -""" -The data specific to any given format version. -""" -FORMAT_DATA = { - "legacy": { - "name": "legacy", - "statement_directory": "problem_statement", - "statement_extensions": ["tex"] - }, - "2023-07": { - "name": "2023-07", - "statement_directory": "statement", - "statement_extensions": ["md", "tex"], - } -} - VERSION_LEGACY = "legacy" VERSION_2023_07 = "2023-07" +@dataclass(frozen=True) +class FormatData: + name: str + statement_directory: str + statement_extensions: list[str] + + +FORMAT_DATACLASSES = { + VERSION_LEGACY: FormatData(name=VERSION_LEGACY, statement_directory="problem_statement", statement_extensions=["tex"]), + VERSION_2023_07: FormatData(name=VERSION_2023_07, statement_directory="statement", statement_extensions=["md", "tex"]) +} + + """ Returns the problem version value of problem.yaml or throws an error if it is unable to read the file. """ @@ -32,15 +30,15 @@ def detect_problem_version(path) -> str: config: dict = yaml.safe_load(f) or {} except Exception as e: raise VersionError(f"Error reading problem.yaml: {e}") - return config.get('problem_format_version', 'legacy') + return config.get('problem_format_version', VERSION_LEGACY) """ -Returns a dictionary containing the necessary data for a file format. +Returns a dataclass containing the necessary data for a file format. """ def get_format_data(path): version = detect_problem_version(path) - data = FORMAT_DATA.get(version) + data = FORMAT_DATACLASSES[version] if not data: raise VersionError(f"No version found with name {version}") else: @@ -48,15 +46,16 @@ def get_format_data(path): """ -Returns a dictionary containing the necessary data for a file format given the format's name. +Returns a dataclass containing the necessary data for a file format given the format's name. """ def get_format_data_by_name(name): - data = FORMAT_DATA.get(name) + data = FORMAT_DATACLASSES.get(name) if not data: raise VersionError(f"No version found with name {name}") else: return data + class VersionError(Exception): pass diff --git a/problemtools/template.py b/problemtools/template.py index c173c11a..f0c7bc4b 100644 --- a/problemtools/template.py +++ b/problemtools/template.py @@ -29,7 +29,7 @@ def __init__(self, problemdir, language=None, force_copy_cls=False, version="aut else: version_data = formatversion.get_format_data_by_name(version) - stmtdir = os.path.join(problemdir, version_data.get('statement_directory')) + stmtdir = os.path.join(problemdir, version_data.statement_directory) langs = [] if glob.glob(os.path.join(stmtdir, 'problem.tex')): langs.append('') diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 3b2cea14..46643ca5 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -711,19 +711,20 @@ def all_datasets(self) -> list: class ProblemStatement(ProblemPart): - FORMAT_DATA = None + format_data = None def setup(self): - self.FORMAT_DATA = formatversion.get_format_data(self.problem.probdir) - if not self.FORMAT_DATA: + self.format_data = formatversion.get_format_data(self.problem.probdir) + print(self.format_data.name) + if not self.format_data: raise NotImplementedError('No version selected.') self.debug(' Loading problem statement') - self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(self.FORMAT_DATA.get("statement_extensions")))) - dir = os.path.join(self.problem.probdir, self.FORMAT_DATA.get("statement_directory")) + self.statement_regex = re.compile(r"problem(\.([a-z]{2,3}|[a-z]{2}-[A-Z]{2}))?\.(%s)$" % ('|'.join(self.format_data.statement_extensions))) + dir = os.path.join(self.problem.probdir, self.format_data.statement_directory) if os.path.isdir(dir): self.statements = [(m.group(0), m.group(2) or '') for file in os.listdir(dir) if (m := re.search(self.statement_regex, file))] else: - self.error(f"No directory named {self.FORMAT_DATA.get('statement_directory')} found") + self.error(f"No directory named {self.format_data.statement_directory} found" self.statements = [] return self.get_config() @@ -734,8 +735,8 @@ def check(self, context: Context) -> bool: self._check_res = True if not self.statements: - allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in self.FORMAT_DATA.get("statement_extensions")) - self.error(f'No problem statements found (expected file of one of following forms in directory {self.FORMAT_DATA.get("statement_directory")}/: {allowed_statements})') + allowed_statements = ', '.join(f'problem.{ext}, problem.[a-z][a-z].{ext}' for ext in self.format_data.statement_extensions) + self.error(f'No problem statements found (expected file of one of following forms in directory {self.format_data.statement_directory}/: {allowed_statements})') langs = [lang or 'en' for _, lang in self.statements] for lang, count in collections.Counter(langs).items(): @@ -772,7 +773,7 @@ def __str__(self) -> str: def get_config(self) -> dict[str, dict[str, str]]: ret: dict[str, dict[str, str]] = {'name':{}} for filename, lang in self.statements: - dir = os.path.join(self.problem.probdir, self.FORMAT_DATA.get("statement_directory")) + dir = os.path.join(self.problem.probdir, self.format_data.statement_directory) with open(os.path.join(dir, filename)) as f: stmt = f.read() hit = re.search(r'\\problemname{(.*)}', stmt, re.MULTILINE) From cba93dcb78ca32449158cd6aa4d14356fc9145ec Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Thu, 27 Mar 2025 16:15:17 +0100 Subject: [PATCH 16/17] Fix documentation --- problemtools/formatversion.py | 49 ++++++++++++++++++++++++----------- 1 file changed, 34 insertions(+), 15 deletions(-) diff --git a/problemtools/formatversion.py b/problemtools/formatversion.py index 258f0c1d..12af9169 100644 --- a/problemtools/formatversion.py +++ b/problemtools/formatversion.py @@ -9,6 +9,12 @@ @dataclass(frozen=True) class FormatData: + """ + A class containing data specific to the format version. + name: the version name. + statement_directory: the directory where the statements should be found. + statement_extensions: the allowed extensions for the statements. + """ name: str statement_directory: str statement_extensions: list[str] @@ -20,10 +26,16 @@ class FormatData: } -""" -Returns the problem version value of problem.yaml or throws an error if it is unable to read the file. -""" def detect_problem_version(path) -> str: + """ + Returns the problem version value of problem.yaml or throws an error if it is unable to read the file. + Args: + path: the problem path + + Returns: + the version name as a String + + """ config_path = os.path.join(path, 'problem.yaml') try: with open(config_path) as f: @@ -33,22 +45,29 @@ def detect_problem_version(path) -> str: return config.get('problem_format_version', VERSION_LEGACY) -""" -Returns a dataclass containing the necessary data for a file format. -""" def get_format_data(path): - version = detect_problem_version(path) - data = FORMAT_DATACLASSES[version] - if not data: - raise VersionError(f"No version found with name {version}") - else: - return data + """ + Gets the dataclass object containing the necessary data for a problem format. + Args: + path: the problem path + + Returns: + the dataclass object containing the necessary data for a problem format + + """ + return get_format_data_by_name(detect_problem_version(path)) -""" -Returns a dataclass containing the necessary data for a file format given the format's name. -""" def get_format_data_by_name(name): + """ + Gets the dataclass object containing the necessary data for a problem format given the format name. + Args: + name: the format name + + Returns: + the dataclass object containing the necessary data for a problem format + + """ data = FORMAT_DATACLASSES.get(name) if not data: raise VersionError(f"No version found with name {name}") From f964bc37de239b4d00b18436db129950104c3d75 Mon Sep 17 00:00:00 2001 From: ElliotRipa Date: Fri, 28 Mar 2025 17:02:55 +0100 Subject: [PATCH 17/17] Remove unnecessary initialisation --- problemtools/verifyproblem.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/problemtools/verifyproblem.py b/problemtools/verifyproblem.py index 46643ca5..3aa566d5 100644 --- a/problemtools/verifyproblem.py +++ b/problemtools/verifyproblem.py @@ -711,11 +711,10 @@ def all_datasets(self) -> list: class ProblemStatement(ProblemPart): - format_data = None + PART_NAME = 'statement' def setup(self): self.format_data = formatversion.get_format_data(self.problem.probdir) - print(self.format_data.name) if not self.format_data: raise NotImplementedError('No version selected.') self.debug(' Loading problem statement') @@ -724,7 +723,7 @@ def setup(self): if os.path.isdir(dir): self.statements = [(m.group(0), m.group(2) or '') for file in os.listdir(dir) if (m := re.search(self.statement_regex, file))] else: - self.error(f"No directory named {self.format_data.statement_directory} found" + self.error(f"No directory named {self.format_data.statement_directory} found") self.statements = [] return self.get_config()