tango-python 0.4.1__py3-none-any.whl → 0.4.2__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/client.py CHANGED
@@ -31,6 +31,7 @@ from tango.models import (
31
31
  Opportunity,
32
32
  Organization,
33
33
  PaginatedResponse,
34
+ Protest,
34
35
  SearchFilters,
35
36
  ShapeConfig,
36
37
  Subaward,
@@ -943,32 +944,6 @@ class TangoClient:
943
944
  page_metadata=data.get("page_metadata"),
944
945
  )
945
946
 
946
- def get_idv_summary(self, identifier: str) -> dict[str, Any]:
947
- """Get a summary for an IDV solicitation identifier (`/api/idvs/{identifier}/summary/`)."""
948
- return self._get(f"/api/idvs/{identifier}/summary/")
949
-
950
- def list_idv_summary_awards(
951
- self,
952
- identifier: str,
953
- limit: int = 25,
954
- cursor: str | None = None,
955
- ordering: str | None = None,
956
- ) -> PaginatedResponse:
957
- """List awards under an IDV summary (`/api/idvs/{identifier}/summary/awards/`)."""
958
- params: dict[str, Any] = {"limit": min(limit, 100)}
959
- if cursor:
960
- params["cursor"] = cursor
961
- if ordering:
962
- params["ordering"] = ordering
963
- data = self._get(f"/api/idvs/{identifier}/summary/awards/", params)
964
- return PaginatedResponse(
965
- count=int(data.get("count") or len(data.get("results") or [])),
966
- next=data.get("next"),
967
- previous=data.get("previous"),
968
- results=data.get("results") or [],
969
- page_metadata=data.get("page_metadata"),
970
- )
971
-
972
947
  def list_otas(
973
948
  self,
974
949
  limit: int = 25,
@@ -1859,6 +1834,129 @@ class TangoClient:
1859
1834
  results=results,
1860
1835
  )
1861
1836
 
