diff --git a/.coveragerc b/.coveragerc
index 0b21d16a7..0f8316766 100644
--- a/.coveragerc
+++ b/.coveragerc
@@ -1,6 +1,5 @@
[run]
omit =
- taxcalc/_version.py
taxcalc/calcfunctions.py
taxcalc/*.json
taxcalc/cli/*
diff --git a/Makefile b/Makefile
index b05fdb261..a5382ae3f 100644
--- a/Makefile
+++ b/Makefile
@@ -75,7 +75,7 @@ TESTS_JSON_FILES := $(shell ls -l ./taxcalc/tests/*json | awk '{print $$9}')
PYLINT_FILES := $(shell grep -rl --include="*py" disable=locally-disabled .)
PYLINT_OPTIONS = --disable=locally-disabled --score=no --jobs=4
RECIPE_FILES := $(shell ls -l ./docs/cookbook/recipe*py | awk '{print $$9}')
-RECIPE_OPTIONS = --disable=C0103,C0111,W0401,W0614 --score=no --jobs=4
+RECIPE_OPTIONS = --disable=C0103,C0111,W0401,W0614,E0401 --score=no --jobs=4
.PHONY=cstest
cstest:
diff --git a/README.md b/README.md
index 2cbf2489f..4102c2ff0 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[![Python 3.6.5](https://img.shields.io/badge/python-3.6.5-blue.svg)](https://www.python.org/downloads/release/python-365/)
+[![Python 3.6](https://img.shields.io/badge/python-3.6-blue.svg)](https://www.python.org/downloads/release/python-360/)
[![Build Status](https://travis-ci.org/open-source-economics/Tax-Calculator.svg?branch=master)](https://travis-ci.org/open-source-economics/Tax-Calculator)
[![Codecov](https://codecov.io/gh/open-source-economics/Tax-Calculator/branch/master/graph/badge.svg)](https://codecov.io/gh/open-source-economics/Tax-Calculator)
diff --git a/conda.recipe/install_local_package.sh b/conda.recipe/install_local_package.sh
index a65186bb6..76a086a7d 100755
--- a/conda.recipe/install_local_package.sh
+++ b/conda.recipe/install_local_package.sh
@@ -16,7 +16,7 @@ echo "BUILD-PREP..."
# check version of conda package
conda list conda | awk '$1=="conda"{v=$2;gsub(/\./,"",v);nv=v+0;if(nv<444)rc=1}END{exit(rc)}'
-if [ $? -eq 1 ]; then
+if [[ $? -eq 1 ]]; then
echo "==> Installing conda 4.4.4+"
conda install conda>=4.4.4 --yes 2>&1 > /dev/null
echo "==> Continuing to build new taxcalc package"
@@ -24,7 +24,7 @@ fi
# install conda-build package if not present
conda list build | awk '$1~/conda-build/{rc=1}END{exit(rc)}'
-if [ $? -eq 0 ]; then
+if [[ $? -eq 0 ]]; then
echo "==> Installing conda-build package"
conda install conda-build --yes 2>&1 > /dev/null
echo "==> Continuing to build new taxcalc package"
diff --git a/conda.recipe/remove_local_package.sh b/conda.recipe/remove_local_package.sh
index 7f63d09f0..d6f03c360 100755
--- a/conda.recipe/remove_local_package.sh
+++ b/conda.recipe/remove_local_package.sh
@@ -5,8 +5,8 @@
# removing a local conda package is analogous to a "make clean" operation
# uninstall any existing taxcalc conda package
-conda list taxcalc | awk '$1~/taxcalc/{rc=1}END{exit(rc)}'
-if [ $? -eq 1 ]; then
+conda list taxcalc | awk '$1=="taxcalc"{rc=1}END{exit(rc)}'
+if [[ $? -eq 1 ]]; then
conda uninstall taxcalc --yes 2>&1 > /dev/null
fi
diff --git a/docs/cookbook.html b/docs/cookbook.html
index 3920828fb..22704f6fd 100644
--- a/docs/cookbook.html
+++ b/docs/cookbook.html
@@ -94,12 +94,12 @@
Preliminaries: Recipe Techniques
and give it a new file name before you start to modify the recipe.
The Calculator object is the central object in Tax-Calculator and
-it is created by passing four secondary objects (a Policy object, a
-Records object, a Behavior object, and a Consumption object) to the
+it is created by passing three secondary objects (a Policy object, a
+Records object, and a Consumption object) to the
Calculator class constructor. When modifying a recipe, following a
few rules will minimize the chance of running into problems.
-Fully specify Consumption, Behavior, Records, and Policy objects
+
Fully specify Policy, Records, and Consumption objects
before passing them to the Calculator class constructor.
After initializing a Calculator object, manipulate it using only
@@ -236,16 +236,17 @@
Advanced Recipe: (2) Estimating Behavioral Response
This is an advanced recipe that should be followed only after
mastering the basic recipe . This recipe
-shows how to analyze the behavioral responses to a tax reform.
+shows how to analyze the behavioral responses to a tax reform using
+the Behavioral-Responses behresp package. Before following
+this recipe, be sure to install the behresp package on your
+compter by executing this at the command prompt:
+conda install -c OSPC behresp
Ingredients
Policy reform in
the ingredients/reformA.json file.
-Economic assumptions in
-the ingredients/assumpA.json file.
-
Instructions
Step-by-step
diff --git a/docs/cookbook/ingredients/assumpA.json b/docs/cookbook/ingredients/assumpA.json
deleted file mode 100644
index d2d384f8b..000000000
--- a/docs/cookbook/ingredients/assumpA.json
+++ /dev/null
@@ -1,16 +0,0 @@
-// This JSON economic assumption file specifies a non-zero substitution
-// elasticity for taxable income, which causes a response in taxable income
-// to a reform-induced change in marginal tax rates
-{
- "consumption": {
- },
- "behavior": {
- "_BE_sub": {"2013": [0.25]}
- },
- "growdiff_baseline": {
- },
- "growdiff_response": {
- },
- "growmodel": {
- }
-}
diff --git a/docs/cookbook/recipe02.py b/docs/cookbook/recipe02.py
index 64b8e4f9c..09f0aa681 100644
--- a/docs/cookbook/recipe02.py
+++ b/docs/cookbook/recipe02.py
@@ -1,9 +1,10 @@
from taxcalc import *
+import behresp
# use publicly-available CPS input file
recs = Records.cps_constructor()
-# specify Calculator object representing current-law policy
+# specify baseline Calculator object representing current-law policy
pol = Policy()
calc1 = Calculator(policy=pol, records=recs)
@@ -14,37 +15,34 @@
calc1.calc_all()
itax_rev1 = calc1.weighted_total('iitax')
-# read JSON reform file and use (the default) static analysis assumptions
+# read JSON reform file
reform_filename = './ingredients/reformA.json'
params = Calculator.read_json_param_objects(reform=reform_filename,
assump=None)
# specify Calculator object for static analysis of reform policy
pol.implement_reform(params['policy'])
-calc2 = Calculator(policy=pol, records=recs)
+calc2sa = Calculator(policy=pol, records=recs)
# calculate reform income tax liabilities for cyr under static assumptions
-calc2.advance_to_year(cyr)
-calc2.calc_all()
-itax_rev2 = calc2.weighted_total('iitax')
+calc2sa.advance_to_year(cyr)
+calc2sa.calc_all()
+itax_rev2sa = calc2sa.weighted_total('iitax')
-# read JSON reform file and (dynamic) behavioral-analysis assumptions
-assump_filename = './ingredients/assumpA.json'
-params = Calculator.read_json_param_objects(reform=reform_filename,
- assump=assump_filename)
-behv = Behavior()
-behv.update_behavior(params['behavior'])
+# specify behavioral-response assumptions
+behresp_json = '{"BE_sub": {"2018": 0.25}}'
+behresp_dict = Calculator.read_json_assumptions(behresp_json)
-# specify Calculator object for behavioral-response analysis of reform policy
-calc3 = Calculator(policy=pol, records=recs, behavior=behv)
+# specify Calculator object for analysis of reform with behavioral response
+calc2br = Calculator(policy=pol, records=recs)
+calc2br.advance_to_year(cyr)
+_, df2br = behresp.response(calc1, calc2br, behresp_dict)
-# calculate reform income tax liabilities for cyr under dynamic assumptions
-calc3.advance_to_year(cyr)
-calc3br = Behavior.response(calc1, calc3)
-itax_rev3 = calc3br.weighted_total('iitax')
+# calculate reform income tax liabilities for cyr with behavioral response
+itax_rev2br = (df2br['iitax'] * df2br['s006']).sum()
-# print total revenue estimates for cyr
+# print total income tax revenue estimates for cyr
# (estimates in billons of dollars rounded to nearest hundredth of a billion)
print('{}_CURRENT_LAW_P__itax_rev($B)= {:.2f}'.format(cyr, itax_rev1 * 1e-9))
-print('{}_REFORM_STATIC__itax_rev($B)= {:.2f}'.format(cyr, itax_rev2 * 1e-9))
-print('{}_REFORM_DYNAMIC_itax_rev($B)= {:.2f}'.format(cyr, itax_rev3 * 1e-9))
+print('{}_REFORM_STATIC__itax_rev($B)= {:.2f}'.format(cyr, itax_rev2sa * 1e-9))
+print('{}_REFORM_DYNAMIC_itax_rev($B)= {:.2f}'.format(cyr, itax_rev2br * 1e-9))
diff --git a/docs/cookbook/test_recipes.py b/docs/cookbook/test_recipes.py
index be35e2c9b..8463ed3ee 100644
--- a/docs/cookbook/test_recipes.py
+++ b/docs/cookbook/test_recipes.py
@@ -20,7 +20,7 @@
RECIPES = glob.glob('./recipe[0-9][0-9].py')
# execute each recipe in RECIPES list and compare output with expected output
-for recipe in RECIPES:
+for recipe in sorted(RECIPES):
out_filename = recipe.replace('.py', '.out')
if os.path.isfile(out_filename):
os.remove(out_filename)
diff --git a/docs/index_results.sh b/docs/index_results.sh
index 3a87cadc8..057fa589b 100755
--- a/docs/index_results.sh
+++ b/docs/index_results.sh
@@ -10,7 +10,7 @@ echo "STARTING : `date`"
# check existence of taxcalc package
conda list taxcalc | awk '$1~/taxcalc/{rc=1}END{exit(rc)}'
-if [ $? -eq 0 ]; then
+if [[ $? -eq 0 ]]; then
echo "ERROR: taxcalc package does not exist"
exit 1
fi
diff --git a/docs/recipe00.graph.html b/docs/recipe00.graph.html
index 4d745def8..6ed9a64a9 100644
--- a/docs/recipe00.graph.html
+++ b/docs/recipe00.graph.html
@@ -1,25 +1,48 @@
+
+
+
-
-
- recipe00.graph
+
+
+
+
+ recipe00.graph
+
+
+
+
+
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
+
+
+
+
+
-
-
+
+
+
\ No newline at end of file
diff --git a/docs/recipe02.py.html b/docs/recipe02.py.html
index ad949ab5e..f02b125ae 100644
--- a/docs/recipe02.py.html
+++ b/docs/recipe02.py.html
@@ -1,10 +1,11 @@
recipe02.py
from taxcalc import *
+import behresp
# use publicly-available CPS input file
recs = Records.cps_constructor()
-# specify Calculator object representing current-law policy
+# specify baseline Calculator object representing current-law policy
pol = Policy()
calc1 = Calculator(policy=pol, records=recs)
@@ -15,38 +16,35 @@
calc1.calc_all()
itax_rev1 = calc1.weighted_total('iitax')
-# read JSON reform file and use (the default) static analysis assumptions
+# read JSON reform file
reform_filename = './ingredients/reformA.json'
params = Calculator.read_json_param_objects(reform=reform_filename,
assump=None)
# specify Calculator object for static analysis of reform policy
pol.implement_reform(params['policy'])
-calc2 = Calculator(policy=pol, records=recs)
+calc2sa = Calculator(policy=pol, records=recs)
# calculate reform income tax liabilities for cyr under static assumptions
-calc2.advance_to_year(cyr)
-calc2.calc_all()
-itax_rev2 = calc2.weighted_total('iitax')
+calc2sa.advance_to_year(cyr)
+calc2sa.calc_all()
+itax_rev2sa = calc2sa.weighted_total('iitax')
-# read JSON reform file and (dynamic) behavioral-analysis assumptions
-assump_filename = './ingredients/assumpA.json'
-params = Calculator.read_json_param_objects(reform=reform_filename,
- assump=assump_filename)
-behv = Behavior()
-behv.update_behavior(params['behavior'])
+# specify behavioral-response assumptions
+behresp_json = '{"BE_sub": {"2018": 0.25}}'
+behresp_dict = Calculator.read_json_assumptions(behresp_json)
-# specify Calculator object for behavioral-response analysis of reform policy
-calc3 = Calculator(policy=pol, records=recs, behavior=behv)
+# specify Calculator object for analysis of reform with behavioral response
+calc2br = Calculator(policy=pol, records=recs)
+calc2br.advance_to_year(cyr)
+_, df2br = behresp.response(calc1, calc2br, behresp_dict)
-# calculate reform income tax liabilities for cyr under dynamic assumptions
-calc3.advance_to_year(cyr)
-calc3br = Behavior.response(calc1, calc3)
-itax_rev3 = calc3br.weighted_total('iitax')
+# calculate reform income tax liabilities for cyr with behavioral response
+itax_rev2br = (df2br['iitax'] * df2br['s006']).sum()
-# print total revenue estimates for cyr
+# print total income tax revenue estimates for cyr
# (estimates in billons of dollars rounded to nearest hundredth of a billion)
print('{}_CURRENT_LAW_P__itax_rev($B)= {:.2f}'.format(cyr, itax_rev1 * 1e-9))
-print('{}_REFORM_STATIC__itax_rev($B)= {:.2f}'.format(cyr, itax_rev2 * 1e-9))
-print('{}_REFORM_DYNAMIC_itax_rev($B)= {:.2f}'.format(cyr, itax_rev3 * 1e-9))
+print('{}_REFORM_STATIC__itax_rev($B)= {:.2f}'.format(cyr, itax_rev2sa * 1e-9))
+print('{}_REFORM_DYNAMIC_itax_rev($B)= {:.2f}'.format(cyr, itax_rev2br * 1e-9))
diff --git a/read-the-docs/source/public_api.rst b/read-the-docs/source/public_api.rst
index 972690213..e6a70a90b 100644
--- a/read-the-docs/source/public_api.rst
+++ b/read-the-docs/source/public_api.rst
@@ -70,16 +70,10 @@ taxcalc.Growfactors
.. autoclass:: taxcalc.Growfactors
:members:
-taxcalc.macro_elasticity
-------------------------
-
-.. automodule:: taxcalc.macro_elasticity
- :members:
-
-taxcalc.ParametersBase
-----------------------
+taxcalc.Parameters
+------------------
-.. autoclass:: taxcalc.ParametersBase
+.. autoclass:: taxcalc.Parameters
:members:
:exclude-members: _update, _indexing_rates_for_update
diff --git a/setup.py b/setup.py
index c3c034d66..9486b4a07 100755
--- a/setup.py
+++ b/setup.py
@@ -1,10 +1,3 @@
-import versioneer
-versioneer.VCS = 'git'
-versioneer.versionfile_source = 'taxcalc/_version.py'
-versioneer.versionfile_build = 'taxcalc/_version.py'
-versioneer.tag_prefix = '' # tags are like 1.2.0
-versioneer.parentdir_prefix = 'taxcalc-' # dirname like 'taxcalc-1.2.0'
-
try:
from setuptools import setup
except ImportError:
@@ -13,8 +6,7 @@
with open('README.md') as f:
longdesc = f.read()
-version = versioneer.get_version()
-cmdclass = versioneer.get_cmdclass()
+version = '0.0.0'
config = {
'description': 'Tax Calculator',
@@ -23,7 +15,6 @@
'description': 'taxcalc',
'long_description': longdesc,
'version': version,
- 'cmdclass': cmdclass,
'license': 'CC0 1.0 Universal public domain dedication',
'packages': ['taxcalc', 'taxcalc.tbi', 'taxcalc.cli'],
'include_package_data': True,
diff --git a/taxcalc/__init__.py b/taxcalc/__init__.py
index 08eb96131..b4eb9a267 100755
--- a/taxcalc/__init__.py
+++ b/taxcalc/__init__.py
@@ -17,6 +17,4 @@
from taxcalc.tbi import *
from taxcalc.cli import *
-from taxcalc._version import get_versions
-__version__ = get_versions()['version']
-del get_versions
+__version__ = '0.0.0'
diff --git a/taxcalc/_version.py b/taxcalc/_version.py
deleted file mode 100644
index b614d185a..000000000
--- a/taxcalc/_version.py
+++ /dev/null
@@ -1,192 +0,0 @@
-
-# This file helps to compute a version number in source trees obtained from
-# git-archive tarball (such as those provided by githubs download-from-tag
-# feature). Distribution tarballs (built by setup.py sdist) and build
-# directories (produced by setup.py build) will contain a much shorter file
-# that just contains the computed version number.
-
-# This file is released into the public domain. Generated by
-# versioneer-0.12 (https://github.com/warner/python-versioneer)
-
-import os
-import sys
-import re
-import subprocess
-import errno
-
-# these strings will be replaced by git during git-archive
-git_refnames = "$Format:%d$"
-git_full = "$Format:%H$"
-
-# these strings are filled in when 'setup.py versioneer' creates _version.py
-tag_prefix = ""
-parentdir_prefix = "taxcalc-"
-versionfile_source = "taxcalc/_version.py"
-
-
-def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
- assert isinstance(commands, list)
- p = None
- for c in commands:
- try:
- # remember shell=False, so use git.cmd on windows, not just git
- p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
- stderr=(subprocess.PIPE if hide_stderr
- else None))
- break
- except EnvironmentError:
- e = sys.exc_info()[1]
- if e.errno == errno.ENOENT:
- continue
- if verbose:
- print("unable to run %s" % args[0])
- print(e)
- return None
- else:
- if verbose:
- print("unable to find command, tried %s" % (commands,))
- return None
- stdout = p.communicate()[0].strip()
- if sys.version >= '3':
- stdout = stdout.decode()
- if p.returncode != 0:
- if verbose:
- print("unable to run %s (error)" % args[0])
- return None
- return stdout
-
-
-def versions_from_parentdir(parentdir_prefix, root, verbose=False):
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
- dirname = os.path.basename(root)
- if not dirname.startswith(parentdir_prefix):
- if verbose:
- print("guessing rootdir is '%s',"
- "but '%s' doesn't start with prefix '%s'"
- % (root, dirname, parentdir_prefix))
- return None
- return {"version": dirname[len(parentdir_prefix):], "full": ""}
-
-
-def git_get_keywords(versionfile_abs):
- # the code embedded in _version.py can just fetch the value of these
- # keywords. When used from setup.py, we don't want to import _version.py,
- # so we do it with a regexp instead. This function is not used from
- # _version.py.
- keywords = {}
- try:
- f = open(versionfile_abs, "r")
- for line in f.readlines():
- if line.strip().startswith("git_refnames ="):
- mo = re.search(r'=\s*"(.*)"', line)
- if mo:
- keywords["refnames"] = mo.group(1)
- if line.strip().startswith("git_full ="):
- mo = re.search(r'=\s*"(.*)"', line)
- if mo:
- keywords["full"] = mo.group(1)
- f.close()
- except EnvironmentError:
- pass
- return keywords
-
-
-def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
- if not keywords:
- return {} # keyword-finding function failed to find keywords
- refnames = keywords["refnames"].strip()
- if refnames.startswith("$Format"):
- if verbose:
- print("keywords are unexpanded, not using")
- return {} # unexpanded, so not in an unpacked git-archive tarball
- refs = set([r.strip() for r in refnames.strip("()").split(",")])
- # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
- # just "foo-1.0". If we see a "tag: " prefix, prefer those.
- TAG = "tag: "
- tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
- if not tags:
- # Either we're using git < 1.8.3, or there really are no tags. We use
- # a heuristic: assume all version tags have a digit. The old git %d
- # expansion behaves like git log --decorate=short and strips out the
- # refs/heads/ and refs/tags/ prefixes that would let us distinguish
- # between branches and tags. By ignoring refnames without digits, we
- # filter out many common branch names like "release" and
- # "stabilization", as well as "HEAD" and "master".
- tags = set([r for r in refs if re.search(r'\d', r)])
- if verbose:
- print("discarding '%s', no digits" % ",".join(refs - tags))
- if verbose:
- print("likely tags: %s" % ",".join(sorted(tags)))
- for ref in sorted(tags):
- # sorting will prefer e.g. "2.0" over "2.0rc1"
- if ref.startswith(tag_prefix):
- r = ref[len(tag_prefix):]
- if verbose:
- print("picking %s" % r)
- return {"version": r,
- "full": keywords["full"].strip()}
- # no suitable tags, so we use the full revision id
- if verbose:
- print("no suitable tags, using full revision id")
- return {"version": keywords["full"].strip(),
- "full": keywords["full"].strip()}
-
-
-def git_versions_from_vcs(tag_prefix, root, verbose=False):
- # this runs 'git' from the root of the source tree. This only gets called
- # if the git-archive 'subst' keywords were *not* expanded, and
- # _version.py hasn't already been rewritten with a short version string,
- # meaning we're inside a checked out source tree.
-
- if not os.path.exists(os.path.join(root, ".git")):
- if verbose:
- print("no .git in %s" % root)
- return {}
-
- GITS = ["git"]
- if sys.platform == "win32":
- GITS = ["git.cmd", "git.exe"]
- stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
- cwd=root)
- if stdout is None:
- return {}
- if not stdout.startswith(tag_prefix):
- if verbose:
- print("tag '%s' doesn't start with prefix '%s'" %
- (stdout, tag_prefix))
- return {}
- tag = stdout[len(tag_prefix):]
- stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
- if stdout is None:
- return {}
- full = stdout.strip()
- if tag.endswith("-dirty"):
- full += "-dirty"
- return {"version": tag, "full": full}
-
-
-def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
- # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
- # __file__, we can work backwards from there to the root. Some
- # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
- # case we can only use expanded keywords.
-
- keywords = {"refnames": git_refnames, "full": git_full}
- ver = git_versions_from_keywords(keywords, tag_prefix, verbose)
- if ver:
- return ver
-
- try:
- root = os.path.abspath(__file__)
- # versionfile_source is the relative path from the top of the source
- # tree (where the .git directory might live) to this file. Invert
- # this to find the root from __file__.
- for i in range(len(versionfile_source.split(os.sep))):
- root = os.path.dirname(root)
- except NameError:
- return default
-
- return (git_versions_from_vcs(tag_prefix, root, verbose) or
- versions_from_parentdir(parentdir_prefix, root, verbose) or
- default)
diff --git a/taxcalc/behavior.py b/taxcalc/behavior.py
index 5b65f2757..72e77b06c 100644
--- a/taxcalc/behavior.py
+++ b/taxcalc/behavior.py
@@ -18,6 +18,10 @@ class Behavior(Parameters):
Constructor for elasticity-based behavioral-response class.
+ WARNING: the Behavior class is deprecated and will be removed soon.
+ FUTURE: use the Behavioral-Responses behresp package OR
+ use the Tax-Calculator quantity_response function.
+
Parameters
----------
start_year: integer
@@ -45,6 +49,10 @@ class instance: Behavior
def __init__(self,
start_year=JSON_START_YEAR,
num_years=DEFAULT_NUM_YEARS):
+ print(('WARNING: the Behavior class is deprecated '
+ 'and will be removed soon.'))
+ print('FUTURE: use the Behavioral-Responses behresp package OR')
+ print(' use the Tax-Calculator quantity_response function.')
super(Behavior, self).__init__()
self._vals = self._params_dict_from_json_file()
if start_year < Policy.JSON_START_YEAR:
diff --git a/taxcalc/calculator.py b/taxcalc/calculator.py
index 32ade2b82..9ed58da43 100644
--- a/taxcalc/calculator.py
+++ b/taxcalc/calculator.py
@@ -114,7 +114,7 @@ def __init__(self, policy=None, records=None, verbose=True,
if self.__policy.current_year < self.__records.data_year:
self.__policy.set_year(self.__records.data_year)
if consumption is None:
- self.__consumption = Consumption(start_year=policy.start_year)
+ self.__consumption = Consumption()
elif isinstance(consumption, Consumption):
self.__consumption = copy.deepcopy(consumption)
else:
diff --git a/taxcalc/cli/tc.py b/taxcalc/cli/tc.py
index ff89c7f99..054f503ec 100644
--- a/taxcalc/cli/tc.py
+++ b/taxcalc/cli/tc.py
@@ -133,10 +133,7 @@ def cli_tc_main():
args = parser.parse_args()
# show Tax-Calculator version and quit if --version option specified
if args.version:
- version = tc.__version__
- if version == 'unknown':
- version = 'locally.generated.package'
- sys.stdout.write('Tax-Calculator {}\n'.format(version))
+ sys.stdout.write('Tax-Calculator {}\n'.format(tc.__version__))
return 0
# write test input and expected output files if --test option specified
if args.test:
diff --git a/taxcalc/consumption.py b/taxcalc/consumption.py
index e0a5ddbc9..8d9bae768 100644
--- a/taxcalc/consumption.py
+++ b/taxcalc/consumption.py
@@ -19,18 +19,7 @@ class Consumption(Parameters):
Parameters
----------
- start_year: integer
- first calendar year for consumption parameters.
-
- num_years: integer
- number of calendar years for which to specify parameter
- values beginning with start_year.
-
- Raises
- ------
- ValueError:
- if start_year is less than Policy.JSON_START_YEAR.
- if num_years is less than one.
+ none
Returns
-------
@@ -41,15 +30,11 @@ class instance: Consumption
DEFAULTS_FILENAME = 'consumption.json'
DEFAULT_NUM_YEARS = Policy.DEFAULT_NUM_YEARS
- def __init__(self,
- start_year=JSON_START_YEAR,
- num_years=DEFAULT_NUM_YEARS):
+ def __init__(self):
super(Consumption, self).__init__()
self._vals = self._params_dict_from_json_file()
- if start_year < Policy.JSON_START_YEAR:
- raise ValueError('start_year < Policy.JSON_START_YEAR')
- if num_years < 1:
- raise ValueError('num_years < 1')
+ start_year = Consumption.JSON_START_YEAR
+ num_years = Consumption.DEFAULT_NUM_YEARS
self.initialize(start_year, num_years)
self.parameter_errors = ''
diff --git a/taxcalc/growdiff.py b/taxcalc/growdiff.py
index 2f69d6436..673917529 100644
--- a/taxcalc/growdiff.py
+++ b/taxcalc/growdiff.py
@@ -18,18 +18,7 @@ class GrowDiff(Parameters):
Parameters
----------
- start_year: integer
- first calendar year for growth difference parameters.
-
- num_years: integer
- number of calendar years for which to specify parameter
- values beginning with start_year.
-
- Raises
- ------
- ValueError:
- if start_year is less than 2013
- if num_years is less than one.
+ none
Returns
-------
@@ -40,15 +29,11 @@ class instance: GrowDiff
DEFAULTS_FILENAME = 'growdiff.json'
DEFAULT_NUM_YEARS = 15 # must be same as Policy.DEFAULT_NUM_YEARS
- def __init__(self,
- start_year=JSON_START_YEAR,
- num_years=DEFAULT_NUM_YEARS):
+ def __init__(self):
super(GrowDiff, self).__init__()
self._vals = self._params_dict_from_json_file()
- if start_year < GrowDiff.JSON_START_YEAR:
- raise ValueError('start_year < GrowDiff.JSON_START_YEAR')
- if num_years < 1:
- raise ValueError('num_years < 1')
+ start_year = GrowDiff.JSON_START_YEAR
+ num_years = GrowDiff.DEFAULT_NUM_YEARS
self.initialize(start_year, num_years)
self.parameter_errors = ''
diff --git a/taxcalc/parameters.py b/taxcalc/parameters.py
index 44ae53cee..d1188b29f 100644
--- a/taxcalc/parameters.py
+++ b/taxcalc/parameters.py
@@ -22,7 +22,7 @@ class Parameters():
DEFAULTS_FILENAME = None
@classmethod
- def default_data(cls, metadata=False, start_year=None):
+ def default_data(cls, metadata=False):
"""
Return parameter data read from the subclass's json file.
@@ -30,22 +30,12 @@ def default_data(cls, metadata=False, start_year=None):
----------
metadata: boolean
- start_year: int or None
-
Returns
-------
params: dictionary of data
"""
- # extract different data from DEFAULT_FILENAME depending on start_year
- if start_year is None:
- params = cls._params_dict_from_json_file()
- else:
- nyrs = start_year - cls.JSON_START_YEAR + 1
- ppo = cls(num_years=nyrs)
- ppo.set_year(start_year)
- params = getattr(ppo, '_vals')
- params = Parameters._revised_default_data(params, start_year,
- nyrs, ppo)
+ # extract data from DEFAULT_FILENAME
+ params = cls._params_dict_from_json_file()
# return different data from params dict depending on metadata value
if metadata:
return params
@@ -316,54 +306,6 @@ def _validate_assump_parameter_values(self, parameters_set):
)
del parameters
- @staticmethod
- def _revised_default_data(params, start_year, nyrs, ppo):
- """
- Return revised default parameter data.
-
- Parameters
- ----------
- params: dictionary of NAME:DATA pairs for each parameter
- as defined in calling default_data staticmethod.
-
- start_year: int
- as defined in calling default_data staticmethod.
-
- nyrs: int
- as defined in calling default_data staticmethod.
-
- ppo: Policy object
- as defined in calling default_data staticmethod.
-
- Returns
- -------
- params: dictionary of revised parameter data
-
- Notes
- -----
- This staticmethod is called from default_data staticmethod in
- order to reduce the complexity of the default_data staticmethod.
- """
- start_year_str = '{}'.format(start_year)
- for name, data in params.items():
- data['start_year'] = start_year
- values = data['value']
- num_values = len(values)
- if num_values <= nyrs:
- # val should be the single start_year value
- rawval = getattr(ppo, name[1:])
- if isinstance(rawval, np.ndarray):
- val = rawval.tolist()
- else:
- val = rawval
- data['value'] = [val]
- data['row_label'] = [start_year_str]
- else: # if num_values > nyrs
- # val should extend beyond the start_year value
- data['value'] = data['value'][(nyrs - 1):]
- data['row_label'] = data['row_label'][(nyrs - 1):]
- return params
-
@classmethod
def _params_dict_from_json_file(cls):
"""
diff --git a/taxcalc/policy.py b/taxcalc/policy.py
index b77123d60..c57d69a8c 100644
--- a/taxcalc/policy.py
+++ b/taxcalc/policy.py
@@ -23,19 +23,10 @@ class Policy(Parameters):
gfactors: GrowFactors class instance
containing price inflation rates and wage growth rates
- start_year: integer
- first calendar year for historical policy parameters.
-
- num_years: integer
- number of calendar years for which to specify policy parameter
- values beginning with start_year.
-
Raises
------
ValueError:
- if gfactors is not a GrowFactors class instance.
- if start_year is less than JSON_START_YEAR.
- if num_years is less than one.
+ if gfactors is not a GrowFactors class instance or None.
Returns
-------
@@ -50,10 +41,7 @@ class instance: Policy
# should increase LAST_BUDGET_YEAR by one every calendar year
DEFAULT_NUM_YEARS = LAST_BUDGET_YEAR - JSON_START_YEAR + 1
- def __init__(self,
- gfactors=None,
- start_year=JSON_START_YEAR,
- num_years=DEFAULT_NUM_YEARS):
+ def __init__(self, gfactors=None):
super(Policy, self).__init__()
if gfactors is None:
@@ -63,21 +51,15 @@ def __init__(self,
else:
raise ValueError('gfactors is not None or a GrowFactors instance')
- # read default parameters
+ # read default parameters and initialize
self._vals = self._params_dict_from_json_file()
-
- if start_year < Policy.JSON_START_YEAR:
- raise ValueError('start_year cannot be less than JSON_START_YEAR')
- if num_years < 1:
- raise ValueError('num_years cannot be less than one')
-
- syr = start_year
- lyr = start_year + num_years - 1
+ syr = Policy.JSON_START_YEAR
+ lyr = Policy.LAST_BUDGET_YEAR
+ nyrs = Policy.DEFAULT_NUM_YEARS
self._inflation_rates = self._gfactors.price_inflation_rates(syr, lyr)
- self._apply_clp_cpi_offset(self._vals['_cpi_offset'], num_years)
+ self._apply_clp_cpi_offset(self._vals['_cpi_offset'], nyrs)
self._wage_growth_rates = self._gfactors.wage_growth_rates(syr, lyr)
-
- self.initialize(start_year, num_years)
+ self.initialize(syr, nyrs)
self.parameter_warnings = ''
self.parameter_errors = ''
diff --git a/taxcalc/records_variables.json b/taxcalc/records_variables.json
index 982e96949..ee01f44f1 100644
--- a/taxcalc/records_variables.json
+++ b/taxcalc/records_variables.json
@@ -479,12 +479,6 @@
"form": {"2013-2016": "sample construction info"},
"availability": "taxdata_cps"
},
- "filer": {
- "type": "int",
- "desc": "1 if unit files an income tax return; 0 if not (not used in tax-calculation logic); in the puf.csv file a value of 1 indicates record is from IRS/SOI PUF and 0 indicates record is from CPS",
- "form": {"2013-2016": "sample construction info"},
- "availability": "taxdata_puf, taxdata_cps"
- },
"fips": {
"type": "int",
"desc": "FIPS state code (not used in tax-calculation logic)",
diff --git a/taxcalc/tests/test_calculator.py b/taxcalc/tests/test_calculator.py
index c18557ac6..cfac69045 100644
--- a/taxcalc/tests/test_calculator.py
+++ b/taxcalc/tests/test_calculator.py
@@ -41,32 +41,19 @@ def fixture_rawinputfile():
pass # sometimes we can't remove a generated temporary file
-@pytest.fixture(scope='module', name='policyfile')
-def fixture_policyfile():
- txt = """{"_almdep": {"value": [7150, 7250, 7400]},
- "_almsep": {"value": [40400, 41050]},
- "_rt5": {"value": [0.33 ]},
- "_rt7": {"value": [0.396]}}"""
- f = tempfile.NamedTemporaryFile(mode="a", delete=False)
- f.write(txt + "\n")
- f.close()
- # Must close and then yield for Windows platform
- yield f
- os.remove(f.name)
-
-
def test_make_calculator(cps_subsample):
- syr = 2014
- pol = Policy(start_year=syr, num_years=9)
- assert pol.current_year == syr
+ start_year = Policy.JSON_START_YEAR
+ sim_year = 2018
+ pol = Policy()
+ assert pol.current_year == start_year
rec = Records.cps_constructor(data=cps_subsample)
consump = Consumption()
- consump.update_consumption({syr: {'_MPC_e20400': [0.05]}})
- assert consump.current_year == Consumption.JSON_START_YEAR
+ consump.update_consumption({sim_year: {'_MPC_e20400': [0.05]}})
+ assert consump.current_year == start_year
calc = Calculator(policy=pol, records=rec,
consumption=consump, behavior=Behavior())
- assert calc.current_year == syr
- assert calc.records_current_year() == syr
+ assert calc.current_year == Records.CPSCSV_YEAR
+ assert calc.records_current_year() == Records.CPSCSV_YEAR
# test incorrect Calculator instantiation:
with pytest.raises(ValueError):
Calculator(policy=None, records=rec)
@@ -224,8 +211,7 @@ def test_calculator_mtr_when_PT_rates_differ():
def test_make_calculator_increment_years_first(cps_subsample):
# create Policy object with policy reform
- syr = 2013
- pol = Policy(start_year=syr)
+ pol = Policy()
reform = {2015: {}, 2016: {}}
std5 = 2000
reform[2015]['_STD_Aged'] = [[std5, std5, std5, std5, std5]]
@@ -238,6 +224,7 @@ def test_make_calculator_increment_years_first(cps_subsample):
calc = Calculator(policy=pol, records=rec)
# compare expected policy parameter values with those embedded in calc
irates = pol.inflation_rates()
+ syr = Policy.JSON_START_YEAR
irate2015 = irates[2015 - syr]
irate2016 = irates[2016 - syr]
std6 = std5 * (1.0 + irate2015)
diff --git a/taxcalc/tests/test_consumption.py b/taxcalc/tests/test_consumption.py
index a9c74af38..5f7b7c082 100644
--- a/taxcalc/tests/test_consumption.py
+++ b/taxcalc/tests/test_consumption.py
@@ -7,11 +7,9 @@
from taxcalc import Policy, Records, Calculator, Consumption
-def test_incorrect_Consumption_instantiation():
- with pytest.raises(ValueError):
- consump = Consumption(start_year=2000)
- with pytest.raises(ValueError):
- consump = Consumption(num_years=0)
+def test_year_consistency():
+ assert Consumption.JSON_START_YEAR == Policy.JSON_START_YEAR
+ assert Consumption.DEFAULT_NUM_YEARS == Policy.DEFAULT_NUM_YEARS
def test_validity_of_consumption_vars_set():
@@ -22,7 +20,7 @@ def test_validity_of_consumption_vars_set():
def test_update_consumption():
- consump = Consumption(start_year=2013)
+ consump = Consumption()
consump.update_consumption({})
consump.update_consumption({2014: {'_MPC_e20400': [0.05],
'_BEN_mcare_value': [0.75]},
diff --git a/taxcalc/tests/test_cpscsv.py b/taxcalc/tests/test_cpscsv.py
index 6903790bd..2371b47ed 100644
--- a/taxcalc/tests/test_cpscsv.py
+++ b/taxcalc/tests/test_cpscsv.py
@@ -107,7 +107,7 @@ def test_cps_availability(tests_path, cps_path):
if 'taxdata_cps' in vdict.get('availability', ''):
recvars.add(vname)
# check that cpsvars and recvars sets are the same
- assert (cpsvars - recvars) == set()
+ assert (cpsvars - recvars) == set(['filer'])
assert (recvars - cpsvars) == set()
diff --git a/taxcalc/tests/test_growdiff.py b/taxcalc/tests/test_growdiff.py
index b6739e687..a00350295 100644
--- a/taxcalc/tests/test_growdiff.py
+++ b/taxcalc/tests/test_growdiff.py
@@ -3,7 +3,7 @@
import os
import json
-from numpy.testing import assert_allclose
+import numpy as np
import pytest
from taxcalc import GrowDiff, GrowFactors, Policy
@@ -13,26 +13,19 @@ def test_year_consistency():
assert GrowDiff.DEFAULT_NUM_YEARS == Policy.DEFAULT_NUM_YEARS
-def test_incorrect_growdiff_ctor():
- with pytest.raises(ValueError):
- gdiff = GrowDiff(start_year=2000)
- with pytest.raises(ValueError):
- gdiff = GrowDiff(num_years=0)
-
-
def test_update_and_apply_growdiff():
- syr = 2013
- nyrs = 5
- lyr = syr + nyrs - 1
- gdiff = GrowDiff(start_year=syr, num_years=nyrs)
+ gdiff = GrowDiff()
# update GrowDiff instance
diffs = {2014: {'_AWAGE': [0.01]},
2016: {'_AWAGE': [0.02]}}
gdiff.update_growdiff(diffs)
- expected_wage_diffs = [0.00, 0.01, 0.01, 0.02, 0.02]
- assert_allclose(gdiff._AWAGE, expected_wage_diffs, atol=0.0, rtol=0.0)
+ expected_wage_diffs = [0.00, 0.01, 0.01, 0.02, 0.02] + [0.02]*10
+ 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
+ lyr = syr + nyrs - 1
pir_pre = gf.price_inflation_rates(syr, lyr)
wgr_pre = gf.wage_growth_rates(syr, lyr)
gfactors = GrowFactors()
@@ -41,8 +34,8 @@ def test_update_and_apply_growdiff():
wgr_pst = gfactors.wage_growth_rates(syr, lyr)
expected_wgr_pst = [wgr_pre[i] + expected_wage_diffs[i]
for i in range(0, nyrs)]
- assert_allclose(pir_pre, pir_pst, atol=0.0, rtol=0.0)
- assert_allclose(wgr_pst, expected_wgr_pst, atol=1.0e-9, rtol=0.0)
+ assert np.allclose(pir_pre, pir_pst, atol=0.0, rtol=0.0)
+ assert np.allclose(wgr_pst, expected_wgr_pst, atol=1.0e-9, rtol=0.0)
def test_incorrect_update_growdiff():
@@ -61,11 +54,12 @@ def test_incorrect_update_growdiff():
def test_has_any_response():
- syr = 2014
- gdiff = GrowDiff(start_year=syr)
+ start_year = GrowDiff.JSON_START_YEAR
+ gdiff = GrowDiff()
+ assert gdiff.current_year == start_year
assert gdiff.has_any_response() is False
gdiff.update_growdiff({2020: {'_AWAGE': [0.01]}})
- assert gdiff.current_year == syr
+ assert gdiff.current_year == start_year
assert gdiff.has_any_response() is True
diff --git a/taxcalc/tests/test_policy.py b/taxcalc/tests/test_policy.py
index c986b8bab..f2cbe6486 100644
--- a/taxcalc/tests/test_policy.py
+++ b/taxcalc/tests/test_policy.py
@@ -6,7 +6,6 @@
import json
import tempfile
import numpy as np
-from numpy.testing import assert_allclose
import pytest
from taxcalc import Policy, Calculator
@@ -14,10 +13,6 @@
def test_incorrect_Policy_instantiation():
with pytest.raises(ValueError):
Policy(gfactors=list())
- with pytest.raises(ValueError):
- Policy(start_year=2000)
- with pytest.raises(ValueError):
- Policy(num_years=0)
def test_correct_Policy_instantiation():
@@ -53,8 +48,7 @@ def test_policy_json_content():
def test_constant_inflation_rate_with_reform():
- syr = 2013
- pol = Policy(start_year=syr)
+ pol = Policy()
# implement reform in year before final year
fyr = Policy.LAST_BUDGET_YEAR
ryr = fyr - 1
@@ -65,6 +59,7 @@ def test_constant_inflation_rate_with_reform():
pol.implement_reform(reform)
# extract price inflation rates
pirates = pol.inflation_rates()
+ syr = Policy.JSON_START_YEAR
irate_b = pirates[ryr - 2 - syr]
irate_a = pirates[ryr - syr]
# check implied inflation rate just before reform
@@ -76,8 +71,8 @@ def test_constant_inflation_rate_with_reform():
def test_variable_inflation_rate_with_reform():
- syr = 2013
- pol = Policy(start_year=syr)
+ pol = Policy()
+ syr = Policy.JSON_START_YEAR
assert pol._II_em[2013 - syr] == 3900
# implement reform in 2020 which is two years before the last year, 2022
reform = {
@@ -108,9 +103,9 @@ def test_multi_year_reform():
Test multi-year reform involving 1D and 2D parameters.
"""
# specify dimensions of policy Policy object
- syr = 2013
+ syr = Policy.JSON_START_YEAR
nyrs = Policy.DEFAULT_NUM_YEARS
- pol = Policy(start_year=syr)
+ pol = Policy()
iratelist = pol.inflation_rates()
ifactor = {}
for i in range(0, nyrs):
@@ -120,48 +115,48 @@ def test_multi_year_reform():
for i in range(0, nyrs):
wfactor[syr + i] = 1.0 + wratelist[i]
# confirm that parameters have current-law values
- assert_allclose(getattr(pol, '_EITC_c'),
- Policy._expand_array(
- np.array([[487, 3250, 5372, 6044],
- [496, 3305, 5460, 6143],
- [503, 3359, 5548, 6242],
- [506, 3373, 5572, 6269],
- [510, 3400, 5616, 6318]],
- dtype=np.float64),
- False, False,
- inflate=True,
- inflation_rates=iratelist,
- num_years=nyrs),
- atol=0.01, rtol=0.0)
- assert_allclose(getattr(pol, '_STD_Dep'),
- Policy._expand_array(
- np.array([1000, 1000, 1050, 1050, 1050],
- dtype=np.float64),
- False, False,
- inflate=True,
- inflation_rates=iratelist,
- num_years=nyrs),
- atol=0.01, rtol=0.0)
- assert_allclose(getattr(pol, '_CTC_c'),
- Policy._expand_array(
- np.array([1000] * 5 + [1400] * 4 +
- [1500] * 3 + [1600] + [1000],
- dtype=np.float64),
- False, False,
- inflate=False,
- inflation_rates=iratelist,
- num_years=nyrs),
- atol=0.01, rtol=0.0)
+ assert np.allclose(getattr(pol, '_EITC_c'),
+ Policy._expand_array(
+ np.array([[487, 3250, 5372, 6044],
+ [496, 3305, 5460, 6143],
+ [503, 3359, 5548, 6242],
+ [506, 3373, 5572, 6269],
+ [510, 3400, 5616, 6318]],
+ dtype=np.float64),
+ False, False,
+ inflate=True,
+ inflation_rates=iratelist,
+ num_years=nyrs),
+ atol=0.01, rtol=0.0)
+ assert np.allclose(getattr(pol, '_STD_Dep'),
+ Policy._expand_array(
+ np.array([1000, 1000, 1050, 1050, 1050],
+ dtype=np.float64),
+ False, False,
+ inflate=True,
+ inflation_rates=iratelist,
+ num_years=nyrs),
+ atol=0.01, rtol=0.0)
+ assert np.allclose(getattr(pol, '_CTC_c'),
+ Policy._expand_array(
+ np.array([1000] * 5 + [1400] * 4 +
+ [1500] * 3 + [1600] + [1000],
+ dtype=np.float64),
+ False, False,
+ inflate=False,
+ inflation_rates=iratelist,
+ num_years=nyrs),
+ atol=0.01, rtol=0.0)
# this parameter uses a different indexing rate
- assert_allclose(getattr(pol, '_SS_Earnings_c'),
- Policy._expand_array(
- np.array([113700, 117000, 118500, 118500, 127200],
- dtype=np.float64),
- False, False,
- inflate=True,
- inflation_rates=wratelist,
- num_years=nyrs),
- atol=0.01, rtol=0.0)
+ assert np.allclose(getattr(pol, '_SS_Earnings_c'),
+ Policy._expand_array(
+ np.array([113700, 117000, 118500, 118500, 127200],
+ dtype=np.float64),
+ False, False,
+ inflate=True,
+ inflation_rates=wratelist,
+ num_years=nyrs),
+ atol=0.01, rtol=0.0)
# specify multi-year reform using a dictionary of year_provisions dicts
reform = {
2015: {
@@ -232,26 +227,26 @@ def check_eitc_c(ppo, reform, ifactor):
alen = len(arr[0])
for i in range(0, ppo.num_years):
actual[ppo.start_year + i] = arr[i]
- assert_allclose(actual[2013], [487, 3250, 5372, 6044],
- atol=0.01, rtol=0.0)
- assert_allclose(actual[2014], [496, 3305, 5460, 6143],
- atol=0.01, rtol=0.0)
- assert_allclose(actual[2015], [503, 3359, 5548, 6242],
- atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2013], [487, 3250, 5372, 6044],
+ atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2014], [496, 3305, 5460, 6143],
+ atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2015], [503, 3359, 5548, 6242],
+ atol=0.01, rtol=0.0)
e2016 = reform[2016]['_EITC_c'][0]
- assert_allclose(actual[2016], e2016, atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2016], e2016, atol=0.01, rtol=0.0)
e2017 = [ifactor[2016] * actual[2016][j] for j in range(0, alen)]
- assert_allclose(actual[2017], e2017, atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2017], e2017, atol=0.01, rtol=0.0)
e2018 = [ifactor[2017] * actual[2017][j] for j in range(0, alen)]
assert np.allclose(actual[2018], e2018, atol=0.01, rtol=0.0)
e2019 = reform[2019]['_EITC_c'][0]
- assert_allclose(actual[2019], e2019, atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2019], e2019, atol=0.01, rtol=0.0)
e2020 = [ifactor[2019] * actual[2019][j] for j in range(0, alen)]
- assert_allclose(actual[2020], e2020, atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2020], e2020, atol=0.01, rtol=0.0)
e2021 = [ifactor[2020] * actual[2020][j] for j in range(0, alen)]
- assert_allclose(actual[2021], e2021, atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2021], e2021, atol=0.01, rtol=0.0)
e2022 = [ifactor[2021] * actual[2021][j] for j in range(0, alen)]
- assert_allclose(actual[2022], e2022, atol=0.01, rtol=0.0)
+ assert np.allclose(actual[2022], e2022, atol=0.01, rtol=0.0)
def check_ii_em(ppo, reform, ifactor):
@@ -335,40 +330,40 @@ def test_create_parameters_from_file(monkeypatch, defaultpolicyfile):
monkeypatch.setattr(Policy, 'DEFAULTS_FILENAME', defaultpolicyfile.name)
ppo = Policy()
inf_rates = ppo.inflation_rates()
- assert_allclose(ppo._almdep,
- Policy._expand_array(
- np.array([7150, 7250, 7400],
- dtype=np.float64),
- False, False,
- inflate=True,
- inflation_rates=inf_rates,
- num_years=ppo.num_years),
- atol=0.01, rtol=0.0)
- assert_allclose(ppo._almsep,
- Policy._expand_array(
- np.array([40400, 41050],
- dtype=np.float64),
- False, False,
- inflate=True,
- inflation_rates=inf_rates,
- num_years=ppo.num_years),
- atol=0.01, rtol=0.0)
- assert_allclose(ppo._rt5,
- Policy._expand_array(
- np.array([0.33]),
- False, False,
- inflate=False,
- inflation_rates=inf_rates,
- num_years=ppo.num_years),
- atol=0.01, rtol=0.0)
- assert_allclose(ppo._rt7,
- Policy._expand_array(
- np.array([0.396]),
- False, False,
- inflate=False,
- inflation_rates=inf_rates,
- num_years=ppo.num_years),
- atol=0.01, rtol=0.0)
+ assert np.allclose(ppo._almdep,
+ Policy._expand_array(
+ np.array([7150, 7250, 7400],
+ dtype=np.float64),
+ False, False,
+ inflate=True,
+ inflation_rates=inf_rates,
+ num_years=ppo.num_years),
+ atol=0.01, rtol=0.0)
+ assert np.allclose(ppo._almsep,
+ Policy._expand_array(
+ np.array([40400, 41050],
+ dtype=np.float64),
+ False, False,
+ inflate=True,
+ inflation_rates=inf_rates,
+ num_years=ppo.num_years),
+ atol=0.01, rtol=0.0)
+ assert np.allclose(ppo._rt5,
+ Policy._expand_array(
+ np.array([0.33]),
+ False, False,
+ inflate=False,
+ inflation_rates=inf_rates,
+ num_years=ppo.num_years),
+ atol=0.01, rtol=0.0)
+ assert np.allclose(ppo._rt7,
+ Policy._expand_array(
+ np.array([0.396]),
+ False, False,
+ inflate=False,
+ inflation_rates=inf_rates,
+ num_years=ppo.num_years),
+ atol=0.01, rtol=0.0)
def test_parameters_get_default():
@@ -384,23 +379,23 @@ def test_implement_reform_Policy_raises_on_no_year():
def test_Policy_reform_in_start_year():
- ppo = Policy(start_year=2013)
+ ppo = Policy()
reform = {2013: {'_STD': [[16000, 13000, 13000, 16000, 16000]]}}
ppo.implement_reform(reform)
- assert_allclose(ppo.STD,
- np.array([16000, 13000, 13000, 16000, 16000]),
- atol=0.01, rtol=0.0)
+ assert np.allclose(ppo.STD,
+ np.array([16000, 13000, 13000, 16000, 16000]),
+ atol=0.01, rtol=0.0)
-def test_implement_reform_Policy_raises_on_future_year():
- ppo = Policy(start_year=2013)
+def test_implement_reform_Policy_raises_on_early_year():
+ ppo = Policy()
reform = {2010: {'_STD_Aged': [[1400, 1100, 1100, 1400, 1400]]}}
with pytest.raises(ValueError):
ppo.implement_reform(reform)
def test_Policy_reform_with_default_cpi_flags():
- ppo = Policy(start_year=2013)
+ ppo = Policy()
reform = {2015: {'_II_em': [4300]}}
ppo.implement_reform(reform)
# '_II_em' has a default cpi_flag of True, so
@@ -410,43 +405,47 @@ def test_Policy_reform_with_default_cpi_flags():
def test_Policy_reform_after_start_year():
- ppo = Policy(start_year=2013)
+ ppo = Policy()
reform = {2015: {'_STD_Aged': [[1400, 1100, 1100, 1400, 1400]]}}
ppo.implement_reform(reform)
ppo.set_year(2015)
- assert_allclose(ppo.STD_Aged,
- np.array([1400, 1100, 1100, 1400, 1400]),
- atol=0.01, rtol=0.0)
+ assert np.allclose(ppo.STD_Aged,
+ np.array([1400, 1100, 1100, 1400, 1400]),
+ atol=0.01, rtol=0.0)
def test_Policy_reform_makes_no_changes_before_year():
- ppo = Policy(start_year=2013)
+ ppo = Policy()
reform = {2015: {'_II_em': [4400], '_II_em_cpi': True}}
ppo.implement_reform(reform)
ppo.set_year(2015)
- assert_allclose(ppo._II_em[:3], np.array([3900, 3950, 4400]),
- atol=0.01, rtol=0.0)
+ assert np.allclose(ppo._II_em[:3], np.array([3900, 3950, 4400]),
+ atol=0.01, rtol=0.0)
assert ppo.II_em == 4400
-def test_parameters_get_default_start_year():
- paramdata = Policy.default_data(metadata=True, start_year=2015)
- # 1D data, has 2015 values
+def test_parameters_get_default_data():
+ paramdata = Policy.default_data(metadata=True)
+ # 1D data, has 2013+ values
meta_II_em = paramdata['_II_em']
- assert meta_II_em['start_year'] == 2015
- assert meta_II_em['row_label'] == [str(cyr) for cyr in range(2015, 2027)]
- assert meta_II_em['value'] == [4000, 4050, 4050] + [0] * 8 + [4883]
- # 2D data, has 2015 values
+ assert meta_II_em['start_year'] == 2013
+ assert meta_II_em['row_label'] == [str(cyr) for cyr in range(2013, 2027)]
+ expval = [3900, 3950, 4000, 4050, 4050] + [0] * 8 + [4883]
+ assert meta_II_em['value'] == expval
+ # 2D data, has 2013+ values
meta_std_aged = paramdata['_STD_Aged']
- assert meta_std_aged['start_year'] == 2015
- assert meta_std_aged['row_label'] == ['2015', '2016', '2017']
- assert meta_std_aged['value'] == [[1550, 1250, 1250, 1550, 1550],
+ assert meta_std_aged['start_year'] == 2013
+ explabels = ['2013', '2014', '2015', '2016', '2017']
+ assert meta_std_aged['row_label'] == explabels
+ assert meta_std_aged['value'] == [[1500, 1200, 1200, 1500, 1500],
+ [1550, 1200, 1200, 1550, 1550],
+ [1550, 1250, 1250, 1550, 1550],
[1550, 1250, 1250, 1550, 1550],
[1550, 1250, 1250, 1550, 1550]]
- # 1D data, doesn't have 2015 values, is not CPI inflated
+ # 1D data, has only 2013 values because is not CPI inflated
meta_kt_c_age = paramdata['_AMT_KT_c_Age']
- assert meta_kt_c_age['start_year'] == 2015
- assert meta_kt_c_age['row_label'] == ['2015']
+ assert meta_kt_c_age['start_year'] == 2013
+ assert meta_kt_c_age['row_label'] == ['2013']
assert meta_kt_c_age['value'] == [24]
@@ -553,11 +552,12 @@ def test_pop_the_cap_reform():
Test eliminating the maximum taxable earnings (MTE)
used in the calculation of the OASDI payroll tax.
"""
- # clarify start year and create Policy parameters object
- syr = 2013
- ppo = Policy(start_year=syr)
+ # create Policy parameters object
+ ppo = Policy()
+ assert ppo.current_year == Policy.JSON_START_YEAR
# confirm that MTE has current-law values in 2015 and 2016
mte = ppo._SS_Earnings_c
+ syr = Policy.JSON_START_YEAR
assert mte[2015 - syr] == 118500
assert mte[2016 - syr] == 118500
# specify a "pop the cap" reform that eliminates MTE cap in 2016
@@ -580,9 +580,9 @@ def test_order_of_cpi_and_level_reforms():
{2015: {'_SS_Earnings_c_cpi': False,
'_SS_Earnings_c': [500000]}}]
# specify two Policy objects
- syr = 2013
- ppo = [Policy(start_year=syr), Policy(start_year=syr)]
+ ppo = [Policy(), Policy()]
# apply reforms to corresponding Policy object & check post-reform values
+ syr = Policy.JSON_START_YEAR
for ref in range(len(reform)):
# confirm pre-reform MTE values in 2014-17
mte = ppo[ref]._SS_Earnings_c
diff --git a/taxcalc/tests/test_pufcsv.py b/taxcalc/tests/test_pufcsv.py
index 40fc064a7..7110ad451 100644
--- a/taxcalc/tests/test_pufcsv.py
+++ b/taxcalc/tests/test_pufcsv.py
@@ -331,7 +331,7 @@ def test_puf_availability(tests_path, puf_path):
if 'taxdata_puf' in vdict.get('availability', ''):
recvars.add(vname)
# check that pufvars and recvars sets are the same
- assert (pufvars - recvars) == set()
+ assert (pufvars - recvars) == set(['filer'])
assert (recvars - pufvars) == set()
diff --git a/taxcalc/validation/taxsim/test.sh b/taxcalc/validation/taxsim/test.sh
index 255b6cd16..097a042bf 100755
--- a/taxcalc/validation/taxsim/test.sh
+++ b/taxcalc/validation/taxsim/test.sh
@@ -50,7 +50,7 @@ unzip -oq output-taxsim.zip $LYY.in.out-taxsim$SUFFIX
tclsh taxdiffs.tcl $OVAR4 $LYY.in.out-simtax$SUFFIX \
$LYY.in.out-taxsim$SUFFIX > $LYY$SUFFIX.taxdiffs
RC=$?
-if [ $RC -ne 0 ]; then
+if [[ $RC -ne 0 ]]; then
exit $RC
fi
# Check for difference between actual .taxdiffs and expected .taxdiffs files
diff --git a/versioneer.py b/versioneer.py
deleted file mode 100644
index 179e34c9e..000000000
--- a/versioneer.py
+++ /dev/null
@@ -1,941 +0,0 @@
-
-# Version: 0.12
-
-"""
-The Versioneer
-==============
-
-* like a rocketeer, but for versions!
-* https://github.com/warner/python-versioneer
-* Brian Warner
-* License: Public Domain
-* Compatible With: python2.6, 2.7, 3.2, 3.3, 3.4, and pypy
-
-[![Build Status]
-(https://travis-ci.org/warner/python-versioneer.png?branch=master)]
-(https://travis-ci.org/warner/python-versioneer)
-
-This is a tool for managing a recorded version number in distutils-based
-python projects. The goal is to remove the tedious and error-prone "update
-the embedded version string" step from your release process. Making a new
-release should be as easy as recording a new tag in your version-control
-system, and maybe making new tarballs.
-
-
-## Quick Install
-
-* `pip install versioneer` to somewhere to your $PATH
-* run `versioneer-installer` in your source tree: this installs `versioneer.py`
-* follow the instructions below (also in the `versioneer.py` docstring)
-
-## Version Identifiers
-
-Source trees come from a variety of places:
-
-* a version-control system checkout (mostly used by developers)
-* a nightly tarball, produced by build automation
-* a snapshot tarball, produced by a web-based VCS browser, like github's
- "tarball from tag" feature
-* a release tarball, produced by "setup.py sdist", distributed through PyPI
-
-Within each source tree, the version identifier (either a string or a number,
-this tool is format-agnostic) can come from a variety of places:
-
-* ask the VCS tool itself, e.g. "git describe" (for checkouts), which knows
- about recent "tags" and an absolute revision-id
-* the name of the directory into which the tarball was unpacked
-* an expanded VCS keyword ($Id$, etc)
-* a `_version.py` created by some earlier build step
-
-For released software, the version identifier is closely related to a VCS
-tag. Some projects use tag names that include more than just the version
-string (e.g. "myproject-1.2" instead of just "1.2"), in which case the tool
-needs to strip the tag prefix to extract the version identifier. For
-unreleased software (between tags), the version identifier should provide
-enough information to help developers recreate the same tree, while also
-giving them an idea of roughly how old the tree is (after version 1.2, before
-version 1.3). Many VCS systems can report a description that captures this,
-for example 'git describe --tags --dirty --always' reports things like
-"0.7-1-g574ab98-dirty" to indicate that the checkout is one revision past the
-0.7 tag, has a unique revision id of "574ab98", and is "dirty" (it has
-uncommitted changes.
-
-The version identifier is used for multiple purposes:
-
-* to allow the module to self-identify its version: `myproject.__version__`
-* to choose a name and prefix for a 'setup.py sdist' tarball
-
-## Theory of Operation
-
-Versioneer works by adding a special `_version.py` file into your source
-tree, where your `__init__.py` can import it. This `_version.py` knows how to
-dynamically ask the VCS tool for version information at import time. However,
-when you use "setup.py build" or "setup.py sdist", `_version.py` in the new
-copy is replaced by a small static file that contains just the generated
-version data.
-
-`_version.py` also contains `$Revision$` markers, and the installation
-process marks `_version.py` to have this marker rewritten with a tag name
-during the "git archive" command. As a result, generated tarballs will
-contain enough information to get the proper version.
-
-
-## Installation
-
-First, decide on values for the following configuration variables:
-
-* `VCS`: the version control system you use. Currently accepts "git".
-
-* `versionfile_source`:
-
- A project-relative pathname into which the generated version strings should
- be written. This is usually a `_version.py` next to your project's main
- `__init__.py` file, so it can be imported at runtime. If your project uses
- `src/myproject/__init__.py`, this should be `src/myproject/_version.py`.
- This file should be checked in to your VCS as usual: the copy created below
- by `setup.py versioneer` will include code that parses expanded VCS
- keywords in generated tarballs. The 'build' and 'sdist' commands will
- replace it with a copy that has just the calculated version string.
-
- This must be set even if your project does not have any modules (and will
- therefore never import `_version.py`), since "setup.py sdist" -based trees
- still need somewhere to record the pre-calculated version strings. Anywhere
- in the source tree should do. If there is a `__init__.py` next to your
- `_version.py`, the `setup.py versioneer` command (described below) will
- append some `__version__`-setting assignments, if they aren't already
- present.
-
-* `versionfile_build`:
-
- Like `versionfile_source`, but relative to the build directory instead of
- the source directory. These will differ when your setup.py uses
- 'package_dir='. If you have `package_dir={'myproject': 'src/myproject'}`,
- then you will probably have `versionfile_build='myproject/_version.py'` and
- `versionfile_source='src/myproject/_version.py'`.
-
- If this is set to None, then `setup.py build` will not attempt to rewrite
- any `_version.py` in the built tree. If your project does not have any
- libraries (e.g. if it only builds a script), then you should use
- `versionfile_build = None` and override `distutils.command.build_scripts`
- to explicitly insert a copy of `versioneer.get_version()` into your
- generated script.
-
-* `tag_prefix`:
-
- a string, like 'PROJECTNAME-', which appears at the start of all VCS tags.
- If your tags look like 'myproject-1.2.0', then you should use
- tag_prefix='myproject-'. If you use unprefixed tags like '1.2.0', this
- should be an empty string.
-
-* `parentdir_prefix`:
-
- a string, frequently the same as tag_prefix, which appears at the start of
- all unpacked tarball filenames. If your tarball unpacks into
- 'myproject-1.2.0', this should be 'myproject-'.
-
-This tool provides one script, named `versioneer-installer`. That script does
-one thing: write a copy of `versioneer.py` into the current directory.
-
-To versioneer-enable your project:
-
-* 1: Run `versioneer-installer` to copy `versioneer.py` into the top of your
- source tree.
-
-* 2: add the following lines to the top of your `setup.py`, with the
- configuration values you decided earlier:
-
- import versioneer
- versioneer.VCS = 'git'
- versioneer.versionfile_source = 'src/myproject/_version.py'
- versioneer.versionfile_build = 'myproject/_version.py'
- versioneer.tag_prefix = '' # tags are like 1.2.0
- versioneer.parentdir_prefix = (
- 'myproject-' # dirname like 'myproject-1.2.0')
-
-* 3: add the following arguments to the setup() call in your setup.py:
-
- version=versioneer.get_version(),
- cmdclass=versioneer.get_cmdclass(),
-
-* 4: now run `setup.py versioneer`, which will create `_version.py`, and will
- modify your `__init__.py` (if one exists next to `_version.py`) to define
- `__version__` (by calling a function from `_version.py`). It will also
- modify your `MANIFEST.in` to include both `versioneer.py` and the generated
- `_version.py` in sdist tarballs.
-
-* 5: commit these changes to your VCS. To make sure you won't forget,
- `setup.py versioneer` will mark everything it touched for addition.
-
-## Post-Installation Usage
-
-Once established, all uses of your tree from a VCS checkout should get the
-current version string. All generated tarballs should include an embedded
-version string (so users who unpack them will not need a VCS tool installed).
-
-If you distribute your project through PyPI, then the release process should
-boil down to two steps:
-
-* 1: git tag 1.0
-* 2: python setup.py register sdist upload
-
-If you distribute it through github (i.e. users use github to generate
-tarballs with `git archive`), the process is:
-
-* 1: git tag 1.0
-* 2: git push; git push --tags
-
-Currently, all version strings must be based upon a tag. Versioneer will
-report "unknown" until your tree has at least one tag in its history. This
-restriction will be fixed eventually (see issue #12).
-
-## Version-String Flavors
-
-Code which uses Versioneer can learn about its version string at runtime by
-importing `_version` from your main `__init__.py` file and running the
-`get_versions()` function. From the "outside" (e.g. in `setup.py`), you can
-import the top-level `versioneer.py` and run `get_versions()`.
-
-Both functions return a dictionary with different keys for different flavors
-of the version string:
-
-* `['version']`: condensed tag+distance+shortid+dirty identifier. For git,
- this uses the output of `git describe --tags --dirty --always` but strips
- the tag_prefix. For example "0.11-2-g1076c97-dirty" indicates that the tree
- is like the "1076c97" commit but has uncommitted changes ("-dirty"), and
- that this commit is two revisions ("-2-") beyond the "0.11" tag. For
- released software (exactly equal to a known tag), the identifier will only
- contain the stripped tag, e.g. "0.11".
-
-* `['full']`: detailed revision identifier. For Git, this is the full SHA1
- commit id, followed by "-dirty" if the tree contains uncommitted changes,
- e.g. "1076c978a8d3cfc70f408fe5974aa6c092c949ac-dirty".
-
-Some variants are more useful than others. Including `full` in a bug report
-should allow developers to reconstruct the exact code being tested (or
-indicate the presence of local changes that should be shared with the
-developers). `version` is suitable for display in an "about" box or a CLI
-`--version` output: it can be easily compared against release notes and lists
-of bugs fixed in various releases.
-
-In the future, this will also include a
-[PEP-0440](http://legacy.python.org/dev/peps/pep-0440/) -compatible flavor
-(e.g. `1.2.post0.dev123`). This loses a lot of information (and has no room
-for a hash-based revision id), but is safe to use in a `setup.py`
-"`version=`" argument. It also enables tools like *pip* to compare version
-strings and evaluate compatibility constraint declarations.
-
-The `setup.py versioneer` command adds the following text to your
-`__init__.py` to place a basic version in `YOURPROJECT.__version__`:
-
- from ._version import get_versions
- __version__ = get_versions()['version']
- del get_versions
-
-## Updating Versioneer
-
-To upgrade your project to a new release of Versioneer, do the following:
-
-* install the new Versioneer (`pip install -U versioneer` or equivalent)
-* re-run `versioneer-installer` in your source tree to replace your copy of
- `versioneer.py`
-* edit `setup.py`, if necessary, to include any new configuration settings
- indicated by the release notes
-* re-run `setup.py versioneer` to replace `SRC/_version.py`
-* commit any changed files
-
-### Upgrading from 0.10 to 0.11
-
-You must add a `versioneer.VCS = "git"` to your `setup.py` before re-running
-`setup.py versioneer`. This will enable the use of additional version-control
-systems (SVN, etc) in the future.
-
-### Upgrading from 0.11 to 0.12
-
-Nothing special.
-
-## Future Directions
-
-This tool is designed to make it easily extended to other version-control
-systems: all VCS-specific components are in separate directories like
-src/git/ . The top-level `versioneer.py` script is assembled from these
-components by running make-versioneer.py . In the future, make-versioneer.py
-will take a VCS name as an argument, and will construct a version of
-`versioneer.py` that is specific to the given VCS. It might also take the
-configuration arguments that are currently provided manually during
-installation by editing setup.py . Alternatively, it might go the other
-direction and include code from all supported VCS systems, reducing the
-number of intermediate scripts.
-
-
-## License
-
-To make Versioneer easier to embed, all its code is hereby released into the
-public domain. The `_version.py` that it creates is also in the public
-domain.
-
-"""
-
-import os
-import sys
-import re
-import subprocess
-import errno
-from distutils.core import Command
-from distutils.command.sdist import sdist as _sdist
-from distutils.command.build import build as _build
-
-# these configuration settings will be overridden by setup.py after it
-# imports us
-versionfile_source = None
-versionfile_build = None
-tag_prefix = None
-parentdir_prefix = None
-VCS = None
-
-# these dictionaries contain VCS-specific tools
-LONG_VERSION_PY = {}
-
-
-def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
- assert isinstance(commands, list)
- p = None
- for c in commands:
- try:
- # remember shell=False, so use git.cmd on windows, not just git
- p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
- stderr=(subprocess.PIPE if hide_stderr
- else None))
- break
- except EnvironmentError:
- e = sys.exc_info()[1]
- if e.errno == errno.ENOENT:
- continue
- if verbose:
- print("unable to run %s" % args[0])
- print(e)
- return None
- else:
- if verbose:
- print("unable to find command, tried %s" % (commands,))
- return None
- stdout = p.communicate()[0].strip()
- if sys.version >= '3':
- stdout = stdout.decode()
- if p.returncode != 0:
- if verbose:
- print("unable to run %s (error)" % args[0])
- return None
- return stdout
-
-LONG_VERSION_PY['git'] = '''
-# This file helps to compute a version number in source trees obtained from
-# git-archive tarball (such as those provided by githubs download-from-tag
-# feature). Distribution tarballs (built by setup.py sdist) and build
-# directories (produced by setup.py build) will contain a much shorter file
-# that just contains the computed version number.
-
-# This file is released into the public domain. Generated by
-# versioneer-0.12 (https://github.com/warner/python-versioneer)
-
-# these strings will be replaced by git during git-archive
-git_refnames = "%(DOLLAR)sFormat:%%d%(DOLLAR)s"
-git_full = "%(DOLLAR)sFormat:%%H%(DOLLAR)s"
-
-# these strings are filled in when 'setup.py versioneer' creates _version.py
-tag_prefix = "%(TAG_PREFIX)s"
-parentdir_prefix = "%(PARENTDIR_PREFIX)s"
-versionfile_source = "%(VERSIONFILE_SOURCE)s"
-
-import os, sys, re, subprocess, errno
-
-def run_command(commands, args, cwd=None, verbose=False, hide_stderr=False):
- assert isinstance(commands, list)
- p = None
- for c in commands:
- try:
- # remember shell=False, so use git.cmd on windows, not just git
- p = subprocess.Popen([c] + args, cwd=cwd, stdout=subprocess.PIPE,
- stderr=(subprocess.PIPE if hide_stderr
- else None))
- break
- except EnvironmentError:
- e = sys.exc_info()[1]
- if e.errno == errno.ENOENT:
- continue
- if verbose:
- print("unable to run %%s" %% args[0])
- print(e)
- return None
- else:
- if verbose:
- print("unable to find command, tried %%s" %% (commands,))
- return None
- stdout = p.communicate()[0].strip()
- if sys.version >= '3':
- stdout = stdout.decode()
- if p.returncode != 0:
- if verbose:
- print("unable to run %%s (error)" %% args[0])
- return None
- return stdout
-
-
-def versions_from_parentdir(parentdir_prefix, root, verbose=False):
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
- dirname = os.path.basename(root)
- if not dirname.startswith(parentdir_prefix):
- if verbose:
- print("guessing rootdir is '%%s',
- but '%%s' doesn't start with prefix '%%s'" %%
- (root, dirname, parentdir_prefix))
- return None
- return {"version": dirname[len(parentdir_prefix):], "full": ""}
-
-def git_get_keywords(versionfile_abs):
- # the code embedded in _version.py can just fetch the value of these
- # keywords. When used from setup.py, we don't want to import _version.py,
- # so we do it with a regexp instead. This function is not used from
- # _version.py.
- keywords = {}
- try:
- f = open(versionfile_abs,"r")
- for line in f.readlines():
- if line.strip().startswith("git_refnames ="):
- mo = re.search(r'=\s*"(.*)"', line)
- if mo:
- keywords["refnames"] = mo.group(1)
- if line.strip().startswith("git_full ="):
- mo = re.search(r'=\s*"(.*)"', line)
- if mo:
- keywords["full"] = mo.group(1)
- f.close()
- except EnvironmentError:
- pass
- return keywords
-
-def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
- if not keywords:
- return {} # keyword-finding function failed to find keywords
- refnames = keywords["refnames"].strip()
- if refnames.startswith("$Format"):
- if verbose:
- print("keywords are unexpanded, not using")
- return {} # unexpanded, so not in an unpacked git-archive tarball
- refs = set([r.strip() for r in refnames.strip("()").split(",")])
- # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
- # just "foo-1.0". If we see a "tag: " prefix, prefer those.
- TAG = "tag: "
- tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
- if not tags:
- # Either we're using git < 1.8.3, or there really are no tags. We use
- # a heuristic: assume all version tags have a digit. The old git %%d
- # expansion behaves like git log --decorate=short and strips out the
- # refs/heads/ and refs/tags/ prefixes that would let us distinguish
- # between branches and tags. By ignoring refnames without digits, we
- # filter out many common branch names like "release" and
- # "stabilization", as well as "HEAD" and "master".
- tags = set([r for r in refs if re.search(r'\d', r)])
- if verbose:
- print("discarding '%%s', no digits" %% ",".join(refs-tags))
- if verbose:
- print("likely tags: %%s" %% ",".join(sorted(tags)))
- for ref in sorted(tags):
- # sorting will prefer e.g. "2.0" over "2.0rc1"
- if ref.startswith(tag_prefix):
- r = ref[len(tag_prefix):]
- if verbose:
- print("picking %%s" %% r)
- return { "version": r,
- "full": keywords["full"].strip() }
- # no suitable tags, so we use the full revision id
- if verbose:
- print("no suitable tags, using full revision id")
- return { "version": keywords["full"].strip(),
- "full": keywords["full"].strip() }
-
-
-def git_versions_from_vcs(tag_prefix, root, verbose=False):
- # this runs 'git' from the root of the source tree. This only gets called
- # if the git-archive 'subst' keywords were *not* expanded, and
- # _version.py hasn't already been rewritten with a short version string,
- # meaning we're inside a checked out source tree.
-
- if not os.path.exists(os.path.join(root, ".git")):
- if verbose:
- print("no .git in %%s" %% root)
- return {}
-
- GITS = ["git"]
- if sys.platform == "win32":
- GITS = ["git.cmd", "git.exe"]
- stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
- cwd=root)
- if stdout is None:
- return {}
- if not stdout.startswith(tag_prefix):
- if verbose:
- print("tag '%%s' doesn't start with prefix
- '%%s'" %% (stdout, tag_prefix))
- return {}
- tag = stdout[len(tag_prefix):]
- stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
- if stdout is None:
- return {}
- full = stdout.strip()
- if tag.endswith("-dirty"):
- full += "-dirty"
- return {"version": tag, "full": full}
-
-
-def get_versions(default={"version": "unknown", "full": ""}, verbose=False):
- # I am in _version.py, which lives at ROOT/VERSIONFILE_SOURCE. If we have
- # __file__, we can work backwards from there to the root. Some
- # py2exe/bbfreeze/non-CPython implementations don't do __file__, in which
- # case we can only use expanded keywords.
-
- keywords = { "refnames": git_refnames, "full": git_full }
- ver = git_versions_from_keywords(keywords, tag_prefix, verbose)
- if ver:
- return ver
-
- try:
- root = os.path.abspath(__file__)
- # versionfile_source is the relative path from the top of the source
- # tree (where the .git directory might live) to this file. Invert
- # this to find the root from __file__.
- for i in range(len(versionfile_source.split(os.sep))):
- root = os.path.dirname(root)
- except NameError:
- return default
-
- return (git_versions_from_vcs(tag_prefix, root, verbose)
- or versions_from_parentdir(parentdir_prefix, root, verbose)
- or default)
-'''
-
-
-def git_get_keywords(versionfile_abs):
- # the code embedded in _version.py can just fetch the value of these
- # keywords. When used from setup.py, we don't want to import _version.py,
- # so we do it with a regexp instead. This function is not used from
- # _version.py.
- keywords = {}
- try:
- f = open(versionfile_abs, "r")
- for line in f.readlines():
- if line.strip().startswith("git_refnames ="):
- mo = re.search(r'=\s*"(.*)"', line)
- if mo:
- keywords["refnames"] = mo.group(1)
- if line.strip().startswith("git_full ="):
- mo = re.search(r'=\s*"(.*)"', line)
- if mo:
- keywords["full"] = mo.group(1)
- f.close()
- except EnvironmentError:
- pass
- return keywords
-
-
-def git_versions_from_keywords(keywords, tag_prefix, verbose=False):
- if not keywords:
- return {} # keyword-finding function failed to find keywords
- refnames = keywords["refnames"].strip()
- if refnames.startswith("$Format"):
- if verbose:
- print("keywords are unexpanded, not using")
- return {} # unexpanded, so not in an unpacked git-archive tarball
- refs = set([r.strip() for r in refnames.strip("()").split(",")])
- # starting in git-1.8.3, tags are listed as "tag: foo-1.0" instead of
- # just "foo-1.0". If we see a "tag: " prefix, prefer those.
- TAG = "tag: "
- tags = set([r[len(TAG):] for r in refs if r.startswith(TAG)])
- if not tags:
- # Either we're using git < 1.8.3, or there really are no tags. We use
- # a heuristic: assume all version tags have a digit. The old git %d
- # expansion behaves like git log --decorate=short and strips out the
- # refs/heads/ and refs/tags/ prefixes that would let us distinguish
- # between branches and tags. By ignoring refnames without digits, we
- # filter out many common branch names like "release" and
- # "stabilization", as well as "HEAD" and "master".
- tags = set([r for r in refs if re.search(r'\d', r)])
- if verbose:
- print("discarding '%s', no digits" % ",".join(refs - tags))
- if verbose:
- print("likely tags: %s" % ",".join(sorted(tags)))
- for ref in sorted(tags):
- # sorting will prefer e.g. "2.0" over "2.0rc1"
- if ref.startswith(tag_prefix):
- r = ref[len(tag_prefix):]
- if verbose:
- print("picking %s" % r)
- return {"version": r,
- "full": keywords["full"].strip()}
- # no suitable tags, so we use the full revision id
- if verbose:
- print("no suitable tags, using full revision id")
- return {"version": keywords["full"].strip(),
- "full": keywords["full"].strip()}
-
-
-def git_versions_from_vcs(tag_prefix, root, verbose=False):
- # this runs 'git' from the root of the source tree. This only gets called
- # if the git-archive 'subst' keywords were *not* expanded, and
- # _version.py hasn't already been rewritten with a short version string,
- # meaning we're inside a checked out source tree.
-
- if not os.path.exists(os.path.join(root, ".git")):
- if verbose:
- print("no .git in %s" % root)
- return {}
-
- GITS = ["git"]
- if sys.platform == "win32":
- GITS = ["git.cmd", "git.exe"]
- stdout = run_command(GITS, ["describe", "--tags", "--dirty", "--always"],
- cwd=root)
- if stdout is None:
- return {}
- if not stdout.startswith(tag_prefix):
- if verbose:
- print("tag '%s' doesn't start with prefix '%s'"
- % (stdout, tag_prefix))
- return {}
- tag = stdout[len(tag_prefix):]
- stdout = run_command(GITS, ["rev-parse", "HEAD"], cwd=root)
- if stdout is None:
- return {}
- full = stdout.strip()
- if tag.endswith("-dirty"):
- full += "-dirty"
- return {"version": tag, "full": full}
-
-
-def do_vcs_install(manifest_in, versionfile_source, ipy):
- GITS = ["git"]
- if sys.platform == "win32":
- GITS = ["git.cmd", "git.exe"]
- files = [manifest_in, versionfile_source]
- if ipy:
- files.append(ipy)
- try:
- me = __file__
- if me.endswith(".pyc") or me.endswith(".pyo"):
- me = os.path.splitext(me)[0] + ".py"
- versioneer_file = os.path.relpath(me)
- except NameError:
- versioneer_file = "versioneer.py"
- files.append(versioneer_file)
- present = False
- try:
- f = open(".gitattributes", "r")
- for line in f.readlines():
- if line.strip().startswith(versionfile_source):
- if "export-subst" in line.strip().split()[1:]:
- present = True
- f.close()
- except EnvironmentError:
- pass
- if not present:
- f = open(".gitattributes", "a+")
- f.write("%s export-subst\n" % versionfile_source)
- f.close()
- files.append(".gitattributes")
- run_command(GITS, ["add", "--"] + files)
-
-
-def versions_from_parentdir(parentdir_prefix, root, verbose=False):
- # Source tarballs conventionally unpack into a directory that includes
- # both the project name and a version string.
- dirname = os.path.basename(root)
- if not dirname.startswith(parentdir_prefix):
- if verbose:
- print("guessing rootdir is '%s',"
- "but '%s' doesn't start with prefix '%s'" %
- (root, dirname, parentdir_prefix))
- return None
- return {"version": dirname[len(parentdir_prefix):], "full": ""}
-
-SHORT_VERSION_PY = """
-# This file was generated by 'versioneer.py' (0.12) from
-# revision-control system data, or from the parent directory name of an
-# unpacked source archive. Distribution tarballs contain a pre-generated copy
-# of this file.
-
-version_version = '%(version)s'
-version_full = '%(full)s'
-def get_versions(default={}, verbose=False):
- return {'version': version_version, 'full': version_full}
-
-"""
-
-DEFAULT = {"version": "unknown", "full": "unknown"}
-
-
-def versions_from_file(filename):
- versions = {}
- try:
- with open(filename) as f:
- for line in f.readlines():
- mo = re.match("version_version = '([^']+)'", line)
- if mo:
- versions["version"] = mo.group(1)
- mo = re.match("version_full = '([^']+)'", line)
- if mo:
- versions["full"] = mo.group(1)
- except EnvironmentError:
- return {}
-
- return versions
-
-
-def write_to_version_file(filename, versions):
- with open(filename, "w") as f:
- f.write(SHORT_VERSION_PY % versions)
-
- print("set %s to '%s'" % (filename, versions["version"]))
-
-
-def get_root():
- try:
- return os.path.dirname(os.path.abspath(__file__))
- except NameError:
- return os.path.dirname(os.path.abspath(sys.argv[0]))
-
-
-def vcs_function(vcs, suffix):
- return getattr(sys.modules[__name__], '%s_%s' % (vcs, suffix), None)
-
-
-def get_versions(default=DEFAULT, verbose=False):
- # returns dict with two keys: 'version' and 'full'
- assert (versionfile_source is not None,
- "please set versioneer.versionfile_source")
- assert tag_prefix is not None, "please set versioneer.tag_prefix"
- assert (parentdir_prefix is not None,
- "please set versioneer.parentdir_prefix")
- assert VCS is not None, "please set versioneer.VCS"
-
- # I am in versioneer.py, which must live at the top of the source tree,
- # which we use to compute the root directory. py2exe/bbfreeze/non-CPython
- # don't have __file__, in which case we fall back to sys.argv[0] (which
- # ought to be the setup.py script). We prefer __file__ since that's more
- # robust in cases where setup.py was invoked in some weird way (e.g. pip)
- root = get_root()
- versionfile_abs = os.path.join(root, versionfile_source)
-
- # extract version from first of _version.py, VCS command (e.g. 'git
- # describe'), parentdir. This is meant to work for developers using a
- # source checkout, for users of a tarball created by 'setup.py sdist',
- # and for users of a tarball/zipball created by 'git archive' or github's
- # download-from-tag feature or the equivalent in other VCSes.
-
- get_keywords_f = vcs_function(VCS, "get_keywords")
- versions_from_keywords_f = vcs_function(VCS, "versions_from_keywords")
- if get_keywords_f and versions_from_keywords_f:
- vcs_keywords = get_keywords_f(versionfile_abs)
- ver = versions_from_keywords_f(vcs_keywords, tag_prefix)
- if ver:
- if verbose:
- print("got version from expanded keyword %s" % ver)
- return ver
-
- ver = versions_from_file(versionfile_abs)
- if ver:
- if verbose:
- print("got version from file %s %s"
- % (versionfile_abs, ver))
- return ver
-
- versions_from_vcs_f = vcs_function(VCS, "versions_from_vcs")
- if versions_from_vcs_f:
- ver = versions_from_vcs_f(tag_prefix, root, verbose)
- if ver:
- if verbose:
- print("got version from VCS %s" % ver)
- return ver
-
- ver = versions_from_parentdir(parentdir_prefix, root, verbose)
- if ver:
- if verbose:
- print("got version from parentdir %s" % ver)
- return ver
-
- if verbose:
- print("got version from default %s" % default)
- return default
-
-
-def get_version(verbose=False):
- return get_versions(verbose=verbose)["version"]
-
-
-class cmd_version(Command):
- description = "report generated version string"
- user_options = []
- boolean_options = []
-
- def initialize_options(self):
- pass
-
- def finalize_options(self):
- pass
-
- def run(self):
- ver = get_version(verbose=True)
- print("Version is currently: %s" % ver)
-
-
-class cmd_build(_build):
- def run(self):
- versions = get_versions(verbose=True)
- _build.run(self)
- # now locate _version.py in the new build/ directory and replace it
- # with an updated value
- if versionfile_build:
- target_versionfile = os.path.join(self.build_lib,
- versionfile_build)
- print("UPDATING %s" % target_versionfile)
- os.unlink(target_versionfile)
- with open(target_versionfile, "w") as f:
- f.write(SHORT_VERSION_PY % versions)
-
-if 'cx_Freeze' in sys.modules: # cx_freeze enabled?
- from cx_Freeze.dist import build_exe as _build_exe
-
- class cmd_build_exe(_build_exe):
- def run(self):
- versions = get_versions(verbose=True)
- target_versionfile = versionfile_source
- print("UPDATING %s" % target_versionfile)
- os.unlink(target_versionfile)
- with open(target_versionfile, "w") as f:
- f.write(SHORT_VERSION_PY % versions)
-
- _build_exe.run(self)
- os.unlink(target_versionfile)
- with open(versionfile_source, "w") as f:
- assert VCS is not None, "please set versioneer.VCS"
- LONG = LONG_VERSION_PY[VCS]
- f.write(LONG % {"DOLLAR": "$",
- "TAG_PREFIX": tag_prefix,
- "PARENTDIR_PREFIX": parentdir_prefix,
- "VERSIONFILE_SOURCE": versionfile_source,
- })
-
-
-class cmd_sdist(_sdist):
- def run(self):
- versions = get_versions(verbose=True)
- self._versioneer_generated_versions = versions
- # unless we update this, the command will keep using the old version
- self.distribution.metadata.version = versions["version"]
- return _sdist.run(self)
-
- def make_release_tree(self, base_dir, files):
- _sdist.make_release_tree(self, base_dir, files)
- # now locate _version.py in the new base_dir directory (remembering
- # that it may be a hardlink) and replace it with an updated value
- target_versionfile = os.path.join(base_dir, versionfile_source)
- print("UPDATING %s" % target_versionfile)
- os.unlink(target_versionfile)
- with open(target_versionfile, "w") as f:
- f.write(SHORT_VERSION_PY % self._versioneer_generated_versions)
-
-INIT_PY_SNIPPET = """
-from ._version import get_versions
-__version__ = get_versions()['version']
-del get_versions
-"""
-
-
-class cmd_update_files(Command):
- description = ("install/upgrade Versioneer files:"
- "__init__.py SRC/_version.py")
- user_options = []
- boolean_options = []
-
- def initialize_options(self):
- pass
-
- def finalize_options(self):
- pass
-
- def run(self):
- print(" creating %s" % versionfile_source)
- with open(versionfile_source, "w") as f:
- assert VCS is not None, "please set versioneer.VCS"
- LONG = LONG_VERSION_PY[VCS]
- f.write(LONG % {"DOLLAR": "$",
- "TAG_PREFIX": tag_prefix,
- "PARENTDIR_PREFIX": parentdir_prefix,
- "VERSIONFILE_SOURCE": versionfile_source,
- })
-
- ipy = os.path.join(os.path.dirname(versionfile_source), "__init__.py")
- if os.path.exists(ipy):
- try:
- with open(ipy, "r") as f:
- old = f.read()
- except EnvironmentError:
- old = ""
- if INIT_PY_SNIPPET not in old:
- print(" appending to %s" % ipy)
- with open(ipy, "a") as f:
- f.write(INIT_PY_SNIPPET)
- else:
- print(" %s unmodified" % ipy)
- else:
- print(" %s doesn't exist, ok" % ipy)
- ipy = None
-
- # Make sure both the top-level "versioneer.py" and versionfile_source
- # (PKG/_version.py, used by runtime code) are in MANIFEST.in, so
- # they'll be copied into source distributions. Pip won't be able to
- # install the package without this.
- manifest_in = os.path.join(get_root(), "MANIFEST.in")
- simple_includes = set()
- try:
- with open(manifest_in, "r") as f:
- for line in f:
- if line.startswith("include "):
- for include in line.split()[1:]:
- simple_includes.add(include)
- except EnvironmentError:
- pass
- # That doesn't cover everything MANIFEST.in can do
- # (http://docs.python.org/2/distutils/sourcedist.html#commands), so
- # it might give some false negatives. Appending redundant 'include'
- # lines is safe, though.
- if "versioneer.py" not in simple_includes:
- print(" appending 'versioneer.py' to MANIFEST.in")
- with open(manifest_in, "a") as f:
- f.write("include versioneer.py\n")
- else:
- print(" 'versioneer.py' already in MANIFEST.in")
- if versionfile_source not in simple_includes:
- print(" appending versionfile_source ('%s') to MANIFEST.in" %
- versionfile_source)
- with open(manifest_in, "a") as f:
- f.write("include %s\n" % versionfile_source)
- else:
- print(" versionfile_source already in MANIFEST.in")
-
- # Make VCS-specific changes. For git, this means creating/changing
- # .gitattributes to mark _version.py for export-time keyword
- # substitution.
- do_vcs_install(manifest_in, versionfile_source, ipy)
-
-
-def get_cmdclass():
- cmds = {'version': cmd_version,
- 'versioneer': cmd_update_files,
- 'build': cmd_build,
- 'sdist': cmd_sdist,
- }
- if 'cx_Freeze' in sys.modules: # cx_freeze enabled?
- cmds['build_exe'] = cmd_build_exe
- del cmds['build']
-
- return cmds