taxcalc 4.6.1__py3-none-any.whl → 4.6.3__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/policy.py CHANGED
@@ -8,6 +8,7 @@ Tax-Calculator federal tax policy Policy class.
8
8
  import os
9
9
  import json
10
10
  from pathlib import Path
11
+ import paramtools
11
12
  from taxcalc.parameters import Parameters
12
13
  from taxcalc.growfactors import GrowFactors
13
14
 
@@ -131,13 +132,34 @@ class Policy(Parameters):
131
132
  """
132
133
  return Parameters._read_json_revision(obj, 'policy')
133
134
 
134
- def implement_reform(self, reform,
135
+ def implement_reform(self, reform: dict,
135
136
  print_warnings=True, raise_errors=True):
136
137
  """
137
- Implement reform using Tax-Calculator syled reforms/adjustments. Users
138
- may also use the adjust method with ParamTools styled reforms.
138
+ Implement reform using a Tax-Calculator-style reform dictionary.
139
139
  """
140
- # need to do conversion:
140
+ if not isinstance(reform, dict):
141
+ raise paramtools.ValidationError(
142
+ {'errors': {'schema': 'reform must be a dictionary'}},
143
+ None
144
+ )
145
+ deprecated_parameters = [
146
+ 'ID_AmountCap_Switch',
147
+ 'ID_AmountCap_rt',
148
+ 'ID_BenefitCap_Switch',
149
+ 'ID_BenefitCap_rt',
150
+ 'ID_BenefitSurtax_Switch',
151
+ 'ID_BenefitSurtax_crt',
152
+ 'ID_BenefitSurtax_trt',
153
+ 'ID_BenefitSurtax_em',
154
+ ]
155
+ for param in reform.keys():
156
+ if param in deprecated_parameters:
157
+ print(
158
+ f'DEPRECATION WARNING: the {param} policy parameter\n'
159
+ 'is scheduled to be removed in Tax-Calculator 5.0.0;\n'
160
+ 'if you think this removal should not happen, open an\n'
161
+ 'issue on GitHub to make your case for non-removal.'
162
+ )
141
163
  return self._update(reform, print_warnings, raise_errors)
142
164
 
143
165
  @staticmethod
@@ -6,7 +6,7 @@
6
6
  "validators": {
7
7
  "range": {
8
8
  "min": 2013,
9
- "max": 2034
9
+ "max": 2035
10
10
  }
11
11
  }
12
12
  },
@@ -21819,7 +21819,7 @@
21819
21819
  "validators": {
21820
21820
  "range": {
21821
21821
  "min": 0,
21822
- "max": "CTC_c"
21822
+ "max": 9e+99
21823
21823
  }
21824
21824
  },
21825
21825
  "compatible_data": {
@@ -34,8 +34,6 @@ in this section.
34
34
 
35
35
  - [2016 Trump Campaign Tax Plan](Trump2016.json)
36
36
 
37
- - [2016 Clinton Campaign Tax Plan](Clinton2016.json)
38
-
39
37
  - [2017 Trump Administration Tax Plan](Trump2017.json)
40
38
 
41
39
  - [2017 Brown-Khanna GAIN Act](BrownKhanna.json)
taxcalc/reforms/ext.json CHANGED
@@ -34,8 +34,6 @@
34
34
  "CTC_c": {"2026": 2000.00},
35
35
  "ACTC_c": {"2026": 1776.67},
36
36
  "ACTC_c-indexed": {"2026": true},
37
- "ACTC_c": {"2032": 2000.00},
38
- "ACTC_c-indexed": {"2032": false},
39
37
  "ODC_c": {"2026": 500.00},
40
38
  "CTC_ps": {"2026": [200000.0, 400000.0, 200000.0, 200000.0, 400000.0]},
41
39
  "ACTC_Income_thd": {"2026": 2500.00},
taxcalc/taxcalcio.py CHANGED
@@ -18,7 +18,7 @@ from taxcalc.consumption import Consumption
18
18
  from taxcalc.growdiff import GrowDiff
19
19
  from taxcalc.growfactors import GrowFactors
20
20
  from taxcalc.calculator import Calculator
21
- from taxcalc.utils import (delete_file, write_graph_file,
21
+ from taxcalc.utils import (json_to_dict, delete_file, write_graph_file,
22
22
  add_quantile_table_row_variable,
23
23
  unweighted_sum, weighted_sum)
24
24
 
@@ -54,6 +54,9 @@ class TaxCalcIO():
54
54
  None implies economic assumptions are standard assumptions,
55
55
  or string is name of optional ASSUMP file.
56
56
 
57
+ runid: int
58
+ run id value to use for simpler output file names
59
+
57
60
  silent: boolean
58
61
  whether or not to suppress action messages.
59
62
 
@@ -64,7 +67,7 @@ class TaxCalcIO():
64
67
  # pylint: disable=too-many-instance-attributes
65
68
 
66
69
  def __init__(self, input_data, tax_year, baseline, reform, assump,
67
- silent=True):
70
+ runid=0, silent=True):
68
71
  # pylint: disable=too-many-arguments,too-many-positional-arguments
69
72
  # pylint: disable=too-many-branches,too-many-statements,too-many-locals
70
73
  self.silent = silent
@@ -133,7 +136,17 @@ class TaxCalcIO():
133
136
  msg = f'{fname} does not end in .json'
134
137
  self.errmsg += f'ERROR: BASELINE file name {msg}\n'
135
138
  # check existence of BASELINE file
136
- if not os.path.isfile(bas):
139
+ if os.path.isfile(bas):
140
+ # check validity of JSON text
141
+ with open(bas, 'r', encoding='utf-8') as jfile:
142
+ json_text = jfile.read()
143
+ try:
144
+ _ = json_to_dict(json_text)
145
+ except ValueError as valerr: # pragma: no cover
146
+ msg = f'{bas} contains invalid JSON'
147
+ self.errmsg += f'ERROR: BASELINE file {msg}\n'
148
+ self.errmsg += f'{valerr}'
149
+ else:
137
150
  msg = f'{bas} could not be found'
138
151
  self.errmsg += f'ERROR: BASELINE file {msg}\n'
139
152
  # add fname to list of basnames used in output file names
@@ -167,7 +180,17 @@ class TaxCalcIO():
167
180
  msg = f'{fname} does not end in .json'
168
181
  self.errmsg += f'ERROR: REFORM file name {msg}\n'
169
182
  # check existence of REFORM file
170
- if not os.path.isfile(rfm):
183
+ if os.path.isfile(rfm):
184
+ # check validity of JSON text
185
+ with open(rfm, 'r', encoding='utf-8') as jfile:
186
+ json_text = jfile.read()
187
+ try:
188
+ _ = json_to_dict(json_text)
189
+ except ValueError as valerr: # pragma: no cover
190
+ msg = f'{rfm} contains invalid JSON'
191
+ self.errmsg += f'ERROR: REFORM file {msg}\n'
192
+ self.errmsg += f'{valerr}'
193
+ else:
171
194
  msg = f'{rfm} could not be found'
172
195
  self.errmsg += f'ERROR: REFORM file {msg}\n'
173
196
  # add fname to list of refnames used in output file names
@@ -205,6 +228,9 @@ class TaxCalcIO():
205
228
  self.errmsg += f'ERROR: {msg}\n'
206
229
  # create OUTPUT file name and delete any existing output files
207
230
  self.output_filename = f'{inp}{bas}{ref}{asm}.xxx'
231
+ self.runid = runid
232
+ if runid > 0:
233
+ self.output_filename = f'run{runid}-{str(tax_year)[2:]}.xxx'
208
234
  self.delete_output_files()
209
235
  # initialize variables whose values are set in init method
210
236
  self.calc_ref = None
@@ -215,13 +241,13 @@ class TaxCalcIO():
215
241
  Delete all output files derived from self.output_filename.
216
242
  """
