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/__init__.py CHANGED
@@ -14,6 +14,6 @@ from taxcalc.taxcalcio import *
14
14
  from taxcalc.utils import *
15
15
  from taxcalc.cli import *
16
16
 
17
- __version__ = '4.6.1'
17
+ __version__ = '4.6.3'
18
18
  __min_python3_version__ = 10
19
19
  __max_python3_version__ = 12
taxcalc/calcfunctions.py CHANGED
@@ -3190,7 +3190,7 @@ def NonrefundableCredits(c05800, e07240, e07260, e07300, e07400,
3190
3190
  @iterate_jit(nopython=True)
3191
3191
  def AdditionalCTC(codtc_limited, ACTC_c, n24, earned, ACTC_Income_thd,
3192
3192
  ACTC_rt, nu06, ACTC_rt_bonus_under6family, ACTC_ChildNum,
3193
- CTC_is_refundable, CTC_include17,
3193
+ CTC_is_refundable, CTC_include17, CTC_c,
3194
3194
  age_head, age_spouse, MARS, nu18,
3195
3195
  ptax_was, c03260, e09800, c59660, e11200,
3196
3196
  c11070):
@@ -3251,7 +3251,7 @@ def AdditionalCTC(codtc_limited, ACTC_c, n24, earned, ACTC_Income_thd,
3251
3251
  childnum = n24 + max(0, nu18 - tu18 - su18 - n24)
3252
3252
  else:
3253
3253
  childnum = n24
3254
- line4 = ACTC_c * childnum
3254
+ line4 = min(ACTC_c, CTC_c) * childnum
3255
3255
  c11070 = 0. # line15
3256
3256
  if line3 > 0. and line4 > 0.:
3257
3257
  line5 = min(line3, line4)
taxcalc/cli/tc.py CHANGED
@@ -43,7 +43,7 @@ def cli_tc_main():
43
43
  ),
44
44
  (
45
45
  ' '
46
- '[--silent] [--test] [--version] [--usage]'
46
+ '[--runid N] [--silent] [--test] [--version] [--usage]'
47
47
  )
48
48
  )
