Skip to content

Commit

Permalink
Add functions for better searching for files
Browse files Browse the repository at this point in the history
  • Loading branch information
MasloMaslane committed Sep 13, 2023
1 parent 72833f2 commit e66595f
Show file tree
Hide file tree
Showing 12 changed files with 88 additions and 50 deletions.
13 changes: 5 additions & 8 deletions src/sinol_make/commands/gen/gen_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,14 @@ def ingen_exists(task_id):
:param task_id: task id, for example abc
:return: True if exists, False otherwise
"""
return len(glob.glob(os.path.join(os.getcwd(), 'prog', task_id + 'ingen.*'))) > 0
return package_util.any_files_matching_pattern(task_id, f'{task_id}ingen.*')


def get_ingen(task_id=None, ingen_path=None):
def get_ingen(task_id, ingen_path=None):
"""
Find ingen source file in `prog/` directory.
If `ingen_path` is specified, then it will be used (if exists).
:param task_id: task id, for example abc. If None, then
will return any ingen matching "*ingen.*"
:param task_id: task id, for example abc.
:param ingen_path: path to ingen source file
:return: path to ingen source file or None if not found
"""
Expand All @@ -35,9 +34,7 @@ def get_ingen(task_id=None, ingen_path=None):
else:
util.exit_with_error(f'Ingen source file {ingen_path} does not exist.')

if task_id is None:
task_id = '*'
ingen = glob.glob(os.path.join(os.getcwd(), 'prog', task_id + 'ingen.*'))
ingen = package_util.get_files_matching_pattern(task_id, f'{task_id}ingen.*')
if len(ingen) == 0:
util.exit_with_error(f'Ingen source file for task {task_id} does not exist.')

Expand Down Expand Up @@ -78,7 +75,7 @@ def get_correct_solution(task_id):
:param task_id: task id, for example abc
:return: path to correct solution or None if not found
"""
correct_solution = glob.glob(os.path.join(os.getcwd(), 'prog', task_id + '.*'))
correct_solution = package_util.get_files_matching_pattern(task_id, f'{task_id}.*')
if len(correct_solution) == 0:
util.exit_with_error(f'Correct solution for task {task_id} does not exist.')
return correct_solution[0]
Expand Down
2 changes: 1 addition & 1 deletion src/sinol_make/commands/inwer/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,7 +134,7 @@ def run(self, args: argparse.Namespace):
print(f'Verifying with inwer {util.bold(relative_path)}')

self.cpus = args.cpus or mp.cpu_count()
self.tests = package_util.get_tests(args.tests)
self.tests = package_util.get_tests(self.task_id, args.tests)

if len(self.tests) == 0:
util.exit_with_error('No tests found.')
Expand Down
2 changes: 1 addition & 1 deletion src/sinol_make/commands/inwer/inwer_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ def get_inwer_path(task_id: str, path = None) -> Union[str, None]:
Returns path to inwer executable for given task or None if no inwer was found.
"""
if path is None:
inwers = glob.glob(os.path.join(os.getcwd(), 'prog', f'{task_id}inwer.*'))
inwers = package_util.get_files_matching_pattern(task_id, f'{task_id}inwer.*')
if len(inwers) == 0:
return None
return inwers[0]
Expand Down
8 changes: 4 additions & 4 deletions src/sinol_make/commands/run/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -716,7 +716,7 @@ def get_whole_groups(self):
Returns a list of groups for which all tests were run.
"""
group_sizes = {}
for test in package_util.get_tests():
for test in package_util.get_tests(self.ID):
group = package_util.get_group(test, self.ID)
if group not in group_sizes:
group_sizes[group] = 0
Expand Down Expand Up @@ -1005,7 +1005,7 @@ def exit(self):
cnt=len(self.failed_compilations), letter='' if len(self.failed_compilations) == 1 else 's'))

def set_scores(self):
self.tests = package_util.get_tests(self.args.tests)
self.tests = package_util.get_tests(self.ID, self.args.tests)
self.groups = self.get_groups(self.tests)
self.scores = collections.defaultdict(int)

Expand Down Expand Up @@ -1129,7 +1129,7 @@ def run(self, args):
print("Task: %s (tag: %s)" % (title, self.ID))
self.cpus = args.cpus or mp.cpu_count()

