tango-python 1.12.0__py3-none-any.whl → 1.14.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 CHANGED
@@ -62,7 +62,7 @@ from .webhooks import (
62
62
  )
63
63
  from .webhooks.receiver import Delivery, WebhookReceiver
64
64
 
65
- __version__ = "1.12.0"
65
+ __version__ = "1.14.0"
66
66
  __all__ = [
67
67
  "TangoClient",
68
68
  "TangoAPIError",
tango/client.py CHANGED
@@ -71,6 +71,9 @@ from tango.shapes import (
71
71
  build_parser_registry_from_client,
72
72
  )
73
73
 
74
+ # Where `_request` stores a list response's `X-Results-CountType` header so each `PaginatedResponse` reads its own, not the shared `last_response_headers`.
75
+ _COUNT_TYPE_KEY = "_tango_count_type"
76
+
74
77
 
75
78
  class TangoClient:
76
79
  """Tango API Client"""
@@ -180,7 +183,11 @@ class TangoClient:
180
183
 
181
184
  self._raise_for_status(response)
182
185
 
183
- return response.json() if response.content else {}
186
+ data = response.json() if response.content else {}
187
+ count_type = response.headers.get("X-Results-CountType")
188
+ if isinstance(count_type, str) and isinstance(data, dict) and "count" in data:
189
+ data[_COUNT_TYPE_KEY] = count_type.lower()
190
+ return data
184
191
 
185
192
  except httpx.HTTPError as e:
186
193
  raise TangoAPIError(f"Request failed: {str(e)}") from e
@@ -495,6 +502,7 @@ class TangoClient:
495
502
  return PaginatedResponse(
496
503
  count=data["count"],
497
504
  next=data.get("next"),
505
+ count_type=data.get(_COUNT_TYPE_KEY),
498
506
  previous=data.get("previous"),
499
507
  results=[
500
508
  ag
@@ -530,6 +538,7 @@ class TangoClient:
530
538
  return PaginatedResponse(
531
539
  count=data.get("count", 0),
532
540
  next=data.get("next"),
541
+ count_type=data.get(_COUNT_TYPE_KEY),
533
542
  previous=data.get("previous"),
534
543
  results=data.get("results", []),
535
544
  meta=data.get("meta"),
@@ -583,6 +592,7 @@ class TangoClient:
583
592
  return PaginatedResponse(
584
593
  count=data.get("count", 0),
585
594
  next=data.get("next"),
595
+ count_type=data.get(_COUNT_TYPE_KEY),
586
596
  previous=data.get("previous"),
587
597
  results=results,
588
598
  meta=data.get("meta"),
@@ -795,6 +805,7 @@ class TangoClient:
795
805
  return PaginatedResponse(
796
806
  count=data["count"],
797
807
  next=data.get("next"),
808
+ count_type=data.get(_COUNT_TYPE_KEY),
798
809
  previous=data.get("previous"),
799
810
  results=results,
800
811
  cursor=data.get("cursor"),
@@ -857,6 +868,7 @@ class TangoClient:
857
868
  return PaginatedResponse(
858
869
  count=int(data.get("count") or len(results)),
859
870
  next=data.get("next"),
871
+ count_type=data.get(_COUNT_TYPE_KEY),
860
872
  previous=data.get("previous"),
861
873
  results=results,
862
874
  cursor=data.get("cursor"),
@@ -880,6 +892,7 @@ class TangoClient:
880
892
  return PaginatedResponse(
881
893
  count=int(data.get("count") or len(data.get("results") or [])),
882
894
  next=data.get("next"),
895
+ count_type=data.get(_COUNT_TYPE_KEY),
883
896
  previous=data.get("previous"),
884
897
  results=data.get("results") or [],
885
898
  cursor=data.get("cursor"),
@@ -984,6 +997,7 @@ class TangoClient:
984
997
  return PaginatedResponse(
985
998
  count=int(data.get("count") or len(results)),
986
999
  next=data.get("next"),
1000
+ count_type=data.get(_COUNT_TYPE_KEY),
987
1001
  previous=data.get("previous"),
988
1002
  results=results,
989
1003
  cursor=data.get("cursor"),
@@ -1087,6 +1101,7 @@ class TangoClient:
1087
1101
  return PaginatedResponse(
1088
1102
  count=int(data.get("count") or len(results)),
1089
1103
  next=data.get("next"),
1104
+ count_type=data.get(_COUNT_TYPE_KEY),
1090
1105
  previous=data.get("previous"),
1091
1106
  results=results,
1092
1107
  cursor=data.get("cursor"),
@@ -1133,6 +1148,7 @@ class TangoClient:
1133
1148
  return PaginatedResponse(
1134
1149
  count=int(data.get("count") or len(results)),
1135
1150
  next=data.get("next"),
1151
+ count_type=data.get(_COUNT_TYPE_KEY),
1136
1152
  previous=data.get("previous"),
1137
1153
  results=results,
1138
1154
  cursor=data.get("cursor"),
@@ -1151,6 +1167,7 @@ class TangoClient:
1151
1167
  return PaginatedResponse(
1152
1168
  count=int(data.get("count") or len(data.get("results") or [])),
1153
1169
  next=data.get("next"),
1170
+ count_type=data.get(_COUNT_TYPE_KEY),
1154
1171
  previous=data.get("previous"),
1155
1172
  results=data.get("results") or [],
1156
1173
  cursor=data.get("cursor"),
@@ -1234,6 +1251,7 @@ class TangoClient:
1234
1251
  return PaginatedResponse(
1235
1252
  count=int(data.get("count") or len(results)),
1236
1253
  next=data.get("next"),
1254
+ count_type=data.get(_COUNT_TYPE_KEY),
1237
1255
  previous=data.get("previous"),
1238
1256
  results=results,
1239
1257
  cursor=data.get("cursor"),
@@ -1340,6 +1358,7 @@ class TangoClient:
1340
1358
  return PaginatedResponse(
1341
1359
  count=int(data.get("count") or len(results)),
1342
1360
  next=data.get("next"),
1361
+ count_type=data.get(_COUNT_TYPE_KEY),
1343
1362
  previous=data.get("previous"),
1344
1363
  results=results,
1345
1364
  cursor=data.get("cursor"),
@@ -1417,6 +1436,7 @@ class TangoClient:
1417
1436
  return PaginatedResponse(
1418
1437
  count=int(data.get("count") or len(results)),
1419
1438
  next=data.get("next"),
1439
+ count_type=data.get(_COUNT_TYPE_KEY),
1420
1440
  previous=data.get("previous"),
1421
1441
  results=results,
1422
1442
  cursor=data.get("cursor"),
@@ -1474,6 +1494,7 @@ class TangoClient:
1474
1494
  return PaginatedResponse(
1475
1495
  count=data.get("count", 0),
1476
1496
  next=data.get("next"),
1497
+ count_type=data.get(_COUNT_TYPE_KEY),
1477
1498
  previous=data.get("previous"),
1478
1499
  results=results,
1479
1500
  meta=data.get("meta"),
@@ -1559,6 +1580,7 @@ class TangoClient:
1559
1580
  return PaginatedResponse(
1560
1581
  count=data.get("count", 0),
1561
1582
  next=data.get("next"),
1583
+ count_type=data.get(_COUNT_TYPE_KEY),
1562
1584
  previous=data.get("previous"),
1563
1585
  results=results,
1564
1586
  meta=data.get("meta"),
@@ -1671,6 +1693,7 @@ class TangoClient:
1671
1693
  return PaginatedResponse(
1672
1694
  count=data.get("count", 0),
1673
1695
  next=data.get("next"),
1696
+ count_type=data.get(_COUNT_TYPE_KEY),
1674
1697
  previous=data.get("previous"),
1675
1698
  results=results,
1676
1699
  meta=data.get("meta"),
@@ -1841,6 +1864,7 @@ class TangoClient:
1841
1864
  return PaginatedResponse(
1842
1865
  count=data["count"],
1843
1866
  next=data.get("next"),
1867
+ count_type=data.get(_COUNT_TYPE_KEY),
1844
1868
  previous=data.get("previous"),
1845
1869
  results=results,
1846
1870
  meta=data.get("meta"),
@@ -1923,6 +1947,7 @@ class TangoClient:
1923
1947
  return PaginatedResponse(
1924
1948
  count=data["count"],
1925
1949
  next=data.get("next"),
1950
+ count_type=data.get(_COUNT_TYPE_KEY),
1926
1951
  previous=data.get("previous"),
1927
1952
  results=results,
1928
1953
  meta=data.get("meta"),
@@ -1972,6 +1997,7 @@ class TangoClient:
1972
1997
  return PaginatedResponse(
1973
1998
  count=data["count"],
1974
1999
  next=data.get("next"),
2000
+ count_type=data.get(_COUNT_TYPE_KEY),
1975
2001
  previous=data.get("previous"),
1976
2002
  results=results,
1977
2003
  meta=data.get("meta"),
@@ -2007,6 +2033,7 @@ class TangoClient:
2007
2033
  return PaginatedResponse(
2008
2034
  count=data["count"],
2009
2035
  next=data.get("next"),
2036
+ count_type=data.get(_COUNT_TYPE_KEY),
2010
2037
  previous=data.get("previous"),
2011
2038
  results=results,
2012
2039
  meta=data.get("meta"),
@@ -2059,6 +2086,7 @@ class TangoClient:
2059
2086
  return PaginatedResponse(
2060
2087
  count=data.get("count", 0),
2061
2088
  next=data.get("next"),
2089
+ count_type=data.get(_COUNT_TYPE_KEY),
2062
2090
  previous=data.get("previous"),
2063
2091
  results=data.get("results", []),
2064
2092
  meta=data.get("meta"),
@@ -2146,6 +2174,7 @@ class TangoClient:
2146
2174
  return PaginatedResponse(
2147
2175
  count=data["count"],
2148
2176
  next=data.get("next"),
2177
+ count_type=data.get(_COUNT_TYPE_KEY),
2149
2178
  previous=data.get("previous"),
2150
2179
  results=results,
2151
2180
  meta=data.get("meta"),
@@ -2203,6 +2232,7 @@ class TangoClient:
2203
2232
  return PaginatedResponse(
2204
2233
  count=int(data.get("count", 0)),
2205
2234
  next=data.get("next"),
2235
+ count_type=data.get(_COUNT_TYPE_KEY),
2206
2236
  previous=data.get("previous"),
2207
2237
  results=list(data.get("results") or []),
2208
2238
  meta=data.get("meta"),
@@ -2296,6 +2326,7 @@ class TangoClient:
2296
2326
  return PaginatedResponse(
2297
2327
  count=data["count"],
2298
2328
  next=data.get("next"),
2329
+ count_type=data.get(_COUNT_TYPE_KEY),
2299
2330
  previous=data.get("previous"),
2300
2331
  results=results,
2301
2332
  meta=data.get("meta"),
@@ -2427,6 +2458,7 @@ class TangoClient:
2427
2458
  return PaginatedResponse(
2428
2459
  count=data["count"],
2429
2460
  next=data.get("next"),
2461
+ count_type=data.get(_COUNT_TYPE_KEY),
2430
2462
  previous=data.get("previous"),
2431
2463
  results=results,
2432
2464
  meta=data.get("meta"),
@@ -2542,6 +2574,7 @@ class TangoClient:
2542
2574
  return PaginatedResponse(
2543
2575
  count=data["count"],
2544
2576
  next=data.get("next"),
2577
+ count_type=data.get(_COUNT_TYPE_KEY),
2545
2578
  previous=data.get("previous"),
2546
2579
  results=results,
2547
2580
  meta=data.get("meta"),
@@ -2664,6 +2697,7 @@ class TangoClient:
2664
2697
  return PaginatedResponse(
2665
2698
  count=data["count"],
2666
2699
  next=data.get("next"),
2700
+ count_type=data.get(_COUNT_TYPE_KEY),
2667
2701
  previous=data.get("previous"),
2668
2702
  results=results,
2669
2703
  meta=data.get("meta"),
@@ -2802,6 +2836,7 @@ class TangoClient:
2802
2836
  return PaginatedResponse(
2803
2837
  count=data["count"],
2804
2838
  next=data.get("next"),
2839
+ count_type=data.get(_COUNT_TYPE_KEY),
2805
2840
  previous=data.get("previous"),
2806
2841
  results=results,
2807
2842
  meta=data.get("meta"),
@@ -2940,6 +2975,7 @@ class TangoClient:
2940
2975
  return PaginatedResponse(
2941
2976
  count=data["count"],
2942
2977
  next=data.get("next"),
2978
+ count_type=data.get(_COUNT_TYPE_KEY),
2943
2979
  previous=data.get("previous"),
2944
2980
  results=results,
2945
2981
  meta=data.get("meta"),
@@ -3080,6 +3116,7 @@ class TangoClient:
3080
3116
  return PaginatedResponse(
3081
3117
  count=data["count"],
3082
3118
  next=data.get("next"),
3119
+ count_type=data.get(_COUNT_TYPE_KEY),
3083
3120
  previous=data.get("previous"),
3084
3121
  results=results,
3085
3122
  meta=data.get("meta"),
@@ -3288,6 +3325,7 @@ class TangoClient:
3288
3325
  return PaginatedResponse(
3289
3326
  count=data["count"],
3290
3327
  next=data.get("next"),
3328
+ count_type=data.get(_COUNT_TYPE_KEY),
3291
3329
  previous=data.get("previous"),
3292
3330
  results=results,
3293
3331
  meta=data.get("meta"),
@@ -3408,6 +3446,7 @@ class TangoClient:
3408
3446
  return PaginatedResponse(
3409
3447
  count=data["count"],
3410
3448
  next=data.get("next"),
3449
+ count_type=data.get(_COUNT_TYPE_KEY),
3411
3450
  previous=data.get("previous"),
3412
3451
  results=results,
3413
3452
  meta=data.get("meta"),
@@ -3546,6 +3585,7 @@ class TangoClient:
3546
3585
  return PaginatedResponse(
3547
3586
  count=data["count"],
3548
3587
  next=data.get("next"),
3588
+ count_type=data.get(_COUNT_TYPE_KEY),
3549
3589
  previous=data.get("previous"),
3550
3590
  results=results,
3551
3591
  meta=data.get("meta"),
@@ -3695,6 +3735,7 @@ class TangoClient:
3695
3735
  return PaginatedResponse(
3696
3736
  count=data["count"],
3697
3737
  next=data.get("next"),
3738
+ count_type=data.get(_COUNT_TYPE_KEY),
3698
3739
  previous=data.get("previous"),
3699
3740
  results=results,
3700
3741
  meta=data.get("meta"),
@@ -3826,6 +3867,7 @@ class TangoClient:
3826
3867
  return PaginatedResponse(
3827
3868
  count=data["count"],
3828
3869
  next=data.get("next"),
3870
+ count_type=data.get(_COUNT_TYPE_KEY),
3829
3871
  previous=data.get("previous"),
3830
3872
  results=results,
3831
3873
  meta=data.get("meta"),
@@ -3947,6 +3989,7 @@ class TangoClient:
3947
3989
  return PaginatedResponse(
3948
3990
  count=data["count"],
3949
3991
  next=data.get("next"),
3992
+ count_type=data.get(_COUNT_TYPE_KEY),
3950
3993
  previous=data.get("previous"),
3951
3994
  results=results,
3952
3995
  meta=data.get("meta"),
@@ -4155,6 +4198,7 @@ class TangoClient:
4155
4198
  return PaginatedResponse(
4156
4199
  count=data["count"],
4157
4200
  next=data.get("next"),
4201
+ count_type=data.get(_COUNT_TYPE_KEY),
4158
4202
  previous=data.get("previous"),
4159
4203
  results=results,
4160
4204
  meta=data.get("meta"),
@@ -4267,6 +4311,7 @@ class TangoClient:
4267
4311
  return PaginatedResponse(
4268
4312
  count=data["count"],
4269
4313
  next=data.get("next"),
4314
+ count_type=data.get(_COUNT_TYPE_KEY),
4270
4315
  previous=data.get("previous"),
4271
4316
  results=results,
4272
4317
  meta=data.get("meta"),
@@ -4391,6 +4436,7 @@ class TangoClient:
4391
4436
  return PaginatedResponse(
4392
4437
  count=data["count"],
4393
4438
  next=data.get("next"),
4439
+ count_type=data.get(_COUNT_TYPE_KEY),
4394
4440
  previous=data.get("previous"),
4395
4441
  results=results,
4396
4442
  meta=data.get("meta"),
@@ -4450,6 +4496,10 @@ class TangoClient:
4450
4496
  subfunction_code: str | None = None,
4451
4497
  account_category: str | None = None,
4452
4498
  account_category_in: str | None = None,
4499
+ data_through_period: int | None = None,
4500
+ data_through_period_gte: int | None = None,
4501
+ data_through_period_lte: int | None = None,
4502
+ data_through_period_isnull: bool | None = None,
4453
4503
  # Range-numeric filters: each field also accepts ``__gte`` / ``__lte``.
4454
4504
  requested_ba: float | None = None,
4455
4505
  requested_ba_gte: float | None = None,
@@ -4561,6 +4611,8 @@ class TangoClient:
4561
4611
  categories may be added.
4562
4612
  account_category_in: Comma-separated account categories to match
4563
4613
  any of, e.g. ``"budgetary,credit_financing"``.
4614
+ data_through_period: File A period (1-12) the account-year's figures run through (exact). Also ``data_through_period_gte`` / ``data_through_period_lte``; a value below 12 means a partial year.
4615
+ data_through_period_isnull: ``True`` for accounts with no File A data, ``False`` for accounts with it.
4564
4616
  requested_ba: President's-budget requested BA (exact). Also
4565
4617
  ``requested_ba_gte`` / ``requested_ba_lte`` for range queries.
4566
4618
  enacted_ba: Enacted budget authority (exact / gte / lte).
@@ -4630,11 +4682,17 @@ class TangoClient:
4630
4682
  ("subfunction_code", subfunction_code),
4631
4683
  ("account_category", account_category),
4632
4684
  ("account_category__in", account_category_in),
4685
+ ("data_through_period", data_through_period),
4686
+ ("data_through_period__gte", data_through_period_gte),
4687
+ ("data_through_period__lte", data_through_period_lte),
4688
+ ("data_through_period__isnull", data_through_period_isnull),
4633
4689
  ("search", search),
4634
4690
  ("ordering", ordering),
4635
4691
  )
4636
4692
  for key, val in scalar_filters:
4637
- if val is not None:
4693
+ if isinstance(val, bool):
4694
+ params[key] = "true" if val else "false"
4695
+ elif val is not None:
4638
4696
  params[key] = val
4639
4697
  # Range-numeric filters: each field has exact / __gte / __lte forms.
4640
4698
  range_filters: tuple[tuple[str, float | None, float | None, float | None], ...] = (
@@ -4780,6 +4838,7 @@ class TangoClient:
4780
4838
  return PaginatedResponse(
4781
4839
  count=data.get("count", 0),
4782
4840
  next=data.get("next"),
4841
+ count_type=data.get(_COUNT_TYPE_KEY),
4783
4842
  previous=data.get("previous"),
4784
4843
  results=results,
4785
4844
  meta=data.get("meta"),
@@ -4832,6 +4891,7 @@ class TangoClient:
4832
4891
  return PaginatedResponse(
4833
4892
  count=int(data.get("count") or len(data.get("results") or [])),
4834
4893
  next=data.get("next"),
4894
+ count_type=data.get(_COUNT_TYPE_KEY),
4835
4895
  previous=data.get("previous"),
4836
4896
  results=data.get("results") or [],
4837
4897
  meta=data.get("meta"),
@@ -4860,6 +4920,7 @@ class TangoClient:
4860
4920
  return PaginatedResponse(
4861
4921
  count=int(data.get("count") or len(data.get("results") or [])),
4862
4922
  next=data.get("next"),
4923
+ count_type=data.get(_COUNT_TYPE_KEY),
4863
4924
  previous=data.get("previous"),
4864
4925
  results=data.get("results") or [],
4865
4926
  meta=data.get("meta"),
@@ -4954,6 +5015,7 @@ class TangoClient:
4954
5015
  return PaginatedResponse(
4955
5016
  count=data["count"],
4956
5017
  next=data.get("next"),
5018
+ count_type=data.get(_COUNT_TYPE_KEY),
4957
5019
  previous=data.get("previous"),
4958
5020
  results=results,
4959
5021
  meta=data.get("meta"),
@@ -5047,6 +5109,7 @@ class TangoClient:
5047
5109
  return PaginatedResponse(
5048
5110
  count=int(data.get("count", len(results))),
5049
5111
  next=data.get("next"),
5112
+ count_type=data.get(_COUNT_TYPE_KEY),
5050
5113
  previous=data.get("previous"),
5051
5114
  results=results,
5052
5115
  meta=data.get("meta"),
@@ -5232,6 +5295,7 @@ class TangoClient:
5232
5295
  return PaginatedResponse(
5233
5296
  count=int(data.get("count", len(results))),
5234
5297
  next=data.get("next"),
5298
+ count_type=data.get(_COUNT_TYPE_KEY),
5235
5299
  previous=data.get("previous"),
5236
5300
  results=results,
5237
5301
  meta=data.get("meta"),
@@ -5450,6 +5514,7 @@ class TangoClient:
5450
5514
  return PaginatedResponse(
5451
5515
  count=int(data.get("count", 0)),
5452
5516
  next=data.get("next"),
5517
+ count_type=data.get(_COUNT_TYPE_KEY),
5453
5518
  previous=data.get("previous"),
5454
5519
  results=list(data.get("results") or []),
5455
5520
  meta=data.get("meta"),
@@ -5488,6 +5553,7 @@ class TangoClient:
5488
5553
  return PaginatedResponse(
5489
5554
  count=int(data.get("count", 0)),
5490
5555
  next=data.get("next"),
5556
+ count_type=data.get(_COUNT_TYPE_KEY),
5491
5557
  previous=data.get("previous"),
5492
5558
  results=list(data.get("results") or []),
5493
5559
  meta=data.get("meta"),
@@ -5589,6 +5655,7 @@ class TangoClient:
5589
5655
  return PaginatedResponse(
5590
5656
  count=int(data.get("count", 0)),
5591
5657
  next=data.get("next"),
5658
+ count_type=data.get(_COUNT_TYPE_KEY),
5592
5659
  previous=data.get("previous"),
5593
5660
  results=list(data.get("results") or []),
5594
5661
  meta=data.get("meta"),
@@ -5636,6 +5703,7 @@ class TangoClient:
5636
5703
  return PaginatedResponse(
5637
5704
  count=int(data.get("count", 0)),
5638
5705
  next=data.get("next"),
5706
+ count_type=data.get(_COUNT_TYPE_KEY),
5639
5707
  previous=data.get("previous"),
5640
5708
  results=list(data.get("results") or []),
5641
5709
  meta=data.get("meta"),
@@ -5704,6 +5772,7 @@ class TangoClient:
5704
5772
  return PaginatedResponse(
5705
5773
  count=int(data.get("count") or len(results)),
5706
5774
  next=data.get("next"),
5775
+ count_type=data.get(_COUNT_TYPE_KEY),
5707
5776
  previous=data.get("previous"),
5708
5777
  results=results,
5709
5778
  cursor=data.get("cursor"),
@@ -5882,6 +5951,7 @@ class TangoClient:
5882
5951
  return PaginatedResponse(
5883
5952
  count=int(data.get("count", 0)),
5884
5953
  next=data.get("next"),
5954
+ count_type=data.get(_COUNT_TYPE_KEY),
5885
5955
  previous=data.get("previous"),
5886
5956
  results=results,
5887
5957
  meta=data.get("meta"),
@@ -5913,6 +5983,7 @@ class TangoClient:
5913
5983
  return PaginatedResponse(
5914
5984
  count=int(data.get("count", 0)),
5915
5985
  next=data.get("next"),
5986
+ count_type=data.get(_COUNT_TYPE_KEY),
5916
5987
  previous=data.get("previous"),
5917
5988
  results=list(data.get("results") or []),
5918
5989
  meta=data.get("meta"),
@@ -5954,6 +6025,7 @@ class TangoClient:
5954
6025
  return PaginatedResponse(
5955
6026
  count=int(data.get("count", 0)),
5956
6027
  next=data.get("next"),
6028
+ count_type=data.get(_COUNT_TYPE_KEY),
5957
6029
  previous=data.get("previous"),
5958
6030
  results=list(data.get("results") or []),
5959
6031
  meta=data.get("meta"),
@@ -6010,6 +6082,7 @@ class TangoClient:
6010
6082
  return PaginatedResponse(
6011
6083
  count=int(data.get("count") or len(results)),
6012
6084
  next=data.get("next"),
6085
+ count_type=data.get(_COUNT_TYPE_KEY),
6013
6086
  previous=data.get("previous"),
6014
6087
  results=results,
6015
6088
  cursor=data.get("cursor"),
tango/models.py CHANGED
@@ -489,6 +489,8 @@ class Vehicle:
489
489
  program_acronym: str | None = None
490
490
  description: str | None = None
491
491
  idv_count: int | None = None
492
+ holder_count: int | None = None
493
+ order_winner_count: int | None = None
492
494
  total_obligated: Decimal | None = None
493
495
  latest_award_date: date | None = None
494
496
  solicitation_title: str | None = None
@@ -847,6 +849,8 @@ class BudgetAccount:
847
849
  id: int | None = None
848
850
  federal_account_symbol: str | None = None
849
851
  fiscal_year: int | None = None
852
+ # File A period (1-12) this account-year's figures run through; below 12 the year is partial, and `None` means no File A data.
853
+ data_through_period: int | None = None
850
854
  agency_code: str | None = None
851
855
  agency_name: str | None = None
852
856
  bureau_name: str | None = None
@@ -1458,6 +1462,8 @@ class PaginatedResponse[T]:
1458
1462
  page_metadata: Always ``None`` — the API has never emitted a
1459
1463
  ``page_metadata`` key. Retained so existing attribute access keeps
1460
1464
  working; use ``meta`` instead.
1465
+ count_type: ``"exact"`` or ``"approximate"``, from the API's ``X-Results-CountType`` header; ``None`` when the endpoint doesn't send it.
1466
+ The contract, IDV, opportunity and notice lists can switch to a query-planner estimate past 1,000 matches, which can be well off.
1461
1467
 
1462
1468
  Examples:
1463
1469
  >>> from tango import TangoClient, ShapeConfig
@@ -1478,6 +1484,7 @@ class PaginatedResponse[T]:
1478
1484
  cursor: str | None = None
1479
1485
  meta: dict[str, Any] | None = None
1480
1486
  page_metadata: dict[str, Any] | None = None
1487
+ count_type: str | None = None
1481
1488
 
1482
1489
  @property
1483
1490
  def agency_warnings(self) -> list[str]:
@@ -1752,7 +1759,7 @@ class ShapeConfig:
1752
1759
  VEHICLES_MINIMAL: Final = (
1753
1760
  "uuid,solicitation_identifier,is_synthetic_solicitation,program_acronym,"
1754
1761
  "organization_id,organization,vehicle_type,description,"
1755
- "idv_count,awardee_count,order_count,total_obligated,"
1762
+ "idv_count,holder_count,order_winner_count,awardee_count,order_count,total_obligated,"
1756
1763
  "vehicle_obligations,vehicle_contracts_value,latest_award_date,"
1757
1764
  "solicitation_title,solicitation_date"
1758
1765
  )
@@ -1764,7 +1771,8 @@ class ShapeConfig:
1764
1771
  "solicitation_title,solicitation_description,solicitation_date,opportunity_id,"
1765
1772
  "naics_code,psc_code,set_aside,"
1766
1773
  "fiscal_year,award_date,latest_award_date,last_date_to_order,"
1767
- "description,idv_count,awardee_count,order_count,total_obligated,"
1774
+ "description,idv_count,holder_count,order_winner_count,awardee_count,order_count,"
1775
+ "total_obligated,"
1768
1776
  "vehicle_obligations,vehicle_contracts_value,"
1769
1777
  "type_of_idc,contract_type,metrics(*)"
1770
1778
  )
@@ -1780,7 +1788,8 @@ class ShapeConfig:
1780
1788
  # Default for list_budget_accounts() / get_budget_account()
1781
1789
  # Mirrors the API's BUDGET_ACCOUNT_DEFAULT_SHAPE.
1782
1790
  BUDGET_ACCOUNTS_MINIMAL: Final = (
1783
- "id,federal_account_symbol,fiscal_year,agency_code,agency_name,bureau_name,"
1791
+ "id,federal_account_symbol,fiscal_year,data_through_period,agency_code,agency_name,"
1792
+ "bureau_name,"
1784
1793
  "account_title,bea_category,on_off_budget,subfunction_code,account_category,"
1785
1794
  "requested_ba,enacted_ba,apportioned,obligated_total,outlayed_total,"
1786
1795
  "unobligated_balance,contract_obligated,contract_share_of_obligated_capped,"
@@ -1337,6 +1337,11 @@ VEHICLE_SCHEMA: dict[str, FieldSchema] = {
1337
1337
  ),
1338
1338
  # Denormalized rollups
1339
1339
  "idv_count": FieldSchema(name="idv_count", type=int, is_optional=True, is_list=False),
1340
+ "holder_count": FieldSchema(name="holder_count", type=int, is_optional=True, is_list=False),
1341
+ "order_winner_count": FieldSchema(
1342
+ name="order_winner_count", type=int, is_optional=True, is_list=False
1343
+ ),
1344
+ # Deprecated: same value as `order_winner_count`; removed at the next major API version.
1340
1345
  "awardee_count": FieldSchema(name="awardee_count", type=int, is_optional=True, is_list=False),
1341
1346
  "order_count": FieldSchema(name="order_count", type=int, is_optional=True, is_list=False),
1342
1347
  "total_obligated": FieldSchema(
@@ -1318,6 +1318,9 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
1318
1318
  name="contract_share_of_obligated_capped", type=str, is_optional=True, is_list=False
1319
1319
  ),
1320
1320
  "created": FieldSchema(name="created", type=datetime, is_optional=True, is_list=False),
1321
+ "data_through_period": FieldSchema(
1322
+ name="data_through_period", type=int, is_optional=True, is_list=False
1323
+ ),
1321
1324
  "enacted_ba": FieldSchema(name="enacted_ba", type=str, is_optional=True, is_list=False),
1322
1325
  "enacted_ba_5yr_cagr": FieldSchema(
1323
1326
  name="enacted_ba_5yr_cagr", type=str, is_optional=True, is_list=False
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.5
2
2
  Name: tango-python
3
- Version: 1.12.0
3
+ Version: 1.14.0
4
4
  Summary: Python SDK for the Tango API
5
5
  Project-URL: Homepage, https://github.com/makegov/tango-python
6
6
  Project-URL: Documentation, https://docs.makegov.com/tango-python
@@ -1,11 +1,11 @@
1
- tango/__init__.py,sha256=XRADxf8CwMbNTUr999g7MgiFKFuzoSQ0L2szhIIDWtU,2739
2
- tango/client.py,sha256=YkbWxdNE91229sDWwPCizAYfTl1LZK517wuD2I5hPhQ,239391
1
+ tango/__init__.py,sha256=XZv0Q3i4cb0rMu4DTMvB6vthWIQsgfmgnTt5EVnqdac,2739
2
+ tango/client.py,sha256=1Z748iPEPdVi8_Sq9XPES8RnPdnugEwL3yAgV7Cvvt0,243419
3
3
  tango/exceptions.py,sha256=oPiLCccBoWLK5SjHkzP-oI6mUD9twEeKSvEuLV5h01I,4224
4
- tango/models.py,sha256=vviVPF0gJQTpqMJE7oGhZrJuavGgwhU5NazlVJBzpYw,69578
4
+ tango/models.py,sha256=Is7HRH3xLy8k82aeRqaJU6zaxZ7CSui4D5Pg9q7Pr9Y,70257
5
5
  tango/shapes/__init__.py,sha256=7ea1WU74jp4znhNw-gXruag6m6eyPZtbVgbDFmFUWro,1072
6
- tango/shapes/explicit_schemas.py,sha256=spYyMmWKOiMJygz9yViBQrjIxUPFfv7HpVkJcWy13x8,84021
6
+ tango/shapes/explicit_schemas.py,sha256=tqGitlPoXN4VDfwCU5T4KfzLfQTyZ2Ephap56bDbB3c,84334
7
7
  tango/shapes/factory.py,sha256=uDPhnp6VVzrLBKodxteZy5AcU43juEv-qKVRWth51j0,31550
8
- tango/shapes/generated_overlay.py,sha256=9SNrqVFBz59Xo8-u24-x-74g42juhCKjAArQr9_MM8o,140723
8
+ tango/shapes/generated_overlay.py,sha256=fyCgKDueIKUcTMtij793mtJcAsC8RynMhU5FXI_9hG0,140860
9
9
  tango/shapes/generator.py,sha256=xzakpwTwqTMUr89I06hp54-FIYZziviWHk2Glscg-LM,22775
10
10
  tango/shapes/models.py,sha256=h3pIhOqrrdlN953Y6r0oney5HFbKPOD-frRndRWimJ0,3018
11
11
  tango/shapes/parser.py,sha256=AecNx5oT_hV_pf2AWZnsR8Y2aLmCtjfgS9-znA2Pesc,27429
@@ -16,8 +16,8 @@ tango/webhooks/cli.py,sha256=f_vQbJ2AeSQjKnQo7MxHFyUB2SAKcgHYmGQULS0isqQ,13858
16
16
  tango/webhooks/receiver.py,sha256=5yhsVhlLyoxmOCGvmbynWAIlDB2OaCPVf1H4GA1SxmU,9279
17
17
  tango/webhooks/signing.py,sha256=92Ee-0B6PR7ZkvY3Np3gzl88-mtfKkh-I7lxqCe2lGw,2374
18
18
  tango/webhooks/simulate.py,sha256=g2Osa0FYU5mJuon07T2aUCtmkUoTEzsY261tlp76fF0,3165
19
- tango_python-1.12.0.dist-info/METADATA,sha256=JsVs05maoR9Q7YGHhn4RQLpqyPG_ptX6BgpGnakcaeI,22118
20
- tango_python-1.12.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
21
- tango_python-1.12.0.dist-info/entry_points.txt,sha256=kGLUbglUjuaAqEFvOZ1QuSW0vWb6VeSpCIFKaOFkKoQ,50
22
- tango_python-1.12.0.dist-info/licenses/LICENSE,sha256=j2kYVHMwTkoGn3ZNScnrdIueG0k2XzB_LCPFoyBc2wk,1064
23
- tango_python-1.12.0.dist-info/RECORD,,
19
+ tango_python-1.14.0.dist-info/METADATA,sha256=IMQQV5MA3ekEPPGbdTWW6K0eYMxCXIzarR5DSM3HxZQ,22118
20
+ tango_python-1.14.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
21
+ tango_python-1.14.0.dist-info/entry_points.txt,sha256=kGLUbglUjuaAqEFvOZ1QuSW0vWb6VeSpCIFKaOFkKoQ,50
22
+ tango_python-1.14.0.dist-info/licenses/LICENSE,sha256=j2kYVHMwTkoGn3ZNScnrdIueG0k2XzB_LCPFoyBc2wk,1064
23
+ tango_python-1.14.0.dist-info/RECORD,,