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.
Files changed (237) hide show
  1. openfisca_core/__init__.py +0 -0
  2. openfisca_core/commons/__init__.py +18 -0
  3. openfisca_core/commons/dummy.py +25 -0
  4. openfisca_core/commons/formulas.py +121 -0
  5. openfisca_core/commons/misc.py +109 -0
  6. openfisca_core/commons/py.typed +0 -0
  7. openfisca_core/commons/rates.py +114 -0
  8. openfisca_core/commons/tests/__init__.py +0 -0
  9. openfisca_core/commons/tests/test_dummy.py +9 -0
  10. openfisca_core/commons/tests/test_formulas.py +75 -0
  11. openfisca_core/commons/tests/test_rates.py +26 -0
  12. openfisca_core/data_storage/__init__.py +7 -0
  13. openfisca_core/data_storage/in_memory_storage.py +198 -0
  14. openfisca_core/data_storage/on_disk_storage.py +307 -0
  15. openfisca_core/data_storage/types.py +14 -0
  16. openfisca_core/entities/__init__.py +23 -0
  17. openfisca_core/entities/_core_entity.py +217 -0
  18. openfisca_core/entities/_description.py +55 -0
  19. openfisca_core/entities/entity.py +60 -0
  20. openfisca_core/entities/group_entity.py +123 -0
  21. openfisca_core/entities/helpers.py +165 -0
  22. openfisca_core/entities/py.typed +0 -0
  23. openfisca_core/entities/role.py +92 -0
  24. openfisca_core/entities/tests/__init__.py +0 -0
  25. openfisca_core/entities/tests/test_entity.py +10 -0
  26. openfisca_core/entities/tests/test_group_entity.py +70 -0
  27. openfisca_core/entities/tests/test_role.py +11 -0
  28. openfisca_core/entities/types.py +44 -0
  29. openfisca_core/errors/__init__.py +64 -0
  30. openfisca_core/errors/cycle_error.py +2 -0
  31. openfisca_core/errors/empty_argument_error.py +39 -0
  32. openfisca_core/errors/nan_creation_error.py +2 -0
  33. openfisca_core/errors/parameter_not_found_error.py +16 -0
  34. openfisca_core/errors/parameter_parsing_error.py +18 -0
  35. openfisca_core/errors/period_mismatch_error.py +9 -0
  36. openfisca_core/errors/situation_parsing_error.py +26 -0
  37. openfisca_core/errors/spiral_error.py +2 -0
  38. openfisca_core/errors/variable_name_config_error.py +2 -0
  39. openfisca_core/errors/variable_not_found_error.py +29 -0
  40. openfisca_core/experimental/__init__.py +9 -0
  41. openfisca_core/experimental/_errors.py +5 -0
  42. openfisca_core/experimental/_memory_config.py +41 -0
  43. openfisca_core/formula_helpers.py +9 -0
  44. openfisca_core/holders/__init__.py +33 -0
  45. openfisca_core/holders/helpers.py +93 -0
  46. openfisca_core/holders/holder.py +328 -0
  47. openfisca_core/holders/tests/__init__.py +0 -0
  48. openfisca_core/holders/tests/test_helpers.py +134 -0
  49. openfisca_core/holders/types.py +3 -0
  50. openfisca_core/indexed_enums/__init__.py +18 -0
  51. openfisca_core/indexed_enums/_enum_type.py +79 -0
  52. openfisca_core/indexed_enums/_errors.py +35 -0
  53. openfisca_core/indexed_enums/_guards.py +209 -0
  54. openfisca_core/indexed_enums/_utils.py +180 -0
  55. openfisca_core/indexed_enums/config.py +6 -0
  56. openfisca_core/indexed_enums/enum.py +218 -0
  57. openfisca_core/indexed_enums/enum_array.py +316 -0
  58. openfisca_core/indexed_enums/py.typed +0 -0
  59. openfisca_core/indexed_enums/tests/__init__.py +0 -0
  60. openfisca_core/indexed_enums/tests/test_enum.py +135 -0
  61. openfisca_core/indexed_enums/tests/test_enum_array.py +30 -0
  62. openfisca_core/indexed_enums/types.py +49 -0
  63. openfisca_core/memory_config.py +9 -0
  64. openfisca_core/model_api.py +71 -0
  65. openfisca_core/parameters/__init__.py +71 -0
  66. openfisca_core/parameters/at_instant_like.py +17 -0
  67. openfisca_core/parameters/config.py +55 -0
  68. openfisca_core/parameters/helpers.py +106 -0
  69. openfisca_core/parameters/parameter.py +217 -0
  70. openfisca_core/parameters/parameter_at_instant.py +75 -0
  71. openfisca_core/parameters/parameter_node.py +176 -0
  72. openfisca_core/parameters/parameter_node_at_instant.py +57 -0
  73. openfisca_core/parameters/parameter_scale.py +121 -0
  74. openfisca_core/parameters/parameter_scale_bracket.py +7 -0
  75. openfisca_core/parameters/values_history.py +5 -0
  76. openfisca_core/parameters/vectorial_parameter_node_at_instant.py +179 -0
  77. openfisca_core/periods/__init__.py +77 -0
  78. openfisca_core/periods/_errors.py +28 -0
  79. openfisca_core/periods/_parsers.py +122 -0
  80. openfisca_core/periods/config.py +20 -0
  81. openfisca_core/periods/date_unit.py +110 -0
  82. openfisca_core/periods/helpers.py +314 -0
  83. openfisca_core/periods/instant_.py +226 -0
  84. openfisca_core/periods/period_.py +919 -0
  85. openfisca_core/periods/py.typed +0 -0
  86. openfisca_core/periods/tests/__init__.py +0 -0
  87. openfisca_core/periods/tests/helpers/__init__.py +0 -0
  88. openfisca_core/periods/tests/helpers/test_helpers.py +65 -0
  89. openfisca_core/periods/tests/helpers/test_instant.py +73 -0
  90. openfisca_core/periods/tests/helpers/test_period.py +134 -0
  91. openfisca_core/periods/tests/test_instant.py +32 -0
  92. openfisca_core/periods/tests/test_parsers.py +129 -0
  93. openfisca_core/periods/tests/test_period.py +283 -0
  94. openfisca_core/populations/__init__.py +64 -0
  95. openfisca_core/populations/_core_population.py +454 -0
  96. openfisca_core/populations/_errors.py +65 -0
  97. openfisca_core/populations/group_population.py +326 -0
  98. openfisca_core/populations/population.py +142 -0
  99. openfisca_core/populations/tests/__init__.py +0 -0
  100. openfisca_core/populations/tests/test_members_position.py +116 -0
  101. openfisca_core/populations/types.py +110 -0
  102. openfisca_core/projectors/__init__.py +39 -0
  103. openfisca_core/projectors/entity_to_person_projector.py +12 -0
  104. openfisca_core/projectors/first_person_to_entity_projector.py +13 -0
  105. openfisca_core/projectors/helpers.py +139 -0
  106. openfisca_core/projectors/projector.py +38 -0
  107. openfisca_core/projectors/typing.py +27 -0
  108. openfisca_core/projectors/unique_role_to_entity_projector.py +14 -0
  109. openfisca_core/rates.py +9 -0
  110. openfisca_core/reforms/__init__.py +24 -0
  111. openfisca_core/reforms/in_yaml_test_reform.py +28 -0
  112. openfisca_core/reforms/reform.py +86 -0
  113. openfisca_core/scripts/__init__.py +106 -0
  114. openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.3.3.pyc +0 -0
  115. openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.4.2.pyc +0 -0
  116. openfisca_core/scripts/__pycache__/__init__.cpython-310.pyc +0 -0
  117. openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.3.3.pyc +0 -0
  118. openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.4.2.pyc +0 -0
  119. openfisca_core/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  120. openfisca_core/scripts/__pycache__/__init__.cpython-312-pytest-8.4.2.pyc +0 -0
  121. openfisca_core/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
  122. openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.3.3.pyc +0 -0
  123. openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.4.2.pyc +0 -0
  124. openfisca_core/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
  125. openfisca_core/scripts/__pycache__/find_placeholders.cpython-311.pyc +0 -0
  126. openfisca_core/scripts/__pycache__/find_placeholders.cpython-313.pyc +0 -0
  127. openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-311.pyc +0 -0
  128. openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-313.pyc +0 -0
  129. openfisca_core/scripts/__pycache__/measure_performances.cpython-311.pyc +0 -0
  130. openfisca_core/scripts/__pycache__/measure_performances.cpython-313.pyc +0 -0
  131. openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-311.pyc +0 -0
  132. openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-313.pyc +0 -0
  133. openfisca_core/scripts/__pycache__/openfisca_command.cpython-310.pyc +0 -0
  134. openfisca_core/scripts/__pycache__/openfisca_command.cpython-311.pyc +0 -0
  135. openfisca_core/scripts/__pycache__/openfisca_command.cpython-312.pyc +0 -0
  136. openfisca_core/scripts/__pycache__/openfisca_command.cpython-313.pyc +0 -0
  137. openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-311.pyc +0 -0
  138. openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-313.pyc +0 -0
  139. openfisca_core/scripts/__pycache__/run_test.cpython-310.pyc +0 -0
  140. openfisca_core/scripts/__pycache__/run_test.cpython-311.pyc +0 -0
  141. openfisca_core/scripts/__pycache__/run_test.cpython-312.pyc +0 -0
  142. openfisca_core/scripts/__pycache__/run_test.cpython-313.pyc +0 -0
  143. openfisca_core/scripts/__pycache__/simulation_generator.cpython-311.pyc +0 -0
  144. openfisca_core/scripts/__pycache__/simulation_generator.cpython-313.pyc +0 -0
  145. openfisca_core/scripts/assets/__init__.py +0 -0
  146. openfisca_core/scripts/assets/__pycache__/__init__.cpython-311.pyc +0 -0
  147. openfisca_core/scripts/assets/__pycache__/__init__.cpython-313.pyc +0 -0
  148. openfisca_core/scripts/assets/index.html +140 -0
  149. openfisca_core/scripts/find_placeholders.py +51 -0
  150. openfisca_core/scripts/measure_numpy_condition_notations.py +137 -0
  151. openfisca_core/scripts/measure_performances.py +291 -0
  152. openfisca_core/scripts/measure_performances_fancy_indexing.py +89 -0
  153. openfisca_core/scripts/migrations/__init__.py +0 -0
  154. openfisca_core/scripts/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
  155. openfisca_core/scripts/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  156. openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-311.pyc +0 -0
  157. openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-313.pyc +0 -0
  158. openfisca_core/scripts/migrations/v16_2_to_v17/__init__.py +0 -0
  159. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-311.pyc +0 -0
  160. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-313.pyc +0 -0
  161. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-311.pyc +0 -0
  162. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-313.pyc +0 -0
  163. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-311.pyc +0 -0
  164. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-313.pyc +0 -0
  165. openfisca_core/scripts/migrations/v16_2_to_v17/legislation.xsd +102 -0
  166. openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_country_template.py +30 -0
  167. openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_extension_template.py +26 -0
  168. openfisca_core/scripts/migrations/v24_to_25.py +156 -0
  169. openfisca_core/scripts/openfisca_command.py +192 -0
  170. openfisca_core/scripts/remove_fuzzy.py +213 -0
  171. openfisca_core/scripts/run_test.py +51 -0
  172. openfisca_core/scripts/simulation_generator.py +90 -0
  173. openfisca_core/simulation_builder.py +16 -0
  174. openfisca_core/simulations/__init__.py +45 -0
  175. openfisca_core/simulations/_build_default_simulation.py +158 -0
  176. openfisca_core/simulations/_build_from_variables.py +230 -0
  177. openfisca_core/simulations/_type_guards.py +298 -0
  178. openfisca_core/simulations/helpers.py +111 -0
  179. openfisca_core/simulations/simulation.py +618 -0
  180. openfisca_core/simulations/simulation_builder.py +855 -0
  181. openfisca_core/simulations/typing.py +203 -0
  182. openfisca_core/taxbenefitsystems/__init__.py +26 -0
  183. openfisca_core/taxbenefitsystems/tax_benefit_system.py +584 -0
  184. openfisca_core/taxscales/__init__.py +35 -0
  185. openfisca_core/taxscales/abstract_rate_tax_scale.py +41 -0
  186. openfisca_core/taxscales/abstract_tax_scale.py +53 -0
  187. openfisca_core/taxscales/amount_tax_scale_like.py +55 -0
  188. openfisca_core/taxscales/helpers.py +44 -0
  189. openfisca_core/taxscales/linear_average_rate_tax_scale.py +76 -0
  190. openfisca_core/taxscales/marginal_amount_tax_scale.py +34 -0
  191. openfisca_core/taxscales/marginal_rate_tax_scale.py +286 -0
  192. openfisca_core/taxscales/rate_tax_scale_like.py +214 -0
  193. openfisca_core/taxscales/single_amount_tax_scale.py +32 -0
  194. openfisca_core/taxscales/tax_scale_like.py +65 -0
  195. openfisca_core/tools/__init__.py +94 -0
  196. openfisca_core/tools/parallel_plugin.py +55 -0
  197. openfisca_core/tools/simulation_dumper.py +137 -0
  198. openfisca_core/tools/test_runner.py +802 -0
  199. openfisca_core/tracers/__init__.py +40 -0
  200. openfisca_core/tracers/computation_log.py +196 -0
  201. openfisca_core/tracers/flat_trace.py +87 -0
  202. openfisca_core/tracers/full_tracer.py +172 -0
  203. openfisca_core/tracers/performance_log.py +133 -0
  204. openfisca_core/tracers/simple_tracer.py +64 -0
  205. openfisca_core/tracers/trace_node.py +121 -0
  206. openfisca_core/tracers/tracing_parameter_node_at_instant.py +81 -0
  207. openfisca_core/types.py +548 -0
  208. openfisca_core/variables/__init__.py +26 -0
  209. openfisca_core/variables/config.py +53 -0
  210. openfisca_core/variables/helpers.py +67 -0
  211. openfisca_core/variables/tests/__init__.py +0 -0
  212. openfisca_core/variables/tests/test_definition_period.py +43 -0
  213. openfisca_core/variables/variable.py +474 -0
  214. openfisca_core/warnings/__init__.py +25 -0
  215. openfisca_core/warnings/libyaml_warning.py +2 -0
  216. openfisca_core/warnings/tempfile_warning.py +2 -0
  217. openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/CHANGELOG.md +4209 -0
  218. openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/README.md +152 -0
  219. openfisca_core_test-46.0.0.dist-info/METADATA +194 -0
  220. openfisca_core_test-46.0.0.dist-info/RECORD +237 -0
  221. openfisca_core_test-46.0.0.dist-info/WHEEL +5 -0
  222. openfisca_core_test-46.0.0.dist-info/entry_points.txt +3 -0
  223. openfisca_core_test-46.0.0.dist-info/licenses/LICENSE +661 -0
  224. openfisca_core_test-46.0.0.dist-info/top_level.txt +2 -0
  225. openfisca_web_api/__init__.py +0 -0
  226. openfisca_web_api/app.py +226 -0
  227. openfisca_web_api/errors.py +11 -0
  228. openfisca_web_api/handlers.py +90 -0
  229. openfisca_web_api/loader/__init__.py +22 -0
  230. openfisca_web_api/loader/entities.py +28 -0
  231. openfisca_web_api/loader/parameters.py +122 -0
  232. openfisca_web_api/loader/spec.py +168 -0
  233. openfisca_web_api/loader/tax_benefit_system.py +27 -0
  234. openfisca_web_api/loader/variables.py +121 -0
  235. openfisca_web_api/openAPI.yml +434 -0
  236. openfisca_web_api/scripts/__init__.py +0 -0
  237. openfisca_web_api/scripts/serve.py +99 -0
