Skip to content

Commit

Permalink
style: apply black and isort
Browse files Browse the repository at this point in the history
  • Loading branch information
k4black committed Dec 14, 2023
1 parent 6b31f92 commit e7002a6
Show file tree
Hide file tree
Showing 23 changed files with 769 additions and 382 deletions.
142 changes: 107 additions & 35 deletions checker/__main__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,22 +11,34 @@
from checker.course import Course, FileSystemTask
from checker.tester import Tester
from checker.utils import print_info

from .configs import CheckerConfig, DeadlinesConfig
from .exceptions import BadConfig, TestingError
from .plugins import load_plugins
from .tester.pipeline import PipelineRunner

ClickReadableFile = click.Path(exists=True, file_okay=True, readable=True, path_type=Path)
ClickReadableDirectory = click.Path(exists=True, file_okay=False, readable=True, path_type=Path)

ClickReadableFile = click.Path(
exists=True, file_okay=True, readable=True, path_type=Path
)
ClickReadableDirectory = click.Path(
exists=True, file_okay=False, readable=True, path_type=Path
)
ClickWritableDirectory = click.Path(file_okay=False, writable=True, path_type=Path)


@click.group(context_settings={"show_default": True})
@click.option(
"--checker-config", type=ClickReadableFile, default=".checker.yml", help="Path to the checker config file."
"--checker-config",
type=ClickReadableFile,
default=".checker.yml",
help="Path to the checker config file.",
)
@click.option(
"--deadlines-config", type=ClickReadableFile, default=".deadlines.yml", help="Path to the deadlines config file."
"--deadlines-config",
type=ClickReadableFile,
default=".deadlines.yml",
help="Path to the deadlines config file.",
)
@click.version_option(package_name="manytask-checker")
@click.pass_context
Expand All @@ -45,7 +57,9 @@ def cli(

@cli.command()
@click.argument("root", type=ClickReadableDirectory, default=".")
@click.option("-v/-s", "--verbose/--silent", is_flag=True, default=True, help="Verbose output")
@click.option(
"-v/-s", "--verbose/--silent", is_flag=True, default=True, help="Verbose output"
)
@click.pass_context
def validate(
ctx: click.Context,
Expand All @@ -64,42 +78,76 @@ def validate(
checker_config = CheckerConfig.from_yaml(ctx.obj["course_config_path"])
deadlines_config = DeadlinesConfig.from_yaml(ctx.obj["deadlines_config_path"])
except BadConfig as e:
print_info("Configuration Failed", color='red')
print_info("Configuration Failed", color="red")
print_info(e)
exit(1)
print_info("Ok", color='green')
print_info("Ok", color="green")

print_info("Validating Course Structure (and tasks configs)...")
try:
course = Course(checker_config, deadlines_config, root)
course.validate()
except BadConfig as e:
print_info("Course Validation Failed", color='red')
print_info("Course Validation Failed", color="red")
print_info(e)
exit(1)
print_info("Ok", color='green')
print_info("Ok", color="green")

print_info("Validating tester...")
try:
tester = Tester(course, checker_config, verbose=verbose)
tester.validate()
except BadConfig as e:
print_info("Tester Validation Failed", color='red')
print_info("Tester Validation Failed", color="red")
print_info(e)
exit(1)
print_info("Ok", color='green')
print_info("Ok", color="green")


@cli.command()
@click.argument("root", type=ClickReadableDirectory, default=".")
@click.argument("reference_root", type=ClickReadableDirectory, default=".")
@click.option("-t", "--task", type=str, multiple=True, default=None, help="Task name to check (multiple possible)")
@click.option("-g", "--group", type=str, multiple=True, default=None, help="Group name to check (multiple possible)")
@click.option("-p", "--parallelize", is_flag=True, default=True, help="Execute parallel checking of tasks")
@click.option("-n", "--num-processes", type=int, default=os.cpu_count(), help="Num of processes parallel checking")
@click.option(
"-t",
"--task",
type=str,
multiple=True,
default=None,
help="Task name to check (multiple possible)",
)
@click.option(
"-g",
"--group",
type=str,
multiple=True,
default=None,
help="Group name to check (multiple possible)",
)
@click.option(
"-p",
"--parallelize",
is_flag=True,
default=True,
help="Execute parallel checking of tasks",
)
@click.option(
"-n",
"--num-processes",
type=int,
default=os.cpu_count(),
help="Num of processes parallel checking",
)
@click.option("--no-clean", is_flag=True, help="Clean or not check tmp folders")
@click.option("-v/-s", "--verbose/--silent", is_flag=True, default=True, help="Verbose tests output")
@click.option("--dry-run", is_flag=True, help="Do not execute anything, only log actions")
@click.option(
"-v/-s",
"--verbose/--silent",
is_flag=True,
default=True,
help="Verbose tests output",
)
@click.option(
"--dry-run", is_flag=True, help="Do not execute anything, only log actions"
)
@click.pass_context
def check(
ctx: click.Context,
Expand All @@ -122,7 +170,7 @@ def check(
deadlines_config = DeadlinesConfig.from_yaml(ctx.obj["deadlines_config_path"])

# read filesystem, check existing tasks
course = Course(checker_config, deadlines_config, root, username='private')
course = Course(checker_config, deadlines_config, root, username="private")

# validate tasks and groups if passed
filesystem_tasks: dict[str, FileSystemTask] = dict()
Expand All @@ -139,32 +187,51 @@ def check(
print_info(f"Checking tasks: {', '.join(filesystem_tasks.keys())}")

# create tester to... to test =)
tester = Tester(course, checker_config, verbose=verbose, cleanup=not no_clean, dry_run=dry_run)
tester = Tester(
course, checker_config, verbose=verbose, cleanup=not no_clean, dry_run=dry_run
)

# run tests
# TODO: progressbar on parallelize
try:
tester.run(tasks=list(filesystem_tasks.values()) if filesystem_tasks else None, report=False)
tester.run(
tasks=list(filesystem_tasks.values()) if filesystem_tasks else None,
report=False,
)
except TestingError as e:
print_info("TESTING FAILED", color='red')
print_info("TESTING FAILED", color="red")
print_info(e)
exit(1)
except Exception as e:
print_info("UNEXPECTED ERROR", color='red')
print_info("UNEXPECTED ERROR", color="red")
print_info(e)
exit(1)
print_info("TESTING PASSED", color='green')
print_info("TESTING PASSED", color="green")


@cli.command()
@click.argument("root", type=ClickReadableDirectory, default=".")
@click.argument("reference_root", type=ClickReadableDirectory, default=".")
@click.option("--submit-score", is_flag=True, help="Submit score to the Manytask server")
@click.option("--timestamp", type=str, default=None, help="Timestamp to use for the submission")
@click.option("--username", type=str, default=None, help="Username to use for the submission")
@click.option(
"--submit-score", is_flag=True, help="Submit score to the Manytask server"
)
@click.option(
"--timestamp", type=str, default=None, help="Timestamp to use for the submission"
)
@click.option(
"--username", type=str, default=None, help="Username to use for the submission"
)
@click.option("--no-clean", is_flag=True, help="Clean or not check tmp folders")
@click.option("-v/-s", "--verbose/--silent", is_flag=True, default=False, help="Verbose tests output")
@click.option("--dry-run", is_flag=True, help="Do not execute anything, only log actions")
@click.option(
"-v/-s",
"--verbose/--silent",
is_flag=True,
default=False,
help="Verbose tests output",
)
@click.option(
"--dry-run", is_flag=True, help="Do not execute anything, only log actions"
)
@click.pass_context
def grade(
ctx: click.Context,
Expand All @@ -185,30 +252,35 @@ def grade(
deadlines_config = DeadlinesConfig.from_yaml(ctx.obj["deadlines_config_path"])

# read filesystem, check existing tasks
course = Course(checker_config, deadlines_config, root, reference_root, username=username)
course = Course(
checker_config, deadlines_config, root, reference_root, username=username
)

# detect changes to test
filesystem_tasks: list[FileSystemTask] = list()
# TODO: detect changes
filesystem_tasks = [task for task in course.get_tasks(enabled=True) if task.name == 'hello_world']
filesystem_tasks = [
task for task in course.get_tasks(enabled=True) if task.name == "hello_world"
]

# create tester to... to test =)
tester = Tester(course, checker_config, verbose=verbose, cleanup=not no_clean, dry_run=dry_run)
tester = Tester(
course, checker_config, verbose=verbose, cleanup=not no_clean, dry_run=dry_run
)

# run tests
# TODO: progressbar on parallelize
try:
tester.run(tasks=filesystem_tasks, report=True)
except TestingError as e:
print_info("TESTING FAILED", color='red')
print_info("TESTING FAILED", color="red")
print_info(e)
exit(1)
except Exception as e:
print_info("UNEXPECTED ERROR", color='red')
print_info("UNEXPECTED ERROR", color="red")
print_info(e)
raise e
exit(1)
print_info("TESTING PASSED", color='green')
print_info("TESTING PASSED", color="green")


if __name__ == "__main__":
Expand Down
9 changes: 7 additions & 2 deletions checker/configs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,14 @@
from .checker import CheckerTestingConfig # noqa: F401
from .checker import (
CheckerConfig,
CheckerExportConfig,
CheckerManytaskConfig,
CheckerTestingConfig, # noqa: F401
PipelineStageConfig,
)
from .deadlines import DeadlinesConfig, DeadlinesGroupConfig, DeadlinesSettingsConfig, DeadlinesTaskConfig # noqa: F401
from .deadlines import (
DeadlinesConfig,
DeadlinesGroupConfig,
DeadlinesSettingsConfig,
DeadlinesTaskConfig,
) # noqa: F401
from .task import TaskConfig # noqa: F401
1 change: 0 additions & 1 deletion checker/configs/checker.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ class CheckerManytaskConfig(CustomBaseModel):


class PipelineStageConfig(CustomBaseModel):

class FailType(Enum):
FAST = "fast"
AFTER_ALL = "after_all"
Expand Down
43 changes: 30 additions & 13 deletions checker/configs/deadlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,16 @@
from datetime import datetime, timedelta
from enum import Enum


if sys.version_info < (3, 8):
from pytz import timezone as ZoneInfo
from pytz import ZoneInfoNotFoundError as ZoneInfoNotFoundError
from pytz import (
ZoneInfoNotFoundError as ZoneInfoNotFoundError,
timezone as ZoneInfo,
)
else:
from zoneinfo import ZoneInfo, ZoneInfoNotFoundError

from pydantic import Field, field_validator, model_validator, AnyUrl
from pydantic import AnyUrl, Field, field_validator, model_validator

from .utils import CustomBaseModel, YamlLoaderMixin

Expand Down Expand Up @@ -90,12 +93,18 @@ def check_dates(self) -> "DeadlinesGroupConfig":
if isinstance(self.end, timedelta) and self.end < timedelta():
raise ValueError(f"end timedelta <{self.end}> should be positive")
if isinstance(self.end, datetime) and self.end < self.start:
raise ValueError(f"end datetime <{self.end}> should be after the start <{self.start}>")
raise ValueError(
f"end datetime <{self.end}> should be after the start <{self.start}>"
)

# check steps
last_step_date_or_delta = self.start
for _, date_or_delta in self.steps.items():
step_date = self.start + date_or_delta if isinstance(date_or_delta, timedelta) else date_or_delta
step_date = (
self.start + date_or_delta
if isinstance(date_or_delta, timedelta)
else date_or_delta
)
last_step_date = (
self.start + last_step_date_or_delta
if isinstance(last_step_date_or_delta, timedelta)
Expand All @@ -105,7 +114,9 @@ def check_dates(self) -> "DeadlinesGroupConfig":
if isinstance(date_or_delta, timedelta) and date_or_delta < timedelta():
raise ValueError(f"step timedelta <{date_or_delta}> should be positive")
if isinstance(date_or_delta, datetime) and date_or_delta <= self.start:
raise ValueError(f"step datetime <{date_or_delta}> should be after the start {self.start}")
raise ValueError(
f"step datetime <{date_or_delta}> should be after the start {self.start}"
)

if step_date <= last_step_date:
raise ValueError(
Expand All @@ -125,8 +136,8 @@ class DeadlinesConfig(CustomBaseModel, YamlLoaderMixin):
schedule: list[DeadlinesGroupConfig]

def get_groups(
self,
enabled: bool | None = None,
self,
enabled: bool | None = None,
) -> list[DeadlinesGroupConfig]:
groups = [group for group in self.schedule]

Expand All @@ -138,10 +149,12 @@ def get_groups(
return groups

def get_tasks(
self,
enabled: bool | None = None,
self,
enabled: bool | None = None,
) -> list[DeadlinesTaskConfig]:
tasks = [task for group in self.get_groups(enabled=enabled) for task in group.tasks]
tasks = [
task for group in self.get_groups(enabled=enabled) for task in group.tasks
]

if enabled is not None:
tasks = [task for task in tasks if task.enabled == enabled]
Expand All @@ -159,7 +172,9 @@ def check_version(cls, data: int) -> int:

@field_validator("schedule")
@classmethod
def check_group_names_unique(cls, data: list[DeadlinesGroupConfig]) -> list[DeadlinesGroupConfig]:
def check_group_names_unique(
cls, data: list[DeadlinesGroupConfig]
) -> list[DeadlinesGroupConfig]:
groups = [group.name for group in data]
duplicates = [name for name in groups if groups.count(name) > 1]
if duplicates:
Expand All @@ -168,7 +183,9 @@ def check_group_names_unique(cls, data: list[DeadlinesGroupConfig]) -> list[Dead

@field_validator("schedule")
@classmethod
def check_task_names_unique(cls, data: list[DeadlinesGroupConfig]) -> list[DeadlinesGroupConfig]:
def check_task_names_unique(
cls, data: list[DeadlinesGroupConfig]
) -> list[DeadlinesGroupConfig]:
tasks_names = [task.name for group in data for task in group.tasks]
duplicates = [name for name in tasks_names if tasks_names.count(name) > 1]
if duplicates:
Expand Down
6 changes: 5 additions & 1 deletion checker/configs/task.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,11 @@

from pydantic import Field, model_validator

from .checker import CheckerParametersConfig, CheckerStructureConfig, PipelineStageConfig
from .checker import (
CheckerParametersConfig,
CheckerStructureConfig,
PipelineStageConfig,
)
from .utils import CustomBaseModel, YamlLoaderMixin


Expand Down
Loading

0 comments on commit e7002a6

Please sign in to comment.