1837
+ # Protest endpoints
1838
+ # See https://tango.makegov.com/docs/api-reference/protests.md
1839
+ # Note: Protests API does not support ordering (returns 400 if provided).
1840
+ # Use shape=...,dockets(...) to request nested dockets.
1841
+ def list_protests(
1842
+ self,
1843
+ page: int = 1,
1844
+ limit: int = 25,
1845
+ shape: str | None = None,
1846
+ flat: bool = False,
1847
+ flat_lists: bool = False,
1848
+ source_system: str | None = None,
1849
+ outcome: str | None = None,
1850
+ case_type: str | None = None,
1851
+ agency: str | None = None,
1852
+ case_number: str | None = None,
1853
+ solicitation_number: str | None = None,
1854
+ protester: str | None = None,
1855
+ filed_date_after: str | None = None,
1856
+ filed_date_before: str | None = None,
1857
+ decision_date_after: str | None = None,
1858
+ decision_date_before: str | None = None,
1859
+ search: str | None = None,
1860
+ ) -> PaginatedResponse:
1861
+ """
1862
+ List bid protests.
1863
+
1864
+ Returns case-level protest records. Use shape=...,dockets(...) to include
1865
+ nested dockets. API reference: https://tango.makegov.com/docs/api-reference/protests.md
1866
+
1867
+ Args:
1868
+ page: Page number
1869
+ limit: Results per page (max 100)
1870
+ shape: Response shape string (defaults to minimal shape)
1871
+ flat: If True, flatten nested objects in shaped response
1872
+ flat_lists: If True, flatten arrays using indexed keys
1873
+ source_system: Filter by source system (e.g. gao)
1874
+ outcome: Filter by outcome (e.g. Denied, Dismissed, Withdrawn, Sustained)
1875
+ case_type: Filter by case type
1876
+ agency: Filter by protested agency text
1877
+ case_number: Filter by case number (e.g. b-423274)
1878
+ solicitation_number: Filter by exact solicitation number
1879
+ protester: Filter by protester name text
1880
+ filed_date_after: Filed date on or after
1881
+ filed_date_before: Filed date on or before
1882
+ decision_date_after: Decision date on or after
1883
+ decision_date_before: Decision date on or before
1884
+ search: Full-text search over protest searchable fields
1885
+ """
1886
+ params: dict[str, Any] = {"page": page, "limit": min(limit, 100)}
1887
+
1888
+ if shape is None:
1889
+ shape = ShapeConfig.PROTESTS_MINIMAL
1890
+ if shape:
1891
+ params["shape"] = shape
1892
+ if flat:
1893
+ params["flat"] = "true"
1894
+ if flat_lists:
1895
+ params["flat_lists"] = "true"
1896
+
1897
+ for key, val in (
1898
+ ("source_system", source_system),
1899
+ ("outcome", outcome),
1900
+ ("case_type", case_type),
1901
+ ("agency", agency),
1902
+ ("case_number", case_number),
1903
+ ("solicitation_number", solicitation_number),
1904
+ ("protester", protester),
1905
+ ("filed_date_after", filed_date_after),
1906
+ ("filed_date_before", filed_date_before),
1907
+ ("decision_date_after", decision_date_after),
1908
+ ("decision_date_before", decision_date_before),
1909
+ ("search", search),
1910
+ ):
1911
+ if val is not None:
1912
+ params[key] = val
1913
+
1914
+ data = self._get("/api/protests/", params)
1915
+
1916
+ results = [
1917
+ self._parse_response_with_shape(item, shape, Protest, flat, flat_lists)
1918
+ for item in data["results"]
1919
+ ]
1920
+
1921
+ return PaginatedResponse(
1922
+ count=data["count"],
1923
+ next=data.get("next"),
1924
+ previous=data.get("previous"),
1925
+ results=results,
1926
+ )
1927
+
1928
+ def get_protest(
1929
+ self,
1930
+ case_id: str,
1931
+ shape: str | None = None,
1932
+ flat: bool = False,
1933
+ flat_lists: bool = False,
1934
+ ) -> Any:
1935
+ """
1936
+ Get a single protest by case_id (RFC 4122 UUID).
1937
+
1938
+ Use shape=...,dockets(...) to include nested dockets.
1939
+ API reference: https://tango.makegov.com/docs/api-reference/protests.md
1940
+
1941
+ Args:
1942
+ case_id: Deterministic case UUID (from source_system + base_case_number)
1943
+ shape: Response shape string (defaults to minimal shape)
1944
+ flat: If True, flatten nested objects in shaped response
1945
+ flat_lists: If True, flatten arrays using indexed keys
1946
+ """
1947
+ params: dict[str, Any] = {}
1948
+ if shape is None:
1949
+ shape = ShapeConfig.PROTESTS_MINIMAL
1950
+ if shape:
1951
+ params["shape"] = shape
1952
+ if flat:
1953
+ params["flat"] = "true"
1954
+ if flat_lists:
1955
+ params["flat_lists"] = "true"
1956
+
1957
+ data = self._get(f"/api/protests/{case_id}/", params)
1958
+ return self._parse_response_with_shape(data, shape, Protest, flat, flat_lists)
1959
+
1862
1960
  # Grant endpoints
1863
1961
  def list_grants(
1864
1962
  self,
@@ -1945,47 +2043,6 @@ class TangoClient:
1945
2043
  results=results,
1946
2044
  )
1947
2045
 
1948
- def list_assistance(
1949
- self,
1950
- limit: int = 25,
1951
- cursor: str | None = None,
1952
- assistance_type: str | None = None,
1953
- award_key: str | None = None,
1954
- fiscal_year: int | None = None,
1955
- fiscal_year_gte: int | None = None,
1956
- fiscal_year_lte: int | None = None,
1957
- highly_compensated_officers: str | None = None,
1958
- recipient: str | None = None,
1959
- recipient_address: str | None = None,
1960
- search: str | None = None,
1961
- ) -> PaginatedResponse:
1962
- """List assistance (financial assistance) transactions (`/api/assistance/`). Keyset pagination."""
1963
- params: dict[str, Any] = {"limit": min(limit, 100)}
1964
- if cursor:
1965
- params["cursor"] = cursor
1966
- for key, val in (
1967
- ("assistance_type", assistance_type),
1968
- ("award_key", award_key),
1969
- ("fiscal_year", fiscal_year),
1970
- ("fiscal_year_gte", fiscal_year_gte),
1971
- ("fiscal_year_lte", fiscal_year_lte),
1972
- ("highly_compensated_officers", highly_compensated_officers),
1973
- ("recipient", recipient),
1974
- ("recipient_address", recipient_address),
1975
- ("search", search),
1976
- ):
1977
- if val is not None:
1978
- params[key] = val
1979
- data = self._get("/api/assistance/", params)
1980
- return PaginatedResponse(
1981
- count=int(data.get("count") or len(data.get("results") or [])),
1982
- next=data.get("next"),
1983
- previous=data.get("previous"),
1984
- results=data.get("results", []),
1985
- cursor=data.get("cursor"),
1986
- page_metadata=data.get("page_metadata"),
1987
- )
1988
-
1989
2046
  # ============================================================================
