feat(file_browser): restore selection_mode='all' and accept list form#9630
Conversation
Re-introduces the 'all' string and adds a list form (e.g. ['file','directory'])
to mo.ui.file_browser, normalized internally to a frozenset of selectable
kinds. The wire format stays a single string ('file' | 'directory' | 'all'),
so the frontend is unchanged. Default remains 'file'.
Closes #9402
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
|
@kirangadhave I have started the AI code review. It will take a few minutes to complete. |
There was a problem hiding this comment.
No issues found across 3 files
Architecture diagram
sequenceDiagram
participant User as User (Python cell)
participant FileBrowser as mo.ui.file_browser __init__
participant Normalizer as _normalize_selection_mode()
participant WireFormat as Wire format builder
participant Frontend as Frontend component
participant DirLister as _list_directory()
participant FileSystem as Filesystem
Note over User,FileSystem: Initialization flow
User->>FileBrowser: file_browser(selection_mode="all")
FileBrowser->>Normalizer: NEW: normalize "all"
Normalizer-->>FileBrowser: frozenset({"file","directory"})
User->>FileBrowser: file_browser(selection_mode=["file","directory"])
FileBrowser->>Normalizer: NEW: normalize list
Normalizer-->>FileBrowser: frozenset({"file","directory"})
User->>FileBrowser: file_browser(selection_mode="file") (unchanged)
FileBrowser->>Normalizer: normalize "file"
Normalizer-->>FileBrowser: frozenset({"file"})
Note over FileBrowser,WireFormat: Derive wire format for frontend
alt selection_mode == {"file","directory"} (i.e. "all")
FileBrowser->>WireFormat: wire = "all"
else single kind selected
FileBrowser->>WireFormat: wire = single element from frozenset
end
WireFormat-->>FileBrowser: "all" | "file" | "directory"
FileBrowser-->>User: UIElement created (unchanged frontend contract)
Note over Frontend,FileSystem: Directory listing flow (CHANGED: filtering logic)
Frontend->>DirLister: list_directory(path)
DirLister->>FileSystem: read directory entries
FileSystem-->>DirLister: list of entries (files + directories)
loop each entry
alt entry is directory
DirLister->>DirLister: Always included (for navigation)
else entry is file
alt "file" in self._selection_mode
DirLister->>DirLister: Include (subject to filetypes)
else "file" not in self._selection_mode
DirLister->>DirLister: NEW: Skip file (was only directory mode previously)
end
end
end
DirLister-->>Frontend: filtered file list
There was a problem hiding this comment.
Pull request overview
Restores mo.ui.file_browser(selection_mode="all") support (regressed previously) and extends selection_mode to also accept a list/tuple form, while keeping the frontend wire format limited to "file" | "directory" | "all".
Changes:
- Added internal normalization of
selection_modeto afrozensetof selectable kinds, supporting"all"and list/tuple inputs. - Updated directory listing behavior to hide files when file selection is disabled, while always showing directories for navigation.
- Added/updated tests and an example demonstrating
selection_mode="all".
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 2 comments.
| File | Description |
|---|---|
marimo/_plugins/ui/_impl/file_browser.py |
Adds selection mode normalization + wire-format mapping and updates listing behavior accordingly. |
tests/_plugins/ui/_impl/test_file_browser.py |
Updates existing assertions and adds coverage for normalization, "all" mode, and list/tuple inputs. |
examples/ui/file_browser.py |
Demonstrates a file browser instance using selection_mode="all". |
| selection_mode (str | Sequence[str], optional): Which kinds of entries | ||
| the user can select. Accepts one of "file" (default), "directory", | ||
| "all", or a list/tuple containing "file" and/or "directory". | ||
| "all" is equivalent to ["file", "directory"]. Defaults to "file". |
There was a problem hiding this comment.
doesn't this mean ["file", "directory"] is the same as "all". What's the reason to have both list & str support?
There was a problem hiding this comment.
yeah it's same as all. If we add something like symlinks or some other type in future, we can pick and choose with this pattern. all will always be all supported types. just a bit of over-engineering for future proofing.
There was a problem hiding this comment.
got it, im usually not keen on over-eng, but leaving it to you.
Summary
selection_mode="all"string onmo.ui.file_browser(regressed in fix: handle cloudpath client #4130).selection_mode=["file", "directory"].frozensetof selectable kinds; the wire format stays a single string ("file" | "directory" | "all"), so the frontend (which already handles"all") is unchanged."file"; no behavior change for existing callers.Closes #9402