217
243
  extensions = [
218
- '-params.bas',
219
- '-params.ref',
220
- '-tables.text',
244
+ '-params.baseline',
245
+ '-params.reform',
246
+ '.tables',
221
247
  '-atr.html',
222
248
  '-mtr.html',
223
- '-pch.html',
224
- '.db',
249
+ '-chg.html',
250
+ '.dumpdb',
225
251
  ]
226
252
  for ext in extensions:
227
253
  delete_file(self.output_filename.replace('.xxx', ext))
@@ -458,13 +484,18 @@ class TaxCalcIO():
458
484
  """
459
485
  # update self.output_filename and delete output files
460
486
  parts = self.output_filename.split('-')
461
- parts[1] = str(year)[2:]
487
+ if self.runid == 0: # if using legacy output file names
488
+ parts[1] = str(year)[2:]
489
+ else: # if using simpler output file names (runN-YY.xxx)
490
+ subparts = parts[1].split('.')
491
+ subparts[0] = str(year)[2:]
492
+ parts[1] = '.'.join(subparts)
462
493
  self.output_filename = '-'.join(parts)
463
494
  self.delete_output_files()
464
495
  # advance baseline and reform Calculator objects to specified year
465
496
  self.calc_bas.advance_to_year(year)
466
497
  self.calc_ref.advance_to_year(year)
467
- idata = 'Advance input data and ' if aging_data else 'Advance'
498
+ idata = 'Advance input data and' if aging_data else 'Advance'
468
499
  if not self.silent:
469
500
  print(f'{idata} policy to {year}')
470
501
 
@@ -550,21 +581,22 @@ class TaxCalcIO():
550
581
  """
