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
openfisca_core/types.py
ADDED
|
@@ -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
|