taxcalc 4.6.1__py3-none-any.whl → 4.6.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -12,7 +12,7 @@ import os
12
12
  import json
13
13
  import numpy as np
14
14
  import pytest
15
- import paramtools as pt
15
+ import paramtools
16
16
  from taxcalc.policy import Policy
17
17
 
18
18
 
@@ -45,21 +45,20 @@ def test_incorrect_class_instantiation():
45
45
  Policy(gfactors=[])
46
46
 
47
47
 
48
- def test_correct_class_instantiation():
48
+ def test_incorrect_implement_reform_usage():
49
49
  """
50
- Test correct instantiation of Policy class object.
50
+ Test for incorrect implement_reform usage.
51
51
  """
52
52
  pol = Policy()
53
53
  assert pol
54
- pol.implement_reform({})
55
- with pytest.raises(pt.ValidationError):
54
+ with pytest.raises(paramtools.ValidationError):
56
55
  pol.implement_reform([])
57
- with pytest.raises(pt.ValidationError):
56
+ with pytest.raises(paramtools.ValidationError):
58
57
  pol.implement_reform({2099: {'II_em': 99000}})
59
58
  pol.set_year(2019)
60
- with pytest.raises(pt.ValidationError):
59
+ with pytest.raises(paramtools.ValidationError):
61
60
  pol.implement_reform({2018: {'II_em': 99000}})
62
- with pytest.raises(pt.ValidationError):
61
+ with pytest.raises(paramtools.ValidationError):
63
62
  pol.implement_reform({2020: {'II_em': -1000}})
64
63
 
65
64
 
@@ -142,7 +141,7 @@ REFORM_JSON = """
142
141
  """
143
142
 
144
143
 
145
- # pylint: disable=protected-access,no-member
144
+ # pylint: disable=protected-access
146
145
 
147
146
 
148
147
  @pytest.mark.parametrize("set_year", [False, True])
@@ -156,7 +155,6 @@ def test_read_json_reform_file_and_implement_reform(set_year):
156
155
  pol.set_year(2015)
157
156
  pol.implement_reform(Policy.read_json_reform(REFORM_JSON))
158
157
  syr = pol.start_year
159
- # pylint: disable=protected-access
160
158
  amt_brk1 = pol._AMT_brk1
161
159
  assert amt_brk1[2015 - syr] == 200000
162
160
  assert amt_brk1[2016 - syr] > 200000
@@ -414,7 +412,7 @@ def test_implement_reform_raises_on_no_year():
414
412
  """
415
413
  reform = {'STD_Aged': [1400, 1200, 1400, 1400, 1400]}
416
414
  ppo = Policy()
417
- with pytest.raises(pt.ValidationError):
415
+ with pytest.raises(paramtools.ValidationError):
418
416
  ppo.implement_reform(reform)
419
417
 
420
418
 
@@ -424,7 +422,7 @@ def test_implement_reform_raises_on_early_year():
424
422
  """
425
423
  ppo = Policy()
426
424
  reform = {'STD_Aged': {2010: [1400, 1100, 1100, 1400, 1400]}}
427
- with pytest.raises(pt.ValidationError):
425
+ with pytest.raises(paramtools.ValidationError):
428
426
  ppo.implement_reform(reform)
429
427
 
430
428
 
@@ -811,37 +809,24 @@ def test_get_index_rate():
811
809
  assert pol.wage_growth_rates() == pol._wage_growth_rates
812
810
 
813
811
 
814
- def test_reform_with_bad_ctc_levels():
815
- """
816
- Implement a reform with _ACTC > _CTC_c values.
817
- """
818
- pol = Policy()
819
- child_credit_reform = {
820
- 'CTC_c': {2020: 2200},
821
- 'ACTC_c': {2020: 2500}
822
- }
823
- with pytest.raises(pt.ValidationError):
824
- pol.implement_reform(child_credit_reform)
825
-
826
-
827
812
  def test_reform_with_removed_parameter(monkeypatch):
828
813
  """
829
814
  Try to use removed parameter in a reform.
830
815
  """
831
816
  policy1 = Policy()
832
817
  reform1 = {'FilerCredit_c': {2020: 1000}}
833
- with pytest.raises(pt.ValidationError):
818
+ with pytest.raises(paramtools.ValidationError):
834
819
  policy1.implement_reform(reform1)
835
820
  policy2 = Policy()
836
821
  reform2 = {'FilerCredit_c-indexed': {2020: True}}
837
- with pytest.raises(pt.ValidationError):
822
+ with pytest.raises(paramtools.ValidationError):
838
823
  policy2.implement_reform(reform2)
839
824
 
840
825
  redefined_msg = {"some_redefined": "some_redefined was redefined."}
841
826
  monkeypatch.setattr(Policy, "REDEFINED_PARAMS", redefined_msg)
842
827
 
843
828
  pol = Policy()
844
- with pytest.raises(pt.ValidationError):
829
+ with pytest.raises(paramtools.ValidationError):
845
830
  pol.implement_reform({"some_redefined": "hello world"})
846
831
 
847
832
 
