taxcalc 4.3.5__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 +14 -9
- taxcalc/data.py +8 -8
- taxcalc/decorators.py +3 -3
- taxcalc/growdiff.py +6 -6
- taxcalc/growfactors.py +1 -1
- taxcalc/parameters.py +91 -47
- taxcalc/policy.py +23 -7
- taxcalc/records.py +1 -0
- taxcalc/records_variables.json +6 -0
- taxcalc/reforms/ext.json +1 -1
- taxcalc/taxcalcio.py +88 -73
- 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 +47 -3
- taxcalc/tests/test_benefits.py +9 -8
- taxcalc/tests/test_calcfunctions.py +55 -38
- taxcalc/tests/test_calculator.py +14 -10
- taxcalc/tests/test_compare.py +44 -50
- taxcalc/tests/test_compatible_data.py +9 -7
- taxcalc/tests/test_consumption.py +41 -22
- taxcalc/tests/test_cpscsv.py +81 -31
- taxcalc/tests/test_data.py +31 -24
- taxcalc/tests/test_decorators.py +84 -32
- taxcalc/tests/test_growdiff.py +20 -19
- taxcalc/tests/test_growfactors.py +8 -8
- taxcalc/tests/test_parameters.py +54 -58
- taxcalc/tests/test_policy.py +16 -14
- 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.3.5.dist-info → taxcalc-4.4.1.dist-info}/METADATA +23 -11
- {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/RECORD +47 -47
- {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/WHEEL +1 -1
- {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/LICENSE +0 -0
- {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/entry_points.txt +0 -0
- {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/top_level.txt +0 -0
taxcalc/parameters.py
CHANGED
@@ -1,13 +1,14 @@
|
|
1
|
+
"""
|
2
|
+
Tax-Calculator abstract base parameter class based on paramtools package.
|
3
|
+
"""
|
4
|
+
|
1
5
|
import os
|
2
6
|
import copy
|
3
7
|
from collections import defaultdict
|
4
8
|
from typing import Union, Mapping, Any, List
|
5
|
-
|
9
|
+
import numpy as np
|
6
10
|
import marshmallow as ma
|
7
11
|
import paramtools as pt
|
8
|
-
import numpy as np
|
9
|
-
|
10
|
-
from taxcalc.growfactors import GrowFactors
|
11
12
|
|
12
13
|
|
13
14
|
class CompatibleDataSchema(ma.Schema):
|
@@ -64,8 +65,8 @@ class Parameters(pt.Parameters):
|
|
64
65
|
Check out the ParamTools
|
65
66
|
`documentation <https://paramtools.dev/api/reference.html>`_
|
66
67
|
for more information on these inherited methods.
|
67
|
-
|
68
68
|
"""
|
69
|
+
# pylint: disable=too-many-instance-attributes
|
69
70
|
defaults = None
|
70
71
|
array_first = True
|
71
72
|
label_to_extend = "year"
|
@@ -83,6 +84,8 @@ class Parameters(pt.Parameters):
|
|
83
84
|
|
84
85
|
def __init__(self, start_year=None, num_years=None, last_known_year=None,
|
85
86
|
removed=None, redefined=None, wage_indexed=None, **kwargs):
|
87
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
88
|
+
|
86
89
|
# In case we need to wait for this to be called from the
|
87
90
|
# initialize method for legacy reasons.
|
88
91
|
if not start_year or not num_years:
|
@@ -98,19 +101,16 @@ class Parameters(pt.Parameters):
|
|
98
101
|
self.DEFAULTS_FILE_PATH,
|
99
102
|
self.DEFAULTS_FILE_NAME
|
100
103
|
)
|
101
|
-
|
104
|
+
last_budget_year = start_year + num_years - 1
|
102
105
|
if last_known_year is None:
|
103
106
|
self._last_known_year = start_year
|
104
107
|
else:
|
105
108
|
assert last_known_year >= start_year
|
106
|
-
assert last_known_year <=
|
109
|
+
assert last_known_year <= last_budget_year
|
107
110
|
self._last_known_year = last_known_year
|
108
|
-
|
109
111
|
self._removed_params = removed or self.REMOVED_PARAMS
|
110
112
|
self._redefined_params = redefined or self.REDEFINED_PARAMS
|
111
|
-
|
112
113
|
self._wage_indexed = wage_indexed or self.WAGE_INDEXED_PARAMS
|
113
|
-
|
114
114
|
if (
|
115
115
|
(start_year or self.JSON_START_YEAR) and
|
116
116
|
"initial_state" not in kwargs
|
@@ -118,10 +118,18 @@ class Parameters(pt.Parameters):
|
|
118
118
|
kwargs["initial_state"] = {
|
119
119
|
"year": start_year or self.JSON_START_YEAR
|
120
120
|
}
|
121
|
+
# update defaults to correspond to user-defined parameter years
|
122
|
+
self.defaults = super().get_defaults()
|
123
|
+
label = self.defaults["schema"]["labels"]["year"]
|
124
|
+
label["validators"]["range"]["max"] = last_budget_year
|
121
125
|
super().__init__(**kwargs)
|
122
126
|
|
123
|
-
def adjust(
|
124
|
-
|
127
|
+
def adjust( # pylint: disable=arguments-differ
|
128
|
+
# pylint warning W0221 is:
|
129
|
+
# Number of parameters was 6 in 'Parameters.adjust' and
|
130
|
+
# is now 5 in overriding 'Parameters.adjust' method
|
131
|
+
self, params_or_path,
|
132
|
+
print_warnings=True, raise_errors=True, **kwargs
|
125
133
|
):
|
126
134
|
"""
|
127
135
|
Update parameter values using a ParamTools styled adjustment.
|
@@ -135,8 +143,10 @@ class Parameters(pt.Parameters):
|
|
135
143
|
|
136
144
|
{
|
137
145
|
"standard_deduction": [
|
138
|
-
{"year": 2024, "marital_status": "single",
|
139
|
-
|
146
|
+
{"year": 2024, "marital_status": "single",
|
147
|
+
"value": 10000.0},
|
148
|
+
{"year": 2024, "marital_status": "joint",
|
149
|
+
"value": 10000.0}
|
140
150
|
],
|
141
151
|
"ss_rate": [{"year": 2024, "value": 0.2}]}
|
142
152
|
}
|
@@ -153,7 +163,7 @@ class Parameters(pt.Parameters):
|
|
153
163
|
adjustment : Dict
|
154
164
|
Parsed paremeter dictionary
|
155
165
|
|
156
|
-
"""
|
166
|
+
"""
|
157
167
|
if print_warnings:
|
158
168
|
_data = copy.deepcopy(self._data)
|
159
169
|
kwargs["ignore_warnings"] = False
|
@@ -176,13 +186,15 @@ class Parameters(pt.Parameters):
|
|
176
186
|
except pt.ValidationError as ve:
|
177
187
|
if self.errors and raise_errors:
|
178
188
|
raise ve
|
179
|
-
|
189
|
+
if self.errors and not raise_errors:
|
180
190
|
return {}
|
181
191
|
if print_warnings:
|
182
192
|
print("WARNING:")
|
183
193
|
print(self.warnings)
|
184
194
|
kwargs["ignore_warnings"] = True
|
195
|
+
# pylint: disable=possibly-used-before-assignment
|
185
196
|
self._data = _data
|
197
|
+
# pylint: enable=possibly-used-before-assignment
|
186
198
|
_warnings = copy.deepcopy(self._warnings)
|
187
199
|
self._warnings = {}
|
188
200
|
self._errors = {}
|
@@ -241,6 +253,8 @@ class Parameters(pt.Parameters):
|
|
241
253
|
wiped out after the year in which the value is adjusted for the
|
242
254
|
same hard-coding reason.
|
243
255
|
"""
|
256
|
+
# pylint: disable=too-many-statements,too-many-locals,too-many-branches
|
257
|
+
|
244
258
|
# Temporarily turn off extra ops during the intermediary adjustments
|
245
259
|
# so that expensive and unnecessary operations are not run.
|
246
260
|
label_to_extend = self.label_to_extend
|
@@ -309,7 +323,7 @@ class Parameters(pt.Parameters):
|
|
309
323
|
self.delete(to_delete, **kwargs)
|
310
324
|
|
311
325
|
# 1.b For all others, these are years after last_known_year.
|
312
|
-
last_known_year
|
326
|
+
# last_known_year=max(cpi_min_year["year"],self._last_known_year)
|
313
327
|
# calculate 2026 value, using new inflation rates, for parameters
|
314
328
|
# that revert to their pre-TCJA values.
|
315
329
|
long_params = ['II_brk7', 'II_brk6', 'II_brk5', 'II_brk4',
|
@@ -361,7 +375,15 @@ class Parameters(pt.Parameters):
|
|
361
375
|
):
|
362
376
|
continue
|
363
377
|
if self._data[param].get("indexed", False):
|
364
|
-
|
378
|
+
# pylint: disable=singleton-comparison
|
379
|
+
to_delete[param] = self.sel[param]["_auto"] == True
|
380
|
+
# pylint warning message:
|
381
|
+
# Comparison 'self.sel[param]['_auto'] == True' should
|
382
|
+
# be 'self.sel[param]['_auto'] is True' if checking for
|
383
|
+
# the singleton value True, or
|
384
|
+
# 'bool(self.sel[param]['_auto'])' if testing for
|
385
|
+
# truthiness
|
386
|
+
# pylint: enable=singleton-comparison
|
365
387
|
needs_reset.append(param)
|
366
388
|
|
367
389
|
self.delete(to_delete, **kwargs)
|
@@ -404,13 +426,14 @@ class Parameters(pt.Parameters):
|
|
404
426
|
min_index_change_year, strict=False
|
405
427
|
)
|
406
428
|
|
407
|
-
if
|
429
|
+
if list(vos):
|
408
430
|
min_adj_year = min(vos, key=lambda vo: vo["year"])[
|
409
431
|
"year"
|
410
432
|
]
|
411
433
|
self.delete(
|
412
434
|
{
|
413
|
-
base_param:
|
435
|
+
base_param:
|
436
|
+
self.sel[base_param]["year"] > min_adj_year
|
414
437
|
}
|
415
438
|
)
|
416
439
|
super().adjust({base_param: vos}, **kwargs)
|
@@ -481,40 +504,45 @@ class Parameters(pt.Parameters):
|
|
481
504
|
)
|
482
505
|
return adj
|
483
506
|
|
484
|
-
def get_index_rate(self, param,
|
507
|
+
def get_index_rate(self, param, lte_val):
|
485
508
|
"""
|
486
509
|
Initalize indexing data and return the indexing rate value
|
487
|
-
depending on the parameter name and
|
488
|
-
label_to_extend.
|
510
|
+
depending on the parameter name and lte_val (that is, the
|
511
|
+
label_to_extend_val), the value of label_to_extend.
|
489
512
|
Returns: rate to use for indexing.
|
490
513
|
"""
|
491
514
|
if not self._inflation_rates or not self._wage_growth_rates:
|
492
515
|
self.set_rates()
|
493
516
|
if param in self._wage_indexed:
|
494
|
-
return self.wage_growth_rates(year=
|
495
|
-
|
496
|
-
return self.inflation_rates(year=label_to_extend_val)
|
517
|
+
return self.wage_growth_rates(year=lte_val)
|
518
|
+
return self.inflation_rates(year=lte_val)
|
497
519
|
|
498
520
|
def set_rates(self):
|
499
521
|
"""
|
500
|
-
This method is implemented by classes inheriting
|
501
|
-
Parameters.
|
522
|
+
This method is implemented by classes inheriting Parameters.
|
502
523
|
"""
|
503
524
|
raise NotImplementedError()
|
504
525
|
|
505
526
|
def wage_growth_rates(self, year=None):
|
527
|
+
"""
|
528
|
+
Return wage growth rates used in parameter indexing.
|
529
|
+
"""
|
506
530
|
if year is not None:
|
507
531
|
syr = max(self.start_year, self._gfactors.first_year)
|
508
532
|
return self._wage_growth_rates[year - syr]
|
509
533
|
return self._wage_growth_rates or []
|
510
534
|
|
511
535
|
def inflation_rates(self, year=None):
|
536
|
+
"""
|
537
|
+
Return price inflation rates used in parameter indexing.
|
538
|
+
"""
|
512
539
|
if year is not None:
|
513
540
|
syr = max(self.start_year, self._gfactors.first_year)
|
514
541
|
return self._inflation_rates[year - syr]
|
515
542
|
return self._inflation_rates or []
|
516
543
|
|
517
|
-
# alias methods below
|
544
|
+
# alias methods below:
|
545
|
+
|
518
546
|
def initialize(self, start_year, num_years, last_known_year=None,
|
519
547
|
removed=None, redefined=None, wage_indexed=None,
|
520
548
|
**kwargs):
|
@@ -522,13 +550,15 @@ class Parameters(pt.Parameters):
|
|
522
550
|
Legacy method for initializing a Parameters instance. Projects
|
523
551
|
should use the __init__ method in the future.
|
524
552
|
"""
|
525
|
-
#
|
553
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
554
|
+
# Handle case where project hasn't been initialized yet
|
526
555
|
if getattr(self, "_data", None) is None:
|
527
556
|
return Parameters.__init__(
|
528
557
|
self, start_year, num_years, last_known_year=last_known_year,
|
529
558
|
removed=removed, redefined=redefined,
|
530
559
|
wage_indexed=wage_indexed, **kwargs
|
531
560
|
)
|
561
|
+
return None # pragma: no cover
|
532
562
|
|
533
563
|
def _update(self, revision, print_warnings, raise_errors):
|
534
564
|
"""
|
@@ -552,13 +582,16 @@ class Parameters(pt.Parameters):
|
|
552
582
|
|
553
583
|
{
|
554
584
|
"standard_deduction": [
|
555
|
-
{"year": 2024, "marital_status": "single",
|
556
|
-
|
585
|
+
{"year": 2024, "marital_status": "single",
|
586
|
+
"value": 10000.0},
|
587
|
+
{"year": 2024, "marital_status": "joint",
|
588
|
+
"value": 10000.0}
|
557
589
|
],
|
558
590
|
"ss_rate": [{"year": 2024, "value": 0.2}]}
|
559
591
|
}
|
560
592
|
|
561
|
-
"""
|
593
|
+
"""
|
594
|
+
# pylint: disable=too-many-branches
|
562
595
|
if not isinstance(revision, dict):
|
563
596
|
raise pt.ValidationError(
|
564
597
|
{"errors": {"schema": "Revision must be a dictionary."}},
|
@@ -650,30 +683,37 @@ class Parameters(pt.Parameters):
|
|
650
683
|
)
|
651
684
|
|
652
685
|
def set_year(self, year):
|
686
|
+
"""Specify parameter year"""
|
653
687
|
self.set_state(year=year)
|
654
688
|
|
655
689
|
@property
|
656
690
|
def current_year(self):
|
691
|
+
"""Propery docstring"""
|
657
692
|
return self.label_grid["year"][0]
|
658
693
|
|
659
694
|
@property
|
660
695
|
def start_year(self):
|
696
|
+
"""Propery docstring"""
|
661
697
|
return self._stateless_label_grid["year"][0]
|
662
698
|
|
663
699
|
@property
|
664
700
|
def end_year(self):
|
701
|
+
"""Propery docstring"""
|
665
702
|
return self._stateless_label_grid["year"][-1]
|
666
703
|
|
667
704
|
@property
|
668
705
|
def num_years(self):
|
706
|
+
"""Propery docstring"""
|
669
707
|
return self.end_year - self.start_year + 1
|
670
708
|
|
671
709
|
@property
|
672
710
|
def parameter_warnings(self):
|
711
|
+
"""Propery docstring"""
|
673
712
|
return self.errors or {}
|
674
713
|
|
675
714
|
@property
|
676
715
|
def parameter_errors(self):
|
716
|
+
"""Propery docstring"""
|
677
717
|
return self.errors or {}
|
678
718
|
|
679
719
|
@staticmethod
|
@@ -697,14 +737,17 @@ class Parameters(pt.Parameters):
|
|
697
737
|
|
698
738
|
Some examples of valid links are:
|
699
739
|
|
700
|
-
- HTTP: ``https://raw.githubusercontent.com/PSLmodels/Tax-Calculator/
|
740
|
+
- HTTP: ``https://raw.githubusercontent.com/PSLmodels/Tax-Calculator/
|
741
|
+
master/taxcalc/reforms/2017_law.json``
|
701
742
|
|
702
|
-
- Github API: ``github://PSLmodels:Tax-Calculator@master/taxcalc/
|
743
|
+
- Github API: ``github://PSLmodels:Tax-Calculator@master/taxcalc/
|
744
|
+
reforms/2017_law.json``
|
703
745
|
|
704
746
|
Checkout the ParamTools
|
705
|
-
`docs <https://paramtools.dev/_modules/paramtools/
|
747
|
+
`docs <https://paramtools.dev/_modules/paramtools/
|
748
|
+
parameters.html#Parameters.read_params>`_
|
706
749
|
for more information on valid file URLs.
|
707
|
-
"""
|
750
|
+
"""
|
708
751
|
# embedded function used only in _read_json_revision staticmethod
|
709
752
|
def convert_year_to_int(syr_dict):
|
710
753
|
"""
|
@@ -712,10 +755,10 @@ class Parameters(pt.Parameters):
|
|
712
755
|
keys, into a dictionary with the same structure but having integer
|
713
756
|
years as secondary keys.
|
714
757
|
"""
|
715
|
-
iyr_dict =
|
758
|
+
iyr_dict = {}
|
716
759
|
for pkey, sdict in syr_dict.items():
|
717
760
|
assert isinstance(pkey, str)
|
718
|
-
iyr_dict[pkey] =
|
761
|
+
iyr_dict[pkey] = {}
|
719
762
|
assert isinstance(sdict, dict)
|
720
763
|
for skey, val in sdict.items():
|
721
764
|
assert isinstance(skey, str)
|
@@ -725,7 +768,7 @@ class Parameters(pt.Parameters):
|
|
725
768
|
# end of embedded function
|
726
769
|
# process the main function arguments
|
727
770
|
if obj is None:
|
728
|
-
return
|
771
|
+
return {}
|
729
772
|
|
730
773
|
full_dict = pt.read_json(obj)
|
731
774
|
|
@@ -742,6 +785,9 @@ class Parameters(pt.Parameters):
|
|
742
785
|
return convert_year_to_int(single_dict)
|
743
786
|
|
744
787
|
def metadata(self):
|
788
|
+
"""
|
789
|
+
Return parameter specification.
|
790
|
+
"""
|
745
791
|
return self.specification(meta_data=True, use_state=False)
|
746
792
|
|
747
793
|
@staticmethod
|
@@ -751,7 +797,7 @@ class Parameters(pt.Parameters):
|
|
751
797
|
assumed to have a param:year:value format.
|
752
798
|
"""
|
753
799
|
assert isinstance(revision, dict)
|
754
|
-
years =
|
800
|
+
years = []
|
755
801
|
for _, paramdata in revision.items():
|
756
802
|
assert isinstance(paramdata, dict)
|
757
803
|
for year, _ in paramdata.items():
|
@@ -773,8 +819,7 @@ class Parameters(pt.Parameters):
|
|
773
819
|
return self.to_array(
|
774
820
|
attr[1:], year=list(range(self.start_year, self.end_year + 1))
|
775
821
|
)
|
776
|
-
|
777
|
-
raise AttributeError(f"{attr} not definied.")
|
822
|
+
raise AttributeError(f"{attr} is not defined.")
|
778
823
|
|
779
824
|
|
780
825
|
TaxcalcReform = Union[str, Mapping[int, Any]]
|
@@ -814,7 +859,6 @@ def is_paramtools_format(params: Union[TaxcalcReform, ParamToolsAdjustment]):
|
|
814
859
|
for data in params.values():
|
815
860
|
if isinstance(data, dict):
|
816
861
|
return False # taxcalc reform
|
817
|
-
|
818
|
-
|
819
|
-
|
820
|
-
return True
|
862
|
+
# Not doing a specific check to see if the value is a list
|
863
|
+
# since it could be a list or just a scalar value.
|
864
|
+
return True
|
taxcalc/policy.py
CHANGED
@@ -24,6 +24,9 @@ class Policy(Parameters):
|
|
24
24
|
gfactors: GrowFactors class instance
|
25
25
|
containing price inflation rates and wage growth rates
|
26
26
|
|
27
|
+
last_budget_year: integer
|
28
|
+
user-defined last parameter extrapolation year
|
29
|
+
|
27
30
|
Raises
|
28
31
|
------
|
29
32
|
ValueError:
|
@@ -39,9 +42,16 @@ class Policy(Parameters):
|
|
39
42
|
JSON_START_YEAR = 2013 # remains the same unless earlier data added
|
40
43
|
LAST_KNOWN_YEAR = 2025 # last year for which indexed param vals are known
|
41
44
|
# should increase LAST_KNOWN_YEAR by one every calendar year
|
42
|
-
LAST_BUDGET_YEAR = 2034 # last extrapolation year
|
45
|
+
LAST_BUDGET_YEAR = 2034 # default value of last extrapolation year
|
43
46
|
# should increase LAST_BUDGET_YEAR by one every calendar year
|
44
|
-
|
47
|
+
|
48
|
+
@staticmethod
|
49
|
+
def number_of_years(last_budget_year=LAST_BUDGET_YEAR):
|
50
|
+
"""
|
51
|
+
Static method returns number of policy parameters years given
|
52
|
+
user-defined last_budget_year.
|
53
|
+
"""
|
54
|
+
return last_budget_year - Policy.JSON_START_YEAR + 1
|
45
55
|
|
46
56
|
# NOTE: the following three data structures use internal parameter names:
|
47
57
|
# (1) specify which Policy parameters have been removed or renamed
|
@@ -80,7 +90,10 @@ class Policy(Parameters):
|
|
80
90
|
# (3) specify which Policy parameters are wage (rather than price) indexed
|
81
91
|
WAGE_INDEXED_PARAMS = ['SS_Earnings_c', 'SS_Earnings_thd']
|
82
92
|
|
83
|
-
def __init__(self,
|
93
|
+
def __init__(self,
|
94
|
+
gfactors=None,
|
95
|
+
last_budget_year=LAST_BUDGET_YEAR,
|
96
|
+
**kwargs):
|
84
97
|
# put JSON contents of DEFAULTS_FILE_NAME into self._vals dictionary
|
85
98
|
super().__init__()
|
86
99
|
# handle gfactors argument
|
@@ -92,7 +105,7 @@ class Policy(Parameters):
|
|
92
105
|
raise ValueError('gfactors is not None or a GrowFactors instance')
|
93
106
|
# read default parameters and initialize
|
94
107
|
syr = Policy.JSON_START_YEAR
|
95
|
-
nyrs = Policy.
|
108
|
+
nyrs = Policy.number_of_years(last_budget_year)
|
96
109
|
self._inflation_rates = None
|
97
110
|
self._wage_growth_rates = None
|
98
111
|
self.initialize(syr, nyrs, Policy.LAST_KNOWN_YEAR,
|
@@ -101,7 +114,10 @@ class Policy(Parameters):
|
|
101
114
|
Policy.WAGE_INDEXED_PARAMS, **kwargs)
|
102
115
|
|
103
116
|
@staticmethod
|
104
|
-
def tmd_constructor(
|
117
|
+
def tmd_constructor(
|
118
|
+
growfactors: Path | GrowFactors,
|
119
|
+
last_budget_year=LAST_BUDGET_YEAR,
|
120
|
+
): # pragma: no cover
|
105
121
|
"""
|
106
122
|
Static method returns a Policy object instantiated with TMD
|
107
123
|
input data. This convenience method works in a analogous way
|
@@ -112,7 +128,7 @@ class Policy(Parameters):
|
|
112
128
|
growfactors = GrowFactors(growfactors_filename=str(growfactors))
|
113
129
|
else:
|
114
130
|
assert isinstance(growfactors, GrowFactors)
|
115
|
-
return Policy(gfactors=growfactors)
|
131
|
+
return Policy(gfactors=growfactors, last_budget_year=last_budget_year)
|
116
132
|
|
117
133
|
@staticmethod
|
118
134
|
def read_json_reform(obj):
|
@@ -142,7 +158,7 @@ class Policy(Parameters):
|
|
142
158
|
Policy.DEFAULTS_FILE_PATH,
|
143
159
|
Policy.DEFAULTS_FILE_NAME
|
144
160
|
)
|
145
|
-
with open(path, 'r',
|
161
|
+
with open(path, 'r', encoding='utf-8') as f:
|
146
162
|
defaults = json.loads(f.read()) # pylint: disable=protected-access
|
147
163
|
return [k for k in defaults if k != "schema"]
|
148
164
|
|
taxcalc/records.py
CHANGED
@@ -136,6 +136,7 @@ class Records(Data):
|
|
136
136
|
adjust_ratios=PUF_RATIOS_FILENAME,
|
137
137
|
exact_calculations=False,
|
138
138
|
weights_scale=0.01):
|
139
|
+
# pylint: disable=too-many-positional-arguments
|
139
140
|
# pylint: disable=no-member,too-many-branches
|
140
141
|
if isinstance(weights, str):
|
141
142
|
weights = os.path.join(Records.CODE_PATH, weights)
|
taxcalc/records_variables.json
CHANGED
@@ -842,6 +842,12 @@
|
|
842
842
|
"form": {"2013-2013": "1040 line 46 minus 1040 line 55",
|
843
843
|
"2014-2016": "1040 line 47 minus 1040 line 56"}
|
844
844
|
},
|
845
|
+
"c32800": {
|
846
|
+
"type": "float",
|
847
|
+
"desc": "Child and dependent care expenses capped by policy (not by earnings)",
|
848
|
+
"form": {"2013-2013": "1040 line 48",
|
849
|
+
"2014-2016": "1040 line 49"}
|
850
|
+
},
|
845
851
|
"c07180": {
|
846
852
|
"type": "float",
|
847
853
|
"desc": "Nonrefundable credit for child and dependent care expenses from Form 2441",
|
taxcalc/reforms/ext.json
CHANGED