checker = glob.glob(os.path.join(os.getcwd(), "prog", f'{self.ID}chk.*'))
checker = package_util.get_files_matching_pattern(self.ID, f'{self.ID}chk.*')
if len(checker) != 0:
print(util.info("Checker found: %s" % os.path.basename(checker[0])))
self.checker = checker[0]
Expand All @@ -1142,7 +1142,7 @@ def run(self, args):
else:
self.checker = None

lib = glob.glob(os.path.join(os.getcwd(), "prog", f'{self.ID}lib.*'))
lib = package_util.get_files_matching_pattern(self.ID, f'{self.ID}lib.*')
self.has_lib = len(lib) != 0

self.set_scores()
Expand Down
49 changes: 42 additions & 7 deletions src/sinol_make/helpers/package_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import re
import yaml
import glob
import fnmatch
from enum import Enum
from typing import List, Union, Dict, Any

Expand Down Expand Up @@ -34,28 +35,29 @@ def extract_test_id(test_path, task_id):
return os.path.split(os.path.splitext(test_path)[0])[1][len(task_id):]


def get_group(test_path, task_id=None):
def get_group(test_path, task_id):
if extract_test_id(test_path, task_id).endswith("ocen"):
return 0
return int("".join(filter(str.isdigit, extract_test_id(test_path, task_id))))


def get_test_key(test):
return get_group(test), test
def get_test_key(test, task_id):
return get_group(test, task_id), test


def get_tests(arg_tests: Union[List[str], None] = None) -> List[str]:
def get_tests(task_id: str, arg_tests: Union[List[str], None] = None) -> List[str]:
"""
Returns list of tests to run.
:param task_id: Task id.
:param arg_tests: Tests specified in command line arguments. If None, all tests are returned.
:return: List of tests to run.
"""
if arg_tests is None:
all_tests = ["in/%s" % test for test in os.listdir("in/")
if test[-3:] == ".in"]
return sorted(all_tests, key=get_test_key)
return sorted(all_tests, key=lambda test: get_test_key(test, task_id))
else:
return sorted(list(set(arg_tests)), key=get_test_key)
return sorted(list(set(arg_tests)), key=lambda test: get_test_key(test, task_id))