@@ -884,28 +869,28 @@ def test_reform_with_scalar_vector_errors():
884
869
  """
885
870
  policy1 = Policy()
886
871
  reform1 = {'SS_thd85': {2020: 30000}}
887
- with pytest.raises(pt.ValidationError):
872
+ with pytest.raises(paramtools.ValidationError):
888
873
  policy1.implement_reform(reform1)
889
874
 
890
875
  policy2 = Policy()
891
876
  reform2 = {'ID_Medical_frt': {2020: [0.08]}}
892
- with pytest.raises(pt.ValidationError):
877
+ with pytest.raises(paramtools.ValidationError):
893
878
  policy2.implement_reform(reform2)
894
879
 
895
880
  policy3 = Policy()
896
881
  reform3 = {'ID_Medical_frt': [{"year": 2020, "value": [0.08]}]}
897
- with pytest.raises(pt.ValidationError):
882
+ with pytest.raises(paramtools.ValidationError):
898
883
  policy3.adjust(reform3)
899
884
 
900
885
  # Check that error is thrown if there are extra elements in array.
901
886
  policy4 = Policy()
902
887
  ref4 = {"II_brk1": {2020: [9700, 19400, 9700, 13850, 19400, 19400]}}
903
- with pytest.raises(pt.ValidationError):
888
+ with pytest.raises(paramtools.ValidationError):
904
889
  policy4.implement_reform(ref4)
905
890
 
906
891
  policy5 = Policy()
907
892
  ref5 = {"II_rt1": {2029: [.2, .3]}}
908
- with pytest.raises(pt.ValidationError):
893
+ with pytest.raises(paramtools.ValidationError):
909
894
  policy5.implement_reform(ref5)
910
895
 
911
896
 
@@ -1416,10 +1401,7 @@ def test_multiple_cpi_swaps2():
1416
1401
  )
1417
1402
 
1418
1403
 
1419
- # pylint: disable=invalid-name
1420
-
1421
-
1422
- def test_adj_CPI_offset_and_index_status():
1404
+ def test_adj_cpi_offset_and_index_status():
1423
1405
  """
1424
1406
  Test changing parameter_indexing_CPI_offset and another
1425
1407
  parameter simultaneously.
@@ -1491,10 +1473,10 @@ def test_adj_related_parameters_and_index_status():
1491
1473
  )
1492
1474
  assert res.isel[0]["value"] == [445400]
1493
1475
 
1494
- II_brk7 = pol.to_array("II_brk7", year=[2021, 2022])
1495
- II_brk7_single = II_brk7[:, 0]
1476
+ ii_brk7 = pol.to_array("II_brk7", year=[2021, 2022])
1477
+ ii_brk7_single = ii_brk7[:, 0]
1496
1478
  np.testing.assert_equal(
1497
- (II_brk7_single[1] / II_brk7_single[0] - 1).round(4),
1479
+ (ii_brk7_single[1] / ii_brk7_single[0] - 1).round(4),
1498
1480
  pol.inflation_rates(year=2021),
1499
1481
  )
1500
1482
 
@@ -1509,7 +1491,7 @@ def test_indexed_status_parsing():
1509
1491
  pol2.adjust({"EITC_c-indexed": False})
1510
1492
  cmp_policy_objs(pol1, pol2)
1511
1493
 
1512
- with pytest.raises(pt.ValidationError):
1494
+ with pytest.raises(paramtools.ValidationError):
1513
1495
  pol2.adjust({"EITC_c-indexed": 123})
1514
1496
 
1515
1497
 
@@ -1557,3 +1539,133 @@ def test_two_sets_of_tax_brackets():
1557
1539
  emsg += f' PT_brk{bnum} is {pt_val}\n'
1558
1540
  if emsg:
1559
1541
  raise ValueError(emsg)