551
582
  Write baseline and reform policy parameter values to separate files.
552
583
  """
584
+ year = self.calc_bas.current_year
553
585
  param_names = Policy.parameter_list()
554
- fname = self.output_filename.replace('.xxx', '-params.bas')
586
+ fname = self.output_filename.replace('.xxx', '-params.baseline')
555
587
  with open(fname, 'w', encoding='utf-8') as pfile:
556
588
  for pname in param_names:
557
589
  pval = self.calc_bas.policy_param(pname)
558
- pfile.write(f'{pname} {pval}\n')
590
+ pfile.write(f'{year} {pname} {pval}\n')
559
591
  if not self.silent:
560
592
  print( # pragma: no cover
561
593
  f'Write baseline policy parameter values to file {fname}'
562
594
  )
563
- fname = self.output_filename.replace('.xxx', '-params.ref')
595
+ fname = self.output_filename.replace('.xxx', '-params.reform')
564
596
  with open(fname, 'w', encoding='utf-8') as pfile:
565
597
  for pname in param_names:
566
598
  pval = self.calc_ref.policy_param(pname)
567
- pfile.write(f'{pname} {pval}\n')
599
+ pfile.write(f'{year} {pname} {pval}\n')
568
600
  if not self.silent:
569
601
  print( # pragma: no cover
570
602
  f'Write reform policy parameter values to file {fname}'
@@ -575,7 +607,7 @@ class TaxCalcIO():
575
607
  Write tables to text file.
576
608
  """
577
609
  # pylint: disable=too-many-locals
578
- tab_fname = self.output_filename.replace('.xxx', '-tables.text')
610
+ tab_fname = self.output_filename.replace('.xxx', '.tables')
579
611
  # skip tables if there are not some positive weights
580
612
  if self.calc_bas.total_weight() <= 0.:
581
613
  with open(tab_fname, 'w', encoding='utf-8') as tfile:
@@ -600,10 +632,21 @@ class TaxCalcIO():
600
632
  diff = nontax + change # using expanded_income under baseline policy
601
633
  diffdf = pd.DataFrame(data=np.column_stack(diff), columns=all_vars)
602
634
  # write each kind of distributional table
635
+ year = self.calc_bas.current_year
603
636
  with open(tab_fname, 'w', encoding='utf-8') as tfile:
604
- TaxCalcIO.write_decile_table(distdf, tfile, tkind='Reform Totals')
637
+ TaxCalcIO.write_decile_table(
638
+ distdf,
639
+ tfile,
640
+ year,
641
+ tkind='Reform Totals',
642
+ )
605
643
  tfile.write('\n')
