Skip to content

Commit 4136667

Browse files
committed
[problem] Fully parse 'source' in problem.yaml
1 parent f0b25d2 commit 4136667

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

bin/problem.py

Lines changed: 54 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,59 @@ def __init__(
8989
warn(f"found unknown problem.yaml key: {key} in credits")
9090

9191

92+
class ProblemSource:
93+
def __init__(self, name: str, url: Optional[str] = None):
94+
self.name = name
95+
self.url = url
96+
97+
def __repr__(self) -> str:
98+
return self.name + (f" ({self.url})" if self.url else "")
99+
100+
101+
class ProblemSources(list[ProblemSource]):
102+
def __init__(
103+
self,
104+
yaml_data: dict[str, Any],
105+
problem_settings: "ProblemSettings",
106+
):
107+
# If problem.yaml uses the legacy version, do not support the new type of the `source` key.
108+
# If problem.yaml uses 2023-07-draft, prefer `source`, but also support `source_url` and warn for it.
109+
legacy_source_url = parse_optional_setting(yaml_data, "source_url", str)
110+
if problem_settings.is_legacy():
111+
source_name = parse_setting(yaml_data, "source", "")
112+
if legacy_source_url:
113+
self.append(ProblemSource(source_name, legacy_source_url))
114+
else:
115+
if legacy_source_url is not None:
116+
warn("problem.yaml: source_url is removed in 2023-07-draft, please use source.url")
117+
if "source" not in yaml_data:
118+
return
119+
if isinstance(yaml_data["source"], str):
120+
self.append(ProblemSource(parse_setting(yaml_data, "source", "")))
121+
return
122+
if isinstance(yaml_data["source"], dict):
123+
source = parse_setting(yaml_data, "source", dict[str, str]())
124+
self.append(
125+
ProblemSource(
126+
parse_setting(source, "name", ""),
127+
parse_optional_setting(source, "url", str),
128+
)
129+
)
130+
return
131+
if isinstance(yaml_data["source"], list):
132+
sources = parse_setting(yaml_data, "source", list[dict[str, str]]())
133+
for raw_source in sources:
134+
source = parse_setting(raw_source, "source", dict[str, str]())
135+
self.append(
136+
ProblemSource(
137+
parse_setting(source, "name", ""),
138+
parse_optional_setting(source, "url", str),
139+
)
140+
)
141+
return
142+
warn("problem.yaml key 'source' does not have the correct type")
143+
144+
92145
class ProblemLimits:
93146
def __init__(
94147
self,
@@ -238,8 +291,7 @@ def __init__(
238291
self.uuid: str = parse_setting(yaml_data, "uuid", "")
239292
self.version: str = parse_setting(yaml_data, "version", "")
240293
self.credits = ProblemCredits(yaml_data, self)
241-
self.source: str = parse_setting(yaml_data, "source", "")
242-
self.source_url: str = parse_setting(yaml_data, "source_url", "")
294+
self.source = ProblemSources(yaml_data, self)
243295
self.license: str = parse_setting(yaml_data, "license", "unknown")
244296
self.rights_owner: str = parse_setting(yaml_data, "rights_owner", "")
245297
# Not implemented in BAPCtools. Should be a date, but we don't do anything with this anyway.

skel/problem/problem.yaml

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,15 @@
11
# Specification: https://icpc.io/problem-package-format/spec/2023-07-draft.html
22
problem_format_version: 2023-07-draft
3+
# 'pass-fail', 'interactive', 'multi-pass', or 'interactive multi-pass'
4+
type: {%type%}
35
name:
46
#lang: name
57
{%problemname%}
6-
# 'pass-fail', 'interactive', 'multi-pass', or 'interactive multi-pass'
7-
type: {%type%}
8-
credits: {%author%}
9-
# Contest name and year
10-
source: {%source%}
11-
# contest.region.eu
12-
source_url: {%source_url%}
138
uuid: {%uuid%}
9+
credits: {%author%}
10+
source:
11+
name: {%source%}
12+
url: {%source_url%}
1413
license: {%license%}
1514
rights_owner: {%rights_owner%}
1615

0 commit comments

Comments
 (0)