diff --git a/openfisca_core/commons/misc.py b/openfisca_core/commons/misc.py index 0966fa1dc..ee985071b 100644 --- a/openfisca_core/commons/misc.py +++ b/openfisca_core/commons/misc.py @@ -1,6 +1,7 @@ -from openfisca_core.types import Array from typing import TypeVar +from openfisca_core.types import Array + T = TypeVar("T") diff --git a/openfisca_core/commons/rates.py b/openfisca_core/commons/rates.py index 355f73f38..7ede496f8 100644 --- a/openfisca_core/commons/rates.py +++ b/openfisca_core/commons/rates.py @@ -1,4 +1,3 @@ -from openfisca_core.types import Array, ArrayLike from typing import Optional from openfisca_core.types import Array, ArrayLike diff --git a/openfisca_core/entities/_core_entity.py b/openfisca_core/entities/_core_entity.py index a578e656b..89fbab26a 100644 --- a/openfisca_core/entities/_core_entity.py +++ b/openfisca_core/entities/_core_entity.py @@ -1,9 +1,10 @@ from __future__ import annotations from abc import abstractmethod -from openfisca_core.types import TaxBenefitSystem, Variable from typing import Any +from openfisca_core.types import TaxBenefitSystem, Variable + import os from .role import Role diff --git a/openfisca_core/errors/__init__.py b/openfisca_core/errors/__init__.py index e9609b0e0..bc981a98b 100644 --- a/openfisca_core/errors/__init__.py +++ b/openfisca_core/errors/__init__.py @@ -31,17 +31,16 @@ from .situation_parsing_error import SituationParsingError from .spiral_error import SpiralError from .variable_name_config_error import VariableNameConflictError +from .variable_name_config_error import ( + VariableNameConflictError as VariableNameConflict, +) from .variable_not_found_error import VariableNotFoundError # noqa: F401 +from .variable_not_found_error import VariableNotFoundError as VariableNotFound from .parameter_not_found_error import ( # noqa: F401, isort: skip ParameterNotFoundError as ParameterNotFound, ) -from .variable_name_config_error import ( - VariableNameConflictError as VariableNameConflict, -) -from .variable_not_found_error import VariableNotFoundError -from .variable_not_found_error import VariableNotFoundError as VariableNotFound __all__ = [ "CycleError", diff --git a/openfisca_core/errors/variable_not_found_error.py b/openfisca_core/errors/variable_not_found_error.py index b61453831..12601158b 100644 --- a/openfisca_core/errors/variable_not_found_error.py +++ b/openfisca_core/errors/variable_not_found_error.py @@ -16,21 +16,15 @@ def __init__(self, variable_name: str, tax_benefit_system): country_package_version = country_package_metadata["version"] if country_package_version: country_package_id = f"{country_package_name}@{country_package_version}" - country_package_name, country_package_version - ) else: country_package_id = country_package_name message = os.linesep.join( [ f"You tried to calculate or to set a value for variable '{variable_name}', but it was not found in the loaded tax and benefit system ({country_package_id}).", - variable_name, country_package_id - ), f"Are you sure you spelled '{variable_name}' correctly?", "If this code used to work and suddenly does not, this is most probably linked to an update of the tax and benefit system.", "Look at its changelog to learn about renames and removals and update your code. If it is an official package,", f"it is probably available on .", - country_package_name - ), ] ) self.message = message diff --git a/openfisca_core/parameters/__init__.py b/openfisca_core/parameters/__init__.py index 299d69399..f64f577fd 100644 --- a/openfisca_core/parameters/__init__.py +++ b/openfisca_core/parameters/__init__.py @@ -41,10 +41,10 @@ from .parameter_scale_bracket import ParameterScaleBracket from .parameter_scale_bracket import ParameterScaleBracket as Bracket from .values_history import ValuesHistory -from .vectorial_asof_date_parameter_node_at_instant import VectorialAsofDateParameterNodeAtInstant -from .vectorial_parameter_node_at_instant import VectorialParameterNodeAtInstant - VectorialParameterNodeAtInstant, +from .vectorial_asof_date_parameter_node_at_instant import ( + VectorialAsofDateParameterNodeAtInstant, ) +from .vectorial_parameter_node_at_instant import VectorialParameterNodeAtInstant __all__ = [ "ParameterNotFound", diff --git a/openfisca_core/parameters/parameter_at_instant.py b/openfisca_core/parameters/parameter_at_instant.py index e4548bb05..e391747e7 100644 --- a/openfisca_core/parameters/parameter_at_instant.py +++ b/openfisca_core/parameters/parameter_at_instant.py @@ -53,8 +53,6 @@ def validate(self, data): if not isinstance(value, config.ALLOWED_PARAM_TYPES): raise ParameterParsingError( f"Value in {self.name} has type {type(value)}, which is not one of the allowed types ({config.ALLOWED_PARAM_TYPES}): {value}", - self.name, type(value), config.ALLOWED_PARAM_TYPES, value - ), self.file_path, ) diff --git a/openfisca_core/parameters/parameter_node_at_instant.py b/openfisca_core/parameters/parameter_node_at_instant.py index 72c90542a..69465ebbc 100644 --- a/openfisca_core/parameters/parameter_node_at_instant.py +++ b/openfisca_core/parameters/parameter_node_at_instant.py @@ -44,7 +44,11 @@ def __getitem__(self, key): if isinstance(key, numpy.ndarray): # If fancy indexing is used wit a datetime64, cast to a vectorial node supporting datetime64 if numpy.issubdtype(key.dtype, numpy.datetime64): - return parameters.VectorialAsofDateParameterNodeAtInstant.build_from_node(self)[key] + return ( + parameters.VectorialAsofDateParameterNodeAtInstant.build_from_node( + self + )[key] + ) return parameters.VectorialParameterNodeAtInstant.build_from_node(self)[key] return self._children[key] diff --git a/openfisca_core/parameters/vectorial_asof_date_parameter_node_at_instant.py b/openfisca_core/parameters/vectorial_asof_date_parameter_node_at_instant.py index 8b7dd0fdd..e00ce1173 100644 --- a/openfisca_core/parameters/vectorial_asof_date_parameter_node_at_instant.py +++ b/openfisca_core/parameters/vectorial_asof_date_parameter_node_at_instant.py @@ -1,7 +1,9 @@ import numpy from openfisca_core.parameters.parameter_node_at_instant import ParameterNodeAtInstant -from openfisca_core.parameters.vectorial_parameter_node_at_instant import VectorialParameterNodeAtInstant +from openfisca_core.parameters.vectorial_parameter_node_at_instant import ( + VectorialParameterNodeAtInstant, +) class VectorialAsofDateParameterNodeAtInstant(VectorialParameterNodeAtInstant): @@ -15,52 +17,58 @@ def build_from_node(node): VectorialParameterNodeAtInstant.check_node_vectorisable(node) subnodes_name = node._children.keys() # Recursively vectorize the children of the node - vectorial_subnodes = tuple([ - VectorialAsofDateParameterNodeAtInstant.build_from_node(node[subnode_name]).vector - if isinstance(node[subnode_name], ParameterNodeAtInstant) - else node[subnode_name] - for subnode_name in subnodes_name - ]) + vectorial_subnodes = tuple( + [ + VectorialAsofDateParameterNodeAtInstant.build_from_node( + node[subnode_name] + ).vector + if isinstance(node[subnode_name], ParameterNodeAtInstant) + else node[subnode_name] + for subnode_name in subnodes_name + ] + ) # A vectorial node is a wrapper around a numpy recarray # We first build the recarray recarray = numpy.array( [vectorial_subnodes], dtype=[ - (subnode_name, subnode.dtype if isinstance(subnode, numpy.recarray) else 'float') + ( + subnode_name, + subnode.dtype if isinstance(subnode, numpy.recarray) else "float", + ) for (subnode_name, subnode) in zip(subnodes_name, vectorial_subnodes) - ] + ], + ) + return VectorialAsofDateParameterNodeAtInstant( + node._name, recarray.view(numpy.recarray), node._instant_str ) - return VectorialAsofDateParameterNodeAtInstant(node._name, recarray.view(numpy.recarray), node._instant_str) def __getitem__(self, key): # If the key is a string, just get the subnode if isinstance(key, str): - key = numpy.array([key], dtype='datetime64[D]') + key = numpy.array([key], dtype="datetime64[D]") return self.__getattr__(key) # If the key is a vector, e.g. ['1990-11-25', '1983-04-17', '1969-09-09'] elif isinstance(key, numpy.ndarray): assert numpy.issubdtype(key.dtype, numpy.datetime64) - names = list(self.dtype.names) # Get all the names of the subnodes, e.g. ['before_X', 'after_X', 'after_Y'] + names = list( + self.dtype.names + ) # Get all the names of the subnodes, e.g. ['before_X', 'after_X', 'after_Y'] values = numpy.asarray([value for value in self.vector[0]]) + names = [name for name in names if not name.startswith("before")] names = [ - name + numpy.datetime64("-".join(name[len("after_") :].split("_"))) for name in names - if not name.startswith("before") ] - names = [ - numpy.datetime64( - "-".join(name[len("after_"):].split("_")) - ) - for name in names - ] - conditions = sum([ - name <= key - for name in names - ]) + conditions = sum([name <= key for name in names]) result = values[conditions] # If the result is not a leaf, wrap the result in a vectorial node. - if numpy.issubdtype(result.dtype, numpy.record) or numpy.issubdtype(result.dtype, numpy.void): - return VectorialAsofDateParameterNodeAtInstant(self._name, result.view(numpy.recarray), self._instant_str) + if numpy.issubdtype(result.dtype, numpy.record) or numpy.issubdtype( + result.dtype, numpy.void + ): + return VectorialAsofDateParameterNodeAtInstant( + self._name, result.view(numpy.recarray), self._instant_str + ) return result diff --git a/openfisca_core/reforms/reform.py b/openfisca_core/reforms/reform.py index 334201ccc..e5671f5bc 100644 --- a/openfisca_core/reforms/reform.py +++ b/openfisca_core/reforms/reform.py @@ -49,9 +49,7 @@ def __init__(self, baseline): self.decomposition_file_path = baseline.decomposition_file_path self.key = self.__class__.__name__ if not hasattr(self, "apply"): - raise Exception( raise Exception(f"Reform {self.key} must define an `apply` function") - ) self.apply() def __getattr__(self, attribute): diff --git a/openfisca_core/scripts/__init__.py b/openfisca_core/scripts/__init__.py index d288b5712..41d36327b 100644 --- a/openfisca_core/scripts/__init__.py +++ b/openfisca_core/scripts/__init__.py @@ -47,8 +47,6 @@ def build_tax_benefit_system(country_package_name, extensions, reforms): if not hasattr(country_package, "CountryTaxBenefitSystem"): raise ImportError( f"`{country_package_name}` does not seem to be a valid Openfisca country package." - country_package_name - ) ) country_package = importlib.import_module(country_package_name) diff --git a/openfisca_core/simulations/helpers.py b/openfisca_core/simulations/helpers.py index cd249b880..a96b5bd74 100644 --- a/openfisca_core/simulations/helpers.py +++ b/openfisca_core/simulations/helpers.py @@ -25,8 +25,7 @@ def check_type(input, input_type, path=None): if not isinstance(input, input_type): raise errors.SituationParsingError( - path, - path, f"Invalid type: must be of type '{json_type_map[input_type]}'." + path, path, f"Invalid type: must be of type '{json_type_map[input_type]}'." ) diff --git a/openfisca_core/simulations/simulation.py b/openfisca_core/simulations/simulation.py index 46573c168..0e479be5e 100644 --- a/openfisca_core/simulations/simulation.py +++ b/openfisca_core/simulations/simulation.py @@ -1,9 +1,8 @@ from __future__ import annotations -from typing import NamedTuple +from typing import Dict, Mapping, NamedTuple, Optional, Set from openfisca_core.types import Population, TaxBenefitSystem, Variable -from typing import Dict, Mapping, NamedTuple, Optional, Set import tempfile import warnings @@ -178,8 +177,8 @@ def calculate_add(self, variable_name: str, period): # Rule out incompatible periods. if ( - variable.definition_period in (DateUnit.MONTH, DateUnit.DAY) - and period.unit == DateUnit.WEEK + variable.definition_period in (periods.DateUnit.MONTH, periods.DateUnit.DAY) + and period.unit == periods.DateUnit.WEEK ): raise ValueError( "Unable to compute variable '{0}' for period {1}, as {1} and {2} are incompatible periods. You can however change the requested period to 'period.this_year'.".format( @@ -188,8 +187,9 @@ def calculate_add(self, variable_name: str, period): ) if ( - variable.definition_period in (DateUnit.WEEK, DateUnit.WEEKDAY) - and period.unit == DateUnit.MONTH + variable.definition_period + in (periods.DateUnit.WEEK, periods.DateUnit.WEEKDAY) + and period.unit == periods.DateUnit.MONTH ): raise ValueError( "Unable to compute variable '{0}' for period {1}, as {1} and {2} are incompatible periods. You can however change the requested period to 'period.this_year' or 'period.first_week'.".format( @@ -248,9 +248,9 @@ def calculate_divide(self, variable_name: str, period): ) if variable.definition_period not in ( - periods.DateUnit.isoformat + periods.DateUnit.isocalendar + periods.DateUnit.YEAR, + periods.DateUnit.WEEK, ): - if variable.definition_period not in (DateUnit.YEAR, DateUnit.WEEK): raise ValueError( f"Unable to DIVIDE constant variable '{variable.name}' over " f"the period {period}: eternal variables can't be divided " @@ -421,15 +421,13 @@ def _check_for_cycle(self, variable: str, period): if frame["name"] == variable ] if period in previous_periods: - raise CycleError( + raise errors.CycleError( f"Circular definition detected on formula {variable}@{period}" ) spiral = len(previous_periods) >= self.max_spiral_loops if spiral: self.invalidate_spiral_variables(variable) message = f"Quasicircular definition detected on formula {variable}@{period} involving {self.tracer.stack}" - variable, period, self.tracer.stack - ) raise errors.SpiralError(message, variable) def invalidate_cache_entry(self, variable: str, period): diff --git a/openfisca_core/simulations/simulation_builder.py b/openfisca_core/simulations/simulation_builder.py index 2e6fdde06..f9a8fb8cd 100644 --- a/openfisca_core/simulations/simulation_builder.py +++ b/openfisca_core/simulations/simulation_builder.py @@ -10,6 +10,9 @@ import numpy from openfisca_core import entities, errors, periods, populations, variables +from openfisca_core.populations import Population +from openfisca_core.simulations import Simulation, helpers +from openfisca_core.variables import Variable from . import helpers from ._build_default_simulation import _BuildDefaultSimulation @@ -36,9 +39,6 @@ TaxBenefitSystem, Variables, ) -from openfisca_core.populations import Population -from openfisca_core.simulations import Simulation, helpers -from openfisca_core.variables import Variable class SimulationBuilder: @@ -142,9 +142,6 @@ def build_from_dict( return self.build_from_entities(tax_benefit_system, params) if not are_entities_specified(params := input_dict, variables): - if any( - key in tax_benefit_system.entities_plural() for key in input_dict.keys() - ): return self.build_from_entities(tax_benefit_system, input_dict) else: return self.build_from_variables(tax_benefit_system, params) diff --git a/openfisca_core/taxbenefitsystems/tax_benefit_system.py b/openfisca_core/taxbenefitsystems/tax_benefit_system.py index 44b7f828f..2471e2822 100644 --- a/openfisca_core/taxbenefitsystems/tax_benefit_system.py +++ b/openfisca_core/taxbenefitsystems/tax_benefit_system.py @@ -156,8 +156,6 @@ def load_variable(self, variable_class, update=False): if baseline_variable and not update: raise VariableNameConflictError( f'Variable "{name}" is already defined. Use `update_variable` to replace it.' - name - ) ) variable = variable_class(baseline_variable=baseline_variable) @@ -272,7 +270,7 @@ def add_variables_from_file(self, file_path): self.add_variable(pot_variable) except Exception: log.error( - log.error(f'Unable to load OpenFisca variables from file "{file_path}"') + log.error(f'Unable to load OpenFisca variables from file "{file_path}"') ) raise diff --git a/openfisca_core/types/_data.py b/openfisca_core/types/_data.py index 31290a07b..51e26bc59 100644 --- a/openfisca_core/types/_data.py +++ b/openfisca_core/types/_data.py @@ -1,11 +1,11 @@ from collections.abc import Sequence from nptyping import NDArray as Array from nptyping import types -from typing import TypeVar, Union + # from typing import Sequence, TypeVar, Union # from nptyping import types, NDArray as Array from numpy.typing import NDArray as Array # noqa: F401 -from typing import Sequence, TypeVar +from typing import Sequence, TypeVar, Union # import numpy diff --git a/openfisca_core/variables/variable.py b/openfisca_core/variables/variable.py index 4323665fa..fd9b03ac3 100644 --- a/openfisca_core/variables/variable.py +++ b/openfisca_core/variables/variable.py @@ -444,11 +444,9 @@ def check_set_value(self, value): if self.value_type == datetime.date: error_message = f"Can't deal with date: '{value}'." else: - error_message = ( error_message = f"Can't deal with value: expected type {self.json_type}, received '{value}'." raise ValueError(error_message) except OverflowError: - error_message = ( error_message = f"Can't deal with value: '{value}', it's too large for type '{self.json_type}'." raise ValueError(error_message) diff --git a/openfisca_web_api/app.py b/openfisca_web_api/app.py index 4ee343461..2141e54ec 100644 --- a/openfisca_web_api/app.py +++ b/openfisca_web_api/app.py @@ -24,26 +24,22 @@ def init_tracker(url, idsite, tracker_token): tracker = piwik.PiwikTracker(url, idsite, tracker_token) - message = ( - [ + message = [ "You chose to activate the `tracker` module. ", "Tracking data will be sent to: " + url, "For more information, see .", - ] - ) + ] log.info(os.linesep.join(message)) return tracker except ImportError: - message = ( - [ + message = [ traceback.format_exc(), "You chose to activate the `tracker` module, but it is not installed.", "For more information, see .", - ] - ) + ] log.warn(os.linesep.join(message)) diff --git a/openfisca_web_api/errors.py b/openfisca_web_api/errors.py index 6b5c3280c..9f54d8095 100644 --- a/openfisca_web_api/errors.py +++ b/openfisca_web_api/errors.py @@ -6,6 +6,4 @@ def handle_import_error(error): raise ImportError( f"OpenFisca is missing some dependencies to run the Web API: '{error}'. To install them, run `pip install openfisca_core[web-api]`." - error - ) ) diff --git a/openfisca_web_api/loader/spec.py b/openfisca_web_api/loader/spec.py index e7e00de23..cb78aa3c4 100644 --- a/openfisca_web_api/loader/spec.py +++ b/openfisca_web_api/loader/spec.py @@ -91,8 +91,6 @@ def build_openAPI_specification(api_data): ) else: message = f"No simulation example has been defined for this tax and benefit system. If you are the maintainer of {country_package_name}, you can define an example by following this documentation: https://openfisca.org/doc/openfisca-web-api/config-openapi.html" - country_package_name - ) dpath.util.new(spec, "components/schemas/SituationInput/example", message) dpath.util.new(spec, "components/schemas/SituationOutput/example", message) dpath.util.new(spec, "components/schemas/Trace/example", message) diff --git a/openfisca_web_api/loader/variables.py b/openfisca_web_api/loader/variables.py index f2eddef07..e1068f41c 100644 --- a/openfisca_web_api/loader/variables.py +++ b/openfisca_web_api/loader/variables.py @@ -56,13 +56,9 @@ def build_formula( return api_formula -def build_formulas( def build_formulas(formulas, country_package_metadata, source_file_path): -): return { - start_date: build_formula( start_date: build_formula(formula, country_package_metadata, source_file_path) - ) for start_date, formula in formulas.items() } diff --git a/tests/core/parameters_date_indexing/test_date_indexing.py b/tests/core/parameters_date_indexing/test_date_indexing.py index 1b19c72ba..05bb77082 100644 --- a/tests/core/parameters_date_indexing/test_date_indexing.py +++ b/tests/core/parameters_date_indexing/test_date_indexing.py @@ -1,9 +1,10 @@ -import numpy import os +import numpy -from openfisca_core.tools import assert_near from openfisca_core.parameters import ParameterNode +from openfisca_core.tools import assert_near + from openfisca_core.model_api import * # noqa LOCAL_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -16,14 +17,21 @@ def get_message(error): def test_on_leaf(): - parameter_at_instant = parameters.full_rate_required_duration('1995-01-01') - birthdate = numpy.array(['1930-01-01', '1935-01-01', '1940-01-01', '1945-01-01'], dtype='datetime64[D]') - assert_near(parameter_at_instant.contribution_quarters_required_by_birthdate[birthdate], [150, 152, 157, 160]) + parameter_at_instant = parameters.full_rate_required_duration("1995-01-01") + birthdate = numpy.array( + ["1930-01-01", "1935-01-01", "1940-01-01", "1945-01-01"], dtype="datetime64[D]" + ) + assert_near( + parameter_at_instant.contribution_quarters_required_by_birthdate[birthdate], + [150, 152, 157, 160], + ) def test_on_node(): - birthdate = numpy.array(['1950-01-01', '1953-01-01', '1956-01-01', '1959-01-01'], dtype='datetime64[D]') - parameter_at_instant = parameters.full_rate_age('2012-03-01') + birthdate = numpy.array( + ["1950-01-01", "1953-01-01", "1956-01-01", "1959-01-01"], dtype="datetime64[D]" + ) + parameter_at_instant = parameters.full_rate_age("2012-03-01") node = parameter_at_instant.full_rate_age_by_birthdate[birthdate] assert_near(node.year, [65, 66, 67, 67]) assert_near(node.month, [0, 2, 0, 0]) diff --git a/tests/core/variables/test_variables.py b/tests/core/variables/test_variables.py index 3ff7f0866..a31edd547 100644 --- a/tests/core/variables/test_variables.py +++ b/tests/core/variables/test_variables.py @@ -47,8 +47,6 @@ def check_error_at_add_variable(tax_benefit_system, variable, error_message_pref if not message or not message.startswith(error_message_prefix): raise AssertionError( f'Incorrect error message. Was expecting something starting by "{error_message_prefix}". Got: "{message}"' - error_message_prefix, message - ) )