taxcalc 4.4.0__py3-none-any.whl → 4.4.1__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 +1 -1
- taxcalc/calcfunctions.py +326 -171
- taxcalc/calculator.py +35 -34
- taxcalc/cli/tc.py +6 -7
- taxcalc/consumption.py +9 -4
- taxcalc/data.py +8 -8
- taxcalc/decorators.py +3 -3
- taxcalc/growdiff.py +5 -0
- taxcalc/growfactors.py +1 -1
- taxcalc/parameters.py +85 -42
- taxcalc/policy.py +1 -1
- taxcalc/records.py +1 -0
- taxcalc/records_variables.json +6 -0
- taxcalc/taxcalcio.py +49 -44
- taxcalc/tests/cmpi_cps_expect.txt +6 -6
- taxcalc/tests/cmpi_puf_expect.txt +6 -6
- taxcalc/tests/conftest.py +42 -41
- taxcalc/tests/test_4package.py +9 -7
- taxcalc/tests/test_benefits.py +9 -8
- taxcalc/tests/test_calcfunctions.py +55 -38
- taxcalc/tests/test_calculator.py +11 -6
- taxcalc/tests/test_compare.py +44 -50
- taxcalc/tests/test_compatible_data.py +9 -7
- taxcalc/tests/test_consumption.py +38 -18
- taxcalc/tests/test_cpscsv.py +33 -31
- taxcalc/tests/test_data.py +31 -24
- taxcalc/tests/test_decorators.py +84 -32
- taxcalc/tests/test_growdiff.py +16 -13
- taxcalc/tests/test_growfactors.py +8 -8
- taxcalc/tests/test_parameters.py +54 -58
- taxcalc/tests/test_policy.py +14 -12
- taxcalc/tests/test_puf_var_stats.py +14 -14
- taxcalc/tests/test_pufcsv.py +40 -40
- taxcalc/tests/test_records.py +73 -60
- taxcalc/tests/test_reforms.py +34 -31
- taxcalc/tests/test_responses.py +4 -4
- taxcalc/tests/test_taxcalcio.py +76 -62
- taxcalc/tests/test_utils.py +78 -46
- taxcalc/utils.py +49 -42
- taxcalc/validation/taxsim35/taxsim_emulation.json +1 -5
- {taxcalc-4.4.0.dist-info → taxcalc-4.4.1.dist-info}/METADATA +19 -5
- {taxcalc-4.4.0.dist-info → taxcalc-4.4.1.dist-info}/RECORD +46 -46
- {taxcalc-4.4.0.dist-info → taxcalc-4.4.1.dist-info}/WHEEL +1 -1
- {taxcalc-4.4.0.dist-info → taxcalc-4.4.1.dist-info}/LICENSE +0 -0
- {taxcalc-4.4.0.dist-info → taxcalc-4.4.1.dist-info}/entry_points.txt +0 -0
- {taxcalc-4.4.0.dist-info → taxcalc-4.4.1.dist-info}/top_level.txt +0 -0
taxcalc/calculator.py
CHANGED
@@ -93,7 +93,8 @@ class Calculator():
|
|
93
93
|
|
94
94
|
def __init__(self, policy=None, records=None, verbose=False,
|
95
95
|
sync_years=True, consumption=None):
|
96
|
-
# pylint: disable=too-many-arguments,too-many-
|
96
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
97
|
+
# pylint: disable=too-many-branches
|
97
98
|
if isinstance(policy, Policy):
|
98
99
|
self.__policy = copy.deepcopy(policy)
|
99
100
|
else:
|
@@ -286,8 +287,7 @@ class Calculator():
|
|
286
287
|
val = getattr(self.__policy, param_name)
|
287
288
|
if param_name.startswith("_"):
|
288
289
|
return val
|
289
|
-
|
290
|
-
return val[0] # drop down a dimension.
|
290
|
+
return val[0] # drop down a dimension.
|
291
291
|
setattr(self.__policy, param_name, param_value)
|
292
292
|
return None
|
293
293
|
|
@@ -345,8 +345,8 @@ class Calculator():
|
|
345
345
|
max_num_years = self.__policy.end_year - self.__policy.current_year + 1
|
346
346
|
assert num_years <= max_num_years
|
347
347
|
calc = copy.deepcopy(self)
|
348
|
-
yearlist =
|
349
|
-
varlist =
|
348
|
+
yearlist = []
|
349
|
+
varlist = []
|
350
350
|
for iyr in range(1, num_years + 1):
|
351
351
|
calc.calc_all()
|
352
352
|
yearlist.append(calc.current_year)
|
@@ -626,8 +626,8 @@ class Calculator():
|
|
626
626
|
'e20100', Charity non-cash contributions;
|
627
627
|
'k1bx14p', Partnership income (also included in e26270 and e02000).
|
628
628
|
"""
|
629
|
-
# pylint: disable=too-many-arguments,too-many-
|
630
|
-
# pylint: disable=too-many-locals,too-many-branches
|
629
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
630
|
+
# pylint: disable=too-many-locals,too-many-branches,too-many-statements
|
631
631
|
assert not zero_out_calculated_vars or not calc_all_already_called
|
632
632
|
# check validity of variable_str parameter
|
633
633
|
if variable_str not in Calculator.MTR_VALID_VARIABLES:
|
@@ -824,7 +824,9 @@ class Calculator():
|
|
824
824
|
-------
|
825
825
|
graph that is a bokeh.plotting figure object
|
826
826
|
"""
|
827
|
-
# pylint: disable=too-many-arguments,too-many-
|
827
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
828
|
+
# pylint: disable=too-many-locals
|
829
|
+
|
828
830
|
# check that two Calculator objects are comparable
|
829
831
|
assert isinstance(calc, Calculator)
|
830
832
|
assert calc.current_year == self.current_year
|
@@ -833,9 +835,8 @@ class Calculator():
|
|
833
835
|
assert mars == 'ALL' or 1 <= mars <= 4
|
834
836
|
# check validity of income_measure
|
835
837
|
assert income_measure in ('expanded_income', 'agi', 'wages')
|
836
|
-
|
837
|
-
|
838
|
-
elif income_measure == 'agi':
|
838
|
+
income_variable = 'expanded_income'
|
839
|
+
if income_measure == 'agi':
|
839
840
|
income_variable = 'c00100'
|
840
841
|
elif income_measure == 'wages':
|
841
842
|
income_variable = 'e00200'
|
@@ -848,15 +849,15 @@ class Calculator():
|
|
848
849
|
(mtr2_ptax, mtr2_itax,
|
849
850
|
mtr2_combined) = calc.mtr(variable_str=mtr_variable,
|
850
851
|
wrt_full_compensation=mtr_wrt_full_compen)
|
851
|
-
if mtr_measure == '
|
852
|
-
mtr1 = mtr1_combined
|
853
|
-
mtr2 = mtr2_combined
|
854
|
-
elif mtr_measure == 'itax':
|
852
|
+
if mtr_measure == 'itax':
|
855
853
|
mtr1 = mtr1_itax
|
856
854
|
mtr2 = mtr2_itax
|
857
855
|
elif mtr_measure == 'ptax':
|
858
856
|
mtr1 = mtr1_ptax
|
859
857
|
mtr2 = mtr2_ptax
|
858
|
+
else:
|
859
|
+
mtr1 = mtr1_combined
|
860
|
+
mtr2 = mtr2_combined
|
860
861
|
# extract datafames needed by mtr_graph_data utility function
|
861
862
|
record_variables = ['s006', 'XTOT']
|
862
863
|
if mars != 'ALL':
|
@@ -1042,17 +1043,15 @@ class Calculator():
|
|
1042
1043
|
# construct data for graph
|
1043
1044
|
data = pch_graph_data(vdf, year=self.current_year,
|
1044
1045
|
pop_quantiles=pop_quantiles)
|
1045
|
-
del vdf
|
1046
|
-
del vdf1
|
1047
|
-
del vdf2
|
1048
1046
|
# construct figure from data
|
1049
|
-
|
1050
|
-
|
1051
|
-
|
1052
|
-
|
1053
|
-
|
1054
|
-
|
1055
|
-
|
1047
|
+
# (see comment at end of pch_graph_plot function in utils.py)
|
1048
|
+
fig = pch_graph_plot( # pylint: disable=assignment-from-no-return
|
1049
|
+
data,
|
1050
|
+
width=850,
|
1051
|
+
height=500,
|
1052
|
+
xlabel='',
|
1053
|
+
ylabel='',
|
1054
|
+
title='')
|
1056
1055
|
return fig
|
1057
1056
|
|
1058
1057
|
REQUIRED_REFORM_KEYS = set(['policy'])
|
@@ -1101,7 +1100,7 @@ class Calculator():
|
|
1101
1100
|
suitable as input into the GrowDiff.update_growdiff method.
|
1102
1101
|
"""
|
1103
1102
|
# construct the composite dictionary
|
1104
|
-
param_dict =
|
1103
|
+
param_dict = {}
|
1105
1104
|
param_dict['policy'] = Policy.read_json_reform(reform)
|
1106
1105
|
param_dict['consumption'] = Consumption.read_json_update(assump)
|
1107
1106
|
for topkey in ['growdiff_baseline', 'growdiff_response']:
|
@@ -1165,7 +1164,7 @@ class Calculator():
|
|
1165
1164
|
return [line]
|
1166
1165
|
# all text does not fix on one line
|
1167
1166
|
first_line = True
|
1168
|
-
line_list =
|
1167
|
+
line_list = []
|
1169
1168
|
words = text.split()
|
1170
1169
|
while words:
|
1171
1170
|
if first_line:
|
@@ -1189,20 +1188,20 @@ class Calculator():
|
|
1189
1188
|
baseline.set_year(year)
|
1190
1189
|
updated.set_year(year)
|
1191
1190
|
assert set(baseline.keys()) == set(updated.keys())
|
1192
|
-
params_with_diff =
|
1191
|
+
params_with_diff = []
|
1193
1192
|
for pname in baseline.keys():
|
1194
1193
|
upda_value = getattr(updated, pname)
|
1195
1194
|
base_value = getattr(baseline, pname)
|
1196
1195
|
is_array = isinstance(upda_value, np.ndarray)
|
1197
1196
|
if (
|
1198
1197
|
(is_array and not np.allclose(upda_value, base_value))
|
1199
|
-
or (is_array
|
1198
|
+
or (is_array is False and upda_value != base_value)
|
1200
1199
|
):
|
1201
1200
|
params_with_diff.append(pname)
|
1202
1201
|
if params_with_diff:
|
1203
1202
|
mdata_base = baseline.specification(meta_data=True)
|
1204
1203
|
# write year
|
1205
|
-
doc += '{}:\n'
|
1204
|
+
doc += f'{year}:\n'
|
1206
1205
|
for pname in sorted(params_with_diff):
|
1207
1206
|
# write updated value line
|
1208
1207
|
pval = getattr(updated, pname).tolist()[0]
|
@@ -1211,7 +1210,7 @@ class Calculator():
|
|
1211
1210
|
pval = [bool(item) for item in pval]
|
1212
1211
|
else:
|
1213
1212
|
pval = bool(pval)
|
1214
|
-
doc += ' {} : {}\n'
|
1213
|
+
doc += f' {pname} : {pval}\n'
|
1215
1214
|
# ... write optional param-vector-index line
|
1216
1215
|
if isinstance(pval, list):
|
1217
1216
|
labels = paramtools.consistent_labels(
|
@@ -1223,13 +1222,15 @@ class Calculator():
|
|
1223
1222
|
label = _label
|
1224
1223
|
break
|
1225
1224
|
if label:
|
1225
|
+
# pylint: disable=protected-access
|
1226
1226
|
lv = baseline._stateless_label_grid[label]
|
1227
|
+
# pylint: enable=protected-access
|
1227
1228
|
lv = [
|
1228
1229
|
str(item) for item in lv
|
1229
1230
|
]
|
1230
1231
|
doc += ' ' * (
|
1231
1232
|
4 + len(pname)
|
1232
|
-
) + '{}\n'
|
1233
|
+
) + f'{lv}\n'
|
1233
1234
|
# ... write param-name line
|
1234
1235
|
name = mdata_base[pname]['title']
|
1235
1236
|
for line in lines('name: ' + name, 6):
|
@@ -1247,7 +1248,7 @@ class Calculator():
|
|
1247
1248
|
pval = [bool(item) for item in pval]
|
1248
1249
|
elif ptype == 'bool':
|
1249
1250
|
pval = bool(pval)
|
1250
|
-
doc += ' baseline_value: {}\n'
|
1251
|
+
doc += f' baseline_value: {pval}\n'
|
1251
1252
|
else: # if baseline is GrowDiff object
|
1252
1253
|
# each GrowDiff parameter has zero as default value
|
1253
1254
|
doc += ' baseline_value: 0.0\n'
|
@@ -1399,7 +1400,7 @@ class Calculator():
|
|
1399
1400
|
item_phaseout = self.array('c21040').copy()
|
1400
1401
|
item_component_variable_names = ['c17000', 'c18300', 'c19200',
|
1401
1402
|
'c19700', 'c20500', 'c20800']
|
1402
|
-
item_cvar =
|
1403
|
+
item_cvar = {}
|
1403
1404
|
for cvname in item_component_variable_names:
|
1404
1405
|
item_cvar[cvname] = self.array(cvname).copy()
|
1405
1406
|
self.zeroarray('c04470')
|
taxcalc/cli/tc.py
CHANGED
@@ -23,7 +23,8 @@ def cli_tc_main():
|
|
23
23
|
Contains command-line interface (CLI) to Tax-Calculator TaxCalcIO class.
|
24
24
|
"""
|
25
25
|
# pylint: disable=too-many-statements,too-many-branches
|
26
|
-
# pylint: disable=too-many-return-statements
|
26
|
+
# pylint: disable=too-many-return-statements,too-many-locals
|
27
|
+
|
27
28
|
# parse command-line arguments:
|
28
29
|
usage_str = 'tc INPUT TAXYEAR {}{}{}{}{}'.format(
|
29
30
|
'[--help]\n',
|
@@ -254,12 +255,10 @@ def _compare_test_output_files():
|
|
254
255
|
Private function that compares expected and actual tc --test output files;
|
255
256
|
returns 0 if pass test, otherwise returns 1.
|
256
257
|
"""
|
257
|
-
|
258
|
-
|
259
|
-
|
260
|
-
|
261
|
-
ACTUAL_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8'
|
262
|
-
).readlines()
|
258
|
+
with open(EXPECTED_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8') as efile:
|
259
|
+
explines = efile.readlines()
|
260
|
+
with open(ACTUAL_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8') as afile:
|
261
|
+
actlines = afile.readlines()
|
263
262
|
if ''.join(explines) == ''.join(actlines):
|
264
263
|
sys.stdout.write('PASSED TEST\n')
|
265
264
|
retcode = 0
|
taxcalc/consumption.py
CHANGED
@@ -68,10 +68,10 @@ class Consumption(Parameters):
|
|
68
68
|
parameters are one
|
69
69
|
"""
|
70
70
|
for var in Consumption.RESPONSE_VARS:
|
71
|
-
if getattr(self, 'MPC_{}'
|
71
|
+
if getattr(self, f'MPC_{var}') > 0.0:
|
72
72
|
return True
|
73
73
|
for var in Consumption.BENEFIT_VARS:
|
74
|
-
if getattr(self, 'BEN_{}_value'
|
74
|
+
if getattr(self, f'BEN_{var}_value') < 1.0:
|
75
75
|
return True
|
76
76
|
return False
|
77
77
|
|
@@ -84,12 +84,17 @@ class Consumption(Parameters):
|
|
84
84
|
raise ValueError('records is not a Records object')
|
85
85
|
for var in Consumption.RESPONSE_VARS:
|
86
86
|
records_var = getattr(records, var)
|
87
|
-
mpc_var = getattr(self, 'MPC_{}'
|
87
|
+
mpc_var = getattr(self, f'MPC_{var}')
|
88
88
|
records_var[:] += mpc_var * income_change
|
89
89
|
|
90
90
|
def benval_params(self):
|
91
91
|
"""
|
92
92
|
Returns list of BEN_*_value parameter values
|
93
93
|
"""
|
94
|
-
return [getattr(self, 'BEN_{}_value'
|
94
|
+
return [getattr(self, f'BEN_{var}_value')
|
95
95
|
for var in Consumption.BENEFIT_VARS]
|
96
|
+
|
97
|
+
def set_rates(self):
|
98
|
+
"""
|
99
|
+
Consumption class has no parameter indexing rates.
|
100
|
+
"""
|
taxcalc/data.py
CHANGED
@@ -63,10 +63,7 @@ class Data():
|
|
63
63
|
-------
|
64
64
|
class instance: Data
|
65
65
|
"""
|
66
|
-
#
|
67
|
-
# pylint: disable=invalid-name
|
68
|
-
# suppress pylint warnings about too many class instance attributes:
|
69
|
-
# pylint: disable=too-many-instance-attributes
|
66
|
+
# pylint: disable=too-many-instance-attributes,invalid-name
|
70
67
|
|
71
68
|
__metaclass__ = abc.ABCMeta
|
72
69
|
|
@@ -75,6 +72,8 @@ class Data():
|
|
75
72
|
|
76
73
|
def __init__(self, data, start_year, gfactors=None,
|
77
74
|
weights=None, weights_scale=0.01):
|
75
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
76
|
+
|
78
77
|
# initialize data variable info sets and read variable information
|
79
78
|
self.INTEGER_READ_VARS = set()
|
80
79
|
self.MUST_READ_VARS = set()
|
@@ -175,12 +174,13 @@ class Data():
|
|
175
174
|
file_path = os.path.join(self.VARINFO_FILE_PATH,
|
176
175
|
self.VARINFO_FILE_NAME)
|
177
176
|
if os.path.isfile(file_path):
|
178
|
-
with open(file_path) as pfile:
|
177
|
+
with open(file_path, 'r', encoding='utf-8') as pfile:
|
179
178
|
json_text = pfile.read()
|
180
179
|
vardict = json_to_dict(json_text)
|
181
|
-
else: # find file in
|
182
|
-
vardict = read_egg_json(
|
183
|
-
self.VARINFO_FILE_NAME
|
180
|
+
else: # find file in taxcalc package
|
181
|
+
vardict = read_egg_json( # pragma: no cover
|
182
|
+
self.VARINFO_FILE_NAME
|
183
|
+
)
|
184
184
|
self.INTEGER_READ_VARS = set(k for k, v in vardict['read'].items()
|
185
185
|
if v['type'] == 'int')
|
186
186
|
FLOAT_READ_VARS = set(k for k, v in vardict['read'].items()
|
taxcalc/decorators.py
CHANGED
@@ -49,7 +49,7 @@ class GetReturnNode(ast.NodeVisitor):
|
|
49
49
|
"""
|
50
50
|
A NodeVisitor to get the return tuple names from a calc-style function.
|
51
51
|
"""
|
52
|
-
def visit_Return(self, node): # pylint: disable=invalid-name
|
52
|
+
def visit_Return(self, node): # pylint: disable=invalid-name
|
53
53
|
"""
|
54
54
|
visit_Return is used by NodeVisitor.visit method.
|
55
55
|
"""
|
@@ -89,7 +89,7 @@ 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("def ap_func({
|
92
|
+
fstr.write(f"def ap_func({','.join(out_args + in_args)}):\n")
|
93
93
|
fstr.write(" for i in range(len(x_0)):\n")
|
94
94
|
out_index = [x + "[i]" for x in out_args]
|
95
95
|
in_index = []
|
@@ -257,7 +257,7 @@ def iterate_jit(parameters=None, **kwargs):
|
|
257
257
|
in_args = inspect.getfullargspec(func).args
|
258
258
|
# Get the numba.jit arguments
|
259
259
|
jit_args_list = inspect.getfullargspec(JIT).args + ['nopython']
|
260
|
-
kwargs_for_jit =
|
260
|
+
kwargs_for_jit = {}
|
261
261
|
for key, val in kwargs.items():
|
262
262
|
if key in jit_args_list:
|
263
263
|
kwargs_for_jit[key] = val
|
taxcalc/growdiff.py
CHANGED
taxcalc/growfactors.py
CHANGED
@@ -165,6 +165,6 @@ class GrowFactors():
|
|
165
165
|
msg = 'cannot update growfactors after they have been used'
|
166
166
|
raise ValueError(msg)
|
167
167
|
assert name in GrowFactors.VALID_NAMES
|
168
|
-
if
|
168
|
+
if self.first_year <= year <= self.last_year:
|
169
169
|
assert isinstance(diff, float)
|
170
170
|
self.gfdf.loc[year, name] += diff
|