Skip to content

Commit 01e1e79

Browse files
vdavezclaude
andcommitted
fix(shapes): register ContractOrIDVCompetition nested schema alias
CONTRACT_SCHEMA/IDV_SCHEMA reference the competition leaf as "ContractOrIDVCompetition" but only "Competition" was registered in EXPLICIT_SCHEMAS, so competition(extent_competed,...) nested selections on contract/IDV shapes raised ShapeValidationError. Register the name as an alias of COMPETITION_SCHEMA. Fixes tango-python#29 item 1. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
1 parent 0ffc550 commit 01e1e79

3 files changed

Lines changed: 27 additions & 0 deletions

File tree

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
2222
- `list_contracts`: no longer sends `page=1` to the cursor-only `/api/contracts/`
2323
endpoint. When no cursor is supplied, neither `page` nor `cursor` is sent and
2424
the API returns the first page by default.
25+
- Shape validation: registered the `ContractOrIDVCompetition` nested schema
26+
(alias of `Competition`) so nested selections like
27+
`competition(extent_competed,number_of_offers_received)` on contract / IDV
28+
shapes validate instead of raising `ShapeValidationError`.
2529

2630
### Added
2731
- Budget accounts surface (tango v4.6.8): `list_budget_accounts`,

tango/shapes/explicit_schemas.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1487,6 +1487,10 @@
14871487
"Location": LOCATION_SCHEMA,
14881488
"PlaceOfPerformance": PLACE_OF_PERFORMANCE_SCHEMA,
14891489
"Competition": COMPETITION_SCHEMA,
1490+
# Alias: CONTRACT_SCHEMA/IDV_SCHEMA reference the competition leaf as
1491+
# "ContractOrIDVCompetition" (the models.py dataclass name); it is the same
1492+
# field set as Competition. Register both so nested shape selection resolves.
1493+
"ContractOrIDVCompetition": COMPETITION_SCHEMA,
14901494
"ParentAward": PARENT_AWARD_SCHEMA,
14911495
"LegislativeMandates": LEGISLATIVE_MANDATES_SCHEMA,
14921496
"SubawardsSummary": SUBAWARDS_SUMMARY_SCHEMA,

tests/test_shapes.py

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -926,6 +926,25 @@ def test_validate_field_suggestions(self):
926926
assert "nam" in error_msg
927927
assert "Did you mean" in error_msg or "name" in error_msg
928928

929+
def test_competition_nested_shape_on_contract(self):
930+
"""Regression (tango-python#29 item 1): CONTRACT_SCHEMA/IDV_SCHEMA
931+
reference the competition leaf as ``ContractOrIDVCompetition``, which
932+
must be registered in EXPLICIT_SCHEMAS so nested field selection like
933+
``competition(extent_competed,...)`` validates instead of raising
934+
ShapeValidationError."""
935+
from tango.shapes.explicit_schemas import EXPLICIT_SCHEMAS
936+
937+
assert "ContractOrIDVCompetition" in EXPLICIT_SCHEMAS
938+
assert "extent_competed" in EXPLICIT_SCHEMAS["ContractOrIDVCompetition"]
939+
940+
parser = ShapeParser()
941+
spec = parser.parse(
942+
"key,piid,competition(extent_competed,number_of_offers_received)"
943+
)
944+
# Must not raise — resolves the competition leaf via the alias.
945+
parser.validate(spec, "Contract")
946+
parser.validate(spec, "IDV")
947+
929948

930949
class TestBuiltinModelsRegistration:
931950
"""Test registration of built-in Tango models"""

0 commit comments

Comments
 (0)