diff --git a/conda.recipe/meta.yaml b/conda.recipe/meta.yaml index d618a778f..261d52f08 100755 --- a/conda.recipe/meta.yaml +++ b/conda.recipe/meta.yaml @@ -9,22 +9,24 @@ build: requirements: build: - "python>=3.10, <3.13" - - "numpy>=1.26,<1.27" + - "numpy>=1.26" - "pandas>=2.2" - "bokeh>=2.4" - - "paramtools>=0.18.3" + - "paramtools>=0.19.0" - numba + - requests - curl - openpyxl - behresp run: - "python>=3.10, <3.13" - - "numpy>=1.26,<1.27" + - "numpy>=1.26" - "pandas>=2.2" - "bokeh>=2.4" - - "paramtools>=0.18.3" + - "paramtools>=0.19.0" - numba + - requests - curl - openpyxl - behresp diff --git a/environment.yml b/environment.yml index 8032c1e8d..a087bf959 100644 --- a/environment.yml +++ b/environment.yml @@ -3,11 +3,13 @@ channels: - conda-forge dependencies: - "python>=3.10, <3.13" -- "numpy>=1.26,<1.27" +- "numpy>=1.26" - "pandas>=2.2" - "bokeh>=2.4" - numba +- requests - curl +- setuptools - pytest - pytest-xdist - pycodestyle @@ -18,4 +20,4 @@ dependencies: - pip - pip: - jupyter-book - - "paramtools>=0.18.3" + - "paramtools>=0.19.0" diff --git a/setup.py b/setup.py index fb16ce918..4ee4a2665 100644 --- a/setup.py +++ b/setup.py @@ -18,13 +18,12 @@ "include_package_data": True, "name": "taxcalc", "install_requires": [ - "setuptools", - "numpy", - "pandas", - "bokeh", + "numpy>=1.26", + "pandas>=2.2", + "bokeh>=2.4", "numba", "requests", - "paramtools>=0.18.3", + "paramtools>=0.19.0", ], "classifiers": [ "Development Status :: 4 - Beta", diff --git a/taxcalc.egg-info/PKG-INFO b/taxcalc.egg-info/PKG-INFO index 60eb54244..34725fec3 100644 --- a/taxcalc.egg-info/PKG-INFO +++ b/taxcalc.egg-info/PKG-INFO @@ -18,13 +18,12 @@ Classifier: Programming Language :: Python :: 3.12 Classifier: Topic :: Software Development :: Libraries :: Python Modules Description-Content-Type: text/markdown License-File: LICENSE -Requires-Dist: setuptools -Requires-Dist: numpy -Requires-Dist: pandas -Requires-Dist: bokeh +Requires-Dist: numpy>=1.26 +Requires-Dist: pandas>=2.2 +Requires-Dist: bokeh>=2.4 Requires-Dist: numba Requires-Dist: requests -Requires-Dist: paramtools>=0.18.3 +Requires-Dist: paramtools>=0.19.0 | | | | --- | --- | diff --git a/taxcalc.egg-info/SOURCES.txt b/taxcalc.egg-info/SOURCES.txt index 9ca90b177..b0b44cb99 100644 --- a/taxcalc.egg-info/SOURCES.txt +++ b/taxcalc.egg-info/SOURCES.txt @@ -19,6 +19,7 @@ pyproject.toml pytest.ini setup.py tctest-nojit.sh +update_pcl.py .github/FUNDING.yml .github/workflows/build_and_test.yml .github/workflows/check_jupyterbook.yml @@ -172,6 +173,8 @@ taxcalc/reforms/ptaxes2.json taxcalc/reforms/ptaxes2.out.csv taxcalc/reforms/ptaxes3.json taxcalc/reforms/ptaxes3.out.csv +taxcalc/reforms/rounding.json +taxcalc/reforms/rounding.out.csv taxcalc/reforms/archive/Clinton2016.json taxcalc/reforms/archive/RyanBrady.json taxcalc/reforms/archive/TCJA_House.json @@ -238,4 +241,6 @@ taxcalc/validation/taxsim35/expected_differences/b20-taxdiffs-expect.csv taxcalc/validation/taxsim35/expected_differences/b21-taxdiffs-expect.csv taxcalc/validation/taxsim35/expected_differences/c17-taxdiffs-expect.csv taxcalc/validation/taxsim35/expected_differences/c18-taxdiffs-expect.csv -taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv \ No newline at end of file +taxcalc/validation/taxsim35/expected_differences/c19-taxdiffs-expect.csv +taxcalc/validation/taxsim35/expected_differences/c20-taxdiffs-expect.csv +taxcalc/validation/taxsim35/expected_differences/c21-taxdiffs-expect.csv \ No newline at end of file diff --git a/taxcalc.egg-info/requires.txt b/taxcalc.egg-info/requires.txt index 2e5f43376..a5c9f5570 100644 --- a/taxcalc.egg-info/requires.txt +++ b/taxcalc.egg-info/requires.txt @@ -1,7 +1,6 @@ -setuptools -numpy -pandas -bokeh +numpy>=1.26 +pandas>=2.2 +bokeh>=2.4 numba requests -paramtools>=0.18.3 +paramtools>=0.19.0 diff --git a/taxcalc/calculator.py b/taxcalc/calculator.py index 3c1cac849..7a757d1ae 100644 --- a/taxcalc/calculator.py +++ b/taxcalc/calculator.py @@ -105,7 +105,8 @@ def __init__(self, policy=None, records=None, verbose=False, if self.__policy.current_year < self.__records.data_year: self.__policy.set_year(self.__records.data_year) if consumption is None: - self.__consumption = Consumption() + print("CONS policy num years = ", policy.NUM_YEARS) + self.__consumption = Consumption(policy.NUM_YEARS) elif isinstance(consumption, Consumption): self.__consumption = copy.deepcopy(consumption) else: diff --git a/taxcalc/cli/tc.py b/taxcalc/cli/tc.py index f27fc3c40..140539ccd 100644 --- a/taxcalc/cli/tc.py +++ b/taxcalc/cli/tc.py @@ -27,6 +27,8 @@ def cli_tc_main(): # parse command-line arguments: usage_str = 'tc INPUT TAXYEAR {}{}{}{}{}'.format( '[--help]\n', + (' ' + '[--budgetend BUDGETENDYEAR]\n'), (' ' '[--baseline BASELINE] [--reform REFORM] [--assump ASSUMP]\n'), (' ' @@ -56,6 +58,15 @@ def cli_tc_main(): 'are computed.'), type=int, default=0) + parser.add_argument('--budgetend', + help=('BUDGETENDYEAR is name of optional ' + 'calendar year that is the last year ' + 'of the budget window to be analyzed. ' + 'No --budget implies the budget window ' + 'extends until ' + 'Policy.DEFAULT_LAST_BUDGET_YEAR.'), + type=int, + default=None) parser.add_argument('--baseline', help=('BASELINE is name of optional JSON reform file. ' 'No --baseline implies baseline policy is ' @@ -164,6 +175,7 @@ def cli_tc_main(): taxyear = args.TAXYEAR # instantiate TaxCalcIO object and do tax analysis tcio = tc.TaxCalcIO(input_data=inputfn, tax_year=taxyear, + budget_end_year=args.budgetend, baseline=args.baseline, reform=args.reform, assump=args.assump, outdir=args.outdir) @@ -179,6 +191,7 @@ def cli_tc_main(): if args.timings: stime = time.time() tcio.init(input_data=inputfn, tax_year=taxyear, + budget_end_year=args.budgetend, baseline=args.baseline, reform=args.reform, assump=args.assump, aging_input_data=aging, diff --git a/taxcalc/consumption.py b/taxcalc/consumption.py index 0be9ea904..0b71f65ce 100644 --- a/taxcalc/consumption.py +++ b/taxcalc/consumption.py @@ -28,14 +28,16 @@ class instance: Consumption """ JSON_START_YEAR = Policy.JSON_START_YEAR - DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS + NUM_YEARS = Policy.NUM_YEARS DEFAULTS_FILE_NAME = 'consumption.json' DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__)) - def __init__(self): + def __init__(self, nyrs=NUM_YEARS): + # put JSON contents of DEFAULTS_FILE_NAME into self._vals dictionary super().__init__() + print("CONS policy num years = ", nyrs) self.initialize(Consumption.JSON_START_YEAR, - Consumption.DEFAULT_NUM_YEARS) + nyrs) @staticmethod def read_json_update(obj): diff --git a/taxcalc/growdiff.py b/taxcalc/growdiff.py index e4cc4ac9e..c1489659a 100644 --- a/taxcalc/growdiff.py +++ b/taxcalc/growdiff.py @@ -28,14 +28,13 @@ class instance: GrowDiff """ JSON_START_YEAR = Policy.JSON_START_YEAR - DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS + NUM_YEARS = Policy.NUM_YEARS DEFAULTS_FILE_NAME = 'growdiff.json' DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__)) - def __init__(self): - super().__init__() + def __init__(self, nyrs=NUM_YEARS): self.initialize(GrowDiff.JSON_START_YEAR, - GrowDiff.DEFAULT_NUM_YEARS) + nyrs) @staticmethod def read_json_update(obj, topkey): diff --git a/taxcalc/growfactors.py b/taxcalc/growfactors.py index 8be68f1fb..a1f89a749 100644 --- a/taxcalc/growfactors.py +++ b/taxcalc/growfactors.py @@ -84,6 +84,7 @@ def __init__(self, growfactors_filename=None): # determine first_year and last_year from gfdf self._first_year = min(gfdf.index) self._last_year = max(gfdf.index) + print("IN Gfactors last year is ", self._last_year) # set gfdf as attribute of class self.gfdf = pd.DataFrame() setattr(self, 'gfdf', gfdf.astype(np.float64)) diff --git a/taxcalc/parameters.py b/taxcalc/parameters.py index 2ec9ba004..ce600debe 100644 --- a/taxcalc/parameters.py +++ b/taxcalc/parameters.py @@ -99,6 +99,7 @@ def __init__(self, start_year=None, num_years=None, last_known_year=None, self.DEFAULTS_FILE_NAME ) + self.LAST_BUDGET_YEAR = start_year + num_years - 1 if last_known_year is None: self._last_known_year = start_year else: @@ -118,6 +119,10 @@ def __init__(self, start_year=None, num_years=None, last_known_year=None, kwargs["initial_state"] = { "year": start_year or self.JSON_START_YEAR } + # Update defaults to user defined budget window + self.defaults = super().get_defaults() + label = self.defaults["schema"]["labels"]["year"] + label["validators"]["range"]["max"] = self.LAST_BUDGET_YEAR super().__init__(**kwargs) def adjust( @@ -817,4 +822,4 @@ def is_paramtools_format(params: Union[TaxcalcReform, ParamToolsAdjustment]): else: # Not doing a specific check to see if the value is a list # since it could be a list or just a scalar value. - return True + return True \ No newline at end of file diff --git a/taxcalc/policy.py b/taxcalc/policy.py index 8f101dd6d..39838fd95 100644 --- a/taxcalc/policy.py +++ b/taxcalc/policy.py @@ -39,9 +39,8 @@ class instance: Policy JSON_START_YEAR = 2013 # remains the same unless earlier data added LAST_KNOWN_YEAR = 2025 # last year for which indexed param vals are known # should increase LAST_KNOWN_YEAR by one every calendar year - LAST_BUDGET_YEAR = 2034 # last extrapolation year - # should increase LAST_BUDGET_YEAR by one every calendar year - DEFAULT_NUM_YEARS = LAST_BUDGET_YEAR - JSON_START_YEAR + 1 + DEFAULT_LAST_BUDGET_YEAR = 2034 # last extrapolation year + NUM_YEARS = DEFAULT_LAST_BUDGET_YEAR - JSON_START_YEAR + 1 # NOTE: the following three data structures use internal parameter names: # (1) specify which Policy parameters have been removed or renamed @@ -80,7 +79,9 @@ class instance: Policy # (3) specify which Policy parameters are wage (rather than price) indexed WAGE_INDEXED_PARAMS = ['SS_Earnings_c', 'SS_Earnings_thd'] - def __init__(self, gfactors=None, **kwargs): + def __init__(self, gfactors=None, + last_budget_year=DEFAULT_LAST_BUDGET_YEAR, + **kwargs): # put JSON contents of DEFAULTS_FILE_NAME into self._vals dictionary super().__init__() # handle gfactors argument @@ -92,7 +93,8 @@ def __init__(self, gfactors=None, **kwargs): raise ValueError('gfactors is not None or a GrowFactors instance') # read default parameters and initialize syr = Policy.JSON_START_YEAR - nyrs = Policy.DEFAULT_NUM_YEARS + nyrs = last_budget_year - syr + 1 + Policy.NUM_YEARS = nyrs self._inflation_rates = None self._wage_growth_rates = None self.initialize(syr, nyrs, Policy.LAST_KNOWN_YEAR, @@ -101,7 +103,8 @@ def __init__(self, gfactors=None, **kwargs): Policy.WAGE_INDEXED_PARAMS, **kwargs) @staticmethod - def tmd_constructor(growfactors: Path | GrowFactors): # pragma: no cover + def tmd_constructor(growfactors: Path | GrowFactors, + last_budget_year=DEFAULT_LAST_BUDGET_YEAR): # pragma: no cover """ Static method returns a Policy object instantiated with TMD input data. This convenience method works in a analogous way @@ -112,7 +115,8 @@ def tmd_constructor(growfactors: Path | GrowFactors): # pragma: no cover growfactors = GrowFactors(growfactors_filename=str(growfactors)) else: assert isinstance(growfactors, GrowFactors) - return Policy(gfactors=growfactors) + return Policy(gfactors=growfactors, + last_budget_year=last_budget_year) @staticmethod def read_json_reform(obj): diff --git a/taxcalc/taxcalcio.py b/taxcalc/taxcalcio.py index 963731c13..191f77df5 100644 --- a/taxcalc/taxcalcio.py +++ b/taxcalc/taxcalcio.py @@ -35,12 +35,16 @@ class TaxCalcIO(): string is name of INPUT file that is CSV formatted containing variable names in the Records USABLE_READ_VARS set, or Pandas DataFrame is INPUT data containing variable names in - the Records USABLE_READ_VARS set. INPUT vsrisbles not in the + the Records USABLE_READ_VARS set. INPUT variables not in the Records USABLE_READ_VARS set can be present but are ignored. tax_year: integer calendar year for which taxes will be computed for INPUT. + budget_end_year: integer + last calendar year in the budget window for which taxes will + be computed for INPUT. + baseline: None or string None implies baseline policy is current-law policy, or string is name of optional BASELINE file that is a JSON @@ -64,8 +68,8 @@ class instance: TaxCalcIO """ # pylint: disable=too-many-instance-attributes - def __init__(self, input_data, tax_year, baseline, reform, assump, - outdir=None): + def __init__(self, input_data, tax_year, budget_end_year, baseline, + reform, assump, outdir=None): # pylint: disable=too-many-arguments,too-many-locals # pylint: disable=too-many-branches,too-many-statements self.gf_reform = None @@ -228,8 +232,8 @@ def __init__(self, input_data, tax_year, baseline, reform, assump, self.param_dict = None self.policy_dicts = [] - def init(self, input_data, tax_year, baseline, reform, assump, - aging_input_data, exact_calculations): + def init(self, input_data, tax_year, budget_end_year, baseline, + reform, assump, aging_input_data, exact_calculations): """ TaxCalcIO class post-constructor method that completes initialization. @@ -253,6 +257,11 @@ def init(self, input_data, tax_year, baseline, reform, assump, basedict = Calculator.read_json_param_objects(baseline, None) # get assumption sub-dictionaries paramdict = Calculator.read_json_param_objects(None, assump) + # Set budget window end year + if budget_end_year is None: + budget_end_year = Policy.DEFAULT_LAST_BUDGET_YEAR + else: + Policy.DEFAULT_LAST_BUDGET_YEAR = budget_end_year # get policy parameter dictionaries from --reform file(s) policydicts = [] if self.specified_reform: @@ -292,7 +301,10 @@ def init(self, input_data, tax_year, baseline, reform, assump, self.gf_reform = copy.deepcopy(gfactors_ref) # create Policy objects: # ... the baseline Policy object - base = Policy(gfactors=gfactors_base) + print("GF BASE = ", gfactors_base.last_year, max(gfactors_base.gfdf.index)) + print("GF BASE = ", gfactors_base.last_year) + base = Policy(gfactors=gfactors_base, + last_budget_year=budget_end_year) try: base.implement_reform(basedict['policy'], print_warnings=True, @@ -303,7 +315,8 @@ def init(self, input_data, tax_year, baseline, reform, assump, self.errmsg += valerr_msg.__str__() # ... the reform Policy object if self.specified_reform: - pol = Policy(gfactors=gfactors_ref) + pol = Policy(gfactors=gfactors_ref, + last_budget_year=budget_end_year) for poldict in policydicts: try: pol.implement_reform(poldict, @@ -316,7 +329,8 @@ def init(self, input_data, tax_year, baseline, reform, assump, except paramtools.ValidationError as valerr_msg: self.errmsg += valerr_msg.__str__() else: - pol = Policy(gfactors=gfactors_base) + pol = Policy(gfactors=gfactors_base, + last_budget_year=budget_end_year) # create Consumption object con = Consumption() try: @@ -393,6 +407,7 @@ def init(self, input_data, tax_year, baseline, reform, assump, msg = msg.format(tax_year, recs.data_year) self.errmsg += 'ERROR: {}\n'.format(msg) # create Calculator objects + print("POLICY YEAR = ", pol.DEFAULT_LAST_BUDGET_YEAR) self.calc = Calculator(policy=pol, records=recs, verbose=True, consumption=con, diff --git a/taxcalc/tests/test_4package.py b/taxcalc/tests/test_4package.py index 6e6e89de3..0c5d24e76 100644 --- a/taxcalc/tests/test_4package.py +++ b/taxcalc/tests/test_4package.py @@ -10,6 +10,34 @@ import subprocess import yaml import pytest +import ast + + +def extract_install_requires(setup_py_content): + """ + Extract the install_requires list from a setup.py file content. + + Args: + setup_py_content (str): The full content of the setup.py file + + Returns: + list: A list of package requirements + """ + # Use regex to find the install_requires list + match = re.search(r'"install_requires"\s*:\s*\[([^\]]+)\]', setup_py_content, re.DOTALL) + + if match: + # Extract the contents of the list and split into packages + packages_str = match.group(1) + # Use ast.literal_eval to safely parse the string representations + packages = [ + ast.literal_eval(f'{pkg.strip()}') + for pkg in packages_str.split(',') + if pkg.strip() + ] + return packages + + return [] @pytest.mark.local @@ -38,6 +66,7 @@ def test_for_consistency(tests_path): 'coverage', "pip", "jupyter-book", + "setuptools" ]) # read conda.recipe/meta.yaml requirements meta_file = os.path.join(tests_path, '..', '..', @@ -65,3 +94,16 @@ def test_for_consistency(tests_path): # confirm that extras in env (relative to run) equal the dev_pkgs set extras = env - run assert extras == dev_pkgs + # Read the setup.py file and extract the install_requires list + setup_file = os.path.join(tests_path, '..', '..', + 'setup.py') + with open(setup_file, 'r') as f: + setup_py_content = f.read() + setup = set(extract_install_requires(setup_py_content)) + # confirm that setup.py + print("Setup packages = ", setup) + print("Meta packages = ", bld) + # if package in both, confirm that the version is the same + for pkg in setup.intersection(bld): + assert pkg in setup + assert pkg in bld diff --git a/taxcalc/tests/test_calculator.py b/taxcalc/tests/test_calculator.py index ac2e18004..8d0d03221 100644 --- a/taxcalc/tests/test_calculator.py +++ b/taxcalc/tests/test_calculator.py @@ -74,9 +74,9 @@ def test_make_calculator_with_policy_reform(cps_subsample): assert calc.current_year == year assert calc.policy_param('II_em') == 4000 assert np.allclose(calc.policy_param('_II_em'), - np.array([4000] * Policy.DEFAULT_NUM_YEARS)) + np.array([4000] * Policy.NUM_YEARS)) exp_STD_Aged = [[1600, 1300, 1300, - 1600, 1600]] * Policy.DEFAULT_NUM_YEARS + 1600, 1600]] * Policy.NUM_YEARS assert np.allclose(calc.policy_param('_STD_Aged'), np.array(exp_STD_Aged)) assert np.allclose(calc.policy_param('STD_Aged'), @@ -100,10 +100,10 @@ def test_make_calculator_with_multiyear_reform(cps_subsample): # create a Calculator object using this policy-reform calc = Calculator(policy=pol, records=rec) # check that Policy object embedded in Calculator object is correct - assert pol.num_years == Policy.DEFAULT_NUM_YEARS + assert pol.num_years == Policy.NUM_YEARS assert calc.current_year == year assert calc.policy_param('II_em') == 3950 - exp_II_em = [3900, 3950, 5000] + [6000] * (Policy.DEFAULT_NUM_YEARS - 3) + exp_II_em = [3900, 3950, 5000] + [6000] * (Policy.NUM_YEARS - 3) assert np.allclose(calc.policy_param('_II_em'), np.array(exp_II_em)) calc.increment_year() diff --git a/taxcalc/tests/test_consumption.py b/taxcalc/tests/test_consumption.py index eaaa24831..e7cefd767 100644 --- a/taxcalc/tests/test_consumption.py +++ b/taxcalc/tests/test_consumption.py @@ -10,7 +10,7 @@ def test_year_consistency(): assert Consumption.JSON_START_YEAR == Policy.JSON_START_YEAR - assert Consumption.DEFAULT_NUM_YEARS == Policy.DEFAULT_NUM_YEARS + assert Consumption.NUM_YEARS == Policy.NUM_YEARS def test_validity_of_consumption_vars_set(): @@ -31,23 +31,23 @@ def test_update_consumption(): 2015: 0.80} } consump.update_consumption(revision) - expected_mpc_e20400 = np.full((Consumption.DEFAULT_NUM_YEARS,), 0.06) + expected_mpc_e20400 = np.full((Consumption.NUM_YEARS,), 0.06) expected_mpc_e20400[0] = 0.0 expected_mpc_e20400[1] = 0.05 assert np.allclose(consump._MPC_e20400, expected_mpc_e20400, rtol=0.0) assert np.allclose(consump._MPC_e17500, - np.zeros((Consumption.DEFAULT_NUM_YEARS,)), + np.zeros((Consumption.NUM_YEARS,)), rtol=0.0) - expected_ben_mcare_value = np.full((Consumption.DEFAULT_NUM_YEARS,), 0.80) + expected_ben_mcare_value = np.full((Consumption.NUM_YEARS,), 0.80) expected_ben_mcare_value[0] = 1.0 expected_ben_mcare_value[1] = 0.75 assert np.allclose(consump._BEN_mcare_value, expected_ben_mcare_value, rtol=0.0) assert np.allclose(consump._BEN_snap_value, - np.ones((Consumption.DEFAULT_NUM_YEARS,)), + np.ones((Consumption.NUM_YEARS,)), rtol=0.0) consump.set_year(2015) assert consump.current_year == 2015 diff --git a/taxcalc/tests/test_cpscsv.py b/taxcalc/tests/test_cpscsv.py index 7517b6adb..821c85971 100644 --- a/taxcalc/tests/test_cpscsv.py +++ b/taxcalc/tests/test_cpscsv.py @@ -161,3 +161,52 @@ def isfloat(value): else: return True return False + + +def test_flexible_last_budget_year(cps_fullsample): + """ + Test flexible LAST_BUDGET_YEAR logic using cps.csv file. + """ + tax_calc_year = Policy.DEFAULT_LAST_BUDGET_YEAR - 1 + growdiff_year = tax_calc_year - 1 + growdiff_dict = {'AWAGE': {growdiff_year: 0.01, tax_calc_year: 0.0}} + + def default_calculator(growdiff_dictionary): + """ + Return CPS-based Calculator object using default LAST_BUDGET_YEAR. + """ + g_factors = GrowFactors() + gdiff = GrowDiff() + gdiff.update_growdiff(growdiff_dictionary) + gdiff.apply_to(g_factors) + pol = Policy(gfactors=g_factors) + rec = Records.cps_constructor(data=cps_fullsample, gfactors=g_factors) + calc = Calculator(policy=pol, records=rec) + return calc + + def flexible_calculator(growdiff_dictionary, last_b_year, num_years): + """ + Return CPS-based Calculator object using custom LAST_BUDGET_YEAR. + """ + g_factors = GrowFactors() + gdiff = GrowDiff(nyrs=num_years) + gdiff.update_growdiff(growdiff_dictionary) + gdiff.apply_to(g_factors) + pol = Policy(gfactors=g_factors, last_budget_year=last_b_year) + rec = Records.cps_constructor(data=cps_fullsample, gfactors=g_factors) + calc = Calculator(policy=pol, records=rec) + return calc + + # begin main test logic + cdef = default_calculator(growdiff_dict) + cdef.advance_to_year(tax_calc_year) + cdef.calc_all() + iitax_def = round(cdef.weighted_total('iitax')) + + num_years = tax_calc_year - Policy.JSON_START_YEAR + 1 + cflx = flexible_calculator(growdiff_dict, tax_calc_year, num_years) + cflx.advance_to_year(tax_calc_year) + cflx.calc_all() + iitax_flx = round(cflx.weighted_total('iitax')) + + assert np.allclose([iitax_flx], [iitax_def]) \ No newline at end of file diff --git a/taxcalc/tests/test_growdiff.py b/taxcalc/tests/test_growdiff.py index 74bd49db5..9b504c47c 100644 --- a/taxcalc/tests/test_growdiff.py +++ b/taxcalc/tests/test_growdiff.py @@ -10,7 +10,7 @@ def test_year_consistency(): assert GrowDiff.JSON_START_YEAR == Policy.JSON_START_YEAR - assert GrowDiff.DEFAULT_NUM_YEARS == Policy.DEFAULT_NUM_YEARS + assert GrowDiff.NUM_YEARS == Policy.NUM_YEARS def test_update_and_apply_growdiff(): @@ -22,13 +22,13 @@ def test_update_and_apply_growdiff(): } gdiff.update_growdiff(diffs) expected_wage_diffs = [0.00, 0.01, 0.01, 0.02, 0.02] - extra_years = GrowDiff.DEFAULT_NUM_YEARS - len(expected_wage_diffs) + extra_years = GrowDiff.NUM_YEARS - len(expected_wage_diffs) expected_wage_diffs.extend([0.02] * extra_years) assert np.allclose(gdiff._AWAGE, expected_wage_diffs, atol=0.0, rtol=0.0) # apply growdiff to GrowFactors instance gf = GrowFactors() syr = GrowDiff.JSON_START_YEAR - nyrs = GrowDiff.DEFAULT_NUM_YEARS + nyrs = GrowDiff.NUM_YEARS lyr = syr + nyrs - 1 pir_pre = gf.price_inflation_rates(syr, lyr) wgr_pre = gf.wage_growth_rates(syr, lyr) diff --git a/taxcalc/tests/test_policy.py b/taxcalc/tests/test_policy.py index 41ba8db3e..dddf12b79 100644 --- a/taxcalc/tests/test_policy.py +++ b/taxcalc/tests/test_policy.py @@ -248,7 +248,7 @@ def test_multi_year_reform(): """ # specify dimensions of policy Policy object syr = Policy.JSON_START_YEAR - nyrs = Policy.DEFAULT_NUM_YEARS + nyrs = Policy.NUM_YEARS pol = Policy() iratelist = pol.inflation_rates() ifactor = {}