-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
issue #6 Split puzzle decorators from Puzzle class
- Loading branch information
Showing
8 changed files
with
117 additions
and
81 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
"""TODO: Document this | ||
""" | ||
|
||
from .core import Puzzle | ||
from .decorators import solved, with_input | ||
|
||
__all__ = ['Puzzle', 'solved', 'with_input'] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
"""Some common declarations for puzzles. | ||
""" | ||
|
||
|
||
# The response of a puzzle step. | ||
PuzzleStepResponse = int | str | ||
|
||
# Return value of a puzzle step. None indicates an unsolved step. | ||
PuzzleStepResult = PuzzleStepResponse | None |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
"""Puzzle step function decorators. | ||
""" | ||
|
||
from functools import wraps | ||
from typing import Callable, Concatenate, ParamSpec, TypeVar | ||
|
||
from ..errors import WrongStepSolution | ||
from .common import PuzzleStepResponse, PuzzleStepResult | ||
|
||
U = TypeVar('U') | ||
|
||
P = ParamSpec('P') | ||
|
||
|
||
def with_input(puzzle_input: U) -> Callable[ | ||
[Callable[Concatenate[U, P], PuzzleStepResult]], | ||
Callable[P, PuzzleStepResult], | ||
]: | ||
"""Injects a value as first argument of the solution step function. | ||
""" | ||
def decorator( | ||
fn: Callable[Concatenate[U, P], PuzzleStepResult], | ||
) -> Callable[P, PuzzleStepResult]: | ||
@wraps(fn) | ||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> PuzzleStepResult: | ||
return fn(puzzle_input, *args, **kwargs) | ||
|
||
return wrapper | ||
|
||
return decorator # type: ignore[return-value] # pending issue 9 | ||
|
||
|
||
def solved(solution: PuzzleStepResponse) -> Callable[ | ||
[Callable[P, PuzzleStepResult]], | ||
Callable[P, PuzzleStepResult], | ||
]: | ||
"""Mark a solution function as solved. The return value of the solution | ||
function must match the passed argument to considere the response as | ||
correct. | ||
""" | ||
def decorator( | ||
fn: Callable[P, PuzzleStepResult], | ||
) -> Callable[P, PuzzleStepResult]: | ||
@wraps(fn) | ||
def wrapper(*args: P.args, **kwargs: P.kwargs) -> PuzzleStepResult: | ||
step_solution = fn(*args, **kwargs) | ||
|
||
if step_solution is not None and step_solution != solution: | ||
raise WrongStepSolution() | ||
|
||
return step_solution | ||
|
||
return wrapper | ||
|
||
return decorator |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
import pytest | ||
|
||
from saulve.errors import WrongStepSolution | ||
from saulve.puzzle.decorators import solved, with_input | ||
|
||
|
||
@pytest.mark.parametrize('decorate', [ | ||
solved(12), | ||
with_input(12), | ||
]) | ||
def test_decorated_functions_are_wrapped(decorate) -> None: # type: ignore | ||
def under_test() -> None: | ||
"""Docstring""" | ||
|
||
decorated = decorate(under_test) | ||
|
||
assert decorated.__doc__ == 'Docstring' | ||
|
||
def test_step_input_is_injected_as_first_argument() -> None: | ||
fn = with_input('Ministry of ')(lambda s: s + 'silly walks') | ||
|
||
assert fn() == 'Ministry of silly walks' | ||
|
||
|
||
def test_solved_wont_do_anything_with_correct_solution() -> None: | ||
fn = solved('Tis but a scratch')(lambda: 'Tis but a scratch') | ||
|
||
assert fn() == 'Tis but a scratch' | ||
|
||
|
||
def test_solved_raises_exception_on_wrong_solution() -> None: | ||
fn = solved('This parrot is dead.')(lambda: 'No, it\'s resting.') | ||
|
||
with pytest.raises(WrongStepSolution): | ||
fn() |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters