fsspec is the filesystem interface the Python data stack
reads through: pandas, pyarrow, dask, Ray and LlamaIndex all resolve a URL like
s3://bucket/key by handing it to fsspec, which hands it to whichever implementation is registered
for that scheme. Point the implementation at Backlot and everything above it follows — a
read_csv("s3://…") in code you did not write now reads your corpus.
pip install -e ".[fsspec]"
python examples/using-fsspec/s3.py # local throwaway server
python examples/using-fsspec/s3.py --url http://localhost:8000 --access-key <AKIA...> --secret-key <secret>
python examples/using-fsspec/gdrive.py --url http://localhost:8000 --token <usr-token>
python examples/using-fsspec/github.py --url http://localhost:8000 --token <usr-token> --repo pipelineEach script spins up its own throwaway mock on a tiny in-code corpus, reads it through fsspec, and
finishes by loading a table into pandas. Pass --url to drive an already-running mock instead. All
reads are ACL-scoped by the credential you pass, exactly as against the real API.
| Source | fsspec implementation | How it's pointed at Backlot |
|---|---|---|
| S3 | s3fs (s3://) |
client_kwargs={"endpoint_url": f"{base_url}/s3"} — an ordinary constructor argument |
| Google Drive | gdrive-fsspec (gdrive://) |
drive_filesystem_at() — it has no endpoint argument |
| GitHub | fsspec.implementations.github (github://) |
github_filesystem_at() — it has no endpoint argument either |
-
S3 (
s3.py): the easy one. s3fs takes the endpoint as a constructor argument and SigV4-signs against it, so there is no shim —storage_optionsin the script is the entire redirect, and the same dict works forfsspec.open,fsspec.filesystemandpandas.read_csv. The script does callpatch_s3fs_walk(), which is not a mock concern: s3fs's async_walkpassestopdowndown to an_lsthat does not accept it, sofs.find()andfs.walk()raise against real AWS too. The shim strips the kwarg and no-ops itself once upstream accepts it. It lives in thellamaindexmodule because that is where the bug was first hit; it is the same shim wherever you reach it from. -
Google Drive (
gdrive.py): the one that needsbacklot.integrations.fsspec.gdrive_fsspecbuilds its Google Drive service with a barebuild("drive", "v3")— no endpoint argument anywhere — sodrive_filesystem_at()supplies one, and works around three of its defects along the way. None of the three is about Backlot; all three reproduce against real Google Drive:Defect What you see Why Cached parent listing ls("folder")returns["folder"]instead of its children, so every recursive walk stops one level inlsconsults_ls_from_cache, which answers out of the cached parent listing with that directory's own entryLeading slash ls("/folder")raisesFileNotFoundErrorits paths are relative and _strip_protocolleaves the/onNo export reading a Doc, Sheet or Slide deck fails with 403 fileNotDownloadablea Google-native file stores no bytes; it only ever calls alt=media, neverfiles.exportThe third is why
gdrive.pycan turn a Google Sheet into a DataFrame at all: Google Drive exports Sheets as CSV, and the filesystem falls back tofiles.exportwhen a file has no binary content. One consequence worth knowing — a listing carries Google Drive's ownsize(the stored content), while a read returns the longer export.fs.info(path)["size"]is reconciled with what a read returns;fs.ls(..., detail=True)is not, because reconciling a listing would mean exporting every native file in it just to measure. -
GitHub (
github.py): a repo's file tree as a filesystem, over the Contents and Git Trees APIs.GithubFileSystemnamesapi.github.comin six places and only two — the class attributesurlandcontent_url— can be rebound; the other four are inline f-strings inside__init__,repos,tagsandbranches, sogithub_filesystem_atis a subclass that replaces those methods rather than a patcher like everything else inbacklot.integrations. Missing even one would leave a "mock" run quietly reading the real GitHub, which is why a test asserts that no URL the filesystem requests namesgithub.com. It also swaps HTTP Basic (what GitHub's own clients send) for the bearer scheme Backlot answers.A seventh host does not show up in that count of six, because the client does not build it: a file whose bytes open with git-LFS's pointer marker makes upstream's
_openabandon the contents response and fetchdownload_url, which Backlot reports — faithfully — as the realraw.githubusercontent.com._openis replaced too. Backlot has no LFS and no >1MB spill, so the contents response always carries the bytes and there is nothing to fall through to.Two caveats:
fs.branchesandfs.tagsare pointed at Backlot but Backlot serves no/branchesor/tagslisting yet — only/branches/{branch}— so they 404 rather than reaching GitHub (#92). And walking a repo works only becausegit/trees/{ref}resolves a subtree sha: a client descends by the sha it read from the parent listing, and answering the repo root for every ref makesls("src")reportsrc/srcandsrc/configand a walk recurse until it runs out of stack. -
Everything else Backlot serves — Slack, Gmail, Notion, Jira, Confluence, Linear, HubSpot, Fireflies — has no fsspec implementation at all, from anyone. They are not filesystem-shaped, and fsspec's registry has no entry for them. Read those through their own SDKs (
examples/using-official-sdk/) or LlamaIndex (examples/using-llamaindex-readers/).
fsspec has a FUSE bridge (fsspec.fuse), but if you want Backlot as a directory you can ls and
grep from any process, examples/using-mirage/ already does it better: a
--fuse flag on every script, six sources rather than two, and a single mountpoint that serves all
of them at once. This directory is about the interface the data stack reads through, not the
kernel mount.