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

149 lines
4.7 KiB
Python

import binascii
import re
from collections.abc import AsyncIterator, Callable
from mirage.accessor.base import Accessor
from mirage.commands.builtin.utils.lines import split_lines
from mirage.commands.builtin.utils.stream import _resolve_source
from mirage.commands.spec.types import CommandName
from mirage.commands.spec.usage import extra_operand_error
from mirage.io.types import ByteSource, IOResult
from mirage.types import PathSpec
async def _xxd_dump_stream(source: AsyncIterator[bytes], cols: int, group: int,
uppercase: bool) -> AsyncIterator[bytes]:
fmt = "{:02X}" if uppercase else "{:02x}"
offset_fmt = "{:08X}: " if uppercase else "{:08x}: "
offset = 0
leftover = b""
async for chunk in source:
data = leftover + chunk
i = 0
while i + cols <= len(data):
row = data[i:i + cols]
hex_parts: list[str] = []
for g in range(0, len(row), group):
hex_parts.append("".join(
fmt.format(b) for b in row[g:g + group]))
hex_part = " ".join(hex_parts)
ascii_part = "".join(chr(b) if 32 <= b < 127 else "." for b in row)
line = offset_fmt.format(
offset
) + f"{hex_part:<{cols * 2 + (cols // group) - 1}} {ascii_part}\n"
yield line.encode()
offset += cols
i += cols
leftover = data[i:]
if leftover:
hex_parts = []
for g in range(0, len(leftover), group):
hex_parts.append("".join(
fmt.format(b) for b in leftover[g:g + group]))
hex_part = " ".join(hex_parts)
ascii_part = "".join(
chr(b) if 32 <= b < 127 else "." for b in leftover)
line = offset_fmt.format(
offset
) + f"{hex_part:<{cols * 2 + (cols // group) - 1}} {ascii_part}\n"
yield line.encode()
async def _xxd_plain_stream(source: AsyncIterator[bytes],
uppercase: bool) -> AsyncIterator[bytes]:
async for chunk in source:
h = binascii.hexlify(chunk)
yield h.upper() if uppercase else h
yield b"\n"
def _reverse_line(line: str) -> bytes:
if ":" in line:
line = line.split(":", 1)[1]
parts = re.split(r" +", line, maxsplit=1)
hex_part = parts[0].replace(" ", "")
if not hex_part:
return b""
try:
return binascii.unhexlify(hex_part)
except binascii.Error:
return b""
async def _xxd_reverse_stream(
source: AsyncIterator[bytes]) -> AsyncIterator[bytes]:
buf = b""
async for chunk in source:
buf += chunk
text = buf.decode(errors="replace")
if ":" in text:
for line in split_lines(text):
if line:
yield _reverse_line(line)
else:
cleaned = re.sub(r"\s+", "", text)
yield binascii.unhexlify(cleaned) if cleaned else b""
async def _apply_limits(source: AsyncIterator[bytes], skip: int,
limit: int) -> AsyncIterator[bytes]:
pos = 0
remaining = limit
async for chunk in source:
chunk_len = len(chunk)
if pos + chunk_len <= skip:
pos += chunk_len
continue
if pos < skip:
chunk = chunk[skip - pos:]
pos = skip
if remaining <= 0:
break
if len(chunk) > remaining:
chunk = chunk[:remaining]
yield chunk
remaining -= len(chunk)
pos += len(chunk)
async def xxd(
paths: list[PathSpec],
*,
read_stream: Callable[..., AsyncIterator[bytes]],
accessor: Accessor | None = None,
stdin: AsyncIterator[bytes] | bytes | None = None,
reverse: bool = False,
plain: bool = False,
uppercase: bool = False,
cols: int = 16,
group: int = 2,
skip: int = 0,
limit: int = 0,
) -> tuple[ByteSource | None, IOResult]:
if len(paths) > 2:
raise extra_operand_error(CommandName.XXD, paths[2].raw_path)
cache: list[str] = []
if paths:
source: AsyncIterator[bytes] = read_stream(accessor, paths[0])
cache = [paths[0].mount_path]
else:
source = _resolve_source(stdin)
if skip or limit:
if not limit:
limit = 2**63
source = _apply_limits(source, skip, limit)
if reverse:
return _xxd_reverse_stream(source), IOResult(cache=cache)
if plain:
return _xxd_plain_stream(source,
uppercase=uppercase), IOResult(cache=cache)
return _xxd_dump_stream(source,
cols=cols,
group=group,
uppercase=uppercase), IOResult(cache=cache)
__all__ = ["xxd"]