tango-python 1.3.0__py3-none-any.whl → 1.5.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- tango/__init__.py +1 -1
- tango/client.py +59 -1
- tango/models.py +93 -1
- tango/shapes/generated_overlay.py +603 -45
- {tango_python-1.3.0.dist-info → tango_python-1.5.0.dist-info}/METADATA +30 -2
- {tango_python-1.3.0.dist-info → tango_python-1.5.0.dist-info}/RECORD +9 -9
- {tango_python-1.3.0.dist-info → tango_python-1.5.0.dist-info}/WHEEL +0 -0
- {tango_python-1.3.0.dist-info → tango_python-1.5.0.dist-info}/entry_points.txt +0 -0
- {tango_python-1.3.0.dist-info → tango_python-1.5.0.dist-info}/licenses/LICENSE +0 -0
tango/__init__.py
CHANGED
tango/client.py
CHANGED
|
@@ -491,6 +491,7 @@ class TangoClient:
|
|
|
491
491
|
for ag in (self._parse_agency(agency) for agency in data["results"])
|
|
492
492
|
if ag is not None
|
|
493
493
|
],
|
|
494
|
+
meta=data.get("meta"),
|
|
494
495
|
)
|
|
495
496
|
|
|
496
497
|
def get_agency(self, code: str) -> Agency:
|
|
@@ -521,6 +522,7 @@ class TangoClient:
|
|
|
521
522
|
next=data.get("next"),
|
|
522
523
|
previous=data.get("previous"),
|
|
523
524
|
results=data.get("results", []),
|
|
525
|
+
meta=data.get("meta"),
|
|
524
526
|
)
|
|
525
527
|
|
|
526
528
|
def get_office(self, code: str) -> dict[str, Any]:
|
|
@@ -573,6 +575,7 @@ class TangoClient:
|
|
|
573
575
|
next=data.get("next"),
|
|
574
576
|
previous=data.get("previous"),
|
|
575
577
|
results=results,
|
|
578
|
+
meta=data.get("meta"),
|
|
576
579
|
)
|
|
577
580
|
|
|
578
581
|
def get_organization(
|
|
@@ -785,6 +788,7 @@ class TangoClient:
|
|
|
785
788
|
previous=data.get("previous"),
|
|
786
789
|
results=results,
|
|
787
790
|
cursor=data.get("cursor"),
|
|
791
|
+
meta=data.get("meta"),
|
|
788
792
|
)
|
|
789
793
|
|
|
790
794
|
def get_contract(
|
|
@@ -846,6 +850,7 @@ class TangoClient:
|
|
|
846
850
|
previous=data.get("previous"),
|
|
847
851
|
results=results,
|
|
848
852
|
cursor=data.get("cursor"),
|
|
853
|
+
meta=data.get("meta"),
|
|
849
854
|
)
|
|
850
855
|
|
|
851
856
|
def get_contract_transactions(
|
|
@@ -868,6 +873,7 @@ class TangoClient:
|
|
|
868
873
|
previous=data.get("previous"),
|
|
869
874
|
results=data.get("results") or [],
|
|
870
875
|
cursor=data.get("cursor"),
|
|
876
|
+
meta=data.get("meta"),
|
|
871
877
|
)
|
|
872
878
|
|
|
873
879
|
# ============================================================================
|
|
@@ -971,6 +977,7 @@ class TangoClient:
|
|
|
971
977
|
previous=data.get("previous"),
|
|
972
978
|
results=results,
|
|
973
979
|
page_metadata=data.get("page_metadata"),
|
|
980
|
+
meta=data.get("meta"),
|
|
974
981
|
)
|
|
975
982
|
|
|
976
983
|
def get_idv(
|
|
@@ -1072,6 +1079,7 @@ class TangoClient:
|
|
|
1072
1079
|
previous=data.get("previous"),
|
|
1073
1080
|
results=results,
|
|
1074
1081
|
page_metadata=data.get("page_metadata"),
|
|
1082
|
+
meta=data.get("meta"),
|
|
1075
1083
|
)
|
|
1076
1084
|
|
|
1077
1085
|
def list_idv_child_idvs(
|
|
@@ -1116,6 +1124,7 @@ class TangoClient:
|
|
|
1116
1124
|
previous=data.get("previous"),
|
|
1117
1125
|
results=results,
|
|
1118
1126
|
page_metadata=data.get("page_metadata"),
|
|
1127
|
+
meta=data.get("meta"),
|
|
1119
1128
|
)
|
|
1120
1129
|
|
|
1121
1130
|
def list_idv_transactions(
|
|
@@ -1132,6 +1141,7 @@ class TangoClient:
|
|
|
1132
1141
|
previous=data.get("previous"),
|
|
1133
1142
|
results=data.get("results") or [],
|
|
1134
1143
|
page_metadata=data.get("page_metadata"),
|
|
1144
|
+
meta=data.get("meta"),
|
|
1135
1145
|
)
|
|
1136
1146
|
|
|
1137
1147
|
def list_otas(
|
|
@@ -1214,6 +1224,7 @@ class TangoClient:
|
|
|
1214
1224
|
results=results,
|
|
1215
1225
|
cursor=data.get("cursor"),
|
|
1216
1226
|
page_metadata=data.get("page_metadata"),
|
|
1227
|
+
meta=data.get("meta"),
|
|
1217
1228
|
)
|
|
1218
1229
|
|
|
1219
1230
|
def get_ota(
|
|
@@ -1319,6 +1330,7 @@ class TangoClient:
|
|
|
1319
1330
|
results=results,
|
|
1320
1331
|
cursor=data.get("cursor"),
|
|
1321
1332
|
page_metadata=data.get("page_metadata"),
|
|
1333
|
+
meta=data.get("meta"),
|
|
1322
1334
|
)
|
|
1323
1335
|
|
|
1324
1336
|
def get_otidv(
|
|
@@ -1395,6 +1407,7 @@ class TangoClient:
|
|
|
1395
1407
|
results=results,
|
|
1396
1408
|
cursor=data.get("cursor"),
|
|
1397
1409
|
page_metadata=data.get("page_metadata"),
|
|
1410
|
+
meta=data.get("meta"),
|
|
1398
1411
|
)
|
|
1399
1412
|
|
|
1400
1413
|
def list_subawards(
|
|
@@ -1449,6 +1462,7 @@ class TangoClient:
|
|
|
1449
1462
|
next=data.get("next"),
|
|
1450
1463
|
previous=data.get("previous"),
|
|
1451
1464
|
results=results,
|
|
1465
|
+
meta=data.get("meta"),
|
|
1452
1466
|
)
|
|
1453
1467
|
|
|
1454
1468
|
def get_subaward(
|
|
@@ -1533,6 +1547,7 @@ class TangoClient:
|
|
|
1533
1547
|
next=data.get("next"),
|
|
1534
1548
|
previous=data.get("previous"),
|
|
1535
1549
|
results=results,
|
|
1550
|
+
meta=data.get("meta"),
|
|
1536
1551
|
)
|
|
1537
1552
|
|
|
1538
1553
|
def get_gsa_elibrary_contract(
|
|
@@ -1639,6 +1654,7 @@ class TangoClient:
|
|
|
1639
1654
|
next=data.get("next"),
|
|
1640
1655
|
previous=data.get("previous"),
|
|
1641
1656
|
results=results,
|
|
1657
|
+
meta=data.get("meta"),
|
|
1642
1658
|
)
|
|
1643
1659
|
|
|
1644
1660
|
def get_itdashboard_investment(
|
|
@@ -1808,6 +1824,7 @@ class TangoClient:
|
|
|
1808
1824
|
next=data.get("next"),
|
|
1809
1825
|
previous=data.get("previous"),
|
|
1810
1826
|
results=results,
|
|
1827
|
+
meta=data.get("meta"),
|
|
1811
1828
|
)
|
|
1812
1829
|
|
|
1813
1830
|
def get_vehicle(
|
|
@@ -1889,6 +1906,7 @@ class TangoClient:
|
|
|
1889
1906
|
next=data.get("next"),
|
|
1890
1907
|
previous=data.get("previous"),
|
|
1891
1908
|
results=results,
|
|
1909
|
+
meta=data.get("meta"),
|
|
1892
1910
|
)
|
|
1893
1911
|
|
|
1894
1912
|
def list_vehicle_orders(
|
|
@@ -1937,6 +1955,7 @@ class TangoClient:
|
|
|
1937
1955
|
next=data.get("next"),
|
|
1938
1956
|
previous=data.get("previous"),
|
|
1939
1957
|
results=results,
|
|
1958
|
+
meta=data.get("meta"),
|
|
1940
1959
|
)
|
|
1941
1960
|
|
|
1942
1961
|
# Business Types endpoints
|
|
@@ -1971,6 +1990,7 @@ class TangoClient:
|
|
|
1971
1990
|
next=data.get("next"),
|
|
1972
1991
|
previous=data.get("previous"),
|
|
1973
1992
|
results=results,
|
|
1993
|
+
meta=data.get("meta"),
|
|
1974
1994
|
)
|
|
1975
1995
|
|
|
1976
1996
|
def list_naics(
|
|
@@ -2022,6 +2042,7 @@ class TangoClient:
|
|
|
2022
2042
|
next=data.get("next"),
|
|
2023
2043
|
previous=data.get("previous"),
|
|
2024
2044
|
results=data.get("results", []),
|
|
2045
|
+
meta=data.get("meta"),
|
|
2025
2046
|
)
|
|
2026
2047
|
|
|
2027
2048
|
# Entity endpoints
|
|
@@ -2108,6 +2129,7 @@ class TangoClient:
|
|
|
2108
2129
|
next=data.get("next"),
|
|
2109
2130
|
previous=data.get("previous"),
|
|
2110
2131
|
results=results,
|
|
2132
|
+
meta=data.get("meta"),
|
|
2111
2133
|
)
|
|
2112
2134
|
|
|
2113
2135
|
def get_entity(
|
|
@@ -2164,6 +2186,7 @@ class TangoClient:
|
|
|
2164
2186
|
next=data.get("next"),
|
|
2165
2187
|
previous=data.get("previous"),
|
|
2166
2188
|
results=list(data.get("results") or []),
|
|
2189
|
+
meta=data.get("meta"),
|
|
2167
2190
|
)
|
|
2168
2191
|
|
|
2169
2192
|
# Forecast endpoints
|
|
@@ -2256,6 +2279,7 @@ class TangoClient:
|
|
|
2256
2279
|
next=data.get("next"),
|
|
2257
2280
|
previous=data.get("previous"),
|
|
2258
2281
|
results=results,
|
|
2282
|
+
meta=data.get("meta"),
|
|
2259
2283
|
)
|
|
2260
2284
|
|
|
2261
2285
|
def get_forecast(
|
|
@@ -2379,6 +2403,7 @@ class TangoClient:
|
|
|
2379
2403
|
next=data.get("next"),
|
|
2380
2404
|
previous=data.get("previous"),
|
|
2381
2405
|
results=results,
|
|
2406
|
+
meta=data.get("meta"),
|
|
2382
2407
|
)
|
|
2383
2408
|
|
|
2384
2409
|
def get_opportunity(
|
|
@@ -2493,6 +2518,7 @@ class TangoClient:
|
|
|
2493
2518
|
next=data.get("next"),
|
|
2494
2519
|
previous=data.get("previous"),
|
|
2495
2520
|
results=results,
|
|
2521
|
+
meta=data.get("meta"),
|
|
2496
2522
|
)
|
|
2497
2523
|
|
|
2498
2524
|
def get_notice(
|
|
@@ -2540,6 +2566,7 @@ class TangoClient:
|
|
|
2540
2566
|
filed_date_before: str | None = None,
|
|
2541
2567
|
decision_date_after: str | None = None,
|
|
2542
2568
|
decision_date_before: str | None = None,
|
|
2569
|
+
naics_code: str | None = None,
|
|
2543
2570
|
search: str | None = None,
|
|
2544
2571
|
) -> PaginatedResponse:
|
|
2545
2572
|
"""
|
|
@@ -2569,6 +2596,7 @@ class TangoClient:
|
|
|
2569
2596
|
filed_date_before: Filed date on or before
|
|
2570
2597
|
decision_date_after: Decision date on or after
|
|
2571
2598
|
decision_date_before: Decision date on or before
|
|
2599
|
+
naics_code: Filter by the solicitation's NAICS code (e.g. 541519)
|
|
2572
2600
|
search: Full-text search over protest searchable fields
|
|
2573
2601
|
"""
|
|
2574
2602
|
params: dict[str, Any] = {"page": page, "limit": min(limit, 100)}
|
|
@@ -2594,6 +2622,7 @@ class TangoClient:
|
|
|
2594
2622
|
("filed_date_before", filed_date_before),
|
|
2595
2623
|
("decision_date_after", decision_date_after),
|
|
2596
2624
|
("decision_date_before", decision_date_before),
|
|
2625
|
+
("naics_code", naics_code),
|
|
2597
2626
|
("search", search),
|
|
2598
2627
|
):
|
|
2599
2628
|
if val is not None:
|
|
@@ -2611,6 +2640,7 @@ class TangoClient:
|
|
|
2611
2640
|
next=data.get("next"),
|
|
2612
2641
|
previous=data.get("previous"),
|
|
2613
2642
|
results=results,
|
|
2643
|
+
meta=data.get("meta"),
|
|
2614
2644
|
)
|
|
2615
2645
|
|
|
2616
2646
|
def get_protest(
|
|
@@ -2747,6 +2777,7 @@ class TangoClient:
|
|
|
2747
2777
|
next=data.get("next"),
|
|
2748
2778
|
previous=data.get("previous"),
|
|
2749
2779
|
results=results,
|
|
2780
|
+
meta=data.get("meta"),
|
|
2750
2781
|
)
|
|
2751
2782
|
|
|
2752
2783
|
def get_dibbs_rfq(
|
|
@@ -2866,6 +2897,7 @@ class TangoClient:
|
|
|
2866
2897
|
next=data.get("next"),
|
|
2867
2898
|
previous=data.get("previous"),
|
|
2868
2899
|
results=results,
|
|
2900
|
+
meta=data.get("meta"),
|
|
2869
2901
|
)
|
|
2870
2902
|
|
|
2871
2903
|
def get_dibbs_rfp(
|
|
@@ -3003,6 +3035,7 @@ class TangoClient:
|
|
|
3003
3035
|
next=data.get("next"),
|
|
3004
3036
|
previous=data.get("previous"),
|
|
3005
3037
|
results=results,
|
|
3038
|
+
meta=data.get("meta"),
|
|
3006
3039
|
)
|
|
3007
3040
|
|
|
3008
3041
|
def get_dibbs_award(
|
|
@@ -3148,6 +3181,7 @@ class TangoClient:
|
|
|
3148
3181
|
next=data.get("next"),
|
|
3149
3182
|
previous=data.get("previous"),
|
|
3150
3183
|
results=results,
|
|
3184
|
+
meta=data.get("meta"),
|
|
3151
3185
|
)
|
|
3152
3186
|
|
|
3153
3187
|
def get_exclusion(
|
|
@@ -3275,6 +3309,7 @@ class TangoClient:
|
|
|
3275
3309
|
next=data.get("next"),
|
|
3276
3310
|
previous=data.get("previous"),
|
|
3277
3311
|
results=results,
|
|
3312
|
+
meta=data.get("meta"),
|
|
3278
3313
|
)
|
|
3279
3314
|
|
|
3280
3315
|
def get_sbir_topic(
|
|
@@ -3395,6 +3430,7 @@ class TangoClient:
|
|
|
3395
3430
|
next=data.get("next"),
|
|
3396
3431
|
previous=data.get("previous"),
|
|
3397
3432
|
results=results,
|
|
3433
|
+
meta=data.get("meta"),
|
|
3398
3434
|
)
|
|
3399
3435
|
|
|
3400
3436
|
def get_sbir_solicitation(
|
|
@@ -3769,6 +3805,7 @@ class TangoClient:
|
|
|
3769
3805
|
next=data.get("next"),
|
|
3770
3806
|
previous=data.get("previous"),
|
|
3771
3807
|
results=results,
|
|
3808
|
+
meta=data.get("meta"),
|
|
3772
3809
|
)
|
|
3773
3810
|
|
|
3774
3811
|
def get_budget_account(
|
|
@@ -3820,6 +3857,7 @@ class TangoClient:
|
|
|
3820
3857
|
next=data.get("next"),
|
|
3821
3858
|
previous=data.get("previous"),
|
|
3822
3859
|
results=data.get("results") or [],
|
|
3860
|
+
meta=data.get("meta"),
|
|
3823
3861
|
)
|
|
3824
3862
|
|
|
3825
3863
|
def get_budget_account_recipients(
|
|
@@ -3847,6 +3885,7 @@ class TangoClient:
|
|
|
3847
3885
|
next=data.get("next"),
|
|
3848
3886
|
previous=data.get("previous"),
|
|
3849
3887
|
results=data.get("results") or [],
|
|
3888
|
+
meta=data.get("meta"),
|
|
3850
3889
|
)
|
|
3851
3890
|
|
|
3852
3891
|
# Grant endpoints
|
|
@@ -3940,6 +3979,7 @@ class TangoClient:
|
|
|
3940
3979
|
next=data.get("next"),
|
|
3941
3980
|
previous=data.get("previous"),
|
|
3942
3981
|
results=results,
|
|
3982
|
+
meta=data.get("meta"),
|
|
3943
3983
|
)
|
|
3944
3984
|
|
|
3945
3985
|
def get_grant(
|
|
@@ -4032,6 +4072,7 @@ class TangoClient:
|
|
|
4032
4072
|
next=data.get("next"),
|
|
4033
4073
|
previous=data.get("previous"),
|
|
4034
4074
|
results=results,
|
|
4075
|
+
meta=data.get("meta"),
|
|
4035
4076
|
)
|
|
4036
4077
|
|
|
4037
4078
|
def create_webhook_endpoint(
|
|
@@ -4216,6 +4257,7 @@ class TangoClient:
|
|
|
4216
4257
|
next=data.get("next"),
|
|
4217
4258
|
previous=data.get("previous"),
|
|
4218
4259
|
results=results,
|
|
4260
|
+
meta=data.get("meta"),
|
|
4219
4261
|
)
|
|
4220
4262
|
|
|
4221
4263
|
def get_webhook_alert(self, alert_id: str) -> WebhookAlert:
|
|
@@ -4430,6 +4472,7 @@ class TangoClient:
|
|
|
4430
4472
|
next=data.get("next"),
|
|
4431
4473
|
previous=data.get("previous"),
|
|
4432
4474
|
results=list(data.get("results") or []),
|
|
4475
|
+
meta=data.get("meta"),
|
|
4433
4476
|
)
|
|
4434
4477
|
|
|
4435
4478
|
def get_department(self, code: str) -> dict[str, Any]:
|
|
@@ -4445,8 +4488,13 @@ class TangoClient:
|
|
|
4445
4488
|
shape: str | None = None,
|
|
4446
4489
|
flat: bool = False,
|
|
4447
4490
|
flat_lists: bool = False,
|
|
4491
|
+
has_awards: bool | None = None,
|
|
4448
4492
|
) -> PaginatedResponse[dict[str, Any]]:
|
|
4449
|
-
"""List Product Service Codes (`/api/psc/`).
|
|
4493
|
+
"""List Product Service Codes (`/api/psc/`).
|
|
4494
|
+
|
|
4495
|
+
Args:
|
|
4496
|
+
has_awards: When True, return only codes with contract award history.
|
|
4497
|
+
"""
|
|
4450
4498
|
params: dict[str, Any] = {"page": page, "limit": min(limit, 100)}
|
|
4451
4499
|
if shape:
|
|
4452
4500
|
params["shape"] = shape
|
|
@@ -4454,12 +4502,15 @@ class TangoClient:
|
|
|
4454
4502
|
params["flat"] = "true"
|
|
4455
4503
|
if flat_lists:
|
|
4456
4504
|
params["flat_lists"] = "true"
|
|
4505
|
+
if has_awards is not None:
|
|
4506
|
+
params["has_awards"] = "true" if has_awards else "false"
|
|
4457
4507
|
data = self._get("/api/psc/", params)
|
|
4458
4508
|
return PaginatedResponse(
|
|
4459
4509
|
count=int(data.get("count", 0)),
|
|
4460
4510
|
next=data.get("next"),
|
|
4461
4511
|
previous=data.get("previous"),
|
|
4462
4512
|
results=list(data.get("results") or []),
|
|
4513
|
+
meta=data.get("meta"),
|
|
4463
4514
|
)
|
|
4464
4515
|
|
|
4465
4516
|
def get_psc(
|
|
@@ -4560,6 +4611,7 @@ class TangoClient:
|
|
|
4560
4611
|
next=data.get("next"),
|
|
4561
4612
|
previous=data.get("previous"),
|
|
4562
4613
|
results=list(data.get("results") or []),
|
|
4614
|
+
meta=data.get("meta"),
|
|
4563
4615
|
)
|
|
4564
4616
|
|
|
4565
4617
|
def get_assistance_listing(
|
|
@@ -4606,6 +4658,7 @@ class TangoClient:
|
|
|
4606
4658
|
next=data.get("next"),
|
|
4607
4659
|
previous=data.get("previous"),
|
|
4608
4660
|
results=list(data.get("results") or []),
|
|
4661
|
+
meta=data.get("meta"),
|
|
4609
4662
|
)
|
|
4610
4663
|
|
|
4611
4664
|
def get_mas_sin(
|
|
@@ -4675,6 +4728,7 @@ class TangoClient:
|
|
|
4675
4728
|
results=results,
|
|
4676
4729
|
cursor=data.get("cursor"),
|
|
4677
4730
|
page_metadata=data.get("page_metadata"),
|
|
4731
|
+
meta=data.get("meta"),
|
|
4678
4732
|
)
|
|
4679
4733
|
|
|
4680
4734
|
def list_entity_contracts(
|
|
@@ -4850,6 +4904,7 @@ class TangoClient:
|
|
|
4850
4904
|
next=data.get("next"),
|
|
4851
4905
|
previous=data.get("previous"),
|
|
4852
4906
|
results=results,
|
|
4907
|
+
meta=data.get("meta"),
|
|
4853
4908
|
)
|
|
4854
4909
|
|
|
4855
4910
|
def list_entity_lcats(
|
|
@@ -4880,6 +4935,7 @@ class TangoClient:
|
|
|
4880
4935
|
next=data.get("next"),
|
|
4881
4936
|
previous=data.get("previous"),
|
|
4882
4937
|
results=list(data.get("results") or []),
|
|
4938
|
+
meta=data.get("meta"),
|
|
4883
4939
|
)
|
|
4884
4940
|
|
|
4885
4941
|
def get_entity_metrics(self, uei: str, months: int, period_grouping: str) -> dict[str, Any]:
|
|
@@ -4920,6 +4976,7 @@ class TangoClient:
|
|
|
4920
4976
|
next=data.get("next"),
|
|
4921
4977
|
previous=data.get("previous"),
|
|
4922
4978
|
results=list(data.get("results") or []),
|
|
4979
|
+
meta=data.get("meta"),
|
|
4923
4980
|
)
|
|
4924
4981
|
|
|
4925
4982
|
# ============================================================================
|
|
@@ -4977,6 +5034,7 @@ class TangoClient:
|
|
|
4977
5034
|
results=results,
|
|
4978
5035
|
cursor=data.get("cursor"),
|
|
4979
5036
|
page_metadata=data.get("page_metadata"),
|
|
5037
|
+
meta=data.get("meta"),
|
|
4980
5038
|
)
|
|
4981
5039
|
|
|
4982
5040
|
def list_agency_awarding_contracts(
|
tango/models.py
CHANGED
|
@@ -1044,7 +1044,15 @@ class PaginatedResponse[T]:
|
|
|
1044
1044
|
previous: URL for the previous page of results (None if first page)
|
|
1045
1045
|
results: List of result items (type depends on shape parameter)
|
|
1046
1046
|
cursor: Cursor token for cursor-based pagination (None if not available)
|
|
1047
|
-
|
|
1047
|
+
meta: Response-level metadata the API attached to this page, when present.
|
|
1048
|
+
Currently carries agency-filter diagnostics: ``resolved_filters`` maps
|
|
1049
|
+
each agency filter to the organizations its ``|``-separated tokens
|
|
1050
|
+
resolved to (or ``None``), and ``warnings`` lists human-readable notes
|
|
1051
|
+
about tokens that were dropped or matched loosely. See
|
|
1052
|
+
:meth:`agency_warnings` and :meth:`unresolved_agency_tokens`.
|
|
1053
|
+
page_metadata: Always ``None`` — the API has never emitted a
|
|
1054
|
+
``page_metadata`` key. Retained so existing attribute access keeps
|
|
1055
|
+
working; use ``meta`` instead.
|
|
1048
1056
|
|
|
1049
1057
|
Examples:
|
|
1050
1058
|
>>> from tango import TangoClient, ShapeConfig
|
|
@@ -1063,8 +1071,92 @@ class PaginatedResponse[T]:
|
|
|
1063
1071
|
previous: str | None
|
|
1064
1072
|
results: list[T]
|
|
1065
1073
|
cursor: str | None = None
|
|
1074
|
+
meta: dict[str, Any] | None = None
|
|
1066
1075
|
page_metadata: dict[str, Any] | None = None
|
|
1067
1076
|
|
|
1077
|
+
@property
|
|
1078
|
+
def agency_warnings(self) -> list[str]:
|
|
1079
|
+
"""Warnings the API raised about agency filters on this request.
|
|
1080
|
+
|
|
1081
|
+
Empty when every supplied agency token resolved cleanly. A non-empty list
|
|
1082
|
+
means part of the filter did not apply, so a small or empty ``results`` is
|
|
1083
|
+
not evidence that no such records exist.
|
|
1084
|
+
|
|
1085
|
+
Examples:
|
|
1086
|
+
>>> response = client.list_contracts(awarding_agency="GSA|NOTANAGENCY")
|
|
1087
|
+
>>> for warning in response.agency_warnings:
|
|
1088
|
+
... print(warning)
|
|
1089
|
+
Agency filter 'awarding_agency': 'NOTANAGENCY' did not match any organization and was ignored.
|
|
1090
|
+
"""
|
|
1091
|
+
if not self.meta:
|
|
1092
|
+
return []
|
|
1093
|
+
warnings = self.meta.get("warnings")
|
|
1094
|
+
return list(warnings) if isinstance(warnings, list) else []
|
|
1095
|
+
|
|
1096
|
+
@property
|
|
1097
|
+
def unresolved_agency_tokens(self) -> dict[str, list[str]]:
|
|
1098
|
+
"""Agency tokens that matched no organization, keyed by filter name.
|
|
1099
|
+
|
|
1100
|
+
Empty when everything resolved. Use this to fail loudly in a pipeline
|
|
1101
|
+
rather than treating a silently-narrowed result set as an answer.
|
|
1102
|
+
|
|
1103
|
+
Examples:
|
|
1104
|
+
>>> response = client.list_contracts(awarding_agency="GSA|NOTANAGENCY")
|
|
1105
|
+
>>> response.unresolved_agency_tokens
|
|
1106
|
+
{'awarding_agency': ['NOTANAGENCY']}
|
|
1107
|
+
"""
|
|
1108
|
+
if not self.meta:
|
|
1109
|
+
return {}
|
|
1110
|
+
resolved = self.meta.get("resolved_filters")
|
|
1111
|
+
if not isinstance(resolved, dict):
|
|
1112
|
+
return {}
|
|
1113
|
+
dropped: dict[str, list[str]] = {}
|
|
1114
|
+
for filter_name, entries in resolved.items():
|
|
1115
|
+
if not isinstance(entries, list):
|
|
1116
|
+
continue
|
|
1117
|
+
tokens = [
|
|
1118
|
+
entry["token"]
|
|
1119
|
+
for entry in entries
|
|
1120
|
+
if isinstance(entry, dict)
|
|
1121
|
+
and entry.get("resolved") is None
|
|
1122
|
+
and entry.get("token") is not None
|
|
1123
|
+
]
|
|
1124
|
+
if tokens:
|
|
1125
|
+
dropped[filter_name] = tokens
|
|
1126
|
+
return dropped
|
|
1127
|
+
|
|
1128
|
+
@property
|
|
1129
|
+
def resolved_agencies(self) -> dict[str, list[dict[str, Any]]]:
|
|
1130
|
+
"""What each agency token actually resolved to, keyed by filter name.
|
|
1131
|
+
|
|
1132
|
+
Agency resolution is fuzzy, so a token can match an organization the caller
|
|
1133
|
+
did not intend and scope the query to that subtree instead. Checking the
|
|
1134
|
+
resolved ``name`` is the only way to catch that from the client side — an
|
|
1135
|
+
unresolved-token check cannot, because nothing was dropped.
|
|
1136
|
+
|
|
1137
|
+
Examples:
|
|
1138
|
+
>>> response = client.list_contracts(awarding_agency="HUD")
|
|
1139
|
+
>>> [org["name"] for org in response.resolved_agencies["awarding_agency"]]
|
|
1140
|
+
['Department of Housing and Urban Development']
|
|
1141
|
+
"""
|
|
1142
|
+
if not self.meta:
|
|
1143
|
+
return {}
|
|
1144
|
+
resolved = self.meta.get("resolved_filters")
|
|
1145
|
+
if not isinstance(resolved, dict):
|
|
1146
|
+
return {}
|
|
1147
|
+
matched: dict[str, list[dict[str, Any]]] = {}
|
|
1148
|
+
for filter_name, entries in resolved.items():
|
|
1149
|
+
if not isinstance(entries, list):
|
|
1150
|
+
continue
|
|
1151
|
+
orgs = [
|
|
1152
|
+
entry["resolved"]
|
|
1153
|
+
for entry in entries
|
|
1154
|
+
if isinstance(entry, dict) and isinstance(entry.get("resolved"), dict)
|
|
1155
|
+
]
|
|
1156
|
+
if orgs:
|
|
1157
|
+
matched[filter_name] = orgs
|
|
1158
|
+
return matched
|
|
1159
|
+
|
|
1068
1160
|
|
|
1069
1161
|
class ShapeConfig:
|
|
1070
1162
|
"""Predefined response shape configurations used as defaults for API methods
|