606
- TaxCalcIO.write_decile_table(diffdf, tfile, tkind='Differences')
644
+ TaxCalcIO.write_decile_table(
645
+ diffdf,
646
+ tfile,
647
+ year,
648
+ tkind='Differences',
649
+ )
607
650
  # delete intermediate DataFrame objects
608
651
  del distdf
609
652
  del diffdf
@@ -614,7 +657,7 @@ class TaxCalcIO():
614
657
  )
615
658
 
616
659
  @staticmethod
617
- def write_decile_table(dfx, tfile, tkind='Totals'):
660
+ def write_decile_table(dfx, tfile, year, tkind='Totals'):
618
661
  """
619
662
  Write to tfile the tkind decile table using dfx DataFrame.
620
663
  """
@@ -642,7 +685,10 @@ class TaxCalcIO():
642
685
  weighted_sum, 'combined', include_groups=False
643
686
  ).values[:, 1]
644
687
  # write decile table to text file
645
- row = f'Weighted Tax {tkind} by Baseline Expanded-Income Decile\n'
688
+ row = (
689
+ f'Weighted Tax {tkind} by '
690
+ f'Baseline Expanded-Income Decile for {year}\n'
691
+ )
646
692
  tfile.write(row)
647
693
  # pylint: disable=consider-using-f-string
648
694
  rowfmt = '{}{}{}{}{}{}\n'
@@ -696,8 +742,8 @@ class TaxCalcIO():
696
742
  pos_wght_sum = self.calc_ref.total_weight() > 0.0
697
743
  fig = None
698
744
  # percentage-aftertax-income-change graph
699
- pch_fname = self.output_filename.replace('.xxx', '-pch.html')
700
- pch_title = 'PCH by Income Percentile'
745
+ pch_fname = self.output_filename.replace('.xxx', '-chg.html')
746
+ pch_title = 'CHG by Income Percentile'
701
747
  if pos_wght_sum:
702
748
  fig = self.calc_bas.pch_graph(self.calc_ref, pop_quantiles=False)
703
749
  write_graph_file(fig, pch_fname, pch_title)
@@ -824,16 +870,41 @@ class TaxCalcIO():
824
870
  # begin main logic
825
871
  assert isinstance(dump_varlist, list)
826
872
  assert len(dump_varlist) > 0
827
- db_fname = self.output_filename.replace('.xxx', '.db')
873
+ db_fname = self.output_filename.replace('.xxx', '.dumpdb')
828
874
  dbcon = sqlite3.connect(db_fname)
829
875
  # write base table
830
876
  outdf = pd.DataFrame()
831
877
  for var in TaxCalcIO.BASE_DUMPVARS:
832
878
  outdf[var] = self.calc_bas.array(var)
833
- outdf['income_group'] = 0
879
+ expanded_income_bin_edges = [ # default income_group definition
880
+ -1e300, # essentially -infinity
881
+ 50e3,
882
+ 100e3,
883
+ 250e3,
884
+ 500e3,
885
+ 1e6,
886
+ 1e300, # essentially +infinity
887
+ ]
888
+ outdf['income_group'] = 1 + pd.cut( # default base.income_group values
889
+ outdf['expanded_income'],
890
+ expanded_income_bin_edges,
891
+ right=False, # bins are defined as [lo_edge, hi_edge)
892
+ labels=False, # pd.cut returns bins numbered 0,1,2,...
893
+ )
834
894
  assert len(outdf.index) == self.calc_bas.array_len
835
895
  outdf.to_sql('base', dbcon, index=False)
836
896
  del outdf
897
+ # write income_group_definition table
898
+ num_groups = len(expanded_income_bin_edges) - 1
899
+ outdf = pd.DataFrame()
900
+ outdf['income_group'] = np.array([
901
+ 1 + grp for grp in range(0, num_groups)
902
+ ])
903
+ outdf['income_lower'] = np.array(expanded_income_bin_edges[:-1])
904
+ outdf['income_up_to'] = np.array(expanded_income_bin_edges[1:])
905
+ assert len(outdf.index) == num_groups
906
+ outdf.to_sql('income_group_definition', dbcon, index=False)
907
+ del outdf
837
908
  # write baseline table
