项目文件夹

文件
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

196 行
6.5 KiB
Python

import gzip as gziplib
import re
from collections.abc import (AsyncIterator, Awaitable, Callable, Mapping,
Sequence)
from dataclasses import dataclass
from functools import partial
from mirage.accessor.base import Accessor
from mirage.commands.builtin.grep_helper import (build_pattern_str,
resolve_pattern)
from mirage.commands.builtin.utils.lines import split_lines
from mirage.commands.builtin.utils.stream import _read_stdin_async
from mirage.commands.spec import SPECS
from mirage.commands.spec.types import FlagView
from mirage.io.types import ByteSource, IOResult
from mirage.types import PathSpec
async def _read_plain(
read_bytes: Callable[..., Awaitable[bytes]],
accessor: Accessor,
path: PathSpec,
index: object = None,
) -> bytes:
return await read_bytes(accessor, path)
def _zgrep_search(
data: bytes,
pattern: str,
ignore_case: bool,
invert: bool,
count: bool,
line_numbers: bool,
filename: str | None,
only_matching: bool,
max_count: int | None,
) -> tuple[list[str], bool]:
text = data.decode(errors="replace")
lines = split_lines(text)
flags = re.IGNORECASE if ignore_case else 0
matched: list[tuple[int, str]] = []
for idx, line in enumerate(lines, 1):
if only_matching and not invert:
hits = list(re.finditer(pattern, line, flags))
if hits:
for m in hits:
matched.append((idx, m.group()))
if max_count is not None and len(matched) >= max_count:
break
elif invert:
matched.append((idx, line))
else:
hit = bool(re.search(pattern, line, flags))
if invert:
hit = not hit
if hit:
matched.append((idx, line))
if max_count is not None and len(matched) >= max_count:
break
if count:
value = str(len(matched))
if filename:
value = f"{filename}:{value}"
return [value], len(matched) > 0
result: list[str] = []
for idx, line in matched:
prefix = ""
if filename:
prefix = filename + ":"
if line_numbers:
prefix += str(idx) + ":"
result.append(prefix + line)
return result, len(matched) > 0
def _files_only_match(data: bytes, pattern: str, ignore_case: bool,
invert: bool) -> bool:
text = data.decode(errors="replace")
flags = re.IGNORECASE if ignore_case else 0
for line in split_lines(text):
hit = bool(re.search(pattern, line, flags))
if invert:
hit = not hit
if hit:
return True
return False
@dataclass(frozen=True, slots=True)
class ZgrepFlags:
"""Parsed zgrep flags; the complete set zgrep honors."""
ignore_case: bool
invert: bool
count: bool
files_only: bool
line_numbers: bool
fixed: bool
force_filename: bool
suppress_filename: bool
only_matching: bool
quiet: bool
whole_word: bool
max_count: int | None
def parse_flags(fl: FlagView, never_match: bool) -> ZgrepFlags:
"""Convert the raw flag bag into ZgrepFlags, the only string-keyed reads.
Args:
fl (FlagView): spec-validated view over the raw flag kwargs.
never_match (bool): zero-pattern sentinel from resolve_pattern; it is
a regex, so it suppresses -F.
"""
return ZgrepFlags(
ignore_case=fl.bool("i"),
invert=fl.bool("v"),
count=fl.bool("c"),
files_only=fl.bool("args_l"),
line_numbers=fl.bool("n"),
fixed=fl.bool("F") and not never_match,
force_filename=fl.bool("H"),
suppress_filename=fl.bool("h"),
only_matching=fl.bool("o"),
quiet=fl.bool("q"),
whole_word=fl.bool("w"),
max_count=fl.int("m"),
)
async def zgrep(
paths: list[PathSpec],
texts: Sequence[str] = (),
flags: Mapping[str, object] | None = None,
*,
read_bytes: Callable[..., Awaitable[bytes]],
accessor: Accessor | None = None,
stdin: AsyncIterator[bytes] | bytes | None = None,
index: object = None,
) -> tuple[ByteSource | None, IOResult]:
fl = FlagView(flags, spec=SPECS["zgrep"])
pattern, never_match = await resolve_pattern(
texts, fl, partial(_read_plain, read_bytes), accessor, index,
"zgrep: usage: zgrep [flags] pattern [path]")
f = parse_flags(fl, never_match)
compiled = build_pattern_str(pattern, f.fixed, f.whole_word)
multi = len(paths) > 1
show_filename = f.force_filename or (multi and not f.suppress_filename)
any_match = False
all_results: list[str] = []
if paths:
for p in paths:
raw = await read_bytes(accessor, p)
data = gziplib.decompress(raw)
fname = p.virtual if show_filename else None
if f.files_only:
if _files_only_match(data, compiled, f.ignore_case, f.invert):
all_results.append(p.virtual)
any_match = True
else:
result, had_match = _zgrep_search(data, compiled,
f.ignore_case, f.invert,
f.count, f.line_numbers,
fname, f.only_matching,
f.max_count)
if had_match:
any_match = True
all_results.extend(result)
else:
raw = await _read_stdin_async(stdin)
data = gziplib.decompress(raw) if raw else b""
if f.files_only:
if _files_only_match(data, compiled, f.ignore_case, f.invert):
all_results.append("(standard input)")
any_match = True
else:
result, had_match = _zgrep_search(data, compiled, f.ignore_case,
f.invert, f.count,
f.line_numbers, None,
f.only_matching, f.max_count)
if had_match:
any_match = True
all_results.extend(result)
if f.quiet:
return None, IOResult(exit_code=0 if any_match else 1)
exit_code = 0 if any_match else 1
if not all_results:
return None, IOResult(exit_code=exit_code)
return ("\n".join(all_results) +
"\n").encode(), IOResult(exit_code=exit_code)
__all__ = ["zgrep"]