taxcalc 5.1.0__py3-none-any.whl → 5.3.0__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.
Files changed (44) hide show
  1. taxcalc/__init__.py +3 -3
  2. taxcalc/calcfunctions.py +21 -16
  3. taxcalc/calculator.py +3 -3
  4. taxcalc/cli/tc.py +15 -11
  5. taxcalc/data.py +1 -1
  6. taxcalc/decorators.py +9 -8
  7. taxcalc/growfactors.py +2 -1
  8. taxcalc/policy.py +13 -5
  9. taxcalc/policy_current_law.json +1191 -1395
  10. taxcalc/puf_ratios.csv +24 -24
  11. taxcalc/puf_weights.csv.gz +0 -0
  12. taxcalc/reforms/2017_law.json +2 -0
  13. taxcalc/reforms/ARPA.out.csv +9 -9
  14. taxcalc/taxcalcio.py +41 -26
  15. taxcalc/tests/conftest.py +1 -1
  16. taxcalc/tests/cpscsv_agg_expect.csv +26 -26
  17. taxcalc/tests/puf_var_correl_coeffs_2016.csv +24 -24
  18. taxcalc/tests/puf_var_wght_means_by_year.csv +80 -80
  19. taxcalc/tests/pufcsv_agg_expect.csv +26 -26
  20. taxcalc/tests/pufcsv_mtr_expect.txt +21 -21
  21. taxcalc/tests/reforms.json +3 -1
  22. taxcalc/tests/reforms_expect.csv +48 -48
  23. taxcalc/tests/test_4package.py +8 -9
  24. taxcalc/tests/test_calculator.py +152 -151
  25. taxcalc/tests/test_compare.py +2 -2
  26. taxcalc/tests/test_consumption.py +2 -2
  27. taxcalc/tests/test_cpscsv.py +4 -3
  28. taxcalc/tests/test_decorators.py +57 -52
  29. taxcalc/tests/test_growdiff.py +2 -2
  30. taxcalc/tests/test_parameters.py +59 -53
  31. taxcalc/tests/test_policy.py +229 -251
  32. taxcalc/tests/test_puf_var_stats.py +2 -2
  33. taxcalc/tests/test_pufcsv.py +5 -4
  34. taxcalc/tests/test_records.py +5 -1
  35. taxcalc/tests/test_reforms.py +101 -99
  36. taxcalc/tests/test_taxcalcio.py +10 -4
  37. taxcalc/utils.py +3 -3
  38. {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/METADATA +3 -6
  39. {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/RECORD +43 -44
  40. taxcalc/reforms/clp.out.csv +0 -10
  41. {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/WHEEL +0 -0
  42. {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/entry_points.txt +0 -0
  43. {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/licenses/LICENSE +0 -0
  44. {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/top_level.txt +0 -0
@@ -26,7 +26,7 @@ def test_make_calculator(cps_subsample):
26
26
  assert pol.current_year == start_year
27
27
  rec = Records.cps_constructor(data=cps_subsample)
28
28
  consump = Consumption()
29
- consump.update_consumption({'MPC_e20400': {sim_year: 0.05}})
29
+ consump.update_consumption({"MPC_e20400": {sim_year: 0.05}})
30
30
  assert consump.current_year == start_year
31
31
  calc = Calculator(policy=pol, records=rec,
32
32
  consumption=consump, verbose=True)
@@ -61,10 +61,10 @@ def test_make_calculator_with_policy_reform(cps_subsample):
61
61
  # create a Policy object and apply a policy reform
62
62
  pol = Policy()
63
63
  reform = {
64
- 'II_em': {2013: 4000},
65
- 'II_em-indexed': {2013: False},
66
- 'STD_Aged': {2013: [1600, 1300, 1300, 1600, 1600]},
67
- 'STD_Aged-indexed': {2013: False}
64
+ "II_em": {2013: 4000},
65
+ "II_em-indexed": {2013: False},
66
+ "STD_Aged": {2013: [1600, 1300, 1300, 1600, 1600]},
67
+ "STD_Aged-indexed": {2013: False}
68
68
  }
69
69
  pol.implement_reform(reform)
70
70
  # create a Calculator object using this policy reform
@@ -72,14 +72,14 @@ def test_make_calculator_with_policy_reform(cps_subsample):
72
72
  assert calc.reform_errors == {}
73
73
  # check that Policy object embedded in Calculator object is correct
74
74
  assert calc.current_year == year
75
- assert calc.policy_param('II_em') == 4000
76
- assert np.allclose(calc.policy_param('_II_em'),
75
+ assert calc.policy_param("II_em") == 4000
76
+ assert np.allclose(calc.policy_param("_II_em"),
77
77
  np.array([4000] * pol.num_years))
78
78
  exp_STD_Aged = [[1600, 1300, 1300,
79
79
  1600, 1600]] * pol.num_years
80
- assert np.allclose(calc.policy_param('_STD_Aged'),
80
+ assert np.allclose(calc.policy_param("_STD_Aged"),
81
81
  np.array(exp_STD_Aged))
82
- assert np.allclose(calc.policy_param('STD_Aged'),
82
+ assert np.allclose(calc.policy_param("STD_Aged"),
83
83
  np.array([1600, 1300, 1300, 1600, 1600]))
84
84
 
85
85
 
@@ -92,23 +92,23 @@ def test_make_calculator_with_multiyear_reform(cps_subsample):
92
92
  # create a Policy object and apply a policy reform
93
93
  pol = Policy()
94
94
  reform = {
95
- 'II_em': {2015: 5000, 2016: 6000},
96
- 'II_em-indexed': {2015: False},
97
- 'STD_Aged': {2016: [1600, 1300, 1600, 1300, 1600]}
95
+ "II_em": {2015: 5000, 2016: 6000},
96
+ "II_em-indexed": {2015: False},
97
+ "STD_Aged": {2016: [1600, 1300, 1600, 1300, 1600]}
98
98
  }
99
99
  pol.implement_reform(reform)
100
100
  # create a Calculator object using this policy-reform
101
101
  calc = Calculator(policy=pol, records=rec)
102
102
  # check that Policy object embedded in Calculator object is correct
103
103
  assert calc.current_year == year
104
- assert calc.policy_param('II_em') == 3950
104
+ assert calc.policy_param("II_em") == 3950
105
105
  exp_II_em = [3900, 3950, 5000] + [6000] * (pol.num_years - 3)
106
- assert np.allclose(calc.policy_param('_II_em'),
106
+ assert np.allclose(calc.policy_param("_II_em"),
107
107
  np.array(exp_II_em))
108
108
  calc.increment_year()
109
109
  calc.increment_year()
110
110
  assert calc.current_year == 2016
111
- assert np.allclose(calc.policy_param('STD_Aged'),
111
+ assert np.allclose(calc.policy_param("STD_Aged"),
112
112
  np.array([1600, 1300, 1600, 1300, 1600]))
113
113
 
114
114
 
@@ -141,44 +141,44 @@ def test_calculator_mtr(cps_subsample):
141
141
  rec = Records.cps_constructor(data=cps_subsample)
142
142
  calcx = Calculator(policy=Policy(), records=rec)
143
143
  calcx.calc_all()
144
- combinedx = calcx.array('combined')
145
- c00100x = calcx.array('c00100')
144
+ combinedx = calcx.array("combined")
145
+ c00100x = calcx.array("c00100")
146
146
  calc = Calculator(policy=Policy(), records=rec)
147
- recs_pre_e00200p = copy.deepcopy(calc.array('e00200p'))
148
- (mtr_ptx, mtr_itx, mtr_cmb) = calc.mtr(variable_str='e00200p',
147
+ recs_pre_e00200p = copy.deepcopy(calc.array("e00200p"))
148
+ (mtr_ptx, mtr_itx, mtr_cmb) = calc.mtr(variable_str="e00200p",
149
149
  zero_out_calculated_vars=True)
150
- recs_post_e00200p = calc.array('e00200p')
150
+ recs_post_e00200p = calc.array("e00200p")
151
151
  assert np.allclose(recs_post_e00200p, recs_pre_e00200p)
152
- assert np.allclose(calc.array('combined'), combinedx)
153
- assert np.allclose(calc.array('c00100'), c00100x)
152
+ assert np.allclose(calc.array("combined"), combinedx)
153
+ assert np.allclose(calc.array("c00100"), c00100x)
154
154
  assert np.array_equal(mtr_cmb, mtr_ptx) is False
155
155
  assert np.array_equal(mtr_ptx, mtr_itx) is False
156
156
  with pytest.raises(ValueError):
157
- calc.mtr(variable_str='bad_income_type')
158
- (_, _, mtr_combined) = calc.mtr(variable_str='e00200s',
157
+ calc.mtr(variable_str="bad_income_type")
158
+ (_, _, mtr_combined) = calc.mtr(variable_str="e00200s",
159
159
  calc_all_already_called=True)
160
160
  assert isinstance(mtr_combined, np.ndarray)
161
- (_, _, mtr_combined) = calc.mtr(variable_str='e00650',
161
+ (_, _, mtr_combined) = calc.mtr(variable_str="e00650",
162
162
  negative_finite_diff=True,
163
163
  calc_all_already_called=True)
164
164
  assert isinstance(mtr_combined, np.ndarray)
165
- (_, _, mtr_combined) = calc.mtr(variable_str='e00900p',
165
+ (_, _, mtr_combined) = calc.mtr(variable_str="e00900p",
166
166
  calc_all_already_called=True)
167
167
  assert isinstance(mtr_combined, np.ndarray)
168
- (_, _, mtr_combined) = calc.mtr(variable_str='e01700',
168
+ (_, _, mtr_combined) = calc.mtr(variable_str="e01700",
169
169
  calc_all_already_called=True)
170
170
  assert isinstance(mtr_combined, np.ndarray)
171
- (_, _, mtr_combined) = calc.mtr(variable_str='e26270',
171
+ (_, _, mtr_combined) = calc.mtr(variable_str="e26270",
172
172
  calc_all_already_called=True)
173
173
  assert isinstance(mtr_combined, np.ndarray)
174
- (_, _, mtr_combined) = calc.mtr(variable_str='k1bx14p',
174
+ (_, _, mtr_combined) = calc.mtr(variable_str="k1bx14p",
175
175
  calc_all_already_called=True)
176
176
  assert isinstance(mtr_combined, np.ndarray)
177
- (_, _, mtr_combined) = calc.mtr(variable_str='e00200p',
177
+ (_, _, mtr_combined) = calc.mtr(variable_str="e00200p",
178
178
  calc_all_already_called=True)
179
179
  assert np.allclose(mtr_combined, mtr_cmb)
180
- assert np.allclose(calc.array('combined'), combinedx)
181
- assert np.allclose(calc.array('c00100'), c00100x)
180
+ assert np.allclose(calc.array("combined"), combinedx)
181
+ assert np.allclose(calc.array("c00100"), c00100x)
182
182
 
183
183
 
184
184
  def test_make_calculator_increment_years_first(cps_subsample):
@@ -190,10 +190,10 @@ def test_make_calculator_increment_years_first(cps_subsample):
190
190
  pol = Policy()
191
191
  std5 = 2000
192
192
  reform = {
193
- 'STD_Aged': {2015: [std5, std5, std5, std5, std5]},
194
- 'II_em': {2015: 5000,
193
+ "STD_Aged": {2015: [std5, std5, std5, std5, std5]},
194
+ "II_em": {2015: 5000,
195
195
  2016: 6000},
196
- 'II_em-indexed': {2016: False}
196
+ "II_em-indexed": {2016: False}
197
197
  }
198
198
  pol.implement_reform(reform)
199
199
  # create Calculator object with Policy object as modified by reform
@@ -211,10 +211,10 @@ def test_make_calculator_increment_years_first(cps_subsample):
211
211
  [std5, std5, std5, std5, std5],
212
212
  [std6, std6, std6, std6, std6],
213
213
  [std7, std7, std7, std7, std7]])
214
- act_STD_Aged = calc.policy_param('_STD_Aged')
214
+ act_STD_Aged = calc.policy_param("_STD_Aged")
215
215
  assert np.allclose(act_STD_Aged[:5], exp_STD_Aged)
216
216
  exp_II_em = np.array([3900, 3950, 5000, 6000, 6000])
217
- act_II_em = calc.policy_param('_II_em')
217
+ act_II_em = calc.policy_param("_II_em")
218
218
  assert np.allclose(act_II_em[:5], exp_II_em)
219
219
 
220
220
 
@@ -227,21 +227,21 @@ def test_ID_StateLocal_HC_vs_CRT(cps_subsample):
227
227
  rec = Records.cps_constructor(data=cps_subsample)
228
228
  # specify state/local complete haircut reform policy and Calculator object
229
229
  hc_policy = Policy()
230
- hc_reform = {'ID_StateLocalTax_hc': {2013: 1.0}}
230
+ hc_reform = {"ID_StateLocalTax_hc": {2013: 1.0}}
231
231
  hc_policy.implement_reform(hc_reform)
232
232
  hc_calc = Calculator(policy=hc_policy, records=rec)
233
233
  hc_calc.calc_all()
234
234
  # specify AGI cap reform policy and Calculator object
235
235
  crt_policy = Policy()
236
- crt_reform = {'ID_StateLocalTax_crt': {2013: 0.0}}
236
+ crt_reform = {"ID_StateLocalTax_crt": {2013: 0.0}}
237
237
  crt_policy.implement_reform(crt_reform)
238
238
  crt_calc = Calculator(policy=crt_policy, records=rec)
239
239
  crt_calc.calc_all()
240
240
  # compare calculated tax results generated by the two reforms
241
- assert np.allclose(hc_calc.array('payrolltax'),
242
- crt_calc.array('payrolltax'))
243
- assert np.allclose(hc_calc.array('iitax'),
244
- crt_calc.array('iitax'))
241
+ assert np.allclose(hc_calc.array("payrolltax"),
242
+ crt_calc.array("payrolltax"))
243
+ assert np.allclose(hc_calc.array("iitax"),
244
+ crt_calc.array("iitax"))
245
245
 
246
246
 
247
247
  def test_ID_RealEstate_HC_vs_CRT(cps_subsample):
@@ -253,31 +253,31 @@ def test_ID_RealEstate_HC_vs_CRT(cps_subsample):
253
253
  rec = Records.cps_constructor(data=cps_subsample)
254
254
  # specify real estate complete haircut reform policy and Calculator object
255
255
  hc_policy = Policy()
256
- hc_reform = {'ID_RealEstate_hc': {2013: 1.0}}
256
+ hc_reform = {"ID_RealEstate_hc": {2013: 1.0}}
257
257
  hc_policy.implement_reform(hc_reform)
258
258
  hc_calc = Calculator(policy=hc_policy, records=rec)
259
259
  hc_calc.calc_all()
260
260
  # specify AGI cap reform policy and Calculator object
261
261
  crt_policy = Policy()
262
- crt_reform = {'ID_RealEstate_crt': {2013: 0.0}}
262
+ crt_reform = {"ID_RealEstate_crt": {2013: 0.0}}
263
263
  crt_policy.implement_reform(crt_reform)
264
264
  crt_calc = Calculator(policy=crt_policy, records=rec)
265
265
  crt_calc.calc_all()
266
266
  # compare calculated tax results generated by the two reforms
267
- assert np.allclose(hc_calc.array('payrolltax'),
268
- crt_calc.array('payrolltax'))
269
- assert np.allclose(hc_calc.array('iitax'),
270
- crt_calc.array('iitax'))
267
+ assert np.allclose(hc_calc.array("payrolltax"),
268
+ crt_calc.array("payrolltax"))
269
+ assert np.allclose(hc_calc.array("iitax"),
270
+ crt_calc.array("iitax"))
271
271
 
272
272
 
273
273
  RAWINPUT_FUNITS = 4
274
274
  RAWINPUT_YEAR = 2015
275
275
  RAWINPUT_CONTENTS = (
276
- 'RECID,MARS,unknown,e00300\n'
277
- ' 1, 2, 9, 0\n'
278
- ' 2, 1, 9, 0\n'
279
- ' 3, 4, 9, 0\n'
280
- ' 4, 3, 9, 0\n'
276
+ "RECID,MARS,unknown,e00300\n"
277
+ " 1, 2, 9, 0\n"
278
+ " 2, 1, 9, 0\n"
279
+ " 3, 4, 9, 0\n"
280
+ " 4, 3, 9, 0\n"
281
281
  )
282
282
 
283
283
 
@@ -297,36 +297,36 @@ def test_calculator_using_nonstd_input():
297
297
  sync_years=False) # keeps raw data unchanged
298
298
  assert calc.current_year == RAWINPUT_YEAR
299
299
  calc.calc_all()
300
- assert calc.weighted_total('e00200') == 0
300
+ assert calc.weighted_total("e00200") == 0
301
301
  assert calc.total_weight() == 0
302
- varlist = ['RECID', 'MARS']
302
+ varlist = ["RECID", "MARS"]
303
303
  dframe = calc.dataframe(varlist)
304
304
  assert isinstance(dframe, pd.DataFrame)
305
305
  assert dframe.shape == (RAWINPUT_FUNITS, len(varlist))
306
- mars = calc.array('MARS')
306
+ mars = calc.array("MARS")
307
307
  assert isinstance(mars, np.ndarray)
308
308
  assert mars.shape == (RAWINPUT_FUNITS,)
309
309
  exp_iitax = np.zeros((nonstd.array_length,))
310
- assert np.allclose(calc.array('iitax'), exp_iitax)
310
+ assert np.allclose(calc.array("iitax"), exp_iitax)
311
311
  mtr_ptax, _, _ = calc.mtr(wrt_full_compensation=False)
312
312
  exp_mtr_ptax = np.zeros((nonstd.array_length,))
313
313
  exp_mtr_ptax.fill(0.153)
314
314
  assert np.allclose(mtr_ptax, exp_mtr_ptax)
315
315
  # misc calls for code coverage
316
- calc.incarray('e00300', np.ones_like(calc.array('e00300')))
317
- calc.policy_param('ID_c', param_value=50e3)
316
+ calc.incarray("e00300", np.ones_like(calc.array("e00300")))
317
+ calc.policy_param("ID_c", param_value=50e3)
318
318
 
319
319
 
320
320
  def test_bad_json_names(tests_path):
321
321
  """
322
- Test that ValueError raised with assump or reform do not end in '.json'
322
+ Test that ValueError raised with assump or reform do not end in ".json"
323
323
  """
324
324
  test_url = (
325
- 'https://raw.githubusercontent.com/PSLmodels/'
326
- 'Tax-Calculator/master/taxcalc/reforms/'
327
- '2017_law.out.csv'
325
+ "https://raw.githubusercontent.com/PSLmodels/"
326
+ "Tax-Calculator/master/taxcalc/reforms/"
327
+ "2017_law.out.csv"
328
328
  )
329
- csvname = os.path.join(tests_path, '..', 'growfactors.csv')
329
+ csvname = os.path.join(tests_path, "..", "growfactors.csv")
330
330
  with pytest.raises(ValueError):
331
331
  Calculator.read_json_param_objects(csvname, None)
332
332
  with pytest.raises(ValueError):
@@ -337,6 +337,7 @@ def test_bad_json_names(tests_path):
337
337
  Calculator.read_json_param_objects(None, test_url)
338
338
 
339
339
 
340
+ @pytest.mark.local
340
341
  def test_json_assump_url():
341
342
  """
342
343
  Test reading JSON assumption file using URL.
@@ -417,9 +418,9 @@ def test_json_assump_url():
417
418
  }
418
419
  }
419
420
  """
420
- assump_url = ('https://raw.githubusercontent.com/PSLmodels/'
421
- 'Tax-Calculator/master/taxcalc/assumptions/'
422
- 'economic_assumptions_template.json')
421
+ assump_url = ("https://raw.githubusercontent.com/PSLmodels/"
422
+ "Tax-Calculator/master/taxcalc/assumptions/"
423
+ "economic_assumptions_template.json")
423
424
  params_str = Calculator.read_json_param_objects(None, assump_str)
424
425
  assert params_str
425
426
  params_url = Calculator.read_json_param_objects(None, assump_url)
@@ -451,19 +452,19 @@ def test_read_bad_json_assump_file():
451
452
  with pytest.raises(ValueError):
452
453
  Calculator.read_json_param_objects(None, badassump1)
453
454
  with pytest.raises(ValueError):
454
- Calculator.read_json_param_objects(None, 'unknown_file_name')
455
+ Calculator.read_json_param_objects(None, "unknown_file_name")
455
456
  with pytest.raises(TypeError):
456
457
  Calculator.read_json_param_objects(None, [])
457
458
 
458
459
 
459
460
  def test_json_doesnt_exist():
460
461
  """
461
- Test JSON file which doesn't exist
462
+ Test JSON file which doesn"t exist
462
463
  """
463
464
  with pytest.raises(ValueError):
464
- Calculator.read_json_param_objects(None, './reforms/doesnt_exist.json')
465
+ Calculator.read_json_param_objects(None, "./reforms/doesnt_exist.json")
465
466
  with pytest.raises(ValueError):
466
- Calculator.read_json_param_objects('./reforms/doesnt_exist.json', None)
467
+ Calculator.read_json_param_objects("./reforms/doesnt_exist.json", None)
467
468
 
468
469
 
469
470
  def test_calc_all():
@@ -501,13 +502,13 @@ def test_noreform_documentation():
501
502
  gfs = GrowFactors()
502
503
  actual_doc = Calculator.reform_documentation(params, gfs)
503
504
  expected_doc = (
504
- 'REFORM DOCUMENTATION\n'
505
- 'Baseline Growth-Difference Assumption Values by Year:\n'
506
- 'none: no baseline GrowDiff assumptions specified\n'
507
- 'Response Growth-Difference Assumption Values by Year:\n'
508
- 'none: no response GrowDiff assumptions specified\n'
509
- 'Policy Reform Parameter Values by Year:\n'
510
- 'none: using current-law policy parameters\n'
505
+ "REFORM DOCUMENTATION\n"
506
+ "Baseline Growth-Difference Assumption Values by Year:\n"
507
+ "none: no baseline GrowDiff assumptions specified\n"
508
+ "Response Growth-Difference Assumption Values by Year:\n"
509
+ "none: no response GrowDiff assumptions specified\n"
510
+ "Policy Reform Parameter Values by Year:\n"
511
+ "none: using current-law policy parameters\n"
511
512
  )
512
513
  assert actual_doc == expected_doc
513
514
 
@@ -550,14 +551,14 @@ def test_reform_documentation():
550
551
  """
551
552
  params = Calculator.read_json_param_objects(reform_json, assump_json)
552
553
  assert isinstance(params, dict)
553
- second_reform = {'II_em': {2019: 6500}}
554
+ second_reform = {"II_em": {2019: 6500}}
554
555
  gfs = GrowFactors()
555
556
  doc = Calculator.reform_documentation(params, gfs, [second_reform])
556
557
  assert isinstance(doc, str)
557
558
  dump = False # set to True to print documentation and force test failure
558
559
  if dump:
559
560
  print(doc)
560
- assert False, 'ERROR: reform_documentation above'
561
+ assert False, "ERROR: reform_documentation above"
561
562
 
562
563
 
563
564
  def test_distribution_tables(cps_subsample):
@@ -569,22 +570,22 @@ def test_distribution_tables(cps_subsample):
569
570
  calc1 = Calculator(policy=pol, records=recs)
570
571
  assert calc1.current_year == 2014
571
572
  calc1.calc_all()
572
- dt1, dt2 = calc1.distribution_tables(None, 'weighted_deciles')
573
+ dt1, dt2 = calc1.distribution_tables(None, "weighted_deciles")
573
574
  assert isinstance(dt1, pd.DataFrame)
574
575
  assert dt2 is None
575
- dt1, dt2 = calc1.distribution_tables(calc1, 'weighted_deciles')
576
+ dt1, dt2 = calc1.distribution_tables(calc1, "weighted_deciles")
576
577
  assert isinstance(dt1, pd.DataFrame)
577
578
  assert isinstance(dt2, pd.DataFrame)
578
579
  reform = {
579
- 'UBI_u18': {2014: 1000},
580
- 'UBI_1820': {2014: 1000},
581
- 'UBI_21': {2014: 1000}
580
+ "UBI_u18": {2014: 1000},
581
+ "UBI_1820": {2014: 1000},
582
+ "UBI_21": {2014: 1000}
582
583
  }
583
584
  pol.implement_reform(reform)
584
585
  assert not pol.parameter_errors
585
586
  calc2 = Calculator(policy=pol, records=recs)
586
587
  calc2.calc_all()
587
- dt1, dt2 = calc1.distribution_tables(calc2, 'weighted_deciles')
588
+ dt1, dt2 = calc1.distribution_tables(calc2, "weighted_deciles")
588
589
  assert isinstance(dt1, pd.DataFrame)
589
590
  assert isinstance(dt2, pd.DataFrame)
590
591
 
@@ -598,13 +599,13 @@ def test_difference_table(cps_subsample):
598
599
  recs = Records.cps_constructor(data=cps_subsample)
599
600
  calc1 = Calculator(policy=pol, records=recs)
600
601
  assert calc1.current_year == cyr
601
- reform = {'SS_Earnings_c': {cyr: 9e99}}
602
+ reform = {"SS_Earnings_c": {cyr: 9e99}}
602
603
  pol.implement_reform(reform)
603
604
  calc2 = Calculator(policy=pol, records=recs)
604
605
  assert calc2.current_year == cyr
605
606
  calc1.calc_all()
606
607
  calc2.calc_all()
607
- diff = calc1.difference_table(calc2, 'weighted_deciles', 'iitax')
608
+ diff = calc1.difference_table(calc2, "weighted_deciles", "iitax")
608
609
  assert isinstance(diff, pd.DataFrame)
609
610
 
610
611
 
@@ -626,13 +627,13 @@ def test_mtr_graph(cps_subsample):
626
627
  calc = Calculator(policy=Policy(), records=recs)
627
628
  fig = calc.mtr_graph(calc,
628
629
  mars=2,
629
- income_measure='wages',
630
- mtr_measure='ptax',
630
+ income_measure="wages",
631
+ mtr_measure="ptax",
631
632
  pop_quantiles=False)
632
633
  assert fig
633
634
  fig = calc.mtr_graph(calc,
634
- income_measure='agi',
635
- mtr_measure='itax',
635
+ income_measure="agi",
636
+ mtr_measure="itax",
636
637
  pop_quantiles=True)
637
638
  assert fig
638
639
 
@@ -643,9 +644,9 @@ def test_atr_graph(cps_subsample):
643
644
  """
644
645
  recs = Records.cps_constructor(data=cps_subsample)
645
646
  calc = Calculator(policy=Policy(), records=recs)
646
- fig = calc.atr_graph(calc, mars=2, atr_measure='itax')
647
+ fig = calc.atr_graph(calc, mars=2, atr_measure="itax")
647
648
  assert fig
648
- fig = calc.atr_graph(calc, atr_measure='ptax')
649
+ fig = calc.atr_graph(calc, atr_measure="ptax")
649
650
  assert fig
650
651
 
651
652
 
@@ -682,7 +683,7 @@ def test_ce_aftertax_income(cps_subsample):
682
683
  rec = Records.cps_constructor(data=cps_subsample)
683
684
  pol = Policy()
684
685
  calc1 = Calculator(policy=pol, records=rec)
685
- pol.implement_reform({'SS_Earnings_c': {2013: 9e99}})
686
+ pol.implement_reform({"SS_Earnings_c": {2013: 9e99}})
686
687
  calc2 = Calculator(policy=pol, records=rec)
687
688
  res = calc1.ce_aftertax_income(calc2)
688
689
  assert isinstance(res, dict)
@@ -691,19 +692,19 @@ def test_ce_aftertax_income(cps_subsample):
691
692
  @pytest.mark.itmded_vars
692
693
  @pytest.mark.pre_release
693
694
  @pytest.mark.requires_pufcsv
694
- @pytest.mark.parametrize('year, cvname, hcname',
695
- [(2018, 'c17000', 'ID_Medical_hc'),
696
- (2018, 'c18300', 'ID_AllTaxes_hc'),
697
- (2018, 'c19200', 'ID_InterestPaid_hc'),
698
- (2018, 'c19700', 'ID_Charity_hc'),
699
- (2018, 'c20500', 'ID_Casualty_hc'),
700
- (2018, 'c20800', 'ID_Miscellaneous_hc'),
701
- (2017, 'c17000', 'ID_Medical_hc'),
702
- (2017, 'c18300', 'ID_AllTaxes_hc'),
703
- (2017, 'c19200', 'ID_InterestPaid_hc'),
704
- (2017, 'c19700', 'ID_Charity_hc'),
705
- (2017, 'c20500', 'ID_Casualty_hc'),
706
- (2017, 'c20800', 'ID_Miscellaneous_hc')])
695
+ @pytest.mark.parametrize("year, cvname, hcname",
696
+ [(2018, "c17000", "ID_Medical_hc"),
697
+ (2018, "c18300", "ID_AllTaxes_hc"),
698
+ (2018, "c19200", "ID_InterestPaid_hc"),
699
+ (2018, "c19700", "ID_Charity_hc"),
700
+ (2018, "c20500", "ID_Casualty_hc"),
701
+ (2018, "c20800", "ID_Miscellaneous_hc"),
702
+ (2017, "c17000", "ID_Medical_hc"),
703
+ (2017, "c18300", "ID_AllTaxes_hc"),
704
+ (2017, "c19200", "ID_InterestPaid_hc"),
705
+ (2017, "c19700", "ID_Charity_hc"),
706
+ (2017, "c20500", "ID_Casualty_hc"),
707
+ (2017, "c20800", "ID_Miscellaneous_hc")])
707
708
  def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample):
708
709
  """
709
710
  Check that all c04470 components are adjusted to reflect the filing
@@ -721,16 +722,16 @@ def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample):
721
722
  # policy1 such that everybody itemizes deductions and all are allowed
722
723
  policy1 = Policy()
723
724
  reform1 = {
724
- 'STD_Aged': {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
725
- 'STD': {year: [0.0, 0.0, 0.0, 0.0, 0.0]}
725
+ "STD_Aged": {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
726
+ "STD": {year: [0.0, 0.0, 0.0, 0.0, 0.0]}
726
727
  }
727
728
  policy1.implement_reform(reform1)
728
729
  assert not policy1.parameter_errors
729
730
  # policy2 such that everybody itemizes deductions but one is disallowed
730
731
  policy2 = Policy()
731
732
  reform2 = {
732
- 'STD_Aged': {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
733
- 'STD': {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
733
+ "STD_Aged": {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
734
+ "STD": {year: [0.0, 0.0, 0.0, 0.0, 0.0]},
734
735
  hcname: {year: 1.0}
735
736
  }
736
737
  policy2.implement_reform(reform2)
@@ -743,36 +744,36 @@ def test_itemded_component_amounts(year, cvname, hcname, puf_fullsample):
743
744
  calc2.advance_to_year(year)
744
745
  calc2.calc_all()
745
746
  # confirm that nobody is taking the standard deduction
746
- assert np.allclose(calc1.array('standard'), 0.)
747
- assert np.allclose(calc2.array('standard'), 0.)
747
+ assert np.allclose(calc1.array("standard"), 0.)
748
+ assert np.allclose(calc2.array("standard"), 0.)
748
749
  # calculate different in total itemized deductions
749
750
  if year == 2017:
750
751
  # pre-Pease limitation total itemized deductions
751
- itmded1 = calc1.weighted_total('c21060') * 1e-9
752
- itmded2 = calc2.weighted_total('c21060') * 1e-9
752
+ itmded1 = calc1.weighted_total("c21060") * 1e-9
753
+ itmded2 = calc2.weighted_total("c21060") * 1e-9
753
754
  elif year == 2018:
754
755
  # total itemized deductions (no Pease-like limitation)
755
- itmded1 = calc1.weighted_total('c04470') * 1e-9
756
- itmded2 = calc2.weighted_total('c04470') * 1e-9
756
+ itmded1 = calc1.weighted_total("c04470") * 1e-9
757
+ itmded2 = calc2.weighted_total("c04470") * 1e-9
757
758
  else:
758
- raise ValueError(f'illegal year value = {year}')
759
+ raise ValueError(f"illegal year value = {year}")
759
760
  difference_in_total_itmded = itmded1 - itmded2
760
761
  # calculate itemized component amount
761
762
  component_amt = calc1.weighted_total(cvname) * 1e-9
762
763
  # confirm that component amount is equal to difference in total deductions
763
- if year == 2017 and cvname == 'c19700':
764
+ if year == 2017 and cvname == "c19700":
764
765
  atol = 0.016
765
- elif year == 2017 and cvname == 'c19200':
766
+ elif year == 2017 and cvname == "c19200":
766
767
  atol = 0.010
767
- elif year == 2017 and cvname == 'c18300':
768
+ elif year == 2017 and cvname == "c18300":
768
769
  atol = 0.009
769
770
  else:
770
771
  atol = 0.00001
771
772
  if not np.allclose(component_amt, difference_in_total_itmded, atol=atol):
772
773
  msg = (
773
- f'\n{cvname}={component_amt:.3f} != '
774
- f'{difference_in_total_itmded:.3f}='
775
- 'difference_in_total_itemized_deductions'
774
+ f"\n{cvname}={component_amt:.3f} != "
775
+ f"{difference_in_total_itmded:.3f}="
776
+ "difference_in_total_itemized_deductions"
776
777
  )
777
778
  raise ValueError(msg)
778
779
 
@@ -792,16 +793,16 @@ def test_qbid_calculation():
792
793
  # and that the spouse has no business income and only earnings.
793
794
  TPC_YEAR = 2018
794
795
  TPC_VARS = (
795
- 'RECID,MARS,e00200s,e00200,e26270,e02000,PT_SSTB_income,'
796
- 'PT_binc_w2_wages,PT_ubia_property,pre_qbid_taxinc,qbid\n'
796
+ "RECID,MARS,e00200s,e00200,e26270,e02000,PT_SSTB_income,"
797
+ "PT_binc_w2_wages,PT_ubia_property,pre_qbid_taxinc,qbid\n"
797
798
  )
798
799
  TPC_FUNITS = (
799
- '1,2, 99000, 99000,75000,75000,1,20000,90000,150000,15000.00\n'
800
- '2,2,349000,349000,75000,75000,1,20000,90000,400000, 1612.50\n'
801
- '3,2,524000,524000,75000,75000,1,20000,90000,575000, 0.00\n'
802
- '4,2, 99000, 99000,75000,75000,0,20000,90000,150000,15000.00\n'
803
- '5,2,349000,349000,75000,75000,0,20000,90000,400000,10750.00\n'
804
- '6,2,524000,524000,75000,75000,0,20000,90000,575000,10000.00\n'
800
+ "1,2, 99000, 99000,75000,75000,1,20000,90000,150000,15000.00\n"
801
+ "2,2,349000,349000,75000,75000,1,20000,90000,400000, 1612.50\n"
802
+ "3,2,524000,524000,75000,75000,1,20000,90000,575000, 0.00\n"
803
+ "4,2, 99000, 99000,75000,75000,0,20000,90000,150000,15000.00\n"
804
+ "5,2,349000,349000,75000,75000,0,20000,90000,400000,10750.00\n"
805
+ "6,2,524000,524000,75000,75000,0,20000,90000,575000,10000.00\n"
805
806
  )
806
807
  # generate actual Calculator pre-qbid taxinc and qbid amounts
807
808
  tpc_df = pd.read_csv(StringIO(TPC_VARS + TPC_FUNITS))
@@ -810,7 +811,7 @@ def test_qbid_calculation():
810
811
  calc = Calculator(policy=Policy(), records=recs)
811
812
  assert calc.current_year == TPC_YEAR
812
813
  calc.calc_all()
813
- varlist = ['RECID', 'c00100', 'standard', 'c04470', 'qbided']
814
+ varlist = ["RECID", "c00100", "standard", "c04470", "qbided"]
814
815
  tc_df = calc.dataframe(varlist, all_vars=True)
815
816
  # compare actual amounts with expected amounts from TPC publication
816
817
  act_taxinc = tc_df.c00100 - np.maximum(tc_df.standard, tc_df.c04470)
@@ -820,11 +821,11 @@ def test_qbid_calculation():
820
821
 
821
822
 
822
823
  def test_calc_all_benefits_amounts(cps_subsample):
823
- '''
824
+ """
824
825
  Testing how benefits are handled in the calc_all method
825
- '''
826
+ """
826
827
  # set a reform with a positive UBI amount
827
- ubi_ref = {'UBI_21': {2020: 1000}}
828
+ ubi_ref = {"UBI_21": {2020: 1000}}
828
829
 
829
830
  # create baseline calculator
830
831
  pol = Policy()
@@ -842,14 +843,14 @@ def test_calc_all_benefits_amounts(cps_subsample):
842
843
 
843
844
  # check that differences in benefits totals are equal to diffs in
844
845
  # UBI
845
- ubi_diff = (calc_ubi.weighted_total('ubi') -
846
- calc_base.weighted_total('ubi')) / 1e9
846
+ ubi_diff = (calc_ubi.weighted_total("ubi") -
847
+ calc_base.weighted_total("ubi")) / 1e9
847
848
  benefit_cost_diff = (
848
- calc_ubi.weighted_total('benefit_cost_total') -
849
- calc_base.weighted_total('benefit_cost_total')) / 1e9
849
+ calc_ubi.weighted_total("benefit_cost_total") -
850
+ calc_base.weighted_total("benefit_cost_total")) / 1e9
850
851
  benefit_value_diff = (
851
- calc_ubi.weighted_total('benefit_cost_total') -
852
- calc_base.weighted_total('benefit_cost_total')) / 1e9
852
+ calc_ubi.weighted_total("benefit_cost_total") -
853
+ calc_base.weighted_total("benefit_cost_total")) / 1e9
853
854
 
854
855
  assert np.allclose(ubi_diff, benefit_cost_diff)
855
856
  assert np.allclose(ubi_diff, benefit_value_diff)
@@ -874,8 +875,8 @@ def test_cg_top_rate():
874
875
  "STD": {2019: [0, 0, 0, 0, 0]}}
875
876
 
876
877
  # create one record just below the top CG bracket and one just above
877
- VARS = 'RECID,MARS,p23250\n'
878
- FUNITS = '1,2,999999\n2,2,1000001\n'
878
+ VARS = "RECID,MARS,p23250\n"
879
+ FUNITS = "1,2,999999\n2,2,1000001\n"
879
880
 
880
881
  pol_base = Policy()
881
882
  pol_base.implement_reform(base)
@@ -894,23 +895,23 @@ def test_cg_top_rate():
894
895
  calc_ref.calc_all()
895
896
 
896
897
  # calculate MTRs wrt long term gains
897
- mtr_base = calc_base.mtr(variable_str='p23250',
898
+ mtr_base = calc_base.mtr(variable_str="p23250",
898
899
  calc_all_already_called=True,
899
900
  wrt_full_compensation=False)
900
901
  mtr_itax_base = mtr_base[1]
901
902
 
902
- cg_rt3 = pol_base.to_array('CG_rt3', year=2019)
903
+ cg_rt3 = pol_base.to_array("CG_rt3", year=2019)
903
904
  # check that MTR for both records is equal to CG_rt3
904
905
  assert np.allclose(mtr_itax_base, cg_rt3)
905
906
 
906
907
  # calculate MTRs under reform
907
- mtr_ref = calc_ref.mtr(variable_str='p23250',
908
+ mtr_ref = calc_ref.mtr(variable_str="p23250",
908
909
  calc_all_already_called=True,
909
910
  wrt_full_compensation=False)
910
911
  mtr_itax_ref = mtr_ref[1]
911
912
 
912
- cg_rt3_ref = pol_ref.to_array('CG_rt3', year=2019)
913
- cg_rt4_ref = pol_ref.to_array(param='CG_rt4', year=2019)
913
+ cg_rt3_ref = pol_ref.to_array("CG_rt3", year=2019)
914
+ cg_rt4_ref = pol_ref.to_array(param="CG_rt4", year=2019)
914
915
 
915
916
  # check that MTR of houshold below top threshold is equal to
916
917
  # CG_rt3