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.
Files changed (57) hide show
  1. taxcalc/__init__.py +1 -1
  2. taxcalc/calcfunctions.py +326 -171
  3. taxcalc/calculator.py +35 -34
  4. taxcalc/cli/tc.py +6 -7
  5. taxcalc/consumption.json +1 -1
  6. taxcalc/consumption.py +9 -4
  7. taxcalc/cps_weights.csv.gz +0 -0
  8. taxcalc/data.py +8 -8
  9. taxcalc/decorators.py +3 -3
  10. taxcalc/growdiff.json +1 -1
  11. taxcalc/growdiff.py +5 -0
  12. taxcalc/growfactors.csv +26 -25
  13. taxcalc/growfactors.py +1 -1
  14. taxcalc/parameters.py +85 -42
  15. taxcalc/policy.py +2 -2
  16. taxcalc/policy_current_law.json +87 -87
  17. taxcalc/puf_ratios.csv +15 -14
  18. taxcalc/puf_weights.csv.gz +0 -0
  19. taxcalc/records.py +1 -0
  20. taxcalc/records_variables.json +6 -0
  21. taxcalc/reforms/ext.json +21 -21
  22. taxcalc/taxcalcio.py +49 -44
  23. taxcalc/tests/cmpi_cps_expect.txt +6 -6
  24. taxcalc/tests/cmpi_puf_expect.txt +6 -6
  25. taxcalc/tests/conftest.py +43 -42
  26. taxcalc/tests/cpscsv_agg_expect.csv +22 -22
  27. taxcalc/tests/puf_var_wght_means_by_year.csv +70 -70
  28. taxcalc/tests/pufcsv_agg_expect.csv +22 -22
  29. taxcalc/tests/test_4package.py +9 -7
  30. taxcalc/tests/test_benefits.py +9 -8
  31. taxcalc/tests/test_calcfunctions.py +55 -38
  32. taxcalc/tests/test_calculator.py +11 -6
  33. taxcalc/tests/test_compare.py +45 -51
  34. taxcalc/tests/test_compatible_data.py +9 -7
  35. taxcalc/tests/test_consumption.py +38 -18
  36. taxcalc/tests/test_cpscsv.py +33 -31
  37. taxcalc/tests/test_data.py +31 -24
  38. taxcalc/tests/test_decorators.py +84 -32
  39. taxcalc/tests/test_growdiff.py +16 -13
  40. taxcalc/tests/test_growfactors.py +8 -8
  41. taxcalc/tests/test_parameters.py +55 -59
  42. taxcalc/tests/test_policy.py +14 -12
  43. taxcalc/tests/test_puf_var_stats.py +14 -14
  44. taxcalc/tests/test_pufcsv.py +40 -40
  45. taxcalc/tests/test_records.py +73 -60
  46. taxcalc/tests/test_reforms.py +35 -32
  47. taxcalc/tests/test_responses.py +4 -4
  48. taxcalc/tests/test_taxcalcio.py +76 -62
  49. taxcalc/tests/test_utils.py +78 -46
  50. taxcalc/utils.py +49 -42
  51. taxcalc/validation/taxsim35/taxsim_emulation.json +1 -5
  52. {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/METADATA +19 -5
  53. {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/RECORD +57 -57
  54. {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/WHEEL +1 -1
  55. {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/LICENSE +0 -0
  56. {taxcalc-4.4.0.dist-info → taxcalc-4.5.0.dist-info}/entry_points.txt +0 -0
  57. {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
- self, params_or_path, print_warnings=True, raise_errors=True, **kwargs
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", "value": 10000.0},
140
- {"year": 2024, "marital_status": "joint", "value": 10000.0}
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
- """ # noqa
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
- elif self.errors and not raise_errors:
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 = max(cpi_min_year["year"], self._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
- to_delete[param] = self.sel[param]["_auto"] == True # noqa
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 len(list(vos)):
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: self.sel[base_param]["year"] > min_adj_year # noqa
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, label_to_extend_val):
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 label_to_extend_val, the value of
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=label_to_extend_val)
496
- else:
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
- # case where project hasn't been initialized yet.
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", "value": 10000.0},
557
- {"year": 2024, "marital_status": "joint", "value": 10000.0}
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
- """ # noqa: E501
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/master/taxcalc/reforms/2017_law.json``
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/reforms/2017_law.json``
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/parameters.html#Parameters.read_params>`_
747
+ `docs <https://paramtools.dev/_modules/paramtools/
748
+ parameters.html#Parameters.read_params>`_
707
749
  for more information on valid file URLs.
708
- """ # noqa
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 = dict()
758
+ iyr_dict = {}
717
759
  for pkey, sdict in syr_dict.items():
718
760
  assert isinstance(pkey, str)
719
- iyr_dict[pkey] = dict()
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 dict()
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 = list()
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
- else:
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
- else:
819
- # Not doing a specific check to see if the value is a list
820
- # since it could be a list or just a scalar value.
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 = 2034 # default value of last extrapolation 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', encoding='utf-8') as f:
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