Add per-site recipe config helper#4792
Conversation
263e6df to
407f75b
Compare
There was a problem hiding this comment.
Pull request overview
This PR introduces a public helper for attaching site-keyed (per-site) configuration to a Recipe, adds a base Recipe.configured_sites() API with helper-precedence and legacy fallback, and documents the intended usage/limitations.
Changes:
- Added
set_per_site_config(recipe, config)helper and exported it fromnvflare.recipe. - Added
Recipe.set_per_site_config(),_apply_per_site_config()hook, andRecipe.configured_sites()with helper-over-legacy precedence. - Added unit tests and user-guide documentation for the new per-site configuration helper.
Reviewed changes
Copilot reviewed 6 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
nvflare/recipe/utils.py |
Adds helper + shape validation for per-site config before applying to a recipe. |
nvflare/recipe/spec.py |
Adds base recipe APIs for storing helper config, applying it via hook, and reporting configured sites. |
nvflare/recipe/__init__.py |
Exposes set_per_site_config from the top-level nvflare.recipe package. |
tests/unit_test/recipe/utils_test.py |
Verifies the new helper is importable from nvflare.recipe. |
tests/unit_test/recipe/spec_test.py |
Adds behavioral tests for helper storage, hook invocation, precedence, and validation. |
docs/user_guide/data_scientist_guide/job_recipe.rst |
Documents per-site configuration, configured_sites(), and recipe-specific semantics. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Greptile SummaryThis PR adds a
Confidence Score: 5/5Safe to merge. The change is purely additive and touches only the recipe helper layer with no impact on existing job generation or execution paths. All new code is strictly additive. Mutation isolation is correctly handled with a second shallow copy passed to the hook, and a regression test confirms hook key-deletions cannot corrupt stored state. The validation covers all three bad-shape cases and is tested for each. The legacy fallback uses getattr with a None default, making it safe for existing subclasses. No files require special attention. Important Files Changed
Sequence DiagramsequenceDiagram
participant User
participant set_per_site_config as set_per_site_config (utils)
participant Recipe
participant Hook as _apply_per_site_config (subclass)
User->>set_per_site_config: set_per_site_config(recipe, config)
set_per_site_config->>set_per_site_config: _validate_per_site_config_shape(config)
Note right of set_per_site_config: Checks top-level keys are str,<br/>values are dict -- raises TypeError otherwise
set_per_site_config->>Recipe: recipe.set_per_site_config(validated_config)
Recipe->>Recipe: "_helper_per_site_config = dict(config)"
Recipe->>Hook: _apply_per_site_config(dict(_helper_per_site_config))
Hook-->>Recipe: may mutate its own copy safely
User->>Recipe: recipe.configured_sites()
alt helper config set
Recipe-->>User: list(_helper_per_site_config.keys())
else legacy per_site_config exists
Recipe-->>User: list(per_site_config.keys())
else
Recipe-->>User: []
end
Reviews (3): Last reviewed commit: "Add per-site recipe config helper" | Re-trigger Greptile |
407f75b to
55a3274
Compare
55a3274 to
110c546
Compare
Summary
set_per_site_config(recipe, config)and export it fromnvflare.recipeRecipe.configured_sites()with helper-config precedence and legacyper_site_configfallbackTests
python3 -m pytest tests/unit_test/recipe/spec_test.py tests/unit_test/recipe/utils_test.py -q./runtest.sh -s