Update private self-contained Congress Space bundle
Browse files- README.md +29 -30
- __pycache__/public_space_app.cpython-311.pyc +0 -0
- public_copy.json +1 -0
- public_space_app.py +25 -13
- requirements.txt +2 -3
README.md
CHANGED
|
@@ -1,31 +1,30 @@
|
|
| 1 |
-
---
|
| 2 |
-
title: Congress Public Records Slice
|
| 3 |
-
emoji: 🔎
|
| 4 |
-
colorFrom: green
|
| 5 |
-
colorTo: yellow
|
| 6 |
-
sdk: gradio
|
| 7 |
-
sdk_version: "5.23.1"
|
| 8 |
-
python_version: "3.11"
|
| 9 |
-
app_file: app.py
|
| 10 |
-
pinned: false
|
| 11 |
-
---
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
| 20 |
-
-
|
| 21 |
-
-
|
| 22 |
-
|
| 23 |
-
|
| 24 |
-
|
| 25 |
-
|
| 26 |
-
-
|
| 27 |
-
-
|
| 28 |
-
-
|
| 29 |
-
-
|
| 30 |
-
- Some rows remain review-tier or include unresolved official source references and should be read with those labels in mind.
|
| 31 |
- The public package includes verification summaries and SHA-backed artifact indexes, but it does not include the full internal raw corpus, so external verification is bounded by what is published here.
|
|
|
|
| 1 |
+
---
|
| 2 |
+
title: Congress Public Records Slice
|
| 3 |
+
emoji: 🔎
|
| 4 |
+
colorFrom: green
|
| 5 |
+
colorTo: yellow
|
| 6 |
+
sdk: gradio
|
| 7 |
+
sdk_version: "5.23.1"
|
| 8 |
+
python_version: "3.11"
|
| 9 |
+
app_file: app.py
|
| 10 |
+
pinned: false
|
| 11 |
+
---
|
| 12 |
+
|
| 13 |
+
# Congress Public Records Slice Space
|
| 14 |
+
|
| 15 |
+
Neutral Records explorer for a public-record slice of congressional money-and-power linkages.
|
| 16 |
+
|
| 17 |
+
## Runtime Notes
|
| 18 |
+
|
| 19 |
+
- This Space first checks for a bundled local `dataset_bundle` inside the Space repo, then falls back to the configured Hugging Face dataset repo.
|
| 20 |
+
- For local testing, set the `PUBLIC_RELEASE_LOCAL_ROOT` environment variable to the release root folder before launching `app.py`.
|
| 21 |
+
- The Space is intentionally neutral and does not assign guilt, wrongdoing, intent, or causality.
|
| 22 |
+
|
| 23 |
+
## Required Caveats
|
| 24 |
+
|
| 25 |
+
- This release is a slice of public-record data, not a complete accounting of all potentially relevant data.
|
| 26 |
+
- Future releases may update or expand this slice as source recovery, parsing, and evidence linkage improve.
|
| 27 |
+
- This release does not assign guilt, wrongdoing, intent, or causality to any person or organization.
|
| 28 |
+
- The release shows public-record overlaps, timing, and linkage strength, not proof of illegality or corruption.
|
| 29 |
+
- Some rows remain review-tier or include unresolved official source references and should be read with those labels in mind.
|
|
|
|
| 30 |
- The public package includes verification summaries and SHA-backed artifact indexes, but it does not include the full internal raw corpus, so external verification is bounded by what is published here.
|
__pycache__/public_space_app.cpython-311.pyc
ADDED
|
Binary file (48.3 kB). View file
|
|
|
public_copy.json
CHANGED
|
@@ -4,6 +4,7 @@
|
|
| 4 |
"subtitle": "Neutral Records explorer for a public-record slice of congressional money-and-power linkages.",
|
| 5 |
"dataset_repo_id": "cjc0013/cmp-data",
|
| 6 |
"space_repo_id": "cjc0013/cmp",
|
|
|
|
| 7 |
"landing_markdown": "# Congress Public Records Slice\n\nA neutral, review-oriented slice of House public-record linkages across financial disclosures, sector overlap, and community project funding recipient relationships.\n\n- This release is a slice of public-record data, not a complete accounting of all potentially relevant data.\n- Future releases may update or expand this slice as source recovery, parsing, and evidence linkage improve.\n- This release does not assign guilt, wrongdoing, intent, or causality to any person or organization.\n- The release shows public-record overlaps, timing, and linkage strength, not proof of illegality or corruption.\n- Some rows remain review-tier or include unresolved official source references and should be read with those labels in mind.\n- The public package includes verification summaries and SHA-backed artifact indexes, but it does not include the full internal raw corpus, so external verification is bounded by what is published here.",
|
| 8 |
"downloads_markdown": "## Downloads\n\n- Dataset repo id: `cjc0013/cmp-data`\n- Space repo id: `cjc0013/cmp`\n\nUse the dataset bundle files for direct review, CSV download, and SHA-backed source checks.",
|
| 9 |
"dataset_bundle_prefix": "dataset_bundle"
|
|
|
|
| 4 |
"subtitle": "Neutral Records explorer for a public-record slice of congressional money-and-power linkages.",
|
| 5 |
"dataset_repo_id": "cjc0013/cmp-data",
|
| 6 |
"space_repo_id": "cjc0013/cmp",
|
| 7 |
+
"welcome_markdown": "# Congress Public Records Slice\n\nStart with the **Network Graph** tab.\n\n- Search one House member name first.\n- Green dots are House members, rust dots are funding recipients, and gold dots are sectors.\n- Lines show public-record support in this released slice; thicker lines mean more supporting rows.\n- Use **Explore** and **Event Detail** to inspect the underlying rows, source URLs, and SHA-backed artifacts.\n\nThis is an exploration tool, not an accusation tool.",
|
| 8 |
"landing_markdown": "# Congress Public Records Slice\n\nA neutral, review-oriented slice of House public-record linkages across financial disclosures, sector overlap, and community project funding recipient relationships.\n\n- This release is a slice of public-record data, not a complete accounting of all potentially relevant data.\n- Future releases may update or expand this slice as source recovery, parsing, and evidence linkage improve.\n- This release does not assign guilt, wrongdoing, intent, or causality to any person or organization.\n- The release shows public-record overlaps, timing, and linkage strength, not proof of illegality or corruption.\n- Some rows remain review-tier or include unresolved official source references and should be read with those labels in mind.\n- The public package includes verification summaries and SHA-backed artifact indexes, but it does not include the full internal raw corpus, so external verification is bounded by what is published here.",
|
| 9 |
"downloads_markdown": "## Downloads\n\n- Dataset repo id: `cjc0013/cmp-data`\n- Space repo id: `cjc0013/cmp`\n\nUse the dataset bundle files for direct review, CSV download, and SHA-backed source checks.",
|
| 10 |
"dataset_bundle_prefix": "dataset_bundle"
|
public_space_app.py
CHANGED
|
@@ -245,6 +245,18 @@ def _consistency_summary_markdown(consistency: Dict[str, Any]) -> str:
|
|
| 245 |
)
|
| 246 |
|
| 247 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 248 |
def _render_graph(nodes: pd.DataFrame, edges: pd.DataFrame) -> str:
|
| 249 |
if edges.empty:
|
| 250 |
return "<div style=\"padding: 1rem; border: 1px solid #d6d0c4; background: #fffdf8; color: #3a3a3a;\">No relationships match the current filters.</div>"
|
|
@@ -332,7 +344,7 @@ def _render_graph(nodes: pd.DataFrame, edges: pd.DataFrame) -> str:
|
|
| 332 |
color=edge_style["color"],
|
| 333 |
dashes=edge_style["dashes"],
|
| 334 |
)
|
| 335 |
-
return network.generate_html(notebook=False)
|
| 336 |
|
| 337 |
|
| 338 |
def _event_detail(events: pd.DataFrame, provenance: pd.DataFrame, event_id: str) -> Tuple[str, pd.DataFrame]:
|
|
@@ -421,18 +433,7 @@ def build_app(copy_path: str | Path):
|
|
| 421 |
overview_member_limit = int(graph_defaults.get("overview_member_limit", 8))
|
| 422 |
|
| 423 |
with gr.Blocks(title=copy_payload.get("title", "Congress Public Records Slice")) as app:
|
| 424 |
-
gr.Markdown(copy_payload.get("landing_markdown", ""))
|
| 425 |
-
with gr.Tab("Explore"):
|
| 426 |
-
with gr.Row():
|
| 427 |
-
member_query = gr.Textbox(label="Member name or slug")
|
| 428 |
-
event_type = gr.Dropdown(label="Event type", choices=event_type_choices, value="all")
|
| 429 |
-
score_label = gr.Dropdown(label="Score label", choices=score_label_choices, value="all")
|
| 430 |
-
text_query = gr.Textbox(label="Issuer or sector search")
|
| 431 |
-
explore_df = gr.Dataframe(value=events.head(100), interactive=False)
|
| 432 |
-
def _update_events(member_query: str, event_type: str, score_label: str, text_query: str):
|
| 433 |
-
return _filter_events(events, member_query, event_type, score_label, text_query)
|
| 434 |
-
for control in (member_query, event_type, score_label, text_query):
|
| 435 |
-
control.change(_update_events, [member_query, event_type, score_label, text_query], explore_df)
|
| 436 |
with gr.Tab("Network Graph"):
|
| 437 |
gr.Markdown(_graph_intro_markdown(data["graph_config"]))
|
| 438 |
with gr.Row():
|
|
@@ -453,6 +454,17 @@ def build_app(copy_path: str | Path):
|
|
| 453 |
for control in (family, member_graph_query, target_query, graph_score, review_status, hide_unresolved_only, max_edges):
|
| 454 |
control.change(_update_graph, [family, member_graph_query, target_query, graph_score, review_status, hide_unresolved_only, max_edges], [graph_html, graph_df])
|
| 455 |
app.load(_update_graph, [family, member_graph_query, target_query, graph_score, review_status, hide_unresolved_only, max_edges], [graph_html, graph_df])
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 456 |
with gr.Tab("Event Detail"):
|
| 457 |
event_id = gr.Dropdown(label="Event id", choices=event_id_choices, value=event_id_choices[0] if event_id_choices else None)
|
| 458 |
event_detail_md = gr.Markdown()
|
|
|
|
| 245 |
)
|
| 246 |
|
| 247 |
|
| 248 |
+
def _embed_html_document(document_html: str, *, height: int = 760) -> str:
|
| 249 |
+
escaped = html.escape(document_html, quote=True)
|
| 250 |
+
return (
|
| 251 |
+
"<div style=\"border: 1px solid #d6d0c4; border-radius: 12px; overflow: hidden; background: #fbf7ee;\">"
|
| 252 |
+
f"<iframe srcdoc=\"{escaped}\" "
|
| 253 |
+
"style=\"width: 100%; border: 0; background: #fbf7ee;\" "
|
| 254 |
+
f"height=\"{int(height)}\" "
|
| 255 |
+
"sandbox=\"allow-scripts allow-same-origin allow-popups allow-downloads\"></iframe>"
|
| 256 |
+
"</div>"
|
| 257 |
+
)
|
| 258 |
+
|
| 259 |
+
|
| 260 |
def _render_graph(nodes: pd.DataFrame, edges: pd.DataFrame) -> str:
|
| 261 |
if edges.empty:
|
| 262 |
return "<div style=\"padding: 1rem; border: 1px solid #d6d0c4; background: #fffdf8; color: #3a3a3a;\">No relationships match the current filters.</div>"
|
|
|
|
| 344 |
color=edge_style["color"],
|
| 345 |
dashes=edge_style["dashes"],
|
| 346 |
)
|
| 347 |
+
return _embed_html_document(network.generate_html(notebook=False))
|
| 348 |
|
| 349 |
|
| 350 |
def _event_detail(events: pd.DataFrame, provenance: pd.DataFrame, event_id: str) -> Tuple[str, pd.DataFrame]:
|
|
|
|
| 433 |
overview_member_limit = int(graph_defaults.get("overview_member_limit", 8))
|
| 434 |
|
| 435 |
with gr.Blocks(title=copy_payload.get("title", "Congress Public Records Slice")) as app:
|
| 436 |
+
gr.Markdown(copy_payload.get("welcome_markdown", copy_payload.get("landing_markdown", "")))
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 437 |
with gr.Tab("Network Graph"):
|
| 438 |
gr.Markdown(_graph_intro_markdown(data["graph_config"]))
|
| 439 |
with gr.Row():
|
|
|
|
| 454 |
for control in (family, member_graph_query, target_query, graph_score, review_status, hide_unresolved_only, max_edges):
|
| 455 |
control.change(_update_graph, [family, member_graph_query, target_query, graph_score, review_status, hide_unresolved_only, max_edges], [graph_html, graph_df])
|
| 456 |
app.load(_update_graph, [family, member_graph_query, target_query, graph_score, review_status, hide_unresolved_only, max_edges], [graph_html, graph_df])
|
| 457 |
+
with gr.Tab("Explore"):
|
| 458 |
+
with gr.Row():
|
| 459 |
+
member_query = gr.Textbox(label="Member name or slug")
|
| 460 |
+
event_type = gr.Dropdown(label="Event type", choices=event_type_choices, value="all")
|
| 461 |
+
score_label = gr.Dropdown(label="Score label", choices=score_label_choices, value="all")
|
| 462 |
+
text_query = gr.Textbox(label="Issuer or sector search")
|
| 463 |
+
explore_df = gr.Dataframe(value=events.head(100), interactive=False)
|
| 464 |
+
def _update_events(member_query: str, event_type: str, score_label: str, text_query: str):
|
| 465 |
+
return _filter_events(events, member_query, event_type, score_label, text_query)
|
| 466 |
+
for control in (member_query, event_type, score_label, text_query):
|
| 467 |
+
control.change(_update_events, [member_query, event_type, score_label, text_query], explore_df)
|
| 468 |
with gr.Tab("Event Detail"):
|
| 469 |
event_id = gr.Dropdown(label="Event id", choices=event_id_choices, value=event_id_choices[0] if event_id_choices else None)
|
| 470 |
event_detail_md = gr.Markdown()
|
requirements.txt
CHANGED
|
@@ -1,3 +1,2 @@
|
|
| 1 |
-
pandas>=2.2.0
|
| 2 |
-
pyvis>=0.3.2
|
| 3 |
-
|
|
|
|
| 1 |
+
pandas>=2.2.0
|
| 2 |
+
pyvis>=0.3.2
|
|
|