Skip to content
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
33 changes: 32 additions & 1 deletion tierkreis/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,38 @@ build-backend = "hatchling.build"

[tool.ruff]
target-version = "py312"
extend-exclude = []
extend-exclude = [
# Ignore worker stubs:
"*_worker.py",
"stubs.py",
"stubs_output.py",
# Ignore docs
"tierkreis/docs/*",
]
[tool.ruff.lint]
select = ["ALL"]
isort.known-first-party = ["tierkreis", "tierkreis_visualizer"]
pydocstyle.convention = "pep257"

# Ignore specific rules that might be redundant or annoying
ignore = [
"D203", # Conflict: 1 blank line before class (D203) vs no blank lines (D211)
"D213", # Conflict: Multi-line docstring summary start (D212) vs (D213)
"ISC001", # Single line implicit string concatenation
"S603", # Subprocess calls
"D107", # In favor of documenting classes directly
]

[tool.ruff.lint.per-file-ignores]
"tierkreis/tests/*" = [
"S101", # asserts allowed in tests...
"ARG", # Unused function args -> fixtures nevertheless are functionally relevant...
"FBT", # Don't care about booleans as positional arguments in tests, e.g. via @pytest.mark.parametrize()
"PLR2004", # Magic value used in comparison, ...
"S311", # Standard pseudo-random generators are not suitable for cryptographic purposes
"D",
]


[tool.pyright]
include = ["."]
Expand Down
32 changes: 19 additions & 13 deletions tierkreis/tests/cli/test_run_workflow.py
Original file line number Diff line number Diff line change
@@ -1,25 +1,25 @@
import pytest
import json
from pathlib import Path
from uuid import UUID
from unittest import mock
from uuid import UUID

import pytest

from tierkreis.controller.data.graph import GraphData
from tierkreis.cli.run_workflow import run_workflow
from tests.controller.sample_graphdata import simple_eval
from tierkreis.cli.run_workflow import run_workflow
from tierkreis.controller.data.graph import GraphData
from tierkreis.controller.data.types import ptype_from_bytes


@pytest.fixture()
@pytest.fixture
def graph() -> GraphData:
return simple_eval()


