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

384 lines
12 KiB
Python

import pytest
from mirage.commands.builtin.generic.diff import diff
from mirage.commands.builtin.generic.jq import jq
from mirage.commands.builtin.generic.patch import patch
from mirage.commands.builtin.generic.tar import tar
from mirage.commands.builtin.generic.tsort import tsort
from mirage.commands.builtin.generic.unzip import unzip
from mirage.commands.builtin.generic.zip_cmd import zip_cmd
from mirage.types import PathSpec
from mirage.utils.key_prefix import mount_key
def _spec(path: str, prefix: str = "") -> PathSpec:
return PathSpec(resource_path=mount_key(path, prefix),
virtual=path,
directory=path,
resolved=True)
def _make_backend(files: dict[str, bytes]):
store = dict(files)
async def read_bytes(accessor, path, index=None):
key = path.virtual if isinstance(path, PathSpec) else path
if key not in store:
raise FileNotFoundError(key)
return store[key]
async def write_bytes(accessor, path, data, index=None):
key = path.virtual if isinstance(path, PathSpec) else path
store[key] = data
async def read_stream(accessor, path, index=None):
key = path.virtual if isinstance(path, PathSpec) else path
if key not in store:
raise FileNotFoundError(key)
yield store[key]
async def mkdir_fn(accessor, path, parents=False):
pass
return read_bytes, write_bytes, read_stream, mkdir_fn, store
@pytest.mark.asyncio
async def test_tsort_basic():
rb, _, _, _, _ = _make_backend({"deps": b"a b\nb c\n"})
out, io = await tsort([_spec("deps")], read_bytes=rb)
assert out == b"a\nb\nc\n"
assert io.exit_code == 0
@pytest.mark.asyncio
async def test_tsort_cycle_detection():
rb, _, _, _, _ = _make_backend({"deps": b"a b\nb a\n"})
out, io = await tsort([_spec("deps")], read_bytes=rb)
assert b"cycle" in out
assert io.exit_code == 1
@pytest.mark.asyncio
async def test_tsort_odd_tokens():
rb, _, _, _, _ = _make_backend({"deps": b"a b c\n"})
out, io = await tsort([_spec("deps")], read_bytes=rb)
assert b"odd number" in out
assert io.exit_code == 1
@pytest.mark.asyncio
async def test_tsort_stdin():
rb, _, _, _, _ = _make_backend({})
out, io = await tsort([], read_bytes=rb, stdin=b"x y\ny z\n")
assert out == b"x\ny\nz\n"
@pytest.mark.asyncio
async def test_jq_simple_object():
rb, _, rs, _, _ = _make_backend({"a.json": b'{"name":"alice","age":30}'})
out, _ = await jq([_spec("a.json")],
".name",
read_bytes=rb,
read_stream=rs)
assert b'"alice"' in out
@pytest.mark.asyncio
async def test_jq_raw_output():
rb, _, rs, _, _ = _make_backend({"a.json": b'{"name":"alice"}'})
out, _ = await jq([_spec("a.json")],
".name",
read_bytes=rb,
read_stream=rs,
r=True)
assert b"alice" in out
assert b'"' not in out
@pytest.mark.asyncio
async def test_jq_stdin():
rb, _, rs, _, _ = _make_backend({})
out, _ = await jq([],
".x",
read_bytes=rb,
read_stream=rs,
stdin=b'{"x":42}')
assert b"42" in out
@pytest.mark.asyncio
async def test_jq_missing_expression_defaults_dot():
rb, _, rs, _, _ = _make_backend({})
out, io = await jq([], read_bytes=rb, read_stream=rs, stdin=b'{"x":42}')
assert b"42" in out
assert io.exit_code == 0
out, io = await jq([], read_bytes=rb, read_stream=rs)
assert out is None
assert io.exit_code == 0
@pytest.mark.asyncio
async def test_jq_no_input():
rb, _, rs, _, _ = _make_backend({})
out, io = await jq([], ".x", read_bytes=rb, read_stream=rs)
assert out is None
assert io.exit_code == 0
@pytest.mark.asyncio
async def test_zip_basic():
rb, wb, _, _, store = _make_backend({
"f1.txt": b"hello",
"f2.txt": b"world"
})
out, io = await zip_cmd(
[_spec("out.zip"), _spec("f1.txt"),
_spec("f2.txt")],
read_bytes=rb,
write_bytes=wb)
assert b"adding" in out
assert "out.zip" in store
archive = store["out.zip"]
assert archive.startswith(b"PK")
@pytest.mark.asyncio
async def test_zip_quiet():
rb, wb, _, _, _ = _make_backend({"f.txt": b"x"})
out, _ = await zip_cmd([_spec("o.zip"), _spec("f.txt")],
read_bytes=rb,
write_bytes=wb,
q=True)
assert out is None
@pytest.mark.asyncio
async def test_zip_too_few_paths():
rb, wb, _, _, _ = _make_backend({})
with pytest.raises(ValueError, match="usage"):
await zip_cmd([_spec("only.zip")], read_bytes=rb, write_bytes=wb)
@pytest.mark.asyncio
async def test_unzip_extracts():
import io as _io
import zipfile
buf = _io.BytesIO()
with zipfile.ZipFile(buf, "w") as zf:
zf.writestr("a.txt", b"hello")
zf.writestr("sub/b.txt", b"world")
rb, wb, _, mk, store = _make_backend({"a.zip": buf.getvalue()})
out, io_res = await unzip([_spec("a.zip")],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk)
assert b"inflating" in out
assert "/a.txt" in io_res.writes
assert "/sub/b.txt" in io_res.writes
@pytest.mark.asyncio
async def test_unzip_list():
import io as _io
import zipfile
buf = _io.BytesIO()
with zipfile.ZipFile(buf, "w") as zf:
zf.writestr("file.txt", b"data")
rb, wb, _, mk, _ = _make_backend({"a.zip": buf.getvalue()})
out, _ = await unzip([_spec("a.zip")],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
args_l=True)
assert b"file.txt" in out
@pytest.mark.asyncio
async def test_unzip_test_mode():
import io as _io
import zipfile
buf = _io.BytesIO()
with zipfile.ZipFile(buf, "w") as zf:
zf.writestr("ok.txt", b"x")
rb, wb, _, mk, _ = _make_backend({"a.zip": buf.getvalue()})
out, _ = await unzip([_spec("a.zip")],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
t=True)
assert b"No errors" in out
@pytest.mark.asyncio
async def test_unzip_pipe_mode():
import io as _io
import zipfile
buf = _io.BytesIO()
with zipfile.ZipFile(buf, "w") as zf:
zf.writestr("a.txt", b"hello")
rb, wb, _, mk, _ = _make_backend({"a.zip": buf.getvalue()})
out, _ = await unzip([_spec("a.zip")],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
p=True)
assert out == b"hello"
@pytest.mark.asyncio
async def test_tar_create_and_list():
rb, wb, _, mk, store = _make_backend({"a.txt": b"alpha", "b.txt": b"beta"})
_, io_res = await tar([_spec("a.txt"), _spec("b.txt")],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
c=True,
f=_spec("out.tar"))
assert "/out.tar" in io_res.writes
out, _ = await tar([],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
t=True,
f=_spec("out.tar"))
assert b"a.txt" in out
assert b"b.txt" in out
@pytest.mark.asyncio
async def test_tar_extract():
rb, wb, _, mk, _ = _make_backend({"x.txt": b"data"})
await tar([_spec("x.txt")],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
c=True,
f=_spec("a.tar"))
_, io_res = await tar([],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
x=True,
f=_spec("a.tar"),
C=_spec("/out"))
assert any("x.txt" in p for p in io_res.writes)
@pytest.mark.asyncio
async def test_tar_requires_mode():
rb, wb, _, mk, _ = _make_backend({})
with pytest.raises(ValueError, match="-c, -x, or -t"):
await tar([], read_bytes=rb, write_bytes=wb, mkdir_fn=mk)
@pytest.mark.asyncio
async def test_tar_requires_f():
rb, wb, _, mk, _ = _make_backend({"a.txt": b"x"})
with pytest.raises(ValueError, match="-f is required"):
await tar([_spec("a.txt")],
read_bytes=rb,
write_bytes=wb,
mkdir_fn=mk,
c=True)
@pytest.mark.asyncio
async def test_diff_identical_files():
rb, _, _, _, _ = _make_backend({"a": b"hello\n", "b": b"hello\n"})
async def rd(accessor, path, index=None):
return []
out, io_res = await diff([_spec("a"), _spec("b")],
read_bytes=rb,
readdir_fn=rd)
assert out == b""
assert io_res.exit_code == 0
@pytest.mark.asyncio
async def test_diff_quiet_differ():
rb, _, _, _, _ = _make_backend({"a": b"x\n", "b": b"y\n"})
async def rd(accessor, path, index=None):
return []
out, io_res = await diff([_spec("a"), _spec("b")],
read_bytes=rb,
readdir_fn=rd,
q=True)
assert b"differ" in out
assert io_res.exit_code == 1
@pytest.mark.asyncio
async def test_diff_unified():
rb, _, _, _, _ = _make_backend({
"a": b"hello\nworld\n",
"b": b"hello\nuniverse\n"
})
async def rd(accessor, path, index=None):
return []
out, _ = await diff([_spec("a"), _spec("b")],
read_bytes=rb,
readdir_fn=rd,
u=True)
assert b"-world" in out
assert b"+universe" in out
@pytest.mark.asyncio
async def test_diff_too_few_paths():
rb, _, _, _, _ = _make_backend({"a": b"x\n"})
async def rd(accessor, path, index=None):
return []
with pytest.raises(ValueError, match="two paths"):
await diff([_spec("a")], read_bytes=rb, readdir_fn=rd)
@pytest.mark.asyncio
async def test_patch_apply():
diff_text = (b"--- a/hello.txt\n+++ b/hello.txt\n@@ -1,2 +1,2 @@\n"
b" hello\n-world\n+universe\n")
rb, wb, _, _, store = _make_backend({"/hello.txt": b"hello\nworld\n"})
_, io_res = await patch([],
read_bytes=rb,
write_bytes=wb,
has_resource=True,
stdin=diff_text,
p="1")
assert b"universe" in store["/hello.txt"]
assert "/hello.txt" in io_res.writes
@pytest.mark.asyncio
async def test_patch_reverse():
diff_text = (b"--- a/x.txt\n+++ b/x.txt\n@@ -1,2 +1,2 @@\n"
b" hello\n-world\n+universe\n")
rb, wb, _, _, store = _make_backend({"/x.txt": b"hello\nuniverse\n"})
await patch([],
read_bytes=rb,
write_bytes=wb,
has_resource=True,
stdin=diff_text,
R=True,
p="1")
assert b"world" in store["/x.txt"]
@pytest.mark.asyncio
async def test_patch_missing_input():
rb, wb, _, _, store = _make_backend({})
out, io = await patch([],
read_bytes=rb,
write_bytes=wb,
has_resource=False)
assert out is None
assert io.exit_code == 0
assert not store