Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Make a Policy object's last budget year be flexible #2856

Merged
merged 12 commits into from
Dec 18, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions conda.recipe/meta.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,21 +9,21 @@ 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
- 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
- curl
- openpyxl
Expand Down
5 changes: 3 additions & 2 deletions environment.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,12 @@ channels:
- conda-forge
dependencies:
- "python>=3.10, <3.13"
- "numpy>=1.26,<1.27"
- "numpy>=1.26"
- "pandas>=2.2"
- "bokeh>=2.4"
- numba
- curl
- setuptools
- pytest
- pytest-xdist
- pycodestyle
Expand All @@ -18,4 +19,4 @@ dependencies:
- pip
- pip:
- jupyter-book
- "paramtools>=0.18.3"
- "paramtools>=0.19.0"
10 changes: 4 additions & 6 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,11 @@
"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",
Expand Down
12 changes: 5 additions & 7 deletions taxcalc.egg-info/PKG-INFO
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: taxcalc
Version: 4.3.4
Version: 4.3.5
Summary: taxcalc
Home-page: https://github.com/PSLmodels/Tax-Calculator
Download-URL: https://github.com/PSLmodels/Tax-Calculator
Expand All @@ -18,13 +18,11 @@ 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

| | |
| --- | --- |
Expand Down
10 changes: 4 additions & 6 deletions taxcalc.egg-info/requires.txt
Original file line number Diff line number Diff line change
@@ -1,7 +1,5 @@
setuptools
numpy
pandas
bokeh
numpy>=1.26
pandas>=2.2
bokeh>=2.4
numba
requests
paramtools>=0.18.3
paramtools>=0.19.0
2 changes: 1 addition & 1 deletion taxcalc/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,6 @@
from taxcalc.utils import *
from taxcalc.cli import *

__version__ = '4.3.5'
__version__ = '4.3.5a'
__min_python3_version__ = 10
__max_python3_version__ = 12
10 changes: 5 additions & 5 deletions taxcalc/consumption.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ class Consumption(Parameters):

Parameters
----------
none
last_budget_year: integer
user-defined last parameter extrapolation year

Returns
-------
class instance: Consumption
"""

JSON_START_YEAR = Policy.JSON_START_YEAR
DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS
DEFAULTS_FILE_NAME = 'consumption.json'
DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__))

def __init__(self):
def __init__(self, last_budget_year=Policy.LAST_BUDGET_YEAR):
super().__init__()
self.initialize(Consumption.JSON_START_YEAR,
Consumption.DEFAULT_NUM_YEARS)
nyrs = Policy.number_of_years(last_budget_year)
self.initialize(Consumption.JSON_START_YEAR, nyrs)

@staticmethod
def read_json_update(obj):
Expand Down
15 changes: 5 additions & 10 deletions taxcalc/growdiff.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,22 +20,22 @@ class GrowDiff(Parameters):

Parameters
----------
none
last_budget_year: integer
user-defined last parameter extrapolation year

Returns
-------
class instance: GrowDiff
"""

JSON_START_YEAR = Policy.JSON_START_YEAR
DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS
DEFAULTS_FILE_NAME = 'growdiff.json'
DEFAULTS_FILE_PATH = os.path.abspath(os.path.dirname(__file__))

def __init__(self):
def __init__(self, last_budget_year=Policy.LAST_BUDGET_YEAR):
super().__init__()
self.initialize(GrowDiff.JSON_START_YEAR,
GrowDiff.DEFAULT_NUM_YEARS)
nyrs = Policy.number_of_years(last_budget_year)
self.initialize(GrowDiff.JSON_START_YEAR, nyrs)

@staticmethod
def read_json_update(obj, topkey):
Expand Down Expand Up @@ -81,8 +81,3 @@ def apply_to(self, growfactors):
cyr = i + self.start_year
diff_array = getattr(self, _gfvn)
growfactors.update(gfvn, cyr, diff_array[i])

def set_rates(self):
"""
Unimplemented base class method that is not used here.
"""
13 changes: 7 additions & 6 deletions taxcalc/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,26 +98,27 @@ def __init__(self, start_year=None, num_years=None, last_known_year=None,
self.DEFAULTS_FILE_PATH,
self.DEFAULTS_FILE_NAME
)

last_budget_year = start_year + num_years - 1
if last_known_year is None:
self._last_known_year = start_year
else:
assert last_known_year >= start_year
assert last_known_year <= self.LAST_BUDGET_YEAR
assert last_known_year <= last_budget_year
self._last_known_year = last_known_year

self._removed_params = removed or self.REMOVED_PARAMS
self._redefined_params = redefined or self.REDEFINED_PARAMS

self._wage_indexed = wage_indexed or self.WAGE_INDEXED_PARAMS

if (
(start_year or self.JSON_START_YEAR) and
"initial_state" not in kwargs
):
kwargs["initial_state"] = {
"year": start_year or self.JSON_START_YEAR
}
# update defaults to correspond to user-defined parameter years
self.defaults = super().get_defaults()
label = self.defaults["schema"]["labels"]["year"]
label["validators"]["range"]["max"] = last_budget_year
super().__init__(**kwargs)

def adjust(
Expand Down Expand Up @@ -774,7 +775,7 @@ def __getattr__(self, attr):
attr[1:], year=list(range(self.start_year, self.end_year + 1))
)
else:
raise AttributeError(f"{attr} not definied.")
raise AttributeError(f"{attr} is not defined.")


TaxcalcReform = Union[str, Mapping[int, Any]]
Expand Down
28 changes: 22 additions & 6 deletions taxcalc/policy.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,9 @@ class Policy(Parameters):
gfactors: GrowFactors class instance
containing price inflation rates and wage growth rates

last_budget_year: integer
user-defined last parameter extrapolation year

Raises
------
ValueError:
Expand All @@ -39,9 +42,16 @@ 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
LAST_BUDGET_YEAR = 2034 # default value of last extrapolation year
# should increase LAST_BUDGET_YEAR by one every calendar year
DEFAULT_NUM_YEARS = LAST_BUDGET_YEAR - JSON_START_YEAR + 1

@staticmethod
def number_of_years(last_budget_year=LAST_BUDGET_YEAR):
"""
Static method returns number of policy parameters years given
user-defined last_budget_year.
"""
return last_budget_year - Policy.JSON_START_YEAR + 1

# NOTE: the following three data structures use internal parameter names:
# (1) specify which Policy parameters have been removed or renamed
Expand Down Expand Up @@ -80,7 +90,10 @@ 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=LAST_BUDGET_YEAR,
**kwargs):
# put JSON contents of DEFAULTS_FILE_NAME into self._vals dictionary
super().__init__()
# handle gfactors argument
Expand All @@ -92,7 +105,7 @@ 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 = Policy.number_of_years(last_budget_year)
self._inflation_rates = None
self._wage_growth_rates = None
self.initialize(syr, nyrs, Policy.LAST_KNOWN_YEAR,
Expand All @@ -101,7 +114,10 @@ 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=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
Expand All @@ -112,7 +128,7 @@ 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):
Expand Down
Loading
Loading