Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(docs): docs generation #76

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 11 additions & 17 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,26 @@ name: Lint and Test

on:
push:
branches: [ main ]
branches: [ main, new-1.x.x ]
pull_request:
branches: [ main, new-1.x.x ]


concurrency:
group: ${{ github.workflow }}-${{ github.ref_name || github.ref }}
group: ${{ github.workflow }}-${{ github.ref_name | github.ref }}
cancel-in-progress: true


env:
PYTHON_VERSIONS: ['3.8', '3.9', '3.10', '3.11', '3.12']


jobs:
package-lint:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ${{ env.PYTHON_VERSIONS }}
fail-fast: false
steps:
- uses: actions/checkout@v4
Expand All @@ -36,7 +40,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ${{ env.PYTHON_VERSIONS }}
fail-fast: false
steps:
- uses: actions/checkout@v4
Expand All @@ -63,7 +67,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.8', '3.9', '3.10', '3.11', '3.12']
python-version: ${{ env.PYTHON_VERSIONS }}
fail-fast: false
steps:
- uses: actions/checkout@v4
Expand All @@ -84,14 +88,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.12
cache: 'pip' # caching pip dependencies
- name: Install dependencies
run: |
echo "TODO: add docs dependencies"
# python -m pip install -e .[docs]
python -m pip install -e .[docs]
- name: TODO
run: |
echo "TODO: add docs tests"
Expand All @@ -100,14 +99,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: 3.12
cache: 'pip' # caching pip dependencies
- name: Install dependencies
run: |
echo "TODO: add docs dependencies"
# python -m pip install -e .[docs]
python -m pip install -e .[docs]
- name: TODO
run: |
echo "TODO: add docs preview"
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -132,3 +132,7 @@ dmypy.json

# Pyre type checker
.pyre/

# Specified files
docs/ignore_me__production.md
docs/ignore_me__system_setup.md
7 changes: 5 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -52,12 +52,15 @@ format:
# Build the documentation
docs-build:
@echo "[make] Building the documentation..."
@echo "TODO"
mike deploy `cat VERSION`
mike set-default `cat VERSION`

# Serve the documentation in development mode
docs-serve:
@echo "[make] Serve the documentation..."
@echo "TODO"
mike deploy `cat VERSION`
mike set-default `cat VERSION`
mike serve


.PHONY: all help test-unit test-integration test-docstests test lint format docs-build docs-serve
25 changes: 1 addition & 24 deletions checker/__main__.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
from __future__ import annotations

import json
import os
import sys
from pathlib import Path
Expand All @@ -11,7 +10,7 @@
from checker.tester import Tester
from checker.utils import print_info

from .configs import CheckerConfig, DeadlinesConfig, TaskConfig
from .configs import CheckerConfig, DeadlinesConfig
from .exceptions import BadConfig, TestingError


