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

139 lines
4.5 KiB
Python

import inspect
from collections import deque
from collections.abc import AsyncIterator
from typing import Any, Callable
from mirage.accessor.base import Accessor
from mirage.cache.read_through import cache_aware_read
from mirage.types import PathSpec
from mirage.utils.stream import ensure_stream
async def head(
src: bytes | AsyncIterator[bytes],
*,
n: int | None = None,
c: int | None = None,
) -> AsyncIterator[bytes]:
if c is not None:
if c == 0:
return
if c > 0:
emitted = 0
async for chunk in ensure_stream(src):
remaining = c - emitted
if len(chunk) >= remaining:
if remaining > 0:
yield chunk[:remaining]
return
yield chunk
emitted += len(chunk)
return
keep = -c
buf = b""
async for chunk in ensure_stream(src):
buf += chunk
if len(buf) > keep:
yield buf[:-keep]
buf = buf[-keep:]
return
target = n if n is not None else 10
if target >= 0:
if target == 0:
return
emitted_lines = 0
buf = b""
async for chunk in ensure_stream(src):
buf += chunk
while b"\n" in buf and emitted_lines < target:
line, buf = buf.split(b"\n", 1)
yield line + b"\n"
emitted_lines += 1
if emitted_lines >= target:
return
if buf and emitted_lines < target:
yield buf
return
keep = -target
recent: deque[bytes] = deque(maxlen=keep)
buf = b""
async for chunk in ensure_stream(src):
buf += chunk
while b"\n" in buf:
line, buf = buf.split(b"\n", 1)
if len(recent) == keep:
yield recent[0] + b"\n"
recent.append(line)
def head_multi(
paths: list[PathSpec],
*,
read: Callable[..., Any],
accessor: Accessor | None = None,
index: object = None,
n: int | None = None,
c: int | None = None,
show_headers: bool = False,
) -> AsyncIterator[bytes]:
"""Run head over multiple already-resolved paths.
Globs are expanded by the caller, so ``paths`` is a flat list of concrete
entries. When ``show_headers`` is set a ``==> path <==`` banner is emitted
before each file (POSIX/GNU head with multiple files), separated by a blank
line between files. The per-file source is produced lazily by ``read`` so
only one file streams at a time.
This is a plain ``def`` returning the async generator: the cache-aware
wrap captures the active manager now, when the command calls
``head_multi`` inside the mount's cache-manager scope, not when the
returned stream is drained later (after that scope is gone). A warm read
then returns the cached bytes; only a cold read streams lazily from the
backend, preserving early-exit (``cat big | head -5``).
Args:
paths (list[PathSpec]): Resolved paths; only ``.virtual`` is read.
read (Callable[..., Any]): Reader called as ``read(accessor, path,
index)``; returns bytes, an awaitable of bytes, or an async byte
iterator.
accessor (Accessor | None): Backend accessor passed through to
``read``.
index (object): Index cache store passed through to ``read``.
n (int | None): Line count (negative = all-but-last-N, per head).
c (int | None): Byte count.
show_headers (bool): Emit ``==> path <==`` banners between files.
"""
return _head_multi(paths,
read=cache_aware_read(read),
accessor=accessor,
index=index,
n=n,
c=c,
show_headers=show_headers)
async def _head_multi(
paths: list[PathSpec],
*,
read: Callable[..., Any],
accessor: Accessor | None = None,
index: object = None,
n: int | None = None,
c: int | None = None,
show_headers: bool = False,
) -> AsyncIterator[bytes]:
for i, p in enumerate(paths):
if show_headers:
header = f"==> {p.raw_path} <==\n"
if i > 0:
header = "\n" + header
yield header.encode()
source = read(accessor, p, index)
if inspect.isawaitable(source):
source = await source
async for chunk in head(source, n=n, c=c):
yield chunk