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.
- openfisca_core/__init__.py +0 -0
- openfisca_core/commons/__init__.py +18 -0
- openfisca_core/commons/dummy.py +25 -0
- openfisca_core/commons/formulas.py +121 -0
- openfisca_core/commons/misc.py +109 -0
- openfisca_core/commons/py.typed +0 -0
- openfisca_core/commons/rates.py +114 -0
- openfisca_core/commons/tests/__init__.py +0 -0
- openfisca_core/commons/tests/test_dummy.py +9 -0
- openfisca_core/commons/tests/test_formulas.py +75 -0
- openfisca_core/commons/tests/test_rates.py +26 -0
- openfisca_core/data_storage/__init__.py +7 -0
- openfisca_core/data_storage/in_memory_storage.py +198 -0
- openfisca_core/data_storage/on_disk_storage.py +307 -0
- openfisca_core/data_storage/types.py +14 -0
- openfisca_core/entities/__init__.py +23 -0
- openfisca_core/entities/_core_entity.py +217 -0
- openfisca_core/entities/_description.py +55 -0
- openfisca_core/entities/entity.py +60 -0
- openfisca_core/entities/group_entity.py +123 -0
- openfisca_core/entities/helpers.py +165 -0
- openfisca_core/entities/py.typed +0 -0
- openfisca_core/entities/role.py +92 -0
- openfisca_core/entities/tests/__init__.py +0 -0
- openfisca_core/entities/tests/test_entity.py +10 -0
- openfisca_core/entities/tests/test_group_entity.py +70 -0
- openfisca_core/entities/tests/test_role.py +11 -0
- openfisca_core/entities/types.py +44 -0
- openfisca_core/errors/__init__.py +64 -0
- openfisca_core/errors/cycle_error.py +2 -0
- openfisca_core/errors/empty_argument_error.py +39 -0
- openfisca_core/errors/nan_creation_error.py +2 -0
- openfisca_core/errors/parameter_not_found_error.py +16 -0
- openfisca_core/errors/parameter_parsing_error.py +18 -0
- openfisca_core/errors/period_mismatch_error.py +9 -0
- openfisca_core/errors/situation_parsing_error.py +26 -0
- openfisca_core/errors/spiral_error.py +2 -0
- openfisca_core/errors/variable_name_config_error.py +2 -0
- openfisca_core/errors/variable_not_found_error.py +29 -0
- openfisca_core/experimental/__init__.py +9 -0
- openfisca_core/experimental/_errors.py +5 -0
- openfisca_core/experimental/_memory_config.py +41 -0
- openfisca_core/formula_helpers.py +9 -0
- openfisca_core/holders/__init__.py +33 -0
- openfisca_core/holders/helpers.py +93 -0
- openfisca_core/holders/holder.py +328 -0
- openfisca_core/holders/tests/__init__.py +0 -0
- openfisca_core/holders/tests/test_helpers.py +134 -0
- openfisca_core/holders/types.py +3 -0
- openfisca_core/indexed_enums/__init__.py +18 -0
- openfisca_core/indexed_enums/_enum_type.py +79 -0
- openfisca_core/indexed_enums/_errors.py +35 -0
- openfisca_core/indexed_enums/_guards.py +209 -0
- openfisca_core/indexed_enums/_utils.py +180 -0
- openfisca_core/indexed_enums/config.py +6 -0
- openfisca_core/indexed_enums/enum.py +218 -0
- openfisca_core/indexed_enums/enum_array.py +316 -0
- openfisca_core/indexed_enums/py.typed +0 -0
- openfisca_core/indexed_enums/tests/__init__.py +0 -0
- openfisca_core/indexed_enums/tests/test_enum.py +135 -0
- openfisca_core/indexed_enums/tests/test_enum_array.py +30 -0
- openfisca_core/indexed_enums/types.py +49 -0
- openfisca_core/memory_config.py +9 -0
- openfisca_core/model_api.py +71 -0
- openfisca_core/parameters/__init__.py +71 -0
- openfisca_core/parameters/at_instant_like.py +17 -0
- openfisca_core/parameters/config.py +55 -0
- openfisca_core/parameters/helpers.py +106 -0
- openfisca_core/parameters/parameter.py +217 -0
- openfisca_core/parameters/parameter_at_instant.py +75 -0
- openfisca_core/parameters/parameter_node.py +176 -0
- openfisca_core/parameters/parameter_node_at_instant.py +57 -0
- openfisca_core/parameters/parameter_scale.py +121 -0
- openfisca_core/parameters/parameter_scale_bracket.py +7 -0
- openfisca_core/parameters/values_history.py +5 -0
- openfisca_core/parameters/vectorial_parameter_node_at_instant.py +179 -0
- openfisca_core/periods/__init__.py +77 -0
- openfisca_core/periods/_errors.py +28 -0
- openfisca_core/periods/_parsers.py +122 -0
- openfisca_core/periods/config.py +20 -0
- openfisca_core/periods/date_unit.py +110 -0
- openfisca_core/periods/helpers.py +314 -0
- openfisca_core/periods/instant_.py +226 -0
- openfisca_core/periods/period_.py +919 -0
- openfisca_core/periods/py.typed +0 -0
- openfisca_core/periods/tests/__init__.py +0 -0
- openfisca_core/periods/tests/helpers/__init__.py +0 -0
- openfisca_core/periods/tests/helpers/test_helpers.py +65 -0
- openfisca_core/periods/tests/helpers/test_instant.py +73 -0
- openfisca_core/periods/tests/helpers/test_period.py +134 -0
- openfisca_core/periods/tests/test_instant.py +32 -0
- openfisca_core/periods/tests/test_parsers.py +129 -0
- openfisca_core/periods/tests/test_period.py +283 -0
- openfisca_core/populations/__init__.py +64 -0
- openfisca_core/populations/_core_population.py +454 -0
- openfisca_core/populations/_errors.py +65 -0
- openfisca_core/populations/group_population.py +326 -0
- openfisca_core/populations/population.py +142 -0
- openfisca_core/populations/tests/__init__.py +0 -0
- openfisca_core/populations/tests/test_members_position.py +116 -0
- openfisca_core/populations/types.py +110 -0
- openfisca_core/projectors/__init__.py +39 -0
- openfisca_core/projectors/entity_to_person_projector.py +12 -0
- openfisca_core/projectors/first_person_to_entity_projector.py +13 -0
- openfisca_core/projectors/helpers.py +139 -0
- openfisca_core/projectors/projector.py +38 -0
- openfisca_core/projectors/typing.py +27 -0
- openfisca_core/projectors/unique_role_to_entity_projector.py +14 -0
- openfisca_core/rates.py +9 -0
- openfisca_core/reforms/__init__.py +24 -0
- openfisca_core/reforms/in_yaml_test_reform.py +28 -0
- openfisca_core/reforms/reform.py +86 -0
- openfisca_core/scripts/__init__.py +106 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.3.3.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-310.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.3.3.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-312-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.3.3.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.4.2.pyc +0 -0
- openfisca_core/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/find_placeholders.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/find_placeholders.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-310.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-312.pyc +0 -0
- openfisca_core/scripts/__pycache__/openfisca_command.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-310.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-312.pyc +0 -0
- openfisca_core/scripts/__pycache__/run_test.cpython-313.pyc +0 -0
- openfisca_core/scripts/__pycache__/simulation_generator.cpython-311.pyc +0 -0
- openfisca_core/scripts/__pycache__/simulation_generator.cpython-313.pyc +0 -0
- openfisca_core/scripts/assets/__init__.py +0 -0
- openfisca_core/scripts/assets/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/assets/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/assets/index.html +140 -0
- openfisca_core/scripts/find_placeholders.py +51 -0
- openfisca_core/scripts/measure_numpy_condition_notations.py +137 -0
- openfisca_core/scripts/measure_performances.py +291 -0
- openfisca_core/scripts/measure_performances_fancy_indexing.py +89 -0
- openfisca_core/scripts/migrations/__init__.py +0 -0
- openfisca_core/scripts/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__init__.py +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-311.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-313.pyc +0 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/legislation.xsd +102 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_country_template.py +30 -0
- openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_extension_template.py +26 -0
- openfisca_core/scripts/migrations/v24_to_25.py +156 -0
- openfisca_core/scripts/openfisca_command.py +192 -0
- openfisca_core/scripts/remove_fuzzy.py +213 -0
- openfisca_core/scripts/run_test.py +51 -0
- openfisca_core/scripts/simulation_generator.py +90 -0
- openfisca_core/simulation_builder.py +16 -0
- openfisca_core/simulations/__init__.py +45 -0
- openfisca_core/simulations/_build_default_simulation.py +158 -0
- openfisca_core/simulations/_build_from_variables.py +230 -0
- openfisca_core/simulations/_type_guards.py +298 -0
- openfisca_core/simulations/helpers.py +111 -0
- openfisca_core/simulations/simulation.py +618 -0
- openfisca_core/simulations/simulation_builder.py +855 -0
- openfisca_core/simulations/typing.py +203 -0
- openfisca_core/taxbenefitsystems/__init__.py +26 -0
- openfisca_core/taxbenefitsystems/tax_benefit_system.py +584 -0
- openfisca_core/taxscales/__init__.py +35 -0
- openfisca_core/taxscales/abstract_rate_tax_scale.py +41 -0
- openfisca_core/taxscales/abstract_tax_scale.py +53 -0
- openfisca_core/taxscales/amount_tax_scale_like.py +55 -0
- openfisca_core/taxscales/helpers.py +44 -0
- openfisca_core/taxscales/linear_average_rate_tax_scale.py +76 -0
- openfisca_core/taxscales/marginal_amount_tax_scale.py +34 -0
- openfisca_core/taxscales/marginal_rate_tax_scale.py +286 -0
- openfisca_core/taxscales/rate_tax_scale_like.py +214 -0
- openfisca_core/taxscales/single_amount_tax_scale.py +32 -0
- openfisca_core/taxscales/tax_scale_like.py +65 -0
- openfisca_core/tools/__init__.py +94 -0
- openfisca_core/tools/parallel_plugin.py +55 -0
- openfisca_core/tools/simulation_dumper.py +137 -0
- openfisca_core/tools/test_runner.py +802 -0
- openfisca_core/tracers/__init__.py +40 -0
- openfisca_core/tracers/computation_log.py +196 -0
- openfisca_core/tracers/flat_trace.py +87 -0
- openfisca_core/tracers/full_tracer.py +172 -0
- openfisca_core/tracers/performance_log.py +133 -0
- openfisca_core/tracers/simple_tracer.py +64 -0
- openfisca_core/tracers/trace_node.py +121 -0
- openfisca_core/tracers/tracing_parameter_node_at_instant.py +81 -0
- openfisca_core/types.py +548 -0
- openfisca_core/variables/__init__.py +26 -0
- openfisca_core/variables/config.py +53 -0
- openfisca_core/variables/helpers.py +67 -0
- openfisca_core/variables/tests/__init__.py +0 -0
- openfisca_core/variables/tests/test_definition_period.py +43 -0
- openfisca_core/variables/variable.py +474 -0
- openfisca_core/warnings/__init__.py +25 -0
- openfisca_core/warnings/libyaml_warning.py +2 -0
- openfisca_core/warnings/tempfile_warning.py +2 -0
- openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/CHANGELOG.md +4209 -0
- openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/README.md +152 -0
- openfisca_core_test-46.0.0.dist-info/METADATA +194 -0
- openfisca_core_test-46.0.0.dist-info/RECORD +237 -0
- openfisca_core_test-46.0.0.dist-info/WHEEL +5 -0
- openfisca_core_test-46.0.0.dist-info/entry_points.txt +3 -0
- openfisca_core_test-46.0.0.dist-info/licenses/LICENSE +661 -0
- openfisca_core_test-46.0.0.dist-info/top_level.txt +2 -0
- openfisca_web_api/__init__.py +0 -0
- openfisca_web_api/app.py +226 -0
- openfisca_web_api/errors.py +11 -0
- openfisca_web_api/handlers.py +90 -0
- openfisca_web_api/loader/__init__.py +22 -0
- openfisca_web_api/loader/entities.py +28 -0
- openfisca_web_api/loader/parameters.py +122 -0
- openfisca_web_api/loader/spec.py +168 -0
- openfisca_web_api/loader/tax_benefit_system.py +27 -0
- openfisca_web_api/loader/variables.py +121 -0
- openfisca_web_api/openAPI.yml +434 -0
- openfisca_web_api/scripts/__init__.py +0 -0
- 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,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"]
|