OpenFisca-Core-test 46.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- openfisca_core/__init__.py +0 -0
- openfisca_core/commons/__init__.py +18 -0
- openfisca_core/commons/dummy.py +25 -0
- openfisca_core/commons/formulas.py +121 -0
- openfisca_core/commons/misc.py +109 -0
- openfisca_core/commons/py.typed +0 -0
- openfisca_core/commons/rates.py +114 -0
- openfisca_core/commons/tests/__init__.py +0 -0
- openfisca_core/commons/tests/test_dummy.py +9 -0
- openfisca_core/commons/tests/test_formulas.py +75 -0
- openfisca_core/commons/tests/test_rates.py +26 -0
- openfisca_core/data_storage/__init__.py +7 -0
- openfisca_core/data_storage/in_memory_storage.py +198 -0
- openfisca_core/data_storage/on_disk_storage.py +307 -0
- openfisca_core/data_storage/types.py +14 -0
- openfisca_core/entities/__init__.py +23 -0
- openfisca_core/entities/_core_entity.py +217 -0
- openfisca_core/entities/_description.py +55 -0
- openfisca_core/entities/entity.py +60 -0
- openfisca_core/entities/group_entity.py +123 -0
- openfisca_core/entities/helpers.py +165 -0
- openfisca_core/entities/py.typed +0 -0
- openfisca_core/entities/role.py +92 -0
- openfisca_core/entities/tests/__init__.py +0 -0
- openfisca_core/entities/tests/test_entity.py +10 -0
- openfisca_core/entities/tests/test_group_entity.py +70 -0
- openfisca_core/entities/tests/test_role.py +11 -0
- openfisca_core/entities/types.py +44 -0
- openfisca_core/errors/__init__.py +64 -0
- openfisca_core/errors/cycle_error.py +2 -0
- openfisca_core/errors/empty_argument_error.py +39 -0
- openfisca_core/errors/nan_creation_error.py +2 -0
- openfisca_core/errors/parameter_not_found_error.py +16 -0
- openfisca_core/errors/parameter_parsing_error.py +18 -0
- openfisca_core/errors/period_mismatch_error.py +9 -0
- openfisca_core/errors/situation_parsing_error.py +26 -0
- openfisca_core/errors/spiral_error.py +2 -0
- openfisca_core/errors/variable_name_config_error.py +2 -0
- openfisca_core/errors/variable_not_found_error.py +29 -0
- openfisca_core/experimental/__init__.py +9 -0
- openfisca_core/experimental/_errors.py +5 -0
- openfisca_core/experimental/_memory_config.py +41 -0
- openfisca_core/formula_helpers.py +9 -0
- openfisca_core/holders/__init__.py +33 -0
- openfisca_core/holders/helpers.py +93 -0
- openfisca_core/holders/holder.py +328 -0
- openfisca_core/holders/tests/__init__.py +0 -0
- openfisca_core/holders/tests/test_helpers.py +134 -0
- openfisca_core/holders/types.py +3 -0
- openfisca_core/indexed_enums/__init__.py +18 -0
- openfisca_core/indexed_enums/_enum_type.py +79 -0
- openfisca_core/indexed_enums/_errors.py +35 -0
- openfisca_core/indexed_enums/_guards.py +209 -0
- openfisca_core/indexed_enums/_utils.py +180 -0
- openfisca_core/indexed_enums/config.py +6 -0
- openfisca_core/indexed_enums/enum.py +218 -0
- openfisca_core/indexed_enums/enum_array.py +316 -0
- openfisca_core/indexed_enums/py.typed +0 -0
- openfisca_core/indexed_enums/tests/__init__.py +0 -0
- openfisca_core/indexed_enums/tests/test_enum.py +135 -0
- openfisca_core/indexed_enums/tests/test_enum_array.py +30 -0
- openfisca_core/indexed_enums/types.py +49 -0
- openfisca_core/memory_config.py +9 -0
- openfisca_core/model_api.py +71 -0
- openfisca_core/parameters/__init__.py +71 -0
- openfisca_core/parameters/at_instant_like.py +17 -0
- openfisca_core/parameters/config.py +55 -0
- openfisca_core/parameters/helpers.py +106 -0
- openfisca_core/parameters/parameter.py +217 -0
- openfisca_core/parameters/parameter_at_instant.py +75 -0
- openfisca_core/parameters/parameter_node.py +176 -0
- openfisca_core/parameters/parameter_node_at_instant.py +57 -0
- openfisca_core/parameters/parameter_scale.py +121 -0
- openfisca_core/parameters/parameter_scale_bracket.py +7 -0
- openfisca_core/parameters/values_history.py +5 -0
- openfisca_core/parameters/vectorial_parameter_node_at_instant.py +179 -0
- openfisca_core/periods/__init__.py +77 -0
- openfisca_core/periods/_errors.py +28 -0
- openfisca_core/periods/_parsers.py +122 -0
- openfisca_core/periods/config.py +20 -0
- openfisca_core/periods/date_unit.py +110 -0
- openfisca_core/periods/helpers.py +314 -0
- openfisca_core/periods/instant_.py +226 -0
- openfisca_core/periods/period_.py +919 -0
- openfisca_core/periods/py.typed +0 -0
- openfisca_core/periods/tests/__init__.py +0 -0
- openfisca_core/periods/tests/helpers/__init__.py +0 -0
- openfisca_core/periods/tests/helpers/test_helpers.py +65 -0
- openfisca_core/periods/tests/helpers/test_instant.py +73 -0
- openfisca_core/periods/tests/helpers/test_period.py +134 -0
- openfisca_core/periods/tests/test_instant.py +32 -0
- openfisca_core/periods/tests/test_parsers.py +129 -0
- openfisca_core/periods/tests/test_period.py +283 -0
- openfisca_core/populations/__init__.py +64 -0
- openfisca_core/populations/_core_population.py +454 -0
- openfisca_core/populations/_errors.py +65 -0
- openfisca_core/populations/group_population.py +326 -0
- openfisca_core/populations/population.py +142 -0
- openfisca_core/populations/tests/__init__.py +0 -0
- openfisca_core/populations/tests/test_members_position.py +116 -0
- openfisca_core/populations/types.py +110 -0
- openfisca_core/projectors/__init__.py +39 -0
- openfisca_core/projectors/entity_to_person_projector.py +12 -0
- openfisca_core/projectors/first_person_to_entity_projector.py +13 -0
- openfisca_core/projectors/helpers.py +139 -0
- openfisca_core/projectors/projector.py +38 -0
- openfisca_core/projectors/typing.py +27 -0
- openfisca_core/projectors/unique_role_to_entity_projector.py +14 -0
- openfisca_core/rates.py +9 -0
- openfisca_core/reforms/__init__.py +24 -0
- openfisca_core/reforms/in_yaml_test_reform.py +28 -0
- openfisca_core/reforms/reform.py +86 -0
- openfisca_core/scripts/__init__.py +106 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.3.3.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-310.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.3.3.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-312-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.3.3.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/find_placeholders.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/find_placeholders.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-310.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-312.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-310.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-312.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/simulation_generator.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/simulation_generator.cpython-313.pyc +0 -0
- openfisca_core/scripts/assets/__init__.py +0 -0
- openfisca_core/scripts/assets/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/assets/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/assets/index.html +140 -0
- openfisca_core/scripts/find_placeholders.py +51 -0
- openfisca_core/scripts/measure_numpy_condition_notations.py +137 -0
- openfisca_core/scripts/measure_performances.py +291 -0
- openfisca_core/scripts/measure_performances_fancy_indexing.py +89 -0
- openfisca_core/scripts/migrations/__init__.py +0 -0
- openfisca_core/scripts/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__init__.py +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/legislation.xsd +102 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_country_template.py +30 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_extension_template.py +26 -0
- openfisca_core/scripts/migrations/v24_to_25.py +156 -0
- openfisca_core/scripts/openfisca_command.py +192 -0
- openfisca_core/scripts/remove_fuzzy.py +213 -0
- openfisca_core/scripts/run_test.py +51 -0
- openfisca_core/scripts/simulation_generator.py +90 -0
- openfisca_core/simulation_builder.py +16 -0
- openfisca_core/simulations/__init__.py +45 -0
- openfisca_core/simulations/_build_default_simulation.py +158 -0
- openfisca_core/simulations/_build_from_variables.py +230 -0
- openfisca_core/simulations/_type_guards.py +298 -0
- openfisca_core/simulations/helpers.py +111 -0
- openfisca_core/simulations/simulation.py +618 -0
- openfisca_core/simulations/simulation_builder.py +855 -0
- openfisca_core/simulations/typing.py +203 -0
- openfisca_core/taxbenefitsystems/__init__.py +26 -0
- openfisca_core/taxbenefitsystems/tax_benefit_system.py +584 -0
- openfisca_core/taxscales/__init__.py +35 -0
- openfisca_core/taxscales/abstract_rate_tax_scale.py +41 -0
- openfisca_core/taxscales/abstract_tax_scale.py +53 -0
- openfisca_core/taxscales/amount_tax_scale_like.py +55 -0
- openfisca_core/taxscales/helpers.py +44 -0
- openfisca_core/taxscales/linear_average_rate_tax_scale.py +76 -0
- openfisca_core/taxscales/marginal_amount_tax_scale.py +34 -0
- openfisca_core/taxscales/marginal_rate_tax_scale.py +286 -0
- openfisca_core/taxscales/rate_tax_scale_like.py +214 -0
- openfisca_core/taxscales/single_amount_tax_scale.py +32 -0
- openfisca_core/taxscales/tax_scale_like.py +65 -0
- openfisca_core/tools/__init__.py +94 -0
- openfisca_core/tools/parallel_plugin.py +55 -0
- openfisca_core/tools/simulation_dumper.py +137 -0
- openfisca_core/tools/test_runner.py +802 -0
- openfisca_core/tracers/__init__.py +40 -0
- openfisca_core/tracers/computation_log.py +196 -0
- openfisca_core/tracers/flat_trace.py +87 -0
- openfisca_core/tracers/full_tracer.py +172 -0
- openfisca_core/tracers/performance_log.py +133 -0
- openfisca_core/tracers/simple_tracer.py +64 -0
- openfisca_core/tracers/trace_node.py +121 -0
- openfisca_core/tracers/tracing_parameter_node_at_instant.py +81 -0
- openfisca_core/types.py +548 -0
- openfisca_core/variables/__init__.py +26 -0
- openfisca_core/variables/config.py +53 -0
- openfisca_core/variables/helpers.py +67 -0
- openfisca_core/variables/tests/__init__.py +0 -0
- openfisca_core/variables/tests/test_definition_period.py +43 -0
- openfisca_core/variables/variable.py +474 -0
- openfisca_core/warnings/__init__.py +25 -0
- openfisca_core/warnings/libyaml_warning.py +2 -0
- openfisca_core/warnings/tempfile_warning.py +2 -0
- openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/CHANGELOG.md +4209 -0
- openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/README.md +152 -0
- openfisca_core_test-46.0.0.dist-info/METADATA +194 -0
- openfisca_core_test-46.0.0.dist-info/RECORD +237 -0
- openfisca_core_test-46.0.0.dist-info/WHEEL +5 -0
- openfisca_core_test-46.0.0.dist-info/entry_points.txt +3 -0
- openfisca_core_test-46.0.0.dist-info/licenses/LICENSE +661 -0
- openfisca_core_test-46.0.0.dist-info/top_level.txt +2 -0
- openfisca_web_api/__init__.py +0 -0
- openfisca_web_api/app.py +226 -0
- openfisca_web_api/errors.py +11 -0
- openfisca_web_api/handlers.py +90 -0
- openfisca_web_api/loader/__init__.py +22 -0
- openfisca_web_api/loader/entities.py +28 -0
- openfisca_web_api/loader/parameters.py +122 -0
- openfisca_web_api/loader/spec.py +168 -0
- openfisca_web_api/loader/tax_benefit_system.py +27 -0
- openfisca_web_api/loader/variables.py +121 -0
- openfisca_web_api/openAPI.yml +434 -0
- openfisca_web_api/scripts/__init__.py +0 -0
- openfisca_web_api/scripts/serve.py +99 -0
|
@@ -0,0 +1,217 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import abc
|
|
4
|
+
import os
|
|
5
|
+
from typing import ClassVar
|
|
6
|
+
|
|
7
|
+
from . import types as t
|
|
8
|
+
from .role import Role
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
class CoreEntity:
|
|
12
|
+
"""Base class to build entities from.
|
|
13
|
+
|
|
14
|
+
Args:
|
|
15
|
+
*__args: Any arguments.
|
|
16
|
+
**__kwargs: Any keyword arguments.
|
|
17
|
+
|
|
18
|
+
Examples:
|
|
19
|
+
>>> from openfisca_core import entities
|
|
20
|
+
>>> from openfisca_core.entities import types as t
|
|
21
|
+
|
|
22
|
+
>>> class Entity(entities.CoreEntity):
|
|
23
|
+
... def __init__(self, key):
|
|
24
|
+
... self.key = t.EntityKey(key)
|
|
25
|
+
|
|
26
|
+
>>> Entity("individual")
|
|
27
|
+
Entity(individual)
|
|
28
|
+
|
|
29
|
+
"""
|
|
30
|
+
|
|
31
|
+
#: A key to identify the ``CoreEntity``.
|
|
32
|
+
key: t.EntityKey
|
|
33
|
+
|
|
34
|
+
#: The ``key`` pluralised.
|
|
35
|
+
plural: t.EntityPlural
|
|
36
|
+
|
|
37
|
+
#: A summary description.
|
|
38
|
+
label: str
|
|
39
|
+
|
|
40
|
+
#: A full description.
|
|
41
|
+
doc: str
|
|
42
|
+
|
|
43
|
+
#: Whether the ``CoreEntity`` is a person or not.
|
|
44
|
+
is_person: ClassVar[bool]
|
|
45
|
+
|
|
46
|
+
#: A ``TaxBenefitSystem`` instance.
|
|
47
|
+
_tax_benefit_system: None | t.TaxBenefitSystem = None
|
|
48
|
+
|
|
49
|
+
@abc.abstractmethod
|
|
50
|
+
def __init__(self, *__args: object, **__kwargs: object) -> None: ...
|
|
51
|
+
|
|
52
|
+
def __repr__(self) -> str:
|
|
53
|
+
return f"{self.__class__.__name__}({self.key})"
|
|
54
|
+
|
|
55
|
+
def set_tax_benefit_system(self, tax_benefit_system: t.TaxBenefitSystem) -> None:
|
|
56
|
+
"""A ``CoreEntity`` belongs to a ``TaxBenefitSystem``."""
|
|
57
|
+
self._tax_benefit_system = tax_benefit_system
|
|
58
|
+
|
|
59
|
+
def get_variable(
|
|
60
|
+
self,
|
|
61
|
+
variable_name: t.VariableName,
|
|
62
|
+
check_existence: bool = False,
|
|
63
|
+
) -> t.Variable | None:
|
|
64
|
+
"""Get ``variable_name`` from ``variables``.
|
|
65
|
+
|
|
66
|
+
Args:
|
|
67
|
+
variable_name: The ``Variable`` to be found.
|
|
68
|
+
check_existence: Was the ``Variable`` found?
|
|
69
|
+
|
|
70
|
+
Returns:
|
|
71
|
+
Variable: When the ``Variable`` exists.
|
|
72
|
+
None: When the ``Variable`` doesn't exist.
|
|
73
|
+
|
|
74
|
+
Raises:
|
|
75
|
+
ValueError: When the :attr:`_tax_benefit_system` is not set yet.
|
|
76
|
+
ValueError: When ``check_existence`` is ``True`` and
|
|
77
|
+
the ``Variable`` doesn't exist.
|
|
78
|
+
|
|
79
|
+
Examples:
|
|
80
|
+
>>> from openfisca_core import (
|
|
81
|
+
... entities,
|
|
82
|
+
... periods,
|
|
83
|
+
... taxbenefitsystems,
|
|
84
|
+
... variables,
|
|
85
|
+
... )
|
|
86
|
+
|
|
87
|
+
>>> this = entities.SingleEntity("this", "", "", "")
|
|
88
|
+
>>> that = entities.SingleEntity("that", "", "", "")
|
|
89
|
+
|
|
90
|
+
>>> this.get_variable("tax")
|
|
91
|
+
Traceback (most recent call last):
|
|
92
|
+
ValueError: You must set 'tax_benefit_system' before calling this...
|
|
93
|
+
|
|
94
|
+
>>> tax_benefit_system = taxbenefitsystems.TaxBenefitSystem([this])
|
|
95
|
+
>>> this.set_tax_benefit_system(tax_benefit_system)
|
|
96
|
+
|
|
97
|
+
>>> this.get_variable("tax")
|
|
98
|
+
|
|
99
|
+
>>> this.get_variable("tax", check_existence=True)
|
|
100
|
+
Traceback (most recent call last):
|
|
101
|
+
VariableNotFoundError: You tried to calculate or to set a value...
|
|
102
|
+
|
|
103
|
+
>>> class tax(variables.Variable):
|
|
104
|
+
... definition_period = periods.MONTH
|
|
105
|
+
... value_type = float
|
|
106
|
+
... entity = that
|
|
107
|
+
|
|
108
|
+
>>> this._tax_benefit_system.add_variable(tax)
|
|
109
|
+
<openfisca_core.entities._core_entity.tax object at ...>
|
|
110
|
+
|
|
111
|
+
>>> this.get_variable("tax")
|
|
112
|
+
<openfisca_core.entities._core_entity.tax object at ...>
|
|
113
|
+
|
|
114
|
+
"""
|
|
115
|
+
if self._tax_benefit_system is None:
|
|
116
|
+
msg = "You must set 'tax_benefit_system' before calling this method."
|
|
117
|
+
raise ValueError(
|
|
118
|
+
msg,
|
|
119
|
+
)
|
|
120
|
+
return self._tax_benefit_system.get_variable(variable_name, check_existence)
|
|
121
|
+
|
|
122
|
+
def check_variable_defined_for_entity(self, variable_name: t.VariableName) -> None:
|
|
123
|
+
"""Check if ``variable_name`` is defined for ``self``.
|
|
124
|
+
|
|
125
|
+
Args:
|
|
126
|
+
variable_name: The ``Variable`` to be found.
|
|
127
|
+
|
|
128
|
+
Raises:
|
|
129
|
+
ValueError: When the ``Variable`` exists but is defined
|
|
130
|
+
for another ``Entity``.
|
|
131
|
+
|
|
132
|
+
Examples:
|
|
133
|
+
>>> from openfisca_core import (
|
|
134
|
+
... entities,
|
|
135
|
+
... periods,
|
|
136
|
+
... taxbenefitsystems,
|
|
137
|
+
... variables,
|
|
138
|
+
... )
|
|
139
|
+
|
|
140
|
+
>>> this = entities.SingleEntity("this", "", "", "")
|
|
141
|
+
>>> that = entities.SingleEntity("that", "", "", "")
|
|
142
|
+
>>> tax_benefit_system = taxbenefitsystems.TaxBenefitSystem([that])
|
|
143
|
+
>>> this.set_tax_benefit_system(tax_benefit_system)
|
|
144
|
+
|
|
145
|
+
>>> this.check_variable_defined_for_entity("tax")
|
|
146
|
+
Traceback (most recent call last):
|
|
147
|
+
VariableNotFoundError: You tried to calculate or to set a value...
|
|
148
|
+
|
|
149
|
+
>>> class tax(variables.Variable):
|
|
150
|
+
... definition_period = periods.WEEK
|
|
151
|
+
... value_type = int
|
|
152
|
+
... entity = that
|
|
153
|
+
|
|
154
|
+
>>> this._tax_benefit_system.add_variable(tax)
|
|
155
|
+
<openfisca_core.entities._core_entity.tax object at ...>
|
|
156
|
+
|
|
157
|
+
>>> this.check_variable_defined_for_entity("tax")
|
|
158
|
+
Traceback (most recent call last):
|
|
159
|
+
ValueError: You tried to compute the variable 'tax' for the enti...
|
|
160
|
+
|
|
161
|
+
>>> tax.entity = this
|
|
162
|
+
|
|
163
|
+
>>> this._tax_benefit_system.update_variable(tax)
|
|
164
|
+
<openfisca_core.entities._core_entity.tax object at ...>
|
|
165
|
+
|
|
166
|
+
>>> this.check_variable_defined_for_entity("tax")
|
|
167
|
+
|
|
168
|
+
"""
|
|
169
|
+
entity: None | t.CoreEntity = None
|
|
170
|
+
variable: None | t.Variable = self.get_variable(
|
|
171
|
+
variable_name,
|
|
172
|
+
check_existence=True,
|
|
173
|
+
)
|
|
174
|
+
|
|
175
|
+
if variable is not None:
|
|
176
|
+
entity = variable.entity
|
|
177
|
+
|
|
178
|
+
if entity is None:
|
|
179
|
+
return
|
|
180
|
+
|
|
181
|
+
if entity.key != self.key:
|
|
182
|
+
message = (
|
|
183
|
+
f"You tried to compute the variable '{variable_name}' for",
|
|
184
|
+
f"the entity '{self.plural}'; however the variable",
|
|
185
|
+
f"'{variable_name}' is defined for '{entity.plural}'.",
|
|
186
|
+
"Learn more about entities in our documentation:",
|
|
187
|
+
"<https://openfisca.org/doc/coding-the-legislation/50_entities.html>.",
|
|
188
|
+
)
|
|
189
|
+
raise ValueError(os.linesep.join(message))
|
|
190
|
+
|
|
191
|
+
@staticmethod
|
|
192
|
+
def check_role_validity(role: object) -> None:
|
|
193
|
+
"""Check if ``role`` is an instance of ``Role``.
|
|
194
|
+
|
|
195
|
+
Args:
|
|
196
|
+
role: Any object.
|
|
197
|
+
|
|
198
|
+
Raises:
|
|
199
|
+
ValueError: When ``role`` is not a ``Role``.
|
|
200
|
+
|
|
201
|
+
Examples:
|
|
202
|
+
>>> from openfisca_core import entities
|
|
203
|
+
|
|
204
|
+
>>> role = entities.Role({"key": "key"}, object())
|
|
205
|
+
>>> entities.check_role_validity(role)
|
|
206
|
+
|
|
207
|
+
>>> entities.check_role_validity("hey!")
|
|
208
|
+
Traceback (most recent call last):
|
|
209
|
+
ValueError: hey! is not a valid role
|
|
210
|
+
|
|
211
|
+
"""
|
|
212
|
+
if role is not None and not isinstance(role, Role):
|
|
213
|
+
msg = f"{role} is not a valid role"
|
|
214
|
+
raise ValueError(msg)
|
|
215
|
+
|
|
216
|
+
|
|
217
|
+
__all__ = ["CoreEntity"]
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import dataclasses
|
|
4
|
+
import textwrap
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
@dataclasses.dataclass(frozen=True)
|
|
8
|
+
class _Description:
|
|
9
|
+
r"""A ``Role``'s description.
|
|
10
|
+
|
|
11
|
+
Examples:
|
|
12
|
+
>>> data = {
|
|
13
|
+
... "key": "parent",
|
|
14
|
+
... "label": "Parents",
|
|
15
|
+
... "plural": "parents",
|
|
16
|
+
... "doc": "\t\t\tThe one/two adults in charge of the household.",
|
|
17
|
+
... }
|
|
18
|
+
|
|
19
|
+
>>> description = _Description(**data)
|
|
20
|
+
|
|
21
|
+
>>> repr(_Description)
|
|
22
|
+
"<class 'openfisca_core.entities._description._Description'>"
|
|
23
|
+
|
|
24
|
+
>>> repr(description)
|
|
25
|
+
"_Description(key='parent', plural='parents', label='Parents', ...)"
|
|
26
|
+
|
|
27
|
+
>>> str(description)
|
|
28
|
+
"_Description(key='parent', plural='parents', label='Parents', ...)"
|
|
29
|
+
|
|
30
|
+
>>> {description}
|
|
31
|
+
{_Description(key='parent', plural='parents', label='Parents', doc=...}
|
|
32
|
+
|
|
33
|
+
>>> description.key
|
|
34
|
+
'parent'
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
#: A key to identify the ``Role``.
|
|
39
|
+
key: str
|
|
40
|
+
|
|
41
|
+
#: The ``key`` pluralised.
|
|
42
|
+
plural: None | str = None
|
|
43
|
+
|
|
44
|
+
#: A summary description.
|
|
45
|
+
label: None | str = None
|
|
46
|
+
|
|
47
|
+
#: A full description, non-indented.
|
|
48
|
+
doc: None | str = None
|
|
49
|
+
|
|
50
|
+
def __post_init__(self) -> None:
|
|
51
|
+
if self.doc is not None:
|
|
52
|
+
object.__setattr__(self, "doc", textwrap.dedent(self.doc))
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
__all__ = ["_Description"]
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import textwrap
|
|
2
|
+
from typing import ClassVar
|
|
3
|
+
|
|
4
|
+
from . import types as t
|
|
5
|
+
from ._core_entity import CoreEntity
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class Entity(CoreEntity):
|
|
9
|
+
r"""An entity (e.g. a person, a household) on which calculations can be run.
|
|
10
|
+
|
|
11
|
+
Args:
|
|
12
|
+
key: A key to identify the ``Entity``.
|
|
13
|
+
plural: The ``key`` pluralised.
|
|
14
|
+
label: A summary description.
|
|
15
|
+
doc: A full description.
|
|
16
|
+
|
|
17
|
+
Examples:
|
|
18
|
+
>>> from openfisca_core import entities
|
|
19
|
+
|
|
20
|
+
>>> entity = entities.SingleEntity(
|
|
21
|
+
... "individual",
|
|
22
|
+
... "individuals",
|
|
23
|
+
... "An individual",
|
|
24
|
+
... "\t\t\tThe minimal legal entity on which a rule might be a...",
|
|
25
|
+
... )
|
|
26
|
+
|
|
27
|
+
>>> repr(entities.SingleEntity)
|
|
28
|
+
"<class 'openfisca_core.entities.entity.Entity'>"
|
|
29
|
+
|
|
30
|
+
>>> repr(entity)
|
|
31
|
+
'Entity(individual)'
|
|
32
|
+
|
|
33
|
+
>>> str(entity)
|
|
34
|
+
'Entity(individual)'
|
|
35
|
+
|
|
36
|
+
"""
|
|
37
|
+
|
|
38
|
+
#: A key to identify the ``Entity``.
|
|
39
|
+
key: t.EntityKey
|
|
40
|
+
|
|
41
|
+
#: The ``key`` pluralised.
|
|
42
|
+
plural: t.EntityPlural
|
|
43
|
+
|
|
44
|
+
#: A summary description.
|
|
45
|
+
label: str
|
|
46
|
+
|
|
47
|
+
#: A full description.
|
|
48
|
+
doc: str
|
|
49
|
+
|
|
50
|
+
#: Whether the ``Entity`` is a person or not.
|
|
51
|
+
is_person: ClassVar[bool] = True
|
|
52
|
+
|
|
53
|
+
def __init__(self, key: str, plural: str, label: str, doc: str) -> None:
|
|
54
|
+
self.key = t.EntityKey(key)
|
|
55
|
+
self.plural = t.EntityPlural(plural)
|
|
56
|
+
self.label = label
|
|
57
|
+
self.doc = textwrap.dedent(doc)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
__all__ = ["Entity"]
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
import textwrap
|
|
4
|
+
from collections.abc import Iterable, Sequence
|
|
5
|
+
from itertools import chain
|
|
6
|
+
from typing import ClassVar
|
|
7
|
+
|
|
8
|
+
from . import types as t
|
|
9
|
+
from ._core_entity import CoreEntity
|
|
10
|
+
from .role import Role
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class GroupEntity(CoreEntity):
|
|
14
|
+
r"""Represents an entity containing several others with different roles.
|
|
15
|
+
|
|
16
|
+
A ``GroupEntity`` represents an ``Entity`` containing several other entities,
|
|
17
|
+
with different roles, and on which calculations can be run.
|
|
18
|
+
|
|
19
|
+
Args:
|
|
20
|
+
key: A key to identify the ``GroupEntity``.
|
|
21
|
+
plural: The ``key`` pluralised.
|
|
22
|
+
label: A summary description.
|
|
23
|
+
doc: A full description.
|
|
24
|
+
roles: The list of roles of the group entity.
|
|
25
|
+
containing_entities: The list of keys of group entities whose members
|
|
26
|
+
are guaranteed to be a superset of this group's entities.
|
|
27
|
+
|
|
28
|
+
Examples:
|
|
29
|
+
>>> from openfisca_core import entities
|
|
30
|
+
|
|
31
|
+
>>> family_roles = [
|
|
32
|
+
... {
|
|
33
|
+
... "key": "parent",
|
|
34
|
+
... "subroles": ["first_parent", "second_parent"],
|
|
35
|
+
... }
|
|
36
|
+
... ]
|
|
37
|
+
|
|
38
|
+
>>> family = entities.GroupEntity(
|
|
39
|
+
... "family",
|
|
40
|
+
... "families",
|
|
41
|
+
... "A family",
|
|
42
|
+
... "\t\t\tAll the people somehow related living together.",
|
|
43
|
+
... family_roles,
|
|
44
|
+
... )
|
|
45
|
+
|
|
46
|
+
>>> household_roles = [
|
|
47
|
+
... {
|
|
48
|
+
... "key": "partners",
|
|
49
|
+
... "subroles": ["first_partner", "second_partner"],
|
|
50
|
+
... }
|
|
51
|
+
... ]
|
|
52
|
+
|
|
53
|
+
>>> household = entities.GroupEntity(
|
|
54
|
+
... "household",
|
|
55
|
+
... "households",
|
|
56
|
+
... "A household",
|
|
57
|
+
... "\t\t\tAll the people who live together in the same place.",
|
|
58
|
+
... household_roles,
|
|
59
|
+
... (family.key,),
|
|
60
|
+
... )
|
|
61
|
+
|
|
62
|
+
>>> repr(entities.GroupEntity)
|
|
63
|
+
"<class 'openfisca_core.entities.group_entity.GroupEntity'>"
|
|
64
|
+
|
|
65
|
+
>>> repr(household)
|
|
66
|
+
'GroupEntity(household)'
|
|
67
|
+
|
|
68
|
+
>>> str(household)
|
|
69
|
+
'GroupEntity(household)'
|
|
70
|
+
|
|
71
|
+
"""
|
|
72
|
+
|
|
73
|
+
#: A key to identify the ``Entity``.
|
|
74
|
+
key: t.EntityKey
|
|
75
|
+
|
|
76
|
+
#: The ``key`` pluralised.
|
|
77
|
+
plural: t.EntityPlural
|
|
78
|
+
|
|
79
|
+
#: A summary description.
|
|
80
|
+
label: str
|
|
81
|
+
|
|
82
|
+
#: A full description.
|
|
83
|
+
doc: str
|
|
84
|
+
|
|
85
|
+
#: The list of roles of the ``GroupEntity``.
|
|
86
|
+
roles: Iterable[Role]
|
|
87
|
+
|
|
88
|
+
#: Whether the entity is a person or not.
|
|
89
|
+
is_person: ClassVar[bool] = False
|
|
90
|
+
|
|
91
|
+
def __init__(
|
|
92
|
+
self,
|
|
93
|
+
key: str,
|
|
94
|
+
plural: str,
|
|
95
|
+
label: str,
|
|
96
|
+
doc: str,
|
|
97
|
+
roles: Sequence[t.RoleParams],
|
|
98
|
+
containing_entities: Iterable[str] = (),
|
|
99
|
+
) -> None:
|
|
100
|
+
self.key = t.EntityKey(key)
|
|
101
|
+
self.plural = t.EntityPlural(plural)
|
|
102
|
+
self.label = label
|
|
103
|
+
self.doc = textwrap.dedent(doc)
|
|
104
|
+
self.roles_description = roles
|
|
105
|
+
self.roles: Iterable[Role] = ()
|
|
106
|
+
for role_description in roles:
|
|
107
|
+
role = Role(role_description, self)
|
|
108
|
+
setattr(self, role.key.upper(), role)
|
|
109
|
+
self.roles = (*self.roles, role)
|
|
110
|
+
if subroles := role_description.get("subroles"):
|
|
111
|
+
role.subroles = ()
|
|
112
|
+
for subrole_key in subroles:
|
|
113
|
+
subrole = Role({"key": subrole_key, "max": 1}, self)
|
|
114
|
+
setattr(self, subrole.key.upper(), subrole)
|
|
115
|
+
role.subroles = (*role.subroles, subrole)
|
|
116
|
+
role.max = len(role.subroles)
|
|
117
|
+
self.flattened_roles = tuple(
|
|
118
|
+
chain.from_iterable(role.subroles or [role] for role in self.roles),
|
|
119
|
+
)
|
|
120
|
+
self.containing_entities = containing_entities
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
__all__ = ["GroupEntity"]
|
|
@@ -0,0 +1,165 @@
|
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from collections.abc import Iterable, Sequence
|
|
4
|
+
|
|
5
|
+
from . import types as t
|
|
6
|
+
from .entity import Entity as SingleEntity
|
|
7
|
+
from .group_entity import GroupEntity
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def build_entity(
|
|
11
|
+
key: str,
|
|
12
|
+
plural: str,
|
|
13
|
+
label: str,
|
|
14
|
+
doc: str = "",
|
|
15
|
+
roles: None | Sequence[t.RoleParams] = None,
|
|
16
|
+
is_person: bool = False,
|
|
17
|
+
*,
|
|
18
|
+
class_override: object = None,
|
|
19
|
+
containing_entities: Sequence[str] = (),
|
|
20
|
+
) -> t.SingleEntity | t.GroupEntity:
|
|
21
|
+
"""Build an ``Entity`` or a ``GroupEntity``.
|
|
22
|
+
|
|
23
|
+
Args:
|
|
24
|
+
key: Key to identify the ``Entity`` or ``GroupEntity``.
|
|
25
|
+
plural: The ``key`` pluralised.
|
|
26
|
+
label: A summary description.
|
|
27
|
+
doc: A full description.
|
|
28
|
+
roles: A list of roles —if it's a ``GroupEntity``.
|
|
29
|
+
is_person: If is an individual, or not.
|
|
30
|
+
class_override: ?
|
|
31
|
+
containing_entities: Keys of contained entities.
|
|
32
|
+
|
|
33
|
+
Returns:
|
|
34
|
+
Entity: When ``is_person`` is ``True``.
|
|
35
|
+
GroupEntity: When ``is_person`` is ``False``.
|
|
36
|
+
|
|
37
|
+
Raises:
|
|
38
|
+
NotImplementedError: If ``roles`` is ``None``.
|
|
39
|
+
|
|
40
|
+
Examples:
|
|
41
|
+
>>> from openfisca_core import entities
|
|
42
|
+
|
|
43
|
+
>>> entity = entities.build_entity(
|
|
44
|
+
... "syndicate",
|
|
45
|
+
... "syndicates",
|
|
46
|
+
... "Banks loaning jointly.",
|
|
47
|
+
... roles=[],
|
|
48
|
+
... containing_entities=(),
|
|
49
|
+
... )
|
|
50
|
+
>>> entity
|
|
51
|
+
GroupEntity(syndicate)
|
|
52
|
+
|
|
53
|
+
>>> entities.build_entity(
|
|
54
|
+
... "company",
|
|
55
|
+
... "companies",
|
|
56
|
+
... "A small or medium company.",
|
|
57
|
+
... is_person=True,
|
|
58
|
+
... )
|
|
59
|
+
Entity(company)
|
|
60
|
+
|
|
61
|
+
>>> role = entities.Role({"key": "key"}, entity)
|
|
62
|
+
|
|
63
|
+
>>> entities.build_entity(
|
|
64
|
+
... "syndicate",
|
|
65
|
+
... "syndicates",
|
|
66
|
+
... "Banks loaning jointly.",
|
|
67
|
+
... roles=[role],
|
|
68
|
+
... )
|
|
69
|
+
Traceback (most recent call last):
|
|
70
|
+
TypeError: 'Role' object is not subscriptable
|
|
71
|
+
|
|
72
|
+
"""
|
|
73
|
+
if is_person:
|
|
74
|
+
return SingleEntity(key, plural, label, doc)
|
|
75
|
+
|
|
76
|
+
if roles is not None:
|
|
77
|
+
return GroupEntity(
|
|
78
|
+
key,
|
|
79
|
+
plural,
|
|
80
|
+
label,
|
|
81
|
+
doc,
|
|
82
|
+
roles,
|
|
83
|
+
containing_entities=containing_entities,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
raise NotImplementedError
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
def find_role(
|
|
90
|
+
roles: Iterable[t.Role],
|
|
91
|
+
key: t.RoleKey,
|
|
92
|
+
*,
|
|
93
|
+
total: None | int = None,
|
|
94
|
+
) -> None | t.Role:
|
|
95
|
+
"""Find a ``Role`` in a ``GroupEntity``.
|
|
96
|
+
|
|
97
|
+
Args:
|
|
98
|
+
roles: The roles to search.
|
|
99
|
+
key: The key of the role to find.
|
|
100
|
+
total: The ``max`` attribute of the role to find.
|
|
101
|
+
|
|
102
|
+
Returns:
|
|
103
|
+
Role: The role if found
|
|
104
|
+
None: Else ``None``.
|
|
105
|
+
|
|
106
|
+
Examples:
|
|
107
|
+
>>> from openfisca_core import entities
|
|
108
|
+
>>> from openfisca_core.entities import types as t
|
|
109
|
+
|
|
110
|
+
>>> principal = t.RoleParams(
|
|
111
|
+
... key="principal",
|
|
112
|
+
... label="Principal",
|
|
113
|
+
... doc="Person focus of a calculation in a family context.",
|
|
114
|
+
... max=1,
|
|
115
|
+
... )
|
|
116
|
+
|
|
117
|
+
>>> partner = t.RoleParams(
|
|
118
|
+
... key="partner",
|
|
119
|
+
... plural="partners",
|
|
120
|
+
... label="Partners",
|
|
121
|
+
... doc="Persons partners of the principal.",
|
|
122
|
+
... )
|
|
123
|
+
|
|
124
|
+
>>> parent = t.RoleParams(
|
|
125
|
+
... key="parent",
|
|
126
|
+
... plural="parents",
|
|
127
|
+
... label="Parents",
|
|
128
|
+
... doc="Persons parents of children of the principal",
|
|
129
|
+
... subroles=["first_parent", "second_parent"],
|
|
130
|
+
... )
|
|
131
|
+
|
|
132
|
+
>>> group_entity = entities.build_entity(
|
|
133
|
+
... key="family",
|
|
134
|
+
... plural="families",
|
|
135
|
+
... label="Family",
|
|
136
|
+
... doc="A Family represents a collection of related persons.",
|
|
137
|
+
... roles=[principal, partner, parent],
|
|
138
|
+
... )
|
|
139
|
+
|
|
140
|
+
>>> entities.find_role(group_entity.roles, "principal", total=1)
|
|
141
|
+
Role(principal)
|
|
142
|
+
|
|
143
|
+
>>> entities.find_role(group_entity.roles, "partner")
|
|
144
|
+
Role(partner)
|
|
145
|
+
|
|
146
|
+
>>> entities.find_role(group_entity.roles, "parent", total=2)
|
|
147
|
+
Role(parent)
|
|
148
|
+
|
|
149
|
+
>>> entities.find_role(group_entity.roles, "first_parent", total=1)
|
|
150
|
+
Role(first_parent)
|
|
151
|
+
|
|
152
|
+
"""
|
|
153
|
+
for role in roles:
|
|
154
|
+
if role.subroles:
|
|
155
|
+
for subrole in role.subroles:
|
|
156
|
+
if (subrole.max == total) and (subrole.key == key):
|
|
157
|
+
return subrole
|
|
158
|
+
|
|
159
|
+
if (role.max == total) and (role.key == key):
|
|
160
|
+
return role
|
|
161
|
+
|
|
162
|
+
return None
|
|
163
|
+
|
|
164
|
+
|
|
165
|
+
__all__ = ["build_entity", "find_role"]
|
|
File without changes
|