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,209 @@
1
+ from __future__ import annotations
2
+
3
+ from typing import Final
4
+
5
+ import numpy
6
+ from typing_extensions import TypeIs
7
+
8
+ from . import types as t
9
+
10
+ #: Types for int arrays.
11
+ ints: Final = {
12
+ numpy.uint8,
13
+ numpy.uint16,
14
+ numpy.uint32,
15
+ numpy.uint64,
16
+ numpy.int8,
17
+ numpy.int16,
18
+ numpy.int32,
19
+ numpy.int64,
20
+ }
21
+
22
+ #: Types for object arrays.
23
+ objs: Final = {numpy.object_}
24
+
25
+ #: Types for str arrays.
26
+ strs: Final = {numpy.str_}
27
+
28
+
29
+ def _is_enum_array(array: t.VarArray) -> TypeIs[t.ObjArray]:
30
+ """Narrow the type of a given array to an array of :obj:`numpy.object_`.
31
+
32
+ Args:
33
+ array: Array to check.
34
+
35
+ Returns:
36
+ bool: True if ``array`` is an array of :obj:`numpy.object_`, False otherwise.
37
+
38
+ Examples:
39
+ >>> import numpy
40
+
41
+ >>> from openfisca_core import indexed_enums as enum
42
+
43
+ >>> Enum = enum.Enum("Enum", ["A", "B"])
44
+ >>> array = numpy.array([Enum.A], dtype=numpy.object_)
45
+ >>> _is_enum_array(array)
46
+ True
47
+
48
+ >>> array = numpy.array([1.0])
49
+ >>> _is_enum_array(array)
50
+ False
51
+
52
+ """
53
+ return array.dtype.type in objs
54
+
55
+
56
+ def _is_enum_array_like(
57
+ array: t.VarArray | t.ArrayLike[object],
58
+ ) -> TypeIs[t.ArrayLike[t.Enum]]:
59
+ """Narrow the type of a given array-like to an sequence of :class:`.Enum`.
60
+
61
+ Args:
62
+ array: Array to check.
63
+
64
+ Returns:
65
+ bool: True if ``array`` is an array-like of :class:`.Enum`, False otherwise.
66
+
67
+ Examples:
68
+ >>> from openfisca_core import indexed_enums as enum
69
+
70
+ >>> class Housing(enum.Enum):
71
+ ... OWNER = "owner"
72
+ ... TENANT = "tenant"
73
+
74
+ >>> array = [Housing.OWNER]
75
+ >>> _is_enum_array_like(array)
76
+ True
77
+
78
+ >>> array = ["owner"]
79
+ >>> _is_enum_array_like(array)
80
+ False
81
+
82
+ """
83
+ return all(isinstance(item, t.Enum) for item in array)
84
+
85
+
86
+ def _is_int_array(array: t.VarArray) -> TypeIs[t.IndexArray]:
87
+ """Narrow the type of a given array to an array of :obj:`numpy.integer`.
88
+
89
+ Args:
90
+ array: Array to check.
91
+
92
+ Returns:
93
+ bool: True if ``array`` is an array of :obj:`numpy.integer`, False otherwise.
94
+
95
+ Examples:
96
+ >>> import numpy
97
+
98
+ >>> array = numpy.array([1], dtype=numpy.int16)
99
+ >>> _is_int_array(array)
100
+ True
101
+
102
+ >>> array = numpy.array([1], dtype=numpy.int32)
103
+ >>> _is_int_array(array)
104
+ True
105
+
106
+ >>> array = numpy.array([1.0])
107
+ >>> _is_int_array(array)
108
+ False
109
+
110
+ """
111
+ return array.dtype.type in ints
112
+
113
+
114
+ def _is_int_array_like(
115
+ array: t.VarArray | t.ArrayLike[object],
116
+ ) -> TypeIs[t.ArrayLike[int]]:
117
+ """Narrow the type of a given array-like to a sequence of :obj:`int`.
118
+
119
+ Args:
120
+ array: Array to check.
121
+
122
+ Returns:
123
+ bool: True if ``array`` is an array-like of :obj:`int`, False otherwise.
124
+
125
+ Examples:
126
+ >>> array = [1]
127
+ >>> _is_int_array_like(array)
128
+ True
129
+
130
+ >>> array = (1, 2)
131
+ >>> _is_int_array_like(array)
132
+ True
133
+
134
+ >>> array = [1.0]
135
+ >>> _is_int_array_like(array)
136
+ False
137
+
138
+ """
139
+ return all(isinstance(item, int) for item in array)
140
+
141
+
142
+ def _is_str_array(array: t.VarArray) -> TypeIs[t.StrArray]:
143
+ """Narrow the type of a given array to an array of :obj:`numpy.str_`.
144
+
145
+ Args:
146
+ array: Array to check.
147
+
148
+ Returns:
149
+ bool: True if ``array`` is an array of :obj:`numpy.str_`, False otherwise.
150
+
151
+ Examples:
152
+ >>> import numpy
153
+
154
+ >>> from openfisca_core import indexed_enums as enum
155
+
156
+ >>> class Housing(enum.Enum):
157
+ ... OWNER = "owner"
158
+ ... TENANT = "tenant"
159
+
160
+ >>> array = numpy.array([Housing.OWNER])
161
+ >>> _is_str_array(array)
162
+ False
163
+
164
+ >>> array = numpy.array(["owner"])
165
+ >>> _is_str_array(array)
166
+ True
167
+
168
+ """
169
+ return array.dtype.type in strs
170
+
171
+
172
+ def _is_str_array_like(
173
+ array: t.VarArray | t.ArrayLike[object],
174
+ ) -> TypeIs[t.ArrayLike[str]]:
175
+ """Narrow the type of a given array-like to an sequence of :obj:`str`.
176
+
177
+ Args:
178
+ array: Array to check.
179
+
180
+ Returns:
181
+ bool: True if ``array`` is an array-like of :obj:`str`, False otherwise.
182
+
183
+ Examples:
184
+ >>> from openfisca_core import indexed_enums as enum
185
+
186
+ >>> class Housing(enum.Enum):
187
+ ... OWNER = "owner"
188
+ ... TENANT = "tenant"
189
+
190
+ >>> array = [Housing.OWNER]
191
+ >>> _is_str_array_like(array)
192
+ False
193
+
194
+ >>> array = ["owner"]
195
+ >>> _is_str_array_like(array)
196
+ True
197
+
198
+ """
199
+ return all(isinstance(item, str) for item in array)
200
+
201
+
202
+ __all__ = [
203
+ "_is_enum_array",
204
+ "_is_enum_array_like",
205
+ "_is_int_array",
206
+ "_is_int_array_like",
207
+ "_is_str_array",
208
+ "_is_str_array_like",
209
+ ]
@@ -0,0 +1,180 @@
1
+ from __future__ import annotations
2
+
3
+ import numpy
4
+
5
+ from . import types as t
6
+
7
+
8
+ def _enum_to_index(value: t.ObjArray | t.ArrayLike[t.Enum]) -> t.IndexArray:
9
+ """Transform an array of enum members into an index array.
10
+
11
+ Args:
12
+ value: The enum members array to encode.
13
+
14
+ Returns:
15
+ The index array.
16
+
17
+ Examples:
18
+ >>> import numpy
19
+
20
+ >>> from openfisca_core import indexed_enums as enum
21
+
22
+ >>> class Road(enum.Enum):
23
+ ... STREET = (
24
+ ... "A public road that connects two points, but also has "
25
+ ... "buildings on both sides of it; these typically run "
26
+ ... "perpendicular to avenues."
27
+ ... )
28
+ ... AVENUE = (
29
+ ... "A public way that also has buildings and/or trees on both "
30
+ ... "sides; these run perpendicular to streets and are "
31
+ ... "traditionally wider."
32
+ ... )
33
+
34
+ >>> class Rogue(enum.Enum):
35
+ ... BOULEVARD = "More like a shady impasse, to be honest."
36
+
37
+ >>> _enum_to_index(Road.AVENUE)
38
+ Traceback (most recent call last):
39
+ TypeError: 'Road' object is not iterable
40
+
41
+ >>> _enum_to_index([Road.AVENUE])
42
+ array([1], dtype=int16)
43
+
44
+ >>> _enum_to_index(numpy.array(Road.AVENUE))
45
+ Traceback (most recent call last):
46
+ TypeError: iteration over a 0-d array
47
+
48
+ >>> _enum_to_index(numpy.array([Road.AVENUE]))
49
+ array([1], dtype=int16)
50
+
51
+ >>> value = numpy.array([Road.STREET, Road.AVENUE, Road.STREET])
52
+ >>> _enum_to_index(value)
53
+ array([0, 1, 0], dtype=int16)
54
+
55
+ >>> value = numpy.array([Road.AVENUE, Road.AVENUE, Rogue.BOULEVARD])
56
+ >>> _enum_to_index(value)
57
+ array([1, 1, 0], dtype=int16)
58
+
59
+ """
60
+ return numpy.array([enum.index for enum in value], t.EnumDType)
61
+
62
+
63
+ def _int_to_index(
64
+ enum_class: type[t.Enum], value: t.IndexArray | t.ArrayLike[int]
65
+ ) -> t.IndexArray:
66
+ """Transform an integer array into an index array.
67
+
68
+ Args:
69
+ enum_class: The enum class to encode the integer array.
70
+ value: The integer array to encode.
71
+
72
+ Returns:
73
+ The index array.
74
+
75
+ Examples:
76
+ >>> from array import array
77
+
78
+ >>> import numpy
79
+
80
+ >>> from openfisca_core import indexed_enums as enum
81
+
82
+ >>> class Road(enum.Enum):
83
+ ... STREET = (
84
+ ... "A public road that connects two points, but also has "
85
+ ... "buildings on both sides of it; these typically run "
86
+ ... "perpendicular to avenues."
87
+ ... )
88
+ ... AVENUE = (
89
+ ... "A public way that also has buildings and/or trees on both "
90
+ ... "sides; these run perpendicular to streets and are "
91
+ ... "traditionally wider."
92
+ ... )
93
+
94
+ >>> _int_to_index(Road, 1)
95
+ array([1], dtype=int16)
96
+
97
+ >>> _int_to_index(Road, [1])
98
+ array([1], dtype=int16)
99
+
100
+ >>> _int_to_index(Road, array("B", [1]))
101
+ array([1], dtype=int16)
102
+
103
+ >>> _int_to_index(Road, memoryview(array("B", [1])))
104
+ array([1], dtype=int16)
105
+
106
+ >>> _int_to_index(Road, numpy.array(1))
107
+ array([1], dtype=int16)
108
+
109
+ >>> _int_to_index(Road, numpy.array([1]))
110
+ array([1], dtype=int16)
111
+
112
+ >>> _int_to_index(Road, numpy.array([0, 1, 0]))
113
+ array([0, 1, 0], dtype=int16)
114
+
115
+ >>> _int_to_index(Road, numpy.array([1, 1, 2]))
116
+ array([1, 1], dtype=int16)
117
+
118
+ """
119
+ indices = enum_class.indices
120
+ values = numpy.asarray(value)
121
+ return values[values < indices.size].astype(t.EnumDType)
122
+
123
+
124
+ def _str_to_index(
125
+ enum_class: type[t.Enum], value: t.StrArray | t.ArrayLike[str]
126
+ ) -> t.IndexArray:
127
+ """Transform a string array into an index array.
128
+
129
+ Args:
130
+ enum_class: The enum class to encode the string array.
131
+ value: The string array to encode.
132
+
133
+ Returns:
134
+ The index array.
135
+
136
+ Examples:
137
+ >>> import numpy
138
+
139
+ >>> from openfisca_core import indexed_enums as enum
140
+
141
+ >>> class Road(enum.Enum):
142
+ ... STREET = (
143
+ ... "A public road that connects two points, but also has "
144
+ ... "buildings on both sides of it; these typically run "
145
+ ... "perpendicular to avenues."
146
+ ... )
147
+ ... AVENUE = (
148
+ ... "A public way that also has buildings and/or trees on both "
149
+ ... "sides; these run perpendicular to streets and are "
150
+ ... "traditionally wider."
151
+ ... )
152
+
153
+ >>> _str_to_index(Road, "AVENUE")
154
+ array([1], dtype=int16)
155
+
156
+ >>> _str_to_index(Road, ["AVENUE"])
157
+ array([1], dtype=int16)
158
+
159
+ >>> _str_to_index(Road, numpy.array("AVENUE"))
160
+ array([1], dtype=int16)
161
+
162
+ >>> _str_to_index(Road, numpy.array(["AVENUE"]))
163
+ array([1], dtype=int16)
164
+
165
+ >>> _str_to_index(Road, numpy.array(["STREET", "AVENUE", "STREET"]))
166
+ array([0, 1, 0], dtype=int16)
167
+
168
+ >>> _str_to_index(Road, numpy.array(["AVENUE", "AVENUE", "BOULEVARD"]))
169
+ array([1, 1], dtype=int16)
170
+
171
+ """
172
+ values = numpy.asarray(value)
173
+ names = enum_class.names
174
+ mask = numpy.isin(values, names)
175
+ sorter = numpy.argsort(names)
176
+ result = sorter[numpy.searchsorted(names, values[mask], sorter=sorter)]
177
+ return result.astype(t.EnumDType)
178
+
179
+
180
+ __all__ = ["_enum_to_index", "_int_to_index", "_str_to_index"]
@@ -0,0 +1,6 @@
1
+ import numpy
2
+
3
+ ENUM_ARRAY_DTYPE = numpy.int16
4
+
5
+
6
+ __all__ = ["ENUM_ARRAY_DTYPE"]
@@ -0,0 +1,218 @@
1
+ from __future__ import annotations
2
+
3
+ from collections.abc import Sequence
4
+
5
+ import numpy
6
+
7
+ from . import types as t
8
+ from ._enum_type import EnumType
9
+ from ._errors import EnumEncodingError, EnumMemberNotFoundError
10
+ from ._guards import (
11
+ _is_enum_array,
12
+ _is_enum_array_like,
13
+ _is_int_array,
14
+ _is_int_array_like,
15
+ _is_str_array,
16
+ _is_str_array_like,
17
+ )
18
+ from ._utils import _enum_to_index, _int_to_index, _str_to_index
19
+ from .enum_array import EnumArray
20
+
21
+
22
+ class Enum(t.Enum, metaclass=EnumType):
23
+ """Enum based on `enum34 <https://pypi.python.org/pypi/enum34/>`_.
24
+
25
+ Its items have an :class:`int` index, useful and performant when running
26
+ :mod:`~openfisca_core.simulations` on large :mod:`~openfisca_core.populations`.
27
+
28
+ Examples:
29
+ >>> from openfisca_core import indexed_enums as enum
30
+
31
+ >>> class Housing(enum.Enum):
32
+ ... OWNER = "Owner"
33
+ ... TENANT = "Tenant"
34
+ ... FREE_LODGER = "Free lodger"
35
+ ... HOMELESS = "Homeless"
36
+
37
+ >>> repr(Housing)
38
+ "<enum 'Housing'>"
39
+
40
+ >>> repr(Housing.TENANT)
41
+ 'Housing.TENANT'
42
+
43
+ >>> str(Housing.TENANT)
44
+ 'Housing.TENANT'
45
+
46
+ >>> dict([(Housing.TENANT, Housing.TENANT.value)])
47
+ {Housing.TENANT: 'Tenant'}
48
+
49
+ >>> list(Housing)
50
+ [Housing.OWNER, Housing.TENANT, Housing.FREE_LODGER, Housing.HOMELESS]
51
+
52
+ >>> Housing["TENANT"]
53
+ Housing.TENANT
54
+
55
+ >>> Housing("Tenant")
56
+ Housing.TENANT
57
+
58
+ >>> Housing.TENANT in Housing
59
+ True
60
+
61
+ >>> len(Housing)
62
+ 4
63
+
64
+ >>> Housing.TENANT == Housing.TENANT
65
+ True
66
+
67
+ >>> Housing.TENANT != Housing.TENANT
68
+ False
69
+
70
+ >>> Housing.TENANT.index
71
+ 1
72
+
73
+ >>> Housing.TENANT.name
74
+ 'TENANT'
75
+
76
+ >>> Housing.TENANT.value
77
+ 'Tenant'
78
+
79
+ """
80
+
81
+ #: The :attr:`index` of the :class:`.Enum` member.
82
+ index: int
83
+
84
+ def __init__(self, *__args: object, **__kwargs: object) -> None:
85
+ """Tweak :class:`enum.Enum` to add an :attr:`.index` to each enum item.
86
+
87
+ When the enum is initialised, ``_member_names_`` contains the names of
88
+ the already initialized items, so its length is the index of this item.
89
+
90
+ Args:
91
+ *__args: Positional arguments.
92
+ **__kwargs: Keyword arguments.
93
+
94
+ Examples:
95
+ >>> import numpy
96
+
97
+ >>> from openfisca_core import indexed_enums as enum
98
+
99
+ >>> Housing = enum.Enum("Housing", "owner tenant")
100
+ >>> Housing.tenant.index
101
+ 1
102
+
103
+ >>> class Housing(enum.Enum):
104
+ ... OWNER = "Owner"
105
+ ... TENANT = "Tenant"
106
+
107
+ >>> Housing.TENANT.index
108
+ 1
109
+
110
+ >>> array = numpy.array([[1, 2], [3, 4]])
111
+ >>> array[Housing.TENANT.index]
112
+ array([3, 4])
113
+
114
+ Note:
115
+ ``_member_names_`` is undocumented in upstream :class:`enum.Enum`.
116
+
117
+ """
118
+ self.index = len(self._member_names_)
119
+
120
+ def __repr__(self) -> str:
121
+ return f"{self.__class__.__name__}.{self.name}"
122
+
123
+ @classmethod
124
+ def encode(cls, array: t.VarArray | t.ArrayLike[object]) -> t.EnumArray:
125
+ """Encode an encodable array into an :class:`.EnumArray`.
126
+
127
+ Args:
128
+ array: :class:`~numpy.ndarray` to encode.
129
+
130
+ Returns:
131
+ EnumArray: An :class:`.EnumArray` with the encoded input values.
132
+
133
+ Examples:
134
+ >>> import numpy
135
+
136
+ >>> from openfisca_core import indexed_enums as enum
137
+
138
+ >>> class Housing(enum.Enum):
139
+ ... OWNER = "Owner"
140
+ ... TENANT = "Tenant"
141
+
142
+ # EnumArray
143
+
144
+ >>> array = numpy.array([1])
145
+ >>> enum_array = enum.EnumArray(array, Housing)
146
+ >>> Housing.encode(enum_array)
147
+ EnumArray([Housing.TENANT])
148
+
149
+ # Array of Enum
150
+
151
+ >>> array = numpy.array([Housing.TENANT])
152
+ >>> enum_array = Housing.encode(array)
153
+ >>> enum_array == Housing.TENANT
154
+ array([ True])
155
+
156
+ # Array of integers
157
+
158
+ >>> array = numpy.array([1])
159
+ >>> enum_array = Housing.encode(array)
160
+ >>> enum_array == Housing.TENANT
161
+ array([ True])
162
+
163
+ # Array of strings
164
+
165
+ >>> array = numpy.array(["TENANT"])
166
+ >>> enum_array = Housing.encode(array)
167
+ >>> enum_array == Housing.TENANT
168
+ array([ True])
169
+
170
+ # Array of bytes
171
+
172
+ >>> array = numpy.array([b"TENANT"])
173
+ >>> enum_array = Housing.encode(array)
174
+ Traceback (most recent call last):
175
+ EnumEncodingError: Failed to encode "[b'TENANT']" of type 'bytes...
176
+
177
+ .. seealso::
178
+ :meth:`.EnumArray.decode` for decoding.
179
+
180
+ """
181
+ if isinstance(array, EnumArray):
182
+ return array
183
+ if len(array) == 0:
184
+ return EnumArray(numpy.asarray(array, t.EnumDType), cls)
185
+ if isinstance(array, Sequence):
186
+ return cls._encode_array_like(array)
187
+ return cls._encode_array(array)
188
+
189
+ @classmethod
190
+ def _encode_array(cls, value: t.VarArray) -> t.EnumArray:
191
+ if _is_int_array(value):
192
+ indices = _int_to_index(cls, value)
193
+ elif _is_str_array(value): # type: ignore[unreachable]
194
+ indices = _str_to_index(cls, value)
195
+ elif _is_enum_array(value) and cls == value[0].__class__:
196
+ indices = _enum_to_index(value)
197
+ else:
198
+ raise EnumEncodingError(cls, value)
199
+ if indices.size != len(value):
200
+ raise EnumMemberNotFoundError(cls)
201
+ return EnumArray(indices, cls)
202
+
203
+ @classmethod
204
+ def _encode_array_like(cls, value: t.ArrayLike[object]) -> t.EnumArray:
205
+ if _is_int_array_like(value):
206
+ indices = _int_to_index(cls, value)
207
+ elif _is_str_array_like(value): # type: ignore[unreachable]
208
+ indices = _str_to_index(cls, value)
209
+ elif _is_enum_array_like(value):
210
+ indices = _enum_to_index(value)
211
+ else:
212
+ raise EnumEncodingError(cls, value)
213
+ if indices.size != len(value):
214
+ raise EnumMemberNotFoundError(cls)
215
+ return EnumArray(indices, cls)
216
+
217
+
218
+ __all__ = ["Enum"]