1990
2047
  # Webhooks (v2)
1991
2048
  # ============================================================================
tango/models.py CHANGED
@@ -433,6 +433,33 @@ class Notice:
433
433
  naics_code: str | None = None
434
434
 
435
435
 
436
+ @dataclass
437
+ class Protest:
438
+ """Schema definition for Protest (not used for instances)
439
+
440
+ Bid protest records at /api/protests/. Case-level object identified by case_id (UUID).
441
+ See https://tango.makegov.com/docs/api-reference/protests.md.
442
+ """
443
+
444
+ case_id: str
445
+ case_number: str | None = None
446
+ title: str | None = None
447
+ source_system: str | None = None
448
+ outcome: str | None = None
449
+ agency: str | None = None
450
+ protester: str | None = None
451
+ solicitation_number: str | None = None
452
+ case_type: str | None = None
453
+ filed_date: datetime | None = None
454
+ posted_date: datetime | None = None
455
+ decision_date: datetime | None = None
456
+ due_date: datetime | None = None
457
+ docket_url: str | None = None
458
+ decision_url: str | None = None
459
+ digest: str | None = None
460
+ dockets: list[dict[str, Any]] | None = None
461
+
462
+
436
463
  @dataclass
437
464
  class AssistanceListing:
438
465
  """Schema definition for Assistance Listing (not used for instances)"""
@@ -575,7 +602,7 @@ class ShapeConfig:
575
602
  "business_types,primary_naics,naics_codes,psc_codes,"
576
603
  "email_address,entity_url,description,capabilities,keywords,"
577
604
  "physical_address,mailing_address,"
578
- "federal_obligations,congressional_district"
605
+ "federal_obligations(*),congressional_district"
579
606
  )
580
607
 
581
608
  # Default for list_forecasts()
@@ -589,6 +616,9 @@ class ShapeConfig:
589
616
  # Default for list_notices()
590
617
  NOTICES_MINIMAL: Final = "notice_id,title,solicitation_number,posted_date"
591
618
 
619
+ # Default for list_protests()
620
+ PROTESTS_MINIMAL: Final = "case_id,case_number,title,source_system,outcome,filed_date"
621
+
592
622
  # Default for list_grants()
593
623
  GRANTS_MINIMAL: Final = "grant_id,opportunity_number,title,status(*),agency_code"
594
624
 
@@ -637,6 +637,57 @@ NOTICE_SCHEMA: dict[str, FieldSchema] = {
637
637
  }
638
638
 
639
639
 
