refactor(metadata): finish wiring invoke formatter to pydantic union#216
Merged
refactor(metadata): finish wiring invoke formatter to pydantic union#216
Conversation
…uctured parsing via pydantic
…lstein/PhotoMapAI into lstein/feature/refactor-invoke-metadata
The invoke metadata refactor left `invoke_formatter.py` pointing at classes that no longer existed, so opening the drawer on an InvokeAI-generated image would raise ImportError. This change completes the wiring and locks in the behavior with regression tests. - Add `InvokeMetadataView`, a version-agnostic facade over the `GenerationMetadata2/3/5` discriminated union, so the formatter doesn't sprinkle `isinstance` checks across extraction logic. - Rewrite `invoke_formatter.py` as a thin HTML renderer on top of the view, preserving the existing drawer table layout. - Move `_normalize_ref_images` out of `GenerationMetadataAdapter.parse` and into `GenerationMetadata5` as a `@model_validator(mode="before")`, where it belongs. - Re-enable `metadata_modules/__init__.py` re-exports that had been commented out during the refactor. - Delete the now-unused `invoke/invoke_metadata_abc.py`. - Drawer HTML tweaks: suppress empty negative-prompt row; keep positive prompt row but drop copy icon when empty; per-column suppression in tuple tables; fall back to `1.0` when a surviving weight column has gaps; surface Flux Redux `imageInfluence` (e.g. "Medium") in the weight column when no numeric weight is present. - Add 33 regression tests in `tests/backend/test_invoke_metadata.py` covering view-level extraction and end-to-end HTML rendering for v2/v3/v5 (both `ref_images` and `canvas_v2_metadata` paths). - Run ruff across `invoke/` to modernize `typing.Optional`/`Union`/ `List`/`Dict` to PEP 604 / PEP 585 forms. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
invoke_formatter.pyto the newGenerationMetadata2/3/5discriminated union via a newInvokeMetadataViewfacade (the formatter was previously importing classes that no longer existed, so opening the drawer on any InvokeAI-generated image raisedImportError).1.0fallback for gaps) and surfaces Flux ReduximageInfluence(e.g. "Medium") in the weight column when no numeric weight is present.ref_imagesandcanvas_v2_metadatapaths), plus Flux Redux, mixed weights, ref_images normalization, and empty-field edge cases.What changed
Pydantic union plumbing
photomap/backend/metadata_modules/invoke/invoke_metadata_view.py— version-agnostic facade that exposespositive_prompt,negative_prompt,model_name,seed,loras,reference_images,control_layers,raster_images. Allisinstance-dispatch lives here; the formatter stays ignorant of which v2/v3/v5 shape it's looking at.invoke_formatter.pyrewritten as a thin HTML renderer over the view, preserving the existing drawer table layout. Falls back to<i>Unknown invoke metadata format.</i>on PydanticValidationError._normalize_ref_imagesmoved out ofGenerationMetadataAdapter.parseand ontoGenerationMetadata5as a@model_validator(mode="before")(addresses a# MOVE THIS CODETODO).metadata_modules/__init__.pyre-exports (SlideSummary,format_exif_metadata,format_invoke_metadata) re-enabled — they had been commented out during the refactor, breakingmetadata_formatting.py.invoke/invoke_metadata_abc.py— dead code, not imported anywhere underphotomap/.Drawer HTML tweaks
1.0(InvokeAI's effective default).IPAdapter.image_influence/RefImageConfig.image_influence(values like "Medium") is displayed in the weight column when no numeric weight is available.Modernization
ruff check photomap/backend/metadata_modules/invoke/ --fixswept 227typing.Optional/Union/List/Dictusages to PEP 604 / PEP 585 forms (X | None,list[T],dict[K, V]), plus one manualisinstance(x, (int, float))→isinstance(x, int | float)fix.Docs
CLAUDE.mdwith orientation for future Claude Code sessions (architecture, commands, metadata subsystem layout).Test plan
pytest tests/backend— 82 passing (including 33 new tests intest_invoke_metadata.py)ruff check photomap/backend/metadata_modules/invoke/— cleanruff checkon all newly-authored / modified files — cleanref_imagesand canvas) InvokeAI-generated image and confirm the rendered table matches what the pre-refactor formatter producedimageInfluencevalue (e.g. "Medium")🤖 Generated with Claude Code