fix(salary): treat null metadata/categories as absent instead of crashing (#413)

--validate treats an explicit "metadata": null / "categories": null the same
as an omitted key ("...must be an object when provided", None is skipped), but
format_entry read both through dict.get(key, {}), which only substitutes the
default for an *absent* key - a present-but-null value passed through. The
renderer then hit None.get("index_label", ...) (AttributeError) or, via the
numeric-field fallback, None[key] = value (TypeError), so a hand-maintained
salary_data.json using null for "no value" died with an uncaught traceback
right after printing "Found 1 match(es)".

format_entry now coerces both to {} up front, honouring the validator's
existing "when provided" contract at the single consumer that broke it.

Tests (all verified to fail on the unfixed renderer):
- two unit cases calling format_entry with null metadata / null categories
- two end-to-end cases running main() --validate (blesses the file) then the
  lookup path (renders it), one per null shape

Plus an [Unreleased] CHANGELOG entry.

Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
soumyadip sarkar
2026-09-01 21:35:59 +02:00
committed by GitHub
co-authored by Claude Sonnet 5
parent 6ef295bf7b
commit 9833a5dcb7
3 changed files with 112 additions and 2 deletions
+7 -2
View File
@@ -291,6 +291,11 @@ def search_company(data, query, city=None):
def format_entry(entry, metadata):
"""Format a single company entry for display."""
# `metadata` and `entry["categories"]` may be an explicit null: --validate
# treats a null the same as an omitted key ("...must be an object when
# provided"), but dict.get(key, default) only substitutes the default for an
# absent key, so a null reached `.get()`/`[]` here and crashed the lookup.
metadata = metadata or {}
lines = []
lines.append(f"\n{'='*60}")
lines.append(f" {entry['company']}")
@@ -298,8 +303,8 @@ def format_entry(entry, metadata):
lines.append(f" Location: {entry['city']}")
lines.append(f"{'='*60}")
# Get category data (everything except company/city fields)
categories = entry.get("categories", {})
# Get category data (everything except company/city fields).
categories = entry.get("categories") or {}
if not categories:
# Fallback: treat any numeric fields as categories
skip_keys = {"company", "city", "categories"}