tests/strategies.py
Rama dev · réplica de lectura del repositorio original.
"""Hypothesis strategies shared by the share-filter test modules."""
from __future__ import annotations
from hypothesis import strategies as st
from shortlist.engine.privacy import FilterCondition, serialize_filter
# Raw filter values. `,` `|` `=` `!` really are syntax and never appear inside a value — but `&` is
# NOT in that list: it is a separator in Plex Web's dialect and an ordinary character in a label
# ("Kids & Family"), so a filter using both at once is genuinely ambiguous and no parser can resolve
# it. `&`-in-value is therefore covered by explicit `|`-separated cases below rather than generated
# here, where hypothesis would happily build the ambiguous combination.
value = st.text(alphabet=st.sampled_from("abcdefgXYZ0123456789_%."), min_size=1, max_size=12)
field_name = st.sampled_from(["label", "contentRating", "genre", "year"])
# Both separators of each kind, because plex.tv stores whatever the last writer used and hands it
# straight back — live-verified 2026-08-10. Plex Web writes `&` with `%2C`, plexapi writes `|` with
# `%2C`, Shortlist writes `|` with `,`; a filter can be in any of those shapes when we read it.
condition_sep = st.sampled_from(["|", "&"])
value_sep = st.sampled_from([",", "%2C"])
@st.composite
def _condition(draw):
values = tuple(draw(st.lists(value, min_size=1, max_size=4)))
return FilterCondition(
draw(field_name),
draw(st.sampled_from(["=", "!="])),
values,
sep=draw(condition_sep),
value_seps=tuple(draw(st.lists(value_sep, min_size=len(values) - 1, max_size=len(values) - 1))),
)
condition = _condition()
filter_string = st.lists(condition, min_size=0, max_size=5).map(serialize_filter)