-
Notifications
You must be signed in to change notification settings - Fork 0
Open
Labels
Description
Summary
Add a Rows result type as an alternative to returning raw lists of model instances from DB execution methods (.all(), .first(), etc.). Rows would behave like a list but provide extra conveniences for post-query manipulation. Ferro would return Rows by default, with configuration to opt out globally or per method.
Current behavior
All DB execution methods (e.g. .all(), .first()) return a list of the corresponding data models.
Proposed behavior
- Rows – A list-like type returned by default from execution methods, with additional helpers:
Rows.filter(func: Callable[(X), bool]) -> Self– Filter in-memory by predicateusers.filter(lambda x: x.archived == false)
Rows.select(*fields) -> dict- Select specific fields. Returns a list if selecting a single field, dict otherwise.users.select("id", "email")
Rows.get(field: str) -> Self– Lookup by index or key (e.g. by id)users.get(email="admin@ferro.com")
Rows.sort(key: Callable[(X), Any], reverse: bool = False) -> Self– Sort in-memory by key/attributeusers.sort(key = lambda x: x.order)
Rows.to_pandas() -> pd.DataFrame- Convert database data to a pandas dataframeusers.to_pandas() # Raises exception if pandas is not installed
Rows.to_polars() -> pl.DataFrame- Convert database data to a polars dataframeusers.to_polars() # Raises exception if polars is not installed
- (and similar conveniences as needed)
Rows should feel like a list (iterable, indexable, len(), etc.) so existing code that expects a list continues to work, while new code can use the extra methods.
Configuration
- Global: Configure Ferro to return plain lists instead of Rows (e.g. for projects that want minimal API surface).
- Per method: Allow opting into Rows or plain list on a per-call basis (e.g.
.all(return_rows=False)or.all(return_type="list")), so callers can choose per query.
Acceptance criteria (draft)
-
Rowstype is list-like (iterable, indexable,len(), sliceable). - Rows supports
.filter,.map,.get,.sort(and any other agreed conveniences). - Execution methods return Rows by default.
- Global config to default to plain list instead of Rows.
- Per-method override to request list or Rows.
- Documentation and tests for Rows API and configuration.
Notes
- Naming and exact method set (filter/map/get/sort vs. others) can be refined during design.
- Consider whether
.first()returns a single model vs. a Rows of length 0 or 1 for consistency.
Reactions are currently unavailable