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,316 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import NoReturn, Self
4
+
5
+ import numpy
6
+
7
+ from . import types as t
8
+
9
+
10
+ class EnumArray(t.EnumArray):
11
+ """A subclass of :class:`~numpy.ndarray` of :class:`.Enum`.
12
+
13
+ :class:`.Enum` arrays are encoded as :class:`int` to improve performance.
14
+
15
+ Note:
16
+ Subclassing :class:`~numpy.ndarray` is a little tricky™. To read more
17
+ about the :meth:`.__new__` and :meth:`.__array_finalize__` methods
18
+ below, see `Subclassing ndarray`_.
19
+
20
+ Examples:
21
+ >>> import numpy
22
+
23
+ >>> from openfisca_core import indexed_enums as enum, variables
24
+
25
+ >>> class Housing(enum.Enum):
26
+ ... OWNER = "Owner"
27
+ ... TENANT = "Tenant"
28
+ ... FREE_LODGER = "Free lodger"
29
+ ... HOMELESS = "Homeless"
30
+
31
+ >>> array = numpy.array([1], dtype=numpy.int16)
32
+ >>> enum_array = enum.EnumArray(array, Housing)
33
+
34
+ >>> repr(enum.EnumArray)
35
+ "<class 'openfisca_core.indexed_enums.enum_array.EnumArray'>"
36
+
37
+ >>> repr(enum_array)
38
+ 'EnumArray([Housing.TENANT])'
39
+
40
+ >>> str(enum_array)
41
+ "['TENANT']"
42
+
43
+ >>> list(map(int, enum_array))
44
+ [1]
45
+
46
+ >>> int(enum_array[0])
47
+ 1
48
+
49
+ >>> enum_array[0] in enum_array
50
+ True
51
+
52
+ >>> len(enum_array)
53
+ 1
54
+
55
+ >>> enum_array = enum.EnumArray(list(Housing), Housing)
56
+ Traceback (most recent call last):
57
+ AttributeError: 'list' object has no attribute 'view'
58
+
59
+ >>> class OccupancyStatus(variables.Variable):
60
+ ... value_type = enum.Enum
61
+ ... possible_values = Housing
62
+
63
+ >>> enum.EnumArray(array, OccupancyStatus.possible_values)
64
+ EnumArray([Housing.TENANT])
65
+
66
+ .. _Subclassing ndarray:
67
+ https://numpy.org/doc/stable/user/basics.subclassing.html
68
+
69
+ """
70
+
71
+ #: Enum type of the array items.
72
+ possible_values: None | type[t.Enum]
73
+
74
+ def __new__(
75
+ cls,
76
+ input_array: t.IndexArray,
77
+ possible_values: type[t.Enum],
78
+ ) -> Self:
79
+ """See comment above."""
80
+ obj = input_array.view(cls)
81
+ obj.possible_values = possible_values
82
+ return obj
83
+
84
+ def __array_finalize__(self, obj: None | t.EnumArray | t.VarArray) -> None:
85
+ """See comment above."""
86
+ if obj is None:
87
+ return
88
+ self.possible_values = getattr(obj, "possible_values", None)
89
+
90
+ def __eq__(self, other: object) -> t.BoolArray: # type: ignore[override]
91
+ """Compare equality with the item's :attr:`~.Enum.index`.
92
+
93
+ When comparing to an item of :attr:`.possible_values`, use the
94
+ item's :attr:`~.Enum.index`. to speed up the comparison.
95
+
96
+ Whenever possible, use :any:`numpy.ndarray.view` so that the result is
97
+ a classic :class:`~numpy.ndarray`, not an :obj:`.EnumArray`.
98
+
99
+ Args:
100
+ other: Another :class:`object` to compare to.
101
+
102
+ Returns:
103
+ bool: When ???
104
+ ndarray[bool_]: When ???
105
+
106
+ Examples:
107
+ >>> import numpy
108
+
109
+ >>> from openfisca_core import indexed_enums as enum
110
+
111
+ >>> class Housing(enum.Enum):
112
+ ... OWNER = "Owner"
113
+ ... TENANT = "Tenant"
114
+
115
+ >>> array = numpy.array([1])
116
+ >>> enum_array = enum.EnumArray(array, Housing)
117
+
118
+ >>> enum_array == Housing
119
+ array([False, True])
120
+
121
+ >>> enum_array == Housing.TENANT
122
+ array([ True])
123
+
124
+ >>> enum_array == 1
125
+ array([ True])
126
+
127
+ >>> enum_array == [1]
128
+ array([ True])
129
+
130
+ >>> enum_array == [2]
131
+ array([False])
132
+
133
+ >>> enum_array == "1"
134
+ array([False])
135
+
136
+ >>> enum_array is None
137
+ False
138
+
139
+ >>> enum_array == enum.EnumArray(numpy.array([1]), Housing)
140
+ array([ True])
141
+
142
+ Note:
143
+ This breaks the `Liskov substitution principle`_.
144
+
145
+ .. _Liskov substitution principle:
146
+ https://en.wikipedia.org/wiki/Liskov_substitution_principle
147
+
148
+ """
149
+ result: t.BoolArray
150
+
151
+ if self.possible_values is None:
152
+ return NotImplemented
153
+ if other is None:
154
+ return NotImplemented
155
+ if isinstance(other, type(t.Enum)) and other == self.possible_values:
156
+ result = (
157
+ self.view(numpy.ndarray)
158
+ == self.possible_values.indices[
159
+ self.possible_values.indices <= max(self)
160
+ ]
161
+ )
162
+ return result
163
+ if isinstance(other, t.Enum) and other.__class__ == self.possible_values:
164
+ result = self.view(numpy.ndarray) == other.index
165
+ return result
166
+ # For NumPy >=1.26.x.
167
+ if isinstance(is_equal := self.view(numpy.ndarray) == other, numpy.ndarray):
168
+ return is_equal
169
+ # For NumPy <1.26.x.
170
+ return numpy.array([is_equal], dtype=t.BoolDType)
171
+
172
+ def __ne__(self, other: object) -> t.BoolArray: # type: ignore[override]
173
+ """Inequality.
174
+
175
+ Args:
176
+ other: Another :class:`object` to compare to.
177
+
178
+ Returns:
179
+ bool: When ???
180
+ ndarray[bool_]: When ???
181
+
182
+ Examples:
183
+ >>> import numpy
184
+
185
+ >>> from openfisca_core import indexed_enums as enum
186
+
187
+ >>> class Housing(enum.Enum):
188
+ ... OWNER = "Owner"
189
+ ... TENANT = "Tenant"
190
+
191
+ >>> array = numpy.array([1])
192
+ >>> enum_array = enum.EnumArray(array, Housing)
193
+
194
+ >>> enum_array != Housing
195
+ array([ True, False])
196
+
197
+ >>> enum_array != Housing.TENANT
198
+ array([False])
199
+
200
+ >>> enum_array != 1
201
+ array([False])
202
+
203
+ >>> enum_array != [1]
204
+ array([False])
205
+
206
+ >>> enum_array != [2]
207
+ array([ True])
208
+
209
+ >>> enum_array != "1"
210
+ array([ True])
211
+
212
+ >>> enum_array is not None
213
+ True
214
+
215
+ Note:
216
+ This breaks the `Liskov substitution principle`_.
217
+
218
+ .. _Liskov substitution principle:
219
+ https://en.wikipedia.org/wiki/Liskov_substitution_principle
220
+
221
+ """
222
+ return numpy.logical_not(self == other)
223
+
224
+ @staticmethod
225
+ def _forbidden_operation(*__args: object, **__kwds: object) -> NoReturn:
226
+ msg = (
227
+ "Forbidden operation. The only operations allowed on EnumArrays "
228
+ "are '==' and '!='."
229
+ )
230
+ raise TypeError(msg)
231
+
232
+ __add__ = _forbidden_operation
233
+ __mul__ = _forbidden_operation
234
+ __lt__ = _forbidden_operation
235
+ __le__ = _forbidden_operation
236
+ __gt__ = _forbidden_operation
237
+ __ge__ = _forbidden_operation
238
+ __and__ = _forbidden_operation
239
+ __or__ = _forbidden_operation
240
+
241
+ def decode(self) -> t.ObjArray:
242
+ """Decode itself to a normal array.
243
+
244
+ Returns:
245
+ ndarray[Enum]: The items of the :obj:`.EnumArray`.
246
+
247
+ Raises:
248
+ TypeError: When the :attr:`.possible_values` is not defined.
249
+
250
+ Examples:
251
+ >>> import numpy
252
+
253
+ >>> from openfisca_core import indexed_enums as enum
254
+
255
+ >>> class Housing(enum.Enum):
256
+ ... OWNER = "Owner"
257
+ ... TENANT = "Tenant"
258
+
259
+ >>> array = numpy.array([1])
260
+ >>> enum_array = enum.EnumArray(array, Housing)
261
+ >>> enum_array.decode()
262
+ array([Housing.TENANT], dtype=object)
263
+
264
+ """
265
+ result: t.ObjArray
266
+ if self.possible_values is None:
267
+ msg = (
268
+ f"The possible values of the {self.__class__.__name__} are not defined."
269
+ )
270
+ raise TypeError(msg)
271
+ array = self.reshape(1).astype(t.EnumDType) if self.ndim == 0 else self
272
+ result = self.possible_values.enums[array]
273
+ return result
274
+
275
+ def decode_to_str(self) -> t.StrArray:
276
+ """Decode itself to an array of strings.
277
+
278
+ Returns:
279
+ ndarray[str_]: The string values of the :obj:`.EnumArray`.
280
+
281
+ Raises:
282
+ TypeError: When the :attr:`.possible_values` is not defined.
283
+
284
+ Examples:
285
+ >>> import numpy
286
+
287
+ >>> from openfisca_core import indexed_enums as enum
288
+
289
+ >>> class Housing(enum.Enum):
290
+ ... OWNER = "Owner"
291
+ ... TENANT = "Tenant"
292
+
293
+ >>> array = numpy.array([1])
294
+ >>> enum_array = enum.EnumArray(array, Housing)
295
+ >>> enum_array.decode_to_str()
296
+ array(['TENANT'], dtype='<U6')
297
+
298
+ """
299
+ result: t.StrArray
300
+ if self.possible_values is None:
301
+ msg = (
302
+ f"The possible values of the {self.__class__.__name__} are not defined."
303
+ )
304
+ raise TypeError(msg)
305
+ array = self.reshape(1).astype(t.EnumDType) if self.ndim == 0 else self
306
+ result = self.possible_values.names[array]
307
+ return result
308
+
309
+ def __repr__(self) -> str:
310
+ return f"{self.__class__.__name__}({self.decode()!s})"
311
+
312
+ def __str__(self) -> str:
313
+ return str(self.decode_to_str())
314
+
315
+
316
+ __all__ = ["EnumArray"]
File without changes
File without changes
@@ -0,0 +1,135 @@
1
+ import numpy
2
+ import pytest
3
+ from numpy.testing import assert_array_equal
4
+
5
+ from openfisca_core import indexed_enums as enum
6
+
7
+
8
+ class Animal(enum.Enum):
9
+ CAT = b"Cat"
10
+ DOG = b"Dog"
11
+
12
+
13
+ class Colour(enum.Enum):
14
+ INCARNADINE = "incarnadine"
15
+ TURQUOISE = "turquoise"
16
+ AMARANTH = "amaranth"
17
+
18
+
19
+ # Arrays of Enum
20
+
21
+
22
+ def test_enum_encode_with_array_of_enum():
23
+ """Does encode when called with an array of enums."""
24
+ array = numpy.array([Animal.DOG, Animal.DOG, Animal.CAT])
25
+ enum_array = Animal.encode(array)
26
+ assert_array_equal(enum_array, numpy.array([1, 1, 0]))
27
+
28
+
29
+ def test_enum_encode_with_enum_sequence():
30
+ """Does encode when called with an enum sequence."""
31
+ sequence = list(Animal)
32
+ enum_array = Animal.encode(sequence)
33
+ assert Animal.DOG in enum_array
34
+
35
+
36
+ def test_enum_encode_with_enum_scalar_array():
37
+ """Does not encode when called with an enum scalar array."""
38
+ array = numpy.array(Animal.DOG)
39
+ with pytest.raises(TypeError):
40
+ Animal.encode(array)
41
+
42
+
43
+ def test_enum_encode_with_enum_with_bad_value():
44
+ """Does not encode when called with a value not in an Enum."""
45
+ array = numpy.array([Colour.AMARANTH])
46
+ with pytest.raises(TypeError):
47
+ Animal.encode(array)
48
+
49
+
50
+ # Arrays of int
51
+
52
+
53
+ def test_enum_encode_with_array_of_int():
54
+ """Does encode when called with an array of int."""
55
+ array = numpy.array([1, 1, 0])
56
+ enum_array = Animal.encode(array)
57
+ assert_array_equal(enum_array, numpy.array([1, 1, 0]))
58
+
59
+
60
+ def test_enum_encode_with_int_sequence():
61
+ """Does encode when called with an int sequence."""
62
+ sequence = (0, 1)
63
+ enum_array = Animal.encode(sequence)
64
+ assert Animal.DOG in enum_array
65
+
66
+
67
+ def test_enum_encode_with_int_scalar_array():
68
+ """Does not encode when called with an int scalar array."""
69
+ array = numpy.array(1)
70
+ with pytest.raises(TypeError):
71
+ Animal.encode(array)
72
+
73
+
74
+ def test_enum_encode_with_int_with_bad_value():
75
+ """Does not encode when called with a value not in an Enum."""
76
+ array = numpy.array([2])
77
+ with pytest.raises(IndexError):
78
+ Animal.encode(array)
79
+
80
+
81
+ # Arrays of strings
82
+
83
+
84
+ def test_enum_encode_with_array_of_string():
85
+ """Does encode when called with an array of string."""
86
+ array = numpy.array(["DOG", "DOG", "CAT"])
87
+ enum_array = Animal.encode(array)
88
+ assert_array_equal(enum_array, numpy.array([1, 1, 0]))
89
+
90
+
91
+ def test_enum_encode_with_str_sequence():
92
+ """Does encode when called with a str sequence."""
93
+ sequence = ("DOG", "CAT")
94
+ enum_array = Animal.encode(sequence)
95
+ assert Animal.DOG in enum_array
96
+
97
+
98
+ def test_enum_encode_with_str_scalar_array():
99
+ """Does not encode when called with a str scalar array."""
100
+ array = numpy.array("DOG")
101
+ with pytest.raises(TypeError):
102
+ Animal.encode(array)
103
+
104
+
105
+ def test_enum_encode_with_str_with_bad_value():
106
+ """Encode encode when called with a value not in an Enum."""
107
+ array = numpy.array(["JAIBA"])
108
+ with pytest.raises(IndexError):
109
+ Animal.encode(array)
110
+
111
+
112
+ # Unsupported encodings
113
+
114
+
115
+ def test_enum_encode_with_any_array():
116
+ """Does not encode when called with unsupported types."""
117
+ value = {"animal": "dog"}
118
+ array = numpy.array([value])
119
+ with pytest.raises(TypeError):
120
+ Animal.encode(array)
121
+
122
+
123
+ def test_enum_encode_with_any_scalar_array():
124
+ """Does not encode when called with unsupported types."""
125
+ value = 1.5
126
+ array = numpy.array(value)
127
+ with pytest.raises(TypeError):
128
+ Animal.encode(array)
129
+
130
+
131
+ def test_enum_encode_with_any_sequence():
132
+ """Does not encode when called with unsupported types."""
133
+ sequence = memoryview(b"DOG")
134
+ with pytest.raises(IndexError):
135
+ Animal.encode(sequence)
@@ -0,0 +1,30 @@
1
+ import numpy
2
+ import pytest
3
+
4
+ from openfisca_core import indexed_enums as enum
5
+
6
+
7
+ class Fruit(enum.Enum):
8
+ APPLE = b"apple"
9
+ BERRY = b"berry"
10
+
11
+
12
+ @pytest.fixture
13
+ def enum_array():
14
+ return enum.EnumArray(numpy.array([1]), Fruit)
15
+
16
+
17
+ def test_enum_array_eq_operation(enum_array):
18
+ """The equality operation is permitted."""
19
+ assert enum_array == enum.EnumArray(numpy.array([1]), Fruit)
20
+
21
+
22
+ def test_enum_array_ne_operation(enum_array):
23
+ """The non-equality operation is permitted."""
24
+ assert enum_array != enum.EnumArray(numpy.array([0]), Fruit)
25
+
26
+
27
+ def test_enum_array_any_other_operation(enum_array):
28
+ """Only equality and non-equality operations are permitted."""
29
+ with pytest.raises(TypeError, match="Forbidden operation."):
30
+ enum_array * 1
@@ -0,0 +1,49 @@
1
+ from enum import _EnumDict as EnumDict
2
+ from typing import TypeAlias
3
+
4
+ from numpy import (
5
+ bool_ as BoolDType,
6
+ )
7
+ from numpy import (
8
+ generic as VarDType,
9
+ )
10
+ from numpy import (
11
+ int32 as IntDType,
12
+ )
13
+ from numpy import (
14
+ object_ as ObjDType,
15
+ )
16
+ from numpy import (
17
+ str_ as StrDType,
18
+ )
19
+
20
+ from openfisca_core.types import Array, ArrayLike, DTypeLike, Enum, EnumArray, EnumType
21
+
22
+ from .config import ENUM_ARRAY_DTYPE as EnumDType
23
+
24
+ #: Type for enum indices arrays.
25
+ IndexArray: TypeAlias = Array[EnumDType]
26
+
27
+ #: Type for boolean arrays.
28
+ BoolArray: TypeAlias = Array[BoolDType]
29
+
30
+ #: Type for int arrays.
31
+ IntArray: TypeAlias = Array[IntDType]
32
+
33
+ #: Type for str arrays.
34
+ StrArray: TypeAlias = Array[StrDType]
35
+
36
+ #: Type for object arrays.
37
+ ObjArray: TypeAlias = Array[ObjDType]
38
+
39
+ #: Type for generic arrays.
40
+ VarArray: TypeAlias = Array[VarDType]
41
+
42
+ __all__ = [
43
+ "ArrayLike",
44
+ "DTypeLike",
45
+ "Enum",
46
+ "EnumArray",
47
+ "EnumDict",
48
+ "EnumType",
49
+ ]
@@ -0,0 +1,9 @@
1
+ # The memory config module has been deprecated since X.X.X,
2
+ # and will be removed in the future.
3
+ #
4
+ # Module's contents have been moved to the experimental module.
5
+ #
6
+ # The following are transitional imports to ensure non-breaking changes.
7
+ # Could be deprecated in the next major release.
8
+
9
+ from openfisca_core.experimental import MemoryConfig # noqa: F401
@@ -0,0 +1,71 @@
1
+ from datetime import date
2
+
3
+ from numpy import (
4
+ logical_not as not_,
5
+ )
6
+ from numpy import (
7
+ maximum as max_,
8
+ )
9
+ from numpy import (
10
+ minimum as min_,
11
+ )
12
+ from numpy import (
13
+ round as round_,
14
+ )
15
+ from numpy import (
16
+ select,
17
+ where,
18
+ )
19
+
20
+ from openfisca_core.commons import apply_thresholds, concat, switch
21
+ from openfisca_core.holders import (
22
+ set_input_dispatch_by_period,
23
+ set_input_divide_by_period,
24
+ )
25
+ from openfisca_core.indexed_enums import Enum
26
+ from openfisca_core.parameters import (
27
+ Bracket,
28
+ Parameter,
29
+ ParameterNode,
30
+ Scale,
31
+ ValuesHistory,
32
+ load_parameter_file,
33
+ )
34
+ from openfisca_core.periods import DAY, ETERNITY, MONTH, YEAR, period
35
+ from openfisca_core.populations import ADD, DIVIDE
36
+ from openfisca_core.reforms import Reform
37
+ from openfisca_core.simulations import calculate_output_add, calculate_output_divide
38
+ from openfisca_core.variables import Variable
39
+
40
+ __all__ = [
41
+ "ADD",
42
+ "DAY",
43
+ "DIVIDE",
44
+ "ETERNITY",
45
+ "MONTH",
46
+ "YEAR",
47
+ "Bracket",
48
+ "Enum",
49
+ "Parameter",
50
+ "ParameterNode",
51
+ "Reform",
52
+ "Scale",
53
+ "ValuesHistory",
54
+ "Variable",
55
+ "apply_thresholds",
56
+ "calculate_output_add",
57
+ "calculate_output_divide",
58
+ "concat",
59
+ "date",
60
+ "load_parameter_file",
61
+ "max_",
62
+ "min_",
63
+ "not_",
64
+ "period",
65
+ "round_",
66
+ "select",
67
+ "set_input_dispatch_by_period",
68
+ "set_input_divide_by_period",
69
+ "switch",
70
+ "where",
71
+ ]
@@ -0,0 +1,71 @@
1
+ # Transitional imports to ensure non-breaking changes.
2
+ # Could be deprecated in the next major release.
3
+ #
4
+ # How imports are being used today:
5
+ #
6
+ # >>> from openfisca_core.module import symbol
7
+ #
8
+ # The previous example provokes cyclic dependency problems
9
+ # that prevent us from modularizing the different components
10
+ # of the library so to make them easier to test and to maintain.
11
+ #
12
+ # How could them be used after the next major release:
13
+ #
14
+ # >>> from openfisca_core import module
15
+ # >>> module.symbol()
16
+ #
17
+ # And for classes:
18
+ #
19
+ # >>> from openfisca_core.module import Symbol
20
+ # >>> Symbol()
21
+ #
22
+ # See: https://www.python.org/dev/peps/pep-0008/#imports
23
+
24
+ from openfisca_core.errors import ParameterNotFound, ParameterParsingError
25
+
26
+ from .at_instant_like import AtInstantLike
27
+ from .config import (
28
+ ALLOWED_PARAM_TYPES,
29
+ COMMON_KEYS,
30
+ FILE_EXTENSIONS,
31
+ date_constructor,
32
+ dict_no_duplicate_constructor,
33
+ )
34
+ from .helpers import contains_nan, load_parameter_file
35
+ from .parameter import Parameter
36
+ from .parameter_at_instant import ParameterAtInstant
37
+ from .parameter_node import ParameterNode
38
+ from .parameter_node_at_instant import ParameterNodeAtInstant
39
+ from .parameter_scale import ParameterScale
40
+ from .parameter_scale import ParameterScale as Scale
41
+ from .parameter_scale_bracket import (
42
+ ParameterScaleBracket,
43
+ )
44
+ from .parameter_scale_bracket import (
45
+ ParameterScaleBracket as Bracket,
46
+ )
47
+ from .values_history import ValuesHistory
48
+ from .vectorial_parameter_node_at_instant import VectorialParameterNodeAtInstant
49
+
50
+ __all__ = [
51
+ "ALLOWED_PARAM_TYPES",
52
+ "COMMON_KEYS",
53
+ "FILE_EXTENSIONS",
54
+ "AtInstantLike",
55
+ "Bracket",
56
+ "Parameter",
57
+ "ParameterAtInstant",
58
+ "ParameterNode",
59
+ "ParameterNodeAtInstant",
60
+ "ParameterNotFound",
61
+ "ParameterParsingError",
62
+ "ParameterScale",
63
+ "ParameterScaleBracket",
64
+ "Scale",
65
+ "ValuesHistory",
66
+ "VectorialParameterNodeAtInstant",
67
+ "contains_nan",
68
+ "date_constructor",
69
+ "dict_no_duplicate_constructor",
70
+ "load_parameter_file",
71
+ ]
@@ -0,0 +1,17 @@
1
+ import abc
2
+
3
+ from openfisca_core import periods
4
+
5
+
6
+ class AtInstantLike(abc.ABC):
7
+ """Base class for various types of parameters implementing the at instant protocol."""
8
+
9
+ def __call__(self, instant):
10
+ return self.get_at_instant(instant)
11
+
12
+ def get_at_instant(self, instant):
13
+ instant = str(periods.instant(instant))
14
+ return self._get_at_instant(instant)
15
+
16
+ @abc.abstractmethod
17
+ def _get_at_instant(self, instant): ...