1542
+
1543
+
1544
+ def test_ext_plus_ctc1_reform(tests_path):
1545
+ """
1546
+ Test ext.json plus ctc1 compound reform relative to ext.json baseline.
1547
+ """
1548
+ # specify baseline policy, bas, as the extend-TCJA reform
1549
+ bas = Policy()
1550
+ filename = os.path.join(tests_path, '..', 'reforms', 'ext.json')
1551
+ with open(filename, 'r', encoding='utf-8') as rfile:
1552
+ ext_text = rfile.read()
1553
+ bas.implement_reform(Policy.read_json_reform(ext_text))
1554
+ assert not bas.parameter_errors
1555
+ # specify reform policy, ref, as extend-TCJA plus liberalization of CTC
1556
+ ref = Policy()
1557
+ ref.implement_reform(Policy.read_json_reform(ext_text))
1558
+ ctc1_reform = {
1559
+ # one possible child-tax-credit revision to the extend-TCJA reform
1560
+ 'CTC_c': {
1561
+ 2026: 2500.00,
1562
+ 2027: 2500.00,
1563
+ 2028: 2500.00,
1564
+ 2029: 2000.00,
1565
+ },
1566
+ 'CTC_c-indexed': {2029: True},
1567
+ }
1568
+ ref.implement_reform(ctc1_reform)
1569
+ assert not ref.parameter_errors
1570
+ # check bas and ref parameter values against expected parameter values
1571
+ exp_ctc_c_bas = {
1572
+ 2025: 2000,
1573
+ 2026: 2000,
1574
+ 2027: 2000,
1575
+ 2028: 2000,
1576
+ 2029: 2000,
1577
+ 2030: 2000,
1578
+ }
1579
+ exp_ctc_c_ref = {
1580
+ 2025: 2000,
1581
+ 2026: 2500,
1582
+ 2027: 2500,
1583
+ 2028: 2500,
1584
+ 2029: 2000,
1585
+ 2030: 2044.80,
1586
+ }
1587
+ exp_actc_c = {
1588
+ 2025: 1700,
1589
+ 2026: 1776.67,
1590
+ 2027: 1819.84,
1591
+ 2028: 1861.88,
1592
+ 2029: 1903.96,
1593
+ 2030: 1946.61,
1594
+ }
1595
+ for year in range(2025, 2031):
1596
+ bas.set_year(year)
1597
+ assert np.allclose([bas.CTC_c], [exp_ctc_c_bas[year]])
1598
+ assert np.allclose([bas.ACTC_c], [exp_actc_c[year]])
1599
+ ref.set_year(year)
1600
+ assert np.allclose([ref.CTC_c], [exp_ctc_c_ref[year]])
1601
+ assert np.allclose([ref.ACTC_c], [exp_actc_c[year]])
1602
+
1603
+
1604
+ def test_ext_plus_ctc2_reform(tests_path):
1605
+ """
1606
+ Test ext.json plus ctc2 compound reform relative to ext.json baseline.
1607
+ """
1608
+ # specify baseline policy, bas, as the extend-TCJA reform
1609
+ bas = Policy()
1610
+ filename = os.path.join(tests_path, '..', 'reforms', 'ext.json')
1611
+ with open(filename, 'r', encoding='utf-8') as rfile:
1612
+ ext_text = rfile.read()
1613
+ bas.implement_reform(Policy.read_json_reform(ext_text))
1614
+ assert not bas.parameter_errors
1615
+ # specify reform policy, ref, as extend-TCJA plus liberalization of CTC
1616
+ ref = Policy()
1617
+ ref.implement_reform(Policy.read_json_reform(ext_text))
1618
+ ctc2_reform = {
1619
+ # one possible child-tax-credit revision to the extend-TCJA reform
1620
+ 'CTC_c': {
1621
+ 2026: 2500.00,
1622
+ 2027: 2500.00,
1623
+ 2028: 2500.00,
1624
+ 2029: 2000.00,
1625
+ },
1626
+ 'CTC_c-indexed': {2029: True},
1627
+ 'ACTC_c': {2029: 1750},
1628
+ 'ACTC_c-indexed': {2029: False},
1629
+ }
1630
+ ref.implement_reform(ctc2_reform)
1631
+ assert not ref.parameter_errors
1632
+ # check bas and ref parameter values against expected parameter values
1633
+ exp_ctc_c_bas = {
1634
+ 2025: 2000,
1635
+ 2026: 2000,
1636
+ 2027: 2000,
1637
+ 2028: 2000,
1638
+ 2029: 2000,
1639
+ 2030: 2000,
1640
+ }
1641
+ exp_ctc_c_ref = {
1642
+ 2025: 2000,
1643
+ 2026: 2500,
1644
+ 2027: 2500,
1645
+ 2028: 2500,
1646
+ 2029: 2000,
1647
+ 2030: 2044.80,
1648
+ }
1649
+ exp_actc_c_bas = {
1650
+ 2025: 1700,
1651
+ 2026: 1776.67,
1652
+ 2027: 1819.84,
1653
+ 2028: 1861.88,
1654
+ 2029: 1903.96,
1655
+ 2030: 1946.61,
1656
+ }
1657
+ exp_actc_c_ref = {
1658
+ 2025: 1700,
1659
+ 2026: 1776.67,
1660
+ 2027: 1819.84,
1661
+ 2028: 1861.88,
1662
+ 2029: 1750,
1663
+ 2030: 1750,
1664
+ }
1665
+ for year in range(2025, 2031):
1666
+ bas.set_year(year)
1667
+ assert np.allclose([bas.CTC_c], [exp_ctc_c_bas[year]])
1668
+ assert np.allclose([bas.ACTC_c], [exp_actc_c_bas[year]])
1669
+ ref.set_year(year)
1670
+ assert np.allclose([ref.CTC_c], [exp_ctc_c_ref[year]])
1671
+ assert np.allclose([ref.ACTC_c], [exp_actc_c_ref[year]])
@@ -338,7 +338,7 @@ def fixture_reforms_dict(tests_path):
338
338
  return json.loads(rjson)
339
339
 
340
340
 
341
- NUM_REFORMS = 64 # when changing this also change num_reforms in conftest.py
341
+ NUM_REFORMS = 63 # when changing this also change num_reforms in conftest.py
342
342
 
343
343
 
344
344
  @pytest.mark.requires_pufcsv
@@ -386,4 +386,4 @@ def test_ext_reform(tests_path):
386
386
  iitax_ext = calc_ext.array('iitax')
387
387
  rdiff = iitax_ext - iitax_end
388
388
  weighted_sum_rdiff = (rdiff * calc_end.array('s006')).sum() * 1.0e-9
389
- assert np.allclose([weighted_sum_rdiff], [-205.769], rtol=0.0, atol=0.01)
389
+ assert np.allclose([weighted_sum_rdiff], [-214.393], rtol=0.0, atol=0.01)
@@ -153,6 +153,24 @@ def fixture_errorreformfile():
153
153
  pass # sometimes we can't remove a generated temporary file
154
154
 
155
155
 
156
+ @pytest.fixture(scope='session', name='ereformfile')
157
+ def fixture_ereformfile():
158
+ """
159
+ Temporary reform file with .json extension.
160
+ """
161
+ contents = '{"II_em": {"2022": 1000},}'
162
+ with tempfile.NamedTemporaryFile(
163
+ suffix='.json', mode='a', delete=False
164
+ ) as rfile:
165
+ rfile.write(contents)
166
+ yield rfile
167
+ if os.path.isfile(rfile.name):
168
+ try:
169
+ os.remove(rfile.name)
170
+ except OSError:
171
+ pass # sometimes we can't remove a generated temporary file
172
+
173
+
156
174
  @pytest.fixture(scope='session', name='errorassumpfile')
157
175
  def fixture_errorassumpfile():
158
176
  """
@@ -249,6 +267,7 @@ def fixture_assumpfile2():
249
267
  'no-dot-json-filename'),
250
268
  ([], [], [], [],),
251
269
  ('no-exist.csv', 'no-exist.json', 'no-exist.json', 'no-exist.json'),
270
+ ('cps.csv', 'ereformfile', 'ereformfile', 'no-exist.json'),
252
271
  ])
253
272
  def test_ctor_errors(input_data, baseline, reform, assump):
254
273
  """
