taxcalc 4.4.0__py3-none-any.whl → 4.5.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 +1 -1
- taxcalc/calcfunctions.py +326 -171
- taxcalc/calculator.py +35 -34
- taxcalc/cli/tc.py +6 -7
- taxcalc/consumption.json +1 -1
- taxcalc/consumption.py +9 -4
- taxcalc/cps_weights.csv.gz +0 -0
- taxcalc/data.py +8 -8
- taxcalc/decorators.py +3 -3
- taxcalc/growdiff.json +1 -1
- taxcalc/growdiff.py +5 -0
- taxcalc/growfactors.csv +26 -25
- taxcalc/growfactors.py +1 -1
- taxcalc/parameters.py +85 -42
- taxcalc/policy.py +2 -2
- taxcalc/policy_current_law.json +87 -87
- taxcalc/puf_ratios.csv +15 -14
- taxcalc/puf_weights.csv.gz +0 -0
- taxcalc/records.py +1 -0
- taxcalc/records_variables.json +6 -0
- taxcalc/reforms/ext.json +21 -21
- 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 +43 -42
- taxcalc/tests/cpscsv_agg_expect.csv +22 -22
- taxcalc/tests/puf_var_wght_means_by_year.csv +70 -70
- taxcalc/tests/pufcsv_agg_expect.csv +22 -22
- 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 +45 -51
- 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 +55 -59
- 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 +35 -32
- 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.5.0.dist-info}/METADATA +19 -5
- {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/RECORD +57 -57
- {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/WHEEL +1 -1
- {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/LICENSE +0 -0
- {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/entry_points.txt +0 -0
- {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.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:
|
@@ -121,8 +124,12 @@ class Parameters(pt.Parameters):
|
|
121
124
|
label["validators"]["range"]["max"] = last_budget_year
|
122
125
|
super().__init__(**kwargs)
|
123
126
|
|
124
|
-
def adjust(
|
125
|
-
|
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
|
126
133
|
):
|
127
134
|
"""
|
128
135
|
Update parameter values using a ParamTools styled adjustment.
|
@@ -136,8 +143,10 @@ class Parameters(pt.Parameters):
|
|
136
143
|
|
137
144
|
{
|
138
145
|
"standard_deduction": [
|
139
|
-
{"year": 2024, "marital_status": "single",
|
140
|
-
|
146
|
+
{"year": 2024, "marital_status": "single",
|
147
|
+
"value": 10000.0},
|
148
|
+
{"year": 2024, "marital_status": "joint",
|
149
|
+
"value": 10000.0}
|
141
150
|
],
|
142
151
|
"ss_rate": [{"year": 2024, "value": 0.2}]}
|
143
152
|
}
|
@@ -154,7 +163,7 @@ class Parameters(pt.Parameters):
|
|
154
163
|
adjustment : Dict
|
155
164
|
Parsed paremeter dictionary
|
156
165
|
|
157
|
-
"""
|
166
|
+
"""
|
158
167
|
if print_warnings:
|
159
168
|
_data = copy.deepcopy(self._data)
|
160
169
|
kwargs["ignore_warnings"] = False
|
@@ -177,13 +186,15 @@ class Parameters(pt.Parameters):
|
|
177
186
|
except pt.ValidationError as ve:
|
178
187
|
if self.errors and raise_errors:
|
179
188
|
raise ve
|
180
|
-
|
189
|
+
if self.errors and not raise_errors:
|
181
190
|
return {}
|
182
191
|
if print_warnings:
|
183
192
|
print("WARNING:")
|
184
193
|
print(self.warnings)
|
185
194
|
kwargs["ignore_warnings"] = True
|
195
|
+
# pylint: disable=possibly-used-before-assignment
|
186
196
|
self._data = _data
|
197
|
+
# pylint: enable=possibly-used-before-assignment
|
187
198
|
_warnings = copy.deepcopy(self._warnings)
|
188
199
|
self._warnings = {}
|
189
200
|
self._errors = {}
|
@@ -242,6 +253,8 @@ class Parameters(pt.Parameters):
|
|
242
253
|
wiped out after the year in which the value is adjusted for the
|
243
254
|
same hard-coding reason.
|
244
255
|
"""
|
256
|
+
# pylint: disable=too-many-statements,too-many-locals,too-many-branches
|
257
|
+
|
245
258
|
# Temporarily turn off extra ops during the intermediary adjustments
|
246
259
|
# so that expensive and unnecessary operations are not run.
|
247
260
|
label_to_extend = self.label_to_extend
|
@@ -310,7 +323,7 @@ class Parameters(pt.Parameters):
|
|
310
323
|
self.delete(to_delete, **kwargs)
|
311
324
|
|
312
325
|
# 1.b For all others, these are years after last_known_year.
|
313
|
-
last_known_year
|
326
|
+
# last_known_year=max(cpi_min_year["year"],self._last_known_year)
|
314
327
|
# calculate 2026 value, using new inflation rates, for parameters
|
315
328
|
# that revert to their pre-TCJA values.
|
316
329
|
long_params = ['II_brk7', 'II_brk6', 'II_brk5', 'II_brk4',
|
@@ -362,7 +375,15 @@ class Parameters(pt.Parameters):
|
|
362
375
|
):
|
363
376
|
continue
|
364
377
|
if self._data[param].get("indexed", False):
|
365
|
-
|
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
|
366
387
|
needs_reset.append(param)
|
367
388
|
|
368
389
|
self.delete(to_delete, **kwargs)
|
@@ -405,13 +426,14 @@ class Parameters(pt.Parameters):
|
|
405
426
|
min_index_change_year, strict=False
|
406
427
|
)
|
407
428
|
|
408
|
-
if
|
429
|
+
if list(vos):
|
409
430
|
min_adj_year = min(vos, key=lambda vo: vo["year"])[
|
410
431
|
"year"
|
411
432
|
]
|
412
433
|
self.delete(
|
413
434
|
{
|
414
|
-
base_param:
|
435
|
+
base_param:
|
436
|
+
self.sel[base_param]["year"] > min_adj_year
|
415
437
|
}
|
416
438
|
)
|
417
439
|
super().adjust({base_param: vos}, **kwargs)
|
@@ -482,40 +504,45 @@ class Parameters(pt.Parameters):
|
|
482
504
|
)
|
483
505
|
return adj
|
484
506
|
|
485
|
-
def get_index_rate(self, param,
|
507
|
+
def get_index_rate(self, param, lte_val):
|
486
508
|
"""
|
487
509
|
Initalize indexing data and return the indexing rate value
|
488
|
-
depending on the parameter name and
|
489
|
-
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.
|
490
512
|
Returns: rate to use for indexing.
|
491
513
|
"""
|
492
514
|
if not self._inflation_rates or not self._wage_growth_rates:
|
493
515
|
self.set_rates()
|
494
516
|
if param in self._wage_indexed:
|
495
|
-
return self.wage_growth_rates(year=
|
496
|
-
|
497
|
-
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)
|
498
519
|
|
499
520
|
def set_rates(self):
|
500
521
|
"""
|
501
|
-
This method is implemented by classes inheriting
|
502
|
-
Parameters.
|
522
|
+
This method is implemented by classes inheriting Parameters.
|
503
523
|
"""
|
504
524
|
raise NotImplementedError()
|
505
525
|
|
506
526
|
def wage_growth_rates(self, year=None):
|
527
|
+
"""
|
528
|
+
Return wage growth rates used in parameter indexing.
|
529
|
+
"""
|
507
530
|
if year is not None:
|
508
531
|
syr = max(self.start_year, self._gfactors.first_year)
|
509
532
|
return self._wage_growth_rates[year - syr]
|
510
533
|
return self._wage_growth_rates or []
|
511
534
|
|
512
535
|
def inflation_rates(self, year=None):
|
536
|
+
"""
|
537
|
+
Return price inflation rates used in parameter indexing.
|
538
|
+
"""
|
513
539
|
if year is not None:
|
514
540
|
syr = max(self.start_year, self._gfactors.first_year)
|
515
541
|
return self._inflation_rates[year - syr]
|
516
542
|
return self._inflation_rates or []
|
517
543
|
|
518
|
-
# alias methods below
|
544
|
+
# alias methods below:
|
545
|
+
|
519
546
|
def initialize(self, start_year, num_years, last_known_year=None,
|
520
547
|
removed=None, redefined=None, wage_indexed=None,
|
521
548
|
**kwargs):
|
@@ -523,13 +550,15 @@ class Parameters(pt.Parameters):
|
|
523
550
|
Legacy method for initializing a Parameters instance. Projects
|
524
551
|
should use the __init__ method in the future.
|
525
552
|
"""
|
526
|
-
#
|
553
|
+
# pylint: disable=too-many-arguments,too-many-positional-arguments
|
554
|
+
# Handle case where project hasn't been initialized yet
|
527
555
|
if getattr(self, "_data", None) is None:
|
528
556
|
return Parameters.__init__(
|
529
557
|
self, start_year, num_years, last_known_year=last_known_year,
|
530
558
|
removed=removed, redefined=redefined,
|
531
559
|
wage_indexed=wage_indexed, **kwargs
|
532
560
|
)
|
561
|
+
return None # pragma: no cover
|
533
562
|
|
534
563
|
def _update(self, revision, print_warnings, raise_errors):
|
535
564
|
"""
|
@@ -553,13 +582,16 @@ class Parameters(pt.Parameters):
|
|
553
582
|
|
554
583
|
{
|
555
584
|
"standard_deduction": [
|
556
|
-
{"year": 2024, "marital_status": "single",
|
557
|
-
|
585
|
+
{"year": 2024, "marital_status": "single",
|
586
|
+
"value": 10000.0},
|
587
|
+
{"year": 2024, "marital_status": "joint",
|
588
|
+
"value": 10000.0}
|
558
589
|
],
|
559
590
|
"ss_rate": [{"year": 2024, "value": 0.2}]}
|
560
591
|
}
|
561
592
|
|
562
|
-
"""
|
593
|
+
"""
|
594
|
+
# pylint: disable=too-many-branches
|
563
595
|
if not isinstance(revision, dict):
|
564
596
|
raise pt.ValidationError(
|
565
597
|
{"errors": {"schema": "Revision must be a dictionary."}},
|
@@ -651,30 +683,37 @@ class Parameters(pt.Parameters):
|
|
651
683
|
)
|
652
684
|
|
653
685
|
def set_year(self, year):
|
686
|
+
"""Specify parameter year"""
|
654
687
|
self.set_state(year=year)
|
655
688
|
|
656
689
|
@property
|
657
690
|
def current_year(self):
|
691
|
+
"""Propery docstring"""
|
658
692
|
return self.label_grid["year"][0]
|
659
693
|
|
660
694
|
@property
|
661
695
|
def start_year(self):
|
696
|
+
"""Propery docstring"""
|
662
697
|
return self._stateless_label_grid["year"][0]
|
663
698
|
|
664
699
|
@property
|
665
700
|
def end_year(self):
|
701
|
+
"""Propery docstring"""
|
666
702
|
return self._stateless_label_grid["year"][-1]
|
667
703
|
|
668
704
|
@property
|
669
705
|
def num_years(self):
|
706
|
+
"""Propery docstring"""
|
670
707
|
return self.end_year - self.start_year + 1
|
671
708
|
|
672
709
|
@property
|
673
710
|
def parameter_warnings(self):
|
711
|
+
"""Propery docstring"""
|
674
712
|
return self.errors or {}
|
675
713
|
|
676
714
|
@property
|
677
715
|
def parameter_errors(self):
|
716
|
+
"""Propery docstring"""
|
678
717
|
return self.errors or {}
|
679
718
|
|
680
719
|
@staticmethod
|
@@ -698,14 +737,17 @@ class Parameters(pt.Parameters):
|
|
698
737
|
|
699
738
|
Some examples of valid links are:
|
700
739
|
|
701
|
-
- HTTP: ``https://raw.githubusercontent.com/PSLmodels/Tax-Calculator/
|
740
|
+
- HTTP: ``https://raw.githubusercontent.com/PSLmodels/Tax-Calculator/
|
741
|
+
master/taxcalc/reforms/2017_law.json``
|
702
742
|
|
703
|
-
- Github API: ``github://PSLmodels:Tax-Calculator@master/taxcalc/
|
743
|
+
- Github API: ``github://PSLmodels:Tax-Calculator@master/taxcalc/
|
744
|
+
reforms/2017_law.json``
|
704
745
|
|
705
746
|
Checkout the ParamTools
|
706
|
-
`docs <https://paramtools.dev/_modules/paramtools/
|
747
|
+
`docs <https://paramtools.dev/_modules/paramtools/
|
748
|
+
parameters.html#Parameters.read_params>`_
|
707
749
|
for more information on valid file URLs.
|
708
|
-
"""
|
750
|
+
"""
|
709
751
|
# embedded function used only in _read_json_revision staticmethod
|
710
752
|
def convert_year_to_int(syr_dict):
|
711
753
|
"""
|
@@ -713,10 +755,10 @@ class Parameters(pt.Parameters):
|
|
713
755
|
keys, into a dictionary with the same structure but having integer
|
714
756
|
years as secondary keys.
|
715
757
|
"""
|
716
|
-
iyr_dict =
|
758
|
+
iyr_dict = {}
|
717
759
|
for pkey, sdict in syr_dict.items():
|
718
760
|
assert isinstance(pkey, str)
|
719
|
-
iyr_dict[pkey] =
|
761
|
+
iyr_dict[pkey] = {}
|
720
762
|
assert isinstance(sdict, dict)
|
721
763
|
for skey, val in sdict.items():
|
722
764
|
assert isinstance(skey, str)
|
@@ -726,7 +768,7 @@ class Parameters(pt.Parameters):
|
|
726
768
|
# end of embedded function
|
727
769
|
# process the main function arguments
|
728
770
|
if obj is None:
|
729
|
-
return
|
771
|
+
return {}
|
730
772
|
|
731
773
|
full_dict = pt.read_json(obj)
|
732
774
|
|
@@ -743,6 +785,9 @@ class Parameters(pt.Parameters):
|
|
743
785
|
return convert_year_to_int(single_dict)
|
744
786
|
|
745
787
|
def metadata(self):
|
788
|
+
"""
|
789
|
+
Return parameter specification.
|
790
|
+
"""
|
746
791
|
return self.specification(meta_data=True, use_state=False)
|
747
792
|
|
748
793
|
@staticmethod
|
@@ -752,7 +797,7 @@ class Parameters(pt.Parameters):
|
|
752
797
|
assumed to have a param:year:value format.
|
753
798
|
"""
|
754
799
|
assert isinstance(revision, dict)
|
755
|
-
years =
|
800
|
+
years = []
|
756
801
|
for _, paramdata in revision.items():
|
757
802
|
assert isinstance(paramdata, dict)
|
758
803
|
for year, _ in paramdata.items():
|
@@ -774,8 +819,7 @@ class Parameters(pt.Parameters):
|
|
774
819
|
return self.to_array(
|
775
820
|
attr[1:], year=list(range(self.start_year, self.end_year + 1))
|
776
821
|
)
|
777
|
-
|
778
|
-
raise AttributeError(f"{attr} is not defined.")
|
822
|
+
raise AttributeError(f"{attr} is not defined.")
|
779
823
|
|
780
824
|
|
781
825
|
TaxcalcReform = Union[str, Mapping[int, Any]]
|
@@ -815,7 +859,6 @@ def is_paramtools_format(params: Union[TaxcalcReform, ParamToolsAdjustment]):
|
|
815
859
|
for data in params.values():
|
816
860
|
if isinstance(data, dict):
|
817
861
|
return False # taxcalc reform
|
818
|
-
|
819
|
-
|
820
|
-
|
821
|
-
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
@@ -42,7 +42,7 @@ class Policy(Parameters):
|
|
42
42
|
JSON_START_YEAR = 2013 # remains the same unless earlier data added
|
43
43
|
LAST_KNOWN_YEAR = 2025 # last year for which indexed param vals are known
|
44
44
|
# should increase LAST_KNOWN_YEAR by one every calendar year
|
45
|
-
LAST_BUDGET_YEAR =
|
45
|
+
LAST_BUDGET_YEAR = 2035 # default value of last extrapolation year
|
46
46
|
# should increase LAST_BUDGET_YEAR by one every calendar year
|
47
47
|
|
48
48
|
@staticmethod
|
@@ -158,7 +158,7 @@ class Policy(Parameters):
|
|
158
158
|
Policy.DEFAULTS_FILE_PATH,
|
159
159
|
Policy.DEFAULTS_FILE_NAME
|
160
160
|
)
|
161
|
-
with open(path, 'r',
|
161
|
+
with open(path, 'r', encoding='utf-8') as f:
|
162
162
|
defaults = json.loads(f.read()) # pylint: disable=protected-access
|
163
163
|
return [k for k in defaults if k != "schema"]
|
164
164
|
|