Skip to content
Merged
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
11 changes: 7 additions & 4 deletions src/openjd/model/_range_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def from_str(range_str: str) -> IntRangeExpr:
return Parser().parse(range_str)

@staticmethod
def from_list(values: list[int | str]) -> IntRangeExpr:
def from_list(values: list[int] | list[str] | list[int | str]) -> IntRangeExpr:
"""Creates a range expression object from a list of integers/strings containing integers."""
if len(values) == 0:
return IntRangeExpr([])
Expand All @@ -66,7 +66,7 @@ def from_list(values: list[int | str]) -> IntRangeExpr:
values_as_int: list[int] = sorted({int(i) for i in values})
# Find all the ranges, and concatenate them
ranges = []
start = values_as_int[0]
start = end = values_as_int[0]
step = None

for value in values_as_int[1:]:
Expand All @@ -78,7 +78,7 @@ def from_list(values: list[int | str]) -> IntRangeExpr:
end = value
else:
ranges.append(IntRange(start, end, step))
start = value
start = end = value
step = None
ranges.append(IntRange(start, end, step or 1))
return IntRangeExpr(ranges)
Expand Down Expand Up @@ -183,8 +183,11 @@ def __init__(self, start: int, end: int, step: int = 1):
self._validate()

def __str__(self) -> str:
if len(self) == 1:
len_self = len(self)
if len_self == 1:
return str(self._start)
elif len_self == 2:
return f"{self._start},{self._end}"
elif self.step == 1:
return f"{self._start}-{self._end}"
else:
Expand Down
478 changes: 445 additions & 33 deletions src/openjd/model/_step_param_space_iter.py

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions src/openjd/model/_types.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,8 @@ class ParameterValueType(str, Enum):
INT = "INT"
FLOAT = "FLOAT"
PATH = "PATH"
# This type is only used for task parameters, not job parameters
CHUNK_INT = "CHUNK[INT]"


@dataclass(frozen=True, **dataclass_kwargs)
Expand Down
2 changes: 2 additions & 0 deletions src/openjd/model/v2023_09/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,7 @@
StringRangeList,
StringTaskParameterDefinition,
TaskChunksDefinition,
TaskChunksRangeConstraint,
TaskParameterList,
TaskParameterStringValue,
TaskParameterStringValueAsJob,
Expand Down Expand Up @@ -157,6 +158,7 @@
"StringRangeList",
"StringTaskParameterDefinition",
"TaskChunksDefinition",
"TaskChunksRangeConstraint",
"TaskParameterList",
"TaskParameterStringValue",
"TaskParameterStringValueAsJob",
Expand Down
5 changes: 5 additions & 0 deletions src/openjd/model/v2023_09/_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -584,6 +584,8 @@ def _validate_default_task_count(cls, value: Any) -> Any:
@field_validator("targetRuntimeSeconds", mode="before")
@classmethod
def _validate_target_runtime_seconds(cls, value: Any) -> Any:
if value is None:
return value
return validate_int_fmtstring_field(value, ge=0)


Expand Down Expand Up @@ -909,6 +911,9 @@ class StepParameterSpaceDefinition(OpenJDModel_v2023_09):
@field_validator("taskParameterDefinitions")
@classmethod
def _validate_parameters(cls, v: TaskParameterList) -> TaskParameterList:
# Only one CHUNK[INT] parameter is permitted
if len([param for param in v if param.type == TaskParameterType.CHUNK_INT]) > 1:
raise ValueError("Only one CHUNK[INT] task parameter is permitted")
# Must have a unique name for each Task parameter
return validate_unique_elements(v, item_value=lambda v: v.name, property="name")

Expand Down
4 changes: 3 additions & 1 deletion test/openjd/model/_internal/test_range_expr.py
Original file line number Diff line number Diff line change
Expand Up @@ -128,7 +128,8 @@ def test_parse_one_positive_range_no_step(
"range_expr,start,end,total_range,range_str",
[
pytest.param("1-100,101-200", 1, 200, 200, "1-200"),
pytest.param("0-1,3-4,7-9,10", 0, 10, 8, "0-1,3-4,7-10"),
pytest.param("0-1,3-4,7-9,10", 0, 10, 8, "0,1,3,4,7-10"),
pytest.param("0-3:3,5-10:5,12,13,14,15", 0, 15, 8, "0,3,5,10,12-15"),
pytest.param("20-29,0-9,10-19", 0, 29, 30, "0-29"),
],
)
Expand Down Expand Up @@ -208,6 +209,7 @@ def test_range_expr_from_str(self, range_input_str: str, range_str: str):
"range_list,range_str",
[
pytest.param([5], "5", id="one int"),
pytest.param([1, 2, 3, 4, 5, 7], "1-5,7", id="two ranges"),
pytest.param(["7"], "7", id="one int as a str"),
pytest.param([9, 0, 3, 2, 8, 10, 1, 4, 7, 6, 5], "0-10", id="values 0-10 out of order"),
pytest.param(
Expand Down
26 changes: 13 additions & 13 deletions test/openjd/model/test_step_param_space_iter.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,14 +12,10 @@
parse_model,
)

from openjd.model.v2023_09 import JobTemplate as JobTemplate_2023_09
from openjd.model.v2023_09 import (
JobTemplate as JobTemplate_2023_09,
RangeExpressionTaskParameterDefinition as RangeExpressionTaskParameterDefinition_2023_09,
)
from openjd.model.v2023_09 import (
RangeListTaskParameterDefinition as RangeListTaskParameterDefinition_2023_09,
)
from openjd.model.v2023_09 import (
StepParameterSpace as StepParameterSpace_2023_09,
)

Expand Down Expand Up @@ -68,13 +64,14 @@ def test_no_param_iteration(self):
job = create_job(job_template=job_template, job_parameter_values=dict())

space = job.steps[0].parameterSpace
iterator = StepParameterSpaceIterator(space=space)

# WHEN
result = list(iterator)
it = StepParameterSpaceIterator(space=space)

# THEN
assert result == expected
assert list(it) == expected
it.reset_iter()
assert list(it) == expected

def test_no_param_getelem(self):
# GIVEN
Expand All @@ -90,16 +87,16 @@ def test_no_param_getelem(self):
space = job.steps[0].parameterSpace

# WHEN
result = StepParameterSpaceIterator(space=space)
it = StepParameterSpaceIterator(space=space)

# THEN
with pytest.raises(IndexError):
result[1]
it[1]
with pytest.raises(IndexError):
result[-2]
it[-2]
expected = {}
assert result[0] == expected
assert result[-1] == expected
assert it[0] == expected
assert it[-1] == expected

@pytest.mark.parametrize(
"range_int_param",
Expand Down Expand Up @@ -130,6 +127,9 @@ def test_single_param_iteration(self, range_int_param):
} == next(it), f"i = {i}"
with pytest.raises(StopIteration):
next(it)
# The chunks parameter is only relevant when the parameter space is chunked
with pytest.raises(ValueError):
it.chunks_default_task_count = 1

@pytest.mark.parametrize("param_range", [["10"], ["10", "11", "12", "13", "14", "15"]])
def test_single_param_getelem(self, param_range):
Expand Down
Loading