Skip to content

Refactor get_metadata to return None when create=False#49

Merged
AlanRockefeller merged 2 commits intomainfrom
test
Mar 12, 2026
Merged

Refactor get_metadata to return None when create=False#49
AlanRockefeller merged 2 commits intomainfrom
test

Conversation

@AlanRockefeller
Copy link
Copy Markdown
Owner

@AlanRockefeller AlanRockefeller commented Mar 12, 2026

Previously, SidecarManager.get_metadata(..., create=False) returned a blank EntryMetadata object if no entry existed. This obscured the difference between "no metadata exists" and "empty metadata exists."

This commit updates the API to return None when a requested sidecar entry is missing and create=False.

Changes:

  • Added @overload type hints to Youtube to strictly type the return value based on the create boolean.
  • Updated all read-only metadata lookups in AppController to safely and explicitly handle None values.
  • Updated side_effect mocks in tests to accept **kwargs.

Summary by CodeRabbit

  • Bug Fixes

    • Improved stability when image metadata is missing: the app now safely handles absent sidecar data and uses sensible defaults to avoid crashes and UI errors.
    • Fixed edge cases around uploaded/stacked/favorite/todo flags and their dates for more consistent behavior.
  • Tests

    • Updated tests to tolerate additional mock parameters, making metadata-related tests more robust.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 12, 2026

Warning

Rate limit exceeded

@AlanRockefeller has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 19 minutes and 29 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: a325f785-f12c-42f8-b6bd-b232e06b495a

📥 Commits

Reviewing files that changed from the base of the PR and between de42838 and 4700ea6.

📒 Files selected for processing (1)
  • ChangeLog.md

Walkthrough

Sidecar metadata handling was made defensive: SidecarManager.get_metadata() now can return None (with typed overloads), and callers in faststack/app.py were updated to handle missing metadata by returning safe defaults; tests adjusted mock signatures to accept extra kwargs.

Changes

Cohort / File(s) Summary
Metadata Handling Robustness
faststack/app.py
Added guards for meta possibly being None across functions (jump_to_last_uploaded, _get_metadata_dict, get_current_metadata, add_favorites_to_batch, add_uploaded_to_batch, is_stacked, and other dict constructions). Return safe defaults (False for booleans, empty string for date fields) to avoid AttributeError.
Sidecar Manager Type Safety
faststack/io/sidecar.py
Introduced Literal, Optional, and overload imports and three @overload signatures for get_metadata(). Implementation updated so get_metadata(..., create=False) can return None; default behavior still creates metadata when create=True. Docstring updated.
Test Mock Signature Update
faststack/tests/test_jump_to_last_uploaded.py
Updated two mocked side_effect functions to accept **kwargs (signature def side_effect(stem, **kwargs)) so mocks tolerate extra keyword args passed to get_metadata.

Sequence Diagram(s)

(omitted)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The PR title clearly and concisely describes the main change: refactoring get_metadata to return None when create=False, which is the primary modification across the changeset.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch test
📝 Coding Plan for PR comments
  • Generate coding plan

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Previously, get_metadata with create=False returned a blank
EntryMetadata object if no entry existed. This obscured the
difference between missing metadata and empty metadata.

This commit updates the API to return None when a requested sidecar
entry is missing and create=False.

Changes:
- Added overload type hints to get_metadata for strict return typing.
- Updated read-only metadata lookups in AppController to handle None.
- Updated side_effect mocks in tests to accept keyword arguments.
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
faststack/app.py (1)

2118-2133: Consider centralizing the default metadata shape.

The fallback flag/date values are now duplicated across _get_metadata_dict() and get_current_metadata(). A small shared helper would make future metadata fields less likely to drift between grid and loupe views.

Also applies to: 2384-2394

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@faststack/app.py` around lines 2118 - 2133, Create a single source of truth
for the default metadata shape and replace the duplicated literal dicts in
_get_metadata_dict() and get_current_metadata() (and the other occurrence
referenced around the second block) with a call or reference to that helper;
e.g., add a constant or function like DEFAULT_METADATA_DICT() or
get_default_metadata() that returns the default flag/date values, then have
_get_metadata_dict() and get_current_metadata() return that default when meta is
None and map meta fields from it when present so both views stay in sync.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@faststack/tests/test_jump_to_last_uploaded.py`:
- Around line 69-70: The test double function side_effect used for get_metadata
must honor the create flag: update the side_effect(s) in
test_jump_to_last_uploaded.py (the mock used for get_metadata) to check
kwargs.get("create", True) and return EntryMetadata() only when create is True
and the stem is unknown; if create is False and the stem is not in
{"img1","img2","img3"} return None so the test exercises the missing-stem path
(apply same change to the other occurrence around lines 140-141).

---

Nitpick comments:
In `@faststack/app.py`:
- Around line 2118-2133: Create a single source of truth for the default
metadata shape and replace the duplicated literal dicts in _get_metadata_dict()
and get_current_metadata() (and the other occurrence referenced around the
second block) with a call or reference to that helper; e.g., add a constant or
function like DEFAULT_METADATA_DICT() or get_default_metadata() that returns the
default flag/date values, then have _get_metadata_dict() and
get_current_metadata() return that default when meta is None and map meta fields
from it when present so both views stay in sync.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 2cb9fd8e-77d5-4d76-b40d-b5a6b7bbdc91

📥 Commits

Reviewing files that changed from the base of the PR and between b0a3a2e and e80b2f6.

📒 Files selected for processing (3)
  • faststack/app.py
  • faststack/io/sidecar.py
  • faststack/tests/test_jump_to_last_uploaded.py

Comment on lines +69 to 70
def side_effect(stem, **kwargs):
return {"img1": meta1, "img2": meta2, "img3": meta3}.get(stem, EntryMetadata())
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟡 Minor

Honor create=False in these get_metadata test doubles.

These mocks still fall back to EntryMetadata() for unknown stems, which preserves the old contract and can hide the regression this PR is meant to catch. If jump_to_last_uploaded() looks up a missing stem with create=False, this test would never exercise the new None path.

Suggested fix
-    def side_effect(stem, **kwargs):
-        return {"img1": meta1, "img2": meta2, "img3": meta3}.get(stem, EntryMetadata())
+    def side_effect(stem, **kwargs):
+        metadata = {"img1": meta1, "img2": meta2, "img3": meta3}
+        if stem in metadata:
+            return metadata[stem]
+        return EntryMetadata() if kwargs.get("create", True) else None

Also applies to: 140-141

🧰 Tools
🪛 Ruff (0.15.5)

[warning] 69-69: Unused function argument: kwargs

(ARG001)

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@faststack/tests/test_jump_to_last_uploaded.py` around lines 69 - 70, The test
double function side_effect used for get_metadata must honor the create flag:
update the side_effect(s) in test_jump_to_last_uploaded.py (the mock used for
get_metadata) to check kwargs.get("create", True) and return EntryMetadata()
only when create is True and the stem is unknown; if create is False and the
stem is not in {"img1","img2","img3"} return None so the test exercises the
missing-stem path (apply same change to the other occurrence around lines
140-141).

@AlanRockefeller AlanRockefeller merged commit 5df197c into main Mar 12, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant