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,548 @@
1
+ from __future__ import annotations
2
+
3
+ import abc
4
+ import enum
5
+ import re
6
+ from collections.abc import Iterable, Iterator, Sequence, Sized
7
+ from typing import NewType, Required, Self, TypeAlias, TypeVar, Union
8
+
9
+ import numpy
10
+ import pendulum
11
+ from numpy import (
12
+ bool_ as BoolDType,
13
+ )
14
+ from numpy import (
15
+ bytes_ as BytesDType,
16
+ )
17
+ from numpy import (
18
+ datetime64 as DateDType,
19
+ )
20
+ from numpy import (
21
+ float32 as FloatDType,
22
+ )
23
+ from numpy import (
24
+ generic as VarDType,
25
+ )
26
+ from numpy import (
27
+ int32 as IntDType,
28
+ )
29
+ from numpy import (
30
+ object_ as ObjDType,
31
+ )
32
+ from numpy import (
33
+ str_ as StrDType,
34
+ )
35
+ from numpy import (
36
+ uint8 as EnumDType,
37
+ )
38
+ from numpy.typing import DTypeLike, NDArray
39
+ from typing_extensions import Protocol, TypedDict
40
+
41
+ #: Generic covariant type var.
42
+ _T_co = TypeVar("_T_co", covariant=True)
43
+
44
+ # Arrays
45
+
46
+ #: Type var for numpy arrays.
47
+ _N_co = TypeVar("_N_co", covariant=True, bound="DTypeGeneric")
48
+
49
+ #: Type representing an numpy array.
50
+ Array: TypeAlias = NDArray[_N_co]
51
+
52
+ #: Type alias for a boolean array.
53
+ BoolArray: TypeAlias = Array[BoolDType]
54
+
55
+ #: Type alias for an array of bytes.
56
+ BytesArray: TypeAlias = Array[BytesDType]
57
+
58
+ #: Type alias for an array of dates.
59
+ DateArray: TypeAlias = Array[DateDType]
60
+
61
+ #: Type alias for an array of floats.
62
+ FloatArray: TypeAlias = Array[FloatDType]
63
+
64
+ #: Type alias for an array of enum indices.
65
+ IndexArray: TypeAlias = Array[EnumDType]
66
+
67
+ #: Type alias for an array of integers.
68
+ IntArray: TypeAlias = Array[IntDType]
69
+
70
+ #: Type alias for an array of objects.
71
+ ObjArray: TypeAlias = Array[ObjDType]
72
+
73
+ #: Type alias for an array of strings.
74
+ StrArray: TypeAlias = Array[StrDType]
75
+
76
+ #: Type alias for an array of generic objects.
77
+ VarArray: TypeAlias = Array[VarDType]
78
+
79
+ # Arrays-like
80
+
81
+ #: Type var for array-like objects.
82
+ _L = TypeVar("_L")
83
+
84
+ #: Type representing an array-like object.
85
+ ArrayLike: TypeAlias = Sequence[_L]
86
+
87
+ #: Type for bool arrays.
88
+ DTypeBool: TypeAlias = numpy.bool_
89
+
90
+ #: Type for int arrays.
91
+ DTypeInt: TypeAlias = numpy.int32
92
+
93
+ #: Type for float arrays.
94
+ DTypeFloat: TypeAlias = numpy.float32
95
+
96
+ #: Type for string arrays.
97
+ DTypeStr: TypeAlias = numpy.str_
98
+
99
+ #: Type for bytes arrays.
100
+ DTypeBytes: TypeAlias = numpy.bytes_
101
+
102
+ #: Type for Enum arrays.
103
+ DTypeEnum: TypeAlias = numpy.uint8
104
+
105
+ #: Type for date arrays.
106
+ DTypeDate: TypeAlias = numpy.datetime64
107
+
108
+ #: Type for "object" arrays.
109
+ DTypeObject: TypeAlias = numpy.object_
110
+
111
+ #: Type for "generic" arrays.
112
+ DTypeGeneric: TypeAlias = numpy.generic
113
+
114
+ # TODO(<Mauko Quiroga-Alvarado>): Properly resolve metaclass types.
115
+ # https://github.com/python/mypy/issues/14033
116
+
117
+
118
+ class _SeqIntMeta(type):
119
+ def __instancecheck__(self, arg: object, /) -> bool:
120
+ return (
121
+ bool(arg)
122
+ and isinstance(arg, Sequence)
123
+ and all(isinstance(item, int) for item in arg)
124
+ )
125
+
126
+
127
+ class SeqInt(list[int], metaclass=_SeqIntMeta): ... # type: ignore[misc]
128
+
129
+
130
+ # Entities
131
+
132
+ #: For example "person".
133
+ EntityKey = NewType("EntityKey", str)
134
+
135
+ #: For example "persons".
136
+ EntityPlural = NewType("EntityPlural", str)
137
+
138
+ #: For example "principal".
139
+ RoleKey = NewType("RoleKey", str)
140
+
141
+ #: For example "parents".
142
+ RolePlural = NewType("RolePlural", str)
143
+
144
+
145
+ class CoreEntity(Protocol):
146
+ key: EntityKey
147
+ plural: EntityPlural
148
+
149
+ def check_role_validity(self, role: object, /) -> None: ...
150
+
151
+ def check_variable_defined_for_entity(
152
+ self,
153
+ variable_name: VariableName,
154
+ /,
155
+ ) -> None: ...
156
+
157
+ def get_variable(
158
+ self,
159
+ variable_name: VariableName,
160
+ check_existence: bool = ...,
161
+ /,
162
+ ) -> None | Variable: ...
163
+
164
+
165
+ class SingleEntity(CoreEntity, Protocol): ...
166
+
167
+
168
+ class GroupEntity(CoreEntity, Protocol): ...
169
+
170
+
171
+ class Role(Protocol):
172
+ entity: GroupEntity
173
+ max: int | None
174
+ subroles: None | Iterable[Role]
175
+
176
+ @property
177
+ def key(self, /) -> RoleKey: ...
178
+
179
+ @property
180
+ def plural(self, /) -> None | RolePlural: ...
181
+
182
+
183
+ # Indexed enums
184
+
185
+
186
+ class EnumType(enum.EnumMeta):
187
+ indices: Array[DTypeEnum]
188
+ names: Array[DTypeStr]
189
+ enums: Array[DTypeObject]
190
+
191
+
192
+ class Enum(enum.Enum, metaclass=EnumType):
193
+ index: int
194
+ _member_names_: list[str]
195
+
196
+
197
+ class EnumArray(
198
+ numpy.ndarray[tuple[int, ...], numpy.dtype[DTypeEnum]], metaclass=abc.ABCMeta
199
+ ):
200
+ possible_values: None | type[Enum]
201
+
202
+ @abc.abstractmethod
203
+ def __new__(
204
+ cls, input_array: Array[DTypeEnum], possible_values: type[Enum]
205
+ ) -> Self: ...
206
+
207
+
208
+ # Holders
209
+
210
+
211
+ class Holder(Protocol):
212
+ def clone(self, population: CorePopulation, /) -> Holder: ...
213
+
214
+ def get_memory_usage(self, /) -> MemoryUsage: ...
215
+
216
+
217
+ class MemoryUsage(TypedDict, total=False):
218
+ cell_size: int
219
+ dtype: DTypeLike
220
+ nb_arrays: int
221
+ nb_cells_by_array: int
222
+ nb_requests: int
223
+ nb_requests_by_array: int
224
+ total_nb_bytes: Required[int]
225
+
226
+
227
+ # Parameters
228
+
229
+ #: A type representing a node of parameters.
230
+ ParameterNode: TypeAlias = Union[
231
+ "ParameterNodeAtInstant", "VectorialParameterNodeAtInstant"
232
+ ]
233
+
234
+ #: A type representing a ???
235
+ ParameterNodeChild: TypeAlias = ParameterNode | ArrayLike[object]
236
+
237
+
238
+ class ParameterNodeAtInstant(Protocol):
239
+ _instant_str: InstantStr
240
+
241
+ def __contains__(self, __item: object, /) -> bool: ...
242
+
243
+ def __getitem__(
244
+ self, __index: str | Array[DTypeGeneric], /
245
+ ) -> ParameterNodeChild: ...
246
+
247
+
248
+ class VectorialParameterNodeAtInstant(Protocol):
249
+ _instant_str: InstantStr
250
+
251
+ def __contains__(self, item: object, /) -> bool: ...
252
+
253
+ def __getitem__(
254
+ self, __index: str | Array[DTypeGeneric], /
255
+ ) -> ParameterNodeChild: ...
256
+
257
+
258
+ # Periods
259
+
260
+ #: Matches "2015", "2015-01", "2015-01-01" but not "2015-13", "2015-12-32".
261
+ iso_format = re.compile(r"^\d{4}(-(?:0[1-9]|1[0-2])(-(?:0[1-9]|[12]\d|3[01]))?)?$")
262
+
263
+ #: Matches "2015", "2015-W01", "2015-W53-1" but not "2015-W54", "2015-W10-8".
264
+ iso_calendar = re.compile(r"^\d{4}(-W(0[1-9]|[1-4][0-9]|5[0-3]))?(-[1-7])?$")
265
+
266
+ #: For example 2020.
267
+ InstantInt = NewType("InstantInt", int)
268
+
269
+ #: For example 2020.
270
+ PeriodInt = NewType("PeriodInt", int)
271
+
272
+
273
+ class _InstantStrMeta(type):
274
+ def __instancecheck__(self, arg: object) -> bool:
275
+ return isinstance(arg, (ISOFormatStr, ISOCalendarStr))
276
+
277
+
278
+ class InstantStr(str, metaclass=_InstantStrMeta): # type: ignore[misc]
279
+ __slots__ = ()
280
+
281
+
282
+ class _ISOFormatStrMeta(type):
283
+ def __instancecheck__(self, arg: object) -> bool:
284
+ return isinstance(arg, str) and bool(iso_format.match(arg))
285
+
286
+
287
+ class ISOFormatStr(str, metaclass=_ISOFormatStrMeta): # type: ignore[misc]
288
+ __slots__ = ()
289
+
290
+
291
+ class _ISOCalendarStrMeta(type):
292
+ def __instancecheck__(self, arg: object) -> bool:
293
+ return isinstance(arg, str) and bool(iso_calendar.match(arg))
294
+
295
+
296
+ class ISOCalendarStr(str, metaclass=_ISOCalendarStrMeta): # type: ignore[misc]
297
+ __slots__ = ()
298
+
299
+
300
+ class _PeriodStrMeta(type):
301
+ def __instancecheck__(self, arg: object) -> bool:
302
+ return (
303
+ isinstance(arg, str)
304
+ and ":" in arg
305
+ and isinstance(arg.split(":")[1], InstantStr)
306
+ )
307
+
308
+
309
+ class PeriodStr(str, metaclass=_PeriodStrMeta): # type: ignore[misc]
310
+ __slots__ = ()
311
+
312
+
313
+ class Container(Protocol[_T_co]):
314
+ def __contains__(self, __item: object, /) -> bool: ...
315
+
316
+
317
+ class Indexable(Protocol[_T_co]):
318
+ def __getitem__(self, __index: int, /) -> _T_co: ...
319
+
320
+
321
+ class DateUnit(Container[str], Protocol):
322
+ def upper(self, /) -> str: ...
323
+
324
+
325
+ class Instant(Indexable[int], Iterable[int], Sized, Protocol):
326
+ @property
327
+ def year(self, /) -> int: ...
328
+
329
+ @property
330
+ def month(self, /) -> int: ...
331
+
332
+ @property
333
+ def day(self, /) -> int: ...
334
+
335
+ @property
336
+ def date(self, /) -> pendulum.Date: ...
337
+
338
+ def __lt__(self, __other: object, /) -> bool: ...
339
+
340
+ def __le__(self, __other: object, /) -> bool: ...
341
+
342
+ def offset(self, __offset: str | int, __unit: DateUnit, /) -> None | Instant: ...
343
+
344
+
345
+ class Period(Indexable[DateUnit | Instant | int], Protocol):
346
+ @property
347
+ def unit(self, /) -> DateUnit: ...
348
+
349
+ @property
350
+ def start(self, /) -> Instant: ...
351
+
352
+ @property
353
+ def size(self, /) -> int: ...
354
+
355
+ @property
356
+ def stop(self, /) -> Instant: ...
357
+
358
+ def contains(self, __other: Period, /) -> bool: ...
359
+
360
+ def offset(
361
+ self, __offset: str | int, __unit: None | DateUnit = None, /
362
+ ) -> Period: ...
363
+
364
+
365
+ #: Type alias for a period-like object.
366
+ PeriodLike: TypeAlias = Period | PeriodStr | PeriodInt
367
+
368
+ # Populations
369
+
370
+
371
+ class CorePopulation(Protocol): ...
372
+
373
+
374
+ class SinglePopulation(CorePopulation, Protocol):
375
+ entity: SingleEntity
376
+
377
+ def get_holder(self, variable_name: VariableName, /) -> Holder: ...
378
+
379
+
380
+ class GroupPopulation(CorePopulation, Protocol): ...
381
+
382
+
383
+ # Simulations
384
+
385
+
386
+ class Simulation(Protocol):
387
+ def calculate(
388
+ self, variable_name: VariableName, period: Period, /
389
+ ) -> Array[DTypeGeneric]: ...
390
+
391
+ def calculate_add(
392
+ self, variable_name: VariableName, period: Period, /
393
+ ) -> Array[DTypeGeneric]: ...
394
+
395
+ def calculate_divide(
396
+ self, variable_name: VariableName, period: Period, /
397
+ ) -> Array[DTypeGeneric]: ...
398
+
399
+ def get_population(self, plural: None | str, /) -> CorePopulation: ...
400
+
401
+
402
+ # Tax-Benefit systems
403
+
404
+
405
+ class TaxBenefitSystem(Protocol):
406
+ person_entity: SingleEntity
407
+
408
+ def get_variable(
409
+ self,
410
+ variable_name: VariableName,
411
+ check_existence: bool = ...,
412
+ /,
413
+ ) -> None | Variable: ...
414
+
415
+
416
+ # Tracers
417
+
418
+ #: A type representing a unit time.
419
+ Time: TypeAlias = float
420
+
421
+ #: A type representing a mapping of flat traces.
422
+ FlatNodeMap: TypeAlias = dict["NodeKey", "FlatTraceMap"]
423
+
424
+ #: A type representing a mapping of serialized traces.
425
+ SerializedNodeMap: TypeAlias = dict["NodeKey", "SerializedTraceMap"]
426
+
427
+ #: Key of a trace.
428
+ NodeKey = NewType("NodeKey", str)
429
+
430
+
431
+ class FlatTraceMap(TypedDict, total=True):
432
+ dependencies: list[NodeKey]
433
+ parameters: dict[NodeKey, None | ArrayLike[object]]
434
+ value: None | VarArray
435
+ calculation_time: Time
436
+ formula_time: Time
437
+
438
+
439
+ class SerializedTraceMap(TypedDict, total=True):
440
+ dependencies: list[NodeKey]
441
+ parameters: dict[NodeKey, None | ArrayLike[object]]
442
+ value: None | ArrayLike[object]
443
+ calculation_time: Time
444
+ formula_time: Time
445
+
446
+
447
+ class SimpleTraceMap(TypedDict, total=True):
448
+ name: VariableName
449
+ period: int | Period
450
+
451
+
452
+ class ComputationLog(Protocol):
453
+ def print_log(self, __aggregate: bool = ..., __max_depth: int = ..., /) -> None: ...
454
+
455
+
456
+ class FlatTrace(Protocol):
457
+ def get_trace(self, /) -> FlatNodeMap: ...
458
+
459
+ def get_serialized_trace(self, /) -> SerializedNodeMap: ...
460
+
461
+
462
+ class FullTracer(Protocol):
463
+ @property
464
+ def trees(self, /) -> list[TraceNode]: ...
465
+
466
+ def browse_trace(self, /) -> Iterator[TraceNode]: ...
467
+
468
+ def get_nb_requests(self, __name: VariableName, /) -> int: ...
469
+
470
+
471
+ class PerformanceLog(Protocol):
472
+ def generate_graph(self, __dir_path: str, /) -> None: ...
473
+
474
+ def generate_performance_tables(self, __dir_path: str, /) -> None: ...
475
+
476
+
477
+ class SimpleTracer(Protocol):
478
+ @property
479
+ def stack(self, /) -> SimpleStack: ...
480
+
481
+ def record_calculation_start(
482
+ self, __name: VariableName, __period: PeriodInt | Period, /
483
+ ) -> None: ...
484
+
485
+ def record_calculation_end(self, /) -> None: ...
486
+
487
+
488
+ class TraceNode(Protocol):
489
+ @property
490
+ def children(self, /) -> list[TraceNode]: ...
491
+
492
+ @property
493
+ def end(self, /) -> Time: ...
494
+
495
+ @property
496
+ def name(self, /) -> str: ...
497
+
498
+ @property
499
+ def parameters(self, /) -> list[TraceNode]: ...
500
+
501
+ @property
502
+ def parent(self, /) -> None | TraceNode: ...
503
+
504
+ @property
505
+ def period(self, /) -> PeriodInt | Period: ...
506
+
507
+ @property
508
+ def start(self, /) -> Time: ...
509
+
510
+ @property
511
+ def value(self, /) -> None | VarArray: ...
512
+
513
+ def calculation_time(self, *, __round: bool = ...) -> Time: ...
514
+
515
+ def formula_time(self, /) -> Time: ...
516
+
517
+ def append_child(self, __node: TraceNode, /) -> None: ...
518
+
519
+
520
+ #: A stack of simple traces.
521
+ SimpleStack: TypeAlias = list[SimpleTraceMap]
522
+
523
+ # Variables
524
+
525
+ #: For example "salary".
526
+ VariableName = NewType("VariableName", str)
527
+
528
+
529
+ class Variable(Protocol):
530
+ entity: CoreEntity
531
+ name: VariableName
532
+
533
+
534
+ class Formula(Protocol):
535
+ def __call__(
536
+ self,
537
+ population: CorePopulation,
538
+ instant: Instant,
539
+ params: Params,
540
+ /,
541
+ ) -> Array[DTypeGeneric]: ...
542
+
543
+
544
+ class Params(Protocol):
545
+ def __call__(self, instant: Instant, /) -> ParameterNodeAtInstant: ...
546
+
547
+
548
+ __all__ = ["DTypeLike"]
@@ -0,0 +1,26 @@
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 .config import FORMULA_NAME_PREFIX, VALUE_TYPES # noqa: F401
25
+ from .helpers import get_annualized_variable, get_neutralized_variable # noqa: F401
26
+ from .variable import Variable # noqa: F401
@@ -0,0 +1,53 @@
1
+ import datetime
2
+
3
+ import numpy
4
+
5
+ from openfisca_core import indexed_enums
6
+ from openfisca_core.indexed_enums import Enum
7
+
8
+ VALUE_TYPES = {
9
+ bool: {
10
+ "dtype": numpy.bool_,
11
+ "default": False,
12
+ "json_type": "boolean",
13
+ "formatted_value_type": "Boolean",
14
+ "is_period_size_independent": True,
15
+ },
16
+ int: {
17
+ "dtype": numpy.int32,
18
+ "default": 0,
19
+ "json_type": "integer",
20
+ "formatted_value_type": "Int",
21
+ "is_period_size_independent": False,
22
+ },
23
+ float: {
24
+ "dtype": numpy.float32,
25
+ "default": 0,
26
+ "json_type": "number",
27
+ "formatted_value_type": "Float",
28
+ "is_period_size_independent": False,
29
+ },
30
+ str: {
31
+ "dtype": object,
32
+ "default": "",
33
+ "json_type": "string",
34
+ "formatted_value_type": "String",
35
+ "is_period_size_independent": True,
36
+ },
37
+ Enum: {
38
+ "dtype": indexed_enums.ENUM_ARRAY_DTYPE,
39
+ "json_type": "string",
40
+ "formatted_value_type": "String",
41
+ "is_period_size_independent": True,
42
+ },
43
+ datetime.date: {
44
+ "dtype": "datetime64[D]",
45
+ "default": datetime.date.fromtimestamp(0), # 0 == 1970-01-01
46
+ "json_type": "string",
47
+ "formatted_value_type": "Date",
48
+ "is_period_size_independent": True,
49
+ },
50
+ }
51
+
52
+
53
+ FORMULA_NAME_PREFIX = "formula"
@@ -0,0 +1,67 @@
1
+ from __future__ import annotations
2
+
3
+ import sortedcontainers
4
+
5
+ from openfisca_core import variables
6
+ from openfisca_core.periods import Period
7
+
8
+
9
+ def get_annualized_variable(
10
+ variable: variables.Variable,
11
+ annualization_period: Period | None = None,
12
+ ) -> variables.Variable:
13
+ """Returns a clone of ``variable`` that is annualized for the period ``annualization_period``.
14
+ When annualized, a variable's formula is only called for a January calculation, and the results for other months are assumed to be identical.
15
+ """
16
+
17
+ def make_annual_formula(original_formula, annualization_period=None):
18
+ def annual_formula(population, period, parameters):
19
+ if period.start.month != 1 and (
20
+ annualization_period is None or annualization_period.contains(period)
21
+ ):
22
+ return population(variable.name, period.this_year.first_month)
23
+ if original_formula.__code__.co_argcount == 2:
24
+ return original_formula(population, period)
25
+ return original_formula(population, period, parameters)
26
+
27
+ return annual_formula
28
+
29
+ new_variable = variable.clone()
30
+ new_variable.formulas = sortedcontainers.sorteddict.SortedDict(
31
+ {
32
+ key: make_annual_formula(formula, annualization_period)
33
+ for key, formula in variable.formulas.items()
34
+ },
35
+ )
36
+
37
+ return new_variable
38
+
39
+
40
+ def get_neutralized_variable(variable):
41
+ """Return a new neutralized variable (to be used by reforms).
42
+ A neutralized variable always returns its default value, and does not cache anything.
43
+ """
44
+ result = variable.clone()
45
+ result.is_neutralized = True
46
+ result.label = (
47
+ (
48
+ "[Neutralized]"
49
+ if variable.label is None
50
+ else f"[Neutralized] {variable.label}"
51
+ ),
52
+ )
53
+
54
+ return result
55
+
56
+
57
+ def _partition(dict, predicate):
58
+ true_dict = {}
59
+ false_dict = {}
60
+
61
+ for key, value in dict.items():
62
+ if predicate(key, value):
63
+ true_dict[key] = value
64
+ else:
65
+ false_dict[key] = value
66
+
67
+ return true_dict, false_dict
File without changes