mirror of
https://github.com/rio-labs/rio.git
synced 2026-02-10 07:39:51 -06:00
287 lines
7.2 KiB
Python
287 lines
7.2 KiB
Python
import math
|
|
import re
|
|
import typing as t
|
|
|
|
import pytest
|
|
|
|
import rio
|
|
import rio.utils
|
|
|
|
|
|
def _assert_stops_match(
|
|
stops_should: t.Iterable[tuple[rio.Color, float]],
|
|
stops_are: t.Iterable[tuple[rio.Color, float]],
|
|
) -> None:
|
|
"""
|
|
Given two lists of stops (all with positions), verify that they are
|
|
identical.
|
|
"""
|
|
stops_should = list(stops_should)
|
|
stops_are = list(stops_are)
|
|
|
|
assert len(stops_are) == len(stops_should)
|
|
|
|
for stop_should, stop_are in zip(stops_should, stops_are):
|
|
assert isinstance(stop_should, tuple)
|
|
assert isinstance(stop_are, tuple)
|
|
|
|
assert len(stop_should) == 2
|
|
assert len(stop_are) == 2
|
|
|
|
color_should, position_should = stop_should
|
|
color_are, position_are = stop_are
|
|
|
|
assert color_should.hexa == color_are.hexa
|
|
assert math.isclose(position_should, position_are)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"input_type,output_type",
|
|
[
|
|
# Simple cases
|
|
("pdf", "pdf"),
|
|
(".Pdf", "pdf"),
|
|
(".PDF", "pdf"),
|
|
("*pdf", "pdf"),
|
|
("*.Pdf", "pdf"),
|
|
("*.PDF", "pdf"),
|
|
("application/pdf", "pdf"),
|
|
# Make sure the results are standardized
|
|
(".jpg", "jpg"),
|
|
(".jpeg", "jpg"),
|
|
("image/jpeg", "jpg"),
|
|
# Invalid MIME types
|
|
("not/a/real/type", "type"),
|
|
("////Type", "type"),
|
|
],
|
|
)
|
|
def test_standardize_file_types(
|
|
input_type: str,
|
|
output_type: str,
|
|
) -> None:
|
|
cleaned_type = rio.utils.normalize_file_extension(input_type)
|
|
assert cleaned_type == output_type
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"unsorted_sequence,keys,sorted_sequence_should",
|
|
[
|
|
(
|
|
[0, 1, 2, 3, 4],
|
|
[0, 1, 2, 3, 4],
|
|
[0, 1, 2, 3, 4],
|
|
),
|
|
(
|
|
[4, 3, 2, 1, 0],
|
|
[4, 3, 2, 1, 0],
|
|
[0, 1, 2, 3, 4],
|
|
),
|
|
(
|
|
[4, 3, 2, 1, 0],
|
|
[4, None, None, None, 0],
|
|
[0, 3, 2, 1, 4],
|
|
),
|
|
(
|
|
[0, 1, 2, 3],
|
|
[0, 1, 1, 3],
|
|
[0, 1, 2, 3],
|
|
),
|
|
(
|
|
[3, 2, 1, 0],
|
|
[3, 1, 1, 0],
|
|
[0, 2, 1, 3],
|
|
),
|
|
(
|
|
[0, 1, 2, 3],
|
|
[0, None, None, None],
|
|
[0, 1, 2, 3],
|
|
),
|
|
(
|
|
[0, 1, 2, 3],
|
|
[9, None, None, None],
|
|
[1, 2, 3, 0],
|
|
),
|
|
],
|
|
)
|
|
def test_soft_sort(
|
|
unsorted_sequence: list[int],
|
|
keys: list[int],
|
|
sorted_sequence_should: list[int],
|
|
) -> None:
|
|
# Sort the sequence
|
|
sorted_sequence_is = unsorted_sequence.copy()
|
|
rio.utils.soft_sort(
|
|
sorted_sequence_is,
|
|
key=lambda x: keys[unsorted_sequence.index(x)],
|
|
)
|
|
|
|
# Verify the result
|
|
assert sorted_sequence_is == sorted_sequence_should
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"stops_in, stops_should",
|
|
[
|
|
# No explicit positions
|
|
(
|
|
(rio.Color.BLACK,),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.BLACK, 1.0),
|
|
),
|
|
),
|
|
(
|
|
(
|
|
rio.Color.BLACK,
|
|
rio.Color.WHITE,
|
|
),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
),
|
|
(
|
|
(
|
|
rio.Color.BLACK,
|
|
rio.Color.BLUE,
|
|
rio.Color.WHITE,
|
|
),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.BLUE, 0.5),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
),
|
|
# Containing explicit positions
|
|
(
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
),
|
|
(
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
rio.Color.WHITE,
|
|
),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
),
|
|
(
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
rio.Color.BLUE,
|
|
rio.Color.WHITE,
|
|
),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.BLUE, 0.5),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
),
|
|
(
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
rio.Color.RED,
|
|
rio.Color.GREEN,
|
|
rio.Color.BLUE,
|
|
(rio.Color.CYAN, 0.8),
|
|
rio.Color.MAGENTA,
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.RED, 0.2),
|
|
(rio.Color.GREEN, 0.4),
|
|
(rio.Color.BLUE, 0.6),
|
|
(rio.Color.CYAN, 0.8),
|
|
(rio.Color.MAGENTA, 0.9),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
),
|
|
# Duplicate positions
|
|
(
|
|
(
|
|
rio.Color.BLACK,
|
|
(rio.Color.RED, 0.5),
|
|
(rio.Color.GREEN, 0.5),
|
|
rio.Color.WHITE,
|
|
),
|
|
(
|
|
(rio.Color.BLACK, 0.0),
|
|
(rio.Color.RED, 0.5),
|
|
(rio.Color.GREEN, 0.5),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
),
|
|
],
|
|
)
|
|
def test_interpolation_is_correct(
|
|
stops_in: tuple[rio.Color, ...],
|
|
stops_should: tuple[tuple[rio.Color, float], ...],
|
|
) -> None:
|
|
"""
|
|
Test that the interpolation function correctly assigns positions to stops.
|
|
"""
|
|
stops_are = rio.utils.verify_and_interpolate_gradient_stops(stops_in)
|
|
_assert_stops_match(stops_should, stops_are)
|
|
|
|
|
|
@pytest.mark.parametrize(
|
|
"stops_in, error_msg",
|
|
[
|
|
# Empty stops
|
|
(
|
|
tuple(),
|
|
"Gradients must have at least one stop",
|
|
),
|
|
# Position out of range
|
|
(
|
|
(
|
|
(rio.Color.BLACK, -0.1),
|
|
(rio.Color.WHITE, 1.0),
|
|
),
|
|
"Gradient stop positions must be in range [0, 1], but stop 0 is at position -0.1",
|
|
),
|
|
(
|
|
(
|
|
(rio.Color.BLACK, 0.1),
|
|
(rio.Color.WHITE, 1.1),
|
|
),
|
|
"Gradient stop positions must be in range [0, 1], but stop 1 is at position 1.1",
|
|
),
|
|
# Positions not ascending
|
|
(
|
|
(
|
|
(rio.Color.BLACK, 0.8),
|
|
(rio.Color.WHITE, 0.2),
|
|
),
|
|
"Gradient stops must be in ascending order, but stop 0 is at position 0.8 while stop 1 is at position 0.2",
|
|
),
|
|
(
|
|
(
|
|
rio.Color.RED,
|
|
(rio.Color.BLACK, 0.8),
|
|
rio.Color.BLUE,
|
|
(rio.Color.WHITE, 0.2),
|
|
),
|
|
"Gradient stops must be in ascending order, but stop 1 is at position 0.8 while stop 3 is at position 0.2",
|
|
),
|
|
],
|
|
)
|
|
def test_invalid_stops_raise_error(
|
|
stops_in: tuple[rio.Color | tuple[rio.Color, float], ...],
|
|
error_msg: str,
|
|
) -> None:
|
|
"""
|
|
Test that invalid gradient stop configurations raise appropriate errors.
|
|
"""
|
|
with pytest.raises(ValueError, match=re.escape(error_msg)):
|
|
rio.utils.verify_and_interpolate_gradient_stops(stops_in)
|