tango-python 1.14.0__py3-none-any.whl → 1.16.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/models.py +23 -6
- tango/shapes/explicit_schemas.py +2 -0
- tango/shapes/generated_overlay.py +4 -0
- {tango_python-1.14.0.dist-info → tango_python-1.16.0.dist-info}/METADATA +10 -1
- {tango_python-1.14.0.dist-info → tango_python-1.16.0.dist-info}/RECORD +9 -9
- {tango_python-1.14.0.dist-info → tango_python-1.16.0.dist-info}/WHEEL +0 -0
- {tango_python-1.14.0.dist-info → tango_python-1.16.0.dist-info}/entry_points.txt +0 -0
- {tango_python-1.14.0.dist-info → tango_python-1.16.0.dist-info}/licenses/LICENSE +0 -0
tango/__init__.py
CHANGED
tango/models.py
CHANGED
|
@@ -571,6 +571,12 @@ class Opportunity:
|
|
|
571
571
|
The award fields (``award_date``, ``award_amount``, ``awardee``, ``awardee_uei``) are filled only where SAM.gov posted an award notice, and ``award_amount`` is the text SAM.gov published, not a number.
|
|
572
572
|
SAM.gov often posts an award as its own opportunity; when that award notice references its solicitation, ``solicitation_opportunity_id`` points back to it, and the solicitation's ``awards(...)`` expand lists up to ten of the most recent linked awards, with ``award_count`` giving the full count.
|
|
573
573
|
An award notice that does not reference its solicitation is not linked.
|
|
574
|
+
|
|
575
|
+
The ``meta(...)`` expand counts an opportunity's attachments three ways (Tango API 5.9.0).
|
|
576
|
+
An attachment's ``type`` is ``file`` (a document attached to the notice; only files have extracted text) or ``link`` (a URL the notice lists).
|
|
577
|
+
``meta.files_count`` and ``meta.links_count`` count each, and ``meta.attachments_count`` counts every attachment, links included.
|
|
578
|
+
An attachment of any other type counts only in the total, so files plus links need not equal it.
|
|
579
|
+
``files_count`` and ``links_count`` are null until the record has been counted, so treat null as unknown, not zero.
|
|
574
580
|
"""
|
|
575
581
|
|
|
576
582
|
opportunity_id: str
|
|
@@ -600,6 +606,10 @@ class Notice:
|
|
|
600
606
|
Both must be named, e.g. ``attachments(name,url,doc_role,doc_role_alt)``, because ``attachments(*)`` does not include them.
|
|
601
607
|
An attachment Tango has not classified omits both keys rather than returning null, so read them with ``.get()``.
|
|
602
608
|
A Free-plan request that names them gets the response without them, plus an entry in ``meta.upgrade_hints``.
|
|
609
|
+
|
|
610
|
+
``file_count`` and ``link_count`` (Tango API 5.9.0) split ``attachment_count`` by attachment ``type``: ``file`` is a document attached to the notice (only files have extracted text) and ``link`` is a URL the notice lists.
|
|
611
|
+
``attachment_count`` still counts every attachment, links included, and an attachment of any other type counts only there, so files plus links need not equal it.
|
|
612
|
+
``file_count`` and ``link_count`` are null until the notice has been counted, so treat null as unknown, not zero.
|
|
603
613
|
"""
|
|
604
614
|
|
|
605
615
|
notice_id: str
|
|
@@ -613,6 +623,9 @@ class Notice:
|
|
|
613
623
|
award_amount: str | None = None
|
|
614
624
|
awardee: str | None = None
|
|
615
625
|
awardee_uei: str | None = None
|
|
626
|
+
attachment_count: int | None = None
|
|
627
|
+
file_count: int | None = None
|
|
628
|
+
link_count: int | None = None
|
|
616
629
|
|
|
617
630
|
|
|
618
631
|
@dataclass
|
|
@@ -1352,6 +1365,10 @@ class EbuyAttachment:
|
|
|
1352
1365
|
"""Schema definition for one entry in an eBuy request's ``attachments`` (not used for instances).
|
|
1353
1366
|
|
|
1354
1367
|
``is_link=True`` means the entry is an outbound URL in ``doc_path`` with no stored document behind it, so ``get_ebuy_attachment_url()`` raises ``TangoAttachmentLinkError`` for it.
|
|
1368
|
+
|
|
1369
|
+
``extracted_text`` (Tango API 5.9.1) is the text extracted from the attachment's document.
|
|
1370
|
+
It must be named, e.g. ``attachments(doc_seq_num,doc_name,extracted_text)``, because neither the default response nor ``attachments(*)`` includes it.
|
|
1371
|
+
An attachment with no text (a link, an empty scan, or a document not yet extracted) omits the key from the API response rather than returning null; the SDK's shaped result reads that as ``None``.
|
|
1355
1372
|
"""
|
|
1356
1373
|
|
|
1357
1374
|
doc_seq_num: int | None = None
|
|
@@ -1360,6 +1377,7 @@ class EbuyAttachment:
|
|
|
1360
1377
|
doc_path: str | None = None
|
|
1361
1378
|
is_link: bool | None = None
|
|
1362
1379
|
doc_session_date: datetime | None = None
|
|
1380
|
+
extracted_text: str | None = None
|
|
1363
1381
|
|
|
1364
1382
|
|
|
1365
1383
|
class EbuyRequest:
|
|
@@ -1454,11 +1472,10 @@ class PaginatedResponse[T]:
|
|
|
1454
1472
|
results: List of result items (type depends on shape parameter)
|
|
1455
1473
|
cursor: Cursor token for cursor-based pagination (None if not available)
|
|
1456
1474
|
meta: Response-level metadata the API attached to this page, when present.
|
|
1457
|
-
Currently carries agency-filter diagnostics: ``resolved_filters`` maps
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
:meth:`agency_warnings` and :meth:`unresolved_agency_tokens`.
|
|
1475
|
+
Currently carries agency-filter diagnostics: ``resolved_filters`` maps each agency filter to the organizations its ``|``-separated tokens resolved to (or ``None``), and ``warnings`` lists human-readable notes about tokens that were dropped or matched loosely.
|
|
1476
|
+
Each ``resolved_filters`` entry that resolved also carries ``matched_by`` (Tango API 5.9.0+), saying how the token matched: ``"key"`` (an organization UUID), ``"code"`` (a 3-digit CGAC or 4-digit FPDS code), ``"name"`` (the organization's name, including a department's everyday name, a spelling variant or a rename), ``"alias"`` (an abbreviation or the organization's own alias) or ``"fuzzy"`` (a looser text match, worth checking against the resolved ``name``).
|
|
1477
|
+
An entry that did not resolve has no ``matched_by``.
|
|
1478
|
+
See :meth:`agency_warnings`, :meth:`unresolved_agency_tokens` and :meth:`resolved_agencies`.
|
|
1462
1479
|
page_metadata: Always ``None`` — the API has never emitted a
|
|
1463
1480
|
``page_metadata`` key. Retained so existing attribute access keeps
|
|
1464
1481
|
working; use ``meta`` instead.
|
|
@@ -1648,7 +1665,7 @@ class ShapeConfig:
|
|
|
1648
1665
|
"link_count,last_seen"
|
|
1649
1666
|
)
|
|
1650
1667
|
|
|
1651
|
-
# Default for get_ebuy_request(). Mirrors the API's own retrieve default; the attachment fields are named rather than `attachments(*)` so their dates parse.
|
|
1668
|
+
# Default for get_ebuy_request(). Mirrors the API's own retrieve default; the attachment fields are named rather than `attachments(*)` so their dates parse. `extracted_text` is left out because document bodies are large and the API serves them only when named.
|
|
1652
1669
|
EBUY_REQUESTS_COMPREHENSIVE: Final = (
|
|
1653
1670
|
"rfq_id,request_type,title,description,schedule,sin,status,buyer_name,"
|
|
1654
1671
|
"buyer_agency,buyer_agency_code,buyer_email,buyer_user_id,reference_number,"
|
tango/shapes/explicit_schemas.py
CHANGED
|
@@ -886,6 +886,8 @@ EBUY_ATTACHMENT_SCHEMA: dict[str, FieldSchema] = {
|
|
|
886
886
|
"doc_session_date": FieldSchema(
|
|
887
887
|
name="doc_session_date", type=datetime, is_optional=True, is_list=False
|
|
888
888
|
),
|
|
889
|
+
# Only when named in the shape; the API omits the key for an attachment with no text.
|
|
890
|
+
"extracted_text": FieldSchema(name="extracted_text", type=str, is_optional=True, is_list=False),
|
|
889
891
|
}
|
|
890
892
|
|
|
891
893
|
|
|
@@ -641,6 +641,8 @@ META2_SCHEMA: dict[str, FieldSchema] = {
|
|
|
641
641
|
"attachments_count": FieldSchema(
|
|
642
642
|
name="attachments_count", type=int, is_optional=True, is_list=False
|
|
643
643
|
),
|
|
644
|
+
"files_count": FieldSchema(name="files_count", type=int, is_optional=True, is_list=False),
|
|
645
|
+
"links_count": FieldSchema(name="links_count", type=int, is_optional=True, is_list=False),
|
|
644
646
|
"notice_type": FieldSchema(
|
|
645
647
|
name="notice_type", type=dict, is_optional=True, is_list=False, nested_model="NoticeType"
|
|
646
648
|
),
|
|
@@ -2252,6 +2254,8 @@ GENERATED_OVERLAY: dict[str, dict[str, FieldSchema]] = {
|
|
|
2252
2254
|
"award_date": FieldSchema(name="award_date", type=date, is_optional=True, is_list=False),
|
|
2253
2255
|
"awardee": FieldSchema(name="awardee", type=str, is_optional=True, is_list=False),
|
|
2254
2256
|
"awardee_uei": FieldSchema(name="awardee_uei", type=str, is_optional=True, is_list=False),
|
|
2257
|
+
"file_count": FieldSchema(name="file_count", type=int, is_optional=True, is_list=False),
|
|
2258
|
+
"link_count": FieldSchema(name="link_count", type=int, is_optional=True, is_list=False),
|
|
2255
2259
|
"meta": FieldSchema(
|
|
2256
2260
|
name="meta", type=dict, is_optional=True, is_list=False, nested_model="Meta"
|
|
2257
2261
|
),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: tango-python
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.16.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
|
|
@@ -219,6 +219,15 @@ for warning in response.agency_warnings:
|
|
|
219
219
|
print(warning)
|
|
220
220
|
```
|
|
221
221
|
|
|
222
|
+
Each entry of `response.meta["resolved_filters"][<filter name>]` that resolved also says how its token matched, in `matched_by` (Tango API 5.9.0+): `key` (an organization UUID), `code` (a 3-digit CGAC or 4-digit FPDS code), `name` (the organization's name, including a department's everyday name, a spelling variant or a rename), `alias` (an abbreviation or the organization's own alias) or `fuzzy` (a looser text match).
|
|
223
|
+
A `fuzzy` match is the one worth checking against the resolved name:
|
|
224
|
+
|
|
225
|
+
```python
|
|
226
|
+
for entry in response.meta["resolved_filters"].get("awarding_agency", []):
|
|
227
|
+
if entry.get("matched_by") == "fuzzy":
|
|
228
|
+
print(f"{entry['token']!r} loosely matched {entry['resolved']['name']}")
|
|
229
|
+
```
|
|
230
|
+
|
|
222
231
|
If *every* token for a filter fails to resolve, the API returns `400` and the SDK raises
|
|
223
232
|
`TangoValidationError` naming the offending value, rather than an empty page.
|
|
224
233
|
|
|
@@ -1,11 +1,11 @@
|
|
|
1
|
-
tango/__init__.py,sha256=
|
|
1
|
+
tango/__init__.py,sha256=_eYomSjLflugfMOs-MzscP6WX7UWlC63YvuwqX87PU4,2739
|
|
2
2
|
tango/client.py,sha256=1Z748iPEPdVi8_Sq9XPES8RnPdnugEwL3yAgV7Cvvt0,243419
|
|
3
3
|
tango/exceptions.py,sha256=oPiLCccBoWLK5SjHkzP-oI6mUD9twEeKSvEuLV5h01I,4224
|
|
4
|
-
tango/models.py,sha256=
|
|
4
|
+
tango/models.py,sha256=2kyX6ogMWVNfsBbh1ah5hUgWFH1EQuArwUCHzrHRY4Y,72598
|
|
5
5
|
tango/shapes/__init__.py,sha256=7ea1WU74jp4znhNw-gXruag6m6eyPZtbVgbDFmFUWro,1072
|
|
6
|
-
tango/shapes/explicit_schemas.py,sha256=
|
|
6
|
+
tango/shapes/explicit_schemas.py,sha256=RCsUOVKe89WYPORVSAPKWX6u3If1DdI_7a94VTAbzrI,84525
|
|
7
7
|
tango/shapes/factory.py,sha256=uDPhnp6VVzrLBKodxteZy5AcU43juEv-qKVRWth51j0,31550
|
|
8
|
-
tango/shapes/generated_overlay.py,sha256=
|
|
8
|
+
tango/shapes/generated_overlay.py,sha256=7UwqTeqNW4NIuwsQlKVZgBlH2biEVBdEZ4z2IwiS1k4,141244
|
|
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.16.0.dist-info/METADATA,sha256=cAmejqQdWIlO6x7flbQye3-EktIp4eN2Kjdyp4sqlyQ,22824
|
|
20
|
+
tango_python-1.16.0.dist-info/WHEEL,sha256=W3fkpkm7-wf9vBI5Z-7s0eWkeM-spu78I8Neb98DeEg,87
|
|
21
|
+
tango_python-1.16.0.dist-info/entry_points.txt,sha256=kGLUbglUjuaAqEFvOZ1QuSW0vWb6VeSpCIFKaOFkKoQ,50
|
|
22
|
+
tango_python-1.16.0.dist-info/licenses/LICENSE,sha256=j2kYVHMwTkoGn3ZNScnrdIueG0k2XzB_LCPFoyBc2wk,1064
|
|
23
|
+
tango_python-1.16.0.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|