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
taxcalc/__init__.py CHANGED
@@ -14,6 +14,6 @@ from taxcalc.taxcalcio import *
14
14
  from taxcalc.utils import *
15
15
  from taxcalc.cli import *
16
16
 
17
- __version__ = '5.1.0'
18
- __min_python3_version__ = 10
19
- __max_python3_version__ = 12
17
+ __version__ = '5.3.0'
18
+ __min_python3_version__ = 11
19
+ __max_python3_version__ = 13
taxcalc/calcfunctions.py CHANGED
@@ -943,8 +943,9 @@ def ItemDed(e17500, e18400, e18500, e19200,
943
943
  ID_Medical_c, ID_StateLocalTax_c, ID_RealEstate_c,
944
944
  ID_InterestPaid_c, ID_Charity_c, ID_Casualty_c,
945
945
  ID_Miscellaneous_c, ID_AllTaxes_c, ID_AllTaxes_hc,
946
+ ID_AllTaxes_c_ps, ID_AllTaxes_c_po_rate, ID_AllTaxes_c_po_floor,
946
947
  ID_StateLocalTax_crt, ID_RealEstate_crt, ID_Charity_f,
947
- ID_reduction_salt_rate, ID_reduction_other_rate):
948
+ ID_reduction_rate):
948
949
  """
949
950
  Calculates itemized deductions, Form 1040, Schedule A.
950
951
 
@@ -1057,10 +1058,16 @@ def ItemDed(e17500, e18400, e18500, e19200,
1057
1058
  Ceiling on the amount of miscellaneous expense deduction
1058
1059
  allowed (dollars)
1059
1060
  ID_AllTaxes_c: list
1060
- Ceiling on the amount of state and local income, stales, and
1061
+ Cap on the amount of state and local income, sales, and
1061
1062
  real estate deductions allowed (dollars)
1062
1063
  ID_AllTaxes_hc: float
1063
1064
  State and local income, sales, and real estate tax deduciton haircut
1065
+ ID_AllTaxes_c_ps: float
1066
+ AGI level above which ID_AllTaxes_c is reduced
1067
+ ID_AllTaxes_c_po_rate: float
1068
+ ID_AllTaxes_c reduction rate when AGI is above ID_AllTaxes_c_ps
1069
+ ID_AllTaxes_c_po_floor: float
1070
+ Floor below which ID_AllTaxes_c cannot be reduced
1064
1071
  ID_StateLocalTax_crt: float
1065
1072
  Ceiling (as decimal fraction of AGI) for the combination of all
1066
1073
  state and local income and sales tax deductions
@@ -1069,10 +1076,8 @@ def ItemDed(e17500, e18400, e18500, e19200,
1069
1076
  state, local, and foreign real estate tax deductions
1070
1077
  ID_Charity_f: list
1071
1078
  Floor on the amount of charity expense deduction allowed (dollars)
1072
- ID_reduction_salt_rate: float
1073
- OBBBA reduction rate for SALT deductions
1074
- ID_reduction_other_rate: float
1075
- OBBBA reduction rate for other deductions
1079
+ ID_reduction_rate: float
1080
+ OBBBA reduction rate for all itemized deductions
1076
1081
 
1077
1082
  Returns
1078
1083
  -------
@@ -1115,7 +1120,12 @@ def ItemDed(e17500, e18400, e18500, e19200,
1115
1120
  c18400 = min(c18400, ID_StateLocalTax_crt * max(c00100, 0.0001))
1116
1121
  c18500 = min(c18500, ID_RealEstate_crt * max(c00100, 0.0001))
1117
1122
  c18300 = (c18400 + c18500) * (1. - ID_AllTaxes_hc)
1118
- c18300 = min(c18300, ID_AllTaxes_c[MARS - 1])
1123
+ cap = ID_AllTaxes_c[MARS - 1]
1124
+ if posagi > ID_AllTaxes_c_ps[MARS - 1]:
1125
+ excess_agi = posagi - ID_AllTaxes_c_ps[MARS - 1]
1126
+ cap = max(0., cap - excess_agi * ID_AllTaxes_c_po_rate)
1127
+ cap = max(cap, ID_AllTaxes_c_po_floor[MARS - 1])
1128
+ c18300 = min(c18300, cap)
1119
1129
  # Interest paid
1120
1130
  c19200 = e19200 * (1. - ID_InterestPaid_hc)
1121
1131
  c19200 = min(c19200, ID_InterestPaid_c[MARS - 1])
@@ -1154,16 +1164,11 @@ def ItemDed(e17500, e18400, e18500, e19200,
1154
1164
  # OBBBA limitation on total itemized deductions
1155
1165
  # (no attempt to adjust c04470 components for limitation)
1156
1166
  reduction = 0.
1157
- if ID_reduction_salt_rate > 0. or ID_reduction_other_rate > 0.:
1158
- assert c21040 <= 0.0, "Pease and OBBBA cannot both be in effect"
1167
+ if ID_reduction_rate > 0.:
1168
+ assert c21040 <= 0.0, 'Pease and OBBBA cannot both be in effect'
1159
1169
  tincome = max(0., c00100 - c04600)
1160
1170
  texcess = max(0., tincome - II_brk6[MARS - 1])
1161
- smaller_salt = min(c18300, texcess)
1162
- salt_reduction = ID_reduction_salt_rate * smaller_salt
1163
- other_deds = max(0, c04470 - c18300)
1164
- smaller_other = min(other_deds, texcess)
1165
- other_reduction = ID_reduction_other_rate * smaller_other
1166
- reduction = salt_reduction + other_reduction
1171
+ reduction = ID_reduction_rate * texcess
1167
1172
  c04470 = max(0., c04470 - reduction)
1168
1173
  # Cap total itemized deductions
1169
1174
  # (no attempt to adjust c04470 components for limitation)
@@ -2197,7 +2202,7 @@ def F2441(MARS, earned_p, earned_s, f2441, CDCC_c, e32800, exact, c00100,
2197
2202
  )
2198
2203
  # ... second phase-down from CDCC_po1_rate_min to CDCC_po2_rate_min
2199
2204
  ps2 = CDCC_ps2[MARS - 1]
2200
- assert ps2 >= ps1, "CDCC_ps2 must be no less than CDCC_ps1"
2205
+ assert ps2 >= ps1, 'CDCC_ps2 must be no less than CDCC_ps1'
2201
2206
  if c00100 > ps2:
2202
2207
  steps_fractional = (c00100 - ps2) / CDCC_po2_step_size[MARS - 1]
2203
2208
  if exact == 1: # exact calculation as on tax forms
taxcalc/calculator.py CHANGED
@@ -282,7 +282,7 @@ class Calculator():
282
282
  """
