File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change 1+ Use a mortgage-specific deduction variable for the JCT mortgage tax expenditure target instead of broad interest deductions.
Original file line number Diff line number Diff line change 1- import logging
21import hashlib
2+ import logging
3+ from pathlib import Path
34from typing import List , Optional
45
56from sqlalchemy import event , text , UniqueConstraint
@@ -506,14 +507,29 @@ def create_database(
506507 # Create validation triggers
507508 create_validation_triggers (engine )
508509
509- # Create SQL views
510+ create_or_replace_views (engine )
511+
512+ logger .info (f"Database and tables created successfully at { db_uri } " )
513+ return engine
514+
515+
516+ def create_or_replace_views (engine ) -> None :
517+ """Refresh SQL views so existing databases pick up schema changes."""
510518 with engine .connect () as conn :
519+ conn .execute (text ("DROP VIEW IF EXISTS stratum_domain" ))
520+ conn .execute (text ("DROP VIEW IF EXISTS target_overview" ))
511521 conn .execute (text (STRATUM_DOMAIN_VIEW ))
512522 conn .execute (text (TARGET_OVERVIEW_VIEW ))
513523 conn .commit ()
514524
515- logger .info (f"Database and tables created successfully at { db_uri } " )
516- return engine
525+
526+ def refresh_views_for_db_path (db_path : str | Path ) -> None :
527+ """Refresh SQL views for an existing SQLite database file."""
528+ engine = create_engine (f"sqlite:///{ Path (db_path )} " )
529+ try :
530+ create_or_replace_views (engine )
531+ finally :
532+ engine .dispose ()
517533
518534
519535if __name__ == "__main__" :
Original file line number Diff line number Diff line change @@ -87,7 +87,7 @@ def extract_national_targets(dataset: str = DEFAULT_DATASET):
8787 "year" : HARDCODED_YEAR ,
8888 },
8989 {
90- "variable" : "interest_deduction " ,
90+ "variable" : "deductible_mortgage_interest " ,
9191 "value" : 24.8e9 ,
9292 "source" : "Joint Committee on Taxation" ,
9393 "notes" : "Mortgage interest deduction tax expenditure" ,
Original file line number Diff line number Diff line change 11import os
22
3- from policyengine_us_data .utils .huggingface import download
43from pathlib import Path
4+ from policyengine_us_data .db .create_database_tables import (
5+ refresh_views_for_db_path ,
6+ )
7+ from policyengine_us_data .utils .huggingface import download
58
69FOLDER = Path (__file__ ).parent
710
4144 local_folder = FOLDER ,
4245 version = None ,
4346 )
47+ refresh_views_for_db_path (FOLDER / "calibration" / "policy_data.db" )
Original file line number Diff line number Diff line change 11"""Shared fixtures for local area calibration tests."""
22
33import pytest
4+ from sqlalchemy import create_engine
45
6+ from policyengine_us_data .db .create_database_tables import (
7+ create_or_replace_views ,
8+ )
59from policyengine_us_data .storage import STORAGE_FOLDER
610
711
12+ @pytest .fixture (scope = "session" , autouse = True )
13+ def refresh_policy_db_views ():
14+ db_path = STORAGE_FOLDER / "calibration" / "policy_data.db"
15+ if db_path .exists ():
16+ engine = create_engine (f"sqlite:///{ db_path } " )
17+ try :
18+ create_or_replace_views (engine )
19+ finally :
20+ engine .dispose ()
21+
22+
823@pytest .fixture (scope = "module" )
924def db_uri ():
1025 db_path = STORAGE_FOLDER / "calibration" / "policy_data.db"
Original file line number Diff line number Diff line change 11import hashlib
2+ from sqlalchemy import text
23
34import pytest
45from sqlalchemy .exc import IntegrityError
89 Stratum ,
910 StratumConstraint ,
1011 Target ,
12+ create_or_replace_views ,
1113 create_database ,
1214)
1315
@@ -226,6 +228,38 @@ def test_target_with_null_source(engine):
226228 assert retrieved .source is None
227229
228230
231+ def test_create_database_refreshes_existing_views (tmp_path ):
232+ db_uri = f"sqlite:///{ tmp_path / 'test.db' } "
233+ engine = create_database (db_uri )
234+
235+ with engine .connect () as conn :
236+ conn .execute (text ("DROP VIEW target_overview" ))
237+ conn .execute (
238+ text (
239+ """
240+ CREATE VIEW target_overview AS
241+ SELECT
242+ t.target_id,
243+ t.stratum_id,
244+ t.variable,
245+ t.value,
246+ t.period,
247+ t.active
248+ FROM targets t
249+ """
250+ )
251+ )
252+ conn .commit ()
253+
254+ create_or_replace_views (engine )
255+
256+ with engine .connect () as conn :
257+ cursor = conn .execute (text ("SELECT * FROM target_overview LIMIT 0" ))
258+ columns = [desc [0 ] for desc in cursor .cursor .description ]
259+
260+ assert "reform_id" in columns
261+
262+
229263def test_valid_geographic_hierarchy (engine ):
230264 """CD under its correct state should succeed."""
231265 with Session (engine ) as session :
Original file line number Diff line number Diff line change @@ -125,6 +125,25 @@ def test_national_targets_loaded(built_db):
125125 )
126126
127127
128+ def test_jct_mortgage_tax_expenditure_uses_mortgage_specific_variable (built_db ):
129+ """The mortgage JCT target should point at a mortgage-specific variable."""
130+ conn = sqlite3 .connect (str (built_db ))
131+ rows = conn .execute ("""
132+ SELECT DISTINCT t.variable, t.source, t.notes
133+ FROM targets t
134+ WHERE t.variable = 'deductible_mortgage_interest'
135+ """ ).fetchall ()
136+ conn .close ()
137+
138+ assert rows == [
139+ (
140+ "deductible_mortgage_interest" ,
141+ "PolicyEngine" ,
142+ "Mortgage interest deduction tax expenditure | Modeled as repeal-based income tax expenditure target | Source: Joint Committee on Taxation" ,
143+ )
144+ ]
145+
146+
128147def test_state_income_tax_targets (built_db ):
129148 """State income tax targets should cover all income-tax states."""
130149 conn = sqlite3 .connect (str (built_db ))
You can’t perform that action at this time.
0 commit comments