@@ -351,16 +370,19 @@ def test_ctor_init_with_cps_files():
351
370
  """
352
371
  # specify valid tax_year for cps.csv input data
353
372
  txyr = 2020
354
- tcio = TaxCalcIO('cps.csv', txyr, None, None, None)
355
- tcio.init('cps.csv', txyr, None, None, None,
356
- aging_input_data=True,
357
- exact_calculations=False)
358
- assert not tcio.errmsg
359
- assert tcio.tax_year() == txyr
360
- # test advance_to_year method
361
- tcio.silent = False
362
- tcio.advance_to_year(txyr + 1, True)
363
- assert tcio.tax_year() == txyr + 1
373
+ for rid in [0, 99]:
374
+ tcio = TaxCalcIO('cps.csv', txyr, None, None, None, runid=rid)
375
+ tcio.init(
376
+ 'cps.csv', txyr, None, None, None,
377
+ aging_input_data=True,
378
+ exact_calculations=False,
379
+ )
380
+ assert not tcio.errmsg
381
+ assert tcio.tax_year() == txyr
382
+ # test advance_to_year method
383
+ tcio.silent = False
384
+ tcio.advance_to_year(txyr + 1, True)
385
+ assert tcio.tax_year() == txyr + 1
364
386
  # specify invalid tax_year for cps.csv input data
365
387
  txyr = 2013
366
388
  tcio = TaxCalcIO('cps.csv', txyr, None, None, None)
@@ -426,7 +448,7 @@ def test_output_options_min(reformfile1, assumpfile1):
426
448
  aging_input_data=False,
427
449
  exact_calculations=False)
428
450
  assert not tcio.errmsg
429
- dumppath = tcio.output_filepath().replace('.xxx', '.db')
451
+ dumppath = tcio.output_filepath().replace('.xxx', '.dumpdb')
430
452
  # minimal dump output
431
453
  dumpvars = TaxCalcIO.MINIMAL_DUMPVARS
432
454
  try:
@@ -461,7 +483,7 @@ def test_output_options_mtr(reformfile1, assumpfile1):
461
483
  aging_input_data=False,
462
484
  exact_calculations=False)
463
485
  assert not tcio.errmsg
464
- dumppath = tcio.output_filepath().replace('.xxx', '.db')
486
+ dumppath = tcio.output_filepath().replace('.xxx', '.dumpdb')
465
487
  # minimal+mtr_* dump output
466
488
  dumpvars = TaxCalcIO.MINIMAL_DUMPVARS
467
489
  for var in TaxCalcIO.MTR_DUMPVARS:
@@ -503,7 +525,7 @@ def test_write_policy_param_files(reformfile1):
503
525
  assert not tcio.errmsg
504
526
  tcio.write_policy_params_files()
505
527
  outfilepath = tcio.output_filepath()
506
- for ext in ['-params.bas', '-params.ref']:
528
+ for ext in ['-params.baseline', '-params.reform']:
507
529
  filepath = outfilepath.replace('.xxx', ext)
508
530
  if os.path.isfile(filepath):
509
531
  os.remove(filepath)
taxcalc/utils.py CHANGED
@@ -8,6 +8,7 @@ PUBLIC low-level utility functions for Tax-Calculator.
8
8
  # pylint: disable=too-many-lines
9
9
 
10
10
  import os
11
+ import re
11
12
  import math
12
13
  import json
13
14
  import copy
@@ -930,8 +931,8 @@ def mtr_graph_data(vdf, year,
930
931
  ).values[:, 1]
931
932
  # construct DataFrame containing the two mtr?_series
932
933
  lines = pd.DataFrame()
933
- lines['base'] = mtr1_series
934
- lines['reform'] = mtr2_series
934
+ lines['base'] = np.round(mtr1_series, decimals=4)
935
+ lines['reform'] = np.round(mtr2_series, decimals=4)
935
936
  # construct dictionary containing merged data and auto-generated labels
936
937
  data = {}
937
938
  data['lines'] = lines
@@ -1064,8 +1065,8 @@ def atr_graph_data(vdf, year,
1064
1065
  where=avginc_series[included] != 0)
1065
1066
  # construct DataFrame containing the two atr?_series
1066
1067
  lines = pd.DataFrame()
1067
- lines['base'] = atr1_series
1068
- lines['reform'] = atr2_series
1068
+ lines['base'] = np.round(atr1_series, decimals=4)
1069
+ lines['reform'] = np.round(atr2_series, decimals=4)
1069
1070
  # include only percentiles with average income no less than min_avginc
1070
1071
  lines = lines[included]
1071
1072
  # construct dictionary containing plot lines and auto-generated labels
@@ -1236,7 +1237,7 @@ def pch_graph_data(vdf, year, pop_quantiles=False):
1236
1237
  where=avginc_series[included] != 0)
1237
1238
  # construct DataFrame containing the pch_series expressed as percent
1238
1239
  line = pd.DataFrame()
1239
- line['pch'] = pch_series * 100
1240
+ line['pch'] = np.round(pch_series * 100, decimals=2)
1240
1241
  # include only percentiles with average income no less than min_avginc
1241
1242
  line = line[included]
1242
1243
  # construct dictionary containing plot line and auto-generated labels
@@ -1574,25 +1575,45 @@ def bootstrap_se_ci(data, seed, num_samples, statistic, alpha):
1574
1575
  return bsest
1575
1576
 
1576
1577
 
1577
- def json_to_dict(json_text):
1578
+ def json_to_dict(jsontext):
1578
1579
  """
1579
1580
  Convert specified JSON text into an ordered Python dictionary.