283
283
  if param_value is None:
284
284
  val = getattr(self.__policy, param_name)
285
- if param_name.startswith("_"):
285
+ if param_name.startswith('_'):
286
286
  return val
287
287
  return val[0] # drop down a dimension.
288
288
  setattr(self.__policy, param_name, param_value)
@@ -1214,11 +1214,11 @@ class Calculator():
1214
1214
  # ... write optional param-vector-index line
1215
1215
  if isinstance(pval, list):
1216
1216
  labels = paramtools.consistent_labels(
1217
- [mdata_base[pname]["value"][0]]
1217
+ [mdata_base[pname]['value'][0]]
1218
1218
  )
1219
1219
  label = None
1220
1220
  for _label in labels:
1221
- if _label not in ("value", "year"):
1221
+ if _label not in ('value', 'year'):
1222
1222
  label = _label
1223
1223
  break
1224
1224
  if label:
taxcalc/cli/tc.py CHANGED
@@ -96,23 +96,23 @@ def cli_tc_main():
96
96
  '"stair-step" provisions in the tax law that '
97
97
  'complicate marginal-tax-rate calculations.'),
98
98
  default=False,
99
- action="store_true")
99
+ action='store_true')
100
100
  parser.add_argument('--params',
101
101
  help=('optional flag that causes policy parameter '
102
102
  'values for baseline and reform to be written '
103
103
  'to separate text files.'),
104
104
  default=False,
105
- action="store_true")
105
+ action='store_true')
106
106
  parser.add_argument('--tables',
107
107
  help=('optional flag that causes distributional '
108
108
  'tables to be written to a text file.'),
109
109
  default=False,
110
- action="store_true")
110
+ action='store_true')
111
111
  parser.add_argument('--graphs',
112
112
  help=('optional flag that causes graphs to be written '
113
113
  'to HTML files for viewing in browser.'),
114
114
  default=False,
115
- action="store_true")
115
+ action='store_true')
116
116
  parser.add_argument('--dumpdb',
117
117
  help=('optional flag that causes TAXYEAR variable '
118
118
  'values for each tax-unit under both '
@@ -121,7 +121,7 @@ def cli_tc_main():
121
121
  'included in the database are controlled by '
122
122
  'the --dumpvars option).'),
123
123
  default=False,
124
- action="store_true")
124
+ action='store_true')
125
125
  parser.add_argument('--dumpvars',
126
126
  help=('DUMPVARS is name of optional file containing a '
127
127
  'space-delimited list of variables to include '
@@ -129,7 +129,9 @@ def cli_tc_main():
129
129
  'a minimal set of variables. Valid variable '
130
130
  'names include all variables in the '
131
131
  'records_variables.json file plus mtr_itax and '
132
- 'mtr_ptax (MTRs wrt taxpayer earnings).'),
132
+ 'mtr_ptax (MTRs wrt taxpayer earnings). If '
133
+ 'DUMPVARS is ALL, then all valid variable names '
134
+ 'are included in the dump database.'),
133
135
  default=None)