49
49
  parser = argparse.ArgumentParser(
@@ -75,20 +75,20 @@ def cli_tc_main():
75
75
  parser.add_argument('--baseline',
76
76
  help=('BASELINE is name of optional JSON reform file. '
77
77
  'A compound reform can be specified using 2+ '
78
- 'file names separated by plus (+) character(s). '
78
+ 'file names connected by plus (+) character(s). '
79
79
  'No --baseline implies baseline policy is '
80
80
  'current-law policy.'),
81
81
  default=None)
82
82
  parser.add_argument('--reform',
83
83
  help=('REFORM is name of optional JSON reform file. '
84
84
  'A compound reform can be specified using 2+ '
85
- 'file names separated by plus (+) character(s). '
85
+ 'file names connected by plus (+) character(s). '
86
86
  'No --reform implies reform policy is '
87
87
  'current-law policy).'),
88
88
  default=None)
89
89
  parser.add_argument('--assump',
90
90
  help=('ASSUMP is name of optional JSON economic '
91
- 'assumptions file. No --assump implies use '
91
+ 'assumptions file. No --assump implies use '
92
92
  'of no customized assumptions.'),
93
93
  default=None)
94
94
  parser.add_argument('--exact',
@@ -125,12 +125,19 @@ def cli_tc_main():
125
125
  parser.add_argument('--dumpvars',
126
126
  help=('DUMPVARS is name of optional file containing a '
127
127
  'space-delimited list of variables to include '
128
- 'in the dump database. No --dumpvars '
129
- 'implies a minimal set of variables. Valid '
130
- 'variable names include all variables in the '
128
+ 'in the dump database. No --dumpvars implies '
129
+ 'a minimal set of variables. Valid variable '
130
+ 'names include all variables in the '
131
131
  'records_variables.json file plus mtr_itax and '
132
132
  'mtr_ptax (MTRs wrt taxpayer earnings).'),
133
133
  default=None)
134
+ parser.add_argument('--runid', metavar='N',
135
+ help=('N is a positive integer run id that is used '
136
+ 'to construct simpler output file names. '
137
+ 'No --runid implies legacy output file names '
138
+ 'are used.'),
139
+ type=int,
140
+ default=0)
134
141
  parser.add_argument('--silent',
135
142
  help=('optional flag that suppresses messages about '
136
143
  'input and output actions.'),
@@ -153,16 +160,23 @@ def cli_tc_main():
153
160
  default=False,
154
161
  action="store_true")
155
162
  args = parser.parse_args()
163
+ using_error_file = args.silent and args.runid != 0
164
+ efilename = f'run{args.runid}.errors'
156
165
  # check Python version
157
166
  pyv = sys.version_info
158
167
  pymin = tc.__min_python3_version__
159
168
  pymax = tc.__max_python3_version__
160
169
  if pyv[0] != 3 or pyv[1] < pymin or pyv[1] > pymax: # pragma: no cover
161
170
  pyreq = f'at least Python 3.{pymin} and at most Python 3.{pymax}'
162
- sys.stderr.write(
171
+ msg = (
163
172
  f'ERROR: Tax-Calculator requires {pyreq}\n'
164
173
  f' but Python {pyv[0]}.{pyv[1]} is installed\n'
165
174
  )
175
+ if using_error_file:
176
+ with open(efilename, 'w', encoding='utf-8') as efile:
177
+ efile.write(msg)
178
+ else:
179
+ sys.stderr.write(msg)
166
180
  return 1
167
181
  # show Tax-Calculator version and quit if --version option is specified
168
182
  if args.version:
@@ -186,20 +200,32 @@ def cli_tc_main():
186
200
  # check taxyear value
187
201
  if taxyear > tc.Policy.LAST_BUDGET_YEAR:
188
202
  msg = f'ERROR: TAXYEAR is greater than {tc.Policy.LAST_BUDGET_YEAR}\n'
189
- sys.stderr.write(msg)
190
- sys.stderr.write('USAGE: tc --help\n')
203
+ if using_error_file:
204
+ with open(efilename, 'w', encoding='utf-8') as efile:
205
+ efile.write(msg)
206
+ else:
207
+ sys.stderr.write(msg)
208
+ sys.stderr.write('USAGE: tc --help\n')
191
209
  return 1
192
210
  # check numyears value
193
211
  if args.numyears < 1:
194
212
  msg = 'ERROR: --numyears parameter N is less than one\n'
195
- sys.stderr.write(msg)
196
- sys.stderr.write('USAGE: tc --help\n')
213
+ if using_error_file:
214
+ with open(efilename, 'w', encoding='utf-8') as efile:
215
+ efile.write(msg)
216
+ else:
217
+ sys.stderr.write(msg)
218
+ sys.stderr.write('USAGE: tc --help\n')
197
219
  return 1
198
220
  max_numyears = tc.Policy.LAST_BUDGET_YEAR - taxyear + 1
199
221
  if args.numyears > max_numyears:
200
222
  msg = f'ERROR: --numyears parameter N is greater than {max_numyears}\n'
201
- sys.stderr.write(msg)
202
- sys.stderr.write('USAGE: tc --help\n')
223
+ if using_error_file:
224
+ with open(efilename, 'w', encoding='utf-8') as efile:
225
+ efile.write(msg)
226
+ else:
227
+ sys.stderr.write(msg)
228
+ sys.stderr.write('USAGE: tc --help\n')
203
229
  return 1
204
230
  # specify if aging input data
205
231
  aging_data = (
@@ -210,8 +236,12 @@ def cli_tc_main():
210
236
  # check args.dumpdb and args.dumpvars consistency
211
237
  if not args.dumpdb and args.dumpvars:
212
238
  msg = 'ERROR: DUMPVARS file specified without --dumpdb option\n'
213
- sys.stderr.write(msg)
214
- sys.stderr.write('USAGE: tc --help\n')
239
+ if using_error_file:
240
+ with open(efilename, 'w', encoding='utf-8') as efile:
241
+ efile.write(msg)
242
+ else:
243
+ sys.stderr.write(msg)
244
+ sys.stderr.write('USAGE: tc --help\n')
215
245
  return 1
216
246
  # specify dumpvars_str from args.dumpvars file
217
247
  dumpvars_str = ''
@@ -221,9 +251,22 @@ def cli_tc_main():
221
251
  dumpvars_str = dfile.read()
222
252
  else:
223
253
  msg = f'ERROR: DUMPVARS file {args.dumpvars} does not exist\n'
254
+ if using_error_file:
255
+ with open(efilename, 'w', encoding='utf-8') as efile:
256
+ efile.write(msg)
257
+ else:
258
+ sys.stderr.write(msg)
259
+ sys.stderr.write('USAGE: tc --help\n')
260
+ return 1
261
+ if args.runid < 0:
262
+ msg = 'ERROR: --runid parameter N is less than zero\n'
263
+ if using_error_file:
264
+ with open(efilename, 'w', encoding='utf-8') as efile:
265
+ efile.write(msg)
266
+ else:
224
267
  sys.stderr.write(msg)
225
268
  sys.stderr.write('USAGE: tc --help\n')
226
- return 1
269
+ return 1
227
270
  # do calculations for taxyear
228
271
  # ... initialize TaxCalcIO object for taxyear
229
272
  tcio = tc.TaxCalcIO(
@@ -232,14 +275,19 @@ def cli_tc_main():
232
275
  baseline=args.baseline,
233
276
  reform=args.reform,
234
277
  assump=args.assump,
278
+ runid=args.runid,
235
279
  silent=args.silent,
236
280
  )
237
281
  if tcio.errmsg:
238
- if tcio.errmsg.endswith('\n'):
239
- sys.stderr.write(tcio.errmsg)
282
+ msg = tcio.errmsg
283
+ if not msg.endswith('\n'):
284
+ msg += '\n'
285
+ if using_error_file:
286
+ with open(efilename, 'w', encoding='utf-8') as efile:
287
+ efile.write(msg)
240
288
  else:
241
- sys.stderr.write(tcio.errmsg + '\n')
242
- sys.stderr.write('USAGE: tc --help\n')
289
+ sys.stderr.write(msg)
290
+ sys.stderr.write('USAGE: tc --help\n')
243
291
  return 1
244
292
  tcio.init(
245
293
  input_data=inputfn,
@@ -251,19 +299,27 @@ def cli_tc_main():
251
299
  exact_calculations=args.exact,
252
300
  )
253
301
  if tcio.errmsg:
254
- if tcio.errmsg.endswith('\n'):
255
- sys.stderr.write(tcio.errmsg)
302
+ msg = tcio.errmsg
303
+ if not msg.endswith('\n'):
304
+ msg += '\n'
305
+ if using_error_file:
306
+ with open(efilename, 'w', encoding='utf-8') as efile:
307
+ efile.write(msg)
256
308
  else:
257
- sys.stderr.write(tcio.errmsg + '\n')
258
- sys.stderr.write('USAGE: tc --help\n')
309
+ sys.stderr.write(msg)
310
+ sys.stderr.write('USAGE: tc --help\n')
259
311
  return 1
260
312
  # ... conduct tax analysis for taxyear
261
313
  dumpvars_list = tcio.dump_variables(dumpvars_str)
262
314
  if tcio.errmsg:
263
- if tcio.errmsg.endswith('\n'):
264
- sys.stderr.write(tcio.errmsg)
315
+ msg = tcio.errmsg
316
+ if not msg.endswith('\n'):
317
+ msg += '\n'
318
+ if using_error_file:
319
+ with open(efilename, 'w', encoding='utf-8') as efile:
320
+ efile.write(msg)
265
321
  else:
266
- sys.stderr.write(tcio.errmsg + '\n')
322
+ sys.stderr.write(msg)
267
323
  sys.stderr.write('USAGE: tc --help\n')
268
324
  return 1
269
325
  tcio.analyze(
@@ -313,7 +369,7 @@ EXPECTED_TEST_OUTPUT = (
313
369
  '1|131.88\n'
314
370
  '2|28879.00\n'
315
371
  )
316
- TEST_DUMPDB_FILENAME = f'test-{str(TEST_TAXYEAR)[2:]}-#-#-#.db'
372
+ TEST_DUMPDB_FILENAME = f'test-{str(TEST_TAXYEAR)[2:]}-#-#-#.dumpdb'
317
373
  TEST_SQLITE_QUERY = """
318
374
  SELECT
319
375
  RECID AS id,