Skip to content
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# Changelog

## 43.4.0 [#1327](https://github.com/openfisca/openfisca-core/pull/1327)

#### New features

- Introduce parallel axes expansion to the Web API
- Allows for calculating variables based on a range of depending values

### 43.3.5 [#1325](https://github.com/openfisca/openfisca-core/pull/1325)

#### Documentation
Expand Down
87 changes: 56 additions & 31 deletions openfisca_web_api/handlers.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,11 @@ def calculate(tax_benefit_system, input_data: dict) -> dict:
afilter=lambda t: t is None,
yielded=True,
)
# Calculated results requested by the user.
computation_results: dict = {}
# Paths to delete from the result in case of axes calculation.
paths_to_delete = []

for computation in requested_computations:
path = computation[
0
Expand All @@ -22,43 +26,64 @@ def calculate(tax_benefit_system, input_data: dict) -> dict:
variable = tax_benefit_system.get_variable(variable_name)
result = simulation.calculate(variable_name, period)
population = simulation.get_population(entity_plural)
entity_index = population.get_index(entity_id)

if variable.value_type == Enum:
entity_result = result.decode()[entity_index].name
elif variable.value_type == float:
entity_result = float(
str(result[entity_index]),
) # To turn the float32 into a regular float without adding confusing extra decimals. There must be a better way.
elif variable.value_type == str:
entity_result = str(result[entity_index])
# With axes, entities are expanded by the given number of `counts`.
# So, for example, `bob` becomes `bob_0`, `bob_1`, `bob_2`, etc.
if input_data.get("axes") is None:
entity_ids = [entity_id]
else:
entity_result = result.tolist()[entity_index]
# Don't use dpath.new, because there is a problem with dpath>=2.0
# when we have a key that is numeric, like the year.
# See https://github.com/dpath-maintainers/dpath-python/issues/160
if computation_results == {}:
computation_results = {
entity_plural: {entity_id: {variable_name: {period: entity_result}}},
}
elif entity_plural in computation_results:
if entity_id in computation_results[entity_plural]:
if variable_name in computation_results[entity_plural][entity_id]:
computation_results[entity_plural][entity_id][variable_name][
period
] = entity_result
entity_ids = [
id_
for id_ in population.ids
if id_.startswith(entity_id) and id_ != entity_id
]
paths_to_delete.append("/".join(path.split("/")[0:2]))

for entity_id in entity_ids:
entity_index = population.get_index(entity_id)

if variable.value_type == Enum:
entity_result = result.decode()[entity_index].name
elif variable.value_type == float:
entity_result = float(
str(result[entity_index]),
) # To turn the float32 into a regular float without adding confusing extra decimals. There must be a better way.
elif variable.value_type == str:
entity_result = str(result[entity_index])
else:
entity_result = result.tolist()[entity_index]
# Don't use dpath.new, because there is a problem with dpath>=2.0
# when we have a key that is numeric, like the year.
# See https://github.com/dpath-maintainers/dpath-python/issues/160
if computation_results == {}:
computation_results = {
entity_plural: {
entity_id: {variable_name: {period: entity_result}}
},
}
elif entity_plural in computation_results:
if entity_id in computation_results[entity_plural]:
if variable_name in computation_results[entity_plural][entity_id]:
computation_results[entity_plural][entity_id][variable_name][
period
] = entity_result
else:
computation_results[entity_plural][entity_id][variable_name] = {
period: entity_result,
}
else:
computation_results[entity_plural][entity_id][variable_name] = {
period: entity_result,
computation_results[entity_plural][entity_id] = {
variable_name: {period: entity_result},
}
else:
computation_results[entity_plural][entity_id] = {
variable_name: {period: entity_result},
computation_results[entity_plural] = {
entity_id: {variable_name: {period: entity_result}},
}
else:
computation_results[entity_plural] = {
entity_id: {variable_name: {period: entity_result}},
}

for path in paths_to_delete:
if dpath.search(input_data, path):
dpath.delete(input_data, path)

dpath.merge(input_data, computation_results)

return input_data
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@

setup(
name="OpenFisca-Core",
version="43.3.5",
version="43.4.0",
author="OpenFisca Team",
author_email="[email protected]",
classifiers=[
Expand Down
Loading
Loading