Changelogs » Openfisca-core



- Request parameter at a given date with the `parameters.benefits('2015-07-01')` notation.

- Be more flexible about parameters definitions

The two following expressions are for instance striclty equivalent:

Parameter("taxes.rate", {"2015-01-01": 2000})
Parameter("taxes.rate", {"values": {"2015-01-01":{"value": 2000}}})

- Make sure `parameters.benefits('2015-07-01')` and `parameters.benefits('2015-07')` return the same value.
- Raise an error when calling `parameters.benefits('invalid_key')`.
- Improve errors when `parameter.update` is used with wrong arguments


- Deprecate `ValuesHistory` class. Use `Parameter` instead.
- Deprecate `parameter.values_history`. Just use `parameter` instead.


Bug fixes

- Fix incomplete initialization of group entities provided by default when not supplied in YAML tests


Technical changes

- Update dependencies: Numpy, Flask, dpath, numexpr


New features

- Allow formulas to return scalar values; broadcast these values to population-sized arrays


New features

- Support role indices in SimulationBuilder.join_with_persons
- This broadens the range of input data we can handle, at some risk of misattributing roles


Bug fix

- Allow both `*.yaml` and `*.yml` extensions for YAML tests


Technical changes

- Use pytest instead of nose in `openfica test`

Breaking changes

- Remove `generate_tests` function from ``:
- While this function was public and documented, its purpose was primarily internal and is unlikely to have been directly used by users.


- Improve error message when too many persons are given a role with a `max` attribute
- This error typically happens when 3 parents are declared in a family, while the entity declaration specifies there can be at most 2.


Breaking changes

- Duplicate keys in YAML parameter files now raise an error
- Before, only one of the two values declared was taking into account, while the other was silently ignored


- Fix host in the `/spec` route of the Web API
- The host should not include the HTTP scheme (http or https)


- Display symbolic values of Enums in /trace and print_computation_log


Breaking changes

- Split the "Entity" class hierarchy (Entity, PersonEntity, GroupEntity) into two parallel hierarchies, representing respectively the abstract, model-level information (classes named Entity etc.) and the population-level information (classes named Population and GroupPopulation)
- As a result, the first parameter passed to a formula is now a Population instance
- Much more detail (and class diagrams) in the PR description
- Remove support from the syntax `some_entity.SOME_ROLE` to access roles (where `some_entity` is the entity passed to a formula).

Migration details

- Use the standard SomeEntity.SOME_ROLE instead. (Where SomeEntity is the capitalized entity or instance, Household.PARENT.)
- Code that relied excessively on internal implementation details of Entity may break, and should be updated to access methods of Entity/Population instead.


- Improve usability of Enum values:
- Details:
- Allow the use of Enum values in comparisons: instead of using `<Enum class>.possible_values` you can simply `import` the Enum class
- Accept Enum values via set_input (same result as the previous point)


Breaking changes

- Require clients to make explicit when input variables cover a range of dates, rather than allowing inputs to be derived from past or future values; also removes the `missing_value` base function

Migration notes

You might need to change your code if any of the following applies:
- you are a model author, and there are variables in your model that use a `base_function` attribute
- your model **or application** uses any non-numeric variables (boolean, date, string or Enum) used in, for which the period on which you define **inputs** does not match the period for which you are requesting **outputs**

