mirror of
https://github.com/OpenBB-finance/OpenBB.git
synced 2026-10-27 12:40:35 +00:00
[Feature] openbb-congress-gov: Add Amendments and Committee Documents Endpoints (#7428)
* add amendments and committees endpoints to congress_gov and migrate all items into the parent congress_gov folder * codespell * fix tests * no-redef * linting
This commit is contained in:
3
.codespell.skip
vendored
3
.codespell.skip
vendored
@@ -29,4 +29,5 @@
|
||||
./desktop/src-tauri/src/tauri_handlers/startup.rs
|
||||
./desktop/src/routes/environments.tsx
|
||||
./desktop/src/tests/routes/installation-progress.test.tsx
|
||||
./desktop/src/tests/routes/index.test.tsx
|
||||
./desktop/src/tests/routes/index.test.tsx
|
||||
./openbb_platform/providers/congress_gov/openbb_congress_gov/utils/helpers.py
|
||||
|
||||
@@ -435,103 +435,5 @@
|
||||
}
|
||||
},
|
||||
"groups": []
|
||||
},
|
||||
{
|
||||
"name": "The United States Congress",
|
||||
"img": "https://www.congress.gov/img/opengraph1200by630.jpg",
|
||||
"img_dark": "https://www.congress.gov/img/opengraph1200by630.jpg",
|
||||
"img_light": "https://www.congress.gov/img/opengraph1200by630.jpg",
|
||||
"description": "Find and view US federal legislative information and complete bill text.",
|
||||
"allowCustomization": true,
|
||||
"tabs": {
|
||||
"": {
|
||||
"id": "",
|
||||
"name": "",
|
||||
"layout": [
|
||||
{
|
||||
"i": "uscongress_bills_congress_gov_obb",
|
||||
"x": 0,
|
||||
"y": 0,
|
||||
"w": 40,
|
||||
"h": 11,
|
||||
"state": {
|
||||
"params": {
|
||||
"bill_url": "119/hr/1"
|
||||
},
|
||||
"chartView": {
|
||||
"enabled": false,
|
||||
"chartType": "line"
|
||||
},
|
||||
"columnState": {
|
||||
"default": {
|
||||
"columnVisibility": {
|
||||
"hiddenColIds": [
|
||||
"origin_chamber_code"
|
||||
]
|
||||
},
|
||||
"columnOrder": {
|
||||
"orderedColIds": [
|
||||
"update_date",
|
||||
"latest_action_date",
|
||||
"bill_url",
|
||||
"congress",
|
||||
"bill_number",
|
||||
"origin_chamber",
|
||||
"origin_chamber_code",
|
||||
"bill_type",
|
||||
"title",
|
||||
"latest_action",
|
||||
"update_date_including_text"
|
||||
]
|
||||
},
|
||||
"focusedCell": {
|
||||
"colId": "bill_url",
|
||||
"rowIndex": 2,
|
||||
"rowPinned": null
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"i": "uscongress_bill_text_congress_gov_obb",
|
||||
"x": 16,
|
||||
"y": 11,
|
||||
"w": 24,
|
||||
"h": 41,
|
||||
"state": {
|
||||
"params": {
|
||||
"bill_url": "119/hr/1"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"i": "uscongress_bill_info_congress_gov_obb",
|
||||
"x": 0,
|
||||
"y": 11,
|
||||
"w": 16,
|
||||
"h": 41,
|
||||
"state": {
|
||||
"params": {
|
||||
"bill_url": "119/hr/1"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"name": "Group 1",
|
||||
"type": "param",
|
||||
"paramName": "bill_url",
|
||||
"defaultValue": "119/hr/1",
|
||||
"widgetIds": [
|
||||
"uscongress_bills_congress_gov_obb",
|
||||
"uscongress_bill_text_congress_gov_obb",
|
||||
"uscongress_bill_info_congress_gov_obb"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
|
||||
@@ -194,6 +194,7 @@ if not has_root_apps:
|
||||
|
||||
if has_additional_apps(app):
|
||||
additional_apps = await get_additional_apps(app)
|
||||
|
||||
if additional_apps:
|
||||
for apps in additional_apps.values():
|
||||
if not apps:
|
||||
@@ -225,7 +226,8 @@ if not has_root_apps:
|
||||
if _tabs := template.get("tabs"):
|
||||
for v in _tabs.values():
|
||||
if v.get("layout", []) and all(
|
||||
item.get("i") in widgets_json
|
||||
item.get("i", "").startswith("rich_note")
|
||||
or item.get("i") in widgets_json
|
||||
for item in v.get("layout")
|
||||
):
|
||||
new_templates.append(template)
|
||||
@@ -233,7 +235,9 @@ if not has_root_apps:
|
||||
elif (
|
||||
template.get("layout")
|
||||
and all(
|
||||
item.get("i") in widgets_json for item in template["layout"]
|
||||
item.get("i", "").startswith("rich_note")
|
||||
or item.get("i") in widgets_json
|
||||
for item in template["layout"]
|
||||
)
|
||||
and template not in new_templates
|
||||
):
|
||||
@@ -282,7 +286,7 @@ else:
|
||||
|
||||
|
||||
def launch_api(**_kwargs): # noqa PRL0912
|
||||
"""Main function."""
|
||||
"""Start the API server."""
|
||||
host = _kwargs.pop("host", os.getenv("OPENBB_API_HOST", "127.0.0.1"))
|
||||
if not host:
|
||||
logger.info(
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
"""US Congress Router module for integration tests."""
|
||||
@@ -1,128 +0,0 @@
|
||||
"""Test Government API."""
|
||||
|
||||
import base64
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
from openbb_core.env import Env
|
||||
from openbb_core.provider.utils.helpers import get_querystring
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def headers():
|
||||
"""Get the headers for the API request."""
|
||||
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
|
||||
userpass_bytes = userpass.encode("ascii")
|
||||
base64_bytes = base64.b64encode(userpass_bytes)
|
||||
|
||||
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
|
||||
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"limit": 5,
|
||||
"offset": 0,
|
||||
"sort_by": "desc",
|
||||
"congress": None,
|
||||
"bill_type": None,
|
||||
"start_date": None,
|
||||
"end_date": None,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bills(params, headers):
|
||||
"""Test the government congress bills endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bills?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "119/hr/1",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_info(params, headers):
|
||||
"""Test the government congress bill info endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bill_info?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "https://api.congress.gov/v3/bill/119/s/1947?format=json",
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text_urls(params, headers):
|
||||
"""Test the government congress bill text URLs endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bill_text_urls?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/bills/hr1/BILLS-119hr1eh.pdf",
|
||||
],
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text(params, headers):
|
||||
"""Test the government congress bill text endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
urls = params.pop("urls", [])
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bill_text?{query_str}"
|
||||
result = requests.post(url, headers=headers, json=f"'{urls}'", timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
@@ -1,124 +0,0 @@
|
||||
"""Test Government extension."""
|
||||
|
||||
import pytest
|
||||
from openbb_congress_gov.models.bill_info import CongressBillInfoData
|
||||
from openbb_congress_gov.models.bill_text import CongressBillTextData
|
||||
from openbb_core.app.model.obbject import OBBject
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def obb(pytestconfig): # pylint: disable=inconsistent-return-statements
|
||||
"""Fixture to setup obb."""
|
||||
|
||||
if pytestconfig.getoption("markexpr") != "not integration":
|
||||
import openbb # pylint: disable=import-outside-toplevel
|
||||
|
||||
return openbb.obb
|
||||
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"limit": 5,
|
||||
"offset": 0,
|
||||
"sort_by": "desc",
|
||||
"congress": None,
|
||||
"bill_type": None,
|
||||
"start_date": None,
|
||||
"end_date": None,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bills(params, obb):
|
||||
"""Test US Congress bills."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bills(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert len(result.results) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "119/hr/1",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_info(params, obb):
|
||||
"""Test US Congress bill info."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bill_info(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert isinstance(result.results, CongressBillInfoData)
|
||||
assert isinstance(result.results.markdown_content, str)
|
||||
assert isinstance(result.results.raw_data, dict)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "https://api.congress.gov/v3/bill/119/s/1947?format=json",
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text_urls(params, obb):
|
||||
"""Test US Congress bill text URLs."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bill_text_urls(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/bills/hr1/BILLS-119hr1eh.pdf",
|
||||
],
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text(params, obb):
|
||||
"""Test US Congress bill text."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bill_text(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
assert isinstance(result[0], CongressBillTextData)
|
||||
@@ -0,0 +1,333 @@
|
||||
"""Test Government API."""
|
||||
|
||||
import base64
|
||||
|
||||
import pytest
|
||||
import requests
|
||||
from openbb_core.env import Env
|
||||
from openbb_core.provider.utils.helpers import get_querystring
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def headers():
|
||||
"""Get the headers for the API request."""
|
||||
userpass = f"{Env().API_USERNAME}:{Env().API_PASSWORD}"
|
||||
userpass_bytes = userpass.encode("ascii")
|
||||
base64_bytes = base64.b64encode(userpass_bytes)
|
||||
|
||||
return {"Authorization": f"Basic {base64_bytes.decode('ascii')}"}
|
||||
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"limit": 5,
|
||||
"offset": 0,
|
||||
"sort_by": "desc",
|
||||
"congress": None,
|
||||
"bill_type": None,
|
||||
"start_date": None,
|
||||
"end_date": None,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bills(params, headers):
|
||||
"""Test the government congress bills endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bills?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "119/hr/1",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_info(params, headers):
|
||||
"""Test the government congress bill info endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bill_info?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "https://api.congress.gov/v3/bill/119/s/1947?format=json",
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text_urls(params, headers):
|
||||
"""Test the government congress bill text URLs endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bill_text_urls?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/bills/hr1/BILLS-119hr1eh.pdf",
|
||||
],
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text(params, headers):
|
||||
"""Test the government congress bill text endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
urls = params.pop("urls", [])
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/bill_text?{query_str}"
|
||||
result = requests.post(url, headers=headers, json=f"'{urls}'", timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"congress": 119,
|
||||
"limit": 1,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendments(params, headers):
|
||||
"""Test the government congress amendments endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/amendments?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"amendment_url": "119/hamdt/2",
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendment_text_urls(params, headers):
|
||||
"""Test the government congress amendment text URLs endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/amendment_text_urls?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"amendment_url": "119/hamdt/2",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendment_info(params, headers):
|
||||
"""Test the government congress amendment info endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/amendment_info?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/crec/2026/03/21/172/52/CREC-2026-03-21-pt1-PgS1484-6.pdf",
|
||||
],
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendment_text(params, headers):
|
||||
"""Test the government congress amendment text endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
urls = params.pop("urls", [])
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/amendment_text?{query_str}"
|
||||
result = requests.post(url, headers=headers, json=f"'{urls}'", timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_info(params, headers):
|
||||
"""Test the government congress committee info endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/committee_info?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
"doc_type": "report",
|
||||
"congress": 119,
|
||||
"limit": 5,
|
||||
"use_cache": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_documents(params, headers):
|
||||
"""Test the government congress committee documents endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/committee_documents?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"congress": None,
|
||||
"committee": None,
|
||||
"subcommittees": None,
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_choices(params, headers):
|
||||
"""Test the government congress committee choices endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/committee_choices?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
"subcommittee": None,
|
||||
"doc_type": "report",
|
||||
"congress": 119,
|
||||
"is_workspace": False,
|
||||
"use_cache": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_document_urls(params, headers):
|
||||
"""Test the government congress committee document URLs endpoint."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
query_str = get_querystring(params, [])
|
||||
url = f"http://0.0.0.0:8000/api/v1/uscongress/committee_document_urls?{query_str}"
|
||||
result = requests.get(url, headers=headers, timeout=10)
|
||||
assert isinstance(result, requests.Response)
|
||||
assert result.status_code == 200
|
||||
@@ -0,0 +1,317 @@
|
||||
"""Test Government extension."""
|
||||
|
||||
import pytest
|
||||
from openbb_congress_gov.models.bill_info import CongressBillInfoData
|
||||
from openbb_congress_gov.models.bill_text import CongressBillTextData
|
||||
from openbb_core.app.model.obbject import OBBject
|
||||
|
||||
|
||||
@pytest.fixture(scope="session")
|
||||
def obb(pytestconfig): # pylint: disable=inconsistent-return-statements
|
||||
"""Fixture to setup obb."""
|
||||
|
||||
if pytestconfig.getoption("markexpr") != "not integration":
|
||||
import openbb # pylint: disable=import-outside-toplevel
|
||||
|
||||
return openbb.obb
|
||||
|
||||
|
||||
# pylint: disable=redefined-outer-name
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
}
|
||||
),
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"limit": 5,
|
||||
"offset": 0,
|
||||
"sort_by": "desc",
|
||||
"congress": None,
|
||||
"bill_type": None,
|
||||
"start_date": None,
|
||||
"end_date": None,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bills(params, obb):
|
||||
"""Test US Congress bills."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bills(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert len(result.results) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "119/hr/1",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_info(params, obb):
|
||||
"""Test US Congress bill info."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bill_info(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert isinstance(result.results, CongressBillInfoData)
|
||||
assert isinstance(result.results.markdown_content, str)
|
||||
assert isinstance(result.results.raw_data, dict)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"bill_url": "https://api.congress.gov/v3/bill/119/s/1947?format=json",
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text_urls(params, obb):
|
||||
"""Test US Congress bill text URLs."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bill_text_urls(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/bills/hr1/BILLS-119hr1eh.pdf",
|
||||
],
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_bill_text(params, obb):
|
||||
"""Test US Congress bill text."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.bill_text(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
assert isinstance(result[0], CongressBillTextData)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"congress": 119,
|
||||
"limit": 1,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendments(params, obb):
|
||||
"""Test US Congress amendments."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.amendments(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
assert len(result.results) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"amendment_url": "119/hamdt/2",
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendment_text_urls(params, obb):
|
||||
"""Test US Congress amendment text URLs."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.amendment_text_urls(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"amendment_url": "119/hamdt/2",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendment_info(params, obb):
|
||||
"""Test US Congress amendment info."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.amendment_info(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/crec/2026/03/21/172/52/CREC-2026-03-21-pt1-PgS1484-6.pdf",
|
||||
],
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_amendment_text(params, obb):
|
||||
"""Test US Congress amendment text."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.amendment_text(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_info(params, obb):
|
||||
"""Test US Congress committee info."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.committee_info(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
"doc_type": "report",
|
||||
"congress": 119,
|
||||
"limit": 5,
|
||||
"use_cache": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_documents(params, obb):
|
||||
"""Test US Congress committee documents."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.committee_documents(**params)
|
||||
assert result
|
||||
assert isinstance(result, OBBject)
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"congress": None,
|
||||
"committee": None,
|
||||
"subcommittees": None,
|
||||
"is_workspace": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_choices(params, obb):
|
||||
"""Test US Congress committee choices."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.committee_choices(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"params",
|
||||
[
|
||||
(
|
||||
{
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
"subcommittee": None,
|
||||
"doc_type": "report",
|
||||
"congress": 119,
|
||||
"is_workspace": False,
|
||||
"use_cache": False,
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
@pytest.mark.integration
|
||||
def test_uscongress_committee_document_urls(params, obb):
|
||||
"""Test US Congress committee document URLs."""
|
||||
params = {p: v for p, v in params.items() if v}
|
||||
|
||||
result = obb.uscongress.committee_document_urls(**params)
|
||||
assert result
|
||||
assert isinstance(result, list)
|
||||
assert len(result) > 0
|
||||
@@ -1,8 +1,17 @@
|
||||
"""Congress.gov Provider Module."""
|
||||
|
||||
from openbb_congress_gov.models.amendment_info import CongressAmendmentInfoFetcher
|
||||
from openbb_congress_gov.models.amendment_text import CongressAmendmentTextFetcher
|
||||
from openbb_congress_gov.models.bill_info import CongressBillInfoFetcher
|
||||
from openbb_congress_gov.models.bill_text import CongressBillTextFetcher
|
||||
from openbb_congress_gov.models.congress_amendments import CongressAmendmentsFetcher
|
||||
from openbb_congress_gov.models.congress_bills import CongressBillsFetcher
|
||||
from openbb_congress_gov.models.congress_committee_documents import (
|
||||
CongressCommitteeDocumentsFetcher,
|
||||
)
|
||||
from openbb_congress_gov.models.congress_committee_info import (
|
||||
CongressCommitteeInfoFetcher,
|
||||
)
|
||||
from openbb_core.provider.abstract.provider import Provider
|
||||
|
||||
congress_gov_provider = Provider(
|
||||
@@ -16,6 +25,11 @@ Register API provides access to presidential documents and regulations.""",
|
||||
"CongressBills": CongressBillsFetcher,
|
||||
"CongressBillInfo": CongressBillInfoFetcher,
|
||||
"CongressBillText": CongressBillTextFetcher,
|
||||
"CongressAmendments": CongressAmendmentsFetcher,
|
||||
"CongressAmendmentInfo": CongressAmendmentInfoFetcher,
|
||||
"CongressAmendmentText": CongressAmendmentTextFetcher,
|
||||
"CongressCommitteeInfo": CongressCommitteeInfoFetcher,
|
||||
"CongressCommitteeDocuments": CongressCommitteeDocumentsFetcher,
|
||||
},
|
||||
repr_name="Congress.gov",
|
||||
instructions="""To get a Congress.gov API key:
|
||||
|
||||
@@ -0,0 +1,245 @@
|
||||
"""Congress Amendment Info Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from typing import Any
|
||||
|
||||
from openbb_core.provider.abstract.data import Data
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.abstract.query_params import QueryParams
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
|
||||
class CongressAmendmentInfoQueryParams(QueryParams):
|
||||
"""Congress Amendment Info Query."""
|
||||
|
||||
__json_schema_extra__ = {
|
||||
"amendment_url": {
|
||||
"x-widget_config": {
|
||||
"label": "Amendment URL",
|
||||
"description": "Enter a base URL of an amendment"
|
||||
+ " (e.g., 'https://api.congress.gov/v3/amendment/119/hamdt/2?')."
|
||||
+ " Alternatively, you can enter a shorthand (e.g., '119/hamdt/2')."
|
||||
+ " Create a group on the 'amendment_url' field of the 'Congressional Amendments' widget"
|
||||
+ " and click on the cell to view amendment details.",
|
||||
"value": "119/hamdt/2",
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
amendment_url: str = Field(
|
||||
description="Enter a base URL of an amendment"
|
||||
+ " (e.g., 'https://api.congress.gov/v3/amendment/119/hamdt/2?format=json')."
|
||||
+ " Alternatively, you can enter a shorthand (e.g., '119/hamdt/2')."
|
||||
)
|
||||
|
||||
|
||||
class CongressAmendmentInfoData(Data):
|
||||
"""Congress Amendment Info Data."""
|
||||
|
||||
model_config = ConfigDict(
|
||||
json_schema_extra={
|
||||
"x-widget_config": {
|
||||
"$.type": "markdown",
|
||||
"$.name": "Congressional Amendment Info",
|
||||
"$.description": "Metadata and details for a U.S. Congressional Amendment.",
|
||||
"$.category": "Government",
|
||||
"$.subCategory": "Congress",
|
||||
"$.data": {
|
||||
"dataKey": "results.markdown_content",
|
||||
},
|
||||
"$.refetchInterval": False,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
markdown_content: str = Field(
|
||||
description="Aggregated metadata for the amendment in Markdown format."
|
||||
)
|
||||
raw_data: dict[str, Any] = Field(
|
||||
description="Raw JSON data from the collected amendment information.",
|
||||
json_schema_extra={
|
||||
"x-widget_config": {
|
||||
"exclude": True,
|
||||
}
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class CongressAmendmentInfoFetcher(
|
||||
Fetcher[CongressAmendmentInfoQueryParams, CongressAmendmentInfoData]
|
||||
):
|
||||
"""Congress Amendment Info Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: dict[str, Any]) -> CongressAmendmentInfoQueryParams:
|
||||
"""Transform the query parameters."""
|
||||
return CongressAmendmentInfoQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: CongressAmendmentInfoQueryParams,
|
||||
credentials: dict[str, str] | None,
|
||||
**kwargs: Any,
|
||||
) -> dict:
|
||||
"""Extract data from the Congress API."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_core.provider.utils.errors import UnauthorizedError
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
|
||||
api_key = credentials.get("congress_gov_api_key", "") if credentials else ""
|
||||
amendment_url = query.amendment_url
|
||||
|
||||
if amendment_url[0].isnumeric() or (
|
||||
amendment_url[0] == "/" and amendment_url[1].isnumeric()
|
||||
):
|
||||
amendment_url = (
|
||||
"https://api.congress.gov/v3/amendment/"
|
||||
+ f"{amendment_url[1:] if amendment_url[0] == '/' else amendment_url}?format=json"
|
||||
)
|
||||
|
||||
url = amendment_url + "&api_key=" + api_key
|
||||
base_info: dict = await amake_request(url) # type: ignore
|
||||
|
||||
if isinstance(base_info, dict) and (error := base_info.get("error", {})):
|
||||
if "API_KEY" in error.get("code", ""):
|
||||
raise UnauthorizedError(
|
||||
f"{error.get('code', '')} -> {error.get('message', '')}"
|
||||
)
|
||||
raise OpenBBError(f"{error.get('code', '')} -> {error.get('message', '')}")
|
||||
|
||||
base_info = base_info.get("amendment", {})
|
||||
|
||||
cosponsors = base_info.get("cosponsors", {})
|
||||
if isinstance(cosponsors, dict) and cosponsors.get("count", 0) > 0:
|
||||
cosponsors_url = cosponsors.get("url", "") + "&api_key=" + api_key
|
||||
cosponsors_response: dict = await amake_request(cosponsors_url) # type: ignore
|
||||
cosponsors_list = cosponsors_response.get("cosponsors", [])
|
||||
if cosponsors_list:
|
||||
base_info["cosponsors"] = cosponsors_list
|
||||
|
||||
actions = base_info.get("actions", {})
|
||||
if actions.get("count", 0) > 0:
|
||||
actions_url = actions.get("url", "") + "&api_key=" + api_key
|
||||
actions_response: dict = await amake_request(actions_url) # type: ignore
|
||||
actions_list = actions_response.get("actions", [])
|
||||
if actions_list:
|
||||
base_info["actions"] = actions_list
|
||||
|
||||
text_versions = base_info.get("textVersions", {})
|
||||
if isinstance(text_versions, dict) and text_versions.get("count", 0) > 0:
|
||||
text_url = text_versions.get("url", "") + "&api_key=" + api_key
|
||||
text_response: dict = await amake_request(text_url) # type: ignore
|
||||
text_list = text_response.get("textVersions", [])
|
||||
if text_list:
|
||||
base_info["textVersions"] = text_list
|
||||
|
||||
return base_info
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: CongressAmendmentInfoQueryParams,
|
||||
data: dict,
|
||||
**kwargs: Any,
|
||||
) -> CongressAmendmentInfoData:
|
||||
"""Transform the data into the model."""
|
||||
number = data.get("number", "")
|
||||
amendment_type = data.get("type", "")
|
||||
congress = data.get("congress", "")
|
||||
description = data.get("description", "")
|
||||
purpose = data.get("purpose", "")
|
||||
header = (
|
||||
description or purpose or f"Amendment {congress} {amendment_type} {number}"
|
||||
)
|
||||
|
||||
markdown_content = f"# {header}\n\n"
|
||||
if purpose and purpose != description:
|
||||
markdown_content += f"> {purpose}\n\n"
|
||||
markdown_content += f"- **Congress**: {congress}\n"
|
||||
markdown_content += f"- **Number**: {number}\n"
|
||||
markdown_content += f"- **Type**: {amendment_type}\n"
|
||||
markdown_content += f"- **Chamber**: {data.get('chamber', '')}\n"
|
||||
|
||||
submitted_at = data.get("submittedDate") or data.get("proposedDate")
|
||||
if submitted_at:
|
||||
markdown_content += f"- **Submitted**: {submitted_at}\n"
|
||||
|
||||
markdown_content += f"- **Last Updated**: {data.get('updateDate', '')}\n"
|
||||
|
||||
latest_action = data.get("latestAction", {})
|
||||
if latest_action:
|
||||
markdown_content += (
|
||||
f"- **Latest Action**: {latest_action.get('actionDate', '')} - "
|
||||
f"{latest_action.get('text', '')}\n"
|
||||
)
|
||||
|
||||
amended_bill = data.get("amendedBill", {})
|
||||
if amended_bill:
|
||||
bill_congress = amended_bill.get("congress", "")
|
||||
bill_type = amended_bill.get("type", "")
|
||||
bill_number = amended_bill.get("number", "")
|
||||
bill_title = amended_bill.get("title", "")
|
||||
markdown_content += (
|
||||
f"\n### Amended Bill\n\n"
|
||||
f"- **{bill_congress} {bill_type} {bill_number}**: {bill_title}\n"
|
||||
)
|
||||
|
||||
amended_amendment = data.get("amendedAmendment", {})
|
||||
if amended_amendment:
|
||||
aa_congress = amended_amendment.get("congress", "")
|
||||
aa_type = amended_amendment.get("type", "")
|
||||
aa_number = amended_amendment.get("number", "")
|
||||
markdown_content += (
|
||||
f"\n### Amends Amendment\n\n"
|
||||
f"- **{aa_congress} {aa_type} {aa_number}**\n"
|
||||
)
|
||||
|
||||
sponsors = data.get("sponsors", [])
|
||||
if sponsors:
|
||||
markdown_content += "\n### Sponsors\n\n"
|
||||
for sponsor in sponsors:
|
||||
markdown_content += f"- **{sponsor.get('fullName', '')}**"
|
||||
if sponsor.get("party"):
|
||||
markdown_content += f" ({sponsor.get('party', '')})"
|
||||
markdown_content += "\n"
|
||||
|
||||
cosponsors = data.get("cosponsors", {})
|
||||
if isinstance(cosponsors, list) and cosponsors:
|
||||
markdown_content += "\n### Cosponsors\n\n"
|
||||
for cosponsor in cosponsors:
|
||||
cosponsor_name = cosponsor.get("fullName", "")
|
||||
markdown_content += f"- **{cosponsor_name}**"
|
||||
if cosponsor.get("party"):
|
||||
markdown_content += f" ({cosponsor.get('party', '')})"
|
||||
markdown_content += "\n"
|
||||
elif isinstance(cosponsors, dict) and cosponsors.get("count", 0):
|
||||
markdown_content += (
|
||||
f"\n### Cosponsors\n\n- **Count**: {cosponsors['count']}\n"
|
||||
)
|
||||
|
||||
text_versions = data.get("textVersions", [])
|
||||
if text_versions and isinstance(text_versions, list):
|
||||
markdown_content += "\n### Text Versions\n\n"
|
||||
for version in text_versions:
|
||||
version_date = version.get("date", "")
|
||||
version_type = version.get("type", "")
|
||||
markdown_content += f"- **{version_type}** ({version_date})\n"
|
||||
for fmt in version.get("formats", []):
|
||||
fmt_type = fmt.get("type", "")
|
||||
fmt_url = fmt.get("url", "")
|
||||
markdown_content += f" - [{fmt_type}]({fmt_url})\n"
|
||||
|
||||
actions = data.get("actions", [])
|
||||
if actions and isinstance(actions, list):
|
||||
markdown_content += "\n### Actions\n\n"
|
||||
for action in actions:
|
||||
action_date = action.get("actionDate", "")
|
||||
action_text = action.get("text", "")
|
||||
action_type = action.get("type", "")
|
||||
markdown_content += f"\n- **{action_date}**: ({action_type})"
|
||||
markdown_content += f"\n - {action_text}"
|
||||
|
||||
return CongressAmendmentInfoData(
|
||||
markdown_content=markdown_content, raw_data=data
|
||||
)
|
||||
@@ -0,0 +1,137 @@
|
||||
"""Congress Amendment Text Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from typing import Any
|
||||
|
||||
from openbb_core.provider.abstract.data import Data
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.abstract.query_params import QueryParams
|
||||
from pydantic import Field
|
||||
|
||||
|
||||
class CongressAmendmentTextQueryParams(QueryParams):
|
||||
"""Congress Amendment Text Query."""
|
||||
|
||||
__json_schema_extra__ = {
|
||||
"urls": {
|
||||
"multiple_items_allowed": True,
|
||||
}
|
||||
}
|
||||
urls: str | list[str] | dict[str, list[str]] = Field(
|
||||
description="List of direct amendment document URLs to download.",
|
||||
kw_only=True,
|
||||
)
|
||||
|
||||
|
||||
class CongressAmendmentTextData(Data):
|
||||
"""Congress Amendment Text Data."""
|
||||
|
||||
error_type: str | None = Field(
|
||||
default=None,
|
||||
description="Error type if any error occurs during the download.",
|
||||
)
|
||||
content: str = Field(
|
||||
description="Base64-encoded PDF document or plain text content.",
|
||||
)
|
||||
filename: str | None = Field(
|
||||
default=None,
|
||||
description="The filename of the downloaded document.",
|
||||
)
|
||||
data_format: dict[str, str] | None = Field(
|
||||
default=None,
|
||||
description="Data format information, including data type and filename.",
|
||||
)
|
||||
|
||||
|
||||
class CongressAmendmentTextFetcher(
|
||||
Fetcher[CongressAmendmentTextQueryParams, list[CongressAmendmentTextData]]
|
||||
):
|
||||
"""Congress Amendment Text Fetcher."""
|
||||
|
||||
require_credentials = False
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: dict[str, Any]) -> CongressAmendmentTextQueryParams:
|
||||
"""Transform the query parameters."""
|
||||
return CongressAmendmentTextQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: CongressAmendmentTextQueryParams,
|
||||
credentials: dict[str, Any] | None = None,
|
||||
**kwargs: Any,
|
||||
) -> list:
|
||||
"""Extract data from the query."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import base64 # noqa
|
||||
from io import BytesIO
|
||||
from openbb_core.provider.utils.helpers import make_request
|
||||
|
||||
urls = (
|
||||
query.urls.get("urls", [])
|
||||
if isinstance(query.urls, dict)
|
||||
else (query.urls if isinstance(query.urls, list) else query.urls.split(","))
|
||||
)
|
||||
results: list = []
|
||||
|
||||
for url in urls:
|
||||
filename = url.split("/")[-1]
|
||||
|
||||
if "congress.gov" not in url.strip():
|
||||
results.append(
|
||||
{
|
||||
"error_type": "invalid_url",
|
||||
"content": f"Invalid URL: {url}. Must be a valid Congress.gov API URL.",
|
||||
"filename": filename,
|
||||
}
|
||||
)
|
||||
continue
|
||||
try:
|
||||
response = make_request(url)
|
||||
response.raise_for_status()
|
||||
datatype = filename.split(".")[-1].lower()
|
||||
|
||||
if datatype == "pdf":
|
||||
pdf_content = base64.b64encode(
|
||||
BytesIO(response.content).read()
|
||||
).decode("utf-8")
|
||||
results.append(
|
||||
{
|
||||
"content": pdf_content,
|
||||
"data_format": {
|
||||
"data_type": "pdf",
|
||||
"filename": filename,
|
||||
},
|
||||
}
|
||||
)
|
||||
else:
|
||||
results.append(
|
||||
{
|
||||
"content": response.text,
|
||||
"data_format": {
|
||||
"data_type": "text",
|
||||
"filename": filename,
|
||||
},
|
||||
}
|
||||
)
|
||||
except Exception as exc: # pylint: disable=broad-except
|
||||
results.append(
|
||||
{
|
||||
"error_type": "download_error",
|
||||
"content": f"{exc.__class__.__name__}: {exc.args[0]}",
|
||||
"filename": filename,
|
||||
}
|
||||
)
|
||||
continue
|
||||
|
||||
return results
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: CongressAmendmentTextQueryParams,
|
||||
data: list,
|
||||
**kwargs: Any,
|
||||
) -> list[CongressAmendmentTextData]:
|
||||
"""Transform the extracted data into the desired format."""
|
||||
return [CongressAmendmentTextData(**item) for item in data]
|
||||
@@ -254,7 +254,7 @@ class CongressBillInfoFetcher(
|
||||
|
||||
return text
|
||||
|
||||
markdown_content = f"""# {data.get("title")}
|
||||
markdown_content = f"""## {data.get("title")}
|
||||
|
||||
- **Congress**: {data.get("congress")}
|
||||
- **Bill Number**: {data.get("number")}
|
||||
@@ -362,7 +362,7 @@ class CongressBillInfoFetcher(
|
||||
committee_chamber = committee.get("chamber", "")
|
||||
|
||||
if committee_chamber:
|
||||
markdown_content += f"- **{committee_name} - {committee_chamber} ({committee.get('type')}) **\n"
|
||||
markdown_content += f"- **{committee_name} - {committee_chamber} ({committee.get('type')})**\n"
|
||||
else:
|
||||
markdown_content += f"- **{committee_name}**\n"
|
||||
|
||||
|
||||
@@ -83,13 +83,16 @@ class CongressBillTextFetcher(
|
||||
results: list = []
|
||||
|
||||
for url in urls:
|
||||
filename = url.split("/")[-1]
|
||||
from urllib.parse import urlparse
|
||||
|
||||
if "congress.gov" not in url.strip():
|
||||
filename = urlparse(url).path.split("/")[-1]
|
||||
|
||||
_url_lower = url.strip().lower()
|
||||
if "congress.gov" not in _url_lower and "govinfo.gov" not in _url_lower:
|
||||
results.append(
|
||||
{
|
||||
"error_type": "invalid_url",
|
||||
"content": f"Invalid URL: {url}. Must be a valid Congress.gov API URL.",
|
||||
"content": f"Invalid URL: {url}. Must be a valid Congress.gov or GovInfo URL.",
|
||||
"filename": filename,
|
||||
}
|
||||
)
|
||||
|
||||
@@ -0,0 +1,362 @@
|
||||
"""Congress Amendments Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from datetime import date as dateType
|
||||
from typing import Any, Literal
|
||||
|
||||
from openbb_congress_gov.utils.constants import (
|
||||
AmendmentTypes,
|
||||
amendment_type_docstring,
|
||||
amendment_type_options,
|
||||
base_url,
|
||||
)
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_core.provider.abstract.data import Data
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.abstract.query_params import QueryParams
|
||||
from pydantic import ConfigDict, Field, model_validator
|
||||
|
||||
|
||||
class CongressAmendmentsQueryParams(QueryParams):
|
||||
"""Congress Amendments Query Parameters."""
|
||||
|
||||
__json_schema_extra__ = {
|
||||
"amendment_type": {
|
||||
"x-widget_config": {
|
||||
"options": amendment_type_options,
|
||||
"value": None,
|
||||
"style": {"popupWidth": 200},
|
||||
"paramName": "amendment_type",
|
||||
"label": "Amendment Type",
|
||||
},
|
||||
},
|
||||
"congress": {
|
||||
"x-widget_config": {
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"offset": {
|
||||
"x-widget_config": {
|
||||
"type": "number",
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
congress: int | None = Field(
|
||||
default=None,
|
||||
description="Congress number (e.g., 119 for the 119th Congress)."
|
||||
+ " When None, returns amendments across all congresses (requires amendment_type).",
|
||||
)
|
||||
amendment_type: str | None = Field(
|
||||
default=None,
|
||||
description=amendment_type_docstring,
|
||||
examples=["hamdt", "samdt"],
|
||||
)
|
||||
start_date: dateType | None = Field(
|
||||
default=None,
|
||||
description="Filter amendments updated on or after this date.",
|
||||
)
|
||||
end_date: dateType | None = Field(
|
||||
default=None, description="Filter amendments updated on or before this date."
|
||||
)
|
||||
limit: int | None = Field(
|
||||
default=None,
|
||||
description="Maximum number of results to return. When None, defaults to 100 (max 250)."
|
||||
+ " Set to 0 for no limit (must be used with 'amendment_type').",
|
||||
)
|
||||
offset: int | None = Field(
|
||||
default=None, description="The starting record returned. 0 is the first record."
|
||||
)
|
||||
sort_by: Literal["asc", "desc"] = Field(
|
||||
default="desc", description="Sort by update date. Default is latest first."
|
||||
)
|
||||
|
||||
@model_validator(mode="after")
|
||||
@classmethod
|
||||
def validate_query(cls, values):
|
||||
"""Validate the query parameters."""
|
||||
if (
|
||||
values.amendment_type is not None
|
||||
and values.amendment_type not in AmendmentTypes
|
||||
):
|
||||
raise OpenBBError(
|
||||
ValueError(
|
||||
f"Invalid amendment_type: {values.amendment_type}."
|
||||
f" Must be one of: {', '.join(AmendmentTypes)}."
|
||||
)
|
||||
)
|
||||
if values.limit == 0 and values.amendment_type is None:
|
||||
raise OpenBBError(
|
||||
ValueError("'limit' cannot be set to 0 without 'amendment_type'.")
|
||||
)
|
||||
return values
|
||||
|
||||
|
||||
class CongressAmendmentsData(Data):
|
||||
"""Congress Amendments Data."""
|
||||
|
||||
__alias_dict__ = {
|
||||
"amendment_type": "type",
|
||||
"amendment_url": "url",
|
||||
}
|
||||
|
||||
model_config = ConfigDict(
|
||||
json_schema_extra={
|
||||
"x-widget_config": {
|
||||
"$.name": "Congressional Amendments",
|
||||
"$.category": "Government",
|
||||
"$.subCategory": "Congress",
|
||||
"$.description": "Current and historical U.S. Congressional Amendments.",
|
||||
"$.params": [
|
||||
{
|
||||
"paramName": "amendment_url",
|
||||
"label": "Amendment URL",
|
||||
"description": "Ghost parameter to group by the amendment URL."
|
||||
+ " Create a group and use the 'Congressional Amendment Info' widget to view details."
|
||||
+ " The 'Congressional Amendment Text Viewer' widget can also be grouped by this field.",
|
||||
"type": "text",
|
||||
"value": None,
|
||||
"show": True,
|
||||
},
|
||||
],
|
||||
"$.refetchInterval": False,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
congress: int = Field(
|
||||
description="The congress session number.",
|
||||
json_schema_extra={"x-widget_config": {"formatterFn": "none"}},
|
||||
)
|
||||
amendment_type: str = Field(
|
||||
description="The type of amendment (e.g., HAMDT, SAMDT).",
|
||||
json_schema_extra={"x-widget_config": {"label": "Type"}},
|
||||
)
|
||||
number: str = Field(
|
||||
description="The amendment number.",
|
||||
json_schema_extra={
|
||||
"x-widget_config": {"formatterFn": "none", "label": "Amendment No."},
|
||||
},
|
||||
)
|
||||
amended_bill: str | None = Field(
|
||||
default=None,
|
||||
description="The bill being amended (e.g., 'HR 1234' or 'S 456').",
|
||||
json_schema_extra={"x-widget_config": {"label": "Amended Bill"}},
|
||||
)
|
||||
amended_bill_title: str | None = Field(
|
||||
default=None,
|
||||
description="The title of the bill being amended.",
|
||||
json_schema_extra={"x-widget_config": {"label": "Bill Title"}},
|
||||
)
|
||||
description: str | None = Field(
|
||||
default=None,
|
||||
description="A short description of the amendment.",
|
||||
)
|
||||
purpose: str | None = Field(
|
||||
default=None,
|
||||
description="The purpose of the amendment.",
|
||||
)
|
||||
latest_action_date: dateType | None = Field(
|
||||
default=None, description="The date of the latest action."
|
||||
)
|
||||
latest_action: str | None = Field(default=None, description="Latest action text.")
|
||||
latest_action_time: str | None = Field(
|
||||
default=None,
|
||||
description="The time of the latest action.",
|
||||
json_schema_extra={"x-widget_config": {"hide": True}},
|
||||
)
|
||||
sponsor: str | None = Field(
|
||||
default=None,
|
||||
description="The primary sponsor of the amendment.",
|
||||
json_schema_extra={"x-widget_config": {"label": "Sponsor"}},
|
||||
)
|
||||
submitted_date: dateType | None = Field(
|
||||
default=None,
|
||||
description="The date the amendment was submitted.",
|
||||
json_schema_extra={"x-widget_config": {"label": "Submitted"}},
|
||||
)
|
||||
update_date: dateType | None = Field(
|
||||
default=None, description="The date the record was last updated."
|
||||
)
|
||||
amendment_url: str = Field(
|
||||
description="Base URL to the amendment for the congress.gov API.",
|
||||
json_schema_extra={
|
||||
"x-widget_config": {
|
||||
"headerTooltip": "Create a group for the 'amendment_url' parameter and then"
|
||||
+ " click in the cell to change the documents in the"
|
||||
+ " 'Congressional Amendment Info' or 'Congressional Amendment Text Viewer' widgets.",
|
||||
"renderFn": "cellOnClick",
|
||||
"renderFnParams": {
|
||||
"actionType": "groupBy",
|
||||
"groupByParamName": "amendment_url",
|
||||
},
|
||||
},
|
||||
},
|
||||
)
|
||||
|
||||
|
||||
class CongressAmendmentsFetcher(
|
||||
Fetcher[
|
||||
CongressAmendmentsQueryParams,
|
||||
list[CongressAmendmentsData],
|
||||
]
|
||||
):
|
||||
"""Transform the query, extract and transform the data from the Congress API."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: dict[str, Any]) -> CongressAmendmentsQueryParams:
|
||||
"""Transform the query params."""
|
||||
return CongressAmendmentsQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: CongressAmendmentsQueryParams,
|
||||
credentials: dict[str, str] | None,
|
||||
**kwargs: Any,
|
||||
) -> list:
|
||||
"""Extract data from the Congress API."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import asyncio
|
||||
|
||||
from openbb_congress_gov.utils.helpers import get_all_amendments_by_type
|
||||
from openbb_core.provider.utils.errors import UnauthorizedError
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
|
||||
api_key = credentials.get("congress_gov_api_key") if credentials else ""
|
||||
|
||||
if query.limit == 0 and query.amendment_type is not None:
|
||||
if query.congress is None:
|
||||
raise OpenBBError(
|
||||
ValueError("'congress' is required when 'limit' is set to 0.")
|
||||
)
|
||||
|
||||
return await get_all_amendments_by_type(
|
||||
congress=query.congress,
|
||||
amendment_type=query.amendment_type,
|
||||
)
|
||||
|
||||
url = f"{base_url}amendment"
|
||||
|
||||
if query.congress is not None:
|
||||
url += f"/{query.congress}"
|
||||
|
||||
if query.amendment_type is not None:
|
||||
url += f"/{query.amendment_type}"
|
||||
|
||||
url += f"?limit={query.limit if query.limit is not None else 100}"
|
||||
url += f"&offset={query.offset if query.offset else 0}"
|
||||
url += f"&sort=updateDate+{query.sort_by}"
|
||||
|
||||
if query.start_date:
|
||||
url += f"&fromDateTime={query.start_date}T00:00:00Z"
|
||||
|
||||
if query.end_date:
|
||||
url += f"&toDateTime={query.end_date}T23:59:59Z"
|
||||
|
||||
url += f"&format=json&api_key={api_key}"
|
||||
|
||||
try:
|
||||
response = await amake_request(url=url)
|
||||
|
||||
if isinstance(response, dict) and (error := response.get("error", {})):
|
||||
if "API_KEY" in error.get("code", ""):
|
||||
raise UnauthorizedError(
|
||||
f"{error.get('code', '')} -> {error.get('message', '')}"
|
||||
)
|
||||
raise OpenBBError( # noqa: TRY301
|
||||
f"{error.get('code', '')} -> {error.get('message', '')}"
|
||||
)
|
||||
except OpenBBError:
|
||||
raise
|
||||
except Exception as e:
|
||||
raise OpenBBError(e) from e
|
||||
|
||||
amendments = response.get("amendments", []) # type: ignore
|
||||
|
||||
if not amendments:
|
||||
return []
|
||||
|
||||
detail_urls = [
|
||||
a["url"].split("?")[0] + f"?format=json&api_key={api_key}"
|
||||
for a in amendments
|
||||
if "url" in a
|
||||
]
|
||||
detail_responses = await asyncio.gather(
|
||||
*[amake_request(u) for u in detail_urls],
|
||||
return_exceptions=True,
|
||||
)
|
||||
|
||||
for amendment, detail_resp in zip(amendments, detail_responses):
|
||||
if not isinstance(detail_resp, dict):
|
||||
continue
|
||||
|
||||
detail = detail_resp.get("amendment", {})
|
||||
|
||||
for field in (
|
||||
"amendedBill",
|
||||
"amendedAmendment",
|
||||
"sponsors",
|
||||
"submittedDate",
|
||||
"purpose",
|
||||
):
|
||||
if field in detail and field not in amendment:
|
||||
amendment[field] = detail[field]
|
||||
|
||||
for field in ("latestAction", "description"):
|
||||
if field not in amendment and field in detail:
|
||||
amendment[field] = detail[field]
|
||||
|
||||
return amendments
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: CongressAmendmentsQueryParams, data: list, **kwargs: Any
|
||||
) -> list[CongressAmendmentsData]:
|
||||
"""Transform raw data into CongressAmendmentsData models."""
|
||||
transformed_data: list[CongressAmendmentsData] = []
|
||||
|
||||
for amendment in sorted(
|
||||
data,
|
||||
key=lambda x: x.get("latestAction", {}).get("actionDate")
|
||||
or x.get("updateDate"),
|
||||
reverse=query.sort_by == "desc",
|
||||
):
|
||||
latest_action = amendment.pop("latestAction", {})
|
||||
|
||||
if latest_action:
|
||||
amendment["latest_action_date"] = latest_action.get("actionDate")
|
||||
amendment["latest_action_time"] = latest_action.get("actionTime")
|
||||
amendment["latest_action"] = latest_action.get("text")
|
||||
|
||||
amended_bill = amendment.pop("amendedBill", {}) or {}
|
||||
|
||||
if amended_bill:
|
||||
bill_type = amended_bill.get("type", "")
|
||||
bill_number = amended_bill.get("number", "")
|
||||
amendment["amended_bill"] = f"{bill_type} {bill_number}".strip() or None
|
||||
amendment["amended_bill_title"] = amended_bill.get("title") or None
|
||||
|
||||
amended_amendment = amendment.pop("amendedAmendment", {}) or {}
|
||||
|
||||
if amended_amendment and not amendment.get("amended_bill"):
|
||||
aa_type = amended_amendment.get("type", "")
|
||||
aa_number = amended_amendment.get("number", "")
|
||||
amendment["amended_bill"] = (
|
||||
f"Amdt. {aa_type} {aa_number}".strip() or None
|
||||
)
|
||||
|
||||
sponsors = amendment.pop("sponsors", []) or []
|
||||
|
||||
if sponsors:
|
||||
amendment["sponsor"] = sponsors[0].get("fullName") or None
|
||||
|
||||
if submitted := amendment.pop("submittedDate", None):
|
||||
amendment["submitted_date"] = submitted[:10]
|
||||
|
||||
if update_date := amendment.get("updateDate"):
|
||||
amendment["updateDate"] = update_date[:10]
|
||||
|
||||
transformed_data.append(CongressAmendmentsData(**amendment))
|
||||
|
||||
return transformed_data
|
||||
@@ -0,0 +1,223 @@
|
||||
"""Congress Committee Documents Model."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from typing import Any, Literal
|
||||
|
||||
from openbb_congress_gov.utils.constants import doc_type_options
|
||||
from openbb_congress_gov.utils.helpers import year_to_congress
|
||||
from openbb_core.app.model.abstract.error import OpenBBError
|
||||
from openbb_core.app.service.system_service import SystemService
|
||||
from openbb_core.provider.abstract.data import Data
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.abstract.query_params import QueryParams
|
||||
from openbb_core.provider.utils.descriptions import QUERY_DESCRIPTIONS
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
api_prefix = SystemService().system_settings.api_settings.prefix
|
||||
|
||||
|
||||
class CongressCommitteeDocumentsQueryParams(QueryParams):
|
||||
"""Congress Committee Documents Query Parameters."""
|
||||
|
||||
__json_schema_extra__ = {
|
||||
"congress": {
|
||||
"x-widget_config": {
|
||||
"label": "Congress",
|
||||
"type": "number",
|
||||
},
|
||||
},
|
||||
"chamber": {
|
||||
"x-widget_config": {
|
||||
"label": "Chamber",
|
||||
"options": [
|
||||
{"label": "Senate", "value": "senate"},
|
||||
{"label": "House", "value": "house"},
|
||||
{"label": "Joint", "value": "joint"},
|
||||
],
|
||||
"value": "senate",
|
||||
},
|
||||
},
|
||||
"committee": {
|
||||
"x-widget_config": {
|
||||
"label": "Committee",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {
|
||||
"chamber": "$chamber",
|
||||
"congress": "$congress",
|
||||
"is_workspace": True,
|
||||
},
|
||||
"value": "ssaf00",
|
||||
"style": {"popupWidth": 750},
|
||||
"row": 1,
|
||||
},
|
||||
},
|
||||
"subcommittee": {
|
||||
"x-widget_config": {
|
||||
"label": "Subcommittee",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {
|
||||
"chamber": "$chamber",
|
||||
"committee": "$committee",
|
||||
"subcommittees": True,
|
||||
"is_workspace": True,
|
||||
},
|
||||
"style": {"popupWidth": 750},
|
||||
"row": 1,
|
||||
},
|
||||
},
|
||||
"doc_type": {
|
||||
"x-widget_config": {
|
||||
"options": doc_type_options,
|
||||
"value": "all",
|
||||
"paramName": "doc_type",
|
||||
"label": "Document Type",
|
||||
"style": {"popupWidth": 220},
|
||||
},
|
||||
},
|
||||
"limit": {
|
||||
"x-widget_config": {"type": "number"},
|
||||
},
|
||||
"offset": {
|
||||
"x-widget_config": {"type": "number"},
|
||||
},
|
||||
}
|
||||
|
||||
congress: int | None = Field(
|
||||
default=None,
|
||||
description="Congress number (e.g., 119). Defaults to the current Congress.",
|
||||
)
|
||||
chamber: Literal["house", "senate", "joint"] = Field(
|
||||
default="senate",
|
||||
description="Chamber: house, senate, or joint.",
|
||||
)
|
||||
committee: str = Field(
|
||||
default="ssaf00",
|
||||
description="System code of the committee (e.g., ssaf00, hsju00).",
|
||||
)
|
||||
subcommittee: str | None = Field(
|
||||
default=None,
|
||||
description="System code of a subcommittee (e.g., ssga22). Leave empty for parent committee.",
|
||||
)
|
||||
doc_type: Literal["all", "report", "meeting", "publication", "legislation"] = Field(
|
||||
default="all",
|
||||
description=(
|
||||
"Type of committee document to retrieve. "
|
||||
"Options: all (default), report, meeting, publication, legislation."
|
||||
),
|
||||
)
|
||||
limit: int = Field(
|
||||
default=250,
|
||||
description=QUERY_DESCRIPTIONS.get("limit", "") + " Maximum 250.",
|
||||
ge=1,
|
||||
le=250,
|
||||
)
|
||||
offset: int = Field(
|
||||
default=0,
|
||||
description="Pagination offset.",
|
||||
ge=0,
|
||||
)
|
||||
use_cache: bool = Field(
|
||||
default=True,
|
||||
description="Use cached API responses. Set to False to bypass the cache.",
|
||||
)
|
||||
|
||||
|
||||
class CongressCommitteeDocumentsData(Data):
|
||||
"""Congress Committee Documents Data."""
|
||||
|
||||
model_config = ConfigDict(
|
||||
json_schema_extra={
|
||||
"x-widget_config": {
|
||||
"$.type": "table",
|
||||
"$.name": "Congressional Committee Documents",
|
||||
"$.description": (
|
||||
"Documents produced by a U.S. Congressional Committee "
|
||||
"(reports, hearings, meetings, publications/prints) "
|
||||
"sourced from the congress.gov unified search."
|
||||
),
|
||||
"$.category": "Government",
|
||||
"$.subCategory": "Congress",
|
||||
"$.refetchInterval": False,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
doc_type: str = Field(description="Document type (report, meeting, publication).")
|
||||
citation: str | None = Field(
|
||||
default=None,
|
||||
description="Official citation (e.g., 'H. Rept. 119-5' or 'S. Hrg. 119-74').",
|
||||
)
|
||||
title: str | None = Field(
|
||||
default=None,
|
||||
description="Document title.",
|
||||
)
|
||||
congress: int | None = Field(
|
||||
default=None,
|
||||
description="Congress session number.",
|
||||
json_schema_extra={"x-widget_config": {"formatterFn": "none"}},
|
||||
)
|
||||
chamber: str | None = Field(
|
||||
default=None,
|
||||
description="Chamber (House, Senate, Joint).",
|
||||
)
|
||||
|
||||
|
||||
class CongressCommitteeDocumentsFetcher(
|
||||
Fetcher[
|
||||
CongressCommitteeDocumentsQueryParams,
|
||||
list[CongressCommitteeDocumentsData],
|
||||
]
|
||||
):
|
||||
"""Transform the query, extract and transform the data from the Congress API."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(
|
||||
params: dict[str, Any],
|
||||
) -> CongressCommitteeDocumentsQueryParams:
|
||||
"""Transform the query params."""
|
||||
return CongressCommitteeDocumentsQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: CongressCommitteeDocumentsQueryParams,
|
||||
credentials: dict[str, str] | None,
|
||||
**kwargs: Any,
|
||||
) -> list[dict]:
|
||||
"""Extract data from the Congress API."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from datetime import datetime
|
||||
|
||||
from openbb_congress_gov.utils.committees import fetch_committee_documents
|
||||
|
||||
api_key = credentials.get("congress_gov_api_key", "") if credentials else ""
|
||||
|
||||
chamber = query.chamber.lower()
|
||||
system_code = (query.subcommittee or query.committee).lower()
|
||||
congress = query.congress
|
||||
|
||||
if congress is None:
|
||||
congress = year_to_congress(datetime.now().year)
|
||||
|
||||
try:
|
||||
return await fetch_committee_documents(
|
||||
chamber=chamber,
|
||||
system_code=system_code,
|
||||
congress=congress,
|
||||
doc_type=query.doc_type,
|
||||
api_key=api_key,
|
||||
use_cache=query.use_cache,
|
||||
)
|
||||
except OpenBBError as e:
|
||||
raise OpenBBError(e) from None
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: CongressCommitteeDocumentsQueryParams,
|
||||
data: list[dict],
|
||||
**kwargs: Any,
|
||||
) -> list[CongressCommitteeDocumentsData]:
|
||||
"""Transform raw data into CongressCommitteeDocumentsData models."""
|
||||
return [CongressCommitteeDocumentsData.model_validate(d) for d in data]
|
||||
@@ -0,0 +1,269 @@
|
||||
"""Congress Committee Info Model - Widget 2: Metadata and Members for a Single Committee."""
|
||||
|
||||
# pylint: disable=unused-argument
|
||||
|
||||
from typing import Any, Literal
|
||||
|
||||
from openbb_core.app.service.system_service import SystemService
|
||||
from openbb_core.provider.abstract.data import Data
|
||||
from openbb_core.provider.abstract.fetcher import Fetcher
|
||||
from openbb_core.provider.abstract.query_params import QueryParams
|
||||
from pydantic import ConfigDict, Field
|
||||
|
||||
api_prefix = SystemService().system_settings.api_settings.prefix
|
||||
|
||||
chamber_options: list[dict] = [
|
||||
{"label": "Senate", "value": "senate"},
|
||||
{"label": "House", "value": "house"},
|
||||
{"label": "Joint", "value": "joint"},
|
||||
]
|
||||
|
||||
|
||||
class CongressCommitteeInfoQueryParams(QueryParams):
|
||||
"""Congress Committee Info Query Parameters."""
|
||||
|
||||
__json_schema_extra__ = {
|
||||
"chamber": {
|
||||
"x-widget_config": {
|
||||
"label": "Chamber",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {
|
||||
"congress": "$congress",
|
||||
"is_workspace": True,
|
||||
},
|
||||
},
|
||||
},
|
||||
"committee": {
|
||||
"x-widget_config": {
|
||||
"label": "Committee",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {
|
||||
"chamber": "$chamber",
|
||||
"congress": "$congress",
|
||||
"is_workspace": True,
|
||||
},
|
||||
"style": {"popupWidth": 700},
|
||||
"row": 1,
|
||||
},
|
||||
},
|
||||
"subcommittee": {
|
||||
"x-widget_config": {
|
||||
"label": "Subcommittee",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {
|
||||
"chamber": "$chamber",
|
||||
"committee": "$committee",
|
||||
"subcommittees": True,
|
||||
"is_workspace": True,
|
||||
},
|
||||
"style": {"popupWidth": 750},
|
||||
"row": 1,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
chamber: Literal["house", "senate", "joint"] = Field(
|
||||
default="senate",
|
||||
description="Chamber: house, senate, or joint.",
|
||||
)
|
||||
committee: str = Field(
|
||||
default="ssaf00",
|
||||
description="System code of the committee (e.g., ssaf00, hsju00).",
|
||||
)
|
||||
subcommittee: str | None = Field(
|
||||
default=None,
|
||||
description="System code of a subcommittee (e.g., ssga22). Leave empty for parent committee.",
|
||||
)
|
||||
|
||||
|
||||
class CongressCommitteeInfoData(Data):
|
||||
"""Congress Committee Info Data."""
|
||||
|
||||
model_config = ConfigDict(
|
||||
json_schema_extra={
|
||||
"x-widget_config": {
|
||||
"$.type": "markdown",
|
||||
"$.name": "Congressional Committee Info",
|
||||
"$.description": "Membership, subcommittees, and metadata "
|
||||
+ "for a U.S. Congressional Committee. Select a chamber and committee to view details.",
|
||||
"$.category": "Government",
|
||||
"$.subCategory": "Congress",
|
||||
"$.data": {
|
||||
"dataKey": "results.markdown_content",
|
||||
},
|
||||
"$.refetchInterval": False,
|
||||
}
|
||||
}
|
||||
)
|
||||
|
||||
markdown_content: str = Field(
|
||||
description="Committee metadata and membership formatted as Markdown."
|
||||
)
|
||||
raw_data: dict[str, Any] = Field(
|
||||
description="Raw JSON data from the committee detail and member lookups.",
|
||||
json_schema_extra={"x-widget_config": {"exclude": True}},
|
||||
)
|
||||
|
||||
|
||||
class CongressCommitteeInfoFetcher(
|
||||
Fetcher[CongressCommitteeInfoQueryParams, CongressCommitteeInfoData]
|
||||
):
|
||||
"""Congress Committee Info Fetcher."""
|
||||
|
||||
@staticmethod
|
||||
def transform_query(params: dict[str, Any]) -> CongressCommitteeInfoQueryParams:
|
||||
"""Transform the query params."""
|
||||
return CongressCommitteeInfoQueryParams(**params)
|
||||
|
||||
@staticmethod
|
||||
async def aextract_data(
|
||||
query: CongressCommitteeInfoQueryParams,
|
||||
credentials: dict[str, str] | None,
|
||||
**kwargs,
|
||||
) -> dict:
|
||||
"""Extract data from the Congress API."""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import asyncio
|
||||
|
||||
from openbb_congress_gov.utils.committees import get_committee_members
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
|
||||
api_key = credentials.get("congress_gov_api_key", "") if credentials else ""
|
||||
system_code = (
|
||||
query.subcommittee if query.subcommittee else query.committee
|
||||
).lower()
|
||||
chamber = query.chamber.lower()
|
||||
detail_url = (
|
||||
f"https://api.congress.gov/v3/committee/{chamber}/{system_code}"
|
||||
f"?format=json&api_key={api_key}"
|
||||
)
|
||||
|
||||
detail_resp, members = await asyncio.gather(
|
||||
amake_request(detail_url),
|
||||
get_committee_members(system_code),
|
||||
return_exceptions=True,
|
||||
)
|
||||
detail = {} if isinstance(detail_resp, Exception) else detail_resp.get("committee", {}) # type: ignore
|
||||
|
||||
if isinstance(members, Exception):
|
||||
members = []
|
||||
|
||||
return {
|
||||
"chamber": chamber,
|
||||
"system_code": system_code,
|
||||
"detail": detail,
|
||||
"members": members,
|
||||
}
|
||||
|
||||
@staticmethod
|
||||
def transform_data(
|
||||
query: CongressCommitteeInfoQueryParams,
|
||||
data: dict,
|
||||
**kwargs,
|
||||
) -> CongressCommitteeInfoData:
|
||||
"""Transform the raw data into a CongressCommitteeInfoData instance."""
|
||||
chamber = data.get("chamber", "")
|
||||
system_code = data.get("system_code", "")
|
||||
detail = data.get("detail", {})
|
||||
members = data.get("members", [])
|
||||
history = detail.get("history", [])
|
||||
name = ""
|
||||
|
||||
for h in reversed(history):
|
||||
candidate = h.get("officialName") or h.get("libraryOfCongressName") or ""
|
||||
if candidate:
|
||||
name = candidate
|
||||
break
|
||||
|
||||
if not name:
|
||||
name = system_code.upper()
|
||||
|
||||
committee_type = detail.get("type", "")
|
||||
website = detail.get("committeeWebsiteUrl") or ""
|
||||
is_current = detail.get("isCurrent", True)
|
||||
update_date = (detail.get("updateDate") or "")[:10]
|
||||
reports_info = detail.get("reports") or {}
|
||||
bills_info = detail.get("bills") or {}
|
||||
nominations_info = detail.get("nominations") or {}
|
||||
comms_info = detail.get("communications") or {}
|
||||
subcommittees = detail.get("subcommittees") or []
|
||||
md = f"# {name}\n\n"
|
||||
meta_rows = [
|
||||
("Chamber", chamber.title()),
|
||||
("Type", committee_type),
|
||||
("System Code", f"`{system_code}`"),
|
||||
("Current", "Yes" if is_current else "No"),
|
||||
("Last Updated", update_date),
|
||||
]
|
||||
|
||||
if website:
|
||||
meta_rows.append(("Website", f"[{website}]({website})"))
|
||||
|
||||
md += "## Overview\n\n"
|
||||
md += "| Field | Value |\n|---|---|\n"
|
||||
|
||||
for label, val in meta_rows:
|
||||
md += f"| {label} | {val} |\n"
|
||||
|
||||
md += "\n## Activity Counts\n\n"
|
||||
md += "| Type | Count |\n|---|---|\n"
|
||||
|
||||
for label, info in [
|
||||
("Reports", reports_info),
|
||||
("Bills Referred", bills_info),
|
||||
("Nominations", nominations_info),
|
||||
("Communications", comms_info),
|
||||
]:
|
||||
if isinstance(info, dict):
|
||||
count = info.get("count", 0)
|
||||
|
||||
if count:
|
||||
md += f"| {label} | {count:,} |\n"
|
||||
|
||||
if subcommittees:
|
||||
md += f"\n## Subcommittees ({len(subcommittees)})\n\n"
|
||||
|
||||
for sub in subcommittees:
|
||||
sub_name = sub.get("name", "")
|
||||
sub_code = sub.get("systemCode", "")
|
||||
|
||||
if sub_name:
|
||||
md += f"- **{sub_name}** (`{sub_code}`)\n"
|
||||
|
||||
if members:
|
||||
chair = [
|
||||
m
|
||||
for m in members
|
||||
if m.get("title", "").lower()
|
||||
in ("chair", "chairman", "chairwoman", "chairperson")
|
||||
]
|
||||
ranking = [m for m in members if "ranking" in m.get("title", "").lower()]
|
||||
rest = [m for m in members if m not in chair and m not in ranking]
|
||||
md += f"\n## Members ({len(members)})\n\n"
|
||||
md += "| Name | Party | Title |\n|---|---|---|\n"
|
||||
|
||||
for m in chair + ranking + rest:
|
||||
name_val = m.get("name", "Unknown")
|
||||
party = m.get("party", "")
|
||||
title = m.get("title") or "Member"
|
||||
md += f"| {name_val} | {party} | {title} |\n"
|
||||
else:
|
||||
md += "\n*Member data not available for this committee.*\n"
|
||||
|
||||
if history:
|
||||
md += "\n## Historical Names\n\n"
|
||||
|
||||
for h in history:
|
||||
official = h.get("officialName") or h.get("libraryOfCongressName") or ""
|
||||
start = (h.get("startDate") or "")[:10]
|
||||
end = (h.get("endDate") or "present")[:10]
|
||||
if official:
|
||||
md += f"- {official} ({start} – {end})\n"
|
||||
|
||||
return CongressCommitteeInfoData(
|
||||
markdown_content=md,
|
||||
raw_data=data,
|
||||
)
|
||||
277
openbb_platform/providers/congress_gov/openbb_congress_gov/router/apps.json
vendored
Normal file
277
openbb_platform/providers/congress_gov/openbb_congress_gov/router/apps.json
vendored
Normal file
@@ -0,0 +1,277 @@
|
||||
[{
|
||||
"name": "The United States Congress",
|
||||
"img": "https://www.congress.gov/img/opengraph1200by630.jpg",
|
||||
"img_dark": "https://www.congress.gov/img/opengraph1200by630.jpg",
|
||||
"img_light": "https://www.congress.gov/img/opengraph1200by630.jpg",
|
||||
"description": "Find and view US federal legislative information and complete bill text.",
|
||||
"allowCustomization": true,
|
||||
"tabs": {
|
||||
"bills": {
|
||||
"id": "bills",
|
||||
"name": "Bills",
|
||||
"layout": [
|
||||
{
|
||||
"i": "uscongress_bills_congress_gov_obb",
|
||||
"x": 0,
|
||||
"y": 11,
|
||||
"w": 40,
|
||||
"h": 11,
|
||||
"state": {
|
||||
"paramOrder": [
|
||||
"congress",
|
||||
"bill_type",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"limit",
|
||||
"offset",
|
||||
"sort_by",
|
||||
"bill_url"
|
||||
],
|
||||
"chartView": {
|
||||
"enabled": false,
|
||||
"chartType": "line"
|
||||
},
|
||||
"columnState": {
|
||||
"default": {
|
||||
"columnVisibility": {
|
||||
"hiddenColIds": [
|
||||
"origin_chamber_code"
|
||||
]
|
||||
},
|
||||
"columnOrder": {
|
||||
"orderedColIds": [
|
||||
"update_date",
|
||||
"latest_action_date",
|
||||
"bill_url",
|
||||
"congress",
|
||||
"bill_number",
|
||||
"origin_chamber",
|
||||
"origin_chamber_code",
|
||||
"bill_type",
|
||||
"title",
|
||||
"latest_action",
|
||||
"update_date_including_text"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
"Group 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": "uscongress_bill_text_congress_gov_obb",
|
||||
"x": 16,
|
||||
"y": 22,
|
||||
"w": 24,
|
||||
"h": 31,
|
||||
"state": {
|
||||
"params": {
|
||||
"bill_url": "https://api.congress.gov/v3/bill/119/hr/6967?format=json",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/bills/hr6967/BILLS-119hr6967rh.pdf"
|
||||
]
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
"Group 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": "uscongress_bill_info_congress_gov_obb",
|
||||
"x": 0,
|
||||
"y": 22,
|
||||
"w": 16,
|
||||
"h": 31,
|
||||
"state": {
|
||||
"params": {
|
||||
"bill_url": "119/hr/4553"
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
"Group 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": "rich_note-01805711-1294-41d8-9a4b-956d46fa77e3",
|
||||
"x": 0,
|
||||
"y": 2,
|
||||
"w": 40,
|
||||
"h": 9,
|
||||
"state": {
|
||||
"storage": {
|
||||
"html": "<h2 style=\"text-align: left;\">How To Use</h2><p style=\"text-align: left;\">The Congress number is a sequential number representing the formed Congress for the elected period. As of 2026, the current Congress number is 119. Leaving empty will populate the 100 most recent actions.</p><p style=\"text-align: left;\">You can narrow the field by selecting a bill type, restricting dates, or adjusting the limit and offset parameters.</p><p style=\"text-align: left;\">The 3 widgets on this tab are grouped by the \"Bill URL\" column.</p><p style=\"text-align: left;\"><strong>NOTE: Clicking on the cell in the whitespace beside \"Link\" will change the loaded bill in the two widgets below. Don't click the Link directly, but click to the right of it.</strong></p><p style=\"text-align: left;\"><strong>You can also use shorthand to manually enter bills - `{congress}/{bill_type}/{bill_number}`</strong></p><p style=\"text-align: left;\">Some bills may not have any formal text, directly, such as resolutions. If it has not been introduced in the House, it will likely not have any text to display for the viewer. Items from today may not be immediately available to the public via API.</p><p style=\"text-align: left;\"></p><p></p>"
|
||||
}
|
||||
},
|
||||
"groups": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"ammendments": {
|
||||
"id": "ammendments",
|
||||
"name": "Ammendments",
|
||||
"layout": [
|
||||
{
|
||||
"i": "uscongress_amendments_congress_gov_obb",
|
||||
"x": 0,
|
||||
"y": 10,
|
||||
"w": 40,
|
||||
"h": 11,
|
||||
"state": {
|
||||
"paramOrder": [
|
||||
"congress",
|
||||
"amendment_type",
|
||||
"start_date",
|
||||
"end_date",
|
||||
"limit",
|
||||
"offset",
|
||||
"sort_by",
|
||||
"amendment_url"
|
||||
],
|
||||
"params": {
|
||||
"congress": "119",
|
||||
"amendment_type": "samdt",
|
||||
"limit": "100"
|
||||
},
|
||||
"chartView": {
|
||||
"enabled": false,
|
||||
"chartType": "line"
|
||||
},
|
||||
"columnState": {
|
||||
"default": {
|
||||
"columnOrder": {
|
||||
"orderedColIds": [
|
||||
"congress",
|
||||
"amendment_type",
|
||||
"number",
|
||||
"update_date",
|
||||
"amendment_url",
|
||||
"amended_bill",
|
||||
"amended_bill_title",
|
||||
"sponsor",
|
||||
"submitted_date"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
"Group 2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": "uscongress_amendment_info_congress_gov_obb",
|
||||
"x": 0,
|
||||
"y": 21,
|
||||
"w": 14,
|
||||
"h": 27,
|
||||
"groups": [
|
||||
"Group 2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": "uscongress_amendment_text_congress_gov_obb",
|
||||
"x": 14,
|
||||
"y": 21,
|
||||
"w": 26,
|
||||
"h": 27,
|
||||
"state": {
|
||||
"params": {
|
||||
"amendment_url": "https://api.congress.gov/v3/amendment/119/samdt/4743?format=json",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/crec/2026/03/21/172/52/CREC-2026-03-21-pt1-PgS1484-6.pdf"
|
||||
]
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
"Group 2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"i": "rich_note-ba4ed537-f663-4dea-be62-3513bee784a5",
|
||||
"x": 0,
|
||||
"y": 2,
|
||||
"w": 40,
|
||||
"h": 8,
|
||||
"state": {
|
||||
"storage": {
|
||||
"html": "<h2 style=\"text-align: left;\">How To Use</h2><p style=\"text-align: left;\">These widgets work the same way as three on the <strong>Bills</strong> tab.</p><p style=\"text-align: left;\">Click to the right of the \"Link\" in the Amendment URL column to change the loaded ammendment.</p><p style=\"text-align: left;\">With no Congress number, the 100 most recent amendments are surfaced. To filter them by type, you must enter a Congress number.</p><p style=\"text-align: left;\">Some amendments, like those from the Senate, reference Congressional Record text as the source, while others link to the bills themselves.</p><p style=\"text-align: left;\">On a working day, there may be hundreds of amendments appended to the same bill. Each amendment number is a unique record.</p>"
|
||||
}
|
||||
},
|
||||
"groups": []
|
||||
}
|
||||
]
|
||||
},
|
||||
"committees": {
|
||||
"id": "committees",
|
||||
"name": "Committees",
|
||||
"layout": [
|
||||
{
|
||||
"i": "uscongress_committee_document_viewer_congress_gov_obb",
|
||||
"x": 0,
|
||||
"y": 9,
|
||||
"w": 40,
|
||||
"h": 26,
|
||||
"state": {
|
||||
"params": {
|
||||
"chamber": "house",
|
||||
"committee": "hsju00",
|
||||
"doc_type": "report",
|
||||
"congress": "119",
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/crpt/hrpt541/CRPT-119hrpt541.pdf"
|
||||
]
|
||||
}
|
||||
},
|
||||
"groups": []
|
||||
},
|
||||
{
|
||||
"i": "rich_note-ab1c1d5a-f476-4dd9-b9be-88042eef2583",
|
||||
"x": 0,
|
||||
"y": 2,
|
||||
"w": 40,
|
||||
"h": 7,
|
||||
"state": {
|
||||
"storage": {
|
||||
"html": "<h2 style=\"text-align: left;\">How To Use</h2><p style=\"text-align: left;\">Congressional Committees produce different types of documents, this widget exposes them as a hierarchy:</p><p style=\"text-align: left;\">Congress -> Chamber -> Committee -> Subcommittee -> Document Type</p><p style=\"text-align: left;\">When no subcommittee, the documents reflect the parent committee.</p><p style=\"text-align: left;\">Some committee meetings are only available as video, events producing no documents are omitted. <a target=\"_blank\" rel=\"noopener noreferrer nofollow\" class=\"obb-hyper-link\" href=\"http://Congress.gov\">Congress.gov</a> includes files that are not properly encoded at the source, and those will result in \"Failed to load PDF file.\"</p>"
|
||||
}
|
||||
},
|
||||
"groups": []
|
||||
}
|
||||
]
|
||||
}
|
||||
},
|
||||
"groups": [
|
||||
{
|
||||
"name": "Group 1",
|
||||
"type": "param",
|
||||
"paramName": "bill_url",
|
||||
"defaultValue": "https://api.congress.gov/v3/bill/119/hr/6967?format=json"
|
||||
},
|
||||
{
|
||||
"name": "Group 2",
|
||||
"type": "param",
|
||||
"paramName": "amendment_url",
|
||||
"defaultValue": "https://api.congress.gov/v3/amendment/119/samdt/4743?format=json"
|
||||
},
|
||||
{
|
||||
"name": "Group 3",
|
||||
"type": "param",
|
||||
"paramName": "chamber",
|
||||
"defaultValue": "house"
|
||||
},
|
||||
{
|
||||
"name": "Group 4",
|
||||
"type": "param",
|
||||
"paramName": "law_url",
|
||||
"defaultValue": "119/s/3705"
|
||||
},
|
||||
{
|
||||
"name": "Group 5",
|
||||
"type": "endpointParam",
|
||||
"paramName": "subcommittee",
|
||||
"defaultValue": "senate"
|
||||
}
|
||||
]
|
||||
}]
|
||||
@@ -1,7 +1,15 @@
|
||||
# pylint: disable=import-outside-toplevel,unused-argument
|
||||
"""US Congress Router."""
|
||||
|
||||
# pylint: disable=import-outside-toplevel,unused-argument,too-many-positional-arguments
|
||||
|
||||
from typing import Any
|
||||
|
||||
from fastapi.exceptions import HTTPException
|
||||
from openbb_congress_gov.utils.constants import (
|
||||
COMMITTEES,
|
||||
SUBCOMMITTEES,
|
||||
chamber_options,
|
||||
)
|
||||
from openbb_core.app.model.command_context import CommandContext
|
||||
from openbb_core.app.model.example import APIEx
|
||||
from openbb_core.app.model.obbject import OBBject
|
||||
@@ -14,6 +22,7 @@ from openbb_core.app.query import Query as OpenBBQuery
|
||||
from openbb_core.app.router import Router
|
||||
from openbb_core.app.service.system_service import SystemService
|
||||
|
||||
NO_SUBCOMMITTEES = [{"label": "None (Parent Committee)", "value": ""}]
|
||||
router = Router(prefix="", description="Data connector to Congress.gov API.")
|
||||
api_prefix = SystemService().system_settings.api_settings.prefix
|
||||
|
||||
@@ -249,3 +258,517 @@ async def bill_text(
|
||||
In OpenBB Workspace, this command returns as a multi-file viewer widget.
|
||||
"""
|
||||
return (await OBBject.from_query(OpenBBQuery(**locals()))).results # type: ignore[return-value]
|
||||
|
||||
|
||||
@router.command(
|
||||
model="CongressAmendments",
|
||||
examples=[
|
||||
APIEx(parameters={"provider": "congress_gov"}),
|
||||
APIEx(
|
||||
parameters={
|
||||
"congress": 119,
|
||||
"amendment_type": "hamdt",
|
||||
"provider": "congress_gov",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
async def amendments(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Get and filter lists of Congressional Amendments."""
|
||||
return await OBBject.from_query(OpenBBQuery(**locals()))
|
||||
|
||||
|
||||
@router.command(
|
||||
methods=["GET"],
|
||||
examples=[
|
||||
APIEx(
|
||||
parameters={
|
||||
"provider": "congress_gov",
|
||||
"amendment_url": "119/hamdt/2",
|
||||
},
|
||||
),
|
||||
],
|
||||
openapi_extra={
|
||||
"widget_config": {
|
||||
"name": "Congressional Amendment Viewer",
|
||||
"description": "View text documents for a U.S. Congressional Amendment.",
|
||||
"category": "Government",
|
||||
"subCategory": "Congress",
|
||||
"type": "multi_file_viewer",
|
||||
"widgetId": "uscongress_amendment_text_congress_gov_obb",
|
||||
"endpoint": f"{api_prefix}/uscongress/amendment_text",
|
||||
"params": [
|
||||
{
|
||||
"paramName": "urls",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/amendment_text_urls",
|
||||
"optionsParams": {
|
||||
"amendment_url": "$amendment_url",
|
||||
"is_workspace": True,
|
||||
},
|
||||
"show": False,
|
||||
"multiSelect": True,
|
||||
"roles": ["fileSelector"],
|
||||
},
|
||||
{
|
||||
"paramName": "is_workspace",
|
||||
"value": True,
|
||||
"show": False,
|
||||
},
|
||||
{
|
||||
"label": "Amendment URL",
|
||||
"description": "Enter an amendment shorthand (e.g., '119/hamdt/2')."
|
||||
+ " Create a group on the 'amendment_url' field of the 'Congressional Amendments' widget"
|
||||
+ " and click on the cell to view the available documents.",
|
||||
"show": True,
|
||||
"paramName": "amendment_url",
|
||||
"value": "119/hamdt/2",
|
||||
},
|
||||
],
|
||||
"refetchInterval": False,
|
||||
}
|
||||
},
|
||||
)
|
||||
async def amendment_text_urls(
|
||||
amendment_url: str,
|
||||
provider: str = "congress_gov",
|
||||
is_workspace: bool = False,
|
||||
) -> list:
|
||||
"""Get document choices for a specific amendment.
|
||||
|
||||
This function is used by the Congressional Amendment Viewer widget, in OpenBB Workspace,
|
||||
to populate document choices for the selected amendment.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_congress_gov.utils.helpers import get_amendment_text_choices
|
||||
|
||||
if not amendment_url and is_workspace is True:
|
||||
return [
|
||||
{
|
||||
"label": "Enter a valid amendment URL to view available documents.",
|
||||
"value": "",
|
||||
}
|
||||
]
|
||||
|
||||
if not amendment_url:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Amendment URL is required. Please provide a valid amendment shorthand (e.g., '119/hamdt/2').",
|
||||
)
|
||||
|
||||
return await get_amendment_text_choices(
|
||||
amendment_url=amendment_url, is_workspace=is_workspace
|
||||
)
|
||||
|
||||
|
||||
@router.command(
|
||||
model="CongressAmendmentInfo",
|
||||
examples=[
|
||||
APIEx(
|
||||
parameters={
|
||||
"provider": "congress_gov",
|
||||
"amendment_url": "119/hamdt/2",
|
||||
}
|
||||
),
|
||||
],
|
||||
)
|
||||
async def amendment_info(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Get details for a specific amendment.
|
||||
|
||||
Enter the amendment identifier as: {congress}/{type}/{number} (e.g., '119/hamdt/2').
|
||||
|
||||
In OpenBB Workspace, this command returns as a Markdown widget.
|
||||
"""
|
||||
return await OBBject.from_query(OpenBBQuery(**locals()))
|
||||
|
||||
|
||||
@router.command(
|
||||
model="CongressAmendmentText",
|
||||
response_model=list,
|
||||
methods=["POST"],
|
||||
examples=[
|
||||
APIEx(
|
||||
parameters={
|
||||
"provider": "congress_gov",
|
||||
"urls": ["https://www.congress.gov/119/bills/hamdt2/HAMDT2.pdf"],
|
||||
}
|
||||
),
|
||||
],
|
||||
openapi_extra={
|
||||
"widget_config": {
|
||||
"exclude": True,
|
||||
}
|
||||
},
|
||||
)
|
||||
async def amendment_text(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Download amendment document(s) from Congress.gov.
|
||||
|
||||
Note: This endpoint returns only the results array of the OBBject.
|
||||
"""
|
||||
return (await OBBject.from_query(OpenBBQuery(**locals()))).results # type: ignore[return-value]
|
||||
|
||||
|
||||
@router.command(
|
||||
model="CongressCommitteeInfo",
|
||||
examples=[
|
||||
APIEx(
|
||||
parameters={
|
||||
"chamber": "senate",
|
||||
"committee": "ssaf00",
|
||||
"provider": "congress_gov",
|
||||
}
|
||||
),
|
||||
APIEx(
|
||||
parameters={
|
||||
"chamber": "house",
|
||||
"committee": "hsju00",
|
||||
"provider": "congress_gov",
|
||||
}
|
||||
),
|
||||
APIEx(
|
||||
description="Get info for a subcommittee.",
|
||||
parameters={
|
||||
"chamber": "senate",
|
||||
"committee": "ssga00",
|
||||
"subcommittee": "ssga22",
|
||||
"provider": "congress_gov",
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def committee_info(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Get metadata and membership for a single U.S. Congressional Committee.
|
||||
|
||||
Fetches the committee detail (type, website, subcommittees, activity counts)
|
||||
and current member roster with party affiliations and leadership titles.
|
||||
|
||||
Select a chamber, committee, and optional subcommittee to view details.
|
||||
"""
|
||||
return await OBBject.from_query(OpenBBQuery(**locals()))
|
||||
|
||||
|
||||
@router.command(
|
||||
model="CongressCommitteeDocuments",
|
||||
openapi_extra={"widget_config": {"exclude": True}},
|
||||
examples=[
|
||||
APIEx(
|
||||
description="Get reports from the Senate Agriculture Committee.",
|
||||
parameters={
|
||||
"chamber": "senate",
|
||||
"committee": "ssaf00",
|
||||
"doc_type": "report",
|
||||
"provider": "congress_gov",
|
||||
},
|
||||
),
|
||||
APIEx(
|
||||
description="Get hearings from the House Judiciary Committee for the 119th Congress.",
|
||||
parameters={
|
||||
"chamber": "house",
|
||||
"committee": "hsju00",
|
||||
"doc_type": "meeting",
|
||||
"congress": 119,
|
||||
"provider": "congress_gov",
|
||||
},
|
||||
),
|
||||
],
|
||||
)
|
||||
async def committee_documents(
|
||||
cc: CommandContext,
|
||||
provider_choices: ProviderChoices,
|
||||
standard_params: StandardParams,
|
||||
extra_params: ExtraParams,
|
||||
) -> OBBject:
|
||||
"""Get documents (reports, hearings, prints, meetings) produced by a single Congressional Committee.
|
||||
|
||||
Select a chamber, committee, and optional subcommittee.
|
||||
"""
|
||||
return await OBBject.from_query(OpenBBQuery(**locals()))
|
||||
|
||||
|
||||
@router.command(
|
||||
methods=["GET"],
|
||||
openapi_extra={"widget_config": {"exclude": True}},
|
||||
)
|
||||
async def committee_choices(
|
||||
chamber: str | None = None,
|
||||
congress: int | None = None,
|
||||
committee: str | None = None,
|
||||
subcommittees: bool = False,
|
||||
provider: str = "congress_gov",
|
||||
is_workspace: bool = False,
|
||||
) -> list:
|
||||
"""Get committee or subcommittee choices for cascading dropdowns."""
|
||||
if not chamber:
|
||||
return chamber_options
|
||||
|
||||
chamber = chamber.lower()
|
||||
|
||||
if subcommittees and not committee:
|
||||
return [{"label": "Select a committee first.", "value": ""}]
|
||||
|
||||
if subcommittees and committee:
|
||||
return SUBCOMMITTEES.get(f"{chamber}/{committee}", NO_SUBCOMMITTEES)
|
||||
|
||||
if chamber not in ("senate", "house", "joint"):
|
||||
return [{"label": "Invalid chamber.", "value": ""}]
|
||||
|
||||
return COMMITTEES.get(chamber, [{"label": "No committees found.", "value": ""}])
|
||||
|
||||
|
||||
@router.command(
|
||||
methods=["GET"],
|
||||
examples=[
|
||||
APIEx(
|
||||
parameters={
|
||||
"provider": "congress_gov",
|
||||
"chamber": "senate",
|
||||
"committee": "ssaf00",
|
||||
},
|
||||
),
|
||||
],
|
||||
openapi_extra={
|
||||
"widget_config": {
|
||||
"name": "Committee Document Viewer",
|
||||
"description": "Browse and view documents for a U.S. Congressional Committee.",
|
||||
"category": "Government",
|
||||
"subCategory": "Congress",
|
||||
"type": "multi_file_viewer",
|
||||
"widgetId": "uscongress_committee_document_viewer_congress_gov_obb",
|
||||
"endpoint": f"{api_prefix}/uscongress/bill_text",
|
||||
"params": [
|
||||
{
|
||||
"paramName": "urls",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_document_urls",
|
||||
"optionsParams": {
|
||||
"chamber": "$chamber",
|
||||
"committee": "$committee",
|
||||
"subcommittee": "$subcommittee",
|
||||
"doc_type": "$doc_type",
|
||||
"congress": "$congress",
|
||||
"is_workspace": True,
|
||||
},
|
||||
"show": False,
|
||||
"multiSelect": True,
|
||||
"roles": ["fileSelector"],
|
||||
},
|
||||
{
|
||||
"paramName": "is_workspace",
|
||||
"value": True,
|
||||
"show": False,
|
||||
},
|
||||
{
|
||||
"label": "Congress",
|
||||
"description": "Congress number (e.g. 119).",
|
||||
"show": True,
|
||||
"paramName": "congress",
|
||||
"value": 119,
|
||||
"type": "number",
|
||||
},
|
||||
{
|
||||
"label": "Chamber",
|
||||
"show": True,
|
||||
"paramName": "chamber",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {"congress": "$congress", "is_workspace": True},
|
||||
},
|
||||
{
|
||||
"label": "Committee",
|
||||
"show": True,
|
||||
"paramName": "committee",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {
|
||||
"chamber": "$chamber",
|
||||
"congress": "$congress",
|
||||
"is_workspace": True,
|
||||
},
|
||||
"style": {"popupWidth": 750},
|
||||
},
|
||||
{
|
||||
"label": "Subcommittee",
|
||||
"show": True,
|
||||
"paramName": "subcommittee",
|
||||
"type": "endpoint",
|
||||
"optionsEndpoint": f"{api_prefix}/uscongress/committee_choices",
|
||||
"optionsParams": {
|
||||
"chamber": "$chamber",
|
||||
"committee": "$committee",
|
||||
"subcommittees": True,
|
||||
"is_workspace": True,
|
||||
},
|
||||
"style": {"popupWidth": 750},
|
||||
},
|
||||
{
|
||||
"label": "Document Type",
|
||||
"description": "Type of committee document to browse.",
|
||||
"show": True,
|
||||
"paramName": "doc_type",
|
||||
"value": "meeting",
|
||||
"options": [
|
||||
{"label": "Reports", "value": "report"},
|
||||
{"label": "Meetings & Hearings", "value": "meeting"},
|
||||
{"label": "Publications & Prints", "value": "publication"},
|
||||
{"label": "Legislation", "value": "legislation"},
|
||||
],
|
||||
},
|
||||
],
|
||||
"refetchInterval": False,
|
||||
}
|
||||
},
|
||||
)
|
||||
async def committee_document_urls(
|
||||
chamber: str,
|
||||
committee: str,
|
||||
subcommittee: str | None = None,
|
||||
doc_type: str = "all",
|
||||
congress: int | None = None,
|
||||
provider: str = "congress_gov",
|
||||
is_workspace: bool = False,
|
||||
use_cache: bool = True,
|
||||
) -> list:
|
||||
"""Get document choices for a Congressional Committee.
|
||||
|
||||
This endpoint populates the Committee Document Viewer file selector
|
||||
with the committee's available documents by type.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import datetime
|
||||
import re as _re
|
||||
|
||||
from openbb_congress_gov.utils.committees import fetch_committee_documents
|
||||
from openbb_congress_gov.utils.helpers import (
|
||||
check_api_key,
|
||||
year_to_congress,
|
||||
)
|
||||
|
||||
if not committee and is_workspace is True:
|
||||
return [
|
||||
{
|
||||
"label": "Select a committee to view available documents.",
|
||||
"value": "",
|
||||
}
|
||||
]
|
||||
|
||||
if not committee:
|
||||
raise HTTPException(
|
||||
status_code=500,
|
||||
detail="Committee system code is required.",
|
||||
)
|
||||
|
||||
api_key = check_api_key()
|
||||
system_code = (subcommittee or committee).lower()
|
||||
|
||||
if congress is None:
|
||||
congress = year_to_congress(datetime.date.today().year)
|
||||
|
||||
items = await fetch_committee_documents(
|
||||
chamber=chamber.lower(),
|
||||
system_code=system_code,
|
||||
congress=congress,
|
||||
doc_type=doc_type,
|
||||
api_key=api_key,
|
||||
use_cache=use_cache,
|
||||
)
|
||||
|
||||
def _clean_label(text: str) -> str:
|
||||
text = _re.sub(r"\s*\[TEXT NOT AVAILABLE[^\]]*\]", "", text)
|
||||
text = _re.sub(r"\s*\[REFER TO[^\]]*\]", "", text)
|
||||
return text.strip()
|
||||
|
||||
_date_re = _re.compile(r"^\[(\d{4}-\d{2}-\d{2})\]\s*")
|
||||
|
||||
choices = []
|
||||
|
||||
for item in items:
|
||||
citation = item.get("citation") or ""
|
||||
title = _clean_label(item.get("title") or "")
|
||||
short_cite = ""
|
||||
|
||||
if citation:
|
||||
cite_m = _re.match(
|
||||
r"((?:S|H)\.\s*(?:Hrg|Rept|Rpt|Prt|Doc)\.\s*\d{2,3}-\d+(?:,\s*(?:Book|Part)\s*\d+)?)",
|
||||
citation,
|
||||
)
|
||||
if cite_m:
|
||||
short_cite = cite_m.group(1)
|
||||
|
||||
date_m = _date_re.match(title)
|
||||
date_prefix = ""
|
||||
if date_m:
|
||||
date_prefix = f"[{date_m.group(1)}] "
|
||||
title = title[date_m.end() :]
|
||||
|
||||
if short_cite and title:
|
||||
label = f"{date_prefix}{short_cite} — {title}"
|
||||
elif title:
|
||||
label = f"{date_prefix}{title}"
|
||||
elif citation:
|
||||
label = date_prefix + _re.sub(r"\s*\(.*?\)\s*$", "", citation).strip()
|
||||
else:
|
||||
label = date_prefix + item.get("doc_url", "Unknown")
|
||||
|
||||
choices.append({"label": label, "value": item.get("doc_url", "")})
|
||||
|
||||
choices.sort(key=lambda c: c["label"], reverse=True)
|
||||
|
||||
if not choices:
|
||||
return [{"label": "No documents found.", "value": ""}]
|
||||
|
||||
return choices
|
||||
|
||||
|
||||
async def get_congress_gov_apps_json() -> list[dict[str, Any]]:
|
||||
"""Get the IMF apps.json file.
|
||||
|
||||
This endpoint serves the apps.json file containing OpenBB Workspace app configurations
|
||||
related to IMF data and utilities.
|
||||
|
||||
It is automatically merged with any existing apps.json files in the Workspace and API.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[dict[str, Any]]
|
||||
A list of OpenBB Workspace app configurations.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import json
|
||||
from pathlib import Path
|
||||
|
||||
apps_file = Path(__file__).parent / "apps.json"
|
||||
|
||||
try:
|
||||
with apps_file.open("r", encoding="utf-8") as f:
|
||||
apps_json = json.load(f)
|
||||
return apps_json
|
||||
except Exception:
|
||||
return []
|
||||
|
||||
|
||||
router._api_router.add_api_route(
|
||||
path="/apps.json",
|
||||
endpoint=get_congress_gov_apps_json,
|
||||
methods=["GET"],
|
||||
include_in_schema=False,
|
||||
)
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,219 @@
|
||||
"""Async congress.gov search client for committee documents.
|
||||
|
||||
Adapted from the top-level ``congress_search.py`` for use inside the
|
||||
openbb_congress_gov provider package. Exposes only the async internals
|
||||
so callers already running in an event loop can ``await`` directly.
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import math
|
||||
import re
|
||||
from typing import Any, Literal
|
||||
|
||||
import httpx
|
||||
|
||||
_BASE_URL = "https://www.congress.gov/search"
|
||||
_HOME_URL = "https://www.congress.gov/"
|
||||
|
||||
ALL_SOURCES = ["comreports", "committee-publications", "committee-meetings"]
|
||||
|
||||
_PAGE_SIZE = 250
|
||||
|
||||
Chamber = Literal["house", "senate", "joint"]
|
||||
|
||||
_CHAMBER_KEY: dict[str, str] = {
|
||||
"house": "house-committee",
|
||||
"senate": "senate-committee",
|
||||
"joint": "joint-committee",
|
||||
}
|
||||
|
||||
_HEADERS = {
|
||||
"User-Agent": (
|
||||
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) "
|
||||
"AppleWebKit/537.36 (KHTML, like Gecko) "
|
||||
"Chrome/122.0.0.0 Safari/537.36"
|
||||
),
|
||||
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
|
||||
"Accept-Language": "en-US,en;q=0.9",
|
||||
"Accept-Encoding": "gzip, deflate, br",
|
||||
"sec-ch-ua": '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
"sec-ch-ua-mobile": "?0",
|
||||
"Sec-Fetch-Dest": "document",
|
||||
"Sec-Fetch-Mode": "navigate",
|
||||
"Sec-Fetch-Site": "none",
|
||||
"Upgrade-Insecure-Requests": "1",
|
||||
"Cache-Control": "max-age=0",
|
||||
}
|
||||
|
||||
_HTML_ENTITIES = {
|
||||
"—": "\u2014",
|
||||
"–": "\u2013",
|
||||
"&": "&",
|
||||
" ": " ",
|
||||
"<": "<",
|
||||
">": ">",
|
||||
""": '"',
|
||||
"'": "'",
|
||||
"'": "'",
|
||||
}
|
||||
|
||||
|
||||
def _decode(text: str) -> str:
|
||||
for ent, char in _HTML_ENTITIES.items():
|
||||
text = text.replace(ent, char)
|
||||
return re.sub(r"\s+", " ", text).strip()
|
||||
|
||||
|
||||
def _parse_page(html: str) -> list[dict[str, Any]]:
|
||||
sec = re.search(
|
||||
r'<ol[^>]*class="[^"]*results[^"]*"[^>]*>(.*?)</ol>', html, re.DOTALL
|
||||
)
|
||||
if not sec:
|
||||
return []
|
||||
|
||||
raw_items = re.findall(r"<li[^>]*>(.*?)</li>", sec.group(1), re.DOTALL)
|
||||
results: list[dict[str, Any]] = []
|
||||
|
||||
for item in raw_items[::2]:
|
||||
vi = re.search(r'class="visualIndicator">([^<]+)<', item)
|
||||
if not vi:
|
||||
continue
|
||||
doc_type = vi.group(1).strip()
|
||||
|
||||
href_m = re.search(r'class="result-heading".*?href="(/[^"?]+)', item, re.DOTALL)
|
||||
url = f"https://www.congress.gov{href_m.group(1)}" if href_m else ""
|
||||
if not url:
|
||||
continue
|
||||
|
||||
heading_m = re.search(r'class="result-heading">(.*?)</span>', item, re.DOTALL)
|
||||
heading = (
|
||||
_decode(re.sub(r"<[^>]+>", " ", heading_m.group(1))) if heading_m else ""
|
||||
)
|
||||
|
||||
title_m = re.search(r'class="result-title">(.*?)</span>', item, re.DOTALL)
|
||||
title = _decode(re.sub(r"<[^>]+>", " ", title_m.group(1))) if title_m else ""
|
||||
|
||||
doc: dict[str, Any] = {
|
||||
"type": doc_type,
|
||||
"url": url,
|
||||
"heading": heading,
|
||||
}
|
||||
if title:
|
||||
doc["title"] = title
|
||||
|
||||
for span in re.findall(r'class="result-item">(.*?)</span>', item, re.DOTALL):
|
||||
key_m = re.search(r"<strong>([^<]+):</strong>(.*)", span, re.DOTALL)
|
||||
if key_m:
|
||||
key = key_m.group(1).strip()
|
||||
val = _decode(re.sub(r"<[^>]+>", " ", key_m.group(2)))
|
||||
doc[key] = val
|
||||
else:
|
||||
text = _decode(re.sub(r"<[^>]+>", " ", span))
|
||||
if text:
|
||||
doc.setdefault("date", text)
|
||||
|
||||
results.append(doc)
|
||||
|
||||
return results
|
||||
|
||||
|
||||
def _get_total(html: str) -> int:
|
||||
m = re.search(r"[\d,]+\s*-\s*[\d,]+\s*of\s*([\d,]+)", html)
|
||||
return int(m.group(1).replace(",", "")) if m else 0
|
||||
|
||||
|
||||
async def _fetch_page(
|
||||
session: httpx.AsyncClient,
|
||||
q: str,
|
||||
page: int,
|
||||
sem: asyncio.Semaphore,
|
||||
) -> str:
|
||||
async with sem:
|
||||
r = await session.get(
|
||||
_BASE_URL,
|
||||
params={"q": q, "pageSize": str(_PAGE_SIZE), "page": str(page)},
|
||||
)
|
||||
r.raise_for_status()
|
||||
return r.text
|
||||
|
||||
|
||||
async def _run_q(
|
||||
q: str,
|
||||
congress: int,
|
||||
max_concurrent: int,
|
||||
) -> list[dict[str, Any]]:
|
||||
sem = asyncio.Semaphore(max_concurrent)
|
||||
|
||||
async with httpx.AsyncClient(
|
||||
headers=_HEADERS, follow_redirects=True, timeout=30
|
||||
) as session:
|
||||
await session.get(_HOME_URL)
|
||||
await asyncio.sleep(0.4)
|
||||
|
||||
page1_html = await _fetch_page(session, q, 1, sem)
|
||||
total = _get_total(page1_html)
|
||||
docs = _parse_page(page1_html)
|
||||
|
||||
if total > _PAGE_SIZE:
|
||||
n_pages = math.ceil(total / _PAGE_SIZE)
|
||||
remaining = await asyncio.gather(
|
||||
*[_fetch_page(session, q, p, sem) for p in range(2, n_pages + 1)],
|
||||
return_exceptions=True,
|
||||
)
|
||||
for result in remaining:
|
||||
if isinstance(result, str):
|
||||
docs.extend(_parse_page(result))
|
||||
|
||||
for d in docs:
|
||||
d["congress"] = congress
|
||||
|
||||
return docs
|
||||
|
||||
|
||||
async def search_async(
|
||||
congress: int,
|
||||
sources: list[str],
|
||||
committee: str | None = None,
|
||||
chamber: Chamber | None = None,
|
||||
max_concurrent: int = 4,
|
||||
) -> list[dict[str, Any]]:
|
||||
"""Search congress.gov for committee documents (async).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
congress
|
||||
Congress number (e.g. 119).
|
||||
sources
|
||||
Document-type keys, subset of ``ALL_SOURCES``.
|
||||
committee
|
||||
Committee display name (e.g. "Armed Services").
|
||||
chamber
|
||||
"house", "senate", or "joint". Required when *committee* is set
|
||||
and the same name exists in multiple chambers.
|
||||
max_concurrent
|
||||
Max parallel HTTP requests.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[dict]
|
||||
Each dict has ``type``, ``url``, ``heading``, and optional
|
||||
``title``, ``Committee``, ``date``, etc.
|
||||
"""
|
||||
q_dict: dict[str, Any] = {"source": sources, "congress": str(congress)}
|
||||
if committee is not None:
|
||||
if chamber is not None:
|
||||
q_dict[_CHAMBER_KEY[chamber]] = committee
|
||||
else:
|
||||
seen_urls: set[str] = set()
|
||||
merged: list[dict[str, Any]] = []
|
||||
for ch in ("house", "senate", "joint"):
|
||||
sub_q = {**q_dict, _CHAMBER_KEY[ch]: committee}
|
||||
sub_docs = await _run_q(json.dumps(sub_q), congress, max_concurrent)
|
||||
for d in sub_docs:
|
||||
if d["url"] not in seen_urls:
|
||||
seen_urls.add(d["url"])
|
||||
merged.append(d)
|
||||
return merged
|
||||
|
||||
return await _run_q(json.dumps(q_dict), congress, max_concurrent)
|
||||
@@ -70,3 +70,580 @@ A resolution affecting the House of Representatives is designated “H.Res.” f
|
||||
They are not presented to the President for action.
|
||||
|
||||
"""
|
||||
LawTypes: list = ["pub", "priv"]
|
||||
|
||||
law_type_options: list[dict[str, str]] = [
|
||||
{"label": "Public Law", "value": "pub"},
|
||||
{"label": "Private Law", "value": "priv"},
|
||||
]
|
||||
|
||||
law_type_docstring = """Law type filter.
|
||||
|
||||
Must be one of: pub, priv.
|
||||
|
||||
Public Laws
|
||||
-----------
|
||||
|
||||
A public law is a law that affects the general public or classes of citizens.
|
||||
It is identified by a number in the format "{congress}-{number}" (e.g., "119-44").
|
||||
|
||||
Private Laws
|
||||
------------
|
||||
|
||||
A private law is a law that affects specific individuals, organizations, or localities
|
||||
rather than the general public. Private laws are less common than public laws.
|
||||
|
||||
"""
|
||||
|
||||
AmendmentTypes: list = ["hamdt", "samdt", "suamdt"]
|
||||
|
||||
amendment_type_options: list[dict[str, str]] = [
|
||||
{"label": "House Amendment", "value": "hamdt"},
|
||||
{"label": "Senate Amendment", "value": "samdt"},
|
||||
{"label": "Senate Unamended", "value": "suamdt"},
|
||||
]
|
||||
|
||||
amendment_type_docstring = """Amendment type (e.g., "hamdt" for House Amendments).
|
||||
|
||||
Must be one of:
|
||||
|
||||
- hamdt: An amendment offered or adopted in the House of Representatives.
|
||||
House amendments are identified by "H.Amdt." followed by a number.
|
||||
- samdt: An amendment offered or adopted in the Senate.
|
||||
Senate amendments are identified by "S.Amdt." followed by a number.
|
||||
- suamdt: A Senate amendment that was submitted but not subsequently amended.
|
||||
|
||||
"""
|
||||
|
||||
ChamberTypes: list = ["house", "senate", "joint"]
|
||||
|
||||
chamber_options: list[dict[str, str]] = [
|
||||
{"label": "House", "value": "house"},
|
||||
{"label": "Senate", "value": "senate"},
|
||||
{"label": "Joint", "value": "joint"},
|
||||
]
|
||||
|
||||
doc_type_options: list[dict[str, str]] = [
|
||||
{"label": "All", "value": "all"},
|
||||
{"label": "Reports", "value": "report"},
|
||||
{"label": "Meetings & Hearings", "value": "meeting"},
|
||||
{"label": "Publications & Prints", "value": "publication"},
|
||||
{"label": "Legislation", "value": "legislation"},
|
||||
]
|
||||
|
||||
|
||||
COMMITTEES: dict[str, list[dict]] = {
|
||||
"senate": [
|
||||
{
|
||||
"label": "Senate Committee on Agriculture, Nutrition, and Forestry",
|
||||
"value": "ssaf00",
|
||||
},
|
||||
{"label": "Senate Committee on Appropriations", "value": "ssap00"},
|
||||
{"label": "Senate Committee on Armed Services", "value": "ssas00"},
|
||||
{
|
||||
"label": "Senate Committee on Banking, Housing, and Urban Affairs",
|
||||
"value": "ssbk00",
|
||||
},
|
||||
{
|
||||
"label": "Senate Committee on Commerce, Science, and Transportation",
|
||||
"value": "sscm00",
|
||||
},
|
||||
{
|
||||
"label": "Senate Committee on Energy and Natural Resources",
|
||||
"value": "sseg00",
|
||||
},
|
||||
{
|
||||
"label": "Senate Committee on Environment and Public Works",
|
||||
"value": "ssev00",
|
||||
},
|
||||
{"label": "Senate Committee on Finance", "value": "ssfi00"},
|
||||
{"label": "Senate Committee on Foreign Relations", "value": "ssfr00"},
|
||||
{
|
||||
"label": "Senate Committee on Health, Education, Labor, and Pensions",
|
||||
"value": "sshr00",
|
||||
},
|
||||
{
|
||||
"label": "Senate Committee on Homeland Security and Governmental Affairs",
|
||||
"value": "ssga00",
|
||||
},
|
||||
{"label": "Senate Committee on Indian Affairs", "value": "slia00"},
|
||||
{"label": "Senate Committee on Rules and Administration", "value": "ssra00"},
|
||||
{
|
||||
"label": "Senate Committee on Small Business and Entrepreneurship",
|
||||
"value": "sssb00",
|
||||
},
|
||||
{"label": "Senate Committee on Veterans' Affairs", "value": "ssva00"},
|
||||
{"label": "Senate Committee on the Budget", "value": "ssbu00"},
|
||||
{"label": "Senate Committee on the Judiciary", "value": "ssju00"},
|
||||
{"label": "Senate Select Committee on Ethics", "value": "slet00"},
|
||||
{"label": "Senate Select Committee on Intelligence", "value": "slin00"},
|
||||
{"label": "Senate Special Committee on Aging", "value": "spag00"},
|
||||
{
|
||||
"label": "United States Senate Caucus on International Narcotics Control",
|
||||
"value": "scnc00",
|
||||
},
|
||||
],
|
||||
"house": [
|
||||
{"label": "House Committee on Agriculture", "value": "hsag00"},
|
||||
{"label": "House Committee on Appropriations", "value": "hsap00"},
|
||||
{"label": "House Committee on Armed Services", "value": "hsas00"},
|
||||
{"label": "House Committee on Education and Workforce", "value": "hsed00"},
|
||||
{"label": "House Committee on Energy and Commerce", "value": "hsif00"},
|
||||
{"label": "House Committee on Ethics", "value": "hsso00"},
|
||||
{"label": "House Committee on Financial Services", "value": "hsba00"},
|
||||
{"label": "House Committee on Foreign Affairs", "value": "hsfa00"},
|
||||
{"label": "House Committee on Homeland Security", "value": "hshm00"},
|
||||
{"label": "House Committee on House Administration", "value": "hsha00"},
|
||||
{"label": "House Committee on Natural Resources", "value": "hsii00"},
|
||||
{
|
||||
"label": "House Committee on Oversight and Government Reform",
|
||||
"value": "hsgo00",
|
||||
},
|
||||
{"label": "House Committee on Rules", "value": "hsru00"},
|
||||
{
|
||||
"label": "House Committee on Science, Space, and Technology",
|
||||
"value": "hssy00",
|
||||
},
|
||||
{"label": "House Committee on Small Business", "value": "hssm00"},
|
||||
{
|
||||
"label": "House Committee on Transportation and Infrastructure",
|
||||
"value": "hspw00",
|
||||
},
|
||||
{"label": "House Committee on Veterans' Affairs", "value": "hsvr00"},
|
||||
{"label": "House Committee on Ways and Means", "value": "hswm00"},
|
||||
{"label": "House Committee on the Budget", "value": "hsbu00"},
|
||||
{"label": "House Committee on the Judiciary", "value": "hsju00"},
|
||||
{
|
||||
"label": "House Permanent Select Committee on Intelligence",
|
||||
"value": "hlig00",
|
||||
},
|
||||
],
|
||||
"joint": [
|
||||
{
|
||||
"label": "Commission on Security and Cooperation in Europe",
|
||||
"value": "jcse00",
|
||||
},
|
||||
{"label": "Joint Committee of Congress on the Library", "value": "jslc00"},
|
||||
{"label": "Joint Committee on Printing", "value": "jspr00"},
|
||||
{"label": "Joint Committee on Taxation", "value": "jstx00"},
|
||||
{"label": "Joint Economic Committee", "value": "jsec00"},
|
||||
],
|
||||
}
|
||||
|
||||
SUBCOMMITTEES: dict[str, list[dict]] = {
|
||||
"house/hsag00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Commodity Markets, Digital Assets, and Rural Development",
|
||||
"value": "hsag22",
|
||||
},
|
||||
{"label": "Conservation, Research, and Biotechnology", "value": "hsag14"},
|
||||
{"label": "Forestry and Horticulture", "value": "hsag15"},
|
||||
{
|
||||
"label": "General Farm Commodities, Risk Management, and Credit",
|
||||
"value": "hsag16",
|
||||
},
|
||||
{"label": "Livestock, Dairy, and Poultry", "value": "hsag29"},
|
||||
{"label": "Nutrition and Foreign Agriculture", "value": "hsag03"},
|
||||
],
|
||||
"house/hsap00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Agriculture, Rural Development, Food and Drug Administration, and Related Agencies",
|
||||
"value": "hsap01",
|
||||
},
|
||||
{
|
||||
"label": "Commerce, Justice, Science, and Related Agencies",
|
||||
"value": "hsap19",
|
||||
},
|
||||
{"label": "Defense", "value": "hsap02"},
|
||||
{
|
||||
"label": "Energy and Water Development and Related Agencies",
|
||||
"value": "hsap10",
|
||||
},
|
||||
{"label": "Financial Services and General Government", "value": "hsap23"},
|
||||
{"label": "Homeland Security", "value": "hsap15"},
|
||||
{"label": "Interior, Environment, and Related Agencies", "value": "hsap06"},
|
||||
{
|
||||
"label": "Labor, Health and Human Services, Education, and Related Agencies",
|
||||
"value": "hsap07",
|
||||
},
|
||||
{"label": "Legislative Branch", "value": "hsap24"},
|
||||
{
|
||||
"label": "Military Construction, Veterans Affairs, and Related Agencies",
|
||||
"value": "hsap18",
|
||||
},
|
||||
{
|
||||
"label": "National Security, Department of State, and Related Programs",
|
||||
"value": "hsap04",
|
||||
},
|
||||
{
|
||||
"label": "Transportation, Housing and Urban Development, and Related Agencies",
|
||||
"value": "hsap20",
|
||||
},
|
||||
],
|
||||
"house/hsas00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Cyber, Information Technologies, and Innovation", "value": "hsas35"},
|
||||
{"label": "Intelligence and Special Operations", "value": "hsas26"},
|
||||
{"label": "Military Personnel", "value": "hsas02"},
|
||||
{"label": "Readiness", "value": "hsas03"},
|
||||
{"label": "Seapower and Projection Forces", "value": "hsas28"},
|
||||
{"label": "Strategic Forces", "value": "hsas29"},
|
||||
{"label": "Tactical Air and Land Forces", "value": "hsas25"},
|
||||
],
|
||||
"house/hsba00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Capital Markets", "value": "hsba16"},
|
||||
{
|
||||
"label": "Digital Assets, Financial Technology, and Artificial Intelligence",
|
||||
"value": "hsba21",
|
||||
},
|
||||
{"label": "Financial Institutions", "value": "hsba20"},
|
||||
{"label": "Housing and Insurance", "value": "hsba04"},
|
||||
{
|
||||
"label": "National Security, Illicit Finance, and International Financial Institutions",
|
||||
"value": "hsba10",
|
||||
},
|
||||
{"label": "Oversight and Investigations", "value": "hsba09"},
|
||||
],
|
||||
"house/hsed00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Early Childhood, Elementary, and Secondary Education",
|
||||
"value": "hsed14",
|
||||
},
|
||||
{"label": "Health, Employment, Labor, and Pensions", "value": "hsed02"},
|
||||
{"label": "Higher Education and Workforce Development", "value": "hsed13"},
|
||||
{"label": "Workforce Protections", "value": "hsed10"},
|
||||
],
|
||||
"house/hsfa00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Africa", "value": "hsfa16"},
|
||||
{"label": "East Asia and Pacific", "value": "hsfa05"},
|
||||
{"label": "Europe", "value": "hsfa14"},
|
||||
{"label": "Middle East and North Africa", "value": "hsfa13"},
|
||||
{"label": "Oversight and Intelligence", "value": "hsfa17"},
|
||||
{"label": "South and Central Asia", "value": "hsfa19"},
|
||||
{"label": "Western Hemisphere", "value": "hsfa07"},
|
||||
],
|
||||
"house/hsgo00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Cybersecurity, Information Technology, and Government Innovation",
|
||||
"value": "hsgo12",
|
||||
},
|
||||
{"label": "Delivering on Government Efficiency", "value": "hsgo16"},
|
||||
{
|
||||
"label": "Economic Growth, Energy Policy, and Regulatory Affairs",
|
||||
"value": "hsgo05",
|
||||
},
|
||||
{"label": "Federal Law Enforcement", "value": "hsgo33"},
|
||||
{"label": "Government Operations", "value": "hsgo24"},
|
||||
{"label": "Health Care and Financial Services", "value": "hsgo27"},
|
||||
{"label": "Military and Foreign Affairs", "value": "hsgo06"},
|
||||
],
|
||||
"house/hsha00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Elections", "value": "hsha08"},
|
||||
{"label": "Modernization and Innovation", "value": "hsha27"},
|
||||
],
|
||||
"house/hshm00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Border Security and Enforcement", "value": "hshm11"},
|
||||
{"label": "Counterterrorism and Intelligence", "value": "hshm05"},
|
||||
{"label": "Cybersecurity and Infrastructure Protection", "value": "hshm08"},
|
||||
{"label": "Emergency Management and Technology", "value": "hshm12"},
|
||||
{"label": "Oversight, Investigations, and Accountability", "value": "hshm09"},
|
||||
{"label": "Transportation and Maritime Security", "value": "hshm07"},
|
||||
],
|
||||
"house/hsif00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Commerce, Manufacturing, and Trade", "value": "hsif17"},
|
||||
{"label": "Communications and Technology", "value": "hsif16"},
|
||||
{"label": "Energy", "value": "hsif03"},
|
||||
{"label": "Environment", "value": "hsif18"},
|
||||
{"label": "Health", "value": "hsif14"},
|
||||
{"label": "Oversight and Investigations", "value": "hsif02"},
|
||||
],
|
||||
"house/hsii00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Energy and Mineral Resources", "value": "hsii06"},
|
||||
{"label": "Federal Lands", "value": "hsii10"},
|
||||
{"label": "Indian and Insular Affairs", "value": "hsii24"},
|
||||
{"label": "Oversight and Investigations", "value": "hsii15"},
|
||||
{"label": "Water, Wildlife and Fisheries", "value": "hsii13"},
|
||||
],
|
||||
"house/hlig00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Central Intelligence Agency", "value": "hlig01"},
|
||||
{"label": "Defense Intelligence and Overhead Architecture", "value": "hlig04"},
|
||||
{"label": "National Intelligence Enterprise", "value": "hlig06"},
|
||||
{"label": "National Security Agency and Cyber", "value": "hlig02"},
|
||||
{"label": "Open Source Intelligence", "value": "hlig11"},
|
||||
{"label": "Oversight and Investigations", "value": "hlig09"},
|
||||
],
|
||||
"house/hsju00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Courts, Intellectual Property, Artificial Intelligence, and the Internet",
|
||||
"value": "hsju03",
|
||||
},
|
||||
{"label": "Crime and Federal Government Surveillance", "value": "hsju08"},
|
||||
{
|
||||
"label": "Immigration Integrity, Security, and Enforcement",
|
||||
"value": "hsju01",
|
||||
},
|
||||
{"label": "Oversight", "value": "hsju13"},
|
||||
{
|
||||
"label": "The Administrative State, Regulatory Reform, and Antitrust",
|
||||
"value": "hsju05",
|
||||
},
|
||||
{"label": "The Constitution and Limited Government", "value": "hsju10"},
|
||||
],
|
||||
"house/hspw00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Aviation", "value": "hspw05"},
|
||||
{"label": "Coast Guard and Maritime Transportation", "value": "hspw07"},
|
||||
{
|
||||
"label": "Economic Development, Public Buildings, and Emergency Management",
|
||||
"value": "hspw13",
|
||||
},
|
||||
{"label": "Highways and Transit", "value": "hspw12"},
|
||||
{"label": "Railroads, Pipelines, and Hazardous Materials", "value": "hspw14"},
|
||||
{"label": "Water Resources and Environment", "value": "hspw02"},
|
||||
],
|
||||
"house/hsru00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Legislative and Budget Process", "value": "hsru02"},
|
||||
{"label": "Rules and Organization of the House", "value": "hsru04"},
|
||||
],
|
||||
"house/hssm00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Contracting and Infrastructure", "value": "hssm23"},
|
||||
{"label": "Economic Growth, Tax, and Capital Access", "value": "hssm27"},
|
||||
{
|
||||
"label": "Innovation, Entrepreneurship, and Workforce Development",
|
||||
"value": "hssm22",
|
||||
},
|
||||
{"label": "Oversight, Investigations, and Regulations", "value": "hssm24"},
|
||||
{"label": "Rural Development, Energy, and Supply Chains", "value": "hssm21"},
|
||||
],
|
||||
"house/hssy00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Energy", "value": "hssy20"},
|
||||
{"label": "Environment", "value": "hssy18"},
|
||||
{"label": "Investigations and Oversight", "value": "hssy21"},
|
||||
{"label": "Research and Technology", "value": "hssy15"},
|
||||
{"label": "Space and Aeronautics", "value": "hssy16"},
|
||||
],
|
||||
"house/hsvr00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Disability Assistance and Memorial Affairs", "value": "hsvr09"},
|
||||
{"label": "Economic Opportunity", "value": "hsvr10"},
|
||||
{"label": "Health", "value": "hsvr03"},
|
||||
{"label": "Oversight and Investigations", "value": "hsvr08"},
|
||||
{"label": "Technology Modernization", "value": "hsvr11"},
|
||||
],
|
||||
"house/hswm00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Health", "value": "hswm02"},
|
||||
{"label": "Oversight", "value": "hswm06"},
|
||||
{"label": "Social Security", "value": "hswm01"},
|
||||
{"label": "Tax", "value": "hswm05"},
|
||||
{"label": "Trade", "value": "hswm04"},
|
||||
{"label": "Work and Welfare", "value": "hswm03"},
|
||||
],
|
||||
"senate/ssaf00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Commodities, Derivatives, Risk Management, and Trade",
|
||||
"value": "ssaf13",
|
||||
},
|
||||
{
|
||||
"label": "Conservation, Forestry, Natural Resources, and Biotechnology",
|
||||
"value": "ssaf14",
|
||||
},
|
||||
{
|
||||
"label": "Food and Nutrition, Specialty Crops, Organics, and Research",
|
||||
"value": "ssaf16",
|
||||
},
|
||||
{"label": "Livestock, Dairy, Poultry, and Food Safety", "value": "ssaf17"},
|
||||
{"label": "Rural Development, Energy, and Credit", "value": "ssaf15"},
|
||||
],
|
||||
"senate/ssap00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Agriculture, Rural Development, Food and Drug Administration, and Related Agencies",
|
||||
"value": "ssap01",
|
||||
},
|
||||
{
|
||||
"label": "Commerce, Justice, Science, and Related Agencies",
|
||||
"value": "ssap16",
|
||||
},
|
||||
{"label": "Department of Defense", "value": "ssap02"},
|
||||
{"label": "Department of Homeland Security", "value": "ssap14"},
|
||||
{
|
||||
"label": "Department of Interior, Environment, and Related Agencies",
|
||||
"value": "ssap17",
|
||||
},
|
||||
{
|
||||
"label": "Departments of Labor, Health and Human Services, and Education, and Related Agencies",
|
||||
"value": "ssap18",
|
||||
},
|
||||
{"label": "Energy and Water Development", "value": "ssap22"},
|
||||
{"label": "Financial Services and General Government", "value": "ssap23"},
|
||||
{"label": "Legislative Branch", "value": "ssap08"},
|
||||
{
|
||||
"label": "Military Construction, Veterans Affairs, and Related Agencies",
|
||||
"value": "ssap19",
|
||||
},
|
||||
{"label": "State, Foreign Operations, and Related Programs", "value": "ssap20"},
|
||||
{
|
||||
"label": "Transportation, Housing and Urban Development, and Related Agencies",
|
||||
"value": "ssap24",
|
||||
},
|
||||
],
|
||||
"senate/ssas00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Airland", "value": "ssas14"},
|
||||
{"label": "Cybersecurity", "value": "ssas21"},
|
||||
{"label": "Emerging Threats and Capabilities", "value": "ssas20"},
|
||||
{"label": "Personnel", "value": "ssas17"},
|
||||
{"label": "Readiness and Management Support", "value": "ssas15"},
|
||||
{"label": "Seapower", "value": "ssas13"},
|
||||
{"label": "Strategic Forces", "value": "ssas16"},
|
||||
],
|
||||
"senate/ssbk00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Digital Assets", "value": "ssbk13"},
|
||||
{"label": "Economic Policy", "value": "ssbk12"},
|
||||
{"label": "Financial Institutions and Consumer Protection", "value": "ssbk08"},
|
||||
{
|
||||
"label": "Housing, Transportation, and Community Development",
|
||||
"value": "ssbk09",
|
||||
},
|
||||
{
|
||||
"label": "National Security and International Trade and Finance",
|
||||
"value": "ssbk05",
|
||||
},
|
||||
{"label": "Securities, Insurance, and Investment", "value": "ssbk04"},
|
||||
],
|
||||
"senate/sscm00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Aviation, Space, and Innovation", "value": "sscm33"},
|
||||
{"label": "Coast Guard, Maritime, and Fisheries", "value": "sscm36"},
|
||||
{
|
||||
"label": "Consumer Protection, Technology, and Data Privacy",
|
||||
"value": "sscm35",
|
||||
},
|
||||
{"label": "Science, Manufacturing, and Competitiveness", "value": "sscm37"},
|
||||
{
|
||||
"label": "Surface Transportation, Freight, Pipelines, and Safety",
|
||||
"value": "sscm38",
|
||||
},
|
||||
{"label": "Telecommunications and Media", "value": "sscm34"},
|
||||
{"label": "Tourism, Trade, and Export Promotion", "value": "sscm39"},
|
||||
],
|
||||
"senate/sseg00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Energy", "value": "sseg01"},
|
||||
{"label": "National Parks", "value": "sseg04"},
|
||||
{"label": "Public Lands, Forests, and Mining", "value": "sseg03"},
|
||||
{"label": "Water and Power", "value": "sseg07"},
|
||||
],
|
||||
"senate/ssev00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Chemical Safety, Waste Management, Environmental Justice, and Regulatory Oversight",
|
||||
"value": "ssev09",
|
||||
},
|
||||
{
|
||||
"label": "Clean Air, Climate, and Nuclear Innovation and Safety",
|
||||
"value": "ssev10",
|
||||
},
|
||||
{"label": "Fisheries, Wildlife, and Water", "value": "ssev15"},
|
||||
{"label": "Transportation and Infrastructure", "value": "ssev08"},
|
||||
],
|
||||
"senate/ssfi00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Energy, Natural Resources, and Infrastructure", "value": "ssfi12"},
|
||||
{"label": "Fiscal Responsibility and Economic Growth", "value": "ssfi14"},
|
||||
{"label": "Health Care", "value": "ssfi10"},
|
||||
{
|
||||
"label": "International Trade, Customs, and Global Competitiveness",
|
||||
"value": "ssfi13",
|
||||
},
|
||||
{"label": "Social Security, Pensions, and Family Policy", "value": "ssfi02"},
|
||||
{"label": "Taxation and IRS Oversight", "value": "ssfi11"},
|
||||
],
|
||||
"senate/ssfr00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Africa and Global Health Policy", "value": "ssfr09"},
|
||||
{
|
||||
"label": "East Asia, the Pacific, and International Cybersecurity Policy",
|
||||
"value": "ssfr02",
|
||||
},
|
||||
{"label": "Europe and Regional Security Cooperation", "value": "ssfr01"},
|
||||
{
|
||||
"label": (
|
||||
"Multilateral International Development, Multilateral Institutions,"
|
||||
" and International Economic, Energy, and Environmental Policy"
|
||||
),
|
||||
"value": "ssfr15",
|
||||
},
|
||||
{
|
||||
"label": "Near East, South Asia, Central Asia, and Counterterrorism",
|
||||
"value": "ssfr07",
|
||||
},
|
||||
{
|
||||
"label": (
|
||||
"State Department and USAID Management, International Operations,"
|
||||
" and Bilateral International Development"
|
||||
),
|
||||
"value": "ssfr14",
|
||||
},
|
||||
{
|
||||
"label": (
|
||||
"Western Hemisphere, Transnational Crime, Civilian Security,"
|
||||
" Democracy, Human Rights, and Global Women's Issues"
|
||||
),
|
||||
"value": "ssfr06",
|
||||
},
|
||||
],
|
||||
"senate/ssga00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Border Management, Federal Workforce, and Regulatory Affairs",
|
||||
"value": "ssga22",
|
||||
},
|
||||
{
|
||||
"label": "Disaster Management, District of Columbia, and Census",
|
||||
"value": "ssga20",
|
||||
},
|
||||
{"label": "Permanent Subcommittee on Investigations", "value": "ssga01"},
|
||||
],
|
||||
"senate/sshr00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{"label": "Education and the American Family", "value": "sshr09"},
|
||||
{"label": "Employment and Workplace Safety", "value": "sshr11"},
|
||||
{"label": "Primary Health and Retirement Security", "value": "sshr12"},
|
||||
],
|
||||
"senate/ssju00": [
|
||||
{"label": "None (Parent Committee)", "value": ""},
|
||||
{
|
||||
"label": "Antitrust, Competition Policy, and Consumer Rights",
|
||||
"value": "ssju01",
|
||||
},
|
||||
{"label": "Border Security and Immigration", "value": "ssju04"},
|
||||
{"label": "Crime and Counterterrorism", "value": "ssju22"},
|
||||
{
|
||||
"label": "Federal Courts, Oversight, Agency Action, and Federal Rights",
|
||||
"value": "ssju25",
|
||||
},
|
||||
{"label": "Human Rights and the Law", "value": "ssju27"},
|
||||
{"label": "Intellectual Property", "value": "ssju26"},
|
||||
{"label": "Privacy, Technology, and the Law", "value": "ssju28"},
|
||||
{"label": "the Constitution", "value": "ssju21"},
|
||||
],
|
||||
}
|
||||
|
||||
@@ -3,7 +3,13 @@
|
||||
from typing import Literal
|
||||
|
||||
from fastapi.exceptions import HTTPException
|
||||
from openbb_congress_gov.utils.constants import BillTypes, base_url, bill_type_options
|
||||
from openbb_congress_gov.utils.constants import (
|
||||
AmendmentTypes,
|
||||
BillTypes,
|
||||
LawTypes,
|
||||
base_url,
|
||||
bill_type_options,
|
||||
)
|
||||
from openbb_core.app.model.abstract.singleton import SingletonMeta
|
||||
from openbb_core.provider.utils.errors import UnauthorizedError
|
||||
|
||||
@@ -98,11 +104,11 @@ def download_bills(urls: list[str]) -> list:
|
||||
results: list = []
|
||||
|
||||
for url in urls:
|
||||
if "congress.gov" not in url:
|
||||
if "congress.gov" not in url and "govinfo.gov" not in url:
|
||||
results.append(
|
||||
{
|
||||
"error_type": "invalid_url",
|
||||
"content": f"Invalid URL: {url}. Must be a valid Congress.gov API URL.",
|
||||
"content": f"Invalid URL: {url}. Must be a valid Congress.gov or GovInfo.gov URL.",
|
||||
"filename": url.split("/")[-1],
|
||||
}
|
||||
)
|
||||
@@ -435,16 +441,30 @@ async def get_bill_text_choices(bill_url: str, is_workspace: bool = False) -> li
|
||||
)
|
||||
|
||||
text_output: list = []
|
||||
seen_urls: set = set()
|
||||
|
||||
for version in bill_text:
|
||||
bill_version: dict = {}
|
||||
formats = version.get("formats", [])
|
||||
bill_type = version.get("type", "")
|
||||
version_date = version.get("date", "")
|
||||
|
||||
if not formats or not version_date:
|
||||
continue
|
||||
|
||||
pdf_url = next(
|
||||
(f.get("url") for f in formats if f.get("type") == "PDF"), None
|
||||
)
|
||||
|
||||
if pdf_url and pdf_url in seen_urls:
|
||||
continue
|
||||
|
||||
if pdf_url:
|
||||
seen_urls.add(pdf_url)
|
||||
|
||||
bill_version["version_type"] = bill_type
|
||||
bill_version["version_date"] = version_date
|
||||
|
||||
for fmt in formats:
|
||||
doc_url = fmt.get("url")
|
||||
doc_type = fmt.get("type", "").replace("Formatted ", "").lower()
|
||||
@@ -463,13 +483,21 @@ async def get_bill_text_choices(bill_url: str, is_workspace: bool = False) -> li
|
||||
}
|
||||
]
|
||||
|
||||
seen_urls = set()
|
||||
|
||||
for version in bill_text:
|
||||
version_date = version.get("date")
|
||||
formats = version.get("formats", [])
|
||||
version_type = version.get("type", "")
|
||||
|
||||
for fmt in formats:
|
||||
if (doc_type := fmt.get("type")) and doc_type == "PDF":
|
||||
doc_url = fmt.get("url")
|
||||
|
||||
if doc_url in seen_urls:
|
||||
break
|
||||
|
||||
seen_urls.add(doc_url)
|
||||
doc_name = doc_url.split("/")[-1]
|
||||
filename = (
|
||||
f"{version_type} - {version_date} - {doc_name}"
|
||||
@@ -485,3 +513,469 @@ async def get_bill_text_choices(bill_url: str, is_workspace: bool = False) -> li
|
||||
break
|
||||
|
||||
return results
|
||||
|
||||
|
||||
async def get_laws(
|
||||
congress: int,
|
||||
law_type: str | None = None,
|
||||
limit: int | None = None,
|
||||
offset: int | None = None,
|
||||
sort_by: Literal["asc", "desc"] = "desc",
|
||||
) -> dict:
|
||||
"""Fetch laws for a given Congress number.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
congress : int
|
||||
The Congress number (e.g., 119 for the 119th Congress).
|
||||
law_type : Optional[str]
|
||||
The type of law to fetch. Must be one of: "pub", "priv".
|
||||
If None, returns all laws for the congress.
|
||||
limit : Optional[int]
|
||||
The maximum number of laws to return. Defaults to 100 if None.
|
||||
offset : Optional[int]
|
||||
The number of results to skip before starting to collect the result set.
|
||||
sort_by : Literal["asc", "desc"]
|
||||
The sort order for the results. Defaults to "desc".
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dictionary of the raw JSON response from the API.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
|
||||
if law_type is not None and law_type not in LawTypes:
|
||||
raise ValueError(
|
||||
f"Invalid law type: {law_type}. Must be one of {', '.join(LawTypes)}."
|
||||
)
|
||||
|
||||
api_key = check_api_key()
|
||||
|
||||
url = (
|
||||
f"{base_url}law/{congress}"
|
||||
+ (f"/{law_type}" if law_type else "")
|
||||
+ f"?limit={limit if limit is not None else 100}"
|
||||
+ (f"&offset={offset}" if offset else "")
|
||||
+ f"&sort=updateDate+{sort_by}"
|
||||
+ f"&format=json&api_key={api_key}"
|
||||
)
|
||||
|
||||
return await amake_request(url) # type: ignore
|
||||
|
||||
|
||||
async def get_all_laws_by_type(congress: int, law_type: str = "pub") -> list:
|
||||
"""Fetch all laws of a specific type for a given Congress number.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
congress : int
|
||||
The Congress number (e.g., 119 for the 119th Congress).
|
||||
law_type : str
|
||||
The type of law to fetch. Must be one of: "pub", "priv".
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
A list of bill dictionaries for all laws of the specified type.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import math # noqa
|
||||
from openbb_core.provider.utils.helpers import amake_requests
|
||||
|
||||
if law_type not in LawTypes:
|
||||
raise ValueError(
|
||||
f"Invalid law type: {law_type}. Must be one of {', '.join(LawTypes)}."
|
||||
)
|
||||
|
||||
api_key = check_api_key()
|
||||
results: list = []
|
||||
limit = 250
|
||||
res = await get_laws(congress=congress, law_type=law_type, limit=limit, offset=0)
|
||||
results.extend(res.get("bills", [])) # type: ignore
|
||||
total = res.get("pagination", {}).get("count", 0) # type: ignore
|
||||
next_url = res.get("pagination", {}).get("next", None) # type: ignore
|
||||
urls: list = []
|
||||
|
||||
for i in range(1, math.ceil(total / limit)):
|
||||
offset = i * limit
|
||||
url = (
|
||||
next_url.replace(f"offset={limit}", f"offset={offset}").replace(
|
||||
"updateDate ", "updateDate+"
|
||||
)
|
||||
+ f"&api_key={api_key}"
|
||||
)
|
||||
urls.append(url)
|
||||
|
||||
async def response_callback(response, _):
|
||||
result = await response.json()
|
||||
if result and "bills" in result and (bills := result.get("bills", [])):
|
||||
results.extend(bills)
|
||||
|
||||
_ = await amake_requests(urls, response_callback=response_callback) # type: ignore
|
||||
|
||||
return sorted(results, key=lambda x: x.get("updateDate", ""), reverse=True)
|
||||
|
||||
|
||||
async def get_amendments(
|
||||
congress: int | None = None,
|
||||
amendment_type: str | None = None,
|
||||
start_date: str | None = None,
|
||||
end_date: str | None = None,
|
||||
limit: int | None = None,
|
||||
offset: int | None = None,
|
||||
sort_by: Literal["asc", "desc"] = "desc",
|
||||
) -> dict:
|
||||
"""Fetch amendments with optional filters.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
congress : Optional[int]
|
||||
The Congress number. If None, returns amendments across congresses.
|
||||
amendment_type : Optional[str]
|
||||
The type of amendment. Must be one of: "hamdt", "samdt", "suamdt".
|
||||
start_date : Optional[str]
|
||||
The start date in ISO format (YYYY-MM-DD) for filtering by updateDate.
|
||||
end_date : Optional[str]
|
||||
The end date in ISO format (YYYY-MM-DD) for filtering by updateDate.
|
||||
limit : Optional[int]
|
||||
The maximum number of amendments to return. Defaults to 100 if None.
|
||||
offset : Optional[int]
|
||||
The number of results to skip before starting to collect the result set.
|
||||
sort_by : Literal["asc", "desc"]
|
||||
The sort order for the results. Defaults to "desc".
|
||||
|
||||
Returns
|
||||
-------
|
||||
dict
|
||||
A dictionary of the raw JSON response from the API.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
|
||||
if amendment_type is not None and amendment_type not in AmendmentTypes:
|
||||
raise ValueError(
|
||||
f"Invalid amendment type: {amendment_type}. Must be one of {', '.join(AmendmentTypes)}."
|
||||
)
|
||||
|
||||
api_key = check_api_key()
|
||||
url = f"{base_url}amendment"
|
||||
|
||||
if congress is not None:
|
||||
url += f"/{congress}"
|
||||
|
||||
if amendment_type is not None:
|
||||
url += f"/{amendment_type}"
|
||||
|
||||
url += (f"?fromDateTime={start_date + 'T00:00:00Z'}" if start_date else "") + (
|
||||
f"&toDateTime={end_date + 'T23:59:59Z'}" if end_date else ""
|
||||
)
|
||||
url += (
|
||||
f"{'?' if '?' not in url else '&'}"
|
||||
+ f"limit={limit if limit is not None else 100}"
|
||||
+ (f"&offset={offset}" if offset else "")
|
||||
+ f"&sort=updateDate+{sort_by}"
|
||||
+ f"&format=json&api_key={api_key}"
|
||||
)
|
||||
|
||||
return await amake_request(url) # type: ignore
|
||||
|
||||
|
||||
async def get_all_amendments_by_type(congress: int, amendment_type: str) -> list:
|
||||
"""Fetch all amendments of a specific type for a given Congress number.
|
||||
|
||||
Parameters
|
||||
----------
|
||||
congress : int
|
||||
The Congress number (e.g., 119 for the 119th Congress).
|
||||
amendment_type : str
|
||||
The type of amendment. Must be one of: "hamdt", "samdt", "suamdt".
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
A list of all amendment dictionaries for the specified type and congress.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import math # noqa
|
||||
from openbb_core.provider.utils.helpers import amake_requests
|
||||
|
||||
if amendment_type not in AmendmentTypes:
|
||||
raise ValueError(
|
||||
f"Invalid amendment type: {amendment_type}. Must be one of {', '.join(AmendmentTypes)}."
|
||||
)
|
||||
|
||||
api_key = check_api_key()
|
||||
results: list = []
|
||||
limit = 250
|
||||
res = await get_amendments(
|
||||
congress=congress, amendment_type=amendment_type, limit=limit, offset=0
|
||||
)
|
||||
results.extend(res.get("amendments", [])) # type: ignore
|
||||
total = res.get("pagination", {}).get("count", 0) # type: ignore
|
||||
next_url = res.get("pagination", {}).get("next", None) # type: ignore
|
||||
urls: list = []
|
||||
|
||||
for i in range(1, math.ceil(total / limit)):
|
||||
offset = i * limit
|
||||
url = (
|
||||
next_url.replace(f"offset={limit}", f"offset={offset}").replace(
|
||||
"updateDate ", "updateDate+"
|
||||
)
|
||||
+ f"&api_key={api_key}"
|
||||
)
|
||||
urls.append(url)
|
||||
|
||||
async def response_callback(response, _):
|
||||
result = await response.json()
|
||||
if (
|
||||
result
|
||||
and "amendments" in result
|
||||
and (amendments := result.get("amendments", []))
|
||||
):
|
||||
results.extend(amendments)
|
||||
|
||||
_ = await amake_requests(urls, response_callback=response_callback) # type: ignore
|
||||
|
||||
return sorted(results, key=lambda x: x.get("updateDate", ""), reverse=True)
|
||||
|
||||
|
||||
# pylint: disable=R0912,R0914
|
||||
async def get_amendment_text_choices( # noqa: PLR0912
|
||||
amendment_url: str, is_workspace: bool = False
|
||||
) -> list:
|
||||
"""Fetch the direct download links for the available text versions of the specified amendment.
|
||||
|
||||
Makes multiple API calls:
|
||||
1. GET the amendment base detail to retrieve the official textVersions URL and description.
|
||||
2. GET the textVersions sub-resource via the URL returned in the detail response.
|
||||
3. If the description references a committee report (e.g., "House Report 119-1"),
|
||||
GET that report's text — these documents contain the clean printed amendment text
|
||||
and are returned first (higher priority than Congressional Record references).
|
||||
|
||||
Parameters
|
||||
----------
|
||||
amendment_url : str
|
||||
The base URL of the amendment
|
||||
(e.g., "https://api.congress.gov/v3/amendment/119/hamdt/2?format=json")
|
||||
or a shorthand like "119/hamdt/2".
|
||||
is_workspace : bool
|
||||
When True, returns {label, value} dicts suitable for workspace dropdowns.
|
||||
|
||||
Returns
|
||||
-------
|
||||
list
|
||||
List of dictionaries with available text version formats.
|
||||
"""
|
||||
# pylint: disable=import-outside-toplevel
|
||||
import re
|
||||
|
||||
from openbb_core.provider.utils.helpers import amake_request
|
||||
|
||||
api_key = check_api_key()
|
||||
|
||||
if amendment_url[0].isnumeric() or (
|
||||
amendment_url[0] == "/" and amendment_url[1].isnumeric()
|
||||
):
|
||||
path = amendment_url[1:] if amendment_url[0] == "/" else amendment_url
|
||||
amendment_url = f"https://api.congress.gov/v3/amendment/{path}?format=json"
|
||||
|
||||
# Step 1: Amendment base detail for description (committee report check) and text URL
|
||||
detail_response: dict = await amake_request(amendment_url + f"&api_key={api_key}") # type: ignore
|
||||
amendment_detail = detail_response.get("amendment", {})
|
||||
|
||||
# Step 2: Fetch the /text sub-resource.
|
||||
tv_info = amendment_detail.get("textVersions", {})
|
||||
|
||||
if isinstance(tv_info, dict) and tv_info.get("url"):
|
||||
tv_url = tv_info["url"] + f"&api_key={api_key}"
|
||||
else:
|
||||
# Construct the /text URL directly as a fallback
|
||||
tv_url = amendment_url.replace("?", "/text?") + f"&api_key={api_key}"
|
||||
|
||||
tv_response: dict = await amake_request(tv_url) # type: ignore
|
||||
text_versions: list = tv_response.get("textVersions", [])
|
||||
# Step 3: Check if the amendment was printed in a committee report and fetch that text
|
||||
committee_report_text: list = []
|
||||
description = (
|
||||
amendment_detail.get("description") or amendment_detail.get("purpose") or ""
|
||||
)
|
||||
report_match = re.search(
|
||||
r"\b(House|Senate)\s+Report\s+(\d+)-(\d+)", description, re.IGNORECASE
|
||||
)
|
||||
|
||||
if report_match:
|
||||
report_congress = report_match.group(2)
|
||||
report_number = report_match.group(3)
|
||||
report_type = "hrpt" if report_match.group(1).lower() == "house" else "srpt"
|
||||
report_text_url = (
|
||||
f"https://api.congress.gov/v3/committeeReport/{report_congress}"
|
||||
f"/{report_type}/{report_number}/text?format=json&api_key={api_key}"
|
||||
)
|
||||
try:
|
||||
report_response: dict = await amake_request(report_text_url) # type: ignore
|
||||
if isinstance(report_response, dict) and "text" in report_response:
|
||||
committee_report_text = report_response.get("text", [])
|
||||
except Exception: # pylint: disable=broad-except # noqa: S110
|
||||
pass
|
||||
|
||||
# Step 4: If no text versions found, fall back to the amended bill's text versions.
|
||||
bill_text_versions: list = []
|
||||
|
||||
if not text_versions and not committee_report_text:
|
||||
amended_bill = amendment_detail.get("amendedBill", {})
|
||||
bill_url = amended_bill.get("url", "") if amended_bill else ""
|
||||
|
||||
if bill_url:
|
||||
bill_text_url = bill_url.replace("?", "/text?") + f"&api_key={api_key}"
|
||||
|
||||
try:
|
||||
bill_tv_response: dict = await amake_request(bill_text_url) # type: ignore
|
||||
bill_text_versions = bill_tv_response.get("textVersions", [])
|
||||
except Exception: # pylint: disable=broad-except # noqa: S110
|
||||
pass
|
||||
|
||||
if is_workspace is False:
|
||||
if not text_versions and not committee_report_text and not bill_text_versions:
|
||||
raise HTTPException(
|
||||
status_code=404,
|
||||
detail="No text available for this amendment currently.",
|
||||
)
|
||||
|
||||
text_output: list = []
|
||||
seen_pdf_urls: set = set()
|
||||
|
||||
def _deduped_entry(entry: dict, formats: list) -> dict | None:
|
||||
pdf_url = next(
|
||||
(f.get("url") for f in formats if f.get("type") == "PDF"), None
|
||||
)
|
||||
|
||||
if pdf_url and pdf_url in seen_pdf_urls:
|
||||
return None
|
||||
|
||||
if pdf_url:
|
||||
seen_pdf_urls.add(pdf_url)
|
||||
|
||||
for fmt in formats:
|
||||
doc_url = fmt.get("url")
|
||||
doc_type = fmt.get("type", "").replace("Formatted ", "").lower()
|
||||
entry[doc_type] = doc_url
|
||||
|
||||
return entry
|
||||
|
||||
for version in committee_report_text:
|
||||
formats = version.get("formats", [])
|
||||
entry: dict = {
|
||||
"version_type": "Committee Report",
|
||||
"version_date": version.get("date", ""),
|
||||
}
|
||||
result = _deduped_entry(entry, formats)
|
||||
|
||||
if result:
|
||||
text_output.append(result)
|
||||
|
||||
for version in text_versions:
|
||||
formats = version.get("formats", [])
|
||||
version_type = version.get("type", "")
|
||||
version_date = version.get("date", "")
|
||||
|
||||
if not formats or not version_date:
|
||||
continue
|
||||
|
||||
entry = {"version_type": version_type, "version_date": version_date}
|
||||
result = _deduped_entry(entry, formats)
|
||||
|
||||
if result:
|
||||
text_output.append(result)
|
||||
|
||||
for version in bill_text_versions:
|
||||
formats = version.get("formats", [])
|
||||
version_type = version.get("type", "")
|
||||
version_date = version.get("date", "")
|
||||
|
||||
if not formats or not version_date:
|
||||
continue
|
||||
|
||||
entry = {
|
||||
"version_type": f"Bill Text - {version_type}",
|
||||
"version_date": version_date,
|
||||
}
|
||||
result = _deduped_entry(entry, formats)
|
||||
|
||||
if result:
|
||||
text_output.append(result)
|
||||
|
||||
return text_output
|
||||
|
||||
if not text_versions and not committee_report_text and not bill_text_versions:
|
||||
return [
|
||||
{"label": "No text available for this amendment currently.", "value": ""}
|
||||
]
|
||||
|
||||
results: list = []
|
||||
|
||||
# Committee report documents first — these are the printed amendment text
|
||||
for version in committee_report_text:
|
||||
version_date = version.get("date", "")
|
||||
for fmt in version.get("formats", []):
|
||||
if fmt.get("type") == "PDF":
|
||||
doc_url = fmt.get("url", "")
|
||||
doc_name = doc_url.split("/")[-1]
|
||||
label = (
|
||||
f"Committee Report - {version_date} - {doc_name}"
|
||||
if version_date
|
||||
else doc_name
|
||||
)
|
||||
results.append({"label": label, "value": doc_url})
|
||||
break
|
||||
|
||||
seen_urls_ws: set = set()
|
||||
|
||||
# Congressional Record / other text versions
|
||||
for version in text_versions:
|
||||
version_date = version.get("date")
|
||||
formats = version.get("formats", [])
|
||||
version_type = version.get("type", "")
|
||||
|
||||
for fmt in formats:
|
||||
if (doc_type := fmt.get("type")) and doc_type == "PDF":
|
||||
doc_url = fmt.get("url", "")
|
||||
|
||||
if doc_url in seen_urls_ws:
|
||||
break
|
||||
|
||||
seen_urls_ws.add(doc_url)
|
||||
doc_name = doc_url.split("/")[-1]
|
||||
filename = (
|
||||
f"{version_type} - {version_date} - {doc_name}"
|
||||
if version_date
|
||||
else doc_name
|
||||
)
|
||||
results.append({"label": filename, "value": doc_url})
|
||||
break
|
||||
|
||||
# Amended bill text fallback (for ANS amendments that adopt the printed bill)
|
||||
for version in bill_text_versions:
|
||||
version_date = version.get("date")
|
||||
formats = version.get("formats", [])
|
||||
version_type = version.get("type", "")
|
||||
|
||||
for fmt in formats:
|
||||
if (doc_type := fmt.get("type")) and doc_type == "PDF":
|
||||
doc_url = fmt.get("url", "")
|
||||
|
||||
if doc_url in seen_urls_ws:
|
||||
break
|
||||
|
||||
seen_urls_ws.add(doc_url)
|
||||
doc_name = doc_url.split("/")[-1]
|
||||
filename = (
|
||||
f"Bill Text ({version_type}) - {version_date} - {doc_name}"
|
||||
if version_date
|
||||
else doc_name
|
||||
)
|
||||
results.append({"label": filename, "value": doc_url})
|
||||
break
|
||||
|
||||
return results
|
||||
|
||||
@@ -0,0 +1,243 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/amendment/119/hamdt/2?api_key=MOCK_API_KEY&format=json
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA6xVUU/bMBB+51ec8rRJtLHbACLSNGUgNB4GVVftAcSD61xbs8TO7EtFh/jvk5PQ
|
||||
piHAJu0xvu8+333f+fJ4AAAQiBx1mqOmIIbH6qg+lqSMdnuHVUCassJGh/vnpc2CGIIVUeHiMBSF
|
||||
GkqjlxadGy7NOlyPw+1VIeen4UrkKYWjsLnp88LYXNCne2d0sKV+OmyV5NMx/aKyrK+s+q4gBs5P
|
||||
O7XpMp+j9eVFJzzoBI1VS6XPVuIZ89WUDt9EnZkUK2QXRYqyKnKhHuC6tHBhLDpykEh6gd0UNcm0
|
||||
GymLVBCeC8JLLbMyVXo5wwcvejBio+MBGw1YFPy7/nOVZbX0NoxO+PuKy44oYBYwxcKiQ02C1Bpd
|
||||
0Ia/4kGQopNWFd5nz5Vo2I4C1N5gChwKqzRhCkpDfd0UC2PJkw04kAFHVv1EkMLOjQaHv0p0ZIXn
|
||||
BaFTQGncxhHm4NCulUTnOY1VpH7XqIU1PliNHIwZh7kyciUspJgbvSUrrLlHSW7Ybi8ThI4S2bTR
|
||||
GcB6jL1pjU9HA8YHo3HXpxo3U3mF4+M4GsXRCzep8ftag1haRKWXXgBaIUzQ2k1LwA8JY/wjJB6W
|
||||
etB8A2ujJMLaEA77nd29iFG7RVcY7Yz1Dt7uFbTfbIWdK7MsVYqXqaeZMMaO2VGnj9p95X2Tvh/O
|
||||
euILZR1diVqQ79IQ9bEsyix7Bk2xGNY6HEKVALfTwSQZcHbXl5qJHX+V1QcqhKVNRd4XddQYO0n6
|
||||
wn/x+HL0ioeNTv1vr3Jp+3XXNqac54oI05cDNmNHMWMxYzdtJ/0A/UDr3l7i/H8tcX/d+/tku/KS
|
||||
b+ezdrW7jbfXWzTjx3HE4ojf1IQNWWDrp9/5ZT1XdtU/3Nv4rCmjKv6VBRZwftoJUStVFEWmZLUs
|
||||
wqrfFrSWwaN2SjwdPP0BAAD//wMAHGSujHAHAAA=
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '1'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- EXPIRED
|
||||
Cf-Ray:
|
||||
- 9e0a73fc192da509-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 03:47:09 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 04:17:09 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 03:47:09 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/amendment/119/hamdt/2>; rel="canonical"
|
||||
Set-Cookie:
|
||||
- __cf_bm=CKV_kB9IKDO_Ben6qGSgqzHjDpYYhxbvzGWil2A2ayc-1774237629-1.0.1.1-WmvASPnSvODAY0JLuw6mOLKBXYXa_XPvJ5jk6GzPPn7jBZFStmobLYBfcN0zyd2CBaUTPDt.lU1AYwj78o5BknWJ1A_OI4faJDBr2Oavi3A;
|
||||
path=/; expires=Mon, 23-Mar-26 04:17:09 GMT; domain=.congress.gov; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=DlR3dGl05BZY4nXFYZwElh8jwy04QPtDdFJ8.tqmTzk-1774237629063-0.0.1.1-604800000;
|
||||
path=/; domain=.congress.gov; HttpOnly; Secure; SameSite=None
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct336rj3jm8lku8au06g
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '19972'
|
||||
X-Vcap-Request-Id:
|
||||
- 0994fc26-be51-485d-4ac1-1f4e13022eb9
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/amendment/119/hamdt/2/actions?api_key=MOCK_API_KEY&format=json
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA+yUX2vbMBTF3/MpLnpqofE/eYyojBEyRh/adXTd09iDYt+4GrGuJ8mhpvS7D8lt
|
||||
4nhhMCillPpJ6P50fHSufe8mAABMFk6RtkzAj7Dhn7vtaoAsqEQmgL3PkiRhJ4eQT9IFJEuyd9Mk
|
||||
nWb8MHet6sClXOSZyPMxZak1BX7rrMOaiZGdQBS9mdnJ3yUte/FztTTSdEArWJCuDFrL9uj70Vsd
|
||||
3jp/8FKDrAyi0hU4AneD8BWN6UDWqMsatYOjeZKkxzD3WOmhZQcbUgXChhxG4/u4rgmWPq+JzM7E
|
||||
wMC/E0+fMnGei4S/rMTn42BptUKDpY/1wkR9/BEcFaStKtFIfyUBiys445xPOc9PwWttt47fOvB/
|
||||
HTij1iLs+nDZN+CpY3zto6OPcTcn5OOAEPB8UyWsfvYwa2SldPhf9tJgBbXaW84ng/swg79btG4f
|
||||
3Rr80tZLNKFLAy+7+vWDoRtZl+4g8d2sA+BcY0Ucy0ZFxUPAUUWbeMPjLRun6SwOUnH2cUWmlu7D
|
||||
L0t6KPx4OHwR6WxUcgNPsmnWqghBxGOVXtxTodInMrn/AwAA//8DAMfNRJchBwAA
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '0'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- EXPIRED
|
||||
Cf-Ray:
|
||||
- 9e0a73fecb305edd-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 03:47:09 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 04:17:09 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 03:47:09 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/amendment/119/hamdt/2/actions>; rel="canonical"
|
||||
Set-Cookie:
|
||||
- __cf_bm=mYIsHHJKLGlZTktdurFayYzxN7P1UBs1jz7zNvCrBwk-1774237629-1.0.1.1-tDJVH_nGtQSnBrUlcmfYmKfuUMuQG5lt2fTGwPJqPp52nJxhL.AfeCT5JMZ7.KmINvrjDgvyq7_6nsJrne7U2VzZxiGRpfXhqq9O4vwhTNk;
|
||||
path=/; expires=Mon, 23-Mar-26 04:17:09 GMT; domain=.congress.gov; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=mSj6_qUJfB2oH0Gi7jwTwfXw78ApLObFG5nEzMLZTq4-1774237629461-0.0.1.1-604800000;
|
||||
path=/; domain=.congress.gov; HttpOnly; Secure; SameSite=None
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct336rmesfut71i6bp80
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '19972'
|
||||
X-Vcap-Request-Id:
|
||||
- 99dde9e6-9343-4a36-4d4b-23e2043a9fd3
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/amendment/119/hamdt/2/text?api_key=MOCK_API_KEY&format=json
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA7RRO0/DMBDe+RVR5qYXOzzUSIihgDrwqFBhAHUwsZMaNbZxLi2o6n9HcWmahAiJ
|
||||
gfXue913myPP8zzfsEwqhlIrP/Y2bubmiS4V+rFH3Gg72KGteC9FgW0oy4XiuVB4V+avwvqx51N/
|
||||
0LOffRpRbRcs59iLeLRLB0A0RQzAjBwmWmVWFMUw0ytYRVBjgZAROCmgF6m2OcPzt0KrpvCeXIkS
|
||||
MuqssJGJGbOUiSsCuio78QrlNq1GUHzgk7CF1KpyealZh4IcjjN0PjSkJ0FIAhrNKInDMA7D54ZX
|
||||
w68t1y9bU/D7jMns9qYjV2PKdrnr9bpdbtVnYkUCVUYICdAIyBkBcgy55jKVgsP44WocHG4IDJJg
|
||||
mk0iQoPT4QJz/4f1dvDXG6aX1/9wwq/JDU97krcm886T9mnv01RYwQ/0HW1+tP0CAAD//wMAzQuW
|
||||
uWIDAAA=
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '0'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- EXPIRED
|
||||
Cf-Ray:
|
||||
- 9e0a74015d0bff01-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 03:47:09 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 04:17:09 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 03:47:09 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/amendment/119/hamdt/2/text>; rel="canonical"
|
||||
Set-Cookie:
|
||||
- __cf_bm=C9E74wyhKP7Yzn7pkBAdMt38YaHzFQyQX5Iha._eF1w-1774237629-1.0.1.1-uy8As6lBZ4Tnw.uzskJWbzdfEq1BBYDHXZHD_EdxnI8ZSp8.Pnp7Ac.CB2YNUFO_5rAh86l_r7gAJFuexqKcAzfGwrYyV3DDdKihGVK3KjI;
|
||||
path=/; expires=Mon, 23-Mar-26 04:17:09 GMT; domain=.congress.gov; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=4aCnA9tQ2YMgRWJIwnW13Ide1ljDAi7nVAG3icC8kh0-1774237629838-0.0.1.1-604800000;
|
||||
path=/; domain=.congress.gov; HttpOnly; Secure; SameSite=None
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct336rpldpse8i7fghgg
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '19972'
|
||||
X-Vcap-Request-Id:
|
||||
- 50238f3b-1ccb-4b67-589f-5d9bcf498719
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,160 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/amendment/119?api_key=MOCK_API_KEY&format=json&limit=1&offset=0&sort=updateDate+desc
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAAwAAAP//lJE9T8MwEIb3/grLQydax04ExFJUIXVlIhOIwSROMIo/sC8VqMp/R05L
|
||||
GtIJLz75fX333N1xhRBCWGhpai0NBMzRy/gWz3GKRldlTetliB5K85u/oun1m/SYI5zdZSleqPDt
|
||||
ZNSeHh735VLsXS1A7gWMFpaw202SbhgrKeXJPWf0+eqH76L1HcAFTohwavsLt23tgRxSMrVEKM1J
|
||||
ELoGEsl2jfVaQPERrMFT1mGMXk9lsBOtMgKUNZjPhoAr2xvAHGU5ZRcibOQX/AtnF6yH4tI2qmWo
|
||||
1rZpgoSCrjulVbyvSIczn5efvQywhJu2gynNZyOLEkgD5XkJwrlOVWN/ZEw+s55qRtes7Gr4AQAA
|
||||
//8DAKK2+S8oAgAA
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '0'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- MISS
|
||||
Cf-Ray:
|
||||
- 9e0a73f86d0b1571-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 03:47:08 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 04:17:08 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 03:47:08 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/amendment/119>; rel="canonical"
|
||||
Set-Cookie:
|
||||
- __cf_bm=CMeXlsnAwauXxbli0tC93gmaxK3dBd19Nl09xdxlIAY-1774237628-1.0.1.1-POCGHT30UqwehumX7cTqFdkzySlqoZje6mVEG8O20Im1cKmqidI8WQ9jVqzXKqq1rMPok4QYYlsykZg3VbU_UFGnN1mvOnx5xXJh7dDoIIg;
|
||||
path=/; expires=Mon, 23-Mar-26 04:17:08 GMT; domain=.congress.gov; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=ANzPi.dRDTaFcBp6eGuItROHqCe1ot7POgyCvXiV7vg-1774237628466-0.0.1.1-604800000;
|
||||
path=/; domain=.congress.gov; HttpOnly; Secure; SameSite=None
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct336refdt9g1isrble0
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '19973'
|
||||
X-Vcap-Request-Id:
|
||||
- 638f9800-bc1b-45cd-6af1-c0e65f589b6e
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/amendment/119/samdt/4743?api_key=MOCK_API_KEY&format=json
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA6xUwW7bMAy99ysEnZPYsrOtMTAMTnIp1vXQGj206EGxmVSDLHkSHTQo8u+DlMSx
|
||||
MyfdgB1FPpJP71F6vyKEEMpLUEUJCmlC3n1oF85RaGU7QZ/Ide2x0aAbr42kCaGviJVNgoBXYpRr
|
||||
tTJg7Wil18E6DppRAWOTwPKywGD8ZRwH+2HfltqUHL/+tFrRpvt20GLlOkAxFVL2MduNowlhbHJC
|
||||
T9XlAoxjyOLrmJ5ktREroWav/AB6AMURLsJmugAPPUWhQOkzj4BguLIkzXOwViyEFLghabEWVpsN
|
||||
memyFIgAJM2R6CWJwujTH902Vf+Yuio4wpwj3Khc1oVQqwzenDU0CqPPwzAeRhH9d5cWQsqdQYGT
|
||||
6mNT8guynTWlZYhbgXaJrbSy2riS5w77rt8euxB6VYsCbgrXaRqGLGaTk0t74FIYi3e89Fp+5yig
|
||||
F1VLeQA9gBqRqRGIA+ILyFRvCvJ8P0xvX/qKJT9O8HV9oIob3DjEfV/WopMvITS97Uv/hXslOFmD
|
||||
vRL95nkDm9NLW/p64TeymO95NJvEsnCchGEShk9trxDe8BGMvfxXsP/4V7iJH+9k82rSH/OsTfj4
|
||||
aroPJWMsCa+TiD3tGu6bUQO/arCnn+OB3N3ZJW4g2Z6Jv8KZl0FZZ2ldClulvKqkyLn7IwN/5RZ0
|
||||
p4RDHcXYXm1/AwAA//8DAJBVVY/dBQAA
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '2434'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- HIT
|
||||
Cf-Ray:
|
||||
- 9e0a73fb2812cb73-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 03:47:08 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 04:17:08 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 03:06:33 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/amendment/119/samdt/4743>; rel="canonical"
|
||||
Set-Cookie:
|
||||
- __cf_bm=iJuXqW4XKZUqwYN0D4arHuUwMVaQTuUi7qBu2RzEiAY-1774237628-1.0.1.1-MczgduoAU2xDIQiEvlku8r7w_b71Hc1OEMUtQynCVwTdkl6cD70wu1j3OYoFeObs1hQucbsYVeAL5ShshRMAVCp0hjnKlxf1IOlNd.JI1nw;
|
||||
path=/; expires=Mon, 23-Mar-26 04:17:08 GMT; domain=.congress.gov; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=Ae4YolCSd7m_cctjzumiUPJjk2yu_oZqYs9mC3H.A8M-1774237628671-0.0.1.1-604800000;
|
||||
path=/; domain=.congress.gov; HttpOnly; Secure; SameSite=None
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct336rhtr4ktlact71pg
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '19972'
|
||||
X-Vcap-Request-Id:
|
||||
- d8a6f50d-632a-42ff-511c-43484e83f9e1
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -0,0 +1,520 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers: {}
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/committee/senate/slin00/reports?api_key=MOCK_API_KEY&format=json&limit=250
|
||||
response:
|
||||
body:
|
||||
string: "{\n \"pagination\": {\n \"count\": 73\n },\n \"reports\":
|
||||
[\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 113-288\",\n \"congress\": 113,\n \"number\":
|
||||
288,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 13:18:45+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/113/SRPT/288?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 109-85\",\n \"congress\": 109,\n \"number\":
|
||||
85,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 00:05:53+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/109/SRPT/85?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 109-142\",\n \"congress\": 109,\n \"number\":
|
||||
142,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 00:09:29+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/109/SRPT/142?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 109-259\",\n \"congress\": 109,\n \"number\":
|
||||
259,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 00:05:29+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/109/SRPT/259?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 107-63\",\n \"congress\": 107,\n \"number\":
|
||||
63,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-28 04:02:59+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/107/SRPT/63?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 107-149\",\n \"congress\": 107,\n \"number\":
|
||||
149,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-28 04:04:01+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/107/SRPT/149?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 111-55\",\n \"congress\": 111,\n \"number\":
|
||||
55,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-19 23:30:50+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/111/SRPT/55?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 111-223\",\n \"congress\": 111,\n \"number\":
|
||||
223,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-19 23:31:47+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/111/SRPT/223?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 108-44\",\n \"congress\": 108,\n \"number\":
|
||||
44,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-26 06:17:32+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/108/SRPT/44?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 108-258\",\n \"congress\": 108,\n \"number\":
|
||||
258,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-26 06:18:23+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/108/SRPT/258?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-2\",\n \"congress\": 110,\n \"number\":
|
||||
2,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-08-27 12:25:37+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/2?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-75\",\n \"congress\": 110,\n \"number\":
|
||||
75,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-08-27 12:27:02+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/75?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-125\",\n \"congress\": 110,\n \"number\":
|
||||
125,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-08-27 12:29:49+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/125?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-209\",\n \"congress\": 110,\n \"number\":
|
||||
209,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-08-27 12:27:47+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/209?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-333\",\n \"congress\": 110,\n \"number\":
|
||||
333,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-08-27 12:23:06+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/333?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 112-3\",\n \"congress\": 112,\n \"number\":
|
||||
3,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 13:18:11+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/112/SRPT/3?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 113-233\",\n \"congress\": 113,\n \"number\":
|
||||
233,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 13:20:09+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/113/SRPT/233?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-3\",\n \"congress\": 110,\n \"number\":
|
||||
3,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-08-27 12:29:56+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/3?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 104-97\",\n \"congress\": 104,\n \"number\":
|
||||
97,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:39:22+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/104/SRPT/97?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 104-4\",\n \"congress\": 104,\n \"number\":
|
||||
4,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:41:12+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/104/SRPT/4?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 104-246\",\n \"congress\": 104,\n \"number\":
|
||||
246,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:40:58+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/104/SRPT/246?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 104-258\",\n \"congress\": 104,\n \"number\":
|
||||
258,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:38:45+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/104/SRPT/258?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 104-278\",\n \"congress\": 104,\n \"number\":
|
||||
278,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:41:33+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/104/SRPT/278?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 105-24\",\n \"congress\": 105,\n \"number\":
|
||||
24,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:23:44+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/105/SRPT/24?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 105-165\",\n \"congress\": 105,\n \"number\":
|
||||
165,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:23:38+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/105/SRPT/165?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 105-185\",\n \"congress\": 105,\n \"number\":
|
||||
185,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:21:26+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/105/SRPT/185?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 105-1\",\n \"congress\": 105,\n \"number\":
|
||||
1,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 01:22:29+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/105/SRPT/1?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 109-360\",\n \"congress\": 109,\n \"number\":
|
||||
360,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-03-20 00:09:14+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/109/SRPT/360?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 108-52\",\n \"congress\": 108,\n \"number\":
|
||||
52,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-26 06:18:07+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/108/SRPT/52?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 107-51\",\n \"congress\": 107,\n \"number\":
|
||||
51,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-28 04:03:24+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/107/SRPT/51?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 106-48\",\n \"congress\": 106,\n \"number\":
|
||||
48,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-27 04:08:54+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/106/SRPT/48?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 106-352\",\n \"congress\": 106,\n \"number\":
|
||||
352,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-27 04:04:56+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/106/SRPT/352?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 106-279\",\n \"congress\": 106,\n \"number\":
|
||||
279,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-27 04:04:56+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/106/SRPT/279?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 106-3\",\n \"congress\": 106,\n \"number\":
|
||||
3,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2015-09-27 04:08:51+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/106/SRPT/3?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 119-51\",\n \"congress\": 119,\n \"number\":
|
||||
51,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2025-08-13 14:21:15+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/119/SRPT/51?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 114-277\",\n \"congress\": 114,\n \"number\":
|
||||
277,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2016-06-16 13:40:52+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/114/SRPT/277?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 115-2\",\n \"congress\": 115,\n \"number\":
|
||||
2,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2017-01-21 09:58:52+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/115/SRPT/2?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 113-134\",\n \"congress\": 113,\n \"number\":
|
||||
134,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-19 18:49:02+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/113/SRPT/134?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 113-7\",\n \"congress\": 113,\n \"number\":
|
||||
7,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-19 18:50:54+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/113/SRPT/7?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 108-301\",\n \"congress\": 108,\n \"number\":
|
||||
301,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-27 01:50:24+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/108/SRPT/301?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 114-32\",\n \"congress\": 114,\n \"number\":
|
||||
32,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2016-03-28 22:10:55+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/114/SRPT/32?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 114-83\",\n \"congress\": 114,\n \"number\":
|
||||
83,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2016-03-28 22:11:21+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/114/SRPT/83?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 114-8\",\n \"congress\": 114,\n \"number\":
|
||||
8,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2016-03-28 22:10:37+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/114/SRPT/8?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 113-119\",\n \"congress\": 113,\n \"number\":
|
||||
119,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 13:20:01+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/113/SRPT/119?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 113-120\",\n \"congress\": 113,\n \"number\":
|
||||
120,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 13:20:01+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/113/SRPT/120?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"House\",\n \"citation\":
|
||||
\"H. Rept. 107-792\",\n \"congress\": 107,\n \"number\":
|
||||
792,\n \"part\": 1,\n \"type\": \"HRPT\",\n \"updateDate\":
|
||||
\"2016-10-29 12:18:54+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/107/HRPT/792?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 115-13\",\n \"congress\": 115,\n \"number\":
|
||||
13,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2017-03-30 13:12:18+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/115/SRPT/13?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 115-298\",\n \"congress\": 115,\n \"number\":
|
||||
298,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-07-12 13:54:46+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/115/SRPT/298?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 109-330\",\n \"congress\": 109,\n \"number\":
|
||||
330,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-25 03:27:25+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/109/SRPT/330?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 109-331\",\n \"congress\": 109,\n \"number\":
|
||||
331,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-25 03:27:29+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/109/SRPT/331?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 111-199\",\n \"congress\": 111,\n \"number\":
|
||||
199,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-23 03:51:23+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/111/SRPT/199?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 111-6\",\n \"congress\": 111,\n \"number\":
|
||||
6,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-23 03:51:23+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/111/SRPT/6?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-346\",\n \"congress\": 110,\n \"number\":
|
||||
346,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-22 03:02:22+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/346?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-345\",\n \"congress\": 110,\n \"number\":
|
||||
345,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-22 03:02:23+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/345?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-76\",\n \"congress\": 110,\n \"number\":
|
||||
76,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-22 03:02:23+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/76?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 110-57\",\n \"congress\": 110,\n \"number\":
|
||||
57,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2018-11-22 03:02:23+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/110/SRPT/57?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 112-12\",\n \"congress\": 112,\n \"number\":
|
||||
12,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 12:02:54+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/112/SRPT/12?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 115-151\",\n \"congress\": 115,\n \"number\":
|
||||
151,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2017-09-08 14:25:31+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/115/SRPT/151?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 112-43\",\n \"congress\": 112,\n \"number\":
|
||||
43,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 12:03:00+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/112/SRPT/43?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 112-174\",\n \"congress\": 112,\n \"number\":
|
||||
174,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 12:03:06+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/112/SRPT/174?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 112-192\",\n \"congress\": 112,\n \"number\":
|
||||
192,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-02-17 12:03:07+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/112/SRPT/192?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 115-182\",\n \"congress\": 115,\n \"number\":
|
||||
182,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2017-11-08 05:40:20+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/115/SRPT/182?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 116-233\",\n \"congress\": 116,\n \"number\":
|
||||
233,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2020-06-20 09:56:07+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/116/SRPT/233?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 116-20\",\n \"congress\": 116,\n \"number\":
|
||||
20,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-04-05 09:56:06+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/116/SRPT/20?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 116-47\",\n \"congress\": 116,\n \"number\":
|
||||
47,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2019-06-16 09:56:06+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/116/SRPT/47?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 116-290\",\n \"congress\": 116,\n \"number\":
|
||||
290,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2020-11-18 13:41:12+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/116/SRPT/290?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 117-2\",\n \"congress\": 117,\n \"number\":
|
||||
2,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2021-04-08 11:56:11+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/117/SRPT/2?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 117-37\",\n \"congress\": 117,\n \"number\":
|
||||
37,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2021-08-13 11:28:23+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/117/SRPT/37?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 118-5\",\n \"congress\": 118,\n \"number\":
|
||||
5,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2023-03-31 16:56:12+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/118/SRPT/5?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 118-59\",\n \"congress\": 118,\n \"number\":
|
||||
59,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2023-07-26 01:26:14+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/118/SRPT/59?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 117-132\",\n \"congress\": 117,\n \"number\":
|
||||
132,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2022-07-26 11:56:20+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/117/SRPT/132?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 118-181\",\n \"congress\": 118,\n \"number\":
|
||||
181,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2024-06-24 12:21:10+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/118/SRPT/181?format=json\"\n
|
||||
\ },\n {\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 119-1\",\n \"congress\": 119,\n \"number\":
|
||||
1,\n \"part\": 1,\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2025-03-07 11:21:13+00:00\",\n \"url\": \"https://api.congress.gov/v3/committee-report/119/SRPT/1?format=json\"\n
|
||||
\ }\n ],\n \"request\": {\n \"chamber\": \"senate\",\n
|
||||
\ \"committeeUrl\": \"https://api.congress.gov/v3/committee/senate/slin00?format=json\",\n
|
||||
\ \"contentType\": \"application/json\",\n \"format\": \"json\",\n
|
||||
\ \"systemCode\": \"slin00\"\n }\n}"
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '161'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- HIT
|
||||
Cf-Ray:
|
||||
- 9e0b01e3a9b5b876-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 05:24:01 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 05:54:01 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 05:21:19 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/committee/senate/slin00/reports>; rel="canonical"
|
||||
Set-Cookie:
|
||||
- __cf_bm=7wWG6sBN3iBL9gOGx_Hzkzie7EkEyyOEflz0EZ1.ZRE-1774243441-1.0.1.1-s3Cie260TJw_qw0HKN4YE3AX54G15G7cv0djsCclwoffMLQC.WpZO4QCl3j2AlrPWR0fPzPVZ52vLpdMOU0.dJMPbMonhJl5tjigH4pAj_4;
|
||||
path=/; expires=Mon, 23-Mar-26 05:54:01 GMT; domain=.congress.gov; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=mqW8adDI7kmPYdVq4pnysM3Nt6A2jpYVknvEcqti3Fs-1774243441236-0.0.1.1-604800000;
|
||||
path=/; domain=.congress.gov; HttpOnly; Secure; SameSite=None
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct34j6kiq3njs9eek8kg
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '18659'
|
||||
X-Vcap-Request-Id:
|
||||
- 947ac4fe-dc86-418c-47f9-af8883d3e956
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Cookie:
|
||||
- __cf_bm=7wWG6sBN3iBL9gOGx_Hzkzie7EkEyyOEflz0EZ1.ZRE-1774243441-1.0.1.1-s3Cie260TJw_qw0HKN4YE3AX54G15G7cv0djsCclwoffMLQC.WpZO4QCl3j2AlrPWR0fPzPVZ52vLpdMOU0.dJMPbMonhJl5tjigH4pAj_4;
|
||||
_cfuvid=mqW8adDI7kmPYdVq4pnysM3Nt6A2jpYVknvEcqti3Fs-1774243441236-0.0.1.1-604800000
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/committee-report/119/SRPT/51?api_key=MOCK_API_KEY&format=json
|
||||
response:
|
||||
body:
|
||||
string: "{\n \"committeeReports\": [\n {\n \"associatedBill\":
|
||||
[\n {\n \"congress\": 119,\n \"number\":
|
||||
\"2342\",\n \"type\": \"S\",\n \"url\":
|
||||
\"https://api.congress.gov/v3/bill/119/s/2342?format=json\"\n }\n
|
||||
\ ],\n \"chamber\": \"Senate\",\n \"citation\":
|
||||
\"S. Rept. 119-51\",\n \"committees\": [\n {\n \"name\":
|
||||
\"Intelligence (Select) Committee\",\n \"systemCode\":
|
||||
\"slin00\",\n \"url\": \"https://api.congress.gov/v3/committee/senate/slin00?format=json\"\n
|
||||
\ }\n ],\n \"congress\": 119,\n \"isConferenceReport\":
|
||||
false,\n \"issueDate\": \"2025-07-29T04:00:00Z\",\n \"number\":
|
||||
51,\n \"part\": 1,\n \"reportType\": \"S.Rept.\",\n
|
||||
\ \"sessionNumber\": 1,\n \"text\": {\n \"count\":
|
||||
2,\n \"url\": \"https://api.congress.gov/v3/committee-report/119/SRPT/51/text?format=json\"\n
|
||||
\ },\n \"title\": \"INTELLIGENCE AUTHORIZATION ACT FOR
|
||||
FISCAL YEAR 2026\",\n \"type\": \"SRPT\",\n \"updateDate\":
|
||||
\"2026-02-04T04:11:38Z\"\n }\n ],\n \"request\": {\n \"congress\":
|
||||
\"119\",\n \"contentType\": \"application/json\",\n \"format\":
|
||||
\"json\",\n \"reportNumber\": \"51\",\n \"reportType\": \"srpt\"\n
|
||||
\ }\n}"
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '707'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- HIT
|
||||
Cf-Ray:
|
||||
- 9e0b01e3fd51ef3f-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 05:24:01 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 05:54:01 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 05:12:13 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/committee-report/119/SRPT/51>; rel="canonical"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct34j6kutb5sgp2p4iu0
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '18658'
|
||||
X-Vcap-Request-Id:
|
||||
- e511de21-9e59-4fbc-42de-6fcee60d1bc0
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Cookie:
|
||||
- __cf_bm=7wWG6sBN3iBL9gOGx_Hzkzie7EkEyyOEflz0EZ1.ZRE-1774243441-1.0.1.1-s3Cie260TJw_qw0HKN4YE3AX54G15G7cv0djsCclwoffMLQC.WpZO4QCl3j2AlrPWR0fPzPVZ52vLpdMOU0.dJMPbMonhJl5tjigH4pAj_4;
|
||||
_cfuvid=mqW8adDI7kmPYdVq4pnysM3Nt6A2jpYVknvEcqti3Fs-1774243441236-0.0.1.1-604800000
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/committee-report/119/SRPT/1?api_key=MOCK_API_KEY&format=json
|
||||
response:
|
||||
body:
|
||||
string: "{\n \"committeeReports\": [\n {\n \"chamber\":
|
||||
\"Senate\",\n \"citation\": \"S. Rept. 119-1\",\n \"committees\":
|
||||
[\n {\n \"name\": \"Intelligence (Select)
|
||||
Committee\",\n \"systemCode\": \"slin00\",\n \"url\":
|
||||
\"https://api.congress.gov/v3/committee/senate/slin00?format=json\"\n }\n
|
||||
\ ],\n \"congress\": 119,\n \"isConferenceReport\":
|
||||
false,\n \"issueDate\": \"2025-02-20T05:00:00Z\",\n \"number\":
|
||||
1,\n \"part\": 1,\n \"reportType\": \"S.Rept.\",\n \"sessionNumber\":
|
||||
1,\n \"text\": {\n \"count\": 2,\n \"url\":
|
||||
\"https://api.congress.gov/v3/committee-report/119/SRPT/1/text?format=json\"\n
|
||||
\ },\n \"title\": \"REPORT OF THE SELECT COMMITTEE ON
|
||||
INTELLIGENCE UNITED STATES SENATE COVERING THE PERIOD JANUARY 3, 2023 TO JANUARY
|
||||
3, 2025\",\n \"type\": \"SRPT\",\n \"updateDate\": \"2025-05-27T14:13:28Z\"\n
|
||||
\ }\n ],\n \"request\": {\n \"congress\": \"119\",\n \"contentType\":
|
||||
\"application/json\",\n \"format\": \"json\",\n \"reportNumber\":
|
||||
\"1\",\n \"reportType\": \"srpt\"\n }\n}"
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '1408'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- HIT
|
||||
Cf-Ray:
|
||||
- 9e0b01e46c2b0ba9-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 05:24:01 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 05:54:01 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 05:00:32 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/committee-report/119/SRPT/1>; rel="canonical"
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct34j6lfsf5lkfelcpag
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '18659'
|
||||
X-Vcap-Request-Id:
|
||||
- 772985dd-6a9c-43a1-661f-8cdcc576224d
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -0,0 +1,957 @@
|
||||
interactions:
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://unitedstates.github.io/congress-legislators/committee-membership-current.json
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
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
|
||||
XQcA
|
||||
headers:
|
||||
Accept-Ranges:
|
||||
- bytes
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '0'
|
||||
Cache-Control:
|
||||
- max-age=600
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Length:
|
||||
- '46116'
|
||||
Content-Type:
|
||||
- application/json; charset=utf-8
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 05:24:54 GMT
|
||||
Etag:
|
||||
- W/"69baeb7e-75db7"
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 05:34:54 GMT
|
||||
Last-Modified:
|
||||
- Wed, 18 Mar 2026 18:14:22 GMT
|
||||
Server:
|
||||
- GitHub.com
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
Via:
|
||||
- 1.1 varnish
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Cache-Hits:
|
||||
- '0'
|
||||
X-Fastly-Request-ID:
|
||||
- 3587f52f21a01d3844f7881bf5e8fb2ada1f0099
|
||||
X-GitHub-Request-Id:
|
||||
- AEAE:14129F:37CBEDB:3F22384:69C0CEA4
|
||||
X-Served-By:
|
||||
- cache-bfi-krnt7300116-BFI
|
||||
X-Timer:
|
||||
- S1774243494.097309,VS0,VE90
|
||||
x-proxy-cache:
|
||||
- MISS
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
- request:
|
||||
body: null
|
||||
headers:
|
||||
Accept:
|
||||
- application/json
|
||||
Accept-Encoding:
|
||||
- gzip, deflate
|
||||
Connection:
|
||||
- keep-alive
|
||||
method: GET
|
||||
uri: https://api.congress.gov/v3/committee/senate/slin00?api_key=MOCK_API_KEY&format=json
|
||||
response:
|
||||
body:
|
||||
string: !!binary |
|
||||
H4sIAAAAAAAAA6yWXWvbMBSG7/srhK82aGLZcZPYMEaXMiiMtiwZYx27UOwTW5ssedJRSij978Mf
|
||||
Se3Oa0bwpaWj857n+NXH4xkhhDixynOOCOBE5LEaqobXXAjTGWqirUQnIsEsPO/OWC2ciDgZYmEi
|
||||
12UFH8dKphqMGadq624n7kHKNSAZgmsEl5S6ldb7jdI5w3c/jZLOIfXTs8pzpV9hbTjCl67iw8PD
|
||||
mEsEIXgKMoZxLVKJOy/SWMljhlzJVxD9+WQ4xPpr1NE+Tpxxg0rvnIh871TSrbjbnNWugIVKyt/p
|
||||
LEFAjM753+FgkK0FNxmX6aXFTGmOpY4TBmRJPoMhAaV9CwVfa6Z3t5tFQ37D8krrutV68qZWftub
|
||||
QcWfuPwFyRVDdp2Ua+UspDPPD4K+eLXZ8JgzsReqU5PFHpgoSdrifTkMMo1XDKsEXjibjujFyAtX
|
||||
NIgojSi9711kC9Clo2QCEq9UbHOQeGPzNegyzzcSjK9vyNz1wqhvvS0ShrBX9al/MaLeyAtWXhjR
|
||||
aeQH905n0dPh60fLA9wsrNZQWRK1hdaUVDmXx2zs+fPhbNxSPO5eDYXS+EppswE3WCN2vCpj14cc
|
||||
5n92lmx8d7sFbXiaIVEbghmQFWitNDdIllZvgQvBSu/faZVqlpNlS6jXXjuDkO+3aoXh9dro1KZ4
|
||||
/c140ZAj1B9skgKeAuMPCuMPAXMpmdgZbgiTSfmfEhuXXj6FbjIo3WQIuoUS5clYApV8H5UGnkpy
|
||||
W4Cut+wpnNNBOaevcPaefj0Vta8lB3dF/033j9OXTlY+jYJ55IXN6dv019Hw24LB7isoztj+tK8x
|
||||
ug+J8m7AVVMCKwrR3OxuhdcKranLqJczvYB1YWdPfwAAAP//AwAohTXKowkAAA==
|
||||
headers:
|
||||
Access-Control-Allow-Origin:
|
||||
- '*'
|
||||
Age:
|
||||
- '0'
|
||||
Cache-Control:
|
||||
- public, max-age=1800
|
||||
Cf-Cache-Status:
|
||||
- EXPIRED
|
||||
Cf-Ray:
|
||||
- 9e0b032e0fe9fef7-PDX
|
||||
Connection:
|
||||
- keep-alive
|
||||
Content-Encoding:
|
||||
- gzip
|
||||
Content-Type:
|
||||
- application/json
|
||||
Date:
|
||||
- Mon, 23 Mar 2026 05:24:54 GMT
|
||||
Expires:
|
||||
- Mon, 23 Mar 2026 05:54:54 GMT
|
||||
Last-Modified:
|
||||
- Mon, 23 Mar 2026 05:24:54 GMT
|
||||
Link:
|
||||
- <https://api.congress.gov/v3/committee/senate/slin00>; rel="canonical"
|
||||
Set-Cookie:
|
||||
- __cf_bm=Ghx7xy3Ap969eMkaWoWLI2bbeo3GET5wXKVnlDnu74g-1774243494-1.0.1.1-LISaBpl8BfmaZ7_RRHd9nwVsnlYXcyuoU.DMJUqEo8mN8gDthR4.XhZzohXPCeroO_uih__X9FuEQu8qzG4xw2D_6GX9T5Bf0jT7v6wgtXI;
|
||||
path=/; expires=Mon, 23-Mar-26 05:54:54 GMT; domain=.congress.gov; HttpOnly;
|
||||
Secure; SameSite=None
|
||||
- _cfuvid=iaaJ5k.BVHcFj2Usc2rZ5Gq2tasqNuenOKAB2VsBAJc-1774243494321-0.0.1.1-604800000;
|
||||
path=/; domain=.congress.gov; HttpOnly; Secure; SameSite=None
|
||||
Strict-Transport-Security:
|
||||
- max-age=31536000; includeSubDomains; preload
|
||||
Transfer-Encoding:
|
||||
- chunked
|
||||
Vary:
|
||||
- Accept-Encoding
|
||||
- Accept, Accept-Encoding
|
||||
Via:
|
||||
- https/1.1 api-umbrella (ApacheTrafficServer [cMsSf ])
|
||||
X-Api-Umbrella-Request-Id:
|
||||
- ct34jjhhs9hdveiue3tg
|
||||
X-Cache:
|
||||
- MISS
|
||||
X-Content-Type-Options:
|
||||
- nosniff
|
||||
X-Frame-Options:
|
||||
- DENY
|
||||
X-Ratelimit-Limit:
|
||||
- '20000'
|
||||
X-Ratelimit-Remaining:
|
||||
- '18686'
|
||||
X-Vcap-Request-Id:
|
||||
- 9ff444f3-ccc4-43d2-5aab-0dc11bd46aee
|
||||
status:
|
||||
code: 200
|
||||
message: OK
|
||||
version: 1
|
||||
@@ -3,9 +3,18 @@
|
||||
from datetime import datetime
|
||||
|
||||
import pytest
|
||||
from openbb_congress_gov.models.amendment_info import CongressAmendmentInfoFetcher
|
||||
from openbb_congress_gov.models.amendment_text import CongressAmendmentTextFetcher
|
||||
from openbb_congress_gov.models.bill_info import CongressBillInfoFetcher
|
||||
from openbb_congress_gov.models.bill_text import CongressBillTextFetcher
|
||||
from openbb_congress_gov.models.congress_amendments import CongressAmendmentsFetcher
|
||||
from openbb_congress_gov.models.congress_bills import CongressBillsFetcher
|
||||
from openbb_congress_gov.models.congress_committee_documents import (
|
||||
CongressCommitteeDocumentsFetcher,
|
||||
)
|
||||
from openbb_congress_gov.models.congress_committee_info import (
|
||||
CongressCommitteeInfoFetcher,
|
||||
)
|
||||
from openbb_congress_gov.utils.helpers import year_to_congress
|
||||
from openbb_core.app.service.user_service import UserService
|
||||
|
||||
@@ -77,3 +86,72 @@ def test_congress_bill_text_fetcher(credentials=test_credentials):
|
||||
fetcher = CongressBillTextFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_congress_amendments_fetcher(credentials=test_credentials):
|
||||
"""Test Congress Amendments fetcher."""
|
||||
params = {
|
||||
"congress": 119,
|
||||
"limit": 1,
|
||||
}
|
||||
|
||||
fetcher = CongressAmendmentsFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_congress_amendment_info_fetcher(credentials=test_credentials):
|
||||
"""Test Congress Amendment Info fetcher."""
|
||||
params = {
|
||||
"amendment_url": "119/hamdt/2",
|
||||
}
|
||||
|
||||
fetcher = CongressAmendmentInfoFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_congress_amendment_text_fetcher(credentials=test_credentials):
|
||||
"""Test Congress Bill Text fetcher."""
|
||||
params = {
|
||||
"urls": [
|
||||
"https://www.congress.gov/119/crec/2026/03/21/172/52/CREC-2026-03-21-pt1-PgS1484-6.pdf"
|
||||
],
|
||||
}
|
||||
|
||||
fetcher = CongressAmendmentTextFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_congress_committee_documents_fetcher(credentials=test_credentials):
|
||||
"""Test Congress Committee Documents fetcher."""
|
||||
params = {
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
"doc_type": "report",
|
||||
"congress": 119,
|
||||
"limit": 5,
|
||||
"use_cache": False,
|
||||
}
|
||||
|
||||
fetcher = CongressCommitteeDocumentsFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
|
||||
@pytest.mark.record_http
|
||||
def test_congress_committee_info_fetcher(credentials=test_credentials):
|
||||
"""Test Congress Committee Info fetcher."""
|
||||
params = {
|
||||
"chamber": "senate",
|
||||
"committee": "slin00",
|
||||
}
|
||||
|
||||
fetcher = CongressCommitteeInfoFetcher()
|
||||
result = fetcher.test(params, credentials)
|
||||
assert result is None
|
||||
|
||||
Reference in New Issue
Block a user