Skip to content
Open
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
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,17 @@ def __init__(
one_char (str | None): Character to represent binary 1 in ``sneaky_bits`` mode (default: U+2064).

Raises:
ValueError: If an unsupported action or ``encoding_mode`` is provided.
ValueError: If the action is unsupported, marker values are not single characters, or markers are equal.
"""
super().__init__(action=action)
self.zero_char = zero_char if zero_char is not None else "\u2062" # Invisible Times
self.one_char = one_char if one_char is not None else "\u2064" # Invisible Plus

if len(self.zero_char) != 1 or len(self.one_char) != 1:
raise ValueError("zero_char and one_char must each be exactly one character")
if self.zero_char == self.one_char:
raise ValueError("zero_char and one_char must be distinct")

def _build_identifier(self) -> ComponentIdentifier:
"""
Build identifier with sneaky bits parameters.
Expand Down
19 changes: 19 additions & 0 deletions tests/unit/converter/test_sneaky_bits_smuggler_converter.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,25 @@ async def test_sneaky_bits_custom_chars():
assert len(result.output_text) == 8 # 1 ASCII byte = 8 bits


@pytest.mark.parametrize(
("zero_char", "one_char"),
[
("", "1"),
("00", "1"),
("0", ""),
("0", "11"),
],
)
def test_sneaky_bits_custom_chars_must_be_single_characters(zero_char: str, one_char: str):
with pytest.raises(ValueError, match="exactly one character"):
SneakyBitsSmugglerConverter(zero_char=zero_char, one_char=one_char)


def test_sneaky_bits_custom_chars_must_be_distinct():
with pytest.raises(ValueError, match="must be distinct"):
SneakyBitsSmugglerConverter(zero_char="x", one_char="x")


async def test_sneaky_bits_empty():
converter = SneakyBitsSmugglerConverter(action="encode")
result = await converter.convert_async(prompt="", input_type="text")
Expand Down