tango-python 1.6.0__py3-none-any.whl → 1.7.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 +3 -1
- tango/client.py +143 -4
- tango/models.py +84 -6
- tango/shapes/explicit_schemas.py +38 -0
- tango/shapes/generated_overlay.py +61 -23
- {tango_python-1.6.0.dist-info → tango_python-1.7.0.dist-info}/METADATA +1 -1
- {tango_python-1.6.0.dist-info → tango_python-1.7.0.dist-info}/RECORD +10 -10
- {tango_python-1.6.0.dist-info → tango_python-1.7.0.dist-info}/WHEEL +1 -1
- {tango_python-1.6.0.dist-info → tango_python-1.7.0.dist-info}/entry_points.txt +0 -0
- {tango_python-1.6.0.dist-info → tango_python-1.7.0.dist-info}/licenses/LICENSE +0 -0
tango/__init__.py
CHANGED
|
@@ -10,6 +10,7 @@ from .exceptions import (
|
|
|
10
10
|
)
|
|
11
11
|
from .models import (
|
|
12
12
|
BudgetAccount,
|
|
13
|
+
ContractAppeal,
|
|
13
14
|
DibbsAward,
|
|
14
15
|
DibbsRfp,
|
|
15
16
|
DibbsRfq,
|
|
@@ -53,7 +54,7 @@ from .webhooks import (
|
|
|
53
54
|
)
|
|
54
55
|
from .webhooks.receiver import Delivery, WebhookReceiver
|
|
55
56
|
|
|
56
|
-
__version__ = "1.
|
|
57
|
+
__version__ = "1.7.0"
|
|
57
58
|
__all__ = [
|
|
58
59
|
"TangoClient",
|
|
59
60
|
"TangoAPIError",
|
|
@@ -65,6 +66,7 @@ __all__ = [
|
|
|
65
66
|
"ResolveCandidate",
|
|
66
67
|
"ResolveResult",
|
|
67
68
|
"BudgetAccount",
|
|
69
|
+
"ContractAppeal",
|
|
68
70
|
"DibbsAward",
|
|
69
71
|
"DibbsRfp",
|
|
70
72
|
"DibbsRfq",
|
tango/client.py
CHANGED
|
@@ -24,6 +24,7 @@ from tango.models import (
|
|
|
24
24
|
BudgetAccount,
|
|
25
25
|
BusinessType,
|
|
26
26
|
Contract,
|
|
27
|
+
ContractAppeal,
|
|
27
28
|
DibbsAward,
|
|
28
29
|
DibbsRfp,
|
|
29
30
|
DibbsRfq,
|
|
@@ -2592,18 +2593,18 @@ class TangoClient:
|
|
|
2592
2593
|
shape: Response shape string (defaults to minimal shape)
|
|
2593
2594
|
flat: If True, flatten nested objects in shaped response
|
|
2594
2595
|
flat_lists: If True, flatten arrays using indexed keys
|
|
2595
|
-
source_system: Filter by source system
|
|
2596
|
+
source_system: Filter by source system: gao, cofc, or sba_oha
|
|
2596
2597
|
outcome: Filter by outcome (e.g. Denied, Dismissed, Withdrawn, Sustained)
|
|
2597
2598
|
case_type: Filter by case type
|
|
2598
2599
|
agency: Filter by protested agency text
|
|
2599
|
-
case_number: Filter by case number (e.g. b-423274)
|
|
2600
|
+
case_number: Filter by base case number, matched case-insensitively (e.g. b-423274 for GAO, 26-1391 for COFC, SIZ-6100 for SBA OHA)
|
|
2600
2601
|
solicitation_number: Filter by exact solicitation number
|
|
2601
2602
|
protester: Filter by protester name text
|
|
2602
2603
|
filed_date_after: Filed date on or after
|
|
2603
2604
|
filed_date_before: Filed date on or before
|
|
2604
2605
|
decision_date_after: Decision date on or after
|
|
2605
2606
|
decision_date_before: Decision date on or before
|
|
2606
|
-
naics_code: Filter by the
|
|
2607
|
+
naics_code: Filter by the NAICS code at issue in an SBA OHA size or NAICS appeal (e.g. 541519); GAO and COFC protests carry no NAICS code and never match
|
|
2607
2608
|
search: Full-text search over protest searchable fields
|
|
2608
2609
|
"""
|
|
2609
2610
|
params: dict[str, Any] = {"page": page, "limit": min(limit, 100)}
|
|
@@ -2682,6 +2683,141 @@ class TangoClient:
|
|
|
2682
2683
|
data = self._get(f"/api/protests/{case_id}/", params)
|
|
2683
2684
|
return self._parse_response_with_shape(data, shape, Protest, flat, flat_lists)
|
|
2684
2685
|
|
|
2686
|
+
# ============================================================================
|
|
2687
|
+
# Contract Disputes Act appeals (CBCA and ASBCA)
|
|
2688
|
+
# ============================================================================
|
|
2689
|
+
|
|
2690
|
+
def list_contract_appeals(
|
|
2691
|
+
self,
|
|
2692
|
+
page: int = 1,
|
|
2693
|
+
limit: int = 25,
|
|
2694
|
+
shape: str | None = None,
|
|
2695
|
+
flat: bool = False,
|
|
2696
|
+
flat_lists: bool = False,
|
|
2697
|
+
board: str | None = None,
|
|
2698
|
+
docket: str | None = None,
|
|
2699
|
+
appellant: str | None = None,
|
|
2700
|
+
judge: str | None = None,
|
|
2701
|
+
decision_type: str | None = None,
|
|
2702
|
+
decision_date_after: str | None = None,
|
|
2703
|
+
decision_date_before: str | None = None,
|
|
2704
|
+
listed: bool | None = None,
|
|
2705
|
+
document_id: str | None = None,
|
|
2706
|
+
search: str | None = None,
|
|
2707
|
+
ordering: str | None = None,
|
|
2708
|
+
) -> PaginatedResponse:
|
|
2709
|
+
"""
|
|
2710
|
+
List Contract Disputes Act appeal decisions.
|
|
2711
|
+
|
|
2712
|
+
Decisions of the Civilian Board of Contract Appeals (CBCA) and the Armed
|
|
2713
|
+
Services Board of Contract Appeals (ASBCA) — appeals of a contracting
|
|
2714
|
+
officer's decision, which is a different dispute from a bid protest. For
|
|
2715
|
+
protests, use :meth:`list_protests`.
|
|
2716
|
+
|
|
2717
|
+
Args:
|
|
2718
|
+
page: Page number
|
|
2719
|
+
limit: Results per page (max 100)
|
|
2720
|
+
shape: Response shape string (defaults to minimal shape)
|
|
2721
|
+
flat: If True, flatten nested objects in shaped response
|
|
2722
|
+
flat_lists: If True, flatten arrays using indexed keys
|
|
2723
|
+
board: ``cbca`` or ``asbca``. Multi-value: ``cbca|asbca``
|
|
2724
|
+
docket: Exact docket match, e.g. ``3288-R``, ``59116`` or
|
|
2725
|
+
``7092-C(6682, 6765, 6767)``. A leading ``CBCA`` / ``ASBCA`` and
|
|
2726
|
+
``No.`` / ``Nos.`` are ignored, so a docket can be pasted as it is
|
|
2727
|
+
cited. Commas are part of a docket, never a separator; OR several
|
|
2728
|
+
with ``|``
|
|
2729
|
+
appellant: Case-insensitive substring match on the appellant's name
|
|
2730
|
+
(min 2 characters)
|
|
2731
|
+
judge: Case-insensitive exact match on the judge as the listing names
|
|
2732
|
+
them
|
|
2733
|
+
decision_type: CBCA only — ``Decision``, ``Dismissal``, ``Order``,
|
|
2734
|
+
``Full Board Order``, or the listing's own text where it matches
|
|
2735
|
+
none of those. ASBCA rows carry no type
|
|
2736
|
+
decision_date_after: Decided on or after (YYYY-MM-DD)
|
|
2737
|
+
decision_date_before: Decided on or before (YYYY-MM-DD)
|
|
2738
|
+
listed: Whether the board's newest listing still carries the decision.
|
|
2739
|
+
``False`` returns the ones it has dropped, which are kept here
|
|
2740
|
+
rather than deleted
|
|
2741
|
+
document_id: The board's own document id
|
|
2742
|
+
search: Ranked full-text search over the appellant and the full
|
|
2743
|
+
decision text (min 2 characters). Wrap in double quotes for a
|
|
2744
|
+
phrase. Free at every plan, and it returns no fragment of the
|
|
2745
|
+
text — only reading ``decision_text`` needs Enterprise
|
|
2746
|
+
ordering: Sort field — ``decision_date`` (the default, as
|
|
2747
|
+
``-decision_date``), ``appellant``, ``first_listed_at`` or
|
|
2748
|
+
``rank``. ``rank`` requires a non-empty ``search``
|
|
2749
|
+
"""
|
|
2750
|
+
params: dict[str, Any] = {"page": page, "limit": min(limit, 100)}
|
|
2751
|
+
|
|
2752
|
+
if shape is None:
|
|
2753
|
+
shape = ShapeConfig.CONTRACT_APPEALS_MINIMAL
|
|
2754
|
+
if shape:
|
|
2755
|
+
params["shape"] = shape
|
|
2756
|
+
if flat:
|
|
2757
|
+
params["flat"] = "true"
|
|
2758
|
+
if flat_lists:
|
|
2759
|
+
params["flat_lists"] = "true"
|
|
2760
|
+
|
|
2761
|
+
for key, val in (
|
|
2762
|
+
("board", board),
|
|
2763
|
+
("docket", docket),
|
|
2764
|
+
("appellant", appellant),
|
|
2765
|
+
("judge", judge),
|
|
2766
|
+
("decision_type", decision_type),
|
|
2767
|
+
("decision_date_after", decision_date_after),
|
|
2768
|
+
("decision_date_before", decision_date_before),
|
|
2769
|
+
("listed", listed),
|
|
2770
|
+
("document_id", document_id),
|
|
2771
|
+
("search", search),
|
|
2772
|
+
("ordering", ordering),
|
|
2773
|
+
):
|
|
2774
|
+
if val is not None:
|
|
2775
|
+
params[key] = val
|
|
2776
|
+
|
|
2777
|
+
data = self._get("/api/contract_appeals/", params)
|
|
2778
|
+
|
|
2779
|
+
results = [
|
|
2780
|
+
self._parse_response_with_shape(item, shape, ContractAppeal, flat, flat_lists)
|
|
2781
|
+
for item in data["results"]
|
|
2782
|
+
]
|
|
2783
|
+
|
|
2784
|
+
return PaginatedResponse(
|
|
2785
|
+
count=data["count"],
|
|
2786
|
+
next=data.get("next"),
|
|
2787
|
+
previous=data.get("previous"),
|
|
2788
|
+
results=results,
|
|
2789
|
+
meta=data.get("meta"),
|
|
2790
|
+
)
|
|
2791
|
+
|
|
2792
|
+
def get_contract_appeal(
|
|
2793
|
+
self,
|
|
2794
|
+
appeal_id: str,
|
|
2795
|
+
shape: str | None = None,
|
|
2796
|
+
flat: bool = False,
|
|
2797
|
+
flat_lists: bool = False,
|
|
2798
|
+
) -> Any:
|
|
2799
|
+
"""
|
|
2800
|
+
Get a single Contract Disputes Act appeal decision by uuid.
|
|
2801
|
+
|
|
2802
|
+
Args:
|
|
2803
|
+
appeal_id: Decision UUID
|
|
2804
|
+
shape: Response shape string (defaults to the comprehensive shape)
|
|
2805
|
+
flat: If True, flatten nested objects in shaped response
|
|
2806
|
+
flat_lists: If True, flatten arrays using indexed keys
|
|
2807
|
+
"""
|
|
2808
|
+
params: dict[str, Any] = {}
|
|
2809
|
+
if shape is None:
|
|
2810
|
+
shape = ShapeConfig.CONTRACT_APPEALS_COMPREHENSIVE
|
|
2811
|
+
if shape:
|
|
2812
|
+
params["shape"] = shape
|
|
2813
|
+
if flat:
|
|
2814
|
+
params["flat"] = "true"
|
|
2815
|
+
if flat_lists:
|
|
2816
|
+
params["flat_lists"] = "true"
|
|
2817
|
+
|
|
2818
|
+
data = self._get(f"/api/contract_appeals/{appeal_id}/", params)
|
|
2819
|
+
return self._parse_response_with_shape(data, shape, ContractAppeal, flat, flat_lists)
|
|
2820
|
+
|
|
2685
2821
|
# ============================================================================
|
|
2686
2822
|
# DLA DIBBS (RFQs, RFPs, awards)
|
|
2687
2823
|
# ============================================================================
|
|
@@ -4733,7 +4869,10 @@ class TangoClient:
|
|
|
4733
4869
|
Args:
|
|
4734
4870
|
name: Human-readable name for this alert.
|
|
4735
4871
|
query_type: One of ``opportunity``, ``contract``, ``idv``, ``ota``,
|
|
4736
|
-
``otidv``, ``entity``, ``grant``, ``forecast
|
|
4872
|
+
``otidv``, ``entity``, ``grant``, ``forecast``, ``exclusion``,
|
|
4873
|
+
``dibbs_rfq``, ``dibbs_rfp``, ``sled_opportunity`` or
|
|
4874
|
+
``contract_appeal``. :meth:`list_webhook_event_types` is the
|
|
4875
|
+
current authority — this list can only go stale.
|
|
4737
4876
|
filters: Dict of query parameters that the alert matches against
|
|
4738
4877
|
(e.g. ``{"naics": "541330", "set_aside": "SBA"}``).
|
|
4739
4878
|
frequency: ``realtime`` | ``daily`` | ``weekly`` | ``custom``.
|
tango/models.py
CHANGED
|
@@ -559,7 +559,13 @@ class Forecast:
|
|
|
559
559
|
|
|
560
560
|
@dataclass
|
|
561
561
|
class Opportunity:
|
|
562
|
-
"""Schema definition for Opportunity (not used for instances)
|
|
562
|
+
"""Schema definition for Opportunity (not used for instances)
|
|
563
|
+
|
|
564
|
+
The ``attachments(...)`` expand can carry two document-role fields on a Pro plan or above: ``doc_role``, what the document is for (one of ``requirement``, ``instructions``, ``pricing``, ``terms``, ``reference``, ``unknown``), and ``doc_role_alt``, a runner-up role that is usually null.
|
|
565
|
+
Both must be named, e.g. ``attachments(name,url,doc_role,doc_role_alt)``, because ``attachments(*)`` does not include them.
|
|
566
|
+
An attachment Tango has not classified omits both keys rather than returning null, so read them with ``.get()``.
|
|
567
|
+
A Free-plan request that names them gets the response without them, plus an entry in ``meta.upgrade_hints``.
|
|
568
|
+
"""
|
|
563
569
|
|
|
564
570
|
opportunity_id: str
|
|
565
571
|
title: str
|
|
@@ -573,7 +579,13 @@ class Opportunity:
|
|
|
573
579
|
|
|
574
580
|
@dataclass
|
|
575
581
|
class Notice:
|
|
576
|
-
"""Schema definition for Notice (not used for instances)
|
|
582
|
+
"""Schema definition for Notice (not used for instances)
|
|
583
|
+
|
|
584
|
+
The ``attachments(...)`` expand can carry two document-role fields on a Pro plan or above: ``doc_role``, what the document is for (one of ``requirement``, ``instructions``, ``pricing``, ``terms``, ``reference``, ``unknown``), and ``doc_role_alt``, a runner-up role that is usually null.
|
|
585
|
+
Both must be named, e.g. ``attachments(name,url,doc_role,doc_role_alt)``, because ``attachments(*)`` does not include them.
|
|
586
|
+
An attachment Tango has not classified omits both keys rather than returning null, so read them with ``.get()``.
|
|
587
|
+
A Free-plan request that names them gets the response without them, plus an entry in ``meta.upgrade_hints``.
|
|
588
|
+
"""
|
|
577
589
|
|
|
578
590
|
notice_id: str
|
|
579
591
|
title: str
|
|
@@ -1050,6 +1062,10 @@ class SledOpportunity:
|
|
|
1050
1062
|
Searching document text and reading it are separate: ``search=`` matches
|
|
1051
1063
|
inside attachment text on every plan and returns no fragment of it, while
|
|
1052
1064
|
``attachments(extracted_text)`` serves the body on a Small plan or above.
|
|
1065
|
+
|
|
1066
|
+
``delisted_at`` is when a portal dropped the solicitation from its listing before its deadline, which is the reading behind ``status_reason="delisted"``; it is null when the solicitation was never delisted or has been seen again since.
|
|
1067
|
+
|
|
1068
|
+
``meta(jurisdiction_declared)`` is a boolean saying whether the source stated the jurisdiction level itself; ``False`` means Tango classified it from the issuer's name.
|
|
1053
1069
|
"""
|
|
1054
1070
|
|
|
1055
1071
|
opportunity_id: str | None = None
|
|
@@ -1063,6 +1079,7 @@ class SledOpportunity:
|
|
|
1063
1079
|
agency: str | None = None
|
|
1064
1080
|
status: str | None = None
|
|
1065
1081
|
status_reason: str | None = None
|
|
1082
|
+
delisted_at: str | None = None
|
|
1066
1083
|
status_computed_at: str | None = None
|
|
1067
1084
|
source_status: str | None = None
|
|
1068
1085
|
source_url: str | None = None
|
|
@@ -1151,6 +1168,51 @@ class SledForecast:
|
|
|
1151
1168
|
raw: dict[str, Any] | None = None
|
|
1152
1169
|
|
|
1153
1170
|
|
|
1171
|
+
class ContractAppeal:
|
|
1172
|
+
"""Schema definition for ContractAppeal (not used for instances).
|
|
1173
|
+
|
|
1174
|
+
Contract Disputes Act appeal decisions at ``/api/contract_appeals/``, from the
|
|
1175
|
+
Civilian Board of Contract Appeals (CBCA) and the Armed Services Board of
|
|
1176
|
+
Contract Appeals (ASBCA). These are appeals of a contracting officer's
|
|
1177
|
+
decision, not bid protests — protests live at ``/api/protests/``.
|
|
1178
|
+
Shape-on-demand, so every field is optional.
|
|
1179
|
+
|
|
1180
|
+
One row is one decision as the board's own listing publishes it, so several
|
|
1181
|
+
fields describe the listing rather than the dispute. ``listed`` goes false
|
|
1182
|
+
once the board's newest listing stops carrying the decision; the row itself is
|
|
1183
|
+
kept, never dropped. ``docket_numbers`` holds the dockets with the board
|
|
1184
|
+
prefix stripped (``3288-R``, ``59116``) and a consolidated appeal carries
|
|
1185
|
+
several, while ``docket_raw`` keeps the listing's own text.
|
|
1186
|
+
|
|
1187
|
+
``decision_text`` is the extracted decision body and needs an Enterprise plan.
|
|
1188
|
+
Below that tier the key is ABSENT rather than null, so read it with ``.get()``.
|
|
1189
|
+
Searching that text is free at every plan: ``search=`` matches inside it and
|
|
1190
|
+
returns no fragment of it.
|
|
1191
|
+
"""
|
|
1192
|
+
|
|
1193
|
+
uuid: str | None = None
|
|
1194
|
+
board: str | None = None
|
|
1195
|
+
docket_numbers: list[str] | None = None
|
|
1196
|
+
docket_source: str | None = None
|
|
1197
|
+
docket_raw: str | None = None
|
|
1198
|
+
decision_date: date | None = None
|
|
1199
|
+
decision_date_raw: str | None = None
|
|
1200
|
+
decision_date_repaired: bool | None = None
|
|
1201
|
+
appellant: str | None = None
|
|
1202
|
+
judge: str | None = None
|
|
1203
|
+
decision_type: str | None = None
|
|
1204
|
+
decision_type_raw: str | None = None
|
|
1205
|
+
url: str | None = None
|
|
1206
|
+
document_id: str | None = None
|
|
1207
|
+
listing_url: str | None = None
|
|
1208
|
+
listing_year: int | None = None
|
|
1209
|
+
first_listed_at: datetime | None = None
|
|
1210
|
+
listed: bool | None = None
|
|
1211
|
+
text_status: str | None = None
|
|
1212
|
+
text_char_count: int | None = None
|
|
1213
|
+
decision_text: str | None = None
|
|
1214
|
+
|
|
1215
|
+
|
|
1154
1216
|
@dataclass
|
|
1155
1217
|
class PaginatedResponse[T]:
|
|
1156
1218
|
"""Paginated API response
|
|
@@ -1317,6 +1379,21 @@ class ShapeConfig:
|
|
|
1317
1379
|
# Default for list_protests()
|
|
1318
1380
|
PROTESTS_MINIMAL: Final = "case_id,case_number,title,source_system,outcome,filed_date"
|
|
1319
1381
|
|
|
1382
|
+
# Default for list_contract_appeals(). Mirrors the API's own list default.
|
|
1383
|
+
CONTRACT_APPEALS_MINIMAL: Final = (
|
|
1384
|
+
"uuid,board,docket_numbers,decision_date,appellant,judge,decision_type,url"
|
|
1385
|
+
)
|
|
1386
|
+
|
|
1387
|
+
# Default for get_contract_appeal(). Mirrors the API's own retrieve default.
|
|
1388
|
+
# `decision_text` is left out on purpose: it runs to ~100K characters and
|
|
1389
|
+
# needs an Enterprise plan, so naming it by default would make every detail
|
|
1390
|
+
# fetch ask for a body most callers cannot read.
|
|
1391
|
+
CONTRACT_APPEALS_COMPREHENSIVE: Final = (
|
|
1392
|
+
"uuid,board,docket_numbers,decision_date,appellant,judge,decision_type,url,"
|
|
1393
|
+
"docket_raw,docket_source,decision_date_repaired,decision_type_raw,"
|
|
1394
|
+
"listing_year,first_listed_at,listed,text_status,text_char_count"
|
|
1395
|
+
)
|
|
1396
|
+
|
|
1320
1397
|
# Default for list_dibbs_rfqs()
|
|
1321
1398
|
DIBBS_RFQS_MINIMAL: Final = (
|
|
1322
1399
|
"uuid,solicitation,nsn,part_number,nomenclature,quantity,issue_date,return_by_date,is_open"
|
|
@@ -1356,8 +1433,9 @@ class ShapeConfig:
|
|
|
1356
1433
|
# API (median ~550 chars, tail past 120k), so it is not in the list default.
|
|
1357
1434
|
SLED_OPPORTUNITIES_MINIMAL: Final = (
|
|
1358
1435
|
"opportunity_id,solicitation_number,solicitation_type,title,state,"
|
|
1359
|
-
"jurisdiction,agency,status,status_reason,posted_date,
|
|
1360
|
-
"source_url,has_documents,first_seen_at,
|
|
1436
|
+
"jurisdiction,agency,status,status_reason,delisted_at,posted_date,"
|
|
1437
|
+
"response_deadline,source_url,has_documents,first_seen_at,"
|
|
1438
|
+
"last_change_seen_at"
|
|
1361
1439
|
)
|
|
1362
1440
|
|
|
1363
1441
|
# Default for get_sled_opportunity(). `attachments(*)` deliberately does not
|
|
@@ -1367,8 +1445,8 @@ class ShapeConfig:
|
|
|
1367
1445
|
SLED_OPPORTUNITIES_COMPREHENSIVE: Final = (
|
|
1368
1446
|
"opportunity_id,solicitation_number,solicitation_type,"
|
|
1369
1447
|
"solicitation_type_source,title,description,state,jurisdiction,agency,"
|
|
1370
|
-
"status,status_reason,status_computed_at,source_status,
|
|
1371
|
-
"posted_date,response_deadline,response_deadline_original,"
|
|
1448
|
+
"status,status_reason,delisted_at,status_computed_at,source_status,"
|
|
1449
|
+
"source_url,posted_date,response_deadline,response_deadline_original,"
|
|
1372
1450
|
"bid_opening_date,bid_opening_raw,category_codes,has_documents,"
|
|
1373
1451
|
"first_seen_at,last_seen_at,last_change_seen_at,"
|
|
1374
1452
|
"organization(*),contact(*),meta(*),attachments(*),revisions(*)"
|
tango/shapes/explicit_schemas.py
CHANGED
|
@@ -763,6 +763,43 @@ PROTEST_SCHEMA: dict[str, FieldSchema] = {
|
|
|
763
763
|
}
|
|
764
764
|
|
|
765
765
|
|
|
766
|
+
CONTRACT_APPEAL_SCHEMA: dict[str, FieldSchema] = {
|
|
767
|
+
"uuid": FieldSchema(name="uuid", type=str, is_optional=True, is_list=False),
|
|
768
|
+
"board": FieldSchema(name="board", type=str, is_optional=True, is_list=False),
|
|
769
|
+
"docket_numbers": FieldSchema(name="docket_numbers", type=str, is_optional=True, is_list=True),
|
|
770
|
+
"docket_source": FieldSchema(name="docket_source", type=str, is_optional=True, is_list=False),
|
|
771
|
+
"docket_raw": FieldSchema(name="docket_raw", type=str, is_optional=True, is_list=False),
|
|
772
|
+
"decision_date": FieldSchema(name="decision_date", type=date, is_optional=True, is_list=False),
|
|
773
|
+
"decision_date_raw": FieldSchema(
|
|
774
|
+
name="decision_date_raw", type=str, is_optional=True, is_list=False
|
|
775
|
+
),
|
|
776
|
+
"decision_date_repaired": FieldSchema(
|
|
777
|
+
name="decision_date_repaired", type=bool, is_optional=True, is_list=False
|
|
778
|
+
),
|
|
779
|
+
"appellant": FieldSchema(name="appellant", type=str, is_optional=True, is_list=False),
|
|
780
|
+
"judge": FieldSchema(name="judge", type=str, is_optional=True, is_list=False),
|
|
781
|
+
"decision_type": FieldSchema(name="decision_type", type=str, is_optional=True, is_list=False),
|
|
782
|
+
"decision_type_raw": FieldSchema(
|
|
783
|
+
name="decision_type_raw", type=str, is_optional=True, is_list=False
|
|
784
|
+
),
|
|
785
|
+
"url": FieldSchema(name="url", type=str, is_optional=True, is_list=False),
|
|
786
|
+
"document_id": FieldSchema(name="document_id", type=str, is_optional=True, is_list=False),
|
|
787
|
+
"listing_url": FieldSchema(name="listing_url", type=str, is_optional=True, is_list=False),
|
|
788
|
+
"listing_year": FieldSchema(name="listing_year", type=int, is_optional=True, is_list=False),
|
|
789
|
+
"first_listed_at": FieldSchema(
|
|
790
|
+
name="first_listed_at", type=datetime, is_optional=True, is_list=False
|
|
791
|
+
),
|
|
792
|
+
"listed": FieldSchema(name="listed", type=bool, is_optional=True, is_list=False),
|
|
793
|
+
"text_status": FieldSchema(name="text_status", type=str, is_optional=True, is_list=False),
|
|
794
|
+
"text_char_count": FieldSchema(
|
|
795
|
+
name="text_char_count", type=int, is_optional=True, is_list=False
|
|
796
|
+
),
|
|
797
|
+
# Enterprise-only. The key is absent rather than null below that tier, so the
|
|
798
|
+
# schema still carries it — the SDK must not reject a shape the API accepts.
|
|
799
|
+
"decision_text": FieldSchema(name="decision_text", type=str, is_optional=True, is_list=False),
|
|
800
|
+
}
|
|
801
|
+
|
|
802
|
+
|
|
766
803
|
AGENCY_SCHEMA: dict[str, FieldSchema] = {
|
|
767
804
|
"abbreviation": FieldSchema(name="abbreviation", type=str, is_optional=True, is_list=False),
|
|
768
805
|
"code": FieldSchema(name="code", type=str, is_optional=False, is_list=False),
|
|
@@ -1507,6 +1544,7 @@ EXPLICIT_SCHEMAS: dict[str, dict[str, FieldSchema]] = {
|
|
|
1507
1544
|
"Notice": NOTICE_SCHEMA,
|
|
1508
1545
|
"Protest": PROTEST_SCHEMA,
|
|
1509
1546
|
"ProtestDocket": PROTEST_DOCKET_SCHEMA,
|
|
1547
|
+
"ContractAppeal": CONTRACT_APPEAL_SCHEMA,
|
|
1510
1548
|
"Agency": AGENCY_SCHEMA,
|
|
1511
1549
|
"Grant": GRANT_SCHEMA,
|
|
1512
1550
|
# Vehicles (Awards)
|
|
@@ -81,7 +81,20 @@ ARCHIVE_SCHEMA: dict[str, FieldSchema] = {
|
|
|
81
81
|
}
|
|
82
82
|
|
|
83
83
|
ATTACHMENTS_SCHEMA: dict[str, FieldSchema] = {
|
|
84
|
+
"doc_name": FieldSchema(name="doc_name", type=str, is_optional=True, is_list=False),
|
|
85
|
+
"doc_path": FieldSchema(name="doc_path", type=str, is_optional=True, is_list=False),
|
|
86
|
+
"doc_seq_num": FieldSchema(name="doc_seq_num", type=str, is_optional=True, is_list=False),
|
|
87
|
+
"doc_session_date": FieldSchema(
|
|
88
|
+
name="doc_session_date", type=date, is_optional=True, is_list=False
|
|
89
|
+
),
|
|
90
|
+
"doc_type": FieldSchema(name="doc_type", type=str, is_optional=True, is_list=False),
|
|
91
|
+
"is_link": FieldSchema(name="is_link", type=bool, is_optional=True, is_list=False),
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
ATTACHMENTS2_SCHEMA: dict[str, FieldSchema] = {
|
|
84
95
|
"attachment_id": FieldSchema(name="attachment_id", type=str, is_optional=True, is_list=False),
|
|
96
|
+
"doc_role": FieldSchema(name="doc_role", type=str, is_optional=True, is_list=False),
|
|
97
|
+
"doc_role_alt": FieldSchema(name="doc_role_alt", type=str, is_optional=True, is_list=False),
|
|
85
98
|
"extracted_text": FieldSchema(name="extracted_text", type=str, is_optional=True, is_list=False),
|
|
86
99
|
"file_size": FieldSchema(name="file_size", type=int, is_optional=True, is_list=False),
|
|
87
100
|
"mime_type": FieldSchema(name="mime_type", type=str, is_optional=True, is_list=False),
|
|
@@ -92,8 +105,10 @@ ATTACHMENTS_SCHEMA: dict[str, FieldSchema] = {
|
|
|
92
105
|
"url": FieldSchema(name="url", type=str, is_optional=True, is_list=False),
|
|
93
106
|
}
|
|
94
107
|
|
|
95
|
-
|
|
108
|
+
ATTACHMENTS3_SCHEMA: dict[str, FieldSchema] = {
|
|
96
109
|
"attachment_id": FieldSchema(name="attachment_id", type=str, is_optional=True, is_list=False),
|
|
110
|
+
"doc_role": FieldSchema(name="doc_role", type=str, is_optional=True, is_list=False),
|
|
111
|
+
"doc_role_alt": FieldSchema(name="doc_role_alt", type=str, is_optional=True, is_list=False),
|
|
97
112
|
"extracted_text": FieldSchema(name="extracted_text", type=str, is_optional=True, is_list=False),
|
|
98
113
|
"file_size": FieldSchema(name="file_size", type=int, is_optional=True, is_list=False),
|
|
99
114
|
"mime_type": FieldSchema(name="mime_type", type=str, is_optional=True, is_list=False),
|
|
@@ -104,7 +119,7 @@ ATTACHMENTS2_SCHEMA: dict[str, FieldSchema] = {
|
|
|
104
119
|
"url": FieldSchema(name="url", type=str, is_optional=True, is_list=False),
|
|
105
120
|
}
|
|
106
121
|
|
|
107
|
-
|
|
122
|
+
ATTACHMENTS4_SCHEMA: dict[str, FieldSchema] = {
|
|
108
123
|
"char_count": FieldSchema(name="char_count", type=int, is_optional=True, is_list=False),
|
|
109
124
|
"checksum": FieldSchema(name="checksum", type=str, is_optional=True, is_list=False),
|
|
110
125
|
"download_status": FieldSchema(
|
|
@@ -124,13 +139,26 @@ ATTACHMENTS3_SCHEMA: dict[str, FieldSchema] = {
|
|
|
124
139
|
),
|
|
125
140
|
"mime_type": FieldSchema(name="mime_type", type=str, is_optional=True, is_list=False),
|
|
126
141
|
"name": FieldSchema(name="name", type=str, is_optional=True, is_list=False),
|
|
127
|
-
"pages": FieldSchema(name="pages", type=
|
|
128
|
-
"size_bytes": FieldSchema(name="size_bytes", type=
|
|
142
|
+
"pages": FieldSchema(name="pages", type=int, is_optional=True, is_list=False),
|
|
143
|
+
"size_bytes": FieldSchema(name="size_bytes", type=int, is_optional=True, is_list=False),
|
|
129
144
|
"word_count": FieldSchema(name="word_count", type=int, is_optional=True, is_list=False),
|
|
130
145
|
}
|
|
131
146
|
|
|
132
|
-
|
|
147
|
+
ATTACHMENTS5_SCHEMA: dict[str, FieldSchema] = {
|
|
133
148
|
"attachment_id": FieldSchema(name="attachment_id", type=str, is_optional=True, is_list=False),
|
|
149
|
+
"file_size": FieldSchema(name="file_size", type=str, is_optional=True, is_list=False),
|
|
150
|
+
"mime_type": FieldSchema(name="mime_type", type=str, is_optional=True, is_list=False),
|
|
151
|
+
"name": FieldSchema(name="name", type=str, is_optional=True, is_list=False),
|
|
152
|
+
"posted_date": FieldSchema(name="posted_date", type=date, is_optional=True, is_list=False),
|
|
153
|
+
"resource_id": FieldSchema(name="resource_id", type=str, is_optional=True, is_list=False),
|
|
154
|
+
"type": FieldSchema(name="type", type=str, is_optional=True, is_list=False),
|
|
155
|
+
"url": FieldSchema(name="url", type=str, is_optional=True, is_list=False),
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
ATTACHMENTS6_SCHEMA: dict[str, FieldSchema] = {
|
|
159
|
+
"attachment_id": FieldSchema(name="attachment_id", type=str, is_optional=True, is_list=False),
|
|
160
|
+
"doc_role": FieldSchema(name="doc_role", type=str, is_optional=True, is_list=False),
|
|
161
|
+
"doc_role_alt": FieldSchema(name="doc_role_alt", type=str, is_optional=True, is_list=False),
|
|
134
162
|
"extracted_text": FieldSchema(name="extracted_text", type=str, is_optional=True, is_list=False),
|
|
135
163
|
"file_size": FieldSchema(name="file_size", type=str, is_optional=True, is_list=False),
|
|
136
164
|
"mime_type": FieldSchema(name="mime_type", type=str, is_optional=True, is_list=False),
|
|
@@ -375,8 +403,8 @@ DOCUMENTS_SCHEMA: dict[str, FieldSchema] = {
|
|
|
375
403
|
}
|
|
376
404
|
|
|
377
405
|
ESTIMATED_VALUE_SCHEMA: dict[str, FieldSchema] = {
|
|
378
|
-
"max": FieldSchema(name="max", type=
|
|
379
|
-
"min": FieldSchema(name="min", type=
|
|
406
|
+
"max": FieldSchema(name="max", type=Decimal, is_optional=True, is_list=False),
|
|
407
|
+
"min": FieldSchema(name="min", type=Decimal, is_optional=True, is_list=False),
|
|
380
408
|
"raw": FieldSchema(name="raw", type=str, is_optional=True, is_list=False),
|
|
381
409
|
}
|
|
382
410
|
|
|
@@ -624,8 +652,11 @@ META3_SCHEMA: dict[str, FieldSchema] = {
|
|
|
624
652
|
"attachment_count": FieldSchema(
|
|
625
653
|
name="attachment_count", type=int, is_optional=True, is_list=False
|
|
626
654
|
),
|
|
655
|
+
"jurisdiction_declared": FieldSchema(
|
|
656
|
+
name="jurisdiction_declared", type=bool, is_optional=True, is_list=False
|
|
657
|
+
),
|
|
627
658
|
"last_change_source_declared": FieldSchema(
|
|
628
|
-
name="last_change_source_declared", type=
|
|
659
|
+
name="last_change_source_declared", type=bool, is_optional=True, is_list=False
|
|
629
660
|
),
|
|
630
661
|
"last_revision_kind": FieldSchema(
|
|
631
662
|
name="last_revision_kind", type=str, is_optional=True, is_list=False
|
|
@@ -942,13 +973,13 @@ RESOLVED_PROTESTER_SCHEMA: dict[str, FieldSchema] = {
|
|
|
942
973
|
}
|
|
943
974
|
|
|
944
975
|
REVISIONS_SCHEMA: dict[str, FieldSchema] = {
|
|
945
|
-
"changed_fields": FieldSchema(name="changed_fields", type=str, is_optional=True, is_list=
|
|
946
|
-
"changes": FieldSchema(name="changes", type=
|
|
976
|
+
"changed_fields": FieldSchema(name="changed_fields", type=str, is_optional=True, is_list=True),
|
|
977
|
+
"changes": FieldSchema(name="changes", type=dict, is_optional=True, is_list=False),
|
|
947
978
|
"kind": FieldSchema(name="kind", type=str, is_optional=True, is_list=False),
|
|
948
979
|
"observed_at": FieldSchema(name="observed_at", type=datetime, is_optional=True, is_list=False),
|
|
949
|
-
"sequence": FieldSchema(name="sequence", type=
|
|
980
|
+
"sequence": FieldSchema(name="sequence", type=int, is_optional=True, is_list=False),
|
|
950
981
|
"source_declared": FieldSchema(
|
|
951
|
-
name="source_declared", type=
|
|
982
|
+
name="source_declared", type=bool, is_optional=True, is_list=False
|
|
952
983
|
),
|
|
953
984
|
}
|
|
954
985
|
|
|
@@ -1087,6 +1118,8 @@ GENERATED_NESTED: dict[str, dict[str, FieldSchema]] = {
|
|
|
1087
1118
|
"Attachments2": ATTACHMENTS2_SCHEMA,
|
|
1088
1119
|
"Attachments3": ATTACHMENTS3_SCHEMA,
|
|
1089
1120
|
"Attachments4": ATTACHMENTS4_SCHEMA,
|
|
1121
|
+
"Attachments5": ATTACHMENTS5_SCHEMA,
|
|
1122
|
+
"Attachments6": ATTACHMENTS6_SCHEMA,
|
|
1090
1123
|
"Awardee": AWARDEE_SCHEMA,
|
|
1091
1124
|
"AwardingOffice": AWARDING_OFFICE_SCHEMA,
|
|
1092
1125
|
"AwardingOffice2": AWARDING_OFFICE2_SCHEMA,
|
|
@@ -2185,7 +2218,7 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
|
|
|
2185
2218
|
type=dict,
|
|
2186
2219
|
is_optional=True,
|
|
2187
2220
|
is_list=True,
|
|
2188
|
-
nested_model="
|
|
2221
|
+
nested_model="Attachments2",
|
|
2189
2222
|
),
|
|
2190
2223
|
"meta": FieldSchema(
|
|
2191
2224
|
name="meta", type=dict, is_optional=True, is_list=False, nested_model="Meta"
|
|
@@ -2433,7 +2466,7 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
|
|
|
2433
2466
|
type=dict,
|
|
2434
2467
|
is_optional=True,
|
|
2435
2468
|
is_list=False,
|
|
2436
|
-
nested_model="
|
|
2469
|
+
nested_model="Attachments6",
|
|
2437
2470
|
),
|
|
2438
2471
|
"department": FieldSchema(
|
|
2439
2472
|
name="department",
|
|
@@ -2751,7 +2784,7 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
|
|
|
2751
2784
|
),
|
|
2752
2785
|
"description": FieldSchema(name="description", type=str, is_optional=True, is_list=False),
|
|
2753
2786
|
"estimated_advertisement_date": FieldSchema(
|
|
2754
|
-
name="estimated_advertisement_date", type=
|
|
2787
|
+
name="estimated_advertisement_date", type=datetime, is_optional=True, is_list=False
|
|
2755
2788
|
),
|
|
2756
2789
|
"estimated_advertisement_raw": FieldSchema(
|
|
2757
2790
|
name="estimated_advertisement_raw", type=str, is_optional=True, is_list=False
|
|
@@ -2805,17 +2838,17 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
|
|
|
2805
2838
|
name="attachments",
|
|
2806
2839
|
type=dict,
|
|
2807
2840
|
is_optional=True,
|
|
2808
|
-
is_list=
|
|
2809
|
-
nested_model="
|
|
2841
|
+
is_list=True,
|
|
2842
|
+
nested_model="Attachments4",
|
|
2810
2843
|
),
|
|
2811
2844
|
"bid_opening_date": FieldSchema(
|
|
2812
|
-
name="bid_opening_date", type=
|
|
2845
|
+
name="bid_opening_date", type=datetime, is_optional=True, is_list=False
|
|
2813
2846
|
),
|
|
2814
2847
|
"bid_opening_raw": FieldSchema(
|
|
2815
2848
|
name="bid_opening_raw", type=str, is_optional=True, is_list=False
|
|
2816
2849
|
),
|
|
2817
2850
|
"category_codes": FieldSchema(
|
|
2818
|
-
name="category_codes", type=
|
|
2851
|
+
name="category_codes", type=dict, is_optional=True, is_list=True
|
|
2819
2852
|
),
|
|
2820
2853
|
"contact": FieldSchema(
|
|
2821
2854
|
name="contact",
|
|
@@ -2824,6 +2857,9 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
|
|
|
2824
2857
|
is_list=False,
|
|
2825
2858
|
nested_model="GrantorContact",
|
|
2826
2859
|
),
|
|
2860
|
+
"delisted_at": FieldSchema(
|
|
2861
|
+
name="delisted_at", type=datetime, is_optional=True, is_list=False
|
|
2862
|
+
),
|
|
2827
2863
|
"description": FieldSchema(name="description", type=str, is_optional=True, is_list=False),
|
|
2828
2864
|
"first_seen_at": FieldSchema(
|
|
2829
2865
|
name="first_seen_at", type=datetime, is_optional=True, is_list=False
|
|
@@ -2852,16 +2888,18 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
|
|
|
2852
2888
|
is_list=False,
|
|
2853
2889
|
nested_model="Organization3",
|
|
2854
2890
|
),
|
|
2855
|
-
"posted_date": FieldSchema(
|
|
2891
|
+
"posted_date": FieldSchema(
|
|
2892
|
+
name="posted_date", type=datetime, is_optional=True, is_list=False
|
|
2893
|
+
),
|
|
2856
2894
|
"raw": FieldSchema(name="raw", type=dict, is_optional=True, is_list=False),
|
|
2857
2895
|
"response_deadline": FieldSchema(
|
|
2858
|
-
name="response_deadline", type=
|
|
2896
|
+
name="response_deadline", type=datetime, is_optional=True, is_list=False
|
|
2859
2897
|
),
|
|
2860
2898
|
"response_deadline_original": FieldSchema(
|
|
2861
|
-
name="response_deadline_original", type=
|
|
2899
|
+
name="response_deadline_original", type=datetime, is_optional=True, is_list=False
|
|
2862
2900
|
),
|
|
2863
2901
|
"revisions": FieldSchema(
|
|
2864
|
-
name="revisions", type=dict, is_optional=True, is_list=
|
|
2902
|
+
name="revisions", type=dict, is_optional=True, is_list=True, nested_model="Revisions"
|
|
2865
2903
|
),
|
|
2866
2904
|
"snippet": FieldSchema(name="snippet", type=str, is_optional=True, is_list=False),
|
|
2867
2905
|
"solicitation_number": FieldSchema(
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
tango/__init__.py,sha256=
|
|
2
|
-
tango/client.py,sha256=
|
|
1
|
+
tango/__init__.py,sha256=P7q3qdG_74A9OKteDHRNyH1pD_VuPOoBFGSFZECbVA0,2300
|
|
2
|
+
tango/client.py,sha256=R69lCC6XTo42lVbuWXqEJNyO0-tro0IthgwyWiuJs6Y,220172
|
|
3
3
|
tango/exceptions.py,sha256=B1t27BBxHcPglAfJQyan5khNEYNAyF6Wkp2EmPMdRxM,3858
|
|
4
|
-
tango/models.py,sha256=
|
|
4
|
+
tango/models.py,sha256=X5ijWFnz05kgobqoPdtxRxWWW_hVfFZRtCGksbgQW-o,58377
|
|
5
5
|
tango/shapes/__init__.py,sha256=7ea1WU74jp4znhNw-gXruag6m6eyPZtbVgbDFmFUWro,1072
|
|
6
|
-
tango/shapes/explicit_schemas.py,sha256=
|
|
6
|
+
tango/shapes/explicit_schemas.py,sha256=WvkKaEkW01HgO56In-8vNlxZeoEkJJEYjZOUyrGItU4,73775
|
|
7
7
|
tango/shapes/factory.py,sha256=uDPhnp6VVzrLBKodxteZy5AcU43juEv-qKVRWth51j0,31550
|
|
8
|
-
tango/shapes/generated_overlay.py,sha256=
|
|
8
|
+
tango/shapes/generated_overlay.py,sha256=wv3Z4MjsU7xyk8EKzUNG1BgfAxgukGcsQ_5QkPPJyvA,137957
|
|
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.
|
|
20
|
-
tango_python-1.
|
|
21
|
-
tango_python-1.
|
|
22
|
-
tango_python-1.
|
|
23
|
-
tango_python-1.
|
|
19
|
+
tango_python-1.7.0.dist-info/METADATA,sha256=1Jf7m5SbI4g54SfWLy1LQxFVz-W2LA1uLbYA3MBkBlE,21779
|
|
20
|
+
tango_python-1.7.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
21
|
+
tango_python-1.7.0.dist-info/entry_points.txt,sha256=kGLUbglUjuaAqEFvOZ1QuSW0vWb6VeSpCIFKaOFkKoQ,50
|
|
22
|
+
tango_python-1.7.0.dist-info/licenses/LICENSE,sha256=j2kYVHMwTkoGn3ZNScnrdIueG0k2XzB_LCPFoyBc2wk,1064
|
|
23
|
+
tango_python-1.7.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|