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.
- taxcalc/__init__.py +3 -3
- taxcalc/calcfunctions.py +21 -16
- taxcalc/calculator.py +3 -3
- taxcalc/cli/tc.py +15 -11
- taxcalc/data.py +1 -1
- taxcalc/decorators.py +9 -8
- taxcalc/growfactors.py +2 -1
- taxcalc/policy.py +13 -5
- taxcalc/policy_current_law.json +1191 -1395
- taxcalc/puf_ratios.csv +24 -24
- taxcalc/puf_weights.csv.gz +0 -0
- taxcalc/reforms/2017_law.json +2 -0
- taxcalc/reforms/ARPA.out.csv +9 -9
- taxcalc/taxcalcio.py +41 -26
- taxcalc/tests/conftest.py +1 -1
- taxcalc/tests/cpscsv_agg_expect.csv +26 -26
- taxcalc/tests/puf_var_correl_coeffs_2016.csv +24 -24
- taxcalc/tests/puf_var_wght_means_by_year.csv +80 -80
- taxcalc/tests/pufcsv_agg_expect.csv +26 -26
- taxcalc/tests/pufcsv_mtr_expect.txt +21 -21
- taxcalc/tests/reforms.json +3 -1
- taxcalc/tests/reforms_expect.csv +48 -48
- taxcalc/tests/test_4package.py +8 -9
- taxcalc/tests/test_calculator.py +152 -151
- taxcalc/tests/test_compare.py +2 -2
- taxcalc/tests/test_consumption.py +2 -2
- taxcalc/tests/test_cpscsv.py +4 -3
- taxcalc/tests/test_decorators.py +57 -52
- taxcalc/tests/test_growdiff.py +2 -2
- taxcalc/tests/test_parameters.py +59 -53
- taxcalc/tests/test_policy.py +229 -251
- taxcalc/tests/test_puf_var_stats.py +2 -2
- taxcalc/tests/test_pufcsv.py +5 -4
- taxcalc/tests/test_records.py +5 -1
- taxcalc/tests/test_reforms.py +101 -99
- taxcalc/tests/test_taxcalcio.py +10 -4
- taxcalc/utils.py +3 -3
- {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/METADATA +3 -6
- {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/RECORD +43 -44
- taxcalc/reforms/clp.out.csv +0 -10
- {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/WHEEL +0 -0
- {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/entry_points.txt +0 -0
- {taxcalc-5.1.0.dist-info → taxcalc-5.3.0.dist-info}/licenses/LICENSE +0 -0
- {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.
|
18
|
-
__min_python3_version__ =
|
19
|
-
__max_python3_version__ =
|
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
|
-
|
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
|
-
|
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
|
-
|
1073
|
-
OBBBA reduction rate for
|
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
|
-
|
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
|
1158
|
-
assert c21040 <= 0.0,
|
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
|
-
|
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,
|
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][
|
1217
|
+
[mdata_base[pname]['value'][0]]
|
1218
1218
|
)
|
1219
1219
|
label = None
|
1220
1220
|
for _label in labels:
|
1221
|
-
if _label not in (
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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=
|
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
|
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(
|
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
|
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
|
-
|
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[
|
198
|
-
return fakeglobals[
|
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 + [
|
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(
|
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(
|
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[
|
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
|
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 !=
|
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[
|
204
|
-
vo in self._data[
|
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, \
|