@@ -0,0 +1,454 @@
1
+ from __future__ import annotations
2
+
3
+ import traceback
4
+ from collections.abc import Sequence
5
+ from typing import TypeVar
6
+
7
+ import numpy
8
+
9
+ from openfisca_core import holders, periods
10
+
11
+ from . import types as t
12
+ from ._errors import (
13
+ IncompatibleOptionsError,
14
+ InvalidArraySizeError,
15
+ InvalidOptionError,
16
+ PeriodValidityError,
17
+ )
18
+
19
+ #: Type variable for a covariant data type.
20
+ _DT_co = TypeVar("_DT_co", covariant=True, bound=t.VarDType)
21
+
22
+
23
+ class CorePopulation:
24
+ """Base class to build populations from.
25
+
26
+ Args:
27
+ entity: The :class:`~entities.CoreEntity` of the population.
28
+ *__args: Variable length argument list.
29
+ **__kwds: Arbitrary keyword arguments.
30
+
31
+ """
32
+
33
+ #: The number :class:`~entities.CoreEntity` members in the population.
34
+ count: int = 0
35
+
36
+ #: The :class:`~entities.CoreEntity` of the population.
37
+ entity: t.CoreEntity
38
+
39
+ #: A pseudo index for the members of the population.
40
+ ids: Sequence[str] = []
41
+
42
+ #: The :class:`~simulations.Simulation` for which the population is calculated.
43
+ simulation: None | t.Simulation = None
44
+
45
+ def __init__(self, entity: t.CoreEntity, *__args: object, **__kwds: object) -> None:
46
+ self.entity = entity
47
+ self._holders: t.HolderByVariable = {}
48
+
49
+ def __call__(
50
+ self,
51
+ variable_name: t.VariableName,
52
+ period: t.PeriodLike,
53
+ options: None | Sequence[t.Option] = None,
54
+ ) -> None | t.VarArray:
55
+ """Calculate ``variable_name`` for ``period``, using the formula if it exists.
56
+
57
+ Args:
58
+ variable_name: The name of the variable to calculate.
59
+ period: The period to calculate the variable for.
60
+ options: The options to use for the calculation.
61
+
62
+ Returns:
63
+ None: If there is no :class:`~simulations.Simulation`.
64
+ ndarray[generic]: The result of the calculation.
65
+
66
+ Raises:
67
+ IncompatibleOptionsError: If the options are incompatible.
68
+ InvalidOptionError: If the option is invalid.
69
+
70
+ Examples:
71
+ >>> from openfisca_core import (
72
+ ... entities,
73
+ ... periods,
74
+ ... populations,
75
+ ... simulations,
76
+ ... taxbenefitsystems,
77
+ ... variables,
78
+ ... )
79
+
80
+ >>> class Person(entities.SingleEntity): ...
81
+
82
+ >>> person = Person("person", "people", "", "")
83
+ >>> period = periods.Period.eternity()
84
+ >>> population = populations.CorePopulation(person)
85
+ >>> population.count = 3
86
+ >>> population("salary", period)
87
+
88
+ >>> tbs = taxbenefitsystems.TaxBenefitSystem([person])
89
+ >>> person.set_tax_benefit_system(tbs)
90
+ >>> simulation = simulations.Simulation(tbs, {person.key: population})
91
+ >>> population("salary", period)
92
+ Traceback (most recent call last):
93
+ VariableNotFoundError: You tried to calculate or to set a value ...
94
+
95
+ >>> class Salary(variables.Variable):
96
+ ... definition_period = periods.ETERNITY
97
+ ... entity = person
98
+ ... value_type = int
99
+
100
+ >>> tbs.add_variable(Salary)
101
+ <openfisca_core.populations._core_population.Salary object at...
102
+
103
+ >>> population(Salary().name, period)
104
+ array([0, 0, 0], dtype=int32)
105
+
106
+ >>> class Tax(Salary):
107
+ ... default_value = 100.0
108
+ ... definition_period = periods.ETERNITY
109
+ ... entity = person
110
+ ... value_type = float
111
+
112
+ >>> tbs.add_variable(Tax)
113
+ <openfisca_core.populations._core_population.Tax object at...
114
+
115
+ >>> population(Tax().name, period)
116
+ array([100., 100., 100.], dtype=float32)
117
+
118
+ >>> population(Tax().name, period, [populations.ADD])
119
+ Traceback (most recent call last):
120
+ ValueError: Unable to ADD constant variable 'Tax' over the perio...
121
+
122
+ >>> population(Tax().name, period, [populations.DIVIDE])
123
+ Traceback (most recent call last):
124
+ ValueError: Unable to DIVIDE constant variable 'Tax' over the pe...
125
+
126
+ >>> population(Tax().name, period, [populations.ADD, populations.DIVIDE])
127
+ Traceback (most recent call last):
128
+ IncompatibleOptionsError: Options ADD and DIVIDE are incompatibl...
129
+
130
+ >>> population(Tax().name, period, ["LAGRANGIAN"])
131
+ Traceback (most recent call last):
132
+ InvalidOptionError: Option LAGRANGIAN is not a valid option (try...
133
+
134
+ """
135
+ if self.simulation is None:
136
+ return None
137
+
138
+ calculate = t.Calculate(
139
+ variable=variable_name,
140
+ period=periods.period(period),
141
+ option=options,
142
+ )
143
+
144
+ self.entity.check_variable_defined_for_entity(calculate.variable)
145
+ self.check_period_validity(calculate.variable, calculate.period)
146
+
147
+ if not isinstance(calculate.option, Sequence):
148
+ return self.simulation.calculate(
149
+ calculate.variable,
150
+ calculate.period,
151
+ )
152
+
153
+ if t.Option.ADD in calculate.option and t.Option.DIVIDE in calculate.option:
154
+ raise IncompatibleOptionsError(variable_name)
155
+
156
+ if t.Option.ADD in calculate.option:
157
+ return self.simulation.calculate_add(
158
+ calculate.variable,
159
+ calculate.period,
160
+ )
161
+
162
+ if t.Option.DIVIDE in calculate.option:
163
+ return self.simulation.calculate_divide(
164
+ calculate.variable,
165
+ calculate.period,
166
+ )
167
+
168
+ raise InvalidOptionError(calculate.option[0], variable_name)
169
+
170
+ def empty_array(self) -> t.FloatArray:
171
+ """Return an empty array.
172
+
173
+ Returns:
174
+ ndarray[float32]: An empty array.
175
+
176
+ Examples:
177
+ >>> import numpy
178
+
179
+ >>> from openfisca_core import populations as p
180
+
181
+ >>> class Population(p.CorePopulation): ...
182
+
183
+ >>> population = Population(None)
184
+ >>> population.empty_array()
185
+ array([], dtype=float32)
186
+
187
+ >>> population.count = 3
188
+ >>> population.empty_array()
189
+ array([0., 0., 0.], dtype=float32)
190
+
191
+ """
192
+ return numpy.zeros(self.count, dtype=t.FloatDType)
193
+
194
+ def filled_array(
195
+ self, value: _DT_co, dtype: None | t.DTypeLike = None
196
+ ) -> t.Array[_DT_co]:
197
+ """Return an array filled with a value.
198
+
199
+ Args:
200
+ value: The value to fill the array with.
201
+ dtype: The data type of the array.
202
+
203
+ Returns:
204
+ ndarray[generic]: An array filled with the value.
205
+
206
+ Examples:
207
+ >>> import numpy
208
+
209
+ >>> from openfisca_core import populations
210
+
211
+ >>> class Population(populations.CorePopulation): ...
212
+
213
+ >>> population = Population(None)
214
+ >>> population.count = 3
215
+ >>> population.filled_array(1)
216
+ array([1, 1, 1])
217
+
218
+ >>> population.filled_array(numpy.float32(1))
219
+ array([1., 1., 1.], dtype=float32)
220
+
221
+ >>> population.filled_array(1, dtype=str)
222
+ array(['1', '1', '1'], dtype='<U1')
223
+
224
+ >>> population.filled_array("hola", dtype=numpy.uint8)
225
+ Traceback (most recent call last):
226
+ ValueError: could not convert string to float: 'hola'
227
+
228
+ """
229
+ return numpy.full(self.count, value, dtype)
230
+
231
+ def get_index(self, id: str) -> int:
232
+ """Return the index of an `id``.
233
+
234
+ Args:
235
+ id: The id to get the index for.
236
+
237
+ Returns:
238
+ int: The index of the id.
239
+
240
+ Examples:
241
+ >>> from openfisca_core import entities, populations
242
+
243
+ >>> class Person(entities.SingleEntity): ...
244
+
245
+ >>> person = Person("person", "people", "", "")
246
+ >>> population = populations.CorePopulation(person)
247
+ >>> population.ids = ["Juan", "Megan", "Brahim"]
248
+
249
+ >>> population.get_index("Megan")
250
+ 1
251
+
252
+ >>> population.get_index("Ibrahim")
253
+ Traceback (most recent call last):
254
+ ValueError: 'Ibrahim' is not in list
255
+
256
+ """
257
+ return self.ids.index(id)
258
+
259
+ # Calculations
260
+
261
+ def check_array_compatible_with_entity(self, array: t.VarArray) -> None:
262
+ """Check if an array is compatible with the population.
263
+
264
+ Args:
265
+ array: The array to check.
266
+
267
+ Raises:
268
+ InvalidArraySizeError: If the array is not compatible.
269
+
270
+ Examples:
271
+ >>> import numpy
272
+
273
+ >>> from openfisca_core import entities, populations
274
+
275
+ >>> class Person(entities.SingleEntity): ...
276
+
277
+ >>> person = Person("person", "people", "", "")
278
+ >>> population = populations.CorePopulation(person)
279
+ >>> population.count = 3
280
+
281
+ >>> array = numpy.array([1, 2, 3])
282
+ >>> population.check_array_compatible_with_entity(array)
283
+
284
+ >>> array = numpy.array([1, 2, 3, 4])
285
+ >>> population.check_array_compatible_with_entity(array)
286
+ Traceback (most recent call last):
287
+ InvalidArraySizeError: Input [1 2 3 4] is not a valid value for t...
288
+
289
+ """
290
+ if self.count == array.size:
291
+ return
292
+ raise InvalidArraySizeError(array, self.entity.key, self.count)
293
+
294
+ @staticmethod
295
+ def check_period_validity(
296
+ variable_name: t.VariableName,
297
+ period: None | t.PeriodLike = None,
298
+ ) -> None:
299
+ """Check if a period is valid.
300
+
301
+ Args:
302
+ variable_name: The name of the variable.
303
+ period: The period to check.
304
+
305
+ Raises:
306
+ PeriodValidityError: If the period is not valid.
307
+
308
+ Examples:
309
+ >>> from openfisca_core import entities, periods, populations
310
+
311
+ >>> class Person(entities.SingleEntity): ...
312
+
313
+ >>> person = Person("person", "people", "", "")
314
+ >>> period = periods.Period("2017-04")
315
+ >>> population = populations.CorePopulation(person)
316
+
317
+ >>> population.check_period_validity("salary")
318
+ Traceback (most recent call last):
319
+ PeriodValidityError: You requested computation of variable "sala...
320
+
321
+ >>> population.check_period_validity("salary", 2017)
322
+
323
+ >>> population.check_period_validity("salary", "2017-04")
324
+
325
+ >>> population.check_period_validity("salary", period)
326
+
327
+ """
328
+ if isinstance(period, (int, str, periods.Period)):
329
+ return
330
+ stack = traceback.extract_stack()
331
+ filename, line_number, _, line_of_code = stack[-3]
332
+ raise PeriodValidityError(variable_name, filename, line_number, line_of_code)
333
+
334
+ # Helpers
335
+
336
+ def get_holder(self, variable_name: t.VariableName) -> t.Holder:
337
+ """Return the holder of a variable.
338
+
339
+ Args:
340
+ variable_name: The name of the variable.
341
+
342
+ Returns:
343
+ Holder: The holder of the variable.
344
+
345
+ Examples:
346
+ >>> from openfisca_core import (
347
+ ... entities,
348
+ ... holders,
349
+ ... periods,
350
+ ... populations,
351
+ ... simulations,
352
+ ... taxbenefitsystems,
353
+ ... simulations,
354
+ ... variables,
355
+ ... )
356
+
357
+ >>> class Person(entities.SingleEntity): ...
358
+
359
+ >>> person = Person("person", "people", "", "")
360
+
361
+ >>> class Salary(variables.Variable):
362
+ ... definition_period = periods.WEEK
363
+ ... entity = person
364
+ ... value_type = int
365
+
366
+ >>> tbs = taxbenefitsystems.TaxBenefitSystem([person])
367
+ >>> person.set_tax_benefit_system(tbs)
368
+ >>> population = populations.SinglePopulation(person)
369
+ >>> simulation = simulations.Simulation(tbs, {person.key: population})
370
+ >>> population.get_holder("income_tax")
371
+ Traceback (most recent call last):
372
+ VariableNotFoundError: You tried to calculate or to set a value ...
373
+
374
+ >>> tbs.add_variable(Salary)
375
+ <openfisca_core.populations._core_population.Salary object at...
376
+
377
+ >>> salary = Salary()
378
+ >>> population.get_holder(salary.name)
379
+ <openfisca_core.holders.holder.Holder object at ...
380
+
381
+ """
382
+ self.entity.check_variable_defined_for_entity(variable_name)
383
+ holder = self._holders.get(variable_name)
384
+ if holder:
385
+ return holder
386
+ variable = self.entity.get_variable(variable_name)
387
+ self._holders[variable_name] = holder = holders.Holder(variable, self)
388
+ return holder
389
+
390
+ def get_memory_usage(
391
+ self,
392
+ variables: None | Sequence[t.VariableName] = None,
393
+ ) -> t.MemoryUsageByVariable:
394
+ """Return the memory usage of the population per variable.
395
+
396
+ Args:
397
+ variables: The variables to get the memory usage for.
398
+
399
+ Returns:
400
+ MemoryUsageByVariable: The memory usage of the population per variable.
401
+
402
+ Examples:
403
+ >>> from openfisca_core import (
404
+ ... entities,
405
+ ... holders,
406
+ ... periods,
407
+ ... populations,
408
+ ... simulations,
409
+ ... taxbenefitsystems,
410
+ ... simulations,
411
+ ... variables,
412
+ ... )
413
+
414
+ >>> class Person(entities.SingleEntity): ...
415
+
416
+ >>> person = Person("person", "people", "", "")
417
+
418
+ >>> class Salary(variables.Variable):
419
+ ... definition_period = periods.WEEK
420
+ ... entity = person
421
+ ... value_type = int
422
+
423
+ >>> tbs = taxbenefitsystems.TaxBenefitSystem([person])
424
+ >>> population = populations.SinglePopulation(person)
425
+ >>> simulation = simulations.Simulation(tbs, {person.key: population})
426
+ >>> salary = Salary()
427
+ >>> holder = holders.Holder(salary, population)
428
+ >>> population._holders[salary.name] = holder
429
+
430
+ >>> population.get_memory_usage()
431
+ {'total_nb_bytes': 0, 'by_variable': {'Salary': {'nb_cells_by...}}}
432
+
433
+ >>> population.get_memory_usage([salary.name])
434
+ {'total_nb_bytes': 0, 'by_variable': {'Salary': {'nb_cells_by...}}}
435
+
436
+ """
437
+ holders_memory_usage = {
438
+ variable_name: holder.get_memory_usage()
439
+ for variable_name, holder in self._holders.items()
440
+ if variables is None or variable_name in variables
441
+ }
442
+
443
+ total_memory_usage = sum(
444
+ holder_memory_usage["total_nb_bytes"]
445
+ for holder_memory_usage in holders_memory_usage.values()
446
+ )
447
+
448
+ return t.MemoryUsageByVariable(
449
+ total_nb_bytes=total_memory_usage,
450
+ by_variable=holders_memory_usage,
451
+ )
452
+
453
+
454
+ __all__ = ["CorePopulation"]
@@ -0,0 +1,65 @@
1
+ from . import types as t
2
+
3
+
4
+ class IncompatibleOptionsError(ValueError):
5
+ """Raised when two options are incompatible."""
6
+
7
+ def __init__(self, variable_name: t.VariableName) -> None:
8
+ add, divide = t.Option
9
+ msg = (
10
+ f"Options {add} and {divide} are incompatible (trying to compute "
11
+ f"variable {variable_name})."
12
+ )
13
+ super().__init__(msg)
14
+
15
+
16
+ class InvalidOptionError(ValueError):
17
+ """Raised when an option is invalid."""
18
+
19
+ def __init__(self, option: str, variable_name: t.VariableName) -> None:
20
+ msg = (
21
+ f"Option {option} is not a valid option (trying to compute "
22
+ f"variable {variable_name})."
23
+ )
24
+ super().__init__(msg)
25
+
26
+
27
+ class InvalidArraySizeError(ValueError):
28
+ """Raised when an array has an invalid size."""
29
+
30
+ def __init__(self, array: t.VarArray, entity: t.EntityKey, count: int) -> None:
31
+ msg = (
32
+ f"Input {array} is not a valid value for the entity {entity} "
33
+ f"(size = {array.size} != {count} = count)."
34
+ )
35
+ super().__init__(msg)
36
+
37
+
38
+ class PeriodValidityError(ValueError):
39
+ """Raised when a period is not valid."""
40
+
41
+ def __init__(
42
+ self,
43
+ variable_name: t.VariableName,
44
+ filename: str,
45
+ line_number: int,
46
+ line_of_code: int,
47
+ ) -> None:
48
+ msg = (
49
+ f'You requested computation of variable "{variable_name}", but '
50
+ f'you did not specify on which period in "{filename}:{line_number}": '
51
+ f"{line_of_code}. When you request the computation of a variable "
52
+ "within a formula, you must always specify the period as the second "
53
+ 'parameter. The convention is to call this parameter "period". For '
54
+ 'example: computed_salary = person("salary", period). More information at '
55
+ "<https://openfisca.org/doc/coding-the-legislation/35_periods.html#periods-in-variable-definition>."
56
+ )
57
+ super().__init__(msg)
58
+
59
+
60
+ __all__ = [
61
+ "IncompatibleOptionsError",
62
+ "InvalidArraySizeError",
63
+ "InvalidOptionError",
64
+ "PeriodValidityError",
65
+ ]