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
@@ -1,5 +1,5 @@
|
|
1
1
|
TABLE for EITC
|
2
|
-
|
2
|
+
AGIcategory T-C SOI %diff
|
3
3
|
[-9e+99, 1) 0.014 0.210 -93.2
|
4
4
|
[1, 5000) 1.555 1.184 +31.3
|
5
5
|
[5000, 10000) 6.132 7.156 -14.3
|
@@ -21,7 +21,7 @@ AGI category T-C SOI %diff
|
|
21
21
|
[10000000, 9e+99) 0.000 0.000 +nan
|
22
22
|
ALL 54.894 68.525 -19.9
|
23
23
|
TABLE for FCTC
|
24
|
-
|
24
|
+
AGIcategory T-C SOI %diff
|
25
25
|
[-9e+99, 1) 0.005 0.130 -96.0
|
26
26
|
[1, 5000) 0.083 0.079 +4.4
|
27
27
|
[5000, 10000) 1.118 1.474 -24.2
|
@@ -43,7 +43,7 @@ AGI category T-C SOI %diff
|
|
43
43
|
[10000000, 9e+99) 0.000 0.000 +nan
|
44
44
|
ALL 56.073 53.690 +4.4
|
45
45
|
TABLE for NIIT
|
46
|
-
|
46
|
+
AGIcategory T-C SOI %diff
|
47
47
|
[-9e+99, 1) 0.000 0.000 -100.0
|
48
48
|
[1, 5000) 0.000 0.000 +nan
|
49
49
|
[5000, 10000) 0.000 0.000 +nan
|
@@ -65,7 +65,7 @@ AGI category T-C SOI %diff
|
|
65
65
|
[10000000, 9e+99) 4.187 8.273 -49.4
|
66
66
|
ALL 6.179 22.043 -72.0
|
67
67
|
TABLE for ITAX
|
68
|
-
|
68
|
+
AGIcategory T-C SOI %diff
|
69
69
|
[-9e+99, 1) -0.006 0.242 -102.3
|
70
70
|
[1, 5000) -1.529 0.041 -3838.6
|
71
71
|
[5000, 10000) -6.862 0.368 -1964.8
|
@@ -87,7 +87,7 @@ AGI category T-C SOI %diff
|
|
87
87
|
[10000000, 9e+99) 49.547 139.611 -64.5
|
88
88
|
ALL 969.859 1457.891 -33.5
|
89
89
|
TABLE for SETAX
|
90
|
-
|
90
|
+
AGIcategory T-C SOI %diff
|
91
91
|
[-9e+99, 1) 0.014 0.656 -97.9
|
92
92
|
[1, 5000) 0.101 0.555 -81.8
|
93
93
|
[5000, 10000) 0.319 1.896 -83.2
|
@@ -109,7 +109,7 @@ AGI category T-C SOI %diff
|
|
109
109
|
[10000000, 9e+99) 0.073 0.638 -88.6
|
110
110
|
ALL 48.503 60.174 -19.4
|
111
111
|
TABLE for AMTAX
|
112
|
-
|
112
|
+
AGIcategory T-C SOI %diff
|
113
113
|
[-9e+99, 1) 0.000 0.022 -100.0
|
114
114
|
[1, 5000) 0.000 0.000 -100.0
|
115
115
|
[5000, 10000) 0.000 0.000 +nan
|
@@ -1,5 +1,5 @@
|
|
1
1
|
TABLE for EITC
|
2
|
-
|
2
|
+
AGIcategory T-C SOI %diff
|
3
3
|
[-9e+99, 1) 0.174 0.210 -17.5
|
4
4
|
[1, 5000) 1.495 1.184 +26.2
|
5
5
|
[5000, 10000) 5.880 7.156 -17.8
|
@@ -21,7 +21,7 @@ AGI category T-C SOI %diff
|
|
21
21
|
[10000000, 9e+99) 0.000 0.000 +nan
|
22
22
|
ALL 68.057 68.525 -0.7
|
23
23
|
TABLE for FCTC
|
24
|
-
|
24
|
+
AGIcategory T-C SOI %diff
|
25
25
|
[-9e+99, 1) 0.145 0.130 +11.2
|
26
26
|
[1, 5000) 0.115 0.079 +44.7
|
27
27
|
[5000, 10000) 1.084 1.474 -26.5
|
@@ -43,7 +43,7 @@ AGI category T-C SOI %diff
|
|
43
43
|
[10000000, 9e+99) 0.000 0.000 +nan
|
44
44
|
ALL 53.276 53.690 -0.8
|
45
45
|
TABLE for NIIT
|
46
|
-
|
46
|
+
AGIcategory T-C SOI %diff
|
47
47
|
[-9e+99, 1) 0.000 0.000 -100.0
|
48
48
|
[1, 5000) 0.000 0.000 +nan
|
49
49
|
[5000, 10000) 0.000 0.000 +nan
|
@@ -65,7 +65,7 @@ AGI category T-C SOI %diff
|
|
65
65
|
[10000000, 9e+99) 8.112 8.273 -1.9
|
66
66
|
ALL 27.149 22.043 +23.2
|
67
67
|
TABLE for ITAX
|
68
|
-
|
68
|
+
AGIcategory T-C SOI %diff
|
69
69
|
[-9e+99, 1) 4.502 0.242 +1756.7
|
70
70
|
[1, 5000) -1.776 0.041 -4442.6
|
71
71
|
[5000, 10000) -5.779 0.368 -1670.5
|
@@ -87,7 +87,7 @@ AGI category T-C SOI %diff
|
|
87
87
|
[10000000, 9e+99) 97.259 139.611 -30.3
|
88
88
|
ALL 1462.385 1457.891 +0.3
|
89
89
|
TABLE for SETAX
|
90
|
-
|
90
|
+
AGIcategory T-C SOI %diff
|
91
91
|
[-9e+99, 1) 0.761 0.656 +16.1
|
92
92
|
[1, 5000) 0.626 0.555 +12.7
|
93
93
|
[5000, 10000) 1.633 1.896 -13.8
|
@@ -109,7 +109,7 @@ AGI category T-C SOI %diff
|
|
109
109
|
[10000000, 9e+99) 0.033 0.638 -94.8
|
110
110
|
ALL 49.779 60.174 -17.3
|
111
111
|
TABLE for AMTAX
|
112
|
-
|
112
|
+
AGIcategory T-C SOI %diff
|
113
113
|
[-9e+99, 1) 0.012 0.022 -45.5
|
114
114
|
[1, 5000) 0.000 0.000 -68.2
|
115
115
|
[5000, 10000) 0.000 0.000 +nan
|
taxcalc/tests/conftest.py
CHANGED
@@ -1,3 +1,7 @@
|
|
1
|
+
"""
|
2
|
+
The pytest configuration file.
|
3
|
+
"""
|
4
|
+
|
1
5
|
import os
|
2
6
|
import time
|
3
7
|
import glob
|
@@ -12,63 +16,61 @@ numpy.seterr(all='raise')
|
|
12
16
|
|
13
17
|
@pytest.fixture
|
14
18
|
def skip_jit(monkeypatch):
|
19
|
+
"""Fixture docstring"""
|
15
20
|
monkeypatch.setenv("TESTING", "True")
|
16
21
|
yield
|
17
22
|
|
18
23
|
|
19
|
-
@pytest.fixture(scope='session')
|
20
|
-
def
|
24
|
+
@pytest.fixture(scope='session', name='tests_path')
|
25
|
+
def tests_path_fixture():
|
26
|
+
"""Fixture docstring"""
|
21
27
|
return os.path.abspath(os.path.dirname(__file__))
|
22
28
|
|
23
29
|
|
24
|
-
@pytest.fixture(scope='session')
|
25
|
-
def
|
30
|
+
@pytest.fixture(scope='session', name='cps_path')
|
31
|
+
def cps_path_fixture(tests_path):
|
32
|
+
"""Fixture docstring"""
|
26
33
|
return os.path.join(tests_path, '..', 'cps.csv.gz')
|
27
34
|
|
28
35
|
|
29
|
-
@pytest.fixture(scope='session')
|
30
|
-
def
|
36
|
+
@pytest.fixture(scope='session', name='cps_fullsample')
|
37
|
+
def cps_fullsample_fixture(cps_path):
|
38
|
+
"""Fixture docstring"""
|
31
39
|
return pandas.read_csv(cps_path)
|
32
40
|
|
33
41
|
|
34
42
|
@pytest.fixture(scope='session')
|
35
43
|
def cps_subsample(cps_fullsample):
|
44
|
+
"""Fixture docstring"""
|
36
45
|
# draw smaller cps.csv subsample than in test_cpscsv.py
|
37
46
|
return cps_fullsample.sample(frac=0.01, random_state=123456789)
|
38
47
|
|
39
48
|
|
40
|
-
@pytest.fixture(scope='session')
|
41
|
-
def
|
49
|
+
@pytest.fixture(scope='session', name='puf_path')
|
50
|
+
def puf_path_fixture(tests_path):
|
51
|
+
"""Fixture docstring"""
|
42
52
|
return os.path.join(tests_path, '..', '..', 'puf.csv')
|
43
53
|
|
44
54
|
|
45
|
-
@pytest.fixture(scope='session')
|
46
|
-
def
|
55
|
+
@pytest.fixture(scope='session', name='puf_fullsample')
|
56
|
+
def puf_fullsample_fixture(puf_path):
|
57
|
+
"""Fixture docstring"""
|
47
58
|
return pandas.read_csv(puf_path)
|
48
59
|
|
49
60
|
|
50
61
|
@pytest.fixture(scope='session')
|
51
62
|
def puf_subsample(puf_fullsample):
|
63
|
+
"""Fixture docstring"""
|
52
64
|
# draw same puf.csv subsample as in test_pufcsv.py
|
53
65
|
return puf_fullsample.sample(frac=0.05, random_state=2222)
|
54
66
|
|
55
67
|
|
56
|
-
@pytest.fixture(scope='session')
|
57
|
-
def tmd_path(tests_path):
|
58
|
-
return os.path.join(tests_path, '..', '..', 'tmd.csv')
|
59
|
-
|
60
|
-
|
61
|
-
@pytest.fixture(scope='session')
|
62
|
-
def tmd_fullsample(tmd_path):
|
63
|
-
return pandas.read_csv(tmd_path)
|
64
|
-
|
65
|
-
|
66
68
|
@pytest.fixture(scope='session', name='test_reforms_init')
|
67
69
|
def fixture_test_reforms(tests_path):
|
68
70
|
"""
|
69
71
|
Execute logic only once rather than on each pytest-xdist node.
|
70
72
|
"""
|
71
|
-
# pylint: disable=too-many-locals
|
73
|
+
# pylint: disable=too-many-locals,too-many-statements
|
72
74
|
num_reforms = 64 # must be same as NUM_REFORMS in test_reforms.py
|
73
75
|
handling_logic = ('PYTEST_XDIST_WORKER' not in os.environ or
|
74
76
|
os.environ['PYTEST_XDIST_WORKER'] == 'gw0')
|
@@ -86,7 +88,7 @@ def fixture_test_reforms(tests_path):
|
|
86
88
|
for afile in glob.glob(afiles):
|
87
89
|
os.remove(afile)
|
88
90
|
# create reforms_actual_init file
|
89
|
-
with open(initfile, 'w') as ifile:
|
91
|
+
with open(initfile, 'w', encoding='utf-8') as ifile:
|
90
92
|
ifile.write('test_reforms initialization done')
|
91
93
|
else:
|
92
94
|
num_waits = 0
|
@@ -107,26 +109,26 @@ def fixture_test_reforms(tests_path):
|
|
107
109
|
# compare actual and expected results for each test
|
108
110
|
# ... read expected results
|
109
111
|
efile_path = os.path.join(tests_path, 'reforms_expect.csv')
|
110
|
-
with open(efile_path, 'r') as efile:
|
112
|
+
with open(efile_path, 'r', encoding='utf-8') as efile:
|
111
113
|
expect_lines = efile.readlines()
|
112
114
|
# ... compare actual and expected results for each test
|
113
115
|
diffs = False
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
116
|
+
with open(actfile_path, 'w', encoding='utf-8') as actfile:
|
117
|
+
actfile.write('rid,res1,res2,res3,res4\n')
|
118
|
+
idx = 1 # expect_lines list index
|
119
|
+
for rnum in range(1, num_reforms + 1):
|
120
|
+
afile_path = os.path.join(
|
121
|
+
tests_path, f'reform_actual_{rnum}.csv'
|
122
|
+
)
|
123
|
+
with open(afile_path, 'r', encoding='utf-8') as afile:
|
124
|
+
actual_lines = afile.readlines()
|
125
|
+
os.remove(afile_path)
|
126
|
+
actfile.write(actual_lines[1])
|
127
|
+
actual = [float(itm) for itm in actual_lines[1].split(',')]
|
128
|
+
expect = [float(itm) for itm in expect_lines[idx].split(',')]
|
129
|
+
if not numpy.allclose(actual, expect, atol=0.0, rtol=0.0):
|
130
|
+
diffs = True
|
131
|
+
idx += 1
|
130
132
|
# remove init file
|
131
133
|
os.remove(initfile)
|
132
134
|
# remove 'reforms_actual.csv' file if no actual-vs-expect diffs
|
@@ -139,5 +141,4 @@ def fixture_test_reforms(tests_path):
|
|
139
141
|
msg += '--- AND RERUN TEST. ---\n'
|
140
142
|
msg += '-------------------------------------------------\n'
|
141
143
|
raise ValueError(msg)
|
142
|
-
|
143
|
-
os.remove(actfile_path)
|
144
|
+
os.remove(actfile_path)
|
taxcalc/tests/test_4package.py
CHANGED
@@ -7,10 +7,10 @@ Tests for package existence and dependencies consistency.
|
|
7
7
|
|
8
8
|
import os
|
9
9
|
import re
|
10
|
+
import ast
|
10
11
|
import subprocess
|
11
12
|
import yaml
|
12
13
|
import pytest
|
13
|
-
import ast
|
14
14
|
|
15
15
|
|
16
16
|
def extract_install_requires(setup_py_content):
|
@@ -24,8 +24,9 @@ def extract_install_requires(setup_py_content):
|
|
24
24
|
list: A list of package requirements
|
25
25
|
"""
|
26
26
|
# Use regex to find the install_requires list
|
27
|
-
match = re.search(
|
28
|
-
|
27
|
+
match = re.search(
|
28
|
+
r'"install_requires"\s*:\s*\[([^\]]+)\]', setup_py_content, re.DOTALL
|
29
|
+
)
|
29
30
|
if match:
|
30
31
|
# Extract the contents of the list and split into packages
|
31
32
|
packages_str = match.group(1)
|
@@ -50,7 +51,7 @@ def test_for_package_existence():
|
|
50
51
|
out = subprocess.check_output(['conda', 'list', 'taxcalc']).decode('ascii')
|
51
52
|
envless_out = out.replace('taxcalc-dev', 'environment')
|
52
53
|
if re.search('taxcalc', envless_out) is not None:
|
53
|
-
assert 'taxcalc package
|
54
|
+
assert False, 'ERROR: taxcalc package is installed'
|
54
55
|
|
55
56
|
|
56
57
|
def test_for_consistency(tests_path):
|
@@ -58,6 +59,7 @@ def test_for_consistency(tests_path):
|
|
58
59
|
Ensure that there is consistency between environment.yml dependencies
|
59
60
|
and conda.recipe/meta.yaml requirements.
|
60
61
|
"""
|
62
|
+
# pylint: disable=too-many-locals
|
61
63
|
dev_pkgs = set([
|
62
64
|
'pytest',
|
63
65
|
'pytest-xdist',
|
@@ -71,7 +73,7 @@ def test_for_consistency(tests_path):
|
|
71
73
|
# read conda.recipe/meta.yaml requirements
|
72
74
|
meta_file = os.path.join(tests_path, '..', '..',
|
73
75
|
'conda.recipe', 'meta.yaml')
|
74
|
-
with open(meta_file, 'r') as stream:
|
76
|
+
with open(meta_file, 'r', encoding='utf-8') as stream:
|
75
77
|
meta = yaml.safe_load(stream)
|
76
78
|
bld = set(meta['requirements']['build'])
|
77
79
|
run = set(meta['requirements']['run'])
|
@@ -80,7 +82,7 @@ def test_for_consistency(tests_path):
|
|
80
82
|
# read environment.yml dependencies
|
81
83
|
envr_file = os.path.join(tests_path, '..', '..',
|
82
84
|
'environment.yml')
|
83
|
-
with open(envr_file, 'r') as stream:
|
85
|
+
with open(envr_file, 'r', encoding='utf-8') as stream:
|
84
86
|
envr = yaml.safe_load(stream)
|
85
87
|
|
86
88
|
env = []
|
@@ -97,7 +99,7 @@ def test_for_consistency(tests_path):
|
|
97
99
|
# Read the setup.py file and extract the install_requires list
|
98
100
|
setup_file = os.path.join(tests_path, '..', '..',
|
99
101
|
'setup.py')
|
100
|
-
with open(setup_file, 'r') as f:
|
102
|
+
with open(setup_file, 'r', encoding='utf-8') as f:
|
101
103
|
setup_py_content = f.read()
|
102
104
|
setup = set(extract_install_requires(setup_py_content))
|
103
105
|
# confirm that setup.py
|
taxcalc/tests/test_benefits.py
CHANGED
@@ -16,8 +16,9 @@ import os
|
|
16
16
|
import pytest
|
17
17
|
import numpy as np
|
18
18
|
import pandas as pd
|
19
|
-
|
20
|
-
from taxcalc import
|
19
|
+
from taxcalc.policy import Policy
|
20
|
+
from taxcalc.records import Records
|
21
|
+
from taxcalc.calculator import Calculator
|
21
22
|
|
22
23
|
|
23
24
|
@pytest.mark.benefits
|
@@ -33,11 +34,11 @@ def test_benefits(tests_path, cps_fullsample):
|
|
33
34
|
start_year = recs.current_year
|
34
35
|
calc = Calculator(policy=Policy(), records=recs, verbose=False)
|
35
36
|
assert calc.current_year == start_year
|
36
|
-
year_list =
|
37
|
-
bname_list =
|
38
|
-
benamt_list =
|
39
|
-
bencnt_list =
|
40
|
-
benavg_list =
|
37
|
+
year_list = []
|
38
|
+
bname_list = []
|
39
|
+
benamt_list = []
|
40
|
+
bencnt_list = []
|
41
|
+
benavg_list = []
|
41
42
|
for year in range(start_year, 2034 + 1):
|
42
43
|
calc.advance_to_year(year)
|
43
44
|
size = calc.array('XTOT')
|
@@ -46,7 +47,7 @@ def test_benefits(tests_path, cps_fullsample):
|
|
46
47
|
# (head counts include all members of filing unit receiving a benefit,
|
47
48
|
# which means benavg is f.unit benefit amount divided by f.unit size)
|
48
49
|
for bname in benefit_names:
|
49
|
-
ben = calc.array('{}_ben'
|
50
|
+
ben = calc.array(f'{bname}_ben')
|
50
51
|
benamt = round((ben * wght).sum() * 1e-9, 3)
|
51
52
|
bencnt = round((size[ben > 0] * wght[ben > 0]).sum() * 1e-6, 3)
|
52
53
|
benavg = round(benamt / bencnt, 1)
|
@@ -8,10 +8,10 @@ Tests for Tax-Calculator calcfunctions.py logic.
|
|
8
8
|
import os
|
9
9
|
import re
|
10
10
|
import ast
|
11
|
-
from taxcalc import Records # pylint: disable=import-error
|
12
|
-
from taxcalc import calcfunctions
|
13
11
|
import numpy as np
|
14
12
|
import pytest
|
13
|
+
from taxcalc.records import Records
|
14
|
+
from taxcalc import calcfunctions
|
15
15
|
|
16
16
|
|
17
17
|
class GetFuncDefs(ast.NodeVisitor):
|
@@ -23,10 +23,10 @@ class GetFuncDefs(ast.NodeVisitor):
|
|
23
23
|
GetFuncDefs class constructor
|
24
24
|
"""
|
25
25
|
self.fname = ''
|
26
|
-
self.fnames =
|
27
|
-
self.fargs =
|
28
|
-
self.cvars =
|
29
|
-
self.rvars =
|
26
|
+
self.fnames = [] # function name (fname) list
|
27
|
+
self.fargs = {} # lists of function arguments indexed by fname
|
28
|
+
self.cvars = {} # lists of calc vars in function indexed by fname
|
29
|
+
self.rvars = {} # lists of function return vars indexed by fname
|
30
30
|
|
31
31
|
def visit_Module(self, node): # pylint: disable=invalid-name
|
32
32
|
"""
|
@@ -41,10 +41,10 @@ class GetFuncDefs(ast.NodeVisitor):
|
|
41
41
|
"""
|
42
42
|
self.fname = node.name
|
43
43
|
self.fnames.append(self.fname)
|
44
|
-
self.fargs[self.fname] =
|
44
|
+
self.fargs[self.fname] = []
|
45
45
|
for anode in ast.iter_child_nodes(node.args):
|
46
46
|
self.fargs[self.fname].append(anode.arg)
|
47
|
-
self.cvars[self.fname] =
|
47
|
+
self.cvars[self.fname] = []
|
48
48
|
for bodynode in node.body:
|
49
49
|
if isinstance(bodynode, ast.Return):
|
50
50
|
continue # skip function's Return node
|
@@ -84,8 +84,10 @@ def test_calc_and_used_vars(tests_path):
|
|
84
84
|
"""
|
85
85
|
# pylint: disable=too-many-locals
|
86
86
|
funcpath = os.path.join(tests_path, '..', 'calcfunctions.py')
|
87
|
+
with open(funcpath, 'r', encoding='utf-8') as funcfile:
|
88
|
+
funcfile_text = funcfile.read()
|
87
89
|
gfd = GetFuncDefs()
|
88
|
-
fnames, fargs, cvars, rvars = gfd.visit(ast.parse(
|
90
|
+
fnames, fargs, cvars, rvars = gfd.visit(ast.parse(funcfile_text))
|
89
91
|
# Test (1):
|
90
92
|
# .. create set of vars that are actually calculated in calcfunctions.py
|
91
93
|
all_cvars = set()
|
@@ -106,7 +108,7 @@ def test_calc_and_used_vars(tests_path):
|
|
106
108
|
'in calcfunctions.py\n')
|
107
109
|
for var in records_varinfo.CALCULATED_VARS - all_cvars:
|
108
110
|
found_error1 = True
|
109
|
-
msg1 += 'VAR NOT CALCULATED: {}\n'
|
111
|
+
msg1 += f'VAR NOT CALCULATED: {var}\n'
|
110
112
|
# Test (2):
|
111
113
|
faux_functions = ['EITCamount', 'ComputeBenefit', 'BenefitPrograms',
|
112
114
|
'BenefitSurtax', 'BenefitLimitation']
|
@@ -119,10 +121,10 @@ def test_calc_and_used_vars(tests_path):
|
|
119
121
|
if not crvars_set <= set(fargs[fname]):
|
120
122
|
found_error2 = True
|
121
123
|
for var in crvars_set - set(fargs[fname]):
|
122
|
-
msg2 += 'FUNCTION,VARIABLE: {} {}\n'
|
124
|
+
msg2 += f'FUNCTION,VARIABLE: {fname} {var}\n'
|
123
125
|
# Report errors for the two tests:
|
124
126
|
if found_error1 and found_error2:
|
125
|
-
raise ValueError('{}\n{}'
|
127
|
+
raise ValueError(f'{msg1}\n{msg2}')
|
126
128
|
if found_error1:
|
127
129
|
raise ValueError(msg1)
|
128
130
|
if found_error2:
|
@@ -135,7 +137,7 @@ def test_function_args_usage(tests_path):
|
|
135
137
|
function body.
|
136
138
|
"""
|
137
139
|
funcfilename = os.path.join(tests_path, '..', 'calcfunctions.py')
|
138
|
-
with open(funcfilename, 'r') as funcfile:
|
140
|
+
with open(funcfilename, 'r', encoding='utf-8') as funcfile:
|
139
141
|
fcontent = funcfile.read()
|
140
142
|
fcontent = re.sub('#.*', '', fcontent) # remove all '#...' comments
|
141
143
|
fcontent = re.sub('\n', ' ', fcontent) # replace EOL character with space
|
@@ -149,7 +151,7 @@ def test_function_args_usage(tests_path):
|
|
149
151
|
msg = ('Could not find function name, arguments, '
|
150
152
|
'and code portions in the following text:\n')
|
151
153
|
msg += '--------------------------------------------------------\n'
|
152
|
-
msg += '{}\n'
|
154
|
+
msg += f'{fcode}\n'
|
153
155
|
msg += '--------------------------------------------------------\n'
|
154
156
|
raise ValueError(msg)
|
155
157
|
fname = match.group(1)
|
@@ -161,11 +163,14 @@ def test_function_args_usage(tests_path):
|
|
161
163
|
arg = farg.strip()
|
162
164
|
if fbody.find(arg) < 0:
|
163
165
|
found_error = True
|
164
|
-
msg += 'FUNCTION,ARGUMENT= {} {}\n'
|
166
|
+
msg += f'FUNCTION,ARGUMENT= {fname} {arg}\n'
|
165
167
|
if found_error:
|
166
168
|
raise ValueError(msg)
|
167
169
|
|
168
170
|
|
171
|
+
# pylint: disable=invalid-name,unused-argument
|
172
|
+
|
173
|
+
|
169
174
|
def test_DependentCare(skip_jit):
|
170
175
|
"""
|
171
176
|
Tests the DependentCare function
|
@@ -199,7 +204,7 @@ tuple7 = (0, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 3, 1, 0, 0, 2,
|
|
199
204
|
tuple8 = (1, 200, STD_in, 44, 0, STD_Aged_in, 1000, 3, 0, 0, 0, 2,
|
200
205
|
True, 0, 100000, 1, Charity_max_in)
|
201
206
|
tuple9 = (1, 1000, STD_in, 44, 0, STD_Aged_in, 1000, 3, 0, 0, 0, 2,
|
202
|
-
True, 0,100000, 1, Charity_max_in)
|
207
|
+
True, 0, 100000, 1, Charity_max_in)
|
203
208
|
expected = [12000, 15800, 13800, 14400, 6000, 6000, 0, 1000, 1350]
|
204
209
|
|
205
210
|
|
@@ -224,22 +229,28 @@ def test_StdDed(test_tuple, expected_value, skip_jit):
|
|
224
229
|
assert np.allclose(avalue, expected_value), f"{avalue} != {expected_value}"
|
225
230
|
|
226
231
|
|
227
|
-
tuple1 = (120000, 10000, 15000, 100, 2000,
|
228
|
-
|
232
|
+
tuple1 = (120000, 10000, 15000, 100, 2000,
|
233
|
+
0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
234
|
+
400, 0, 0, 0, 0, 0, 0, None, None, None, None, None, None,
|
229
235
|
None, None, None, None, None)
|
230
|
-
tuple2 = (120000, 10000, 15000, 100, 2000,
|
236
|
+
tuple2 = (120000, 10000, 15000, 100, 2000,
|
237
|
+
0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
231
238
|
400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
|
232
239
|
None, None, None, None, None, None)
|
233
|
-
tuple3 = (120000, 150000, 15000, 100, 2000,
|
240
|
+
tuple3 = (120000, 150000, 15000, 100, 2000,
|
241
|
+
0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
234
242
|
400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
|
235
243
|
None, None, None, None, None, None)
|
236
|
-
tuple4 = (120000, 500000, 15000, 100, 2000,
|
244
|
+
tuple4 = (120000, 500000, 15000, 100, 2000,
|
245
|
+
0.06, 0.06, 0.015, 0.015, 0, 400000,
|
237
246
|
400, 2000, 0, 10000, 0, 0, 3000, None, None, None, None, None,
|
238
247
|
None, None, None, None, None, None)
|
239
|
-
tuple5 = (120000, 10000, 15000, 100, 2000,
|
248
|
+
tuple5 = (120000, 10000, 15000, 100, 2000,
|
249
|
+
0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
240
250
|
400, 300, 0, 0, 0, 0, 0, None, None, None, None, None,
|
241
251
|
None, None, None, None, None, None)
|
242
|
-
tuple6 = (120000, 10000, 15000, 100, 2000,
|
252
|
+
tuple6 = (120000, 10000, 15000, 100, 2000,
|
253
|
+
0.06, 0.06, 0.015, 0.015, 0, 99999999999,
|
243
254
|
400, 0, 0, 0, 0, -40000, 0, None, None, None, None, None,
|
244
255
|
None, None, None, None, None, None)
|
245
256
|
expected1 = (0, 4065, 4065, 0, 0, 3252, 25000, 10000, 15000, 10100,
|
@@ -254,6 +265,7 @@ expected5 = (300, 4065, 4065, 0, 0, 3285.3, 25300, 10279.1875, 15000,
|
|
254
265
|
10382, 17000)
|
255
266
|
expected6 = (-40000, 4065, 4065, 0, 0, 3252, 0, 0, 15000, 10100, 17000)
|
256
267
|
|
268
|
+
|
257
269
|
@pytest.mark.parametrize(
|
258
270
|
'test_input, expected_output', [
|
259
271
|
(tuple1, expected1),
|
@@ -272,7 +284,8 @@ def test_EI_PayrollTax(test_input, expected_output, skip_jit):
|
|
272
284
|
print('*INPUT:', test_input)
|
273
285
|
print('ACTUAL:', actual_output)
|
274
286
|
print('EXPECT:', expected_output)
|
275
|
-
assert
|
287
|
+
assert False, 'ERROR: ACTUAL != EXPECT'
|
288
|
+
|
276
289
|
|
277
290
|
def test_AfterTaxIncome(skip_jit):
|
278
291
|
'''
|
@@ -655,7 +668,7 @@ CTC_refundable = True
|
|
655
668
|
CTC_include17 = True
|
656
669
|
c07220 = 0 # actual value will be returned from function
|
657
670
|
odc = 0 # actual value will be returned from function
|
658
|
-
codtc_limited = 0
|
671
|
+
codtc_limited = 0 # actual value will be returned from function
|
659
672
|
tuple0 = (
|
660
673
|
age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
|
661
674
|
c05800, e07260, CR_ResidentialEnergy_hc,
|
@@ -673,8 +686,8 @@ expected0 = (0, 1000, 0)
|
|
673
686
|
|
674
687
|
|
675
688
|
@pytest.mark.parametrize(
|
676
|
-
'test_tuple,expected_value', [
|
677
|
-
|
689
|
+
'test_tuple,expected_value', [(tuple0, expected0)]
|
690
|
+
)
|
678
691
|
def test_ChildDepTaxCredit_2021(test_tuple, expected_value, skip_jit):
|
679
692
|
"""
|
680
693
|
Tests the ChildDepTaxCredit function
|
@@ -682,6 +695,7 @@ def test_ChildDepTaxCredit_2021(test_tuple, expected_value, skip_jit):
|
|
682
695
|
test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
|
683
696
|
assert np.allclose(test_value, expected_value)
|
684
697
|
|
698
|
+
|
685
699
|
# parameterization represents 2022 law
|
686
700
|
age_head = 45
|
687
701
|
age_spouse = 0
|
@@ -712,7 +726,7 @@ CTC_refundable = False
|
|
712
726
|
CTC_include17 = False
|
713
727
|
c07220 = 0 # actual value will be returned from function
|
714
728
|
odc = 0 # actual value will be returned from function
|
715
|
-
codtc_limited = 0
|
729
|
+
codtc_limited = 0 # actual value will be returned from function
|
716
730
|
tuple0 = (
|
717
731
|
age_head, age_spouse, nu18, n24, MARS, c00100, XTOT, num,
|
718
732
|
c05800, e07260, CR_ResidentialEnergy_hc,
|
@@ -739,6 +753,7 @@ def test_ChildDepTaxCredit_2022(test_tuple, expected_value, skip_jit):
|
|
739
753
|
test_value = calcfunctions.ChildDepTaxCredit(*test_tuple)
|
740
754
|
assert np.allclose(test_value, expected_value)
|
741
755
|
|
756
|
+
|
742
757
|
# parameterization represents 2021 law
|
743
758
|
CTC_new_c = 1000
|
744
759
|
CTC_new_rt = 0
|
@@ -762,7 +777,7 @@ c00100 = 1000
|
|
762
777
|
MARS = 4
|
763
778
|
ptax_oasdi = 0
|
764
779
|
c09200 = 0
|
765
|
-
ctc_new = 0
|
780
|
+
ctc_new = 0 # actual value will be returned from function
|
766
781
|
tuple0 = (
|
767
782
|
CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
|
768
783
|
CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
|
@@ -771,7 +786,8 @@ tuple0 = (
|
|
771
786
|
n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
|
772
787
|
c09200, ctc_new)
|
773
788
|
# output tuple is : (ctc_new)
|
774
|
-
expected0 =
|
789
|
+
expected0 = 0
|
790
|
+
|
775
791
|
|
776
792
|
@pytest.mark.parametrize(
|
777
793
|
'test_tuple,expected_value', [
|
@@ -783,6 +799,7 @@ def test_CTCnew_2021(test_tuple, expected_value, skip_jit):
|
|
783
799
|
test_value = calcfunctions.CTC_new(*test_tuple)
|
784
800
|
assert np.allclose(test_value, expected_value)
|
785
801
|
|
802
|
+
|
786
803
|
# parameterization represents 2022 law
|
787
804
|
CTC_new_c = 0
|
788
805
|
CTC_new_rt = 0
|
@@ -806,7 +823,7 @@ c00100 = 1000
|
|
806
823
|
MARS = 4
|
807
824
|
ptax_oasdi = 0
|
808
825
|
c09200 = 0
|
809
|
-
ctc_new = 0
|
826
|
+
ctc_new = 0 # actual value will be returned from function
|
810
827
|
tuple0 = (
|
811
828
|
CTC_new_c, CTC_new_rt, CTC_new_c_under6_bonus,
|
812
829
|
CTC_new_ps, CTC_new_prt, CTC_new_for_all, CTC_include17,
|
@@ -815,11 +832,12 @@ tuple0 = (
|
|
815
832
|
n24, nu06, age_head, age_spouse, nu18, c00100, MARS, ptax_oasdi,
|
816
833
|
c09200, ctc_new)
|
817
834
|
# output tuple is : (ctc_new)
|
818
|
-
expected0 =
|
835
|
+
expected0 = 0
|
836
|
+
|
819
837
|
|
820
838
|
@pytest.mark.parametrize(
|
821
|
-
'test_tuple,expected_value', [
|
822
|
-
|
839
|
+
'test_tuple,expected_value', [(tuple0, expected0)]
|
840
|
+
)
|
823
841
|
def test_CTCnew_2022(test_tuple, expected_value, skip_jit):
|
824
842
|
"""
|
825
843
|
Tests the CTCnew function
|
@@ -828,7 +846,7 @@ def test_CTCnew_2022(test_tuple, expected_value, skip_jit):
|
|
828
846
|
assert np.allclose(test_value, expected_value)
|
829
847
|
|
830
848
|
|
831
|
-
|
849
|
+
# parameters for next test
|
832
850
|
ymod1 = 19330 + 10200
|
833
851
|
c02500 = 0
|
834
852
|
c02900 = 0
|
@@ -859,8 +877,8 @@ expected0 = (19330, 0, 0)
|
|
859
877
|
|
860
878
|
|
861
879
|
@pytest.mark.parametrize(
|
862
|
-
'test_tuple,expected_value', [
|
863
|
-
|
880
|
+
'test_tuple,expected_value', [(tuple0, expected0)]
|
881
|
+
)
|
864
882
|
def test_AGI(test_tuple, expected_value, skip_jit):
|
865
883
|
"""
|
866
884
|
Tests the TaxInc function
|
@@ -868,4 +886,3 @@ def test_AGI(test_tuple, expected_value, skip_jit):
|
|
868
886
|
test_value = calcfunctions.AGI(*test_tuple)
|
869
887
|
print('Returned from agi function: ', test_value)
|
870
888
|
assert np.allclose(test_value, expected_value)
|
871
|
-
|