Skip to content

fix(genbi): normalise null apps/schema_version in app index#2406

Merged
goldmedal merged 3 commits into
Canner:mainfrom
Bartok9:fix/genbi-index-null-apps
Jun 29, 2026
Merged

fix(genbi): normalise null apps/schema_version in app index#2406
goldmedal merged 3 commits into
Canner:mainfrom
Bartok9:fix/genbi-index-null-apps

Conversation

@Bartok9

@Bartok9 Bartok9 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Summary

  • load_index normalised a missing apps key with data.setdefault("apps", {}), but setdefault is a no-op when the key already exists.
  • An apps.yml with an explicit-but-empty apps: (a hand-edit or a truncated write) is valid YAML that parses to {"apps": None} — the key is present, so setdefault leaves None in place. Every accessor (get_app, register_app, remove_app, update_app) then crashes with an opaque AttributeError: 'NoneType' object has no attribute 'get'.

This defeats the whole point of MalformedIndexError, which exists precisely so a bad index file fails clearly instead of crashing deep in a command.

Reproduction

# .wren/apps.yml:
#   schema_version: 1
#   apps:
load_index(project)["apps"]   # -> None
get_app(project, "foo")       # -> AttributeError: 'NoneType' object has no attribute 'get'

Fix

Normalise null values with or instead of setdefault, so an explicit null apps: / schema_version: is coerced to its default. Also raise MalformedIndexError (not a later opaque crash) when apps is present but is a non-mapping (e.g. a list).

Real behavior proof

Real environment: Python 3.12, core/wren via uv run --no-sync, repo main.

Commands:

uv run --no-sync pytest tests/unit/test_genbi_index.py -q
uv run --no-sync pytest tests/unit -q

AFTER fix:

13 passed                      # test_genbi_index.py
779 passed, 42 skipped         # full unit suite

BEFORE fix (new tests stashed onto unpatched index.py):

3 failed, 10 passed
FAILED test_load_index_normalises_null_apps
FAILED test_load_index_normalises_null_schema_version
FAILED test_load_index_raises_on_non_mapping_apps

Tests

tests/unit/test_genbi_index.py gains coverage for null apps, null schema_version, and a non-mapping apps (raises MalformedIndexError). The null-apps test fails without the fix.

Scope / risk

Apache-2.0 path (core/wren). Only changes index normalisation; well-formed index files behave identically (covered by the existing 10 index tests).

Summary by CodeRabbit

  • Bug Fixes
    • Improved normalization of incomplete index data, safely handling explicit null top-level fields.
    • Added clearer error reporting when the apps field isn’t a mapping, preventing downstream crashes.
    • Ensured schema version defaults apply for null/absent values while preserving explicit 0.
  • Tests
    • Added unit tests covering null/empty apps, null schema_version, invalid (non-mapping) apps, and preservation of schema_version: 0.

load_index used data.setdefault('apps', {}), which is a no-op when the key
already exists. An apps.yml written with an explicit but empty 'apps:'
(hand-edit or truncated write) parses to {'apps': None}, so the key was
present and setdefault left None in place — then get_app/register_app/etc.
crashed with an opaque AttributeError, defeating MalformedIndexError's
purpose. Normalise null apps/schema_version with 'or', and raise
MalformedIndexError when apps is a non-mapping.
@github-actions github-actions Bot added python Pull requests that update Python code core labels Jun 28, 2026
@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: f50b6ad9-56e5-48f8-9fe5-46f3c62922a8

📥 Commits

Reviewing files that changed from the base of the PR and between 345b0ff and 75007cb.

📒 Files selected for processing (2)
  • core/wren/src/wren/genbi/index.py
  • core/wren/tests/unit/test_genbi_index.py
🚧 Files skipped from review as they are similar to previous changes (1)
  • core/wren/src/wren/genbi/index.py

Walkthrough

load_index() now normalizes explicit null values for schema_version and apps, validates that apps is a mapping, and raises MalformedIndexError for non-mapping apps values. Unit tests cover null apps, null schema_version, invalid apps, and preserving schema_version: 0.

Changes

