From c46de048ca107a192f3e1fa3e35bb6d5093f68e7 Mon Sep 17 00:00:00 2001 From: Jesse Bannon Date: Wed, 31 Dec 2025 09:06:08 -0800 Subject: [PATCH] [FEATURE] %range function (#1405) Add `%range` function, equivalent to Python's `range`. --- .../scripting/scripting_functions.rst | 7 +++++++ .../script/functions/numeric_functions.py | 17 +++++++++++++++++ .../script/functions/test_numeric_functions.py | 12 ++++++++++++ 3 files changed, 36 insertions(+) diff --git a/docs/source/config_reference/scripting/scripting_functions.rst b/docs/source/config_reference/scripting/scripting_functions.rst index d6064e0f..e2a200ef 100644 --- a/docs/source/config_reference/scripting/scripting_functions.rst +++ b/docs/source/config_reference/scripting/scripting_functions.rst @@ -521,6 +521,13 @@ pow :description: ``**`` operator. Returns the exponential of the base and exponent value. +range +~~~~~ +:spec: ``range(end: Integer, start: Optional[Integer], step: Optional[Integer]) -> Array`` + +:description: + Returns the desired range of Integers in the form of an Array. + sub ~~~ :spec: ``sub(values: Numeric, ...) -> Numeric`` diff --git a/src/ytdl_sub/script/functions/numeric_functions.py b/src/ytdl_sub/script/functions/numeric_functions.py index b25374f9..003c8837 100644 --- a/src/ytdl_sub/script/functions/numeric_functions.py +++ b/src/ytdl_sub/script/functions/numeric_functions.py @@ -1,5 +1,7 @@ import math +from typing import Optional +from ytdl_sub.script.types.array import Array from ytdl_sub.script.types.resolvable import AnyArgument from ytdl_sub.script.types.resolvable import Float from ytdl_sub.script.types.resolvable import Integer @@ -96,3 +98,18 @@ class NumericFunctions: Returns min of all values. """ return _to_numeric(min(val.value for val in values)) + + @staticmethod + def range( + end: Integer, start: Optional[Integer] = None, step: Optional[Integer] = None + ) -> Array: + """ + :description: + Returns the desired range of Integers in the form of an Array. + """ + if start is None: + start = Integer(0) + if step is None: + step = Integer(1) + + return Array(value=[Integer(idx) for idx in range(start.value, end.value, step.value)]) diff --git a/tests/unit/script/functions/test_numeric_functions.py b/tests/unit/script/functions/test_numeric_functions.py index c41f4c59..b05dbb70 100644 --- a/tests/unit/script/functions/test_numeric_functions.py +++ b/tests/unit/script/functions/test_numeric_functions.py @@ -76,3 +76,15 @@ class TestNumericFunctions: def test_pow(self, values: str, expected_output: float): output = single_variable_output(f"{{ %pow({values}) }}") assert output == expected_output + + @pytest.mark.parametrize( + "values, expected_output", + [ + ("5", [0, 1, 2, 3, 4]), + ("5, 1", [1, 2, 3, 4]), + ("5, 1, 2", [1, 3]), + ], + ) + def test_range(self, values: str, expected_output: float): + output = single_variable_output(f"{{ %range({values}) }}") + assert output == expected_output