Files
wehub-resource-sync bcbd1bdb22
Integ / changes (push) Has been skipped
Pre-commit / pre-commit (push) Failing after 1s
CLI exit codes / changes (push) Has been skipped
Test (Install) / changes (push) Has been skipped
Test (Python) / changes (push) Has been skipped
Test (TypeScript) / changes (push) Has been skipped
CLI exit codes / cli-gate (push) Has been cancelled
Test (Install) / test-install-gate (push) Has been cancelled
Integ / integ-gate (push) Has been cancelled
Test (Python) / test-python-gate (push) Has been cancelled
Test (TypeScript) / test-typescript-gate (push) Has been cancelled
Test (Install) / python-minimal (3.12) (push) Has been cancelled
Test (Install) / python-minimal (3.11) (push) Has been cancelled
Test (Install) / python-extra (agno, mirage.agents.agno) (push) Has been cancelled
Test (Install) / python-extra (chroma, mirage.resource.chroma) (push) Has been cancelled
Test (Install) / python-extra (pdf, mirage.core.filetype.pdf) (push) Has been cancelled
Integ / integ (push) Has been cancelled
Integ / integ-database (push) Has been cancelled
Integ / integ-database-ts (push) Has been cancelled
Integ / integ-data (push) Has been cancelled
Integ / integ-ssh (push) Has been cancelled
Integ / integ-ssh-ts (push) Has been cancelled
Test (Python) / audit (push) Has been cancelled
Test (TypeScript) / test (push) Has been cancelled
Test (TypeScript) / python-fs-shim (push) Has been cancelled
CLI exit codes / Python CLI (push) Has been cancelled
CLI exit codes / TypeScript CLI (push) Has been cancelled
CLI exit codes / Cross-language snapshot interop (push) Has been cancelled
Test (Python) / test (push) Has been cancelled
Test (Python) / import-isolation (deepagents, openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Python) / import-isolation (deepagents, pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Integ / integ-ts (push) Has been cancelled
Integ / integ-fuse (push) Has been cancelled
Test (Install) / python-extra (databricks, mirage.resource.databricks_volume) (push) Has been cancelled
Test (Install) / python-extra (deepagents, mirage.agents.langchain) (push) Has been cancelled
Test (Install) / python-extra (email, mirage.resource.email) (push) Has been cancelled
Test (Install) / python-extra (fuse, mirage.fuse.mount) (push) Has been cancelled
Test (Install) / python-extra (hdf5, mirage.core.filetype.hdf5) (push) Has been cancelled
Test (Install) / python-extra (hf, mirage.resource.hf_buckets) (push) Has been cancelled
Test (Install) / python-extra (lancedb, mirage.resource.lancedb) (push) Has been cancelled
Test (Install) / python-extra (langfuse, mirage.resource.langfuse) (push) Has been cancelled
Test (Install) / python-extra (mongodb, mirage.resource.mongodb) (push) Has been cancelled
Test (Install) / python-extra (nextcloud, mirage.resource.nextcloud) (push) Has been cancelled
Test (Install) / python-extra (openai, mirage.agents.openai_agents) (push) Has been cancelled
Test (Install) / python-extra (openhands, mirage.agents.openhands, 3.12) (push) Has been cancelled
Test (Install) / python-extra (parquet, mirage.core.filetype.parquet) (push) Has been cancelled
Test (Install) / python-extra (postgres, mirage.resource.postgres) (push) Has been cancelled
Test (Install) / python-extra (pydantic-ai, mirage.agents.pydantic_ai) (push) Has been cancelled
Test (Install) / python-extra (qdrant, mirage.resource.qdrant) (push) Has been cancelled
Test (Install) / python-extra (redis, mirage.resource.redis) (push) Has been cancelled
Test (Install) / python-extra (s3, mirage.resource.s3) (push) Has been cancelled
Test (Install) / python-extra (ssh, mirage.resource.ssh) (push) Has been cancelled
Test (Install) / ts-minimal (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:30:44 +08:00

249 lines
7.6 KiB
Python

import pytest
from mirage.commands.builtin.generic.nl import nl
from mirage.commands.builtin.generic.rev import rev
from mirage.commands.builtin.generic.sort import sort
from mirage.commands.builtin.generic.tac import tac
from mirage.commands.builtin.generic.tr import tr
from mirage.commands.builtin.generic.uniq import uniq
from mirage.types import PathSpec
def _spec(path: str) -> PathSpec:
return PathSpec(resource_path=(path).strip("/"),
virtual=path,
directory=path,
resolved=True)
def _make_backend(files: dict[str, bytes]):
async def read_bytes(accessor, path, index=None):
spec = path if isinstance(path, PathSpec) else PathSpec(
resource_path=(path).strip("/"), virtual=path, directory=path)
if spec.virtual not in files:
raise FileNotFoundError(spec.virtual)
return files[spec.virtual]
async def read_stream(accessor, path, index=None):
spec = path if isinstance(path, PathSpec) else PathSpec(
resource_path=(path).strip("/"), virtual=path, directory=path)
if spec.virtual not in files:
raise FileNotFoundError(spec.virtual)
yield files[spec.virtual]
return read_bytes, read_stream
async def _drain(stdout) -> bytes:
if stdout is None:
return b""
if isinstance(stdout, bytes):
return stdout
return b"".join([c async for c in stdout])
@pytest.mark.asyncio
async def test_rev_stdin():
rb, _ = _make_backend({})
output, _ = await rev([], read_bytes=rb, stdin=b"hello\nworld\n")
assert output == b"olleh\ndlrow\n"
@pytest.mark.asyncio
async def test_rev_multi_file_concatenates():
rb, _ = _make_backend({"/a.txt": b"foo\n", "/b.txt": b"bar\n"})
output, _ = await rev([_spec("/a.txt"), _spec("/b.txt")], read_bytes=rb)
assert output == b"oof\nrab\n"
@pytest.mark.asyncio
async def test_rev_missing_input_raises():
rb, _ = _make_backend({})
with pytest.raises(ValueError, match="missing operand"):
await rev([], read_bytes=rb)
@pytest.mark.asyncio
async def test_tac_stdin_reverses_lines():
_, rs = _make_backend({})
output, _ = await tac([], read_stream=rs, stdin=b"a\nb\nc\n")
decoded = (await _drain(output)).decode().splitlines()
assert decoded == ["c", "b", "a"]
@pytest.mark.asyncio
async def test_tac_file_reverses_lines():
_, rs = _make_backend({"/a.txt": b"a\nb\nc\n"})
output, io = await tac([_spec("/a.txt")], read_stream=rs)
decoded = (await _drain(output)).decode().splitlines()
assert decoded == ["c", "b", "a"]
assert io.cache == ["/a.txt"]
@pytest.mark.asyncio
async def test_sort_stdin_alpha():
rb, _ = _make_backend({})
output, _ = await sort([], read_bytes=rb, stdin=b"c\na\nb\n")
assert output == b"a\nb\nc\n"
@pytest.mark.asyncio
async def test_sort_reverse():
rb, _ = _make_backend({})
output, _ = await sort([], read_bytes=rb, stdin=b"a\nb\nc\n", reverse=True)
assert output == b"c\nb\na\n"
@pytest.mark.asyncio
async def test_sort_numeric():
rb, _ = _make_backend({})
output, _ = await sort([],
read_bytes=rb,
stdin=b"10\n2\n1\n",
numeric=True)
assert output == b"1\n2\n10\n"
@pytest.mark.asyncio
async def test_sort_unique():
rb, _ = _make_backend({})
output, _ = await sort([],
read_bytes=rb,
stdin=b"b\na\nb\na\n",
unique=True)
assert output == b"a\nb\n"
@pytest.mark.asyncio
async def test_sort_multi_file_merges():
rb, _ = _make_backend({"/a.txt": b"c\na\n", "/b.txt": b"b\n"})
output, _ = await sort([_spec("/a.txt"), _spec("/b.txt")], read_bytes=rb)
assert output == b"a\nb\nc\n"
@pytest.mark.asyncio
async def test_nl_stdin_default():
_, rs = _make_backend({})
output, _ = await nl([], read_stream=rs, stdin=b"alpha\nbeta\n")
decoded = (await _drain(output)).decode()
assert "1" in decoded and "alpha" in decoded
assert "2" in decoded and "beta" in decoded
@pytest.mark.asyncio
async def test_nl_start_value():
_, rs = _make_backend({})
output, _ = await nl([],
read_stream=rs,
stdin=b"alpha\nbeta\n",
start_raw="100")
decoded = (await _drain(output)).decode()
assert "100" in decoded
assert "101" in decoded
@pytest.mark.asyncio
async def test_nl_blank_lines_unnumbered_by_default():
_, rs = _make_backend({})
output, _ = await nl([], read_stream=rs, stdin=b"alpha\n\nbeta\n")
decoded = (await _drain(output)).decode().splitlines()
assert any("1" in ln and "alpha" in ln for ln in decoded)
assert any("2" in ln and "beta" in ln for ln in decoded)
@pytest.mark.asyncio
async def test_tr_translate_charset():
_, rs = _make_backend({})
output, _ = await tr([], ("abc", "xyz"), read_stream=rs, stdin=b"cab")
assert (await _drain(output)) == b"zxy"
@pytest.mark.asyncio
async def test_tr_delete():
_, rs = _make_backend({})
output, _ = await tr([], ("aeiou", ""),
read_stream=rs,
stdin=b"hello world",
delete=True)
assert (await _drain(output)) == b"hll wrld"
@pytest.mark.asyncio
async def test_tr_squeeze():
_, rs = _make_backend({})
output, _ = await tr([], (" ", " "),
read_stream=rs,
stdin=b"a b c",
squeeze=True)
assert (await _drain(output)) == b"a b c"
@pytest.mark.asyncio
async def test_tr_missing_args_raises():
_, rs = _make_backend({})
with pytest.raises(ValueError, match="usage"):
await tr([], (), read_stream=rs)
@pytest.mark.asyncio
async def test_uniq_dedupes_adjacent():
_, rs = _make_backend({})
output, _ = await uniq([], read_stream=rs, stdin=b"a\na\nb\nb\nc\n")
assert (await _drain(output)) == b"a\nb\nc\n"
@pytest.mark.asyncio
async def test_uniq_keeps_non_adjacent_dupes():
"""Real uniq only collapses adjacent duplicates."""
_, rs = _make_backend({})
output, _ = await uniq([], read_stream=rs, stdin=b"a\nb\na\n")
assert (await _drain(output)) == b"a\nb\na\n"
@pytest.mark.asyncio
async def test_uniq_count():
_, rs = _make_backend({})
output, _ = await uniq([],
read_stream=rs,
stdin=b"a\na\na\nb\n",
count=True)
decoded = (await _drain(output)).decode()
assert "3" in decoded and "a" in decoded
assert "1" in decoded and "b" in decoded
@pytest.mark.asyncio
async def test_uniq_duplicates_only():
_, rs = _make_backend({})
output, _ = await uniq([],
read_stream=rs,
stdin=b"a\na\nb\n",
duplicates_only=True)
decoded = (await _drain(output)).decode()
assert "a" in decoded
assert "b" not in decoded
@pytest.mark.asyncio
async def test_uniq_unique_only():
_, rs = _make_backend({})
output, _ = await uniq([],
read_stream=rs,
stdin=b"a\na\nb\n",
unique_only=True)
decoded = (await _drain(output)).decode()
assert "b" in decoded
assert decoded.count("a") == 0
@pytest.mark.asyncio
async def test_uniq_ignore_case():
_, rs = _make_backend({})
output, _ = await uniq([],
read_stream=rs,
stdin=b"Apple\napple\nBanana\n",
ignore_case=True)
decoded = (await _drain(output)).decode().splitlines()
assert len(decoded) == 2