diff --git a/bin/export.py b/bin/export.py index 4c2ce5d8..bab6e8a0 100644 --- a/bin/export.py +++ b/bin/export.py @@ -49,9 +49,7 @@ def build_samples_zip(problems): attachments_dir = problem.path / 'attachments' if problem.interactive and not attachments_dir.is_dir(): - util.error( - f'Interactive problem {problem.name} does not have an attachments/ directory.' - ) + util.error(f'Interactive problem {problem.id} does not have an attachments/ directory.') continue empty = True @@ -78,7 +76,7 @@ def build_samples_zip(problems): empty = False if empty: - util.error(f'No attachments or samples found for problem {problem.name}.') + util.error(f'No attachments or samples found for problem {problem.id}.') zf.close() print("Wrote zip to samples.zip", file=sys.stderr) @@ -148,7 +146,7 @@ def build_problem_zip(problem, output, statement_language): out = out.with_suffix('.pdf') # For Kattis, prepend the problem shortname to all files. if config.args.kattis: - out = problem.name / out + out = problem.id / out copyfiles.add((f, out)) # Build .ZIP file. @@ -248,7 +246,7 @@ def export_contest(): # (YAML 1.2 parses it as a string.) if isinstance(value, int): str(datetime.timedelta(seconds=data[key])) - data[key] = value; + data[key] = value verbose("Uploading contest.yaml:") verbose(data) @@ -294,7 +292,7 @@ def update_problems_yaml(problems, colors=None): for problem in problems: found = False for d in data: - if d['id'] == problem.name: + if d['id'] == problem.id: found = True if problem.settings.name and problem.settings.name != d.get('name'): change = True @@ -313,10 +311,10 @@ def update_problems_yaml(problems, colors=None): break if not found: change = True - log(f'Add problem {problem.name}') + log(f'Add problem {problem.id}') data.append( { - 'id': problem.name, + 'id': problem.id, 'label': problem.label, 'name': problem.settings.name, 'rgb': '#000000', @@ -382,16 +380,16 @@ def export_problems(problems, cid): # Export a single problem to the specified contest ID. def export_problem(problem, cid, pid): if pid: - log(f'Export {problem.name} to id {pid}') + log(f'Export {problem.id} to id {pid}') else: - log(f'Export {problem.name} to new id') + log(f'Export {problem.id} to new id') - zipfile = Path(problem.name).with_suffix('.zip') + zipfile = Path(problem.id).with_suffix('.zip') if not zipfile.is_file(): error(f'Did not find {zipfile}. First run `bt zip`.') return data = None if pid is None else {'problem': pid} - zip_path = Path(problem.name).with_suffix('.zip') + zip_path = Path(problem.id).with_suffix('.zip') zipfile = zip_path.open('rb') r = call_api( 'POST', @@ -435,7 +433,7 @@ def get_problems(): def get_problem_id(problem): nonlocal ccs_problems for p in ccs_problems: - if p['short_name'] == problem.name or p.get('externalid') == problem.name: + if p['short_name'] == problem.id or p.get('externalid') == problem.id: return p['id'] for problem in problems: diff --git a/bin/latex.py b/bin/latex.py index 37057945..9b6f47ee 100644 --- a/bin/latex.py +++ b/bin/latex.py @@ -225,7 +225,7 @@ def build_problem_pdfs(problem, solutions=False): if (problem.path / f"problem_statement/solution.{lang}.tex").exists(): filtered_languages.append(lang) else: - warn(f'{problem.name}: solution.{lang}.tex not found') + warn(f'{problem.id}: solution.{lang}.tex not found') languages = filtered_languages return all(build_problem_pdf(problem, lang, solutions) for lang in languages) @@ -305,10 +305,10 @@ def build_contest_pdf(contest, problems, tmpdir, language, solutions=False, web= # All is good pass elif solutiontex.is_file(): - warn(f'{problem.name}: Rename solution.tex to solution.{language}.tex') + warn(f'{problem.id}: Rename solution.tex to solution.{language}.tex') continue else: - warn(f'{problem.name}: solution.{language}.tex not found') + warn(f'{problem.id}: solution.{language}.tex not found') continue problems_data += util.substitute( @@ -319,7 +319,7 @@ def build_contest_pdf(contest, problems, tmpdir, language, solutions=False, web= 'problemauthor': problem.settings.author, 'timelimit': get_tl(problem), 'problemdir': problem.path.absolute().as_posix(), - 'problemdirname': problem.name, + 'problemdirname': problem.id, 'builddir': problem.tmpdir.as_posix(), }, ) diff --git a/bin/problem.py b/bin/problem.py index 9dd39869..92b393ec 100644 --- a/bin/problem.py +++ b/bin/problem.py @@ -22,10 +22,10 @@ class Problem: def __init__(self, path, tmpdir, label=None): # The problem name/shortname, which is the name of the directory and used as a display name. - self.name = path.resolve().name + self.id = path.resolve().name # The Path of the problem directory. self.path = path - self.tmpdir = tmpdir / self.name + self.tmpdir = tmpdir / self.id # Read problem.yaml and domjudge-problem.ini into self.settings Namespace object. self._read_settings() @@ -43,15 +43,16 @@ def __init__(self, path, tmpdir, label=None): # TODO: transform this into nice warnings assert path.is_dir() - if not Problem._SHORTNAME_REGEX.match(self.name): + if not Problem._SHORTNAME_REGEX.match(self.id): warn( - f'Problem has a bad shortname: {self.name} does not match {self._SHORTNAME_REGEX_STRING}' + f'Problem has a bad shortname: {self.id} does not match {self._SHORTNAME_REGEX_STRING}' ) self.statement_languages = self._determine_statement_languages() def _determine_statement_languages(self): - """Determine the languages that are both mentioned in the problem.yaml under name + """ + Determine the languages that are both mentioned in the problem.yaml under name and have a corresponding problem statement. If problem.yaml's name key is a string, convert into dict; assume `en` as default language. @@ -64,11 +65,11 @@ def _determine_statement_languages(self): ) for lang in texfiles - yamlnames: error( - f"{self.name}: Found problem.{lang}.tex, but no corresponding name in problem.yaml." + f'{self.id}: Found problem.{lang}.tex, but no corresponding name in problem.yaml.' ) for lang in yamlnames - texfiles: error( - f"{self.name}: Found name for language {lang} in problem.yaml, but not problem.{lang}.tex." + f'{self.id}: Found name for language {lang} in problem.yaml, but not problem.{lang}.tex.' ) return sorted(texfiles & yamlnames) @@ -219,9 +220,9 @@ def maybe_copy(x): if len(testcases) == 0: if needinteraction: - warn(f'Didn\'t find any testcases with interaction for {p.name}') + warn(f'Didn\'t find any testcases with interaction for {p.id}') else: - warn(f'Didn\'t find any testcases{" with answer" if needans else ""} for {p.name}') + warn(f'Didn\'t find any testcases{" with answer" if needans else ""} for {p.id}') testcases = False p._testcases[key] = testcases diff --git a/bin/skel.py b/bin/skel.py index 6c9067b2..94552c14 100644 --- a/bin/skel.py +++ b/bin/skel.py @@ -243,7 +243,7 @@ def rename_problem(problem): else _ask_variable_string('dirname', _alpha_num(newname[problem.statement_languages[0]])) ) - shutil.move(problem.name, dirname) + shutil.move(problem.id, dirname) problem_yaml = Path(dirname) / 'problem.yaml' data = read_yaml(problem_yaml) @@ -253,7 +253,7 @@ def rename_problem(problem): problems_yaml = Path('problems.yaml') if problems_yaml.is_file(): data = read_yaml(problems_yaml) or [] - prob = next((p for p in data if p['id'] == problem.name), None) + prob = next((p for p in data if p['id'] == problem.id), None) if prob is not None: prob['id'] = dirname prob['name'] = newname @@ -308,6 +308,6 @@ def problem_source_dir(problem): problem_yml = (config.tools_root / 'skel/gitlab_ci/problem.yaml').read_text() for problem_obj in problems: changesdir = problem_source_dir(problem_obj) - problem = problem_obj.name + problem = problem_obj.id print('\n') print(substitute(problem_yml, locals()), end='') diff --git a/bin/slack.py b/bin/slack.py index 5299f0a5..41dfff94 100644 --- a/bin/slack.py +++ b/bin/slack.py @@ -4,7 +4,7 @@ # Function to create a slack channel for each problem def create_slack_channels(problems): for p in problems: - create_slack_channel(p.name) + create_slack_channel(p.id) # The slack user token is of the form xoxp-... @@ -33,7 +33,7 @@ def join_slack_channels(problems): channel_ids[c['name']] = c['id'] for p in problems: - join_slack_channel(p.name, channel_ids[p.name]) + join_slack_channel(p.id, channel_ids[p.id]) def join_slack_channel(name, id): diff --git a/bin/stats.py b/bin/stats.py index 5adc333d..02037965 100644 --- a/bin/stats.py +++ b/bin/stats.py @@ -68,7 +68,7 @@ def stats(problems): if header == 'problem': width = len(header) for problem in problems: - width = max(width, len(problem.label + ' ' + problem.name)) + width = max(width, len(problem.label + ' ' + problem.id)) header_string += '{:<' + str(width) + '}' format_string += '{:<' + str(width) + '}' elif header == ' comment': @@ -145,7 +145,7 @@ def value(x): print( format_string.format( - problem.label + ' ' + problem.name, + problem.label + ' ' + problem.id, *[ _get_stat( counts[i], diff --git a/bin/tools.py b/bin/tools.py index c7d0985a..848f9378 100755 --- a/bin/tools.py +++ b/bin/tools.py @@ -212,7 +212,7 @@ def get_pos(id): # Sort the problems # Use negative solves instead of reversed, to preserver stable order. - problems.sort(key=lambda p: (-solves[p.name], p.label)) + problems.sort(key=lambda p: (-solves[p.id], p.label)) order = ', '.join(map(lambda p: p.label, problems)) verbose('order: ' + order) @@ -830,7 +830,7 @@ def run_parsed_arguments(args): # Handle one-off subcommands. if action == 'tmp': if level == 'problem': - level_tmpdir = tmpdir / problems[0].name + level_tmpdir = tmpdir / problems[0].id else: level_tmpdir = tmpdir @@ -896,7 +896,7 @@ def run_parsed_arguments(args): and not config.args.all ): continue - print(Style.BRIGHT, 'PROBLEM ', problem.name, Style.RESET_ALL, sep='', file=sys.stderr) + print(Style.BRIGHT, 'PROBLEM ', problem.id, Style.RESET_ALL, sep='', file=sys.stderr) if action in ['generate']: success &= generate.generate(problem)