Closed hdoupe closed 1 week ago
I noticed an error when running a reform like this one:
adjustment = { "behavior": {}, "policy": { "II_brk7_checkbox": [{"value": True}], "II_brk7": [{"value": 445400, "MARS": "single", "year": 2020}], "II_brk6": [{"value": 316700, "MARS": "single", "year": 2020}], }, }
This causes a py.test failure (reproducible here: https://github.com/hdoupe/Tax-Brain/tree/cs-error-repro):
✗ py.test cs-config/cs_config/tests/test_functions.py::TestFunctions1::test_validate_inputs -v ==================================== test session starts ===================================== platform linux -- Python 3.8.6, pytest-6.1.2, py-1.9.0, pluggy-0.13.1 -- /home/hankdoupe/miniconda3/envs/taxbrain-dev/bin/python cachedir: .pytest_cache rootdir: /home/hankdoupe/Tax-Brain/cs-config collected 1 item cs-config/cs_config/tests/test_functions.py::TestFunctions1::test_validate_inputs FAILED [100%] ========================================== FAILURES ========================================== ____________________________ TestFunctions1.test_validate_inputs _____________________________ self = <cs_config.tests.test_functions.TestFunctions1 object at 0x7f84257a5370> def test_validate_inputs(self): self.test_all_data_specified() inputs = self.get_inputs({}) check_get_inputs(inputs) init_metaparams = inputs["meta_parameters"] init_modparams = inputs["model_parameters"] class MetaParams(Parameters): array_first = True defaults = init_metaparams mp_spec = MetaParams().specification(serializable=True) ew_template = { major_sect: {"errors": {}, "warnings": {}} for major_sect in init_modparams } ew_schema = ErrorsWarnings() valid_res = self.validate_inputs( mp_spec, self.ok_adjustment, copy.deepcopy(ew_template) ) check_validate_inputs(valid_res) for major_sect, ew_dict in valid_res["errors_warnings"].items(): ew_schema.load(ew_dict) if len(ew_dict.get("errors")) > 0: raise CSKitError( f"Expected section {major_sect} to be valid but it has errors:\n" f"{ew_dict}" ) if valid_res.get("custom_adjustment"): try: json.dumps(valid_res["custom_adjustment"]) except TypeError as e: raise SerializationError( f"Parameters must be JSON serializable: \n\n\t{str(e)}\n" ) > invalid_res = self.validate_inputs( mp_spec, self.bad_adjustment, copy.deepcopy(ew_template) ) ../miniconda3/envs/taxbrain-dev/lib/python3.8/site-packages/cs_kit/validate.py:194: _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ cs-config/cs_config/functions.py:73: in validate_inputs policy_params.adjust(pol_params, raise_errors=False, ignore_warnings=True) ../miniconda3/envs/taxbrain-dev/lib/python3.8/site-packages/taxcalc/parameters.py:135: in adjust raise ve ../miniconda3/envs/taxbrain-dev/lib/python3.8/site-packages/taxcalc/parameters.py:132: in adjust return self.adjust_with_indexing(params_or_path, **kwargs) ../miniconda3/envs/taxbrain-dev/lib/python3.8/site-packages/taxcalc/parameters.py:421: in adjust_with_indexing self.extend(params=[base_param], label="year") ../miniconda3/envs/taxbrain-dev/lib/python3.8/site-packages/paramtools/parameters.py:871: in extend self._adjust( _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ self = <taxcalc.policy.Policy object at 0x7f83b69e4b80> params_or_path = defaultdict(<class 'list'>, {'II_brk7': [OrderedDict([('year', 2013), ('MARS', 'single'), ('value', 9e+99), ('_auto', ...lue', 9e+99), ('_auto', True)]), OrderedDict([('year', 2030), ('MARS', 'widow'), ('value', 9e+99), ('_auto', True)])]}) ignore_warnings = False, raise_errors = True, extend_adj = False, is_deserialized = True clobber = True def _adjust( self, params_or_path, ignore_warnings=False, raise_errors=True, extend_adj=True, is_deserialized=False, clobber=True, ): """ Internal method for performing adjustments. """ # Validate user adjustments. if is_deserialized: parsed_params = {} try: parsed_params = self._validator_schema.load( params_or_path, ignore_warnings, is_deserialized=True ) except MarshmallowValidationError as ve: self._parse_validation_messages(ve.messages, params_or_path) else: params = self.read_params(params_or_path) parsed_params = {} try: parsed_params = self._validator_schema.load( params, ignore_warnings ) except MarshmallowValidationError as ve: self._parse_validation_messages(ve.messages, params) if not self._errors: if self.label_to_extend is not None and extend_adj: extend_grid = self._stateless_label_grid[self.label_to_extend] to_delete = defaultdict(list) backup = {} for param, vos in parsed_params.items(): for vo in utils.grid_sort( vos, self.label_to_extend, extend_grid ): if self.label_to_extend in vo: if clobber: queryset = self.sel[param] else: queryset = self.sel[param]["_auto"] == True queryset &= queryset.gt( strict=False, **{ self.label_to_extend: vo[ self.label_to_extend ] }, ) other_labels = utils.filter_labels( vo, drop=[self.label_to_extend, "value", "_auto"], ) if other_labels: queryset &= intersection( queryset.eq(strict=False, **{label: value}) for label, value in other_labels.items() ) to_delete[param] += list(queryset) # make copy of value objects since they # are about to be modified backup[param] = copy.deepcopy(self._data[param]["value"]) try: array_first = self.array_first self.array_first = False # delete params that will be overwritten out by extend. self.delete( to_delete, extend_adj=False, raise_errors=True, ignore_warnings=ignore_warnings, ) # set user adjustments. self._adjust( parsed_params, extend_adj=False, raise_errors=True, ignore_warnings=ignore_warnings, ) self.extend( params=parsed_params.keys(), ignore_warnings=ignore_warnings, raise_errors=True, ) except ValidationError: for param in backup: self._data[param]["value"] = backup[param] finally: self.array_first = array_first else: for param, value in parsed_params.items(): self._update_param(param, value) self._validator_schema.context["spec"] = self has_errors = bool(self._errors.get("messages")) has_warnings = bool(self._warnings.get("messages")) # throw error if raise_errors is True or ignore_warnings is False if (raise_errors and has_errors) or ( not ignore_warnings and has_warnings ): > raise self.validation_error E paramtools.exceptions.ValidationError: { E "errors": { E "II_brk7": [ E "II_brk7[MARS=single, year=2020] 445400.0 < min 518158.62 II_brk6[MARS=single, year=2020]" E ] E } E } ../miniconda3/envs/taxbrain-dev/lib/python3.8/site-packages/paramtools/parameters.py:373: ValidationError ====================================== warnings summary ====================================== cs_config/tests/test_functions.py::TestFunctions1::test_validate_inputs /home/hankdoupe/miniconda3/envs/taxbrain-dev/lib/python3.8/site-packages/paramtools/select.py:20: UserWarning: The select module is deprecated. Use Values instead. warnings.warn("The select module is deprecated. Use Values instead.") -- Docs: https://docs.pytest.org/en/stable/warnings.html ================================== short test summary info =================================== FAILED cs-config/cs_config/tests/test_functions.py::TestFunctions1::test_validate_inputs - ... ================================ 1 failed, 1 warning in 5.39s ================================
I think this is something I need to check in Tax-Calculator. I'll comment back in a few hours with more information.
This will be resolved once the new version of Tax-Calculator is released.
I noticed an error when running a reform like this one:
This causes a py.test failure (reproducible here: https://github.com/hdoupe/Tax-Brain/tree/cs-error-repro):