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
File without changes
@@ -0,0 +1,18 @@
1
+ """Common tools for contributors and users."""
2
+
3
+ from .dummy import Dummy
4
+ from .formulas import apply_thresholds, concat, switch
5
+ from .misc import empty_clone, eval_expression, stringify_array
6
+ from .rates import average_rate, marginal_rate
7
+
8
+ __all__ = [
9
+ "Dummy",
10
+ "apply_thresholds",
11
+ "average_rate",
12
+ "concat",
13
+ "empty_clone",
14
+ "eval_expression",
15
+ "marginal_rate",
16
+ "stringify_array",
17
+ "switch",
18
+ ]
@@ -0,0 +1,25 @@
1
+ import warnings
2
+
3
+
4
+ class Dummy:
5
+ """A class that did nothing.
6
+
7
+ Examples:
8
+ >>> Dummy()
9
+ <openfisca_core.commons.dummy.Dummy object...
10
+
11
+ .. deprecated:: 34.7.0
12
+ :class:`.Dummy` has been deprecated and it will be removed in the
13
+ future.
14
+
15
+ """
16
+
17
+ def __init__(self) -> None:
18
+ message = [
19
+ "The 'Dummy' class has been deprecated since version 34.7.0,",
20
+ "and will be removed in the future.",
21
+ ]
22
+ warnings.warn(" ".join(message), DeprecationWarning, stacklevel=2)
23
+
24
+
25
+ __all__ = ["Dummy"]
@@ -0,0 +1,121 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Mapping
4
+
5
+ import numpy
6
+
7
+ from openfisca_core import types as t
8
+
9
+
10
+ def apply_thresholds(
11
+ input: t.FloatArray,
12
+ thresholds: t.ArrayLike[float],
13
+ choices: t.ArrayLike[float],
14
+ ) -> t.FloatArray:
15
+ """Makes a choice based on an input and thresholds.
16
+
17
+ From a list of ``choices``, this function selects one of these values
18
+ based on a list of inputs, depending on the value of each ``input`` within
19
+ a list of ``thresholds``.
20
+
21
+ Args:
22
+ input: A list of inputs to make a choice from.
23
+ thresholds: A list of thresholds to choose.
24
+ choices: A list of the possible values to choose from.
25
+
26
+ Returns:
27
+ ndarray[float32]: A list of the values chosen.
28
+
29
+ Examples:
30
+ >>> input = numpy.array([4, 5, 6, 7, 8])
31
+ >>> thresholds = [5, 7]
32
+ >>> choices = [10, 15, 20]
33
+ >>> apply_thresholds(input, thresholds, choices)
34
+ array([10, 10, 15, 15, 20])
35
+
36
+ """
37
+ condlist: list[t.Array[numpy.bool_] | bool]
38
+ condlist = [input <= threshold for threshold in thresholds]
39
+
40
+ if len(condlist) == len(choices) - 1:
41
+ # If a choice is provided for input > highest threshold, last condition
42
+ # must be true to return it.
43
+ condlist += [True]
44
+
45
+ msg = (
46
+ "'apply_thresholds' must be called with the same number of thresholds "
47
+ "than choices, or one more choice."
48
+ )
49
+ assert len(condlist) == len(choices), msg
50
+
51
+ return numpy.select(condlist, choices)
52
+
53
+
54
+ def concat(
55
+ this: t.StrArray | t.ArrayLike[object],
56
+ that: t.StrArray | t.ArrayLike[object],
57
+ ) -> t.StrArray:
58
+ """Concatenate the values of two arrays.
59
+
60
+ Args:
61
+ this: An array to concatenate.
62
+ that: Another array to concatenate.
63
+
64
+ Returns:
65
+ ndarray[str_]: An array with the concatenated values.
66
+
67
+ Examples:
68
+ >>> this = ["this", "that"]
69
+ >>> that = numpy.array([1, 2.5])
70
+ >>> concat(this, that)
71
+ array(['this1.0', 'that2.5']...)
72
+
73
+ """
74
+ if not isinstance(this, numpy.ndarray):
75
+ this = numpy.array(this)
76
+
77
+ if not numpy.issubdtype(this.dtype, numpy.str_):
78
+ this = this.astype("str")
79
+
80
+ if not isinstance(that, numpy.ndarray):
81
+ that = numpy.array(that)
82
+
83
+ if not numpy.issubdtype(that.dtype, numpy.str_):
84
+ that = that.astype("str")
85
+
86
+ return numpy.char.add(this, that)
87
+
88
+
89
+ def switch(
90
+ conditions: t.FloatArray | t.ArrayLike[float],
91
+ value_by_condition: Mapping[float, float],
92
+ ) -> t.FloatArray:
93
+ """Mimic a switch statement.
94
+
95
+ Given an array of conditions, returns an array of the same size,
96
+ replacing each condition item with the matching given value.
97
+
98
+ Args:
99
+ conditions: An array of conditions.
100
+ value_by_condition: Values to replace for each condition.
101
+
102
+ Returns:
103
+ ndarray[float32]: An array with the replaced values.
104
+
105
+ Examples:
106
+ >>> conditions = numpy.array([1, 1, 1, 2])
107
+ >>> value_by_condition = {1: 80, 2: 90}
108
+ >>> switch(conditions, value_by_condition)
109
+ array([80, 80, 80, 90])
110
+
111
+ """
112
+ assert len(value_by_condition) > 0, (
113
+ "'switch' must be called with at least one value."
114
+ )
115
+
116
+ condlist = [conditions == condition for condition in value_by_condition]
117
+
118
+ return numpy.select(condlist, tuple(value_by_condition.values()))
119
+
120
+
121
+ __all__ = ["apply_thresholds", "concat", "switch"]
@@ -0,0 +1,109 @@
1
+ from __future__ import annotations
2
+
3
+ import numexpr
4
+
5
+ from openfisca_core import types as t
6
+
7
+
8
+ def empty_clone(original: object) -> object:
9
+ """Create an empty instance of the same class of the original object.
10
+
11
+ Args:
12
+ original: An object to clone.
13
+
14
+ Returns:
15
+ object: The cloned, empty, object.
16
+
17
+ Examples:
18
+ >>> Foo = type("Foo", (list,), {})
19
+ >>> foo = Foo([1, 2, 3])
20
+ >>> foo
21
+ [1, 2, 3]
22
+
23
+ >>> bar = empty_clone(foo)
24
+ >>> bar
25
+ []
26
+
27
+ >>> isinstance(bar, Foo)
28
+ True
29
+
30
+ """
31
+
32
+ def __init__(_: object) -> None: ...
33
+
34
+ Dummy = type(
35
+ "Dummy",
36
+ (original.__class__,),
37
+ {"__init__": __init__},
38
+ )
39
+
40
+ new = Dummy()
41
+ new.__class__ = original.__class__
42
+ return new
43
+
44
+
45
+ def stringify_array(array: None | t.VarArray) -> str:
46
+ """Generate a clean string representation of a numpy array.
47
+
48
+ Args:
49
+ array: An array.
50
+
51
+ Returns:
52
+ str: ``"None"`` if the ``array`` is ``None``.
53
+ str: The stringified ``array`` otherwise.
54
+
55
+ Examples:
56
+ >>> import numpy
57
+ >>> stringify_array(None)
58
+ 'None'
59
+
60
+ >>> array = numpy.array([10, 20.0])
61
+ >>> stringify_array(array)
62
+ '[10.0, 20.0]'
63
+
64
+ >>> array = numpy.array(["10", "Twenty"])
65
+ >>> stringify_array(array)
66
+ '[10, Twenty]'
67
+
68
+ >>> array = numpy.array([list, dict(), stringify_array])
69
+ >>> stringify_array(array)
70
+ "[<class 'list'>, {}, <function stringify_array...]"
71
+
72
+ """
73
+ if array is None:
74
+ return "None"
75
+
76
+ return f"[{', '.join(str(cell) for cell in array)}]"
77
+
78
+
79
+ def eval_expression(
80
+ expression: str,
81
+ ) -> str | t.BoolArray | t.IntArray | t.FloatArray:
82
+ """Evaluate a string expression to a numpy array.
83
+
84
+ Args:
85
+ expression: An expression to evaluate.
86
+
87
+ Returns:
88
+ ndarray: The result of the evaluation.
89
+ str: The expression if it couldn't be evaluated.
90
+
91
+ Examples:
92
+ >>> eval_expression("1 + 2")
93
+ array(3, dtype=int32)
94
+
95
+ >>> eval_expression("salary")
96
+ 'salary'
97
+
98
+ >>> eval_expression("date of birth")
99
+ 'date of birth'
100
+
101
+ """
102
+ try:
103
+ return numexpr.evaluate(expression)
104
+
105
+ except (KeyError, TypeError, SyntaxError):
106
+ return expression
107
+
108
+
109
+ __all__ = ["empty_clone", "eval_expression", "stringify_array"]
File without changes
@@ -0,0 +1,114 @@
1
+ from __future__ import annotations
2
+
3
+ import numpy
4
+
5
+ from openfisca_core import types as t
6
+
7
+
8
+ def average_rate(
9
+ target: t.FloatArray,
10
+ varying: t.FloatArray | t.ArrayLike[float],
11
+ trim: None | t.ArrayLike[float] = None,
12
+ ) -> t.FloatArray:
13
+ """Compute the average rate of a target net income.
14
+
15
+ Given a ``target`` net income, and according to the ``varying`` gross
16
+ income. Optionally, a ``trim`` can be applied consisting of the lower and
17
+ upper bounds of the average rate to be computed.
18
+
19
+ Note:
20
+ Usually, ``target`` and ``varying`` are the same size.
21
+
22
+ Args:
23
+ target: The targeted net income.
24
+ varying: The varying gross income.
25
+ trim: The lower and upper bounds of the average rate.
26
+
27
+ Returns:
28
+ ndarray[float32]: The average rate for each target. When ``trim``
29
+ is provided, values that are out of the provided bounds are
30
+ replaced by :obj:`numpy.nan`.
31
+
32
+ Examples:
33
+ >>> target = numpy.array([1, 2, 3])
34
+ >>> varying = [2, 2, 2]
35
+ >>> trim = [-1, 0.25]
36
+ >>> average_rate(target, varying, trim)
37
+ array([ nan, 0. , -0.5])
38
+
39
+ """
40
+ if not isinstance(varying, numpy.ndarray):
41
+ varying = numpy.array(varying, dtype=numpy.float32)
42
+
43
+ average_rate = 1 - target / varying
44
+
45
+ if trim is not None:
46
+ average_rate = numpy.where(
47
+ average_rate <= max(trim),
48
+ average_rate,
49
+ numpy.nan,
50
+ )
51
+
52
+ average_rate = numpy.where(
53
+ average_rate >= min(trim),
54
+ average_rate,
55
+ numpy.nan,
56
+ )
57
+
58
+ return average_rate
59
+
60
+
61
+ def marginal_rate(
62
+ target: t.FloatArray,
63
+ varying: t.FloatArray | t.ArrayLike[float],
64
+ trim: None | t.ArrayLike[float] = None,
65
+ ) -> t.FloatArray:
66
+ """Compute the marginal rate of a target net income.
67
+
68
+ Given a ``target`` net income, and according to the ``varying`` gross
69
+ income. Optionally, a ``trim`` can be applied consisting of the lower and
70
+ upper bounds of the marginal rate to be computed.
71
+
72
+ Note:
73
+ Usually, ``target`` and ``varying`` are the same size.
74
+
75
+ Args:
76
+ target: The targeted net income.
77
+ varying: The varying gross income.
78
+ trim: The lower and upper bounds of the marginal rate.
79
+
80
+ Returns:
81
+ ndarray[float32]: The marginal rate for each target. When ``trim``
82
+ is provided, values that are out of the provided bounds are
83
+ replaced by :class:`numpy.nan`.
84
+
85
+ Examples:
86
+ >>> target = numpy.array([1, 2, 3])
87
+ >>> varying = numpy.array([1, 2, 4])
88
+ >>> trim = [0.25, 0.75]
89
+ >>> marginal_rate(target, varying, trim)
90
+ array([nan, 0.5])
91
+
92
+ """
93
+ if not isinstance(varying, numpy.ndarray):
94
+ varying = numpy.array(varying, dtype=numpy.float32)
95
+
96
+ marginal_rate = +1 - (target[:-1] - target[1:]) / (varying[:-1] - varying[1:])
97
+
98
+ if trim is not None:
99
+ marginal_rate = numpy.where(
100
+ marginal_rate <= max(trim),
101
+ marginal_rate,
102
+ numpy.nan,
103
+ )
104
+
105
+ marginal_rate = numpy.where(
106
+ marginal_rate >= min(trim),
107
+ marginal_rate,
108
+ numpy.nan,
109
+ )
110
+
111
+ return marginal_rate
112
+
113
+
114
+ __all__ = ["average_rate", "marginal_rate"]
File without changes
@@ -0,0 +1,9 @@
1
+ import pytest
2
+
3
+ from openfisca_core.commons import Dummy
4
+
5
+
6
+ def test_dummy_deprecation() -> None:
7
+ """Dummy throws a deprecation warning when instantiated."""
8
+ with pytest.warns(DeprecationWarning):
9
+ assert Dummy()
@@ -0,0 +1,75 @@
1
+ import numpy
2
+ import pytest
3
+ from numpy.testing import assert_array_equal
4
+
5
+ from openfisca_core import commons
6
+
7
+
8
+ def test_apply_thresholds_when_several_inputs() -> None:
9
+ """Make a choice for any given input."""
10
+ input_ = numpy.array([4, 5, 6, 7, 8, 9, 10])
11
+ thresholds = [5, 7, 9]
12
+ choices = [10, 15, 20, 25]
13
+
14
+ result = commons.apply_thresholds(input_, thresholds, choices)
15
+
16
+ assert_array_equal(result, [10, 10, 15, 15, 20, 20, 25])
17
+
18
+
19
+ def test_apply_thresholds_when_too_many_thresholds() -> None:
20
+ """Raise an AssertionError when thresholds > choices."""
21
+ input_ = numpy.array([6])
22
+ thresholds = [5, 7, 9, 11]
23
+ choices = [10, 15, 20]
24
+
25
+ with pytest.raises(AssertionError):
26
+ assert commons.apply_thresholds(input_, thresholds, choices)
27
+
28
+
29
+ def test_apply_thresholds_when_too_many_choices() -> None:
30
+ """Raise an AssertionError when thresholds < choices - 1."""
31
+ input_ = numpy.array([6])
32
+ thresholds = [5, 7]
33
+ choices = [10, 15, 20, 25]
34
+
35
+ with pytest.raises(AssertionError):
36
+ assert commons.apply_thresholds(input_, thresholds, choices)
37
+
38
+
39
+ def test_concat_when_this_is_array_not_str() -> None:
40
+ """Cast ``this`` to ``str`` when it is a NumPy array other than string."""
41
+ this = numpy.array([1, 2])
42
+ that = numpy.array(["la", "o"])
43
+
44
+ result = commons.concat(this, that)
45
+
46
+ assert_array_equal(result, ["1la", "2o"])
47
+
48
+
49
+ def test_concat_when_that_is_array_not_str() -> None:
50
+ """Cast ``that`` to ``str`` when it is a NumPy array other than string."""
51
+ this = numpy.array(["ho", "cha"])
52
+ that = numpy.array([1, 2])
53
+
54
+ result = commons.concat(this, that)
55
+
56
+ assert_array_equal(result, ["ho1", "cha2"])
57
+
58
+
59
+ def test_concat_when_args_not_str_array_like() -> None:
60
+ """Cast ``this`` and ``that`` to a NumPy array or strings."""
61
+ this = (1, 2)
62
+ that = (3, 4)
63
+
64
+ result = commons.concat(this, that)
65
+
66
+ assert_array_equal(result, ["13", "24"])
67
+
68
+
69
+ def test_switch_when_values_are_empty() -> None:
70
+ """Raise an AssertionError when the values are empty."""
71
+ conditions = [1, 1, 1, 2]
72
+ value_by_condition = {}
73
+
74
+ with pytest.raises(AssertionError):
75
+ assert commons.switch(conditions, value_by_condition)
@@ -0,0 +1,26 @@
1
+ import math
2
+
3
+ import numpy
4
+ from numpy.testing import assert_array_equal
5
+
6
+ from openfisca_core import commons
7
+
8
+
9
+ def test_average_rate_when_varying_is_zero() -> None:
10
+ """Yield infinity when the varying gross income crosses zero."""
11
+ target = numpy.array([1, 2, 3])
12
+ varying = [0, 0, 0]
13
+
14
+ result = commons.average_rate(target, varying)
15
+
16
+ assert_array_equal(result, numpy.array([-math.inf, -math.inf, -math.inf]))
17
+
18
+
19
+ def test_marginal_rate_when_varying_is_zero() -> None:
20
+ """Yield infinity when the varying gross income crosses zero."""
21
+ target = numpy.array([1, 2, 3])
22
+ varying = numpy.array([0, 0, 0])
23
+
24
+ result = commons.marginal_rate(target, varying)
25
+
26
+ assert_array_equal(result, numpy.array([math.inf, math.inf]))
@@ -0,0 +1,7 @@
1
+ """Different storage backends for the data of a simulation."""
2
+
3
+ from . import types
4
+ from .in_memory_storage import InMemoryStorage
5
+ from .on_disk_storage import OnDiskStorage
6
+
7
+ __all__ = ["InMemoryStorage", "OnDiskStorage", "types"]