|
2 | 2 |
|
3 | 3 | from pathlib import Path |
4 | 4 |
|
5 | | -from political_event_tracking_research.source_mention_extract import extract_source_records, infer_direction, match_symbols |
| 5 | +from political_event_tracking_research.source_mention_extract import ( |
| 6 | + extract_source_records, |
| 7 | + infer_direction, |
| 8 | + match_symbols, |
| 9 | +) |
6 | 10 | from political_event_tracking_research.source_mention_extract import MentionAlias |
7 | 11 |
|
8 | 12 |
|
@@ -51,3 +55,91 @@ def test_extract_source_records_outputs_confidence_by_source_type(tmp_path: Path |
51 | 55 | assert by_symbol["EVT3"]["confidence"] == "low" |
52 | 56 | assert by_symbol["EVT4"]["event_type"] == "procurement" |
53 | 57 | assert output.exists() |
| 58 | + |
| 59 | + |
| 60 | +def test_generic_aliases_are_context_only_and_keep_evidence(tmp_path: Path) -> None: |
| 61 | + raw_items = tmp_path / "source_items.csv" |
| 62 | + raw_items.write_text( |
| 63 | + "item_id,published_at,source_type,source_url,author,text\n" |
| 64 | + "nist-1,2026-04-01T00:00:00Z,government_policy,https://www.nist.gov/example,NIST," |
| 65 | + 'NIST guidance discusses nuclear reactor safety and tokenization.\n', |
| 66 | + encoding="utf-8", |
| 67 | + ) |
| 68 | + aliases = tmp_path / "aliases.csv" |
| 69 | + aliases.write_text( |
| 70 | + "symbol,name,aliases\n" |
| 71 | + "OKLO,Oklo,Oklo|OKLO|nuclear reactor\n" |
| 72 | + "COIN,Coinbase,Coinbase|COIN|tokenization\n", |
| 73 | + encoding="utf-8", |
| 74 | + ) |
| 75 | + |
| 76 | + rows = extract_source_records(raw_items, aliases, tmp_path / "events.csv") |
| 77 | + |
| 78 | + by_symbol = {row["symbol"]: row for row in rows} |
| 79 | + assert by_symbol["OKLO"]["entity_match_type"] == "industry_context" |
| 80 | + assert by_symbol["COIN"]["entity_match_type"] == "industry_context" |
| 81 | + assert by_symbol["OKLO"]["match_evidence"] == "nuclear reactor" |
| 82 | + assert by_symbol["COIN"]["relationship_type"] == "industry_context" |
| 83 | + |
| 84 | + |
| 85 | +def test_explicit_issuer_match_is_company_level(tmp_path: Path) -> None: |
| 86 | + raw_items = tmp_path / "source_items.csv" |
| 87 | + raw_items.write_text( |
| 88 | + "item_id,published_at,source_type,source_url,author,text\n" |
| 89 | + "issuer-1,2026-04-01T00:00:00Z,issuer_release,https://example.com/release,Issuer," |
| 90 | + 'Coinbase announced a new product.\n', |
| 91 | + encoding="utf-8", |
| 92 | + ) |
| 93 | + aliases = tmp_path / "aliases.csv" |
| 94 | + aliases.write_text("symbol,name,aliases\nCOIN,Coinbase,COIN|tokenization\n", encoding="utf-8") |
| 95 | + |
| 96 | + rows = extract_source_records(raw_items, aliases, tmp_path / "events.csv") |
| 97 | + |
| 98 | + assert rows[0]["entity_match_type"] == "issuer" |
| 99 | + assert rows[0]["relationship_type"] == "issuer" |
| 100 | + assert rows[0]["match_evidence"] == "Coinbase" |
| 101 | + |
| 102 | + |
| 103 | +def test_explicit_beneficiary_relation_is_preserved(tmp_path: Path) -> None: |
| 104 | + raw_items = tmp_path / "source_items.csv" |
| 105 | + raw_items.write_text( |
| 106 | + "item_id,published_at,source_type,source_url,author,text\n" |
| 107 | + "award-1,2026-04-01T00:00:00Z,government_procurement,https://www.govinfo.gov/example,Agency," |
| 108 | + 'Funding for Coinbase was announced.\n', |
| 109 | + encoding="utf-8", |
| 110 | + ) |
| 111 | + aliases = tmp_path / "aliases.csv" |
| 112 | + aliases.write_text("symbol,name,aliases\nCOIN,Coinbase,COIN\n", encoding="utf-8") |
| 113 | + |
| 114 | + rows = extract_source_records(raw_items, aliases, tmp_path / "events.csv") |
| 115 | + |
| 116 | + assert rows[0]["entity_match_type"] == "direct_beneficiary" |
| 117 | + assert rows[0]["relationship_type"] == "direct_beneficiary" |
| 118 | + |
| 119 | + |
| 120 | +def test_known_ticker_and_industry_collisions_never_become_issuer_events(tmp_path: Path) -> None: |
| 121 | + raw_items = tmp_path / "source_items.csv" |
| 122 | + raw_items.write_text( |
| 123 | + "item_id,published_at,source_type,source_url,author,text\n" |
| 124 | + "mstr,2026-04-01T00:00:00Z,government_policy,https://www.nist.gov/mstr,NIST,Strategy guidance\n" |
| 125 | + "oklo,2026-04-01T00:00:00Z,government_policy,https://www.nist.gov/oklo,NIST,nuclear reactor safety\n" |
| 126 | + "panw,2026-04-01T00:00:00Z,government_policy,https://www.nist.gov/panw,NIST,generic cybersecurity guidance\n" |
| 127 | + "coin,2026-04-01T00:00:00Z,government_policy,https://www.federalreserve.gov/coin,Fed,tokenization policy\n" |
| 128 | + "intc,2026-04-01T00:00:00Z,government_policy,https://www.commerce.gov/intc,Commerce,CHIPS Act funding\n", |
| 129 | + encoding="utf-8", |
| 130 | + ) |
| 131 | + aliases = tmp_path / "aliases.csv" |
| 132 | + aliases.write_text( |
| 133 | + "symbol,name,aliases\n" |
| 134 | + "MSTR,Strategy,Strategy|MSTR\n" |
| 135 | + "OKLO,Oklo,Oklo|OKLO|nuclear reactor\n" |
| 136 | + "PANW,Palo Alto Networks,Palo Alto Networks|PANW|cybersecurity\n" |
| 137 | + "COIN,Coinbase,Coinbase|COIN|tokenization\n" |
| 138 | + "INTC,Intel,Intel|INTC|CHIPS Act\n", |
| 139 | + encoding="utf-8", |
| 140 | + ) |
| 141 | + |
| 142 | + rows = extract_source_records(raw_items, aliases, tmp_path / "events.csv") |
| 143 | + |
| 144 | + assert {row["symbol"] for row in rows} == {"MSTR", "OKLO", "PANW", "COIN", "INTC"} |
| 145 | + assert {row["entity_match_type"] for row in rows} == {"industry_context"} |
0 commit comments