Skip to content

Commit 8c4dcea

Browse files
dhruvmanilastokhos
authored andcommitted
Validate only submitted Project Euler solution (TheAlgorithms#3977)
* Update validate solution script to fetch only submitted solution * Update workflow file with the updated PE script * Fix: do not fetch `validate_solutions.py` script * Update script to use the requests package for API calls * Fix: install requests module * Pytest ignore scripts/ directory
1 parent 5b9f710 commit 8c4dcea

File tree

3 files changed

+55
-10
lines changed

3 files changed

+55
-10
lines changed

Diff for: .github/workflows/build.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,6 @@ jobs:
2222
python -m pip install --upgrade pip setuptools six wheel
2323
python -m pip install pytest-cov -r requirements.txt
2424
- name: Run tests
25-
run: pytest --doctest-modules --ignore=project_euler/ --cov-report=term-missing:skip-covered --cov=. .
25+
run: pytest --doctest-modules --ignore=project_euler/ --ignore=scripts/ --cov-report=term-missing:skip-covered --cov=. .
2626
- if: ${{ success() }}
2727
run: scripts/build_directory_md.py 2>&1 | tee DIRECTORY.md

Diff for: .github/workflows/project_euler.yml

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
on:
22
pull_request:
3-
# only check if a file is changed within the project_euler directory and related files
3+
# Run only if a file is changed within the project_euler directory and related files
44
paths:
5-
- 'project_euler/**'
6-
- '.github/workflows/project_euler.yml'
7-
- 'scripts/validate_solutions.py'
5+
- "project_euler/**"
6+
- ".github/workflows/project_euler.yml"
7+
- "scripts/validate_solutions.py"
8+
schedule:
9+
- cron: "0 0 * * *" # Run everyday
810

9-
name: 'Project Euler'
11+
name: "Project Euler"
1012

1113
jobs:
1214
project-euler:
@@ -24,8 +26,10 @@ jobs:
2426
steps:
2527
- uses: actions/checkout@v2
2628
- uses: actions/setup-python@v2
27-
- name: Install pytest
29+
- name: Install pytest and requests
2830
run: |
2931
python -m pip install --upgrade pip
30-
python -m pip install --upgrade pytest
32+
python -m pip install --upgrade pytest requests
3133
- run: pytest scripts/validate_solutions.py
34+
env:
35+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

Diff for: scripts/validate_solutions.py

+43-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,13 @@
11
#!/usr/bin/env python3
22
import importlib.util
33
import json
4+
import os
45
import pathlib
56
from types import ModuleType
67
from typing import Dict, List
78

89
import pytest
10+
import requests
911

1012
PROJECT_EULER_DIR_PATH = pathlib.Path.cwd().joinpath("project_euler")
1113
PROJECT_EULER_ANSWERS_PATH = pathlib.Path.cwd().joinpath(
@@ -24,7 +26,7 @@ def convert_path_to_module(file_path: pathlib.Path) -> ModuleType:
2426
return module
2527

2628

27-
def collect_solution_file_paths() -> List[pathlib.Path]:
29+
def all_solution_file_paths() -> List[pathlib.Path]:
2830
"""Collects all the solution file path in the Project Euler directory"""
2931
solution_file_paths = []
3032
for problem_dir_path in PROJECT_EULER_DIR_PATH.iterdir():
@@ -37,12 +39,51 @@ def collect_solution_file_paths() -> List[pathlib.Path]:
3739
return solution_file_paths
3840

3941

42+
def get_files_url() -> str:
43+
"""Return the pull request number which triggered this action."""
44+
with open(os.environ["GITHUB_EVENT_PATH"]) as file:
45+
event = json.load(file)
46+
return event["pull_request"]["url"] + "/files"
47+
48+
49+
def added_solution_file_path() -> List[pathlib.Path]:
50+
"""Collects only the solution file path which got added in the current
51+
pull request.
52+
53+
This will only be triggered if the script is ran from GitHub Actions.
54+
"""
55+
solution_file_paths = []
56+
headers = {
57+
"Accept": "application/vnd.github.v3+json",
58+
"Authorization": "token " + os.environ["GITHUB_TOKEN"],
59+
}
60+
files = requests.get(get_files_url(), headers=headers).json()
61+
for file in files:
62+
filepath = pathlib.Path.cwd().joinpath(file["filename"])
63+
if (
64+
filepath.suffix != ".py"
65+
or filepath.name.startswith(("_", "test"))
66+
or not filepath.name.startswith("sol")
67+
):
68+
continue
69+
solution_file_paths.append(filepath)
70+
return solution_file_paths
71+
72+
73+
def collect_solution_file_paths() -> List[pathlib.Path]:
74+
if os.environ.get("CI") and os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
75+
# Return only if there are any, otherwise default to all solutions
76+
if filepaths := added_solution_file_path():
77+
return filepaths
78+
return all_solution_file_paths()
79+
80+
4081
@pytest.mark.parametrize(
4182
"solution_path",
4283
collect_solution_file_paths(),
4384
ids=lambda path: f"{path.parent.name}/{path.name}",
4485
)
45-
def test_project_euler(solution_path: pathlib.Path):
86+
def test_project_euler(solution_path: pathlib.Path) -> None:
4687
"""Testing for all Project Euler solutions"""
4788
# problem_[extract this part] and pad it with zeroes for width 3
4889
problem_number: str = solution_path.parent.name[8:].zfill(3)

0 commit comments

Comments
 (0)