def get_file_name(file_path):
Expand Down Expand Up @@ -109,7 +111,7 @@ def _get_limit_from_dict(dict: Dict[str, Any], limit_type: LimitTypes, test_id:

def _get_limit(limit_type: LimitTypes, test_path: str, config: Dict[str, Any], lang: str, task_id: str):
test_id = extract_test_id(test_path, task_id)
test_group = str(get_group(test_path))
test_group = str(get_group(test_path, task_id))
global_limit = _get_limit_from_dict(config, limit_type, test_id, test_group, test_path)
override_limits_dict = config.get("override_limits", {}).get(lang, {})
overriden_limit = _get_limit_from_dict(override_limits_dict, limit_type, test_id, test_group, test_path)
Expand Down Expand Up @@ -167,3 +169,36 @@ def get_invalid_files(path, pattern):
invalid_out_tests = get_invalid_files(os.path.join("out", "*.out"), out_test_re)
if len(invalid_out_tests) > 0:
util.exit_with_error(f'Output tests with invalid names: {", ".join(invalid_out_tests)}.')


def get_all_code_files(task_id: str) -> List[str]:
"""
Returns all code files in package.
:param task_id: Task id.
:return: List of code files.
"""
result = glob.glob(os.path.join(os.getcwd(), "prog", f"{task_id}ingen.sh"))
for ext in ["c", "cpp", "py", "java"]:
result += glob.glob(os.path.join(os.getcwd(), f"prog/{task_id}*.{ext}"))
return result


def get_files_matching_pattern(task_id: str, pattern: str) -> List[str]:
"""
Returns all files in package matching given pattern.
:param task_id: Task id.
:param pattern: Pattern to match.
:return: List of files matching the pattern.
"""
all_files = get_all_code_files(task_id)
return [file for file in all_files if fnmatch.fnmatch(os.path.basename(file), pattern)]


def any_files_matching_pattern(task_id: str, pattern: str) -> bool:
"""
Returns True if any file in package matches given pattern.
:param task_id: Task id.
:param pattern: Pattern to match.
:return: True if any file in package matches given pattern.
"""
return len(get_files_matching_pattern(task_id, pattern)) > 0
6 changes: 0 additions & 6 deletions tests/commands/gen/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,6 @@ def test_get_ingen():
shutil.copytree(simple_package_path, os.path.join(tmpdir, 'simple'))
os.chdir(os.path.join(tmpdir, 'simple'))

ingen_path = gen_util.get_ingen()
assert os.path.basename(ingen_path) == "abcingen.cpp"

ingen_path = gen_util.get_ingen("abc")
assert os.path.basename(ingen_path) == "abcingen.cpp"

Expand All @@ -37,9 +34,6 @@ def test_get_ingen():
shutil.copytree(gen_package_path, os.path.join(tmpdir, 'gen'))
os.chdir(os.path.join(tmpdir, 'gen'))

ingen_path = gen_util.get_ingen()
assert os.path.basename(ingen_path) == "geningen.sh"

ingen_path = gen_util.get_ingen("gen")
assert os.path.basename(ingen_path) == "geningen.sh"

Expand Down
16 changes: 11 additions & 5 deletions tests/commands/inwer/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

from sinol_make import configure_parsers
from sinol_make.commands.inwer import Command
from sinol_make.helpers import package_util
from tests import util
from tests.fixtures import *

Expand All @@ -12,7 +13,8 @@ def test_default(capsys, create_package):
Test `inwer` command with no parameters.
"""
package_path = create_package
util.create_ins(package_path)
task_id = package_util.get_task_id()
util.create_ins(package_path, task_id)
parser = configure_parsers()
args = parser.parse_args(["inwer"])
command = Command()
Expand All @@ -33,7 +35,8 @@ def test_specified_inwer(capsys, create_package):
Test `inwer` command with specified inwer.
"""
package_path = create_package
util.create_ins(package_path)
task_id = package_util.get_task_id()
util.create_ins(package_path, task_id)
parser = configure_parsers()
args = parser.parse_args(["inwer", "prog/werinwer.cpp"])
command = Command()
Expand Down Expand Up @@ -66,7 +69,8 @@ def test_asserting_inwer(capsys, create_package):
Test `inwer` command with inwer that uses assert for verifying.
"""
package_path = create_package
util.create_ins(package_path)
task_id = package_util.get_task_id()
util.create_ins(package_path, task_id)
parser = configure_parsers()
args = parser.parse_args(["inwer", "prog/werinwer3.cpp"])
command = Command()
Expand All @@ -87,7 +91,8 @@ def test_flag_tests(capsys, create_package):
Test `inwer` command with --tests flag.
"""
package_path = create_package
util.create_ins(package_path)
task_id = package_util.get_task_id()
util.create_ins(package_path, task_id)
parser = configure_parsers()
args = parser.parse_args(["inwer", "prog/werinwer.cpp", "--tests", "in/wer2a.in"])
command = Command()
Expand Down Expand Up @@ -125,7 +130,8 @@ def test_no_output(capsys, create_package):
Test `inwer` command when inwer doesn't print anything.
"""
package_path = create_package
util.create_ins(package_path)
task_id = package_util.get_task_id()
util.create_ins(package_path, task_id)
parser = configure_parsers()
args = parser.parse_args(["inwer", "prog/werinwer4.cpp"])
command = Command()
Expand Down
3 changes: 2 additions & 1 deletion tests/commands/inwer/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,8 @@ def test_asserting_inwer(create_package):
Test asserting inwer.
"""
package_path = create_package
util.create_ins(package_path)
task_id = package_util.get_task_id()
util.create_ins(package_path, task_id)
inwer_path = os.path.join(os.getcwd(), 'prog', 'werinwer3.cpp')
args = argparse.Namespace(
c_compiler_path=compiler.get_c_compiler_path(),
Expand Down
5 changes: 3 additions & 2 deletions tests/commands/run/test_integration.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ def test_no_expected_scores(capsys, create_package, time_tool):

out = capsys.readouterr().out
assert "Solutions were added:" in out
solution = glob.glob(os.path.join(package_path, "prog", "???.*"))[0]
solution = package_util.get_files_matching_pattern(command.ID, f"{command.ID}.*")[0]
assert os.path.basename(solution) in out


Expand Down Expand Up @@ -219,7 +219,8 @@ def test_flag_solutions(capsys, create_package, time_tool):
package_path = create_package
create_ins_outs(package_path)

solutions = glob.glob(os.path.join(package_path, "prog", "????.*"))
task_id = package_util.get_task_id()
solutions = package_util.get_files_matching_pattern(task_id, f'{task_id}?.*')
parser = configure_parsers()
args = parser.parse_args(["run", "--solutions", solutions[0], "--time-tool", time_tool])
command = Command()
Expand Down
8 changes: 4 additions & 4 deletions tests/commands/run/test_unit.py
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ def test_execution(create_package, time_tool):
assert result == [True]

create_ins_outs(package_path)
test = package_util.get_tests(None)[0]
test = package_util.get_tests("abc", None)[0]

with open(os.path.join(package_path, "config.yml"), "r") as config_file:
config = yaml.load(config_file, Loader=yaml.FullLoader)
Expand Down Expand Up @@ -78,7 +78,7 @@ def test_run_solutions(create_package, time_tool):
command.args = argparse.Namespace(solutions_report=False, time_tool=time_tool, weak_compilation_flags=False,
hide_memory=False)
create_ins_outs(package_path)
command.tests = package_util.get_tests(None)
command.tests = package_util.get_tests("abc", None)
command.groups = list(sorted(set([command.get_group(test) for test in command.tests])))
command.scores = command.config["scores"]
command.possible_score = command.get_possible_score(command.groups)
Expand Down Expand Up @@ -132,7 +132,7 @@ def test_validate_expected_scores_success():
os.chdir(get_simple_package_path())
command = get_command()
command.scores = command.config["scores"]
command.tests = package_util.get_tests(None)
command.tests = package_util.get_tests("abc", None)

# Test with correct expected scores.
command.args = argparse.Namespace(solutions=["prog/abc.cpp"], tests=None)
Expand Down Expand Up @@ -439,7 +439,7 @@ def test_get_valid_input_files(create_package):
package_path = create_package
command = get_command(package_path)
create_ins_outs(package_path)
command.tests = package_util.get_tests(None)
command.tests = package_util.get_tests(command.ID, None)

outputs = glob.glob(os.path.join(package_path, "out", "*.out"))
os.unlink(outputs[0])
Expand Down
8 changes: 5 additions & 3 deletions tests/helpers/test_package_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,15 @@ def test_extract_test_id():


def test_get_group():
assert package_util.get_group("in/abc1a.in") == 1
assert package_util.get_group("in/abc1a.in", "abc") == 1
assert package_util.get_group("in/long_name2ocen.in", "long_name") == 0


def test_get_tests(create_package):
create_ins(create_package)
os.chdir(create_package)
tests = package_util.get_tests(None)
task_id = package_util.get_task_id()
create_ins(create_package, task_id)
tests = package_util.get_tests("abc", None)
assert tests == ["in/abc1a.in", "in/abc2a.in", "in/abc3a.in", "in/abc4a.in"]


Expand Down
18 changes: 10 additions & 8 deletions tests/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
import glob
import subprocess

from sinol_make.helpers import compile, paths
from sinol_make.helpers import compile, paths, package_util


def get_simple_package_path():
Expand Down Expand Up @@ -87,11 +87,11 @@ def get_long_name_package_path():
return os.path.join(os.path.dirname(__file__), "packages", "long_package_name")


def create_ins(package_path):
def create_ins(package_path, task_id):
"""
Create .in files for package.
"""
ingen = glob.glob(os.path.join(package_path, "prog", "*ingen.*"))[0]
ingen = package_util.get_files_matching_pattern(task_id, f'{task_id}ingen.*')[0]
ingen_executable = paths.get_executables_path("ingen.e")
os.makedirs(paths.get_executables_path(), exist_ok=True)
assert compile.compile(ingen, ingen_executable)
Expand All @@ -100,11 +100,11 @@ def create_ins(package_path):
os.chdir(package_path)


def create_outs(package_path):
def create_outs(package_path, task_id):
"""
Create .out files for package.
"""
solution = glob.glob(os.path.join(package_path, "prog", "???.*"))[0]
solution = package_util.get_files_matching_pattern(task_id, f'{task_id}.*')[0]
solution_executable = paths.get_executables_path("solution.e")
os.makedirs(paths.get_executables_path(), exist_ok=True)
assert compile.compile(solution, solution_executable)
Expand All @@ -120,7 +120,9 @@ def create_ins_outs(package_path):
"""
Create .in and .out files for package.
"""
create_ins(package_path)
has_lib = len(glob.glob(os.path.join(package_path, "prog", "???lib.*"))) > 0
os.chdir(package_path)
task_id = package_util.get_task_id()
create_ins(package_path, task_id)
has_lib = package_util.any_files_matching_pattern(task_id, f"{task_id}lib.*")
if not has_lib:
create_outs(package_path)
create_outs(package_path, task_id)

0 comments on commit e66595f

Please sign in to comment.