134
136
  parser.add_argument('--runid', metavar='N',
135
137
  help=('N is a positive integer run id that is used '
@@ -142,23 +144,23 @@ def cli_tc_main():
142
144
  help=('optional flag that suppresses messages about '
143
145
  'input and output actions.'),
144
146
  default=False,
145
- action="store_true")
147
+ action='store_true')
146
148
  parser.add_argument('--test',
147
149
  help=('optional flag that conducts installation '
148
150
  'test, writes test result to stdout, '
149
151
  'and quits leaving the test-related files.'),
150
152
  default=False,
151
- action="store_true")
153
+ action='store_true')
152
154
  parser.add_argument('--version',
153
155
  help=('optional flag that writes Tax-Calculator '
154
156
  'release version to stdout and quits.'),
155
157
  default=False,
156
- action="store_true")
158
+ action='store_true')
157
159
  parser.add_argument('--usage',
158
160
  help=('optional flag that writes short usage '
159
161
  'reminder to stdout and quits.'),
160
162
  default=False,
161
- action="store_true")
163
+ action='store_true')
162
164
  args = parser.parse_args()
163
165
  using_error_file = args.silent and args.runid != 0
164
166
  efilename = f'run{args.runid}.errors'
@@ -246,7 +248,9 @@ def cli_tc_main():
246
248
  # specify dumpvars_str from args.dumpvars file
247
249
  dumpvars_str = ''
248
250
  if args.dumpvars:
249
- if os.path.exists(args.dumpvars):
251
+ if args.dumpvars == 'ALL':
252
+ dumpvars_str = 'ALL'
253
+ elif os.path.exists(args.dumpvars):
250
254
  with open(args.dumpvars, 'r', encoding='utf-8') as dfile:
251
255
  dumpvars_str = dfile.read()
252
256
  else:
taxcalc/data.py CHANGED
@@ -109,7 +109,7 @@ class Data():
109
109
  self._read_weights(weights)
110
110
  # ... weights must be same size as data
111
111
  if self.array_length > len(self.WT.index):
112
- raise ValueError("Data has more records than weights.")
112
+ raise ValueError('Data has more records than weights.')
113
113
  if self.array_length < len(self.WT.index):
114
114
  # scale-up sub-sample weights by year-specific factor
115
115
  sum_full_weights = self.WT.sum()
taxcalc/decorators.py CHANGED
@@ -39,7 +39,7 @@ def id_wrapper(*dec_args, **dec_kwargs): # pylint: disable=unused-argument
39
39
  return wrap
40
40
 
41
41
 
42
- if DO_JIT is False or 'NOTAXCALCJIT' in os.environ:
42
+ if DO_JIT is False or "NOTAXCALCJIT" in os.environ:
43
43
  JIT = id_wrapper
44
44
  else:
45
45
  JIT = numba.jit
@@ -89,7 +89,8 @@ def create_apply_function_string(sigout, sigin, parameters):
89
89
  out_args = ["x_" + str(i) for i in range(0, len(sigout))]
90
90
  in_args = ["x_" + str(i) for i in range(len(sigout), total_len)]
91
91
 
92
- fstr.write(f"def ap_func({','.join(out_args + in_args)}):\n")
92
+ all_args = ",".join(out_args + in_args)
93
+ fstr.write(f"def ap_func({all_args}):\n")
93
94
  fstr.write(" for i in range(len(x_0)):\n")
94
95
  out_index = [x + "[i]" for x in out_args]
95
96
  in_index = []