Expand Down Expand Up @@ -280,27 +279,5 @@ def grade(
print_info("TESTING PASSED", color="green")


@cli.command(hidden=True)
@click.argument("output_folder", type=ClickReadableDirectory, default=".")
@click.pass_context
def schema(
ctx: click.Context,
output_folder: Path,
) -> None:
"""
Generate json schema for the checker configs.
"""
checker_schema = CheckerConfig.get_json_schema()
deadlines_schema = DeadlinesConfig.get_json_schema()
task_schema = TaskConfig.get_json_schema()

with open(output_folder / "schema-checker.json", "w") as f:
json.dump(checker_schema, f, indent=2)
with open(output_folder / "schema-deadlines.json", "w") as f:
json.dump(deadlines_schema, f, indent=2)
with open(output_folder / "schema-task.json", "w") as f:
json.dump(task_schema, f, indent=2)


if __name__ == "__main__":
cli()
16 changes: 7 additions & 9 deletions checker/configs/checker.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
from __future__ import annotations

from enum import Enum
from typing import Any, Union, Optional
from typing import Any, Union

from pydantic import AnyUrl, Field, RootModel, ValidationError, field_validator

Expand All @@ -14,10 +14,9 @@


class CheckerStructureConfig(CustomBaseModel):
# Note: use Optional/Union[...] instead of ... | None as pydantic does not support | in older python versions
ignore_patterns: Optional[list[str]] = None
private_patterns: Optional[list[str]] = None
public_patterns: Optional[list[str]] = None
ignore_patterns: list[str] | None = None
private_patterns: list[str] | None = None
public_patterns: list[str] | None = None
# TODO: add check "**" is not allowed


Expand Down Expand Up @@ -52,14 +51,13 @@ class FailType(Enum):
name: str
run: str

# Note: use Optional/Union[...] instead of ... | None as pydantic does not support | in older python versions
args: dict[str, Union[ParamType, TTemplate]] = Field(default_factory=dict)
args: dict[str, ParamType | TTemplate] = Field(default_factory=dict)

run_if: Union[bool, TTemplate, None] = None
run_if: bool | TTemplate | None = None
fail: FailType = FailType.FAST

# save pipline stage result to context under this key
register_output: Optional[str] = None
register_output: str | None = None


class CheckerTestingConfig(CustomBaseModel):
Expand Down
15 changes: 6 additions & 9 deletions checker/configs/deadlines.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import sys
from datetime import datetime, timedelta
from enum import Enum
from typing import cast, Union, Optional
from typing import cast

if sys.version_info < (3, 8):
from pytz import (
Expand All @@ -26,12 +26,11 @@ class DeadlinesType(Enum):
class DeadlinesSettingsConfig(CustomBaseModel):
timezone: str

# Note: use Optional/Union[...] instead of ... | None as pydantic does not support | in older python versions
deadlines: DeadlinesType = DeadlinesType.HARD
max_submissions: Optional[int] = None
max_submissions: int | None = None
submission_penalty: float = 0

task_url: Optional[AnyUrl] = None # $GROUP_NAME $TASK_NAME vars are available
task_url: AnyUrl | None = None # $GROUP_NAME $TASK_NAME vars are available

@field_validator("task_url")
@classmethod
Expand Down Expand Up @@ -66,8 +65,7 @@ class DeadlinesTaskConfig(CustomBaseModel):
bonus: int = 0
special: int = 0

# Note: use Optional/Union[...] instead of ... | None as pydantic does not support | in older python versions
url: Optional[AnyUrl] = None
url: AnyUrl | None = None

@property
def name(self) -> str:
Expand All @@ -79,10 +77,9 @@ class DeadlinesGroupConfig(CustomBaseModel):

enabled: bool = True

# Note: use Optional/Union[...] instead of ... | None as pydantic does not support | in older python versions
start: datetime
steps: dict[float, Union[datetime, timedelta]] = Field(default_factory=dict)
end: Union[datetime, timedelta, None] = None
steps: dict[float, datetime | timedelta] = Field(default_factory=dict)
end: datetime | timedelta | None = None

tasks: list[DeadlinesTaskConfig] = Field(default_factory=list)

Expand Down
11 changes: 4 additions & 7 deletions checker/configs/task.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from __future__ import annotations

from typing import Optional

from pydantic import Field, model_validator

from .checker import (
Expand All @@ -17,8 +15,7 @@ class TaskConfig(CustomBaseModel, YamlLoaderMixin['TaskConfig']):

version: int # if config exists, version is always present

# Note: use Optional[...] instead of ... | None as pydantic does not support | in older python versions
structure: Optional[CheckerStructureConfig] = None
parameters: Optional[CheckerParametersConfig] = None
task_pipeline: Optional[list[PipelineStageConfig]] = None
report_pipeline: Optional[list[PipelineStageConfig]] = None
structure: CheckerStructureConfig | None = None
parameters: CheckerParametersConfig | None = None
task_pipeline: list[PipelineStageConfig] | None = None
report_pipeline: list[PipelineStageConfig] | None = None
7 changes: 2 additions & 5 deletions checker/configs/utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
from __future__ import annotations

import re
from pathlib import Path
from typing import Any, Generic, TypeVar, Type, Protocol
Expand Down Expand Up @@ -42,6 +40,5 @@ def to_yaml(self: T, path: Path) -> None:
with path.open("w") as f:
yaml.dump(self.model_dump(), f)

@classmethod
def get_json_schema(cls: type[T]) -> dict[str, Any]:
return cls.model_json_schema()
def get_json_schema(self: T) -> dict[str, Any]:
return self.model_json_schema()
1 change: 1 addition & 0 deletions checker/plugins/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import sys
from collections.abc import Sequence
from pathlib import Path
from typing import Type

from .base import PluginABC, PluginOutput # noqa: F401

Expand Down
4 changes: 2 additions & 2 deletions checker/plugins/aggregate.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
from __future__ import annotations

from typing import Literal, Union
from typing import Literal

from ..exceptions import PluginExecutionFailed
from .base import PluginABC, PluginOutput
Expand All @@ -13,7 +13,7 @@ class AggregatePlugin(PluginABC):

class Args(PluginABC.Args):
scores: list[float]
weights: Union[list[float], None] = None # as pydantic does not support | in older python versions
weights: list[float] | None = None
strategy: Literal["mean", "sum", "min", "max", "product"] = "mean"
# TODO: validate for weights: len weights should be equal to len scores
# TODO: validate not empty scores
Expand Down
6 changes: 2 additions & 4 deletions checker/plugins/manytask.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from __future__ import annotations

from typing import Union

from .base import PluginABC, PluginOutput


Expand All @@ -11,8 +9,8 @@ class AggregatePlugin(PluginABC):
name = "report_score_manytask"

class Args(PluginABC.Args):
origin: Union[str, None] = None # as pydantic does not support | in older python versions
patterns: Union[list[str], None] = None # as pydantic does not support | in older python versions
origin: str | None = None
patterns: list[str] | None = None
username: str
task_name: str
score: float # TODO: validate score is in [0, 1] (bonus score?)
Expand Down
6 changes: 2 additions & 4 deletions checker/plugins/scripts.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
from __future__ import annotations

from typing import Union

from pydantic import Field

from ..exceptions import PluginExecutionFailed
Expand All @@ -15,8 +13,8 @@ class RunScriptPlugin(PluginABC):

class Args(PluginABC.Args):
origin: str
script: Union[str, list[str]] # as pydantic does not support | in older python versions
timeout: Union[float, None] = None # as pydantic does not support | in older python versions
script: str | list[str]
timeout: float | None = None
isolate: bool = False
env_whitelist: list[str] = Field(default_factory=lambda: ["PATH"])

Expand Down
6 changes: 3 additions & 3 deletions docs/3_plugins.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,18 +10,18 @@ You can refer to the [course-template](https://github.com/manytask/course-templa
Plugin is a single stage of the pipeline, have arguments, return exclusion result.
In a nutshell, it is a Python class overriding abstract class `checker.plugins.PluginABC`:

::: checker.plugins.PluginABC
::: checker.plugins.base.PluginABC
handler: python

Note that each plugin should override `checker.plugins.PluginABC.Args` class to provide arguments validation. Otherwise, empty arguments will be passed to `run` method.

::: checker.plugins.PluginABC.Args
::: checker.plugins.base.PluginABC.Args
handler: python


Each plugin output `checker.plugins.PluginOutput` class when executed successfully.

::: checker.plugins.PluginOutput
::: checker.plugins.base.PluginOutput
handler: python

In case of error, `checker.exceptions.PluginExecutionFailed` have to be raised.
Expand Down
20 changes: 13 additions & 7 deletions docs/4_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,21 @@
This section describes advanced usage of the checker.


## CLI
[//]: # (## CLI)

The main checker functionality is available via CLI.
[//]: # ()
[//]: # (The main checker functionality is available via CLI.)

::: mkdocs-click
:module: checker.__main__
:command: cli
:list_subcommands: True
:style: table
[//]: # ()
[//]: # (::: mkdocs-click)

[//]: # ( :module: checker.__main__)

[//]: # ( :command: cli)

[//]: # ( :list_subcommands: True)

[//]: # ( :style: table)


## Docker
Expand Down
4 changes: 4 additions & 0 deletions docs/6_changelog.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{%
include-markdown "../CHANGELOG.md"
heading-offset=0
%}
Binary file added docs/images/logo-manytask.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading
Loading