End of Week 2 — you have reads, filters, groupers, and try/except. Time to combine them into the first real deliverable: a digest dict with two lists, one per source. What shape would make this dict most useful to a caller rendering a daily brief?
Two named keys — "emails" and "events" — each holding a list of strings? That way the template can loop through each section independently.
Exactly that. Two comprehensions, each reading its own API, each producing a flat list of strings. The dict wraps them under named keys:
email_list = [m.get("snippet", "") for m in emails.get("messages", [])]
event_list = [e.get("summary", "") for e in events.get("items", [])]And the caller gets digest["emails"] and digest["events"] as separate lists — no interleaving, no prefixes, just the raw strings?
Raw lists keep the digest flexible. The caller can render, filter, or merge however they want — you don't decide the final UX inside the function:
def build_digest(max_emails: int, max_events: int) -> dict:
emails = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": max_emails})
events = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"query": ""})
email_list = [m.get("snippet", "") for m in emails.get("messages", [])]
event_list = [e.get("summary", "") for e in events.get("items", [])]
return {"emails": email_list, "events": event_list}Should I also add counts? A digest could carry the numbers alongside the lists — {"emails": [...], "email_count": N, ...}?
Counts are derivable from len(digest["emails"]), so adding them duplicates state. Store the source of truth — the list — and let the caller compute the count. Cleaner contract, no drift between list length and stored count.
So this dict is the shape every downstream tool sees — an email template reads the two lists, a dashboard renders them side-by-side, a logger writes them to a file — all without touching the API code again?
One function, two lists, one dict. Every Week 3 lesson writes to a new place — Sheets, Docs, Gmail — but the reader shape is what you just built. That's the whole analytic foundation.
TL;DR: A dict with two named lists — one per source — keeps the reader API simple.
[m.get(...)] and [e.get(...)]{"emails": [...], "events": [...]}| Shape | Problem |
|---|---|
| List + explicit count | Two places to update; can drift |
| Just the list | Caller calls len() when needed |
| Count only | Lossy — can't render items |
Store the source of truth once; derive everything else on demand. Duplicate state is how bugs sneak into reports.
End of Week 2 — you have reads, filters, groupers, and try/except. Time to combine them into the first real deliverable: a digest dict with two lists, one per source. What shape would make this dict most useful to a caller rendering a daily brief?
Two named keys — "emails" and "events" — each holding a list of strings? That way the template can loop through each section independently.
Exactly that. Two comprehensions, each reading its own API, each producing a flat list of strings. The dict wraps them under named keys:
email_list = [m.get("snippet", "") for m in emails.get("messages", [])]
event_list = [e.get("summary", "") for e in events.get("items", [])]And the caller gets digest["emails"] and digest["events"] as separate lists — no interleaving, no prefixes, just the raw strings?
Raw lists keep the digest flexible. The caller can render, filter, or merge however they want — you don't decide the final UX inside the function:
def build_digest(max_emails: int, max_events: int) -> dict:
emails = toolset.execute_action(Action.GMAIL_FETCH_EMAILS, {"max_results": max_emails})
events = toolset.execute_action(Action.GOOGLECALENDAR_FIND_EVENT, {"query": ""})
email_list = [m.get("snippet", "") for m in emails.get("messages", [])]
event_list = [e.get("summary", "") for e in events.get("items", [])]
return {"emails": email_list, "events": event_list}Should I also add counts? A digest could carry the numbers alongside the lists — {"emails": [...], "email_count": N, ...}?
Counts are derivable from len(digest["emails"]), so adding them duplicates state. Store the source of truth — the list — and let the caller compute the count. Cleaner contract, no drift between list length and stored count.
So this dict is the shape every downstream tool sees — an email template reads the two lists, a dashboard renders them side-by-side, a logger writes them to a file — all without touching the API code again?
One function, two lists, one dict. Every Week 3 lesson writes to a new place — Sheets, Docs, Gmail — but the reader shape is what you just built. That's the whole analytic foundation.
TL;DR: A dict with two named lists — one per source — keeps the reader API simple.
[m.get(...)] and [e.get(...)]{"emails": [...], "events": [...]}| Shape | Problem |
|---|---|
| List + explicit count | Two places to update; can drift |
| Just the list | Caller calls len() when needed |
| Count only | Lossy — can't render items |
Store the source of truth once; derive everything else on demand. Duplicate state is how bugs sneak into reports.
Create a free account to get started. Paid plans unlock all tracks.