Null-safe normalization and validation in load_index

Layer / File(s) Summary
Null normalization and mapping validation in load_index
core/wren/src/wren/genbi/index.py
load_index sets default values only when schema_version or apps are explicitly null or missing, then checks that apps is a mapping before assigning it and raising MalformedIndexError if not.
Index normalization and validation tests
core/wren/tests/unit/test_genbi_index.py
Tests cover null apps, null schema_version, non-mapping apps, and preserving an explicit schema_version of 0.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~5 minutes

Poem

🐇 I hopped through the index with a cheerful thump,
Null fields got cozy, no crash and no bump.
A list for apps now gets shown the door,
And schema_version: 0 stays just as before.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly describes the main change: normalizing null apps and schema_version values in the app index.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@core/wren/src/wren/genbi/index.py`:
- Around line 58-65: The normalization in the index loading logic is too broad
because `or` in `index.py` converts any falsy `schema_version` or `apps` value
instead of only handling `None`. Update the `data["schema_version"]` and `apps`
handling in the same block to preserve valid falsy values like `0`, `false`,
`[]`, and `""`, while still defaulting only when the value is actually `None`;
keep the existing `MalformedIndexError` check in place for `apps` so non-mapping
inputs continue to fail in the `INDEX_SCHEMA_VERSION` / `apps` normalization
path.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: cf3d22ec-9de7-45f4-8658-294ff6f81449

📥 Commits

Reviewing files that changed from the base of the PR and between 89ea46c and 345b0ff.

📒 Files selected for processing (2)
  • core/wren/src/wren/genbi/index.py
  • core/wren/tests/unit/test_genbi_index.py

Comment thread core/wren/src/wren/genbi/index.py Outdated
Per review: check 'is None' rather than truthiness so valid falsy values
(0, False, []) are preserved and surfaced for validation instead of being
silently coerced to a default. Add a test for falsy schema_version (0).
@Bartok9

Bartok9 commented Jun 28, 2026

Copy link
Copy Markdown
Contributor Author

Good catch, @coderabbitai — fixed in 75007cb. Switched both fields from or to an explicit is None check so valid falsy values (0, False, [], "") are preserved and surfaced for validation rather than silently coerced to a default. The non-mapping apps guard is unchanged. Added test_load_index_preserves_falsy_schema_version (schema_version: 0). Full file: 14 passed.

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown
Contributor

Tip

For best results, initiate chat on the files or code changes.

@Bartok9 Thanks — that fix looks right. Using an explicit is None check here is the safer behavior since it preserves legitimate falsy values for downstream validation instead of silently normalizing them. Appreciate the added regression test as well.

૮₍ ˶ᵔ ᵕ ᵔ˶ ₎ა


If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@goldmedal

Copy link
Copy Markdown
Collaborator

@Bartok9, please check the CI fails. Thanks.

@Bartok9

Bartok9 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

Thanks @goldmedal — looked into it. The unit tests failure isn't from this PR's change; it's a transient network error in the Rust build step:

error: failed to get `jiff` as a dependency of package `env_logger v0.11.10`
  download of ji/ff/jiff failed
  curl failed
  [56] OpenSSL SSL_read: unexpected eof while reading

crates.io dropped the connection mid-download while building wren-core-py. My change is pure-Python in the genbi app index and the actual test suites that touch it pass (test_genbi_index.py 14 passed, full unit suite green locally). I've pushed an empty commit to re-trigger the run. If it flakes again it's purely a crates.io fetch hiccup on the runner, not a code issue — happy to rebase if you'd prefer.

@Bartok9

Bartok9 commented Jun 29, 2026

Copy link
Copy Markdown
Contributor Author

@goldmedal CI is green now ✅ — all checks pass (unit, postgres, mysql, memory, ui tests, lint, CodeRabbit). The earlier failure has cleared on the latest run. Ready for review whenever you have a moment. Thanks! 🙏

@goldmedal goldmedal left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Thanks @Bartok9 👍

@goldmedal goldmedal merged commit 0c031d6 into Canner:main Jun 29, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

core python Pull requests that update Python code

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants