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.
Files changed (47) 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.py +14 -9
  6. taxcalc/data.py +8 -8
  7. taxcalc/decorators.py +3 -3
  8. taxcalc/growdiff.py +6 -6
  9. taxcalc/growfactors.py +1 -1
  10. taxcalc/parameters.py +91 -47
  11. taxcalc/policy.py +23 -7
  12. taxcalc/records.py +1 -0
  13. taxcalc/records_variables.json +6 -0
  14. taxcalc/reforms/ext.json +1 -1
  15. taxcalc/taxcalcio.py +88 -73
  16. taxcalc/tests/cmpi_cps_expect.txt +6 -6
  17. taxcalc/tests/cmpi_puf_expect.txt +6 -6
  18. taxcalc/tests/conftest.py +42 -41
  19. taxcalc/tests/test_4package.py +47 -3
  20. taxcalc/tests/test_benefits.py +9 -8
  21. taxcalc/tests/test_calcfunctions.py +55 -38
  22. taxcalc/tests/test_calculator.py +14 -10
  23. taxcalc/tests/test_compare.py +44 -50
  24. taxcalc/tests/test_compatible_data.py +9 -7
  25. taxcalc/tests/test_consumption.py +41 -22
  26. taxcalc/tests/test_cpscsv.py +81 -31
  27. taxcalc/tests/test_data.py +31 -24
  28. taxcalc/tests/test_decorators.py +84 -32
  29. taxcalc/tests/test_growdiff.py +20 -19
  30. taxcalc/tests/test_growfactors.py +8 -8
  31. taxcalc/tests/test_parameters.py +54 -58
  32. taxcalc/tests/test_policy.py +16 -14
  33. taxcalc/tests/test_puf_var_stats.py +14 -14
  34. taxcalc/tests/test_pufcsv.py +40 -40
  35. taxcalc/tests/test_records.py +73 -60
  36. taxcalc/tests/test_reforms.py +34 -31
  37. taxcalc/tests/test_responses.py +4 -4
  38. taxcalc/tests/test_taxcalcio.py +76 -62
  39. taxcalc/tests/test_utils.py +78 -46
  40. taxcalc/utils.py +49 -42
  41. taxcalc/validation/taxsim35/taxsim_emulation.json +1 -5
  42. {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/METADATA +23 -11
  43. {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/RECORD +47 -47
  44. {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/WHEEL +1 -1
  45. {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/LICENSE +0 -0
  46. {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/entry_points.txt +0 -0
  47. {taxcalc-4.3.5.dist-info → taxcalc-4.4.1.dist-info}/top_level.txt +0 -0
taxcalc/calculator.py CHANGED
@@ -93,7 +93,8 @@ class Calculator():
93
93
 
94
94
  def __init__(self, policy=None, records=None, verbose=False,
95
95
  sync_years=True, consumption=None):
96
- # pylint: disable=too-many-arguments,too-many-branches
96
+ # pylint: disable=too-many-arguments,too-many-positional-arguments
97
+ # pylint: disable=too-many-branches
97
98
  if isinstance(policy, Policy):
98
99
  self.__policy = copy.deepcopy(policy)
99
100
  else:
@@ -286,8 +287,7 @@ class Calculator():
286
287
  val = getattr(self.__policy, param_name)
287
288
  if param_name.startswith("_"):
288
289
  return val
289
- else:
290
- return val[0] # drop down a dimension.
290
+ return val[0] # drop down a dimension.
291
291
  setattr(self.__policy, param_name, param_value)
292
292
  return None
293
293
 
@@ -345,8 +345,8 @@ class Calculator():
345
345
  max_num_years = self.__policy.end_year - self.__policy.current_year + 1
346
346
  assert num_years <= max_num_years
347
347
  calc = copy.deepcopy(self)
348
- yearlist = list()
349
- varlist = list()
348
+ yearlist = []
349
+ varlist = []
350
350
  for iyr in range(1, num_years + 1):
351
351
  calc.calc_all()
352
352
  yearlist.append(calc.current_year)
@@ -626,8 +626,8 @@ class Calculator():
626
626
  'e20100', Charity non-cash contributions;
627
627
  'k1bx14p', Partnership income (also included in e26270 and e02000).
628
628
  """
629
- # pylint: disable=too-many-arguments,too-many-statements
630
- # pylint: disable=too-many-locals,too-many-branches
629
+ # pylint: disable=too-many-arguments,too-many-positional-arguments
630
+ # pylint: disable=too-many-locals,too-many-branches,too-many-statements
631
631
  assert not zero_out_calculated_vars or not calc_all_already_called
632
632
  # check validity of variable_str parameter
633
633
  if variable_str not in Calculator.MTR_VALID_VARIABLES:
@@ -824,7 +824,9 @@ class Calculator():
824
824
  -------
825
825
  graph that is a bokeh.plotting figure object
826
826
  """
827
- # pylint: disable=too-many-arguments,too-many-locals
827
+ # pylint: disable=too-many-arguments,too-many-positional-arguments
828
+ # pylint: disable=too-many-locals
829
+
828
830
  # check that two Calculator objects are comparable
829
831
  assert isinstance(calc, Calculator)
830
832
  assert calc.current_year == self.current_year
@@ -833,9 +835,8 @@ class Calculator():
833
835
  assert mars == 'ALL' or 1 <= mars <= 4
834
836
  # check validity of income_measure
835
837
  assert income_measure in ('expanded_income', 'agi', 'wages')
836
- if income_measure == 'expanded_income':
837
- income_variable = 'expanded_income'
838
- elif income_measure == 'agi':
838
+ income_variable = 'expanded_income'
839
+ if income_measure == 'agi':
839
840
  income_variable = 'c00100'
840
841
  elif income_measure == 'wages':
841
842
  income_variable = 'e00200'
@@ -848,15 +849,15 @@ class Calculator():
848
849
  (mtr2_ptax, mtr2_itax,
849
850
  mtr2_combined) = calc.mtr(variable_str=mtr_variable,
850
851
  wrt_full_compensation=mtr_wrt_full_compen)
851
- if mtr_measure == 'combined':
852
- mtr1 = mtr1_combined
853
- mtr2 = mtr2_combined
854
- elif mtr_measure == 'itax':
852
+ if mtr_measure == 'itax':
855
853
  mtr1 = mtr1_itax
856
854
  mtr2 = mtr2_itax
857
855
  elif mtr_measure == 'ptax':
858
856
  mtr1 = mtr1_ptax
859
857
  mtr2 = mtr2_ptax
858
+ else:
859
+ mtr1 = mtr1_combined
860
+ mtr2 = mtr2_combined
860
861
  # extract datafames needed by mtr_graph_data utility function
861
862
  record_variables = ['s006', 'XTOT']
862
863
  if mars != 'ALL':
@@ -1042,17 +1043,15 @@ class Calculator():
1042
1043
  # construct data for graph
1043
1044
  data = pch_graph_data(vdf, year=self.current_year,
1044
1045
  pop_quantiles=pop_quantiles)
1045
- del vdf
1046
- del vdf1
1047
- del vdf2
1048
1046
  # construct figure from data
1049
- fig = pch_graph_plot(data,
1050
- width=850,
1051
- height=500,
1052
- xlabel='',
1053
- ylabel='',
1054
- title='')
1055
- del data
1047
+ # (see comment at end of pch_graph_plot function in utils.py)
1048
+ fig = pch_graph_plot( # pylint: disable=assignment-from-no-return
1049
+ data,
1050
+ width=850,
1051
+ height=500,
1052
+ xlabel='',
1053
+ ylabel='',
1054
+ title='')
1056
1055
  return fig
1057
1056
 
1058
1057
  REQUIRED_REFORM_KEYS = set(['policy'])
@@ -1101,7 +1100,7 @@ class Calculator():
1101
1100
  suitable as input into the GrowDiff.update_growdiff method.
1102
1101
  """
1103
1102
  # construct the composite dictionary
1104
- param_dict = dict()
1103
+ param_dict = {}
1105
1104
  param_dict['policy'] = Policy.read_json_reform(reform)
1106
1105
  param_dict['consumption'] = Consumption.read_json_update(assump)
1107
1106
  for topkey in ['growdiff_baseline', 'growdiff_response']:
@@ -1165,7 +1164,7 @@ class Calculator():
1165
1164
  return [line]
1166
1165
  # all text does not fix on one line
1167
1166
  first_line = True
1168
- line_list = list()
1167
+ line_list = []
1169
1168
  words = text.split()
1170
1169
  while words:
1171
1170
  if first_line:
@@ -1189,20 +1188,20 @@ class Calculator():
1189
1188
  baseline.set_year(year)
1190
1189
  updated.set_year(year)
1191
1190
  assert set(baseline.keys()) == set(updated.keys())
1192
- params_with_diff = list()
1191
+ params_with_diff = []
1193
1192
  for pname in baseline.keys():
1194
1193
  upda_value = getattr(updated, pname)
1195
1194
  base_value = getattr(baseline, pname)
1196
1195
  is_array = isinstance(upda_value, np.ndarray)
1197
1196
  if (
1198
1197
  (is_array and not np.allclose(upda_value, base_value))
1199
- or (is_array == False and upda_value != base_value)
1198
+ or (is_array is False and upda_value != base_value)
1200
1199
  ):
1201
1200
  params_with_diff.append(pname)
1202
1201
  if params_with_diff:
1203
1202
  mdata_base = baseline.specification(meta_data=True)
1204
1203
  # write year
1205
- doc += '{}:\n'.format(year)
1204
+ doc += f'{year}:\n'
1206
1205
  for pname in sorted(params_with_diff):
1207
1206
  # write updated value line
1208
1207
  pval = getattr(updated, pname).tolist()[0]
@@ -1211,7 +1210,7 @@ class Calculator():
1211
1210
  pval = [bool(item) for item in pval]
1212
1211
  else:
1213
1212
  pval = bool(pval)
1214
- doc += ' {} : {}\n'.format(pname, pval)
1213
+ doc += f' {pname} : {pval}\n'
1215
1214
  # ... write optional param-vector-index line
1216
1215
  if isinstance(pval, list):
1217
1216
  labels = paramtools.consistent_labels(
@@ -1223,13 +1222,15 @@ class Calculator():
1223
1222
  label = _label
1224
1223
  break
1225
1224
  if label:
1225
+ # pylint: disable=protected-access
1226
1226
  lv = baseline._stateless_label_grid[label]
1227
+ # pylint: enable=protected-access
1227
1228
  lv = [
1228
1229
  str(item) for item in lv
1229
1230
  ]
1230
1231
  doc += ' ' * (
1231
1232
  4 + len(pname)
1232
- ) + '{}\n'.format(lv)
1233
+ ) + f'{lv}\n'
1233
1234
  # ... write param-name line
1234
1235
  name = mdata_base[pname]['title']
1235
1236
  for line in lines('name: ' + name, 6):
@@ -1247,7 +1248,7 @@ class Calculator():
1247
1248
  pval = [bool(item) for item in pval]
1248
1249
  elif ptype == 'bool':
1249
1250
  pval = bool(pval)
1250
- doc += ' baseline_value: {}\n'.format(pval)
1251
+ doc += f' baseline_value: {pval}\n'
1251
1252
  else: # if baseline is GrowDiff object
1252
1253
  # each GrowDiff parameter has zero as default value
1253
1254
  doc += ' baseline_value: 0.0\n'
@@ -1399,7 +1400,7 @@ class Calculator():
1399
1400
  item_phaseout = self.array('c21040').copy()
1400
1401
  item_component_variable_names = ['c17000', 'c18300', 'c19200',
1401
1402
  'c19700', 'c20500', 'c20800']
1402
- item_cvar = dict()
1403
+ item_cvar = {}
1403
1404
  for cvname in item_component_variable_names:
1404
1405
  item_cvar[cvname] = self.array(cvname).copy()
1405
1406
  self.zeroarray('c04470')
taxcalc/cli/tc.py CHANGED
@@ -23,7 +23,8 @@ def cli_tc_main():
23
23
  Contains command-line interface (CLI) to Tax-Calculator TaxCalcIO class.
24
24
  """
25
25
  # pylint: disable=too-many-statements,too-many-branches
26
- # pylint: disable=too-many-return-statements
26
+ # pylint: disable=too-many-return-statements,too-many-locals
27
+
27
28
  # parse command-line arguments:
28
29
  usage_str = 'tc INPUT TAXYEAR {}{}{}{}{}'.format(
29
30
  '[--help]\n',
@@ -254,12 +255,10 @@ def _compare_test_output_files():
254
255
  Private function that compares expected and actual tc --test output files;
255
256
  returns 0 if pass test, otherwise returns 1.
256
257
  """
257
- explines = open(
258
- EXPECTED_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8'
259
- ).readlines()
260
- actlines = open(
261
- ACTUAL_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8'
262
- ).readlines()
258
+ with open(EXPECTED_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8') as efile:
259
+ explines = efile.readlines()
260
+ with open(ACTUAL_TEST_OUTPUT_FILENAME, 'r', encoding='utf-8') as afile:
261
+ actlines = afile.readlines()
263
262
  if ''.join(explines) == ''.join(actlines):
264
263
  sys.stdout.write('PASSED TEST\n')
265
264
  retcode = 0
taxcalc/consumption.py CHANGED
@@ -20,7 +20,8 @@ class Consumption(Parameters):
20
20
 
21
21
  Parameters
22
22
  ----------
23
- none
23
+ last_budget_year: integer
24
+ user-defined last parameter extrapolation year
24
25
 
25
26
  Returns
26
27
  -------
@@ -28,14 +29,13 @@ class Consumption(Parameters):
28
29
  """
29
30
 
30
31
  JSON_START_YEAR = Policy.JSON_START_YEAR
31
- DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS
32
32
  DEFAULTS_FILE_NAME = 'consumption.json'
33
33
  DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__))
34
34
 
35
- def __init__(self):
35
+ def __init__(self, last_budget_year=Policy.LAST_BUDGET_YEAR):
36
36
  super().__init__()
37
- self.initialize(Consumption.JSON_START_YEAR,
38
- Consumption.DEFAULT_NUM_YEARS)
37
+ nyrs = Policy.number_of_years(last_budget_year)
38
+ self.initialize(Consumption.JSON_START_YEAR, nyrs)
39
39
 
40
40
  @staticmethod
41
41
  def read_json_update(obj):
@@ -68,10 +68,10 @@ class Consumption(Parameters):
68
68
  parameters are one
69
69
  """
70
70
  for var in Consumption.RESPONSE_VARS:
71
- if getattr(self, 'MPC_{}'.format(var)) > 0.0:
71
+ if getattr(self, f'MPC_{var}') > 0.0:
72
72
  return True
73
73
  for var in Consumption.BENEFIT_VARS:
74
- if getattr(self, 'BEN_{}_value'.format(var)) < 1.0:
74
+ if getattr(self, f'BEN_{var}_value') < 1.0:
75
75
  return True
76
76
  return False
77
77
 
@@ -84,12 +84,17 @@ class Consumption(Parameters):
84
84
  raise ValueError('records is not a Records object')
85
85
  for var in Consumption.RESPONSE_VARS:
86
86
  records_var = getattr(records, var)
87
- mpc_var = getattr(self, 'MPC_{}'.format(var))
87
+ mpc_var = getattr(self, f'MPC_{var}')
88
88
  records_var[:] += mpc_var * income_change
89
89
 
90
90
  def benval_params(self):
91
91
  """
92
92
  Returns list of BEN_*_value parameter values
93
93
  """
94
- return [getattr(self, 'BEN_{}_value'.format(var))
94
+ return [getattr(self, f'BEN_{var}_value')
95
95
  for var in Consumption.BENEFIT_VARS]
96
+
97
+ def set_rates(self):
98
+ """
99
+ Consumption class has no parameter indexing rates.
100
+ """
taxcalc/data.py CHANGED
@@ -63,10 +63,7 @@ class Data():
63
63
  -------
64
64
  class instance: Data
65
65
  """
66
- # suppress pylint warnings about uppercase variable names:
67
- # pylint: disable=invalid-name
68
- # suppress pylint warnings about too many class instance attributes:
69
- # pylint: disable=too-many-instance-attributes
66
+ # pylint: disable=too-many-instance-attributes,invalid-name
70
67
 
71
68
  __metaclass__ = abc.ABCMeta
72
69
 
@@ -75,6 +72,8 @@ class Data():
75
72
 
76
73
  def __init__(self, data, start_year, gfactors=None,
77
74
  weights=None, weights_scale=0.01):
75
+ # pylint: disable=too-many-arguments,too-many-positional-arguments
76
+
78
77
  # initialize data variable info sets and read variable information
79
78
  self.INTEGER_READ_VARS = set()
80
79
  self.MUST_READ_VARS = set()
@@ -175,12 +174,13 @@ class Data():
175
174
  file_path = os.path.join(self.VARINFO_FILE_PATH,
176
175
  self.VARINFO_FILE_NAME)
177
176
  if os.path.isfile(file_path):
178
- with open(file_path) as pfile:
177
+ with open(file_path, 'r', encoding='utf-8') as pfile:
179
178
  json_text = pfile.read()
180
179
  vardict = json_to_dict(json_text)
181
- else: # find file in conda package
182
- vardict = read_egg_json(
183
- self.VARINFO_FILE_NAME) # pragma: no cover
180
+ else: # find file in taxcalc package
181
+ vardict = read_egg_json( # pragma: no cover
182
+ self.VARINFO_FILE_NAME
183
+ )
184
184
  self.INTEGER_READ_VARS = set(k for k, v in vardict['read'].items()
185
185
  if v['type'] == 'int')
186
186
  FLOAT_READ_VARS = set(k for k, v in vardict['read'].items()
taxcalc/decorators.py CHANGED
@@ -49,7 +49,7 @@ class GetReturnNode(ast.NodeVisitor):
49
49
  """
50
50
  A NodeVisitor to get the return tuple names from a calc-style function.
51
51
  """
52
- def visit_Return(self, node): # pylint: disable=invalid-name,no-self-use
52
+ def visit_Return(self, node): # pylint: disable=invalid-name
53
53
  """
54
54
  visit_Return is used by NodeVisitor.visit method.
55
55
  """
@@ -89,7 +89,7 @@ def create_apply_function_string(sigout, sigin, parameters):
89
89
  out_args = ["x_" + str(i) for i in range(0, len(sigout))]
90
90
  in_args = ["x_" + str(i) for i in range(len(sigout), total_len)]
91
91
 
92
- fstr.write("def ap_func({0}):\n".format(",".join(out_args + in_args)))
92
+ fstr.write(f"def ap_func({','.join(out_args + in_args)}):\n")
93
93
  fstr.write(" for i in range(len(x_0)):\n")
94
94
  out_index = [x + "[i]" for x in out_args]
95
95
  in_index = []
@@ -257,7 +257,7 @@ def iterate_jit(parameters=None, **kwargs):
257
257
  in_args = inspect.getfullargspec(func).args
258
258
  # Get the numba.jit arguments
259
259
  jit_args_list = inspect.getfullargspec(JIT).args + ['nopython']
260
- kwargs_for_jit = dict()
260
+ kwargs_for_jit = {}
261
261
  for key, val in kwargs.items():
262
262
  if key in jit_args_list:
263
263
  kwargs_for_jit[key] = val
taxcalc/growdiff.py CHANGED
@@ -20,7 +20,8 @@ class GrowDiff(Parameters):
20
20
 
21
21
  Parameters
22
22
  ----------
23
- none
23
+ last_budget_year: integer
24
+ user-defined last parameter extrapolation year
24
25
 
25
26
  Returns
26
27
  -------
@@ -28,14 +29,13 @@ class GrowDiff(Parameters):
28
29
  """
29
30
 
30
31
  JSON_START_YEAR = Policy.JSON_START_YEAR
31
- DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS
32
32
  DEFAULTS_FILE_NAME = 'growdiff.json'
33
33
  DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__))
34
34
 
35
- def __init__(self):
35
+ def __init__(self, last_budget_year=Policy.LAST_BUDGET_YEAR):
36
36
  super().__init__()
37
- self.initialize(GrowDiff.JSON_START_YEAR,
38
- GrowDiff.DEFAULT_NUM_YEARS)
37
+ nyrs = Policy.number_of_years(last_budget_year)
38
+ self.initialize(GrowDiff.JSON_START_YEAR, nyrs)
39
39
 
40
40
  @staticmethod
41
41
  def read_json_update(obj, topkey):
@@ -84,5 +84,5 @@ class GrowDiff(Parameters):
84
84
 
85
85
  def set_rates(self):
86
86
  """
87
- Unimplemented base class method that is not used here.
87
+ GrowDiff class has no parameter indexing rates.
88
88
  """
taxcalc/growfactors.py CHANGED
@@ -165,6 +165,6 @@ class GrowFactors():
165
165
  msg = 'cannot update growfactors after they have been used'
166
166
  raise ValueError(msg)
167
167
  assert name in GrowFactors.VALID_NAMES
168
- if year >= self.first_year and year <= self.last_year:
168
+ if self.first_year <= year <= self.last_year:
169
169
  assert isinstance(diff, float)
170
170
  self.gfdf.loc[year, name] += diff