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

103 lines
4.4 KiB
Python

from mirage.accessor.sharepoint import SharePointAccessor
from mirage.cache.index import IndexCacheStore, IndexEntry, ResourceType
from mirage.core.sharepoint._client import GraphError, graph_list, item_url
from mirage.core.sharepoint._resolver import list_drives, list_sites, resolve
from mirage.core.sharepoint.stat import stat
from mirage.types import FileType, PathSpec
from mirage.utils.errors import enoent
from mirage.utils.key_prefix import mount_prefix_of
async def readdir(accessor: SharePointAccessor, path: PathSpec,
index: IndexCacheStore) -> list[str]:
if isinstance(path, str):
path = PathSpec(virtual=path,
directory=path,
resource_path=path.strip("/"))
original = path
prefix = mount_prefix_of(path.virtual, path.resource_path) or ""
raw = path.directory if path.pattern else path.virtual
if prefix and raw.startswith(prefix):
rest = raw[len(prefix):]
if prefix.endswith("/") or rest == "" or rest.startswith("/"):
raw = rest or "/"
stripped = raw.strip("/")
virtual_key = (prefix + "/" + stripped if prefix else "/" + stripped) \
if stripped else (prefix or "/")
listing = await index.list_dir(virtual_key)
if listing.entries is not None:
return listing.entries
resolved = await resolve(accessor, path)
if resolved.level == "root":
sites = await list_sites(accessor)
names = sorted("/" + s for s in sites)
index_entries = [(s,
IndexEntry(id="/" + s,
name=s,
resource_type=ResourceType.FOLDER,
size=None,
remote_time="")) for s in sites]
await index.set_dir(virtual_key, index_entries)
virtual_entries = sorted((prefix + e if prefix else e) for e in names)
return virtual_entries
if resolved.level == "site" and resolved.site_id is not None:
drives = await list_drives(accessor, resolved.site_id)
base = "/" + stripped if stripped else ""
names = sorted(f"{base}/{d}" for d in drives)
index_entries = [(d,
IndexEntry(id=f"{base}/{d}",
name=d,
resource_type=ResourceType.FOLDER,
size=None,
remote_time="")) for d in drives]
await index.set_dir(virtual_key, index_entries)
virtual_entries = sorted((prefix + e if prefix else e) for e in names)
return virtual_entries
if resolved.drive_id is None:
return []
drive_id = resolved.drive_id
item_path = resolved.item_path or ""
url = item_url(drive_id,
"/" + item_path if item_path else "/",
action="/children")
try:
children = await graph_list(accessor.config, url)
except GraphError as exc:
if exc.status != 404:
raise
info = await stat(accessor, original)
if info.type != FileType.DIRECTORY:
raise NotADirectoryError(virtual_key) from exc
raise enoent(virtual_key) from exc
base = "/" + stripped if stripped else ""
names: list[str] = []
index_entries: list[tuple[str, IndexEntry]] = []
for child in children:
cname = child.get("name", "")
key = f"{base}/{cname}"
names.append(key)
if "folder" in child:
entry = IndexEntry(id=key,
name=cname,
resource_type=ResourceType.FOLDER,
size=child.get("size"),
remote_time=child.get("lastModifiedDateTime",
""))
else:
entry = IndexEntry(id=key,
name=cname,
resource_type=ResourceType.FILE,
size=child.get("size"),
remote_time=child.get("lastModifiedDateTime",
""))
index_entries.append((cname, entry))
names = sorted(names)
virtual_entries = sorted((prefix + e if prefix else e) for e in names)
await index.set_dir(virtual_key, index_entries)
return virtual_entries