chore: import upstream snapshot with attribution
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
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
This commit is contained in:
@@ -0,0 +1,228 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import asyncio
|
||||
import copy as _copy
|
||||
import os
|
||||
import tempfile
|
||||
|
||||
from mirage import MountMode, Workspace
|
||||
from mirage.resource.ram import RAMResource
|
||||
|
||||
resource = RAMResource()
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ws = Workspace({"/data": resource}, mode=MountMode.WRITE)
|
||||
|
||||
print("=== tee (create files) ===")
|
||||
await ws.execute('echo "hello world" | tee /data/hello.txt')
|
||||
await ws.execute(
|
||||
'echo \'{"name": "alice", "age": 30}\' | tee /data/user.json')
|
||||
await ws.execute("mkdir /data/reports")
|
||||
await ws.execute(
|
||||
'echo "revenue,100\\nexpense,80" | tee /data/reports/q1.csv')
|
||||
|
||||
print("=== ls /data/ ===")
|
||||
result = await ws.execute("ls /data/")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== cat /data/hello.txt ===")
|
||||
result = await ws.execute("cat /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== head -n 1 /data/reports/q1.csv ===")
|
||||
result = await ws.execute("head -n 1 /data/reports/q1.csv")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== tail -n 1 /data/reports/q1.csv ===")
|
||||
result = await ws.execute("tail -n 1 /data/reports/q1.csv")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== wc /data/hello.txt ===")
|
||||
result = await ws.execute("wc /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== stat /data/hello.txt ===")
|
||||
result = await ws.execute("stat /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== jq .name /data/user.json ===")
|
||||
result = await ws.execute('jq ".name" /data/user.json')
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== nl /data/reports/q1.csv ===")
|
||||
result = await ws.execute("nl /data/reports/q1.csv")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== tree /data/ ===")
|
||||
result = await ws.execute("tree /data/")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== find /data/ -name '*.txt' ===")
|
||||
result = await ws.execute("find /data/ -name '*.txt'")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== grep hello /data/hello.txt ===")
|
||||
result = await ws.execute("grep hello /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== rg hello /data/hello.txt ===")
|
||||
result = await ws.execute("rg hello /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== basename /data/hello.txt ===")
|
||||
result = await ws.execute("basename /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== dirname /data/hello.txt ===")
|
||||
result = await ws.execute("dirname /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== realpath /data/hello.txt ===")
|
||||
result = await ws.execute("realpath /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== sort /data/reports/q1.csv ===")
|
||||
result = await ws.execute("sort /data/reports/q1.csv")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== tr a-z A-Z < /data/hello.txt ===")
|
||||
result = await ws.execute("cat /data/hello.txt | tr a-z A-Z")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== cp /data/hello.txt /data/hello_copy.txt ===")
|
||||
await ws.execute("cp /data/hello.txt /data/hello_copy.txt")
|
||||
result = await ws.execute("cat /data/hello_copy.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== mv /data/hello_copy.txt /data/renamed.txt ===")
|
||||
await ws.execute("mv /data/hello_copy.txt /data/renamed.txt")
|
||||
result = await ws.execute("ls /data/")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== rm /data/renamed.txt ===")
|
||||
await ws.execute("rm /data/renamed.txt")
|
||||
result = await ws.execute("ls /data/")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== du /data/ ===")
|
||||
result = await ws.execute("du /data/")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== sed ===")
|
||||
result = await ws.execute("cat /data/hello.txt | sed s/hello/goodbye/")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== awk ===")
|
||||
result = await ws.execute("cat /data/reports/q1.csv | awk -F, '{print $1}'"
|
||||
)
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== uniq ===")
|
||||
await ws.execute('echo "a\\na\\nb\\nb\\nc" | tee /data/dup.txt')
|
||||
result = await ws.execute("sort /data/dup.txt | uniq")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== rev ===")
|
||||
result = await ws.execute("cat /data/hello.txt | rev")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== md5 /data/hello.txt ===")
|
||||
result = await ws.execute("md5 /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== base64 /data/hello.txt ===")
|
||||
result = await ws.execute("base64 /data/hello.txt")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== not-found errors show the full virtual path ===")
|
||||
for cmd in ("cat /data/missing.txt", "head /data/missing.txt",
|
||||
"stat /data/missing.txt"):
|
||||
result = await ws.execute(cmd)
|
||||
print(f"$ {cmd}")
|
||||
print(f" exit={result.exit_code} "
|
||||
f"{(await result.stderr_str()).strip()}")
|
||||
|
||||
print("=== history (last 5) ===")
|
||||
result = await ws.execute("history 5")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("\n=== /dev (auto-mounted synthetic devices) ===\n")
|
||||
print("=== ls /dev/ ===")
|
||||
result = await ws.execute("ls /dev/")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== wc -c /dev/null ===")
|
||||
result = await ws.execute("wc -c /dev/null")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== wc -c /dev/zero ===")
|
||||
result = await ws.execute("wc -c /dev/zero")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== md5 /dev/zero ===")
|
||||
result = await ws.execute("md5 /dev/zero")
|
||||
print(await result.stdout_str())
|
||||
|
||||
print("=== head -c 8 /dev/zero | xxd ===")
|
||||
result = await ws.execute("head -c 8 /dev/zero | xxd")
|
||||
print(await result.stdout_str())
|
||||
|
||||
# ── provision: dry-run cost estimates (nothing executes) ────────
|
||||
# Read families estimate bytes from stat; pipes/&&/; sum, || takes
|
||||
# a min-max envelope, and writes report UNKNOWN.
|
||||
print("\n=== PROVISION (dry-run cost estimates) ===\n")
|
||||
for cmd in ("cat /data/hello.txt", "sort /data/hello.txt | head -n 1",
|
||||
"head /data/hello.txt || cat /data/hello.txt",
|
||||
"tee /data/out.txt"):
|
||||
plan = await ws.execute(cmd, provision=True)
|
||||
print(f" {cmd}: net={plan.network_read} ops={plan.read_ops} "
|
||||
f"precision={plan.precision.value}")
|
||||
|
||||
# ── persistence: save / load / copy / deepcopy ──────────────────
|
||||
# RAM has no redacted config: full content is in the snapshot, so
|
||||
# no resources= needed at load time.
|
||||
print("\n=== PERSISTENCE ===\n")
|
||||
with tempfile.NamedTemporaryFile(suffix=".tar", delete=False) as f:
|
||||
snap = f.name
|
||||
try:
|
||||
await ws.snapshot(snap)
|
||||
print(f" saved → {snap} ({os.path.getsize(snap)} bytes)")
|
||||
|
||||
loaded = await Workspace.load(snap)
|
||||
r = await loaded.execute("cat /data/hello.txt")
|
||||
print(f" loaded ws cat: {(await r.stdout_str()).strip()!r}")
|
||||
|
||||
cp = await ws.copy()
|
||||
await cp.execute('echo "mutated" | tee /data/hello.txt')
|
||||
r_orig = await ws.execute("cat /data/hello.txt")
|
||||
r_cp = await cp.execute("cat /data/hello.txt")
|
||||
print(f" original: {(await r_orig.stdout_str()).strip()!r}")
|
||||
print(f" copy: {(await r_cp.stdout_str()).strip()!r} "
|
||||
"(local backend → independent)")
|
||||
|
||||
for op_name, op in (("deepcopy", _copy.deepcopy), ("shallow copy",
|
||||
_copy.copy)):
|
||||
try:
|
||||
op(ws)
|
||||
print(f" ✗ {op_name} should have raised")
|
||||
except NotImplementedError as e:
|
||||
print(f" ✓ {op_name} raises: {str(e)[:60]}…")
|
||||
finally:
|
||||
os.unlink(snap)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,63 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
|
||||
from mirage import Mount, MountMode, Workspace
|
||||
from mirage.resource.ram import RAMResource
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[3]
|
||||
DATA_DIR = REPO_ROOT / "data"
|
||||
|
||||
resource = RAMResource()
|
||||
store = resource._store
|
||||
|
||||
for fpath in sorted(DATA_DIR.iterdir()):
|
||||
if fpath.is_file():
|
||||
key = "/" + fpath.name
|
||||
store.files[key] = fpath.read_bytes()
|
||||
store.dirs.add("/")
|
||||
|
||||
print(f"Loaded {len(store.files)} files from {DATA_DIR}")
|
||||
for name in sorted(store.files):
|
||||
size = len(store.files[name])
|
||||
print(f" {name} ({size:,} bytes)")
|
||||
|
||||
with Workspace({"/data/": Mount(resource, mode=MountMode.WRITE,
|
||||
fuse=True)}) as ws:
|
||||
mp = ws.fuse_mountpoint
|
||||
|
||||
print(f"\n=== FUSE MODE: mounted at {mp} ===\n")
|
||||
|
||||
data_path = mp
|
||||
|
||||
print("--- os.listdir() ---")
|
||||
entries = os.listdir(data_path)
|
||||
for e in entries:
|
||||
size = os.path.getsize(f"{data_path}/{e}")
|
||||
print(f" {e:30s} {size:>10,} bytes")
|
||||
|
||||
print(f"\n>>> FUSE mounted at: {mp}")
|
||||
print(">>> Open another terminal and try:")
|
||||
print(f">>> ls -la {mp}/")
|
||||
print(f">>> cat {mp}/example.json")
|
||||
print(f">>> cat {mp}/example.json | jq .")
|
||||
print(f">>> cat {mp}/example.parquet")
|
||||
print(">>> Press Enter to unmount and exit...")
|
||||
input()
|
||||
|
||||
records = ws.ops.records
|
||||
total = sum(r.bytes for r in records)
|
||||
print(f"\nStats: {len(records)} ops, {total} bytes transferred")
|
||||
@@ -0,0 +1,61 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import os
|
||||
import time
|
||||
from pathlib import Path
|
||||
|
||||
from mirage import Mount, MountMode, Workspace
|
||||
from mirage.resource.ram import RAMResource
|
||||
|
||||
REPO_ROOT = Path(__file__).resolve().parents[3]
|
||||
DATA_DIR = REPO_ROOT / "data"
|
||||
|
||||
resource = RAMResource()
|
||||
store = resource._store
|
||||
|
||||
for fpath in sorted(DATA_DIR.iterdir()):
|
||||
if fpath.is_file():
|
||||
key = "/" + fpath.name
|
||||
store.files[key] = fpath.read_bytes()
|
||||
store.dirs.add("/")
|
||||
|
||||
print(f"Seeded {len(store.files)} files from {DATA_DIR}")
|
||||
|
||||
with Workspace({"/data/": Mount(resource, fuse=True)},
|
||||
mode=MountMode.READ) as ws:
|
||||
time.sleep(1)
|
||||
mp = ws.fuse_mountpoint
|
||||
|
||||
print(f"\n=== FUSE MODE (READ): mounted at {mp} ===\n")
|
||||
|
||||
data_path = mp
|
||||
entries = sorted(os.listdir(data_path))
|
||||
for e in entries:
|
||||
size = os.path.getsize(f"{data_path}/{e}")
|
||||
print(f" {e:30s} {size:>10,} bytes")
|
||||
|
||||
existing = entries[0] if entries else "example.json"
|
||||
print(f"\n>>> FUSE mounted READ-ONLY at: {mp}")
|
||||
print(">>> In another terminal: reads ok, writes fail (EACCES).")
|
||||
print(f">>> cat {data_path}/{existing} # ok")
|
||||
print(f">>> echo hi > {data_path}/new.txt # EACCES (create)")
|
||||
print(
|
||||
f">>> echo hi > {data_path}/{existing} # EACCES (overwrite)")
|
||||
print(">>> Press Enter to unmount and exit...")
|
||||
input()
|
||||
|
||||
records = ws.ops.records
|
||||
total = sum(r.bytes for r in records)
|
||||
print(f"\nStats: {len(records)} ops, {total} bytes transferred")
|
||||
@@ -0,0 +1,69 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import asyncio
|
||||
|
||||
from mirage import MountMode, Workspace
|
||||
from mirage.resource.ram import RAMResource
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
ws = Workspace({"/ram": RAMResource()}, mode=MountMode.EXEC)
|
||||
|
||||
print("=== python3 -c (basic) ===")
|
||||
r = await ws.execute('python3 -c "print(42)"')
|
||||
print(f"stdout: {(await r.stdout_str()).strip()} (expected: 42)")
|
||||
|
||||
print("\n=== python3 -c with argv (flag-conditional) ===")
|
||||
r = await ws.execute(
|
||||
'python3 -c "import sys; print(sys.argv[1:])" alpha beta')
|
||||
print(f"argv after -c: {(await r.stdout_str()).strip()} "
|
||||
f"(expected: ['alpha', 'beta'])")
|
||||
|
||||
print("\n=== python3 /ram/script.py (abs path → dispatch read) ===")
|
||||
await ws.execute("echo 'print(\"hello from vfs\")' > /ram/h.py")
|
||||
r = await ws.execute("python3 /ram/h.py")
|
||||
print(f"stdout: {(await r.stdout_str()).strip()} "
|
||||
f"(expected: hello from vfs)")
|
||||
|
||||
print("\n=== python3 /abs/script.py arg1 arg2 (script + argv) ===")
|
||||
await ws.execute("echo 'import sys; print(sys.argv[1:])' > /ram/argv.py")
|
||||
r = await ws.execute("python3 /ram/argv.py one two")
|
||||
print(f"argv after script: {(await r.stdout_str()).strip()} "
|
||||
f"(expected: ['one', 'two'])")
|
||||
|
||||
print("\n=== python3 bare-name script via cwd ===")
|
||||
r = await ws.execute("cd /ram && python3 h.py")
|
||||
print(f"stdout: {(await r.stdout_str()).strip()} "
|
||||
f"(expected: hello from vfs)")
|
||||
|
||||
print("\n=== echo code | python3 (stdin) ===")
|
||||
r = await ws.execute('echo "print(7*6)" | python3')
|
||||
print(f"stdout: {(await r.stdout_str()).strip()} (expected: 42)")
|
||||
|
||||
print("\n=== heredoc ===")
|
||||
r = await ws.execute("python3 <<PYEOF\nprint(1 + 2)\nPYEOF")
|
||||
print(f"stdout: {(await r.stdout_str()).strip()} (expected: 3)")
|
||||
|
||||
print("\n=== session env passthrough ===")
|
||||
await ws.execute("export GREETING=hello_mirage")
|
||||
r = await ws.execute(
|
||||
"python3 -c \"import os; print(os.environ.get('GREETING','none'))\"")
|
||||
print(
|
||||
f"stdout: {(await r.stdout_str()).strip()} (expected: hello_mirage)")
|
||||
|
||||
await ws.close()
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,128 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import asyncio
|
||||
|
||||
from mirage import MountMode, Workspace
|
||||
from mirage.resource.ram import RAMResource
|
||||
|
||||
|
||||
async def run(ws: Workspace, cmd: str) -> None:
|
||||
print(f"\n$ {cmd}")
|
||||
try:
|
||||
result = await ws.execute(cmd)
|
||||
out = (await result.stdout_str()).rstrip()
|
||||
if out:
|
||||
print(out)
|
||||
err = (await result.stderr_str()).rstrip()
|
||||
if err:
|
||||
print(f"stderr: {err}")
|
||||
if result.exit_code != 0:
|
||||
print(f"exit={result.exit_code}")
|
||||
except Exception as e:
|
||||
print(f"threw: {e}")
|
||||
|
||||
|
||||
async def main() -> None:
|
||||
resource = RAMResource()
|
||||
ws = Workspace({"/data": resource}, mode=MountMode.WRITE)
|
||||
|
||||
def seed(path: str, data: bytes) -> None:
|
||||
resource._store.files[path] = data
|
||||
|
||||
seed("/dup.txt", b"banana\napple\ncherry\napple\n")
|
||||
seed("/sorted1.txt", b"apple\nbanana\ndate\n")
|
||||
seed("/sorted2.txt", b"banana\ncherry\ndate\n")
|
||||
seed("/tsv.txt", b"a\tb\tc\nfoo\t42\tbar\nhello\t7\tworld\n")
|
||||
seed("/csv.txt", b"1,alpha,x\n2,beta,y\n3,gamma,z\n")
|
||||
seed("/tabs.txt", b"\tfoo\n\t\tbar\n")
|
||||
seed(
|
||||
"/prose.txt",
|
||||
b"The quick brown fox jumps over the lazy dog. "
|
||||
b"The quick brown fox jumps over the lazy dog. "
|
||||
b"The quick brown fox jumps over the lazy dog.\n",
|
||||
)
|
||||
seed("/words.txt", b"apple\nant\nbanana\nberry\ncherry\n")
|
||||
seed("/join_a.txt", b"1 alpha\n2 beta\n3 gamma\n")
|
||||
seed("/join_b.txt", b"1 red\n2 green\n3 blue\n")
|
||||
seed("/deps.txt", b"a b\nb c\nc d\n")
|
||||
seed(
|
||||
"/binary.bin",
|
||||
bytes([
|
||||
0x00, 0x01, 0x68, 0x65, 0x6c, 0x6c, 0x6f, 0x00, 0x02, 0x77, 0x6f,
|
||||
0x72, 0x6c, 0x64, 0x00, 0xff
|
||||
]),
|
||||
)
|
||||
|
||||
print("━━━ column ━━━")
|
||||
await run(ws, "column -t /data/tsv.txt")
|
||||
|
||||
print("\n━━━ comm (sorted1 vs sorted2) ━━━")
|
||||
await run(ws, "comm /data/sorted1.txt /data/sorted2.txt")
|
||||
|
||||
print("\n━━━ expand / unexpand ━━━")
|
||||
await run(ws, "expand -t 4 /data/tabs.txt")
|
||||
await run(ws, "unexpand -t 4 /data/tsv.txt")
|
||||
|
||||
print("\n━━━ fmt / fold ━━━")
|
||||
await run(ws, "fmt -w 40 /data/prose.txt")
|
||||
await run(ws, "fold -w 20 -s /data/prose.txt")
|
||||
|
||||
print("\n━━━ iconv ━━━")
|
||||
await run(ws, "iconv -f utf-8 -t latin1 /data/sorted1.txt")
|
||||
|
||||
print("\n━━━ join ━━━")
|
||||
await run(ws, "join /data/join_a.txt /data/join_b.txt")
|
||||
|
||||
print("\n━━━ look ━━━")
|
||||
await run(ws, "look ban /data/words.txt")
|
||||
await run(ws, "look app /data/words.txt")
|
||||
|
||||
print("\n━━━ mktemp ━━━")
|
||||
await run(ws, "mktemp -p /data")
|
||||
|
||||
print("\n━━━ shuf / strings ━━━")
|
||||
await run(ws, "shuf /data/dup.txt")
|
||||
await run(ws, "strings -n 4 /data/binary.bin")
|
||||
|
||||
print("\n━━━ tsort ━━━")
|
||||
await run(ws, "tsort /data/deps.txt")
|
||||
|
||||
print("\n━━━ csplit (split on pattern) ━━━")
|
||||
await run(ws, "csplit /data/tsv.txt '/hello/'")
|
||||
await run(ws, "ls /data/")
|
||||
|
||||
print("\n━━━ zip + unzip (roundtrip) ━━━")
|
||||
await run(ws, "zip /data/out.zip /data/sorted1.txt /data/sorted2.txt")
|
||||
await run(ws, "unzip -d /data/extracted /data/out.zip")
|
||||
await run(ws, "ls /data/extracted/")
|
||||
await run(ws, "ls /data/extracted/data/")
|
||||
await run(ws, "cat /data/extracted/data/sorted1.txt")
|
||||
|
||||
print("\n━━━ zgrep (gzip then search) ━━━")
|
||||
await run(ws, "gzip /data/words.txt")
|
||||
await run(ws, "zgrep banana /data/words.txt.gz")
|
||||
|
||||
print("\n━━━ patch (unified diff) ━━━")
|
||||
seed("/orig.txt", b"line1\nline2\nline3\n")
|
||||
seed(
|
||||
"/change.diff",
|
||||
b"--- /orig.txt\n+++ /orig.txt\n"
|
||||
b"@@ -1,3 +1,3 @@\n line1\n-line2\n+LINE2\n line3\n",
|
||||
)
|
||||
await run(ws, "patch -i /data/change.diff")
|
||||
await run(ws, "cat /data/orig.txt")
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
@@ -0,0 +1,60 @@
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
# ========= Copyright 2026 @ Strukto.AI All Rights Reserved. =========
|
||||
|
||||
import asyncio
|
||||
import sys
|
||||
|
||||
from mirage import MountMode, Workspace
|
||||
from mirage.resource.ram import RAMResource
|
||||
|
||||
resource = RAMResource()
|
||||
|
||||
|
||||
async def main():
|
||||
ws = Workspace({"/data": resource}, mode=MountMode.WRITE)
|
||||
|
||||
await ws.execute('echo "hello world" | tee /data/hello.txt')
|
||||
await ws.execute("mkdir /data/sub")
|
||||
await ws.execute('echo "nested" | tee /data/sub/nested.txt')
|
||||
|
||||
with ws:
|
||||
vos = sys.modules["os"]
|
||||
print("=== VFS MODE ===\n")
|
||||
|
||||
print("--- os.listdir() ---")
|
||||
entries = vos.listdir("/data")
|
||||
for e in entries:
|
||||
print(f" {e}")
|
||||
|
||||
print("\n--- open() + read ---")
|
||||
with open("/data/hello.txt") as f:
|
||||
print(f" {f.read().strip()}")
|
||||
|
||||
print("\n--- os.path.exists() ---")
|
||||
print(f" hello.txt: {vos.path.exists('/data/hello.txt')}")
|
||||
print(f" nope.txt: {vos.path.exists('/data/nope.txt')}")
|
||||
|
||||
print("\n--- os.path.isdir() ---")
|
||||
print(f" /data/sub: {vos.path.isdir('/data/sub')}")
|
||||
|
||||
print("\n--- os.listdir() sub ---")
|
||||
for e in vos.listdir("/data/sub"):
|
||||
print(f" {e}")
|
||||
|
||||
records = ws.ops.records
|
||||
total = sum(r.bytes for r in records)
|
||||
print(f"\nStats: {len(records)} ops, {total} bytes transferred")
|
||||
|
||||
|
||||
asyncio.run(main())
|
||||
Reference in New Issue
Block a user