def test_run_workflow(graph: GraphData) -> None:
inputs = {}
run_workflow(inputs=inputs, graph=graph, run_id=31415)
with open(
with Path.open(
Path.home()
/ ".tierkreis"
/ "checkpoints"
Expand All @@ -32,18 +32,24 @@ def test_run_workflow(graph: GraphData) -> None:
assert c == 12


def test_run_workflow_with_output(graph: GraphData, capfd) -> None:
def test_run_workflow_with_output(graph: GraphData, capfd) -> None: # noqa: ANN001
inputs = {}
run_workflow(inputs=inputs, graph=graph, run_id=31415, print_output=True)
out, _ = capfd.readouterr()
assert "simple_eval_output: b'12'\n" in out
assert "simple_eval_output: 12\n" in out


@pytest.fixture
def _patch_uuid4() -> mock.Mock:
with mock.patch("uuid.uuid4", return_value=UUID(int=31415)) as m:
return m


@mock.patch("uuid.uuid4", return_value=UUID(int=31415))
def test_run_workflow_default_run_id(_, graph: GraphData) -> None:
@pytest.mark.usefixtures("_patch_uuid4", "graph")
def test_run_workflow_default_run_id(graph: GraphData) -> None:
inputs = {}
run_workflow(inputs=inputs, graph=graph)
with open(
with Path.open(
Path.home()
/ ".tierkreis"
/ "checkpoints"
Expand All @@ -61,6 +67,6 @@ def test_run_workflow_uv_executor(graph: GraphData) -> None:
inputs=inputs,
graph=graph,
run_id=31415,
use_uv_worker=True,
registry_path=Path("."),
use_uv_executor=True,
registry_path=Path(),
)
38 changes: 23 additions & 15 deletions tierkreis/tests/cli/test_tkr.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import json
import pytest
import sys
from pathlib import Path
from unittest import mock
from uuid import UUID

from tierkreis.cli.tkr import load_graph, _load_inputs, main
import pytest

from tests.controller.sample_graphdata import simple_eval
from tierkreis.cli.tkr import _load_inputs, load_graph, main
from tierkreis.controller.data.graph import GraphData
from tierkreis.controller.data.types import PType
from tierkreis.exceptions import TierkreisError

from tests.controller.sample_graphdata import simple_eval

simple_eval_graph = simple_eval()

graph_params = [
Expand All @@ -20,9 +20,13 @@
]


@pytest.mark.parametrize("input,graph", graph_params, ids=["load_module", "load_file"])
def test_load_graph(input: str, graph: GraphData) -> None:
assert load_graph(input) == graph
@pytest.mark.parametrize(
("inputs", "graph"),
graph_params,
ids=["load_module", "load_file"],
)
def test_load_graph(inputs: str, graph: GraphData) -> None:
assert load_graph(inputs) == graph


def test_load_graph_invalid() -> None:
Expand Down Expand Up @@ -55,10 +59,12 @@ def test_load_graph_invalid() -> None:


@pytest.mark.parametrize(
"input,result", input_params, ids=["json_input", "binary_input"]
("inputs", "result"),
input_params,
ids=["json_input", "binary_input"],
)
def test_load_inputs(input: list[str], result: dict[str, PType]) -> None:
assert _load_inputs(input) == result
def test_load_inputs(inputs: list[str], result: dict[str, PType]) -> None:
assert _load_inputs(inputs) == result


def test_load_inputs_invalid() -> None:
Expand Down Expand Up @@ -91,12 +97,12 @@ def test_load_inputs_invalid() -> None:

cli_params = [
(
default_args + ["-f", "tierkreis/tests/cli/data/sample_graph"],
[*default_args, "-f", "tierkreis/tests/cli/data/sample_graph"],
{"simple_eval_output": 12},
),
(
default_args
+ [
[
*default_args,
"-g",
"tests.controller.sample_graphdata:factorial",
"-i",
Expand All @@ -109,13 +115,15 @@ def test_load_inputs_invalid() -> None:


@pytest.mark.parametrize(
"args,result", cli_params, ids=["simple_eval_cli", "factorial_cli"]
("args", "result"),
cli_params,
ids=["simple_eval_cli", "factorial_cli"],
)
def test_end_to_end(args: list[str], result: dict[str, bytes]) -> None:
with mock.patch.object(sys, "argv", args):
main()
for key, value in result.items():
with open(
with Path.open(
Path.home()
/ ".tierkreis"
/ "checkpoints"
Expand Down
14 changes: 10 additions & 4 deletions tierkreis/tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,23 @@
import pytest


def pytest_addoption(parser):
def pytest_addoption(parser: pytest.Parser) -> None:
parser.addoption(
"--optional", action="store_true", default=False, help="run optional tests"
"--optional",
action="store_true",
default=False,
help="run optional tests",
)


def pytest_configure(config):
def pytest_configure(config: pytest.Config) -> None:
config.addinivalue_line("markers", "optional: mark test as optional to run")


def pytest_collection_modifyitems(config, items):
def pytest_collection_modifyitems(
config: pytest.Config,
items: list[pytest.Item],
) -> None:
if config.getoption("--optional"):
return
skip_slow = pytest.mark.skip(reason="need --optional option to run")
Expand Down
9 changes: 5 additions & 4 deletions tierkreis/tests/controller/loop_graphdata.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
from typing import NamedTuple

import tierkreis.builtins.stubs as tkr_builtins
from tierkreis.controller.data.core import EmptyModel
from tierkreis.builder import GraphBuilder
from tierkreis.controller.data.core import EmptyModel
from tierkreis.controller.data.graph import GraphData
from tierkreis.models import TKR

Expand Down Expand Up @@ -30,7 +31,7 @@ def _loop_body_multiple_acc_untyped() -> GraphData:
"acc1": new_acc,
"acc2": new_acc2,
"acc3": new_acc3,
}
},
)

return g
Expand Down Expand Up @@ -136,10 +137,10 @@ def _loop_body_scoping() -> GraphBuilder[Scoping, ScopingOut]:

one = g.const(1)

next = g.task(tkr_builtins.iadd(g.inputs.current, one))
next_val = g.task(tkr_builtins.iadd(g.inputs.current, one))
should_continue = g.task(tkr_builtins.neq(g.inputs.end, g.inputs.current))

g.outputs(ScopingOut(should_continue=should_continue, current=next))
g.outputs(ScopingOut(should_continue=should_continue, current=next_val))

return g

Expand Down
2 changes: 1 addition & 1 deletion tierkreis/tests/controller/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@
# tierkreis = { path = "../../../tierkreis", editable = true }
# ///
from pathlib import Path
from time import sleep
from sys import argv
from time import sleep

from tierkreis import Worker

Expand Down
22 changes: 11 additions & 11 deletions tierkreis/tests/controller/sample_graphdata.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,10 +38,10 @@ def loop_body() -> GraphData:
g = GraphData()
a = g.input("loop_acc")
one = g.const(1)
N = g.const(10)
n_val: tuple[int, str] = g.const(10)

a_plus = g.func("builtins.iadd", {"a": a, "b": one})("value")
pred = g.func("builtins.igt", {"a": N, "b": a_plus})("value")
pred = g.func("builtins.igt", {"a": n_val, "b": a_plus})("value")
g.output({"loop_acc": a_plus, "should_continue": pred})
return g

Expand All @@ -58,11 +58,11 @@ def simple_loop() -> GraphData:
def simple_map() -> GraphData:
g = GraphData()
six = g.const(6)
Ns_const = g.const(list(range(21)))
Ns = g.func("builtins.unfold_values", {Labels.VALUE: Ns_const})
n_consts = g.const(list(range(21)))
n_vals = g.func("builtins.unfold_values", {Labels.VALUE: n_consts})
doubler_const = g.const(doubler_plus())

m = g.map(doubler_const, {"doubler_input": Ns("*"), "intercept": six})
m = g.map(doubler_const, {"doubler_input": n_vals("*"), "intercept": six})
folded = g.func("builtins.fold_values", {"values_glob": m("*")})
g.output({"value": folded(Labels.VALUE)})
return g
Expand All @@ -82,11 +82,11 @@ def maps_in_series() -> GraphData:
g = GraphData()
zero = g.const(0)

Ns_const = g.const(list(range(21)))
Ns = g.func("builtins.unfold_values", {Labels.VALUE: Ns_const})
n_consts = g.const(list(range(21)))
n_vals = g.func("builtins.unfold_values", {Labels.VALUE: n_consts})
doubler_const = g.const(doubler_plus())

m = g.map(doubler_const, {"doubler_input": Ns("*"), "intercept": zero})
m = g.map(doubler_const, {"doubler_input": n_vals("*"), "intercept": zero})

m2 = g.map(doubler_const, {"doubler_input": m("*"), "intercept": zero})
folded = g.func("builtins.fold_values", {"values_glob": m2("*")})
Expand All @@ -97,11 +97,11 @@ def maps_in_series() -> GraphData:
def map_with_str_keys() -> GraphData:
g = GraphData()
zero = g.const(0)
Ns_const = g.const({"one": 1, "two": 2, "three": 3})
Ns = g.func("builtins.unfold_dict", {Labels.VALUE: Ns_const})
n_consts = g.const({"one": 1, "two": 2, "three": 3})
n_vals = g.func("builtins.unfold_dict", {Labels.VALUE: n_consts})
doubler_const = g.const(doubler_plus())

m = g.map(doubler_const, {"doubler_input": Ns("*"), "intercept": zero})
m = g.map(doubler_const, {"doubler_input": n_vals("*"), "intercept": zero})
folded = g.func("builtins.fold_dict", {"values_glob": m("*")})
g.output({"value": folded(Labels.VALUE)})
return g
Expand Down
10 changes: 7 additions & 3 deletions tierkreis/tests/controller/test_codegen.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
from types import NoneType

import pytest

from tierkreis.codegen import format_generic_type
from tierkreis.controller.data.types import PType
from tierkreis.idl.models import GenericType
Expand All @@ -21,8 +23,10 @@
]


@pytest.mark.parametrize("ttype,expected", formats)
def test_format_ttype(ttype: type[PType], expected: str):
@pytest.mark.parametrize(("ttype", "expected"), formats)
def test_format_ttype(ttype: type[PType], expected: str) -> None:
generic_type = GenericType.from_type(ttype)

assert format_generic_type(generic_type, False, False) == expected
assert (
format_generic_type(generic_type, include_bound=False, is_tkr=False) == expected
)
Loading
Loading