Detailed instructions are provided in the [PR description](


- Raise an error instead of silently ignoring the input when a user tries to set an input for a variable for several months (or several years), but the variable has no `set_input` declared.


- Apply `flake8-bugbear` recommendations and enforce same in continuous integration.


- Remove Python 2 compatibility code.


Breaking changes

- Improve cycle and spiral detection, giving consistent results more systematically

Migration notes

- Remove all optional parameters `max_nb_cycles`
- Avoid relying on cached values of a computation

For additional details, see the PR's [description](


Bug fix

- Fix error on simulation debug attribute at simulation clone
- Details:
- Fixes `AttributeError: 'Simulation' object has no attribute 'debug'` introduced by Core v.`29.0.0`.


- Remove print statements from ``, add linting options to detect stray print statements


Breaking changes

- Remove argument `simulation_json` of `Simulation` constructor, which was deprecated as of Core 25
- Remove keyword arguments from Simulation constructor, which should be called only from SimulationBuilder; introduce a property for `trace`
- Remove `period` attribute of Simulation

Migration notes

- As of Core 25, the preferred way of constructing new Simulation instances is via SimulationBuilder, any remaining uses of scenarios should be migrated to that API first.
- Any period attribute of the Simulation was coming from the simulation data (test case or JSON structure), use that instead of the attribute in the Simulation instance.
- Any keyword arguments of Simulation that you were using (or passing to Simulation-constructing methods) can now be accessed directly or as properties, `trace` being the most widely used. Example below:


simulation = SimulationBuilder().build_from_entities(tax_benefit_system, input_data, trace = True)


simulation = SimulationBuilder().build_from_entities(tax_benefit_system, input_data)
simulation.trace = True


- Consistently use the safe approach to YAML loading, fixing [this deprecation warning]( introduced in PyYAML 5.1


Breaking changes

Remove extra_params altogether from Core. This puts all formulas on an equal footing and simplifies
simulation and data storage code.

Migration notes

For almost all users, no migration is needed.

You may be impacted only if you were computing (for instance in a notebook) one of the two variables from France that used this non-standard extension to the `calculate(variable, period)` API: `rsa_fictif` or `ppa_fictive`. In that case you had to supply the additional parameter `mois_demande`. Use `rsa` or `ppa` directly, and go back to the standard API.


> Note: Versions `27.0.0` and `27.0.1` have been unpublished as the former accidentally introduced a bug affecting test inputs. Please use version `27.0.2` or more recent.

- Fix a bug introduced in 27.0.0, affecting YAML tests; because of an incorrect date comparison, input variables would be ignored if they had an end date.


Technical changes

- Provide three levels of information when running tests depending on context:
- when running `pytest`, all failures are reported, coverage is omitted
- when running `make test`, all failures are reported, with coverage also reported
- in continuous integration, exit on first failure, but report coverage always


Breaking changes

- No longer honor calls to `set_input` for variables which have an end date and for periods after that date.

Migration guide

This change is not expected to actually break much reusing code (if any), as it is unlikely that one would deliberately specify an end date for a variable and use it in computations for periods past that date. However, nothing has previously ruled out relying on that behaviour and it may have been introduced by accident. In particular, it can happen that a variable with a formula and an end date is also, in some applications, used as an input.


- Introduce a way to build a simulation for tabular inputs

New features

- Allow to create a simulation step by step:
1. Create entities with `SimulationBuilder.create_entities(...)`
2. Declare your population
with `SimulationBuilder.declare_person_entity(...)` and `SimulationBuilder.declare_entity(...)`
3. Link between persons in population definition with `SimulationBuilder.join_with_persons(...)`
4. Build a simulation with ``
5. Set variable values with the already existing `Simulation.set_input(...)` method


- No longer raise an error when a group entity is not specified in a test case, or partially specified.
- Instead, each person is by default allocated to a group of which they are the sole member, with the default role in that group.


- Convert tests that were incompatible with Pytest 4.0+ and reported "xfail" when run with that version


- Update autopep8 and flake8, which in particular now enforce rules W504 and W605
- W504 goes against house style, so we add it to ignored rules
- W605 may seem like an [overreach]( but does make sense (additional details in PR description), so we upgrade a few regexes to raw strings


- Fixes regression introduced by Core v25 when running YAML tests with reforms or extensions


- Remove `__future__` statements
- As Python 2 support has been dropped, they are not needed anymore.


- Collect and publish measurements of which lines of codes are exercised (or not) by our tests


- Greet visitors to our Github repo with badges providing contact and code information


What this PR brings

An exciting but under-documented feature, "axes", now has much better test coverage and thus long-term maintainability (the documentation is still lacking, but see for demos)

Breaking changes

This PR deprecates the `new_scenario` approach to constructing Simulation objects. This will impact you if:
- your notebooks or scripts or other Python code rely on the France model and use the old form of creating a Simulation object (see below)
- **or** your country package defines a Scenario class and injects it [the way France does](

**To migrate to this version**, if you are in the first case, the minimum required change is this:

*The old way:*

simulation = tax_benefit_system.new_scenario().init_single_entity(...some data...).new_simulation()

*The new way:*

At the top of your file
from openfisca_france.scenarios import init_single_entity
simulation = init_single_entity(tax_benefit_system.new_scenario(), ...some data...).new_simulation()

If you are in the latter case, you must also transform your `init_single_entity` from a Scenario method to a regular function at global scope, and change your tests and reuses as described above.


- Optimize `set_input_dispatch_by_period` so that it doesn't create duplicate vectors in memory


- Bring up the debugger on integration test failures with `openfisca test --pdb` optional argument


- Rename LICENSE.AGPL.txt to LICENSE to let github recognize it


- Outputs a more helpful message when a variable checked in a test doesn't exist
- Introduces unit tests for the test runner


Technical changes

- Allow France to model "Chèque Energie" in a cleaner way:
- Introduce SingleAmountTaxScale (SATS), a simpler form of MarginalAmountTaxScale (MATS)
- whereas MATS sums the values in brackets, up to the amount subject to the scale, SATS only "looks up" the appropriate value for the amount subject to the scale, and is thus the simpler mechanism
- use `numpy.digitize`, allowing callers to specify right or left intervals
- introduce a `type` tag in `brackets` object, thus far with only `single_amount` allowed
- Rename AmountTaxScale to MarginalAmountTaxScale and make it inherit from SATS

This is non-breaking, as there are no direct clients of these classes outside of Core.


- When a YAML test fails, display the correct period for wrong output variable


- Quell a warning in the build of openfisca-doc by moving a docstring to the right place


- Allow country package users to run `openfisca test` without installing the `web_api` dependency
- Alias `openfisca-run-test` to `openfisca test`


- Improve `print_computation_log` and make it a tested, thus supported call


- Load extensions more reliably, by removing dead code in load_extension


- Supply a missing default parameter in `Simulation.delete_arrays` method.


- Fix an exception on yaml import in test runner


- Fix a regression in the YAML test runner. If you have changed any YAML tests since 25.0.0, please rerun them.


- Update documentation URL in the API welcome message


- Support DAY periods


- Explicit test runner dependencies in Python 2.7
- Using an older version of `ruamel` caused a `'CommentedSeq' object has no attribute 'get'` error.


- Don't sort JSON keys in the Web API
- By default, `flask` sorts JSON _object_ keys alphabetically
- This is useful for reusing http caches for example, at the cost of some performance overhead
- But the [JSON specification]( doesn’t require to keep an order, as _objects_ are defined as "an unordered set of name/value pairs"


Breaking changes

- Change the syntax of OpenFisca YAML tests

For instance, a test that was using the `input_variables` keyword like:

- name: Basic income
period: 2016-12
salary: 1200
basic_income: 600


- name: Basic income
period: 2016-12
salary: 1200
basic_income: 600

A test that was fully specifying its entities like:

name: Housing tax
period: 2017-01
- parents: [ Alicia ]
children: [ Michael ]
- id: Alicia
birth: 1961-01-15
- id: Michael
birth: 2002-01-15
2017: 1000


name: Housing tax
period: 2017-01
parents: [ Alicia ]
children: [ Michael ]
birth: 1961-01-15
birth: 2002-01-15
2017: 1000

A **migration script** is available to automatically convert tests:

python openfisca_core/scripts/migrations/ /path/to/tests/

> Note for country packages using Scenarios (e.g. France, Tunisia):
> Tests are not using scenarios anymore. Therefore, tests cannot partially specify entities anymore. Tests using entities inference may need manual adaptation in addition to the script.

- The `Entity` constructor (usually not directly called by users) does not accept an `entities_json` parameter anymore.


- Deprecate `openfisca-run-test`
- `openfisca test` should be used instead.

- Deprecate the use of the `simulation_json` parameter in the `Simulation` constructor.
- `SimulationBuilder(tax_benefit_system).build_from_entities(simulation_json)` should be used instead

New features

- In YAML tests, allow to define expected output for a specific entity

For instance:

name: Housing tax
period: 2017-01
salary: 3000

- In YAML tests, allow to specify an extension to use to run the test:
- See [example](

- In YAML tests, allow the use of YAML anchors:
- See [example](

- Introduce [`EnumArray.decode_to_str`](

Architecture changes

- Move the complex initialisation logics (for JSON-like inputs) to `SimulationBuilder`, away from the `Simulation` and `Entity` classes


- In Python, simplify getting known periods for variable in a simulation:


simulation = ...
holder = simulation.persons.get_holder('salary')


simulation = ...


- In Python, simplify simulation array deletion:


simulation = ...
holder = simulation.persons.get_holder('salary')


simulation = ...
simulation.delete_arrays('salary', '2018-08')


- Set a 120s default timeout in `openfisca serve`
- Otherwise, they regularly restart with an anxiety-provoking "[CRITICAL] WORKER TIMEOUT (pid:2137)" message in log


- Allow non-integral inputs to int variables


- Ensure `` syntax works consistently across country and extension


- Improve serve command by documenting the bind option
- Avoid crashing when no arguments are supplied


- Clarify the error message when assigning a value larger than MaxInt32 to an 'int' variable


- Allow OpenFisca-Core users to define their own level of log


- Remove the reference doc source, as it's been moved to
- Rebuild the doc when the Core codebase changes


- Allow `ParameterNode` children to have a numeric keys
- Before, an incorrect id would be set for these children, resulting to inconsistencies in the Web API.


- Fix a bug that prevented amount scale parameters from being accessed in a formula


- Introduce `ParameterNode.get_descendants`
- This method returns a generator containing all the parameters and nodes recursively contained in the `ParameterNode`


- Make sure to cap all dependency versions, in order to avoid unwanted functional and integration breaks caused by external code updates
- For example [772](


- Limits the range of PyTest versions to < 4.0 to avoid CI crashes caused by 4.0.


- Adds called parameters to Web API `/trace` endpoint
- For a calculated variable, add `parameters` item next to `dependencies` in `/trace` response
- For example:
"income_tax<2017-01>": {
"dependencies": [
"parameters": {
"taxes.income_tax_rate<2017-01-01>": 0.15
"value": [150]

- Scale parameters are also traced:
"parameters": {
"taxes.social_security_contribution<2017-01-01>": {
"0.0": 0.02,
"12400.0": 0.12,
"6000.0": 0.06


- Exposes `amount` scales through the Web API
- Allows for [AmountTaxScale]( parameters to be consumed through the Web API
- See for an example this [parameter in openfisca-tunisia](


- Always allow `documentation` property for `ParameterNode`
- Due to a bug, this field  was accepted in an `index.yaml` file, but not in a `ParameterNode` located in a single YAML file


- Tests the computation of the average tax rate of a targeted net income, according to the varying gross income.


- Updates the requirements on [numpy]( to permit version 1.16


- Fix unproper `entity.count` restoration of a dumped simulation
- Use more previsible value for average rate even when a division by zero is present


- Improve the warning message incentivizing users to install `libyaml`
- `pyyaml` needs to be fully reinstalled to use `libyaml`


- Use `pytest` to run tests, as `nose` and `nose2` are not in active development anymore
- Declare `nose` as a dependency so dependee libraries like `openfisca-france`can use `openfisca-run-test` without having to add `nose` as a dependency

_Note: `openfisca-run-test` still depends on `nose`._


- Apply W504 enforcement (Knuth's style)
- Removes version cap on linting libraries


- Fix `host` property in the OpenAPI `/spec`
- It should not contain the scheme (e.g. `http`)
- Infer scheme from request
- Before, we would assume `https`, which is not always accurate


- Allow TaxBenefitSystem to define the examples to use in the `/spec` route.
- See [docs](


- When there is an empty `index.yaml` in the parameters, ignore it instead of raising an error.


- Fix the internal server error that appeared for the  `/trace` and (less frequently) `/calculate` route of the Web API
- This error appeared when a simulation output was a variable of type string

> Note: Versions `24.5.3` and `24.5.4` have been unpublished as they accidentally introduced a breaking change. Please use version `24.5.5` or more recent.


- Ignore W503 to enforce Knuth's style (W504)
- Fix failing entities test
- Household description was outdated


- Further adopt simplified simulation initialisation
- See [729](


- In Python, simplify simulation initialisation:


simulation = ...
holder = simulation.persons.get_holder('salary')
holder.set_input('2018-08', [4000])


simulation = ...
simulation.set_input('salary', '2018-08', [4000])


- In Python, allow multiline documentation on parameters and variables
- Introduce `documentation` attribute on `ParameterNode`, `Parameter` and `Variable` classes

- In the Web API, expose this documentation as a `documentation` property for parameters, variables and variables' formulas
- on `/parameter` nodes as `/parameter/benefits`
> = python `ParameterNode.documentation`
> = YAML parameter node (`index.yaml`) `documentation` string attribute
- on `/parameter` leafs as `/parameter/benefits/housing_allowance`
> = python `Parameter.documentation`
> = YAML parameter `documentation` string attribute
- on `/variable` as `/variable/housing_allowance`
> = python `Variable.documentation`
- on every `/variable` leaf formula
> = python `Variable` formula **docstring**


- Add a style formatter that follows community code conventions
- Auto-fix code formatting


- Fix small issues in the `/spec` route of the Web API
- Use proper JSON Schema type to describe input types
- Fix property name in the description of `/parameters` and `/variables`


- Introduce the `/entities` endpoint for the Web API.
- Expose information about the country package's entities, and their roles.
"description": "Household",
"documentation": "Household is an example of a group entity. A group entity contains one or more individual·s.[...]",
"plural": "households",
"roles": {
"parent": {
"description": "The one or two adults in charge of the household.",
"max": 2,
"plural": "parents"
"child": {
"description": "Other individuals living in the household.",
"plural": "children"


- Allow to dump and restore a simulation in a directory


from import dump_simulation
dump_simulation(simulation, '/path/to/directory')


from import restore_simulation
simulation = restore_simulation('/path/to/directory', tax_benefit_system)


- Enhance navigation within the Openfisca Web API.
- Provides a direct link to individual parameters and variables from the `/parameters` and `/variables` routes.

The former `/parameters` route of the Web API:

"benefits.basic_income": {
"description": "Amount of the basic income",
"benefits.housing_allowance": {
"description":"Housing allowance amount (as a fraction of the rent)",


"benefits.basic_income": {
"description": "Amount of the basic income",
"benefits.housing_allowance": {
"description":"Housing allowance amount (as a fraction of the rent)",


- Fix spelling in warning about libyaml


Breaking changes

Only install the Web API dependencies as an opt-in:

- `pip install OpenFisca-Core` will _not_ install the Web API anymore.
- `pip install OpenFisca-Core[web-api]` will.

Country package maintainers who still want to provide the Web API by default with their package (**recommended**) should update their ``:
- In the `install_requires` section, replace `'OpenFisca-Core >= 23.3, < 24.0'` by `'OpenFisca-Core[api] >= 24.0, < 25.0'`
- See [example](

Change default Web API port to 5000:

- `openfisca serve` will now serve by default on the `5000` port instead of `6000` (blocked by Chrome).

Rename OpenFisca Web Api package to `openfisca_web_api`:

- Transparent for users of the `openfisca serve` command.
- Users who used to manually import `openfisca_web_api_preview` must know import `openfisca_web_api`.

Rename development dependencies from `test` to `dev`:

- Developpers should now run `pip install --editable .[dev]` instead of `pip install --editable .[test]` to install them.

New features

- In the `/spec` route:
- Indicate the served country package version as API version (instead of `0.1.0`).
- Infer the host URL from the requests, instead of relying on the undocumented `SERVER_NAME` environnement variable.
- The use of the `SERVER_NAME` environnement variable is therefore deprecated and without effect.


- Revert the undesired side effects of `23.4.0` on the `parameters/` overview route of the Web API
- This route now behaves the exact same way than before `23.4.0`
- The keys of the `/parameters` JSON object are back to using the `.` notation
- Parameter nodes are for now not exposed in the `parameters/` overview (but each of them is exposed in `/parameter/path/to/node`)


_Note: this version has been unpublished due to an issue introduced by 23.4.0 in the Web API. Please use 23.5.2 or a more recent version._

- Remove the irrelevant decimals that were added at the end of `float` results in the Web API and the test runner.
- These decimals were added while converting a Numpy `float32` to a regular 64-bits Python `float`.

For instance, the former Web API response extract:

"tax_incentive": {
"2017-01": 333.3333435058594


"tax_incentive": {
"2017-01": 333.33334


_Note: this version has been unpublished due to an issue introduced by 23.4.0 in the Web API. Please use 23.5.2 or a more recent version._

* On the Web API, expose a welcome message (with a 300 code) on `/` instead of a 404 error.

For instance, `curl -i localhost:5000` gives:


"welcome": "This is the root of an OpenFisca Web API. To learn how to use it, check the general documentation ( and the OpenAPI specification of this instance (http://localhost:5000/spec)."

* This message can be customized:

If the Web API is started with `openfisca serve -p 3000 --welcome-message "Welcome to the OpenFisca-France Web API. To learn how to use it, check our interactive swagger documentation:"`

Then `curl -i localhost:5000` gives:


"welcome": "Welcome to the OpenFisca-France Web API. To learn how to use it, check our interactive swagger documenation:"

(Like other configuration variables, this custom message can also be defined in a configuration file. Check the [openfisca serve documentation](


_Note: this version has been unpublished due to an issue introduced by 23.4.0 in the Web API. Please use 23.5.2 or a more recent version._

* Fix API source IP detection through proxies.


_Note: this version has been unpublished as it introduced an issue in the Web API. Please use 23.5.2 or a more recent version._

* Use `/` rather than `.` in the path to access a parameter:
- For instance `/parameter/benefits.basic_income` becomes `/parameter/benefits/basic_income`
- Using `.` is for now still supported, but is considered deprecated and will be turned to a 301 redirection in the next major version.

* Expose parameters `metadata` and `source` in the Web API and:

For instance, `/parameter/benefits/basic_income` contains:

"description": "Amount of the basic income",
"id": "benefits.basic_income",
"metadata": {
"reference": "",
"unit": "currency-EUR"
"source": "",
"values": {
"2015-12-01": 600.0

* Expose parameters nodes in the Web API
- For instance, `/parameter/benefits` now exists and contains:

"description": "Social benefits",
"id": "benefits",
"metadata": {},
"source": "",
"subparams": {
"basic_income": {
"description": "Amount of the basic income"
"housing_allowance": {
"description": "Housing allowance amount (as a fraction of the rent)"

Note that this route doesn't _recursively_ explore the node, and only exposes its direct children name and description.


Minor Change without any impact for country package developers and users:
- Make code more Python3-like by backporting unicode litterals.
- With this backport, all strings are by default unicodes.
- The `u` prefix for strings should *not* be used anymore.
- Each new module must start by `from __future__ import unicode_literals` for the backport to be effective.


* Send reference of the country-package and its version to the tracker so it will appear in the tracking statistics.


* Change the way metadata are declared for Parameter.

description: Age of retirement
unit: year
values: (...)

description: Age of retirement
unit: year
values: (...)

_Setting `unit` and `reference` out of `metadata` is considered deprecated, but still works for backward compatibility._

* Allow legislation coders to define their own medatada

* Expose in the Python API
- Parameters metadata:
- e.g. `parameters.taxes.rate.metadata['unit']`
- Parameter value metadata:
- e.g. `parameters.taxes.rate.values_list[0].metadata['unit']`
- Parameter node description and metadata:
- e.g. `parameters.taxes.metadata['reference']`, `parameters.taxes.description`
- Note: Parameter descriptions (e.g. `parameters.taxes.rate.description`) were already exposed


* Introduce `TaxBenefitSystem.replace_variable`
- Unlike `update_variable`, this method does _not_ keep any of the replaced variable in the new one.
- See [reference documentation](


* Fix installation on Windows with Python 3.7
- Require `psutil` version `5.4.6`, as `5.4.2` is incompatible with that environment.


* In the error message sent to a user trying to set a variable without specifying for which period, add an example for a variable defined for `ETERNITY`.


* Allow to set uncached variables when using a `memory_config`
- Previously, trying to set variables listed in `variables_to_drop` of the `memory_config` had no effect.
- Now this variables are still not cached, but they can be set by the user.


* Use C binding to load and dump Yaml (`CLoader` and `CDumper`)
- For countries with several Yaml tests, they can take some time to run
- Using the C bindings provided by `libyaml` adds a little performance boost


Fix test that was failing due to migration to HTTPS


- Minor technical improvement
- Publish both Python 2 and Python 3 version on Pypi in CircleCI


- Fixup Python 3 compatibility


Make package compatible with Python 3


Start adapting OpenFisca to Python 3
- Imports are now all absolute imports
- `unicode_type` and `basestring_type` are now used for compatible type checking.
- All calls for sorted() use the key parameter
- Iteration on dict now uses dict.items()


* Re-accept `int` values for `instant` in `tax_benefit_system.get_parameter_at_instant(instant)`
* `int` values were accidently rejected since v23


This changeset aims at simplifying the OpenFisca Core architecture.

Changes should be transparent for legislation modeling and web API usage.

It can impact users using the Python API (see Breaking changes part)

General architecture principles:
- `Simulation` is the class in charge of running the calculations
- `Holder` is the class in charge of keeping input and previously calculated values

Breaking changes

- Remove two (already deprecated) possible values for the variable attribute `base_function`:
- `permanent_default_value`
- `requested_period_added_value`

In `Holder`:
- Remove deprecated constructor `Holder(simulation, variable)`
- Use `Holder(entity, variable)` instead
- Remove attributes:
- `formula` and `real_formula`
- Use `variable.formulas` instead (see more further down)
- `array`
- Use `get_array(period)` instead
- Remove methods:
- `calculate` and `compute`
- Use `simulation.calculate` instead
- `calculate_output`
- Use `simulation.calculate_output` instead
- `compute_add`
- Use `simulation.calculate_add` instead
- `compute_divide`
- Use `simulation.calculate_divide` instead
- `get_from_cache`
- Use `get_array` instead
- `graph`
- Methods `set_input` and `put_in_cache` don't return anything anymore.

In `Simulation`:
- Reorder constructor arguments
- `tax_benefit_system` is now the first (mandatory) argument, and `simulation_json` the second (optional) one.
- Remove attributes:
- `holder_by_name`
- Use `simulation.get_holder(...)` or `entity.get_holder(...)` instead
- Remove methods:
- `compute`
- Use `calculate` instead
- `compute_add`
- Use `calculate_add` instead
- `compute_divide`
- Use `calculate_divide` instead
- `parameters_at`
- Use `simulation.tax_benefit_sytem.get_parameters_at_instant` instead
- `graph`
- `to_input_variables_json`
- Undeprecate, but slightly change the behaviour of the `get_holder(variable)` method:
- Optional second argument `default` is not accepted anymore
- If no holder has yet been created for the variable, no error is raised, and a new holder is created and returned.

New features

- Introduce `variable.formulas`, a sorted dict containing all the formulas of a variable:

>>> SortedDict({
'2015-12-01': <function formula_2015_12 at 0x1079aa500>,
'2016-12-01': <function formula_2016_12 at 0x1079aa488>

Each value is a simple python function.

- Make `holder.set_input` more flexible
- It now accepts a string as `period`
- It now accepts a list as `array`

Technical changes

- Remove module `formulas` and class `Formula`
- Variables's formulas are now simple functions.
- Remove class `DatedHolder`
- All calculation methods now return a simple numpy array
- Variables don't necessary have a base function anymore
- Without a base function, the default behavior is to return the default value if there is no formula.


* Allow two variable file to have the same name in a tax and benefit system
- A [collision]( between module names made it impossible so far.


* Fix `dtype` attribute for `EnumArray`s (returned when calculating a variable of `value_type` `Enum`):
- It was the type `np.int16` and not the dtype instance `np.dtype(np.int16)`
- This caused issue when trying to export an `EnumArray` with `pandas`


* Fix operators such as `household.first_parent`, `foyer_fiscal.declarant_principal` for multi-entities simulations.
- This issue was not affecting simulations with several persons in a _single_ entity
- The underlying `entity.value_from_person` operator was not working as expected in case the persons of the simulation were not sorted by entity id in the persons vector (see example in 22.0.8 right below).


* Fix `entity.max`, `entity.min`, `entity.all` and `entity.reduce` for multi-entities simulations.
- This issue was not affecting simulations with several persons in a _single_ entity
- These operators were not working as expected in case the persons of the simulation were not sorted by entity id in the persons vector. For instance:
- First household: [Alice, Bob]
- Second household: [Cesar]
- Persons vector: [Alice, Cesar, Bob]


* Update CircleCI configuration to its v2


* Improve parameters performances


* Update country-template dependency to >= 3.0.0, < 4.0.0


* Technical improvement:
* Details:
- Make sure ParameterNode:__repr__ generates a valid YAML representation


* Update numpy dependency
* Details:
- Previously, openfisca-core used features removed on numpy 1.13


- Update openfisca_serve [rst]( documentation
* Make native gunicorn parameters use in `openfisca serve` obvious and make parameters' format more explicit


- Fix a bug that broke the route `calculate` of the legacy web API since `21.0.2`


Breaking changes

- Improve entities projection consistency

Before, there were inconsistencies in the behaviors of projectors:

_For instance, for a simulation that contains 4 persons in 1 household:_

person.household('rent', '2018-02')   The rent paid by the household of the person.
>>> [800, 800, 800, 800]   Has the dimension of persons (4)

salaries = person.household.members('salary', '2018-02')
sum_salary = person.household.sum(salaries)   The sum of the salaries of the person's family
>>> [4000] Has the dimension of household (1)

Now, consistency have been enforced for all entities related helpers (`sum`, `min`, `max`, `all`, `any`, `has_role`, etc.)

person.household('rent', '2018-02')   The rent paid by the household of the person.
>>> [800, 800, 800, 800]   Has the dimension of persons (4)

salaries = person.household.members('salary')
sum_salary = person.household.sum(salaries)   The sum of the salaries of the person's family
>>> [4000, 4000, 4000, 4000]   Has the dimension of persons (4)

This is a breaking change, as all the adaptations (such as [this one]( used to overcome these inconsistensies must be removed.


- Introduce:
- [`person.get_rank(entity, criteria, condition)`](
- [`entity.value_nth_person(k, array, default)`](


New features

- Improve `Tracer`:
- Make aggregation more efficient
- Introduce [`tracer.print_trace`](


- Describe `/spec` endpoint in OpenAPI documentation available at `/spec`


* Technical improvement:
* Details:
- Adapt to version `2.1.0` of Country-Template and version `1.1.3` of Extension-Template.


- Introduce [simulation generator](


- Improve API response time


- Make decompositions more robust


- Fix bug on API `/variable/{id}`
- Encode API `/variable/{id}` output to `utf-8`
- Add tests for `/variable/{id}` and `/parameter/{id}` encoding


Add `--only-variables` and `--ignore-variables` options to `openfisca-run-test` to filter out tested output variables if needed.


- When a variable file is loaded twice in the same python interpreter, make sure the second loading doesn't corrupt the first one.
- This fixes a bug introduced in 21.0.2, which could lead to a corruption of the tax and benefit in rare edge cases


- Fix two bugs that appeared with 21.2.0:
- Properly encode the result of a formula returning an Enum value
- Enable storing an Enum value on disk


New features

- Improve [`holder.get_memory_usage`]((
- Add `nb_requests` and `nb_requests_by_array` fields in the memory usage stats for traced simulations.

- Enable intermediate data storage on disk to avoid memory overflow
- Introduce `memory_config` option in `Simulation` constructor
- This allows fine tuning of memory management in OpenFisca

For instance:

from openfisca_core.memory_config import MemoryConfig
config = MemoryConfig(
max_memory_occupation = 0.95,   When 95% of the virtual memory is full, switch to disk storage
priority_variables = ['salary', 'age']   Always store these variables in memory
variables_to_drop = ['age_elder_for_family_benefit']   Do not store the value of these variables


New features

- Improve `Tracer`:

- Introduce an `aggregate` option in [`tracer.print_computation_log`]( to handle large population simulations.
- Introduce [`tracer.usage_stats`]( to keep track of the number of times a variable is computed.

- Introduce methods to keep track of memory usage:

- Introduce [`holder.get_memory_usage`](
- Introduce `entity.get_memory_usage`
- Introduce `simulation.get_memory_usage`

- Improve `Holder` public interface:

- Enhance [`holder.delete_arrays`]( to be able to remove known values only for a specific period
- Introduce [`holder.get_known_periods`](

- Introduce [`variable.get_formula`](

- Re-introduce `taxscales.combine_tax_scales` to combine several tax scales.


- Deprecate `requested_period_added_value` base function, as it had no effect.


Bug fix

- Fix API response encoding from ascii to utf-8
* Improve user message by displaying `UnicodeDecodeError` information


_Note: the 21.0.1 and 21.0.0 versions have been unpublished due to performance issues_

Breaking changes

Change the way enumerations (Enum) are defined when coding variables


u'Free lodger',


class HousingOccupancyStatus(Enum):
tenant = u'Tenant'
owner = u'Owner'
free_lodger = u'Free lodger'
homeless = u'Homeless'

> Each Enum item has:
> - a `name` property that contains its key (e.g. `tenant`)
> - a `value` property that contains its description (e.g. `"Tenant or lodger who pays a monthly rent"`)

- Enum variables must now have an explicit default value

class housing_occupancy_status(Variable):
possible_values = HousingOccupancyStatus,
default_value = HousingOccupancyStatus.tenant
entity = Household
definition_period = MONTH
label = u"Legal housing situation of the household concerning their main residence"

- In a formula, to compare an Enum variable to a fixed value, use `housing_occupancy_status == HousingOccupancyStatus.tenant`

- To access a parameter that has a value for each Enum item (e.g. a value for `zone_1`, a value for `zone_2` ... ), use fancy indexing

> For example, if there is an enum:
> py
>     class TypesZone(Enum):
>         z1 = "Zone 1"
>         z2 = "Zone 2"
> And two parameters `parameters.city_tax.z1` and `parameters.city_tax.z2`, they can be dynamically accessed through:
> py
> zone = np.asarray([TypesZone.z1, TypesZone.z2, TypesZone.z2, TypesZone.z1])
> zone_value = parameters.rate._get_at_instant('2015-01-01').single.owner[zone]
> returns
> py
> [100, 200, 200, 100]

Change the simulation inputs and outputs for enumeration variables

Web API and YAML tests

- When setting the value of an input Enum variable for a simulation, the user must now send the **string identifier** (e.g. `free_lodger`).
- The item index (e.g. `2`) is not accepted anymore
- The value (e.g. `Free lodger`) is not accepted anymore.

- When calculating an Enum variable through the web API, the output will now be the string identifier.

Python API

- When using the Python API (`set_input`), the three following inputs are accepted:
- The enum item (e.g. HousingOccupancyStatus.tenant)
- The enum string identifier (e.g. "tenant")
- The enum item index, though this is not recommanded.
- If you rely on index, make sure to specify an `__order__` attribute to all your enums to make sure each intem has the right index. See the enum34 [doc](

> Example:
holder = simulation.household.get_holder('housing_occupancy_status')
Three possibilities
holder.set_input(period, np.asarray([HousingOccupancyStatus.owner]))
holder.set_input(period, np.asarray(['owner']))
holder.set_input(period, np.asarray([0]))  Highly not recommanded

- When calculating an Enum variable, the output will be an [EnumArray](


Breaking changes

Change the way Variables are declared

- Replace `column` attribute by `value_type`
* Possible values of `value_type` are:
* `int`
* `float`
* `bool`
* `str`
* `date`
* `Enum`


class basic_income(Variable):
column = FloatCol
entity = Person
definition_period = MONTH
label = "Basic income provided to adults"


class basic_income(Variable):
value_type = float
entity = Person
definition_period = MONTH
label = "Basic income provided to adults"

- `default_value` is now a `Variable` attribute


class is_citizen(Variable):
column = BoolCol(default = True)
entity = Person
definition_period = MONTH
label = "Whether the person is a citizen"


class is_citizen(Variable):
value_type = bool
default_value = True
entity = Person
definition_period = MONTH
label = "Whether the person is a citizen"

- For `Variables` which `value_type` is `str`, `max_lentgh` is now an attribute


class zipcode(Variable):
column = FixedStrCol(max_length = 5)
entity = Menage
label = u"Code INSEE (depcom) du lieu de résidence"
definition_period = MONTH


class zipcode(Variable):
value_type = str
max_length = 5
entity = Menage
label = u"Code INSEE (depcom) du lieu de résidence"
definition_period = MONTH

- For `Variables` which `value_type` is `Enum`, `possible_values` is now an attribute:


class housing_occupancy_status(Variable):
column = EnumCol(
enum = Enum([
u'Free lodger',
entity = Household
definition_period = MONTH
label = u"Legal housing situation of the household concerning their main residence"


class housing_occupancy_status(Variable):
value_type = Enum
possible_values = Enum([
u'Free lodger',
entity = Household
definition_period = MONTH
label = u"Legal housing situation of the household concerning their main residence"

- Remove `PeriodSizeIndependentIntCol`:
* Replaced by `Variable` attribute `is_period_size_independent`

Deprecate `Column`

`Column` are now considered deprecated. Preferably use `Variable` instead.

If you do need a column for retro-compatibility, you can use:

from openfisca_core.columns import make_column_from_variable

column = make_column_from_variable(variable)

- In `TaxBenefitSystem`:
* Remove `neutralize_column` (deprecated since `9.1.0`, replaced by `neutralize_variable`)
* Rename `column_by_name` to `variables`
* Rename `get_column` to `get_variable`
* Remove `update_column`
* Remove `add_column`
* Remove `automatically_loaded_variable` (irrelevant since conversion columns have been removed)
* Move `VariableNotFound` to `errors` module

- In `Holder`:
* Rename `holder.column` to `holder.variable`

- In `Column`:
* `Column` should only be instantiated using `make_column_from_variable`. Former constructors do not work anymore.
* Remove `column.start`, which was `None` since `14.0.0`
* Replace `column.formula_class` by `variable.formula`
* Replace `column.enum` by `variable.possible_values`
* Replace `column.default` by `variable.default_value`

- In `formulas`:
* Rename `get_neutralized_column` to `get_neutralized_variable`
* Remove `new_filled_column`

- In `Variable`:
* Remove `to_column`
* Variables can now directly be instanciated:

class salary(Variable):
entity = Person

salary_variable = salary()

You can learn more about `Variable` by checking its [reference documentation](




Breaking changes

- Change the way the API is started
* The previous command `COUNTRY_PACKAGE=openfisca_country gunicorn ...` does not work anymore
* The new command to serve the API is `openfisca serve`.
* Read more in the [doc](
* This command allows to serve reforms and extensions in the new API

- In `openfisca-run-test` and `openfisca-serve`, rename option `--country_package` to `--country-package`


New features

- Improve the representations of parameters when navigating the legislation in Python.

For instance:


>>> basic_income:


- Track the real visitor IP in the web API
- Handle the nginx proxy


- Add a link in `openAPI.yml` to the OpenFisca documentation page explaining the web API inputs and outputs for the /calculate route.


New features

Add tracing to get details about all the intermediate calculations of a simulation

- Introduce new Web API route `/trace` to get a simulation's detailed calculation steps
- See the [swagger documentation for OpenFisca-France](

- Introduce `simulation.tracer.print_computation_log` to print a simulation's detailed calculation steps
- This is available if the `trace` argument has been set to `True` in the `Simulation` constructor.
- See the [reference documentation]( about the tracer.

_Warning: Both of these features are still currently under experimentation. You are very welcome to use them and send us precious feedback, but keep in mind that the way they are used and the results they give might change without any major version bump._

Breaking changes

- Deprecate and remove:
- `simulation.traceback`
- `simulation.stack_trace`
- `simulation.find_traceback_step`
- `simulation.stringify_input_variables_infos`
- `simulation.stringify_variable_for_period_with_array`

- Remove argument `debug_all` from:
- `Scenario.new_simulation` method
- `Simulation` constructor


- Add the possibility to track API visitor's IP


- Enable to calculate parameters according to a variable

For instance, if a parameter `rate` depends on a variable `zone` that can take the values `z1` or `z2`:

In `rate.yaml`:

value: 100
value: 200

Then it is now possible to use:

zone = household('zone', period)
rate = parameters(period).rate[zone]

For more information, check the [documentation](


- Fix migration script ``
- The attributes `reference` of nodes `END`, `VALUE`, `PLACEHOLDER`, `BAREME`, `TRANCHE`, `ASSIETTE`, `TAUX`, `MONTANT`, `SEUIL` were not parsed. Now they are parsed to YAML.


- Reference the new address of the documentation


- Allow to document entities and entities roles
- Add attribute `Entity.doc` (e.g. `Household.doc`)
- Add attribute `Role.doc` (e.g. `Household.CHILD.doc`)


Minor Change

- Handle the case where the user accidentally puts a coma at the end of a variable reference so it has no consequence on the API output.
- All variable references are transformed into lists of strings.


Breaking changes

Parameter files

* Load the legislation parameters from a directory `parameters` containing YAML files, instead of XML files

<NODE code="root">
<NODE code="impot">
<CODE code="taux" description="" format="percent">
<END deb="2016-01-01"/>
<VALUE deb="2015-01-01" valeur="0.32" />
<VALUE deb="1998-01-01" valeur="0.3" />

description: Taux d'impôt sur les salaires
unit: /1
value: null
value: 0.32
value: 0.3

- The XML attributes `format` and `type` are replaced by the YAML attribute `unit`, which is a free text field.


* Rename `Reform.modify_legislation_json()` -> `Reform.modify_parameters()`
* Remove `reforms.compose_reforms()`.
* Remove `reforms.update_legislation()`.
- To modify an existing parameter, use `ValuesHistory.update()` instead.
- You can navigate the parameters using `.` (e.g. `parameters.taxes.tax_on_salaries.public_sector.rate`)
- Before:
new_legislation_parameters = update_legislation(
legislation_json = original_legislation_parameters,
path = ('children', 'impot_revenu', 'children', 'bareme', 'brackets', 1, 'threshold'),
period = reform_period,
value = 6011,

- Now:
parameters.impot_revenu.bareme[1].threshold.update(period = reform_period, value = 6011)

* Change the syntax to dynamically create new parameters
- Before :
reform_legislation_subtree = {
"type": "Node",
"description": "PLF 2016 sur revenus 2015",
"children": {
"decote_seuil_celib": {
"type": "Parameter",
"description": "Seuil de la décôte pour un célibataire",
"format": "integer",
"unit": "currency",
"values": [
{'start': u'2016-01-01', },
{'start': u'2015-01-01', 'value': round(1135 * (1 + inflation))},
"decote_seuil_couple": {
"type": "Parameter",
"description": "Seuil de la décôte pour un couple",
"format": "integer",
"unit": "currency",
"values": [
{'start': u'2065-01-01', },
{'start': u'2015-01-01', 'value': round(1870 * (1 + inflation))},
reference_legislation_copy['children']['plf2016_conterfactual'] = reform_legislation_subtree

- Now:
from openfisca_core.parameters import ParameterNode

inflation = .001
reform_parameters_subtree = ParameterNode('plf2016_conterfactual', data = {
'decote_seuil_celib': {
'values': {
"2015-01-01": {'value': round(1135 * (1 + inflation))},
"2016-01-01": {'value': None}
'decote_seuil_couple': {
'values': {
"2015-01-01": {'value': round(1870 * (1 + inflation))},
"2065-01-01": {'value': None}
reference_parameters.add_child('plf2016_conterfactual', reform_parameters_subtree)

- Note that this way of creating parameters is only recommanded when using dynamically computed values (for instance `round(1135 * (1 + inflation))` in the previous example). If the values are static, the new parameters can be directly built from YAML (See New features section).


* Remove parameter `legislation_json` in constructor
* Remove methods/attributes:
- `compact_legislation_by_instant_cache`
- `get_baseline_compact_legislation`
- `compute_legislation`
- `get_legislation`
+ We can now directly use the `parameters` attribute.
* Rename
- `preprocess_legislation` -> `preprocess_parameters`
- `add_legislation_params` -> `load_parameters`
- `get_compact_legislation` -> `get_parameters_at_instant`
+ The signature of the method has changed. Check the [documentation](


* Remove methods/attributes:
- `compact_legislation_by_instant_cache`
- `get_baseline_compact_legislation`
* Rename
`baseline_compact_legislation_by_instant_cache` -> `baseline_parameters_at_instant_cache`
`legislation_at` -> `parameters_at`

New features

* In reforms, new parameters can be added from a YAML file.
- The function `parameters.load_parameter_file()` loads a YAML file.
- The function `ParameterNode.add_child()` adds a new child to an existing legislation node.
- Example:
import os
from openfisca_core.parameters import load_parameter_file

dir_path = os.path.dirname(__file__)

def reform_modify_parameters(parameters):
file_path = os.path.join(dir_path, 'plf2016.yaml')
reform_parameters_subtree = load_parameter_file(name = 'plf2016', file_path=file_path)
parameters.add_child('plf2016', reform_parameters_subtree)
return parameters


* In module model_api, add classes that are needed to build reforms:
- `load_parameter_file`
- `ParameterNodeNode`
- `Scale`
- `Bracket`
- `Parameter`
- `ValuesHistory`
- `periods.period`.

Technical changes

* Refactor the internal representation and the interface of legislation parameters
- The parameters of a legislation are wraped into the classes `Node`, `Parameter`, `Scale`, `Bracket`, `ValuesHistory`, `ValueAtInstant` instead of bare python dict.
- The parameters of a legislation at a given instant are wraped into the classes `NodeAtInstant`, `ValueAtInstant` and tax scales instead of bare python objects.
- The file `` and the classes defined inside are responsible both for loading and accessing the parameters. Before the loading was implemented in `` and the other processings were implemented in ``
- The validation of the XML files was performed against a XML schema defined in `legislation.xsd`. Now the YAML files are loaded with the library `yaml` and then validated in basic Python.

* The word "legislation" is replaced by the word "parameters" in several internal variables and internal methods. It Reduced the ambiguity between the legislation as a tax and benefit system and the legislation as the parameters.
- `TaxBenefitSystem.compact_legislation_by_instant_cache` -> `TaxBenefitSystem._parameters_at_instant_cache`
- `TaxBenefitSystem.get_baseline_compact_legislation()` -> `TaxBenefitSystem._get_baseline_parameters_at_instant()`
- `Simulation.compact_legislation_by_instant_cache` -> `Simulation._parameters_at_instant_cache`
- `Simulation.get_compact_legislation()` -> `Simulation._get_parameters_at_instant()`
- `Simulation.get_baseline_compact_legislation()` -> `Simulation._get_baseline_parameters_at_instant()`

* The optionnal parameter `traced_simulation` is removed in function `TaxBenefitSystem.get_compact_legislation()` (now `TaxBenefitSystem.get_parameters_at_instant()`). This parameter had no effect.

* The optional parameter `with_source_file_infos` is removed in functions `TaxBenefitSystem.compute_legislation()` (now `TaxBenefitSystem._compute_parameters()`) and `TaxBenefitSystem.get_legislation()`. This parameter had no effect.

* In the API preview, update the internal transformation of the parameters.

* In the directory `script`, add a subdirectory `migrations`.


- Support `reference` attributes on all parameter XML nodes.
- You can now add a `reference` on a `<VALUE>`, for example.


In the preview web API, for variables of type `Enum`:

* Accept and recommend to use strings as simulation inputs, instead of the enum indices.
- For instance, `{"housing_occupancy_status": {"2017-01": "Tenant"}}` is now accepted and prefered to `{"housing_occupancy_status": {"2017-01": 0}}`).
- Using the enum indices as inputs is _still accepted_ for backward compatibility, but _should not_ be encouraged.
* Return strings instead of enum indices.
- For instance, is `housing_occupancy_status` is calculated for `2017-01`, `{"housing_occupancy_status": {"2017-01": "Tenant"}}` is now returned, instead of `{"housing_occupancy_status": {"2017-01": 0}}`.
* In the `/variable/<variable_name>` route, document possible values.
* In the Open API specification, document possible values following JSON schema.
* In the `/variable/<variable_name>` route:
- Document possible values
- Use a string as a default value (instead of the enum default indice)
* In the Open API specification, document possible values following JSON schema.


Minor Change

* Enhance logs
- Replace prints by proper logs
- Give clear and concise feedback to users when a formula cannot compute.


* Enable API monitoring with Piwik
- See the [documentation](


Breaking changes - [545](

* Deprecate `parsers`
- They can no longer be installed through `pip install openfisca_core[parsers]`
- They can still install them directly with `pip install openfisca_parsers`, but they won't be maintained.


Bug fix

- Make `missing_value` base function compatible with v4 syntax and extra params


Breaking changes - [525](

* Rename `Variable` attribute `url` to `reference`
- This attribute is the legislative reference of a variable.
- As previously, this attribute can be a string, or a list of strings.
* Rename `Variable` attribute `reference` to `baseline_variable`
- This attibute is, for a variable defined in a reform, the baseline variable the reform variable is replacing.
* Remove variable attribute `law_reference`
* Rename `TaxBenefitSystem.reference` to `TaxBenefitSystem.baseline`
* Rename `TaxBenefitSystem.get_reference_compact_legislation` to `TaxBenefitSystem.get_baseline_compact_legislation`
* Rename `Simulation.reference_compact_legislation_by_instant_cache` to `Simulation.baseline_compact_legislation_by_instant_cache`
* Rename `Simulation.get_reference_compact_legislation` to `Simulation.get_baseline_compact_legislation`
* Rename parameter `reference` of `AbstractScenario.new_simulation()` to `use_baseline`
* Rename parameter `reference` of `Simulation.legislation_at()` to `use_baseline`


New features

- In the preview API `/calculate` route
- Handle roles with no plural
- Force all persons to be allocated to all entities
- Improve error messages
- Detect unexpected entity errors first
- Document new simulation and entities constructors.


Minor Change

- Rewrite `/calculate` example in the Open API spec so that it works for `Openfisca-France`


Bug fix

- Fix `formula.graph_parameters` and `formula.to_json`
- Bugs were introduced in `14.0.0`

- Fix `simulation.graph`
- A bug was introduced in `14.1.0`


Bug fix

- Fix `simulation.clone` and `entity.clone` methods.
- A bug was introduced in `14.1.0`


New features

- Introduce `/calculate` route in the preview API
- Allows to run calculations.
- Takes a simulation `JSON` as an input, and returns a copy of the input extended with calculation results.

- Handle `500` errors in the preview API
- In this case, the API returns a JSON with details about the error.

- Allows simulations to be built from a JSON using their constructor
- For instance `Simulation(simulation_json = {"persons": {...}, "households": {...}}, tax_benefit_system = tax_benefit_system)`

- Allows entities to be built from a JSON using their constructor
- For instance `Household(simulation, {"first_household": {...}})`

- Introduce `tax_benefit_system.get_variables(entity = None)`
- Allows to get all variables contained in a tax and benefit system, with filtering by entity


- Deprecate `simulation.holder_by_name`, `simulation.get_holder`, `get_or_new_holder`
- These functionalities are now provided by `entity.get_holder(name)`

- Deprecate constructor `Holder(simulation, column)`
- A `Holder` should now be instanciated with `Holder(entity = entity, column = column)`


* Improve error message and add stack trace when a module import fails


Breaking changes

- In variables:
- Merge `Variable` and `DatedVariable`.
- `Variable` can now handle formula evolution over time.
- Remove `start_date` attribute
- Rename `stop_date` attribute to `end`
- Introduce end string format `end = 'YYYY-MM-DD'`
- In formulas:
- Merge `SimpleFormula` and `DatedFormula`.
- `Formula` evolves over time.
- Remove `dated_function`
- start definition goes to formula name: `formula_YYYY[_MM[_DD]]`
- stop is deduced from next formula start


class your_variable(DatedVariable):
... attributes
start_date =, 05, 01)
stop_date =, 05, 31)

openfisca chooses most restrictive start in (start_date, dated_function start)
dated_function(start = date(2015, 1, 1), stop = date(2016, 12, 31))
def function_2015_something(self, simulation, period):
Calculate for 2015

dated_function(start = date(2016, 1, 1))
def function__different_name(self, simulation, period):
Calculate for 2016 > 2017-05-31 (including 2017-05-31 stop_date day)


class your_variable(Variable):
... unchanged attributes
end = '2017-05-31'   string format 'YYYY-MM-DD'

name should begin with 'formula' / you define the start in the name
def formula_2015_05_01(self, simulation, period):   stops on last day before next formula
Calculate for 2015

def formula_2016(self, simulation, period):   similar to formula_2016_01_01 or formula_2016_01
Calculate for 2016+ > 2017-05-31 (including 2017-05-31 end day)

New features

- Change `ETERNITY` period effect
- Remove restriction that prevented formula changes over time for a variable with `definition_period = ETERNITY`.


Bug fix

* Require numpy < 1.13.
- Openfisca is not yet compatible with the new numpy version 1.13.


Breaking changes

* Disallow text out of tags in XML parameters
- This prevents to add "comments" that would be lost by automated transformation of these parameters.

New features

* Introduce a "reference" attribute to document a source in XML parameters


* Serve the [OpenAPI specification]( under the API route `/spec/`


* Use `nose` in the `openfisca-run-test` script
- This avoids boilerplate code on country packages, and makes parallelism easier to set on Circle CI.


* Fix package naming conflict between the preview API and the official one.
* Fix import error


* Validate XML parameters with lxml and a XML Schema
* Raise nicer errors during validation


* Improve the error when the period argument is forgotten in entity call


* When replacing a variable by another one in a reform, assume the new variable has the same metadata than the reference one.
- The is currently the behaviour for all other metadata.


* Include the preview API into OpenFisca-Core
* Remove internationalization (`i18n`, `Babel`)
* Use CircleCI instead of Travis


* Fix variable `source_file_path` computation.
- Make sure the tax and benefit system `location` metadata is consistent with the actual python files being loaded.


* Fix a bug introduced by 11.0.0: variables with several references could not be loaded.


* Fix a bug introduced by 12.0.0: the description of a parameter node was no longer exported in the parameter JSON.


Breaking changes

* Deprecate and remove the `fin` attribute in XML parameters.
- The end date of a parameter is assumed to be the start of the next one.
- The `<END>` indicates that a parameter does not exist anymore
* Deprecate and remove the `fuzzy` attribute in XML parameters.
- By construction, the value of a parameter is always extended towards the future.
- To indicate a likely change of the legislation, a `<PLACEHOLDER>` can be added.
* Deprecate and remove `reforms.create_item`
- New items are created directly with the method `reforms.update_items`.
* Deprecate and remove `reforms.split_item_containing_instant`
- Splitting items does not make sense in the new convention. Use `reform.update_items` to update the parameters.


Breaking changes

These breaking changes only concern variable and tax and benefit system **metadata**. They **do not** impact calculations.

* Make `tax_benefit_system.get_package_metadata()` return a `dict` instead of a `tuple`
* Make `column.source_file_path` a relative path (was absolute before)
* Make `column.url` a list instead of a string

New features

* Make `tax_benefit_system.get_package_metadata()` more robust
- Handle reforms
- Handle tax and benefit systems that are not defined within a package and/or a distribution

Technical changes

* Turn `Variable`s with a `start_date` and/or a `stop_date` into `DatedVariable`s
- This is transparent for users.


* Do not cache values for neutralized variables
- To reduce memory usage for large population simulations


* Improve the raised error message when a wrong period type is given as an input


Breaking changes

* In YAML tests:
- Deprecate and remove the `IGNORE_` prefix
- Deprecate and remove the `ignore` property
* In the YAML test runner:
- Deprecate and remove the `force` option (`-f` in the shell script)
- Deprecate and remove the `default_absolute_error_margin` option (`-M` in the shell script)
- Deprecate and remove the `default_relative_error_margin` option (`-m` in the shell script)

New features

* Add `Reform` and `numpy.round` (as `round_`) in the model API
* Introduce `tax_benefit_system.apply_reform(reform_path)`
* Allow YAML tests to declare the reforms they need to be executed (through the `reforms` property)

Technical changes

* Move the `dummy_extension` to `OpenFisca-Dummy-Country`
* Test `openfisca-run-test` script


* Rename `neutralize_column` to `neutralize_variable`
- Deprecate `neutralize_column` without removing it
* Document `neutralize_variable`


* Fix spelling in error messages


* Test marginal scales
* Move tests out of the main package
* These changes are transparent for users


* Make sure identic periods are stringified the same way
* _Breaking changes_:
- Change `periods.period` signature.
- It now only accepts strings.
- Restrict the possible inputs for `periods.period`
- The authorized formats are listed in [the doc](
- Deprecate and remove:
- `periods.json_or_python_to_period`
- `periods.make_json_or_python_to_period`


* Move the dummy country to [its own repository](


* Raise more explicit error when an invalid test case is given
* Raise more friendly error when trying to calculate a variable which doesn't exist
* _Breaking change_: Python exceptions will now be raised when the test case in invalid. Before, only a byriani error was returned. Reusers must therefore adapt their exception handling.


* Add `Entity.to_json` method. Used by OpenFisca-Web-API in `/entity` endpoint in particular.


* Declare `Openfisca-Parsers` as an optional dependency of `Openfisca-Core`.


* Make it mandatory to provide a period when calculating a variable.
- When a computation is requested (with *.calculate_output, entities.__call__, *.calculate[_add|_divide], *.compute[_add|_divide]), the argument `period` is no longer optional.
- Previously, the period of the simulation was used instead of a missing period. It was error-prone, as values would be returned for the wrong period, without any error or warning to alert the formula writer about a likely coding error.


* Move `` content (file usually located in country packages) to core module `formula_toolbox` so that it can be reused by all countries
* Use `AbstractScenario` if no custom scenario is defined for a tax and benefit sytem


Breaking changes

* Add **mandatory** attribute `definition_period` to variables
* Enforce that inputs provided for a variable match the variable `definition_period`
- If a `set_input` attribute has been defined, automatically cast the input accordingly.
* Change the expected output of a formula
- Only `result` must be returned, instead of `period, result`
* Deprecate and remove:
- `simulation.print_trace`
- `simulation.calculate_add_divide` and `simulation.compute_add_divide`
- `last_duration_last_value` base function
- `variables_name_to_skip` and `use_set_input_hooks` parameters in `scenario.fill_simulation`
- `holders.new_test_case_array`
* Deprecate and forbid `dated_holder.array = ...`
* Raise an error when inconsistent year and month inputs provided for a variable
- Before, the year value would be silently ignored.
* Rename `period.this_month` to `period.first_month`

Technical changes

* Make sure the cache only store values for periods matching the variable `definition_period`
* Use a cache buffer in simulation initialisation when axes are used, to avoid `set_input` conflicts
* Make `DatedHolder` only a wrapper of a variable value for a given period, and no more a dated view of a `Holder`


* the attribute `definition_period` is documented here :


* Add `TaxBenefitSystem` doc to the reference doc
- This is transparent for all users


* Improve `openfisca-run-test` script
- Make country package detection more robust (it only worked for packages installed in editable mode)
- Use spaces instead of commas as separator in the script arguments when loading several extensions or reforms (this is more standard)
* Refactor the `scripts` module to seperate the logic specific to yaml test running from the one that can be re-used by any script which needs to build a tax and benefit system.


* Move `json_or_python_to_test_case` from country packages to core
* Breaking change: `scenarios.set_entities_json_id` has been moved, and should not be considered a public function.


* Bug fix : handle the case when is None.


* Refactor decomposition TaxBenefitSystem attributes. Reform inherit the decomposition_file_path from the reference TaxBenefitSystem.
This does not require changing anything from the caller, which should use the `decompositions.get_decomposition_json` function instead of those attributes.


* Fix occasionnal `NaN` creation in `MarginalRateTaxScale.calc` resulting from `0 * np.inf`


* Use the actual TaxBenefitSystem and not its reference when neutralizing a column.


* Fix `to_value_json` for `DatedVariable` with extra parameters.

This was causing a crash when calculating intermediate variables with the API.

Unlike simple formulas, a `DatedVariable` have several functions. We thus need to select the right one according to the period before doing parameters introspection.


* Fix `set_input` and `default` setting in `new_filled_column`


* Add reference documentation


* Fix permanent and period size independent variables neutralization


* Introduce a YAML test runner in openfisca_core
- Introduce command line tool `openfisca-run-test`

* Refactor the dummy tax benefit system included in openfisca-core
- Make the dummy country look like a real one
- Split defining the country from testing


* Improve docstring of `MarginalTaxRate.inverse` and add test


* Decrease verbosity of `combine_tax_scales`


* Enable `extra_params` in formulas with new syntax.


* Fixup 4.1.2:
* When building positions, handle cases where persons belonging to an entity are not grouped by entity in the persons array.


* Fix bug in entity.sum


* Enable simulation initialization with only legacy roles
* New roles are in this case automatically infered
* Positions are always infered from persons entity id


* Fix update_legislation in reforms


* Add `conflicts` and `origin` fields to xml params (needed for baremes IPP importation)


* Refactor formula syntax

- Don't use the object simulation in formula writing. The entity the variable is calculated for is now the first argument of the formula, for instance `person` or `family`.

- The `legislation` is now the (optional) third argument of a formula. It is a function that can be called with a period (or an instant) for argument, and will compute the legislation at `period.start`.

-  Don't use `calculate_add` and equivalents. Instead, `add` and `divide` are just given in the `options` argument, for instance `options = [ADD]`.

- Rename `entity_class` to `entity`.

- Don't explicitly use a `calculate` method, but the `person('salary', period)` notation instead.

* Introduce implicit conversions between entities, and improve aggregations formulas.

* Deprecate PersonToEntityColumn and EntityToPersonColumn

* Change the way entities are declared

More information on


* Add a `DeprecationWarning` when using a `DateCol` with no `default`, but keep the default date to 1970-01-01.
* Enforce `DateCol.default` to be a `date`.


* Fix `cerfa_field` validation in `Column`, `Formula` and `AbstractConversionVariable`.
Previously, some variables having `cerfa_field` as a `dict` were converted to `unicode` by mistake.


* Move `` to [OpenFisca-Survey-Manager](

No incidence on users since it was only needed for dataframes.


* Adapt requested_period_last_value and last_duration_last_value to extra params


* Update introspection data. This allows to enhance data served by the web API which itself feeds the Legislation Explorer.


* Update travis procedures


* Remove conda from travis config


* Implement simulation.calculate `print_trace=True` argument. Options: `max_depth` and `show_default_values`

simulation = scenario.new_simulation(trace=True)
simulation.calculate('irpp', 2014, print_trace=True)
simulation.calculate('irpp', 2014, print_trace=True, max_depth=-1)
simulation.calculate('irpp', 2014, print_trace=True, max_depth=-1, show_default_values=False)


* Load extensions from pip packages


* Use DEFAULT_DECOMP_FILE attribute from reference TB system


* Explicit the error when a variable is not found


* Update numpy dependency to 1.11


* Force updating version number and before merging on master
* Release tag and Pip version automatically


* Variables are not added to the TaxBenefitSystem when the entities class are imported, but explicitely when the TaxBenefitSystem is instanciated.
* Metaclasses are not used anymore.
* New API for TaxBenefitSystem
* Columns are now stored in the TaxBenefitSystem, not in entities.
* New API for rerforms.
* XmlBasedTaxBenefitSystem is deprecated, and MultipleXmlBasedTaxBenefitSystem renamed to TaxBenefitSystem


* Implement cache opt out system


* Remove `build_column` obsolete function. Use `Variable` class instead.




* Merge pull request 382 from openfisca/fix-sum-by-entity
* The result size must be the targent entity'one


* Many updates


* Add trim option to marginal rate computation
* Compute stop date of whole tax scale instead of a single bracket.
* Use bracket stop date instead of legislation stop date inside a bracket.
* Introduce reference periods
* Fix roles_count bug : was set to 1 for scenarios vectorially defined


* Move docs to gitbook repo
* Upgrade to new Travis infrastructure
* Enhance errors display when a reform modifies the legislation


* First release uploaded to PyPI