838
909
  outdf = dump_output(
839
910
  self.calc_bas, dump_varlist, mtr_itax_bas, mtr_ptax_bas,
taxcalc/tests/conftest.py CHANGED
@@ -71,7 +71,7 @@ def fixture_test_reforms(tests_path):
71
71
  Execute logic only once rather than on each pytest-xdist node.
72
72
  """
73
73
  # pylint: disable=too-many-locals,too-many-statements
74
- num_reforms = 64 # must be same as NUM_REFORMS in test_reforms.py
74
+ num_reforms = 63 # must be same as NUM_REFORMS in test_reforms.py
75
75
  handling_logic = ('PYTEST_XDIST_WORKER' not in os.environ or
76
76
  os.environ['PYTEST_XDIST_WORKER'] == 'gw0')
77
77
  initfile = os.path.join(tests_path, 'reforms_actual_init')
@@ -543,17 +543,6 @@
543
543
  },
544
544
 
545
545
  "55": {
546
- "baseline": "2017_law.json",
547
- "start_year": 2017,
548
- "value": {"ID_AmountCap_rt": 0.02,
549
- "ID_AmountCap_Switch":
550
- [false, true, true, false, false, false, false]},
551
- "name": "Limit amount of S&L deduction to 2% AGI",
552
- "output_type": "iitax",
553
- "compare_with": {"Budget Options": [44.1, 86.6, 87.1, 91.2]}
554
- },
555
-
556
- "56": {
557
546
  "baseline": "policy_current_law.json",
558
547
  "start_year": 2017,
559
548
  "value": {"parameter_indexing_CPI_offset": 0},
@@ -562,7 +551,7 @@
562
551
  "compare_with": {}
563
552
  },
564
553
 
565
- "57": {
554
+ "56": {
566
555
  "baseline": "2017_law.json",
567
556
  "start_year": 2017,
568
557
  "value": {"PT_rt7": 0.35,
@@ -572,7 +561,7 @@
572
561
  "compare_with": {}
573
562
  },
574
563
 
575
- "58": {
564
+ "57": {
576
565
  "baseline": "2017_law.json",
577
566
  "start_year": 2017,
578
567
  "value": {"PT_wages_active_income": true,
@@ -583,7 +572,7 @@
583
572
  "compare_with": {}
584
573
  },
585
574
 
586
- "59": {
575
+ "58": {
587
576
  "baseline": "2017_law.json",
588
577
  "start_year": 2017,
589
578
  "value": {"CTC_new_c": 1000,
@@ -595,7 +584,7 @@
595
584
  "compare_with": {}
596
585
  },
597
586
 
598
- "60": {
587
+ "59": {
599
588
  "baseline": "2017_law.json",
600
589
  "start_year": 2017,
601
590
  "value": {"CTC_new_c": 1000,
@@ -608,7 +597,7 @@
608
597
  "compare_with": {}
609
598
  },
610
599
 
611
- "61": {
600
+ "60": {
612
601
  "baseline": "2017_law.json",
613
602
  "start_year": 2017,
614
603
  "value": {"ID_Charity_hc": 1,
@@ -619,7 +608,7 @@
619
608
  "compare_with": {}
620
609
  },
621
610
 
622
- "62": {
611
+ "61": {
623
612
  "baseline": "2017_law.json",
624
613
  "start_year": 2019,
625
614
  "value": {"EITC_basic_frac": 0.5},
@@ -628,7 +617,7 @@
628
617
  "compare_with": {}
629
618
  },
630
619
 
631
- "63": {
620
+ "62": {
632
621
  "baseline": "policy_current_law.json",
633
622
  "start_year": 2019,
634
623
  "value": {"EITC_indiv": true},
@@ -637,7 +626,7 @@
637
626
  "compare_with": {}
638
627
  },
639
628
 
640
- "64": {
629
+ "63": {
641
630
  "baseline": "policy_current_law.json",
642
631
  "start_year": 2019,
643
632
  "value": {"RPTC_rt": 0.062,
@@ -53,13 +53,12 @@ rid,res1,res2,res3,res4
53
53
  52,-187.0,-187.5,-193.6,-201.6
54
54
  53,-130.0,-129.3,-132.7,-137.7
55
55
  54,30.7,33.2,31.4,41.0
56
- 55,86.1,90.8,94.7,102.1
57
- 56,0.0,0.0,0.0,0.0
58
- 57,-14.1,-15.6,-15.9,-14.4
59
- 58,-15.5,-17.0,-17.4,-15.8
60
- 59,-66.9,-66.9,-67.0,-67.1
61
- 60,-67.3,-67.2,-67.3,-67.4
62
- 61,-1.0,-0.6,-0.8,-1.7
63
- 62,-17.4,-18.0,-24.3,-20.0
64
- 63,-12.7,-13.0,-23.4,-13.8
65
- 64,-46.9,-48.1,-49.2,-52.0
56
+ 55,0.0,0.0,0.0,0.0
57
+ 56,-14.1,-15.6,-15.9,-14.4
58
+ 57,-15.5,-17.0,-17.4,-15.8
59
+ 58,-66.9,-66.9,-67.0,-67.1
60
+ 59,-67.3,-67.2,-67.3,-67.4
61
+ 60,-1.0,-0.6,-0.8,-1.7
62
+ 61,-17.4,-18.0,-24.3,-20.0
63
+ 62,-12.7,-13.0,-23.4,-13.8
64
+ 63,-46.9,-48.1,-49.2,-52.0
@@ -68,7 +68,6 @@ def test_for_consistency(tests_path):
68
68
  'coverage',
69
69
  "pip",
70
70
  "jupyter-book",
71
- "marshmallow>=3.22, <4.0", # TODO: drop this after ParamTools is fixed
72
71
  "setuptools"
73
72
  ])
74
73
  # read conda.recipe/meta.yaml requirements
@@ -11,8 +11,8 @@ import json
11
11
  import math
12
12
  import tempfile
13
13
  import numpy as np
14
- import paramtools
15
14
  import pytest
15
+ import paramtools
16
16
  from taxcalc.parameters import Parameters, is_paramtools_format
17
17
  from taxcalc.policy import Policy
18
18
  from taxcalc.consumption import Consumption
@@ -125,7 +125,8 @@ def test_params_class(revision, expect, params_json_file):
125
125
  """
126
126
  The Params class is derived from the abstract base Parameter class.
127
127
  """
128
- # pylint: disable=too-few-public-methods,abstract-method
128
+ # pylint: disable=abstract-method
129
+
129
130
  DEFAULTS_FILE_NAME = params_json_file.name
130
131
  DEFAULTS_FILE_PATH = ''
131
132
  START_YEAR = 2001
@@ -143,6 +144,8 @@ def test_params_class(revision, expect, params_json_file):
143
144
  """
144
145
  self._update(revision, print_warnings, raise_errors)
145
146
 
147
+ # intentionally do not define a set_rates(self) method
148
+
146
149
  # test Params class
147
150
  prms = Params()
148
151
 
@@ -190,9 +193,6 @@ def test_json_file_contents(tests_path, fname):
190
193
  first_year = Policy.JSON_START_YEAR
191
194
  last_known_year = Policy.LAST_KNOWN_YEAR # for indexed parameter values
192
195
  known_years = set(range(first_year, last_known_year + 1))
193
- # for TCJA-reverting long_params
194
- long_known_years = set(range(first_year, last_known_year + 1))
195
- long_known_years.add(2026)
196
196
  # check elements in each parameter sub-dictionary
197
197
  failures = ''
198
198
  path = os.path.join(tests_path, "..", fname)
@@ -284,7 +284,6 @@ def test_parameters_mentioned(tests_path, jfname, pfname):
284
284
  path = os.path.join(tests_path, '..', pfname)
285
285
  with open(path, 'r', encoding='utf-8') as pfile:
286
286
  code_text = pfile.read()
287
- # pylint: enable=consider-using-join
288
287
  # check that each param (without leading _) is mentioned in code text
289
288
  for pname in allparams:
290
289
  if pname == "schema":
@@ -294,6 +293,7 @@ def test_parameters_mentioned(tests_path, jfname, pfname):
294
293
 
295
294
  # following tests access private methods, so pylint: disable=protected-access
296
295
 
296
+
297
297
  class ArrayParams(Parameters):
298
298
  """ArrayParams class"""
299
299
  defaults = {
@@ -498,10 +498,9 @@ def test_expand_2d_already_filled():
498
498
  """
499
499
  One of several _expand_?D tests.
500
500
  """
501
- # pylint doesn't like caps in var name, so pylint: disable=invalid-name
502
- _II_brk2 = [[36000., 72250., 36500., 48600., 72500., 36250.],
503
- [38000., 74000., 36900., 49400., 73800., 36900.],
504
- [40000., 74900., 37450., 50200., 74900., 37450.]]
501
+ ii_brk2 = [[36000., 72250., 36500., 48600., 72500., 36250.],
502
+ [38000., 74000., 36900., 49400., 73800., 36900.],
503
+ [40000., 74900., 37450., 50200., 74900., 37450.]]
505
504
 
506
505
  years = [2013, 2014, 2015]
507
506
  params = ArrayParams(
@@ -509,27 +508,28 @@ def test_expand_2d_already_filled():
509
508
  label_to_extend=None,
510
509
  )
511
510
  params.adjust({
512
- "II_brk2": params.from_array("II_brk2", np.array(_II_brk2), year=years)
511
+ "II_brk2": params.from_array("II_brk2", np.array(ii_brk2), year=years)
513
512
  })
514
513
 
515
514
  params.extend(
516
515
  params=["II_brk2"], label="year", label_values=years
517
516
  )
518
517
  res = params.to_array("II_brk2", year=years)
519
- assert np.allclose(res, np.array(_II_brk2), atol=0.01, rtol=0.0)
518
+ assert np.allclose(res, np.array(ii_brk2), atol=0.01, rtol=0.0)
520
519
 
521
520
 
522
521
  def test_expand_2d_partial_expand():
523
522
  """
524
523
  One of several _expand_?D tests.
525
524
  """
526
- # pylint doesn't like caps in var name, so pylint: disable=invalid-name
527
- _II_brk2 = [[36000.0, 72250.0, 36500.0, 48600.0, 72500.0, 36250.0],
528
- [38000.0, 74000.0, 36900.0, 49400.0, 73800.0, 36900.0],
529
- [40000.0, 74900.0, 37450.0, 50200.0, 74900.0, 37450.0]]
525
+ ii_brk2 = [
526
+ [36000.0, 72250.0, 36500.0, 48600.0, 72500.0, 36250.0],
527
+ [38000.0, 74000.0, 36900.0, 49400.0, 73800.0, 36900.0],
528
+ [40000.0, 74900.0, 37450.0, 50200.0, 74900.0, 37450.0],
529
+ ]
530
530
  # We have three years worth of data, need 4 years worth,
531
531
  # but we only need the inflation rate for year 3 to go
532
- # from year 3 -> year 4
532
+ # from year 3 to year 4
533
533
  inf_rates = [0.02, 0.02, 0.03]
534
534
  exp1 = 40000. * 1.03
535
535
  exp2 = 74900. * 1.03
@@ -545,11 +545,7 @@ def test_expand_2d_partial_expand():
545
545
  years = [2013, 2014, 2015]
546
546
  params = ArrayParams(array_first=False, label_to_extend=None)
547
547
  params.adjust({
548
- "II_brk2": params.from_array(
549
- "II_brk2",
550
- np.array(_II_brk2),
551
- year=years
552
- )
548
+ "II_brk2": params.from_array("II_brk2", np.array(ii_brk2), year=years)
553
549
  })
554
550
  params._inflation_rates[:3] = inf_rates
555
551
  params.extend(