1580
1581
 
1581
1582
  Parameters
1582
1583
  ----------
1583
- json_text: string
1584
- JSON text.
1584
+ jsontext: string
1585
+ JSON text that may contain comments, which will be removed
1585
1586
 
1586
1587
  Raises
1587
1588
  ------
1588
1589
  ValueError:
1589
- if json_text contains a JSON syntax error.
1590
+ if jsontext contains a JSON syntax error after comments are removed
1590
1591
 
1591
1592
  Returns
1592
1593
  -------
1593
1594
  dictionary: collections.OrderedDict
1594
- JSON data expressed as an ordered Python dictionary.
1595
+ JSON data expressed as an ordered Python dictionary
1595
1596
  """
1597
+ def remove_comments(string):
1598
+ """
1599
+ Remove single and multiline comments from JSON.
1600
+ Logic follows https://stackoverflow.com/a/18381470/9100772
1601
+ """
1602
+ def _replacer(match):
1603
+ # if the 2nd group (capturing comments) is not None,
1604
+ # it means we have captured a non-quoted (real) comment string.
1605
+ if match.group(2) is not None:
1606
+ return "\n" # preserve line numbers
1607
+ # otherwise, we will return the 1st group
1608
+ return match.group(1) # captured quoted-string
1609
+ # begin main remove_comments function logic
1610
+ pattern = r"(\".*?\"|\'.*?\')|(/\*.*?\*/|//[^\r\n]*$)"
1611
+ # first group captures quoted strings (double or single)
1612
+ # second group captures comments (//single-line or /* multi-line */)
1613
+ regex = re.compile(pattern, re.MULTILINE | re.DOTALL)
1614
+ return regex.sub(_replacer, string)
1615
+ # begin main json_to_dict function logic
1616
+ json_text = remove_comments(jsontext)
1596
1617
  try:
1597
1618
  ordered_dict = json.loads(json_text,
1598
1619
  object_pairs_hook=collections.OrderedDict)
@@ -1610,5 +1631,6 @@ def json_to_dict(json_text):
1610
1631
  linenum += 1
1611
1632
  msg += f'{linenum:04d}{line}\n'
1612
1633
  msg += bline + '\n'
1634
+ msg += 'If still puzzled, try using JSONLint online.\n'
1613
1635
  raise ValueError(msg) from valerr
1614
1636
  return ordered_dict
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: taxcalc
3
- Version: 4.6.1
3
+ Version: 4.6.3
4
4
  Summary: Tax-Calculator
5
5
  Home-page: https://github.com/PSLmodels/Tax-Calculator
6
6
  Download-URL: https://github.com/PSLmodels/Tax-Calculator
@@ -22,7 +22,7 @@ Requires-Dist: numpy>=1.26
22
22
  Requires-Dist: pandas>=2.2
23
23
  Requires-Dist: bokeh>=2.4
24
24
  Requires-Dist: numba
25
- Requires-Dist: paramtools>=0.19.0
25
+ Requires-Dist: paramtools>=0.20.0
26
26
  Dynamic: classifier
27
27
  Dynamic: description
28
28
  Dynamic: description-content-type
@@ -57,3 +57,6 @@ explains the workflow involved in contributing model enhancements.
57
57
 
58
58
  Complete documentation is available
59
59
  [here](https://PSLmodels.github.io/Tax-Calculator/).
60
+ This documentation includes
61
+ [examples](https://taxcalc.pslmodels.org/usage/tcja_after_2025.html)
62
+ of how to analyze different ways of extending TCJA policy beyond 2025.
@@ -1,5 +1,5 @@
1
- taxcalc/__init__.py,sha256=_SNXt6U2NMWDx1hqcUw-N6_SVHp4pydp4-U1VFEPldY,536
2
- taxcalc/calcfunctions.py,sha256=G62sQeW-YHJ2gvqOfidRKPBpufSHzXYIdI2PGcApOuU,148423
1
+ taxcalc/__init__.py,sha256=9Esf49oClu0DBglso6q08J0YbCTnWQRRvM6TpVKX5ZE,536
2
+ taxcalc/calcfunctions.py,sha256=Rt2BN7rI9Hr86jSqGN7-HeqqXGlh1PN0wUGuivwbjos,148442
3
3
  taxcalc/calculator.py,sha256=cCsis9yQSyw4eXvYppk7Z70JEaPH8Kd1AADlIqnJhVw,63930
4
4
  taxcalc/conftest.py,sha256=nO4J7qu1sTHgjqrzhpRMvfMJUrNm6GP_IsSuuDt_MeQ,141
5
5
  taxcalc/consumption.json,sha256=FBgDd72AZnviQRhGz5rPgpGpOmaOzNYfGB9GdTCeKPI,8102
@@ -12,21 +12,21 @@ taxcalc/growdiff.json,sha256=ReBAF6We9ZwTb0uDYQwbedPsQKdm6KSOERiddEYZbm0,15037
12
12
  taxcalc/growdiff.py,sha256=Q3St-KPIUN2I_l1S0jwN0yr8O4LuzkNIU-_qbXTkrZw,2977
13
13
  taxcalc/growfactors.csv,sha256=URIGSKApCY4McvdILkCaIm8EhCGEME2Du-ef5Q9c0uE,5134
14
14
  taxcalc/growfactors.py,sha256=dW71yYKhFDbFtGpBT-kZBqY4MV7IswKcNI3_c-X_Nfg,6525
15
- taxcalc/parameters.py,sha256=pxW53fOJkW7yM7XxN04RDNs-f7CwKOjE4vMmMvPtZ8E,33121
16
- taxcalc/policy.py,sha256=4bY3beSYhLKk_X4CTgG7LGnVnILM0D4Invt7uCp8dlA,6725
17
- taxcalc/policy_current_law.json,sha256=enemNPLg0ZlwNQVVK51XJru_YzDzPnV7ClNhdJHlhJQ,689915
15
+ taxcalc/parameters.py,sha256=VmezOOynj1W7hexnDgCzlyffIxHpFK6eSd6zNzn3aAk,36161
16
+ taxcalc/policy.py,sha256=FpzxNSAYmcu6ScWZwxta3reOSQL9aQyRhAqv-bf28_E,7581
17
+ taxcalc/policy_current_law.json,sha256=4NVEbt3Zv55s_i4GksIvKxSMrrWiPs2I74t1LVMcCE0,689913
18
18
  taxcalc/puf_ratios.csv,sha256=USMM79UEX8PnSKY_LYLxvACER_9NHyj4ipNEk2iyykQ,3580
19
19
  taxcalc/puf_weights.csv.gz,sha256=35iZhzFO0dHUI2zf4_liyk60E-3Sgr_AbxszGxw7LfM,13522484
20
20
  taxcalc/records.py,sha256=K5QgP6Pm9PtEVDVzM7tpHYPu554Wio0KnrU7YTTBKgQ,18264
21
21
  taxcalc/records_variables.json,sha256=_YKJiZQ1czp0VH9bkr5ZXmp9Mm1roHoHrt2XnLXAtfw,42975
22
- taxcalc/taxcalcio.py,sha256=1xZ17wZ0yqZeDDa5glEQpCG6xvXJ4wGxbUQPkmTLTD0,34752
23
- taxcalc/utils.py,sha256=noHnQ-tw0AXhEH-OgdTUiPedH8luVOJ5NdfpKI3_obw,62401
22
+ taxcalc/taxcalcio.py,sha256=_ylnC-dZUpDFn79F8pjkZEq-wJhPCQA7Ig9SRLyhrUA,37691
23
+ taxcalc/utils.py,sha256=Wsvni2UP7WgnByN4bRIiLGgamDFwfQoexiy420o6ewY,63666
24
24
  taxcalc/utilsprvt.py,sha256=iIyWp9-N3_XWjQj2jV2CWnJy7vrNlKB2_vIMwYjgbWY,1323
25
25
  taxcalc/assumptions/ASSUMPTIONS.md,sha256=cFQqWn1nScaladVaQ7xNm1jDY8CsGdLmqZEzUZeRrb8,1917
26
26
  taxcalc/assumptions/README.md,sha256=Ww55r2zH1neoRSl_MawrPmX-ugaztIZ7_ALrquuatdQ,809
27
27
  taxcalc/assumptions/economic_assumptions_template.json,sha256=utMk38GwSQFrkOAtRrDVhMQLpfaZH3JmtTznKX7IouM,2610
28
28
  taxcalc/cli/__init__.py,sha256=cyZ0tdx41j_vV_B6GAkqJmNKKG-B0wUC0ThC75lJlk4,104
29
- taxcalc/cli/tc.py,sha256=StZo-46v1c3ozP-64wQWz0uyHOEVqZPAzgTr1JuoFjU,16614
29
+ taxcalc/cli/tc.py,sha256=hGkP-XHkvx0MoFdHf-BjUnKqAxQBRtk8Vv4uqtIGuRY,18760
30
30
  taxcalc/reforms/2017_law.json,sha256=u-xaPSvt5ubfZw1Nb-jNhTNcOPBUJeAX2kJVoEyMgC4,5860
31
31
  taxcalc/reforms/2017_law.out.csv,sha256=nnNKXqY2kof8HC1nnU8srPsvNNepi6ISXQ9OJpQnT7M,473
32
32
  taxcalc/reforms/ARPA.json,sha256=1H9LuJ_QitXRO9e8R3PWizajJgdioIzbGFdvdlt9FVg,3119
@@ -40,7 +40,7 @@ taxcalc/reforms/ConsolidatedAppropriationsAct2021.out.csv,sha256=qSUdI0LoQFGG6h2
40
40
  taxcalc/reforms/Larson2019.json,sha256=bpfcrtwJO2tNKAG4ITXedCUggbkxXNuwxyrZ456KA-U,1662
41
41
  taxcalc/reforms/Larson2019.out.csv,sha256=s9kVoVYOrznFx4bGiDewyHWRKf7-wgXqpMIMTyxC1zA,475
42
42
  taxcalc/reforms/README.md,sha256=0Ua4RBUnLKcEwxHqncRFDg7QMNq1oblXVNeyYRYfae4,1193
43
- taxcalc/reforms/REFORMS.md,sha256=BTXM9vSz0p0Mi9QHdDrngbdQfIbdYPg9u8UE2PtErvk,3658
43
+ taxcalc/reforms/REFORMS.md,sha256=ewozCNudZfuL89FABQHOSxVn4DJ72hAQ2ghjE3s9kN4,3604
44
44
  taxcalc/reforms/Renacci.json,sha256=U6rmbe1-IANG_H69xET5G8-v76ErbbHcm1JdRzAO8y4,2437
45
45
  taxcalc/reforms/Renacci.out.csv,sha256=dBrDH-Sc5EYvsYzotJZShRxd1EbhdI3enOUqaAsAyuI,472
46
46
  taxcalc/reforms/SandersDeFazio.json,sha256=BMSfl96ERD4SGd_PDMQkiDV5s4iD7Mh1BjS7uKxVD18,710
@@ -54,7 +54,7 @@ taxcalc/reforms/Trump2017.json,sha256=DZjCJQZYe98Skyss7z_Jhj8HJld_FPZeQGxwzGgQIn
54
54
  taxcalc/reforms/Trump2017.out.csv,sha256=By1quzZONFLQGK5E76mbNNFuORZ8aCGHpD1BR5iwTS8,474
55
55
  taxcalc/reforms/cases.csv,sha256=JQ0LSnNeyl6xSgW5mimGUJMr7xwCWTOpiOpfwx2ETsg,570
56
56
  taxcalc/reforms/clp.out.csv,sha256=qSUdI0LoQFGG6h24eT-249pLEqmxmt7TvLrv1HX_y3Y,475
57
- taxcalc/reforms/ext.json,sha256=578ckWd4bTbH_XnTR-smMKtE7Auu9seGn7de_hsGIos,3130
57
+ taxcalc/reforms/ext.json,sha256=-IfEpGAAIOiQMp-fW1F1W5OMiuUgdXAnr0mUa364Dok,3058
58
58
  taxcalc/reforms/growfactors_ext.csv,sha256=E0szWXtgV5jcpiyvREOz1yXw_poPIBC77bBQI1rlFxM,17733
59
59
  taxcalc/reforms/ptaxes0.json,sha256=QkvqCVkI23sF7FvTHqaUYNpEJYuHNChbKwH0mH7Otp4,1718
60
60
  taxcalc/reforms/ptaxes0.out.csv,sha256=DKGsyNWqo-ABUnjFjEGMpqqhmT2WDRGuU6sKTgH_obc,476
@@ -75,15 +75,15 @@ taxcalc/reforms/archive/TCJA_Senate_120117.json,sha256=hruGq8bVtJEMmSsOIuTcWiYON
75
75
  taxcalc/tests/benefits_expect.csv,sha256=CFpMpg8a-5iNVSRnmCnl9dncwXx6eGn-KSnTJ2GqmS4,4833
76
76
  taxcalc/tests/cmpi_cps_expect.txt,sha256=NCyG3XhgnV8qJe9TaF9l-9yUuwNfANNDvFn1HcSfZ1c,6262
77
77
  taxcalc/tests/cmpi_puf_expect.txt,sha256=dtHBPDY23qttxjQsPpxhLYoUId1tnPZ4uNHx49NlZ0s,6264
78
- taxcalc/tests/conftest.py,sha256=xBoh0jQwe2_jbjLhuHHwtSmVPBSr2UkbJ7rOmc9FDxk,5164
78
+ taxcalc/tests/conftest.py,sha256=ySPrNaC3m8a7Jp4SaAkq2P4iNTVLCj7b8lqIfpTMxYY,5164
79
79
  taxcalc/tests/cpscsv_agg_expect.csv,sha256=Do3gRVVKUCZtQ2Ooy5jn6gMS9_WbclJ5FhSSHR6gwX8,2089
80
80
  taxcalc/tests/puf_var_correl_coeffs_2016.csv,sha256=2VtWUcTaE6c5cmmEDylv9XKVONLT6GZ10gozELxk-2g,57314
81
81
  taxcalc/tests/puf_var_wght_means_by_year.csv,sha256=nou_pIKICyXmCfyj_UziNXp1EB4BQU7Qa-ZvqlE1WqM,20049
82
82
  taxcalc/tests/pufcsv_agg_expect.csv,sha256=h0r6MtsFEBa1u5zwpRT4fDx2T__ZAkdx4oeLxidQI4s,2117
83
83
  taxcalc/tests/pufcsv_mtr_expect.txt,sha256=xGsUfafzsZ04fFQw162ys-1Mf1CDC_PQ0QZNigS07VY,4265
84
- taxcalc/tests/reforms.json,sha256=vGJrvfKJ7h5iAWF-vV9NmY8Z9HP_iereiYiYNcfhBMo,19212
85
- taxcalc/tests/reforms_expect.csv,sha256=6m0bSH8S6ReMYdHoQC9iWYuJAof5sZ0OONVBi7zX8JE,1464
86
- taxcalc/tests/test_4package.py,sha256=I9i5rWFsg-VCtTLmUWIi9dnusieTZeodrgH8ba_Fbng,3681
84
+ taxcalc/tests/reforms.json,sha256=udnp9vPmTQpQQ39LaYqGUWJrwEZnYGPiEdyVkWklp3c,18835
85
+ taxcalc/tests/reforms_expect.csv,sha256=FlyccVCTgnRSL8CNdNT5-m6_Vx88J935OEjA4PzTqxg,1440
86
+ taxcalc/tests/test_4package.py,sha256=1qhmDS3bdfNHNgz4pggaE6LduT3KKUtOsdtqP3QSIYQ,3601
87
87
  taxcalc/tests/test_benefits.py,sha256=oaui5mO0TuW8Ht-uxvUCBL5zM3iTENq3Whyf_gEpY1U,3392
88
88
  taxcalc/tests/test_calcfunctions.py,sha256=QtMgQg_WpCU8PZM3Hs8Pml4q6LnlLWV_blCzbpGN2sw,31939
89
89
  taxcalc/tests/test_calculator.py,sha256=lcnBli5giNFxqgCLW-MF4J_wsV3gSFqCjzJdCJkihek,36085
@@ -95,14 +95,14 @@ taxcalc/tests/test_data.py,sha256=Zwuf23WeaF0N53X0eo3MlnkO2Pn4qqgGNUZPpD8FETc,44
95
95
  taxcalc/tests/test_decorators.py,sha256=F31pt1S7jIgkgV62xMC-poWRzG7fzYVOJes9tOoCF40,10232
96
96
  taxcalc/tests/test_growdiff.py,sha256=vXZTgPJTUi25mZrfmTPErytSC69Bs_36ydrQmWxgm9g,3420
97
97
  taxcalc/tests/test_growfactors.py,sha256=L-DQMR2fh_rOQa3Lx1CDVnB2Q73zXUfTYYVunt0heto,2796
98
- taxcalc/tests/test_parameters.py,sha256=aOUC2bHZqzaolHT2GDV52jEhsNcyYLxE9igTrJ4horI,20341
99
- taxcalc/tests/test_policy.py,sha256=hJrFqqptMoUWk3abIJ2sdADQtCqvGaUeW5as1aNwhR8,52916
98
+ taxcalc/tests/test_parameters.py,sha256=uVr7C_uKDJ5guOqYOa_yhtCxGAVM5RSSxyIZhINotoA,20000
99
+ taxcalc/tests/test_policy.py,sha256=dTrdJin2G2SKMShb1aOM5S7vDtQ6uxM3BxiQURfs54k,56540
100
100
  taxcalc/tests/test_puf_var_stats.py,sha256=TG-sQtOkR6cBOw0am7MUsMSwjPxVdkvt0Xov342oii8,7786
101
101
  taxcalc/tests/test_pufcsv.py,sha256=kQPwpMcLNPwQDiO-23xvvZggtHYvRz-UYEDn6JjNfbw,16352
102
102
  taxcalc/tests/test_records.py,sha256=ncswnbCY7vZgJ_h6xwql4oFw-jZG2gWOMWvEJC2_jdc,8827
103
- taxcalc/tests/test_reforms.py,sha256=djVxMOE2RytmDDYvzS55AnThRRBcVc_calPbfHuvQ-k,16033
103
+ taxcalc/tests/test_reforms.py,sha256=3vDRnkQrQaRVl5qXEtCxz-nM_y-K2T6e2O-ilx0nZ6o,16033
104
104
  taxcalc/tests/test_responses.py,sha256=2CkVVdaDNCSALMoUcGgweRlS2tfsK3kXogHtDkZMqJU,1663
105
- taxcalc/tests/test_taxcalcio.py,sha256=PV7hCntwp_1LHQYlft7WelbzKSoi5aWzUZqhJAcC5AE,23135
105
+ taxcalc/tests/test_taxcalcio.py,sha256=4WUqtC9OsTczZqsa5jTaXfOQ5YNJRTotg5I6l9859KA,23821
106
106
  taxcalc/tests/test_utils.py,sha256=aUHVNxfSMdyyLAz3w98KLQa5D872rZxXqKbPkIqwLLA,29403
107
107
  taxcalc/validation/CSV_INPUT_VARS.md,sha256=MqlZZGt_a1n8JAU-nY5MjnTmjz1pMOuhtpVYIGUgl38,1433
108
108
  taxcalc/validation/CSV_OUTPUT_VARS.md,sha256=wr8oyCJDXcxl4Lu0H_wMofUQYhEIyHDif6vkbas1FGE,3000
@@ -131,9 +131,9 @@ taxcalc/validation/taxsim35/expected_differences/b21-taxdiffs-expect.csv,sha256=
131
131
  taxcalc/validation/taxsim35/expected_differences/c17-taxdiffs-expect.csv,sha256=YhgojbLowH3yujdYu7SGkdvBZmTgpugu4wYc1Be069M,1125
132
132
  taxcalc/validation/taxsim35/expected_differences/c18-taxdiffs-expect.csv,sha256=g9J4BPbTySV-h-RcLvReJq9v1jscgiRSSZzi0taEA-k,1225
133
133
  taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv,sha256=Ceh15N_Xr3L7cpYjzGa-8NLCV3obc8PNHEhE5ZxSPhI,1238
134
- taxcalc-4.6.1.dist-info/licenses/LICENSE,sha256=m5epLdB-_NXiY7NsEDgcHP4jDtJ4vOlRf5S3Jb-jraY,1299
135
- taxcalc-4.6.1.dist-info/METADATA,sha256=wvnDftJBQ7SKgJAF-hCYRKf_RJX3RNSPj2LLe-nL59s,3509
136
- taxcalc-4.6.1.dist-info/WHEEL,sha256=DnLRTWE75wApRYVsjgc6wsVswC54sMSJhAEd4xhDpBk,91
137
- taxcalc-4.6.1.dist-info/entry_points.txt,sha256=a3ZE1piRv683p27fOLdWZvVJXESkoslTOp5iXV7uVco,50
138
- taxcalc-4.6.1.dist-info/top_level.txt,sha256=Wh8wTDHkA_cm4dn8IoUCviDyGgVQqwEQKPJnl8z6d4c,8
139
- taxcalc-4.6.1.dist-info/RECORD,,
134
+ taxcalc-4.6.3.dist-info/licenses/LICENSE,sha256=m5epLdB-_NXiY7NsEDgcHP4jDtJ4vOlRf5S3Jb-jraY,1299
135
+ taxcalc-4.6.3.dist-info/METADATA,sha256=blEI-Z0ZGiWJHdI9xf4Hlw7h8PNNq37NChbPQr6PWcY,3677
136
+ taxcalc-4.6.3.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
137
+ taxcalc-4.6.3.dist-info/entry_points.txt,sha256=a3ZE1piRv683p27fOLdWZvVJXESkoslTOp5iXV7uVco,50
138
+ taxcalc-4.6.3.dist-info/top_level.txt,sha256=Wh8wTDHkA_cm4dn8IoUCviDyGgVQqwEQKPJnl8z6d4c,8
139
+ taxcalc-4.6.3.dist-info/RECORD,,
@@ -1,5 +1,5 @@
1
1
  Wheel-Version: 1.0
2
- Generator: setuptools (80.4.0)
2
+ Generator: setuptools (80.9.0)
3
3
  Root-Is-Purelib: true
4
4
  Tag: py3-none-any
5
5