@@ -194,8 +195,8 @@ def make_apply_function(func, out_args, in_args, parameters,
194
195
  eval(func_code, # pylint: disable=eval-used
195
196
  {"jitted_f": jitted_f}, fakeglobals)
196
197
  if do_jit:
197
- return JIT(**kwargs)(fakeglobals['ap_func'])
198
- return fakeglobals['ap_func']
198
+ return JIT(**kwargs)(fakeglobals["ap_func"])
199
+ return fakeglobals["ap_func"]
199
200
 
200
201
 
201
202
  def apply_jit(dtype_sig_out, dtype_sig_in, parameters=None, **kwargs):
@@ -256,7 +257,7 @@ def iterate_jit(parameters=None, **kwargs):
256
257
  # Get the input arguments from the function
257
258
  in_args = inspect.getfullargspec(func).args
258
259
  # Get the numba.jit arguments
259
- jit_args_list = inspect.getfullargspec(JIT).args + ['nopython']
260
+ jit_args_list = inspect.getfullargspec(JIT).args + ["nopython"]
260
261
  kwargs_for_jit = {}
261
262
  for key, val in kwargs.items():
262
263
  if key in jit_args_list:
@@ -280,7 +281,7 @@ def iterate_jit(parameters=None, **kwargs):
280
281
  # the AST of the function
281
282
  grn = GetReturnNode()
282
283
  all_out_args = None
283
- for node in ast.walk(ast.parse(''.join(src))):
284
+ for node in ast.walk(ast.parse("".join(src))):
284
285
  all_out_args = grn.visit(node)
285
286
  if all_out_args:
286
287
  break
@@ -301,7 +302,7 @@ def iterate_jit(parameters=None, **kwargs):
301
302
  in iterate_jit decorator.
302
303
  """
303
304
  # os TESTING environment only accepts string arguments
304
- if os.getenv('TESTING') == 'True':
305
+ if os.getenv("TESTING") == "True":
305
306
  return func(*args, **kwargs)
306
307
 
307
308
  in_arrays = []
@@ -321,7 +322,7 @@ def iterate_jit(parameters=None, **kwargs):
321
322
  fakeglobals = {}
322
323
  eval(func_code, # pylint: disable=eval-used
323
324
  {"applied_f": applied_jitted_f}, fakeglobals)
324
- high_level_fn = fakeglobals['hl_func']
325
+ high_level_fn = fakeglobals["hl_func"]
325
326
  ans = high_level_fn(*args, **kwargs)
326
327
  return ans
327
328
 
taxcalc/growfactors.py CHANGED
@@ -35,7 +35,8 @@ class GrowFactors():
35
35
  -----
36
36
  Typical usage is "gfactor = GrowFactors()", which produces an object
37
37
  containing baseline growth factors in the GrowFactors.FILE_NAME file,
38
- which is for use with puf and cps data from the taxdata repository.
38
+ which is used to extrapolate cps and puf data from the taxdata repository,
39
+ and is used to index policy parameters.
39
40
  """
40
41
 
41
42
  PACKAGE_FILE_NAMES = ['growfactors.csv']
taxcalc/policy.py CHANGED
@@ -22,8 +22,9 @@ class Policy(Parameters):
22
22
 
23
23
  Parameters
24
24
  ----------
25
- gfactors: GrowFactors class instance
26
- containing price inflation rates and wage growth rates
25
+ gfactors: GrowFactors class instance or None
26
+ containing price inflation rates and wage growth rates used
27
+ to index policy paramaters
27
28
 
28
29
  last_budget_year: integer
29
30
  user-defined last parameter extrapolation year
@@ -103,6 +104,13 @@ class Policy(Parameters):
103
104
  'ID_Charity_crt_cash': (
104
105
  'was renamed ID_Charity_crt_all in Tax-Calculator 5.1.0'
105
106
  ),
107
+ # following parameters were renamed in PR 2939
108
+ 'ID_reduction_salt_rate': (
109
+ 'was renamed ID_reduction_rate in Tax-Calculator 5.1.0'
110
+ ),
111
+ 'ID_reduction_other_rate': (
112
+ 'was renamed ID_reduction_rate in Tax-Calculator 5.1.0'
113
+ ),
106
114
  }
107
115
  # (2) specify which Policy parameters have been redefined recently
108
116
  # where "recently" means in the last major release
@@ -193,15 +201,15 @@ class Policy(Parameters):
193
201
  )
194
202
  with open(path, 'r', encoding='utf-8') as f:
195
203
  defaults = json.loads(f.read()) # pylint: disable=protected-access
196
- return [k for k in defaults if k != "schema"]
204
+ return [k for k in defaults if k != 'schema']
197
205
 
198
206
  def set_rates(self):
199
207
  """
200
208
  Initialize policy parameter indexing rates.
201
209
  """
202
210
  cpi_vals = [
203
- vo["value"] for
204
- vo in self._data["parameter_indexing_CPI_offset"]["value"]
211
+ vo['value'] for
212
+ vo in self._data['parameter_indexing_CPI_offset']['value']
205
213
  ]
206
214
  # parameter_indexing_CPI_offset parameter is no longer used, so check:
207
215
  assert any(cpi_vals) is False, \