640
+ # Docket-level fields for Protest dockets expansion: dockets(docket_number, filed_date, ...)
641
+ PROTEST_DOCKET_SCHEMA: dict[str, FieldSchema] = {
642
+ "source_system": FieldSchema(name="source_system", type=str, is_optional=True, is_list=False),
643
+ "case_number": FieldSchema(name="case_number", type=str, is_optional=True, is_list=False),
644
+ "docket_number": FieldSchema(name="docket_number", type=str, is_optional=True, is_list=False),
645
+ "title": FieldSchema(name="title", type=str, is_optional=True, is_list=False),
646
+ "protester": FieldSchema(name="protester", type=str, is_optional=True, is_list=False),
647
+ "agency": FieldSchema(name="agency", type=str, is_optional=True, is_list=False),
648
+ "solicitation_number": FieldSchema(
649
+ name="solicitation_number", type=str, is_optional=True, is_list=False
650
+ ),
651
+ "case_type": FieldSchema(name="case_type", type=str, is_optional=True, is_list=False),
652
+ "outcome": FieldSchema(name="outcome", type=str, is_optional=True, is_list=False),
653
+ "filed_date": FieldSchema(name="filed_date", type=datetime, is_optional=True, is_list=False),
654
+ "posted_date": FieldSchema(name="posted_date", type=datetime, is_optional=True, is_list=False),
655
+ "decision_date": FieldSchema(
656
+ name="decision_date", type=datetime, is_optional=True, is_list=False
657
+ ),
658
+ "due_date": FieldSchema(name="due_date", type=datetime, is_optional=True, is_list=False),
659
+ "docket_url": FieldSchema(name="docket_url", type=str, is_optional=True, is_list=False),
660
+ "decision_url": FieldSchema(name="decision_url", type=str, is_optional=True, is_list=False),
661
+ "digest": FieldSchema(name="digest", type=str, is_optional=True, is_list=False),
662
+ }
663
+
664
+ PROTEST_SCHEMA: dict[str, FieldSchema] = {
665
+ "case_id": FieldSchema(name="case_id", type=str, is_optional=False, is_list=False),
666
+ "case_number": FieldSchema(name="case_number", type=str, is_optional=True, is_list=False),
667
+ "title": FieldSchema(name="title", type=str, is_optional=True, is_list=False),
668
+ "source_system": FieldSchema(name="source_system", type=str, is_optional=True, is_list=False),
669
+ "outcome": FieldSchema(name="outcome", type=str, is_optional=True, is_list=False),
670
+ "agency": FieldSchema(name="agency", type=str, is_optional=True, is_list=False),
671
+ "protester": FieldSchema(name="protester", type=str, is_optional=True, is_list=False),
672
+ "solicitation_number": FieldSchema(
673
+ name="solicitation_number", type=str, is_optional=True, is_list=False
674
+ ),
675
+ "case_type": FieldSchema(name="case_type", type=str, is_optional=True, is_list=False),
676
+ "filed_date": FieldSchema(name="filed_date", type=datetime, is_optional=True, is_list=False),
677
+ "posted_date": FieldSchema(name="posted_date", type=datetime, is_optional=True, is_list=False),
678
+ "decision_date": FieldSchema(
679
+ name="decision_date", type=datetime, is_optional=True, is_list=False
680
+ ),
681
+ "due_date": FieldSchema(name="due_date", type=datetime, is_optional=True, is_list=False),
682
+ "docket_url": FieldSchema(name="docket_url", type=str, is_optional=True, is_list=False),
683
+ "decision_url": FieldSchema(name="decision_url", type=str, is_optional=True, is_list=False),
684
+ "digest": FieldSchema(name="digest", type=str, is_optional=True, is_list=False),
685
+ "dockets": FieldSchema(
686
+ name="dockets", type=dict, is_optional=True, is_list=True, nested_model="ProtestDocket"
687
+ ),
688
+ }
689
+
690
+
640
691
  AGENCY_SCHEMA: dict[str, FieldSchema] = {
641
692
  "abbreviation": FieldSchema(name="abbreviation", type=str, is_optional=True, is_list=False),
642
693
  "code": FieldSchema(name="code", type=str, is_optional=False, is_list=False),
@@ -1105,6 +1156,8 @@ EXPLICIT_SCHEMAS: dict[str, dict[str, FieldSchema]] = {
1105
1156
  "Forecast": FORECAST_SCHEMA,
1106
1157
  "Opportunity": OPPORTUNITY_SCHEMA,
1107
1158
  "Notice": NOTICE_SCHEMA,
1159
+ "Protest": PROTEST_SCHEMA,
1160
+ "ProtestDocket": PROTEST_DOCKET_SCHEMA,
1108
1161
  "Agency": AGENCY_SCHEMA,
1109
1162
  "Grant": GRANT_SCHEMA,
1110
1163
  # Vehicles (Awards)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tango-python
3
- Version: 0.4.1
3
+ Version: 0.4.2
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
@@ -61,7 +61,7 @@ A modern Python SDK for the [Tango API](https://tango.makegov.com) by MakeGov, f
61
61
 
62
62
  - **Dynamic Response Shaping** - Request only the fields you need, reducing payload sizes by 60-80%
63
63
  - **Full Type Safety** - Runtime-generated TypedDict types with accurate type hints for IDE autocomplete
64
- - **Comprehensive API Coverage** - All major Tango API endpoints (contracts, entities, forecasts, opportunities, notices, grants, webhooks) [Note: the current version does NOT implement all endpoints, we will be adding them incrementally]
64
+ - **Comprehensive API Coverage** - All major Tango API endpoints (contracts, IDVs, OTAs, entities, forecasts, opportunities, notices, grants, protests, webhooks, and more)
65
65
  - **Flexible Data Access** - Dictionary-based response objects with validation
66
66
  - **Modern Python** - Built for Python 3.12+ using modern async-ready patterns
67
67
  - **Production-Ready** - Comprehensive test suite with VCR.py-based integration tests
@@ -207,14 +207,33 @@ contracts = client.list_contracts(
207
207
  **Response Options:**
208
208
  - `shape`, `flat`, `flat_lists` - Response shaping options
209
209
 
210
+ ### IDVs, OTAs, OTIDVs
211
+
212
+ ```python
213
+ # List IDVs (keyset pagination)
214
+ idvs = client.list_idvs(limit=25, awarding_agency="4700")
215
+
216
+ # Get single IDV with shaping
217
+ idv = client.get_idv("IDV_KEY", shape=ShapeConfig.IDVS_COMPREHENSIVE)
218
+
219
+ # OTAs and OTIDVs follow the same pattern
220
+ otas = client.list_otas(limit=25)
221
+ otidvs = client.list_otidvs(limit=25)
222
+ ```
223
+
224
+ ### Vehicles
225
+
226
+ ```python
227
+ vehicles = client.list_vehicles(search="GSA schedule", shape=ShapeConfig.VEHICLES_MINIMAL)
228
+ vehicle = client.get_vehicle("UUID", shape=ShapeConfig.VEHICLES_COMPREHENSIVE)
229
+ awardees = client.list_vehicle_awardees("UUID")
230
+ ```
231
+
210
232
  ### Entities (Vendors/Recipients)
211
233
 
212
234
  ```python
213
- # List entities
214
- entities = client.list_entities(
215
- page=1,
216
- limit=25
217
- )
235
+ # List entities with filters
236
+ entities = client.list_entities(search="Booz Allen", state="VA", limit=25)
218
237
 
219
238
  # Get specific entity by UEI or CAGE code
220
239
  entity = client.get_entity("ZQGGHJH74DW7")
@@ -223,47 +242,49 @@ entity = client.get_entity("ZQGGHJH74DW7")
223
242
  ### Forecasts
224
243
 
225
244
  ```python
226
- # List contract forecasts
227
- forecasts = client.list_forecasts(
228
- agency="GSA",
229
- limit=25
230
- )
245
+ forecasts = client.list_forecasts(agency="GSA", fiscal_year=2025, limit=25)
231
246
  ```
232
247
 
233
248
  ### Opportunities
234
249
 
235
250
  ```python
236
- # List opportunities/solicitations
237
- opportunities = client.list_opportunities(
238
- agency="DOD",
239
- limit=25
240
- )
251
+ opportunities = client.list_opportunities(agency="DOD", active=True, limit=25)
241
252
  ```
242
253
 
243
254
  ### Notices
244
255
 
245
256
  ```python
246
- # List contract notices
247
- notices = client.list_notices(
248
- agency="DOD",
249
- limit=25
250
- )
257
+ notices = client.list_notices(agency="DOD", notice_type="award", limit=25)
251
258
  ```
252
259
 
253
260
  ### Grants
254
261
 
255
262
  ```python
256
- # List grant opportunities
257
- grants = client.list_grants(
258
- agency_code="HHS",
259
- limit=25
260
- )
263
+ grants = client.list_grants(agency="HHS", status="forecasted", limit=25)
264
+ ```
265
+
266
+ ### Protests
267
+
268
+ ```python
269
+ protests = client.list_protests(source_system="gao", outcome="Sustained", limit=25)
270
+ protest = client.get_protest("CASE_UUID")
271
+ ```
272
+
273
+ ### GSA eLibrary Contracts
274
+
275
+ ```python
276
+ contracts = client.list_gsa_elibrary_contracts(schedule="MAS", limit=25)
277
+ contract = client.get_gsa_elibrary_contract("UUID")
261
278
  ```
262
279
 
263
- ### Business Types
280
+ ### Reference Data
264
281
 
265
282
  ```python
266
- # List business types
283
+ # Offices, organizations, NAICS, subawards, business types
284
+ offices = client.list_offices(search="acquisitions")
285
+ organizations = client.list_organizations(level=1)
286
+ naics = client.list_naics(search="software")
287
+ subawards = client.list_subawards(prime_uei="UEI123")
267
288
  business_types = client.list_business_types()
268
289
  ```
269
290
 
@@ -476,9 +497,16 @@ tango-python/
476
497
  │ ├── test_entities_integration.py
477
498
  │ ├── test_forecasts_integration.py
478
499
  │ ├── test_grants_integration.py
500
+ │ ├── test_naics_integration.py
479
501
  │ ├── test_notices_integration.py
502
+ │ ├── test_offices_integration.py
480
503
  │ ├── test_opportunities_integration.py
504
+ │ ├── test_organizations_integration.py
505
+ │ ├── test_otas_otidvs_integration.py
506
+ │ ├── test_protests_integration.py
481
507
  │ ├── test_reference_data_integration.py
508
+ │ ├── test_subawards_integration.py
509
+ │ ├── test_vehicles_idvs_integration.py
482
510
  │ └── test_edge_cases_integration.py
483
511
  ├── docs/ # Documentation
484
512
  │ ├── API_REFERENCE.md # Complete API reference
@@ -1,16 +1,16 @@
1
1
  tango/__init__.py,sha256=7EdEUgCcK0lDNJWWDgdSWxx8xxryO-fHL-iml9PaYLw,1102
2
- tango/client.py,sha256=ykeTSh4rI4P3LZFALLfGkl2Yr6jM7NWrq_E4V5vY0nc,84112
2
+ tango/client.py,sha256=HvS-ss9QOeajLOkP2IsX9gTF_KvOb9_NOlLUphd8gSc,86111
3
3
  tango/exceptions.py,sha256=JmtbOY0ofBnX24pUErh2XFlTj9dim2ngyboserEGRFw,2226
4
- tango/models.py,sha256=E5jbcQ1CHevTJBD1KOREAqql9bTkft91WaNsL8qbnuA,19575
4
+ tango/models.py,sha256=4sLmWjyqsCU7-b8lr9ZRRG_ElBKz-5txibcOFcScEDY,20555
5
5
  tango/shapes/__init__.py,sha256=7ea1WU74jp4znhNw-gXruag6m6eyPZtbVgbDFmFUWro,1072
6
- tango/shapes/explicit_schemas.py,sha256=iKvmpmeFU8pr4PpTenlpXDKxNbLkuyfUdDc8IV7p4zk,51734
6
+ tango/shapes/explicit_schemas.py,sha256=H4pYs0LCTSV5msRCxftmgiM_-3sc4LsqpDPgj36DkPY,55202
7
7
  tango/shapes/factory.py,sha256=ytpMi5Uw72XZ8MimhuSsLDVXF3zO_Zt3_tAL6NF7LnU,34318
8
8
  tango/shapes/generator.py,sha256=61V1T3lm8Ps_KSMJAezQJLQVFbNKt1jtoLyhiqNtFTs,23380
9
9
  tango/shapes/models.py,sha256=h3pIhOqrrdlN953Y6r0oney5HFbKPOD-frRndRWimJ0,3018
10
10
  tango/shapes/parser.py,sha256=k6OsI2w3GH6-IBbc-XTLgL1mWH7bMf7A_dA6pr1xKfw,24619
11
11
  tango/shapes/schema.py,sha256=VRPOB1sBdjFyimNchrZKIpTHn83CyX4RfU9077aQtIU,14136
12
12
  tango/shapes/types.py,sha256=27jrAE0VIdrKaLjR_FK71hfIIGX2Tg3ex7REEBV1TFE,1301
13
- tango_python-0.4.1.dist-info/METADATA,sha256=QTa_gFDGAc9jj23jv35_0Zy9Js3bXlzK6FV-9OnjLFg,16210
14
- tango_python-0.4.1.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
15
- tango_python-0.4.1.dist-info/licenses/LICENSE,sha256=j2kYVHMwTkoGn3ZNScnrdIueG0k2XzB_LCPFoyBc2wk,1064
16
- tango_python-0.4.1.dist-info/RECORD,,
13
+ tango_python-0.4.2.dist-info/METADATA,sha256=h3QpwadNjsoHnMuXXpFj6BScFCvx61NGGOM43gG6GLQ,17595
14
+ tango_python-0.4.2.dist-info/WHEEL,sha256=QccIxa26bgl1E6uMy58deGWi-0aeIkkangHcxk2kWfw,87
15
+ tango_python-0.4.2.dist-info/licenses/LICENSE,sha256=j2kYVHMwTkoGn3ZNScnrdIueG0k2XzB_LCPFoyBc2wk,1064
16
+ tango_python-0.4.2.dist-info/RECORD,,