OpenFisca-Core 44.2.1__tar.gz → 44.3.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/CHANGELOG.md +20 -0
  2. {openfisca_core-44.2.1 → openfisca_core-44.3.0/OpenFisca_Core.egg-info}/PKG-INFO +1 -1
  3. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/OpenFisca_Core.egg-info/SOURCES.txt +15 -0
  4. {openfisca_core-44.2.1/OpenFisca_Core.egg-info → openfisca_core-44.3.0}/PKG-INFO +1 -1
  5. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/_core_entity.py +40 -0
  6. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/_enum_type.py +1 -1
  7. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/_utils.py +18 -18
  8. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/enum_array.py +2 -4
  9. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/types.py +2 -1
  10. openfisca_core-44.3.0/openfisca_core/links/__init__.py +36 -0
  11. openfisca_core-44.3.0/openfisca_core/links/implicit.py +73 -0
  12. openfisca_core-44.3.0/openfisca_core/links/link.py +109 -0
  13. openfisca_core-44.3.0/openfisca_core/links/many2one.py +227 -0
  14. openfisca_core-44.3.0/openfisca_core/links/one2many.py +242 -0
  15. openfisca_core-44.3.0/openfisca_core/links/tests/__init__.py +58 -0
  16. openfisca_core-44.3.0/openfisca_core/links/tests/test_benchmark.py +93 -0
  17. openfisca_core-44.3.0/openfisca_core/links/tests/test_edge_cases.py +467 -0
  18. openfisca_core-44.3.0/openfisca_core/links/tests/test_implicit.py +76 -0
  19. openfisca_core-44.3.0/openfisca_core/links/tests/test_integration.py +192 -0
  20. openfisca_core-44.3.0/openfisca_core/links/tests/test_many2one.py +121 -0
  21. openfisca_core-44.3.0/openfisca_core/links/tests/test_one2many.py +112 -0
  22. openfisca_core-44.3.0/openfisca_core/links/tests/test_one2many_logic.py +398 -0
  23. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/populations/group_population.py +81 -21
  24. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/populations/population.py +7 -5
  25. openfisca_core-44.3.0/openfisca_core/populations/tests/test_members_position.py +116 -0
  26. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/simulation.py +48 -0
  27. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/abstract_rate_tax_scale.py +1 -1
  28. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/abstract_tax_scale.py +2 -2
  29. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/tax_scale_like.py +2 -2
  30. openfisca_core-44.3.0/openfisca_web_api/scripts/__init__.py +0 -0
  31. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/pyproject.toml +1 -1
  32. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/setup.py +1 -1
  33. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/LICENSE +0 -0
  34. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/MANIFEST.in +0 -0
  35. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/OpenFisca_Core.egg-info/dependency_links.txt +0 -0
  36. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/OpenFisca_Core.egg-info/entry_points.txt +0 -0
  37. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/OpenFisca_Core.egg-info/requires.txt +0 -0
  38. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/OpenFisca_Core.egg-info/top_level.txt +0 -0
  39. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/README.md +0 -0
  40. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/__init__.py +0 -0
  41. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/__init__.py +0 -0
  42. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/dummy.py +0 -0
  43. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/formulas.py +0 -0
  44. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/misc.py +0 -0
  45. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/py.typed +0 -0
  46. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/rates.py +0 -0
  47. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/tests/__init__.py +0 -0
  48. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/tests/test_dummy.py +0 -0
  49. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/tests/test_formulas.py +0 -0
  50. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/commons/tests/test_rates.py +0 -0
  51. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/data_storage/__init__.py +0 -0
  52. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/data_storage/in_memory_storage.py +0 -0
  53. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/data_storage/on_disk_storage.py +0 -0
  54. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/data_storage/types.py +0 -0
  55. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/__init__.py +0 -0
  56. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/_description.py +0 -0
  57. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/entity.py +0 -0
  58. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/group_entity.py +0 -0
  59. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/helpers.py +0 -0
  60. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/py.typed +0 -0
  61. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/role.py +0 -0
  62. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/tests/__init__.py +0 -0
  63. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/tests/test_entity.py +0 -0
  64. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/tests/test_group_entity.py +0 -0
  65. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/tests/test_role.py +0 -0
  66. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/entities/types.py +0 -0
  67. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/__init__.py +0 -0
  68. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/cycle_error.py +0 -0
  69. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/empty_argument_error.py +0 -0
  70. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/nan_creation_error.py +0 -0
  71. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/parameter_not_found_error.py +0 -0
  72. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/parameter_parsing_error.py +0 -0
  73. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/period_mismatch_error.py +0 -0
  74. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/situation_parsing_error.py +0 -0
  75. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/spiral_error.py +0 -0
  76. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/variable_name_config_error.py +0 -0
  77. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/errors/variable_not_found_error.py +0 -0
  78. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/experimental/__init__.py +0 -0
  79. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/experimental/_errors.py +0 -0
  80. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/experimental/_memory_config.py +0 -0
  81. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/formula_helpers.py +0 -0
  82. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/holders/__init__.py +0 -0
  83. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/holders/helpers.py +0 -0
  84. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/holders/holder.py +0 -0
  85. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/holders/tests/__init__.py +0 -0
  86. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/holders/tests/test_helpers.py +0 -0
  87. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/holders/types.py +0 -0
  88. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/__init__.py +0 -0
  89. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/_errors.py +0 -0
  90. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/_guards.py +0 -0
  91. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/config.py +0 -0
  92. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/enum.py +0 -0
  93. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/py.typed +0 -0
  94. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/tests/__init__.py +0 -0
  95. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/tests/test_enum.py +0 -0
  96. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/indexed_enums/tests/test_enum_array.py +0 -0
  97. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/memory_config.py +0 -0
  98. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/model_api.py +0 -0
  99. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/__init__.py +0 -0
  100. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/at_instant_like.py +0 -0
  101. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/config.py +0 -0
  102. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/helpers.py +0 -0
  103. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/parameter.py +0 -0
  104. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/parameter_at_instant.py +0 -0
  105. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/parameter_node.py +0 -0
  106. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/parameter_node_at_instant.py +0 -0
  107. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/parameter_scale.py +0 -0
  108. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/parameter_scale_bracket.py +0 -0
  109. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/values_history.py +0 -0
  110. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/parameters/vectorial_parameter_node_at_instant.py +0 -0
  111. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/__init__.py +0 -0
  112. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/_errors.py +0 -0
  113. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/_parsers.py +0 -0
  114. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/config.py +0 -0
  115. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/date_unit.py +0 -0
  116. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/helpers.py +0 -0
  117. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/instant_.py +0 -0
  118. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/period_.py +0 -0
  119. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/py.typed +0 -0
  120. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/__init__.py +0 -0
  121. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/helpers/__init__.py +0 -0
  122. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/helpers/test_helpers.py +0 -0
  123. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/helpers/test_instant.py +0 -0
  124. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/helpers/test_period.py +0 -0
  125. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/test_instant.py +0 -0
  126. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/test_parsers.py +0 -0
  127. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/periods/tests/test_period.py +0 -0
  128. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/populations/__init__.py +0 -0
  129. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/populations/_core_population.py +0 -0
  130. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/populations/_errors.py +0 -0
  131. {openfisca_core-44.2.1/openfisca_core/scripts/assets → openfisca_core-44.3.0/openfisca_core/populations/tests}/__init__.py +0 -0
  132. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/populations/types.py +0 -0
  133. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/projectors/__init__.py +0 -0
  134. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/projectors/entity_to_person_projector.py +0 -0
  135. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/projectors/first_person_to_entity_projector.py +0 -0
  136. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/projectors/helpers.py +0 -0
  137. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/projectors/projector.py +0 -0
  138. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/projectors/typing.py +0 -0
  139. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/projectors/unique_role_to_entity_projector.py +0 -0
  140. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/rates.py +0 -0
  141. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/reforms/__init__.py +0 -0
  142. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/reforms/in_yaml_test_reform.py +0 -0
  143. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/reforms/reform.py +0 -0
  144. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/reforms/reform_excel.py +0 -0
  145. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/__init__.py +0 -0
  146. {openfisca_core-44.2.1/openfisca_core/scripts/migrations → openfisca_core-44.3.0/openfisca_core/scripts/assets}/__init__.py +0 -0
  147. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/assets/index.html +0 -0
  148. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/find_placeholders.py +0 -0
  149. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/measure_numpy_condition_notations.py +0 -0
  150. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/measure_performances.py +0 -0
  151. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/measure_performances_fancy_indexing.py +0 -0
  152. {openfisca_core-44.2.1/openfisca_core/scripts/migrations/v16_2_to_v17 → openfisca_core-44.3.0/openfisca_core/scripts/migrations}/__init__.py +0 -0
  153. {openfisca_core-44.2.1/openfisca_core/variables/tests → openfisca_core-44.3.0/openfisca_core/scripts/migrations/v16_2_to_v17}/__init__.py +0 -0
  154. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/migrations/v16_2_to_v17/legislation.xsd +0 -0
  155. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_country_template.py +0 -0
  156. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_extension_template.py +0 -0
  157. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/migrations/v24_to_25.py +0 -0
  158. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/openfisca_command.py +0 -0
  159. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/remove_fuzzy.py +0 -0
  160. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/run_test.py +0 -0
  161. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/scripts/simulation_generator.py +0 -0
  162. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulation_builder.py +0 -0
  163. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/__init__.py +0 -0
  164. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/_build_default_simulation.py +0 -0
  165. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/_build_from_variables.py +0 -0
  166. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/_type_guards.py +0 -0
  167. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/helpers.py +0 -0
  168. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/simulation_builder.py +0 -0
  169. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/simulations/typing.py +0 -0
  170. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxbenefitsystems/__init__.py +0 -0
  171. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxbenefitsystems/tax_benefit_system.py +0 -0
  172. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/__init__.py +0 -0
  173. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/amount_tax_scale_like.py +0 -0
  174. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/helpers.py +0 -0
  175. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/linear_average_rate_tax_scale.py +0 -0
  176. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/marginal_amount_tax_scale.py +0 -0
  177. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/marginal_rate_tax_scale.py +0 -0
  178. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/rate_tax_scale_like.py +0 -0
  179. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/taxscales/single_amount_tax_scale.py +0 -0
  180. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tools/__init__.py +0 -0
  181. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tools/parallel_plugin.py +0 -0
  182. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tools/simulation_dumper.py +0 -0
  183. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tools/test_runner.py +0 -0
  184. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/__init__.py +0 -0
  185. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/computation_log.py +0 -0
  186. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/flat_trace.py +0 -0
  187. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/full_tracer.py +0 -0
  188. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/performance_log.py +0 -0
  189. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/simple_tracer.py +0 -0
  190. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/trace_node.py +0 -0
  191. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/tracers/tracing_parameter_node_at_instant.py +0 -0
  192. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/types.py +0 -0
  193. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/variables/__init__.py +0 -0
  194. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/variables/config.py +0 -0
  195. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/variables/helpers.py +0 -0
  196. {openfisca_core-44.2.1/openfisca_web_api → openfisca_core-44.3.0/openfisca_core/variables/tests}/__init__.py +0 -0
  197. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/variables/tests/test_definition_period.py +0 -0
  198. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/variables/variable.py +0 -0
  199. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/warnings/__init__.py +0 -0
  200. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/warnings/libyaml_warning.py +0 -0
  201. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_core/warnings/tempfile_warning.py +0 -0
  202. {openfisca_core-44.2.1/openfisca_web_api/scripts → openfisca_core-44.3.0/openfisca_web_api}/__init__.py +0 -0
  203. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/app.py +0 -0
  204. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/errors.py +0 -0
  205. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/handlers.py +0 -0
  206. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/loader/__init__.py +0 -0
  207. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/loader/entities.py +0 -0
  208. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/loader/parameters.py +0 -0
  209. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/loader/spec.py +0 -0
  210. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/loader/tax_benefit_system.py +0 -0
  211. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/loader/variables.py +0 -0
  212. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/openAPI.yml +0 -0
  213. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/openfisca_web_api/scripts/serve.py +0 -0
  214. {openfisca_core-44.2.1 → openfisca_core-44.3.0}/setup.cfg +0 -0
@@ -1,5 +1,25 @@
1
1
  # Changelog
2
2
 
3
+ ## 44.3.0
4
+
5
+ #### New Features
6
+
7
+ - **Generic Entity Links (Phase 1-6)**: Introduced a new Liam2-inspired generic entity linking system avoiding rigid hierarchies like `Person -> Household`.
8
+ - Added new `Many2OneLink` and `One2ManyLink` models to create powerful inter-entity networks (e.g., `Person -> Employer`).
9
+ - Added implicit links directly binding members arrays. This powers the new `population.links` property natively inside `TaxBenefitSystem.instantiate_entities()`.
10
+ - Full capability to chain relationships via python: `person.mother.household.get("rent", period)`.
11
+ - Powerful vectorized declarative aggregations out-of-the-box (e.g., `households.persons.sum("salary", period, condition=is_female)`).
12
+
13
+ #### Technical Changes
14
+
15
+ - Backward compatibility is 100% maintained. Existing syntax via Projectors natively redirects to implicit links via modified `__getattr__`.
16
+
17
+ ## 44.2.2
18
+
19
+ #### Bug fixes
20
+
21
+ - Fix enum index overflow for enums with more than 256 members (e.g. NAF). Index arrays were encoded as `uint8` (0-255), causing indices > 255 to be truncated and wrong values in simulations. Encoding now uses `int16` (`ENUM_ARRAY_DTYPE`) consistently.
22
+
3
23
  ## 44.2.1 [#1341](https://github.com/openfisca/openfisca-core/pull/1341)
4
24
 
5
25
  #### Technical changes
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: OpenFisca-Core
3
- Version: 44.2.1
3
+ Version: 44.3.0
4
4
  Summary: A versatile microsimulation free software
5
5
  Home-page: https://github.com/openfisca/openfisca-core
6
6
  Author: OpenFisca Team
@@ -78,6 +78,19 @@ openfisca_core/indexed_enums/types.py
78
78
  openfisca_core/indexed_enums/tests/__init__.py
79
79
  openfisca_core/indexed_enums/tests/test_enum.py
80
80
  openfisca_core/indexed_enums/tests/test_enum_array.py
81
+ openfisca_core/links/__init__.py
82
+ openfisca_core/links/implicit.py
83
+ openfisca_core/links/link.py
84
+ openfisca_core/links/many2one.py
85
+ openfisca_core/links/one2many.py
86
+ openfisca_core/links/tests/__init__.py
87
+ openfisca_core/links/tests/test_benchmark.py
88
+ openfisca_core/links/tests/test_edge_cases.py
89
+ openfisca_core/links/tests/test_implicit.py
90
+ openfisca_core/links/tests/test_integration.py
91
+ openfisca_core/links/tests/test_many2one.py
92
+ openfisca_core/links/tests/test_one2many.py
93
+ openfisca_core/links/tests/test_one2many_logic.py
81
94
  openfisca_core/parameters/__init__.py
82
95
  openfisca_core/parameters/at_instant_like.py
83
96
  openfisca_core/parameters/config.py
@@ -113,6 +126,8 @@ openfisca_core/populations/_errors.py
113
126
  openfisca_core/populations/group_population.py
114
127
  openfisca_core/populations/population.py
115
128
  openfisca_core/populations/types.py
129
+ openfisca_core/populations/tests/__init__.py
130
+ openfisca_core/populations/tests/test_members_position.py
116
131
  openfisca_core/projectors/__init__.py
117
132
  openfisca_core/projectors/entity_to_person_projector.py
118
133
  openfisca_core/projectors/first_person_to_entity_projector.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: OpenFisca-Core
3
- Version: 44.2.1
3
+ Version: 44.3.0
4
4
  Summary: A versatile microsimulation free software
5
5
  Home-page: https://github.com/openfisca/openfisca-core
6
6
  Author: OpenFisca Team
@@ -47,6 +47,9 @@ class CoreEntity:
47
47
  #: A ``TaxBenefitSystem`` instance.
48
48
  _tax_benefit_system: None | t.TaxBenefitSystem = None
49
49
 
50
+ #: Named links to other entities (Many2One, One2Many, etc.).
51
+ _links: dict
52
+
50
53
  @abc.abstractmethod
51
54
  def __init__(self, *__args: object, **__kwargs: object) -> None: ...
52
55
 
@@ -57,6 +60,43 @@ class CoreEntity:
57
60
  """A ``CoreEntity`` belongs to a ``TaxBenefitSystem``."""
58
61
  self._tax_benefit_system = tax_benefit_system
59
62
 
63
+ # -- Link management --------------------------------------------------
64
+
65
+ def add_link(self, link) -> None:
66
+ """Register a named link on this entity.
67
+
68
+ Args:
69
+ link: A ``Link`` instance (Many2OneLink, One2ManyLink, etc.).
70
+
71
+ Example::
72
+
73
+ from openfisca_core.links import Many2OneLink
74
+
75
+ mother = Many2OneLink(
76
+ name="mother",
77
+ link_field="mother_id",
78
+ target_entity_key="person",
79
+ )
80
+ person_entity.add_link(mother)
81
+
82
+ """
83
+ if not hasattr(self, "_links") or self._links is None:
84
+ self._links = {}
85
+ self._links[link.name] = link
86
+
87
+ def get_link(self, name: str):
88
+ """Retrieve a link by name, or ``None`` if not found."""
89
+ if not hasattr(self, "_links") or self._links is None:
90
+ return None
91
+ return self._links.get(name)
92
+
93
+ @property
94
+ def links(self) -> dict:
95
+ """All links registered on this entity."""
96
+ if not hasattr(self, "_links") or self._links is None:
97
+ self._links = {}
98
+ return self._links
99
+
60
100
  def get_variable(
61
101
  self,
62
102
  variable_name: t.VariableName,
@@ -26,7 +26,7 @@ class EnumType(t.EnumType):
26
26
  ... TENANT = "Tenant"
27
27
 
28
28
  >>> Housing.indices
29
- array([0, 1], dtype=uint8)
29
+ array([0, 1], dtype=int16)
30
30
 
31
31
  >>> Housing.names
32
32
  array(['OWNER', 'TENANT'], dtype='<U6')
@@ -39,22 +39,22 @@ def _enum_to_index(value: t.ObjArray | t.ArrayLike[t.Enum]) -> t.IndexArray:
39
39
  TypeError: 'Road' object is not iterable
40
40
 
41
41
  >>> _enum_to_index([Road.AVENUE])
42
- array([1], dtype=uint8)
42
+ array([1], dtype=int16)
43
43
 
44
44
  >>> _enum_to_index(numpy.array(Road.AVENUE))
45
45
  Traceback (most recent call last):
46
46
  TypeError: iteration over a 0-d array
47
47
 
48
48
  >>> _enum_to_index(numpy.array([Road.AVENUE]))
49
- array([1], dtype=uint8)
49
+ array([1], dtype=int16)
50
50
 
51
51
  >>> value = numpy.array([Road.STREET, Road.AVENUE, Road.STREET])
52
52
  >>> _enum_to_index(value)
53
- array([0, 1, 0], dtype=uint8)
53
+ array([0, 1, 0], dtype=int16)
54
54
 
55
55
  >>> value = numpy.array([Road.AVENUE, Road.AVENUE, Rogue.BOULEVARD])
56
56
  >>> _enum_to_index(value)
57
- array([1, 1, 0], dtype=uint8)
57
+ array([1, 1, 0], dtype=int16)
58
58
 
59
59
  """
60
60
  return numpy.array([enum.index for enum in value], t.EnumDType)
@@ -92,28 +92,28 @@ def _int_to_index(
92
92
  ... )
93
93
 
94
94
  >>> _int_to_index(Road, 1)
95
- array([1], dtype=uint8)
95
+ array([1], dtype=int16)
96
96
 
97
97
  >>> _int_to_index(Road, [1])
98
- array([1], dtype=uint8)
98
+ array([1], dtype=int16)
99
99
 
100
100
  >>> _int_to_index(Road, array("B", [1]))
101
- array([1], dtype=uint8)
101
+ array([1], dtype=int16)
102
102
 
103
103
  >>> _int_to_index(Road, memoryview(array("B", [1])))
104
- array([1], dtype=uint8)
104
+ array([1], dtype=int16)
105
105
 
106
106
  >>> _int_to_index(Road, numpy.array(1))
107
- array([1], dtype=uint8)
107
+ array([1], dtype=int16)
108
108
 
109
109
  >>> _int_to_index(Road, numpy.array([1]))
110
- array([1], dtype=uint8)
110
+ array([1], dtype=int16)
111
111
 
112
112
  >>> _int_to_index(Road, numpy.array([0, 1, 0]))
113
- array([0, 1, 0], dtype=uint8)
113
+ array([0, 1, 0], dtype=int16)
114
114
 
115
115
  >>> _int_to_index(Road, numpy.array([1, 1, 2]))
116
- array([1, 1], dtype=uint8)
116
+ array([1, 1], dtype=int16)
117
117
 
118
118
  """
119
119
  indices = enum_class.indices
@@ -151,22 +151,22 @@ def _str_to_index(
151
151
  ... )
152
152
 
153
153
  >>> _str_to_index(Road, "AVENUE")
154
- array([1], dtype=uint8)
154
+ array([1], dtype=int16)
155
155
 
156
156
  >>> _str_to_index(Road, ["AVENUE"])
157
- array([1], dtype=uint8)
157
+ array([1], dtype=int16)
158
158
 
159
159
  >>> _str_to_index(Road, numpy.array("AVENUE"))
160
- array([1], dtype=uint8)
160
+ array([1], dtype=int16)
161
161
 
162
162
  >>> _str_to_index(Road, numpy.array(["AVENUE"]))
163
- array([1], dtype=uint8)
163
+ array([1], dtype=int16)
164
164
 
165
165
  >>> _str_to_index(Road, numpy.array(["STREET", "AVENUE", "STREET"]))
166
- array([0, 1, 0], dtype=uint8)
166
+ array([0, 1, 0], dtype=int16)
167
167
 
168
168
  >>> _str_to_index(Road, numpy.array(["AVENUE", "AVENUE", "BOULEVARD"]))
169
- array([1, 1], dtype=uint8)
169
+ array([1, 1], dtype=int16)
170
170
 
171
171
  """
172
172
  values = numpy.asarray(value)
@@ -266,8 +266,7 @@ class EnumArray(t.EnumArray):
266
266
  result: t.ObjArray
267
267
  if self.possible_values is None:
268
268
  msg = (
269
- f"The possible values of the {self.__class__.__name__} are "
270
- f"not defined."
269
+ f"The possible values of the {self.__class__.__name__} are not defined."
271
270
  )
272
271
  raise TypeError(msg)
273
272
  array = self.reshape(1).astype(t.EnumDType) if self.ndim == 0 else self
@@ -301,8 +300,7 @@ class EnumArray(t.EnumArray):
301
300
  result: t.StrArray
302
301
  if self.possible_values is None:
303
302
  msg = (
304
- f"The possible values of the {self.__class__.__name__} are "
305
- f"not defined."
303
+ f"The possible values of the {self.__class__.__name__} are not defined."
306
304
  )
307
305
  raise TypeError(msg)
308
306
  array = self.reshape(1).astype(t.EnumDType) if self.ndim == 0 else self
@@ -10,9 +10,10 @@ from numpy import (
10
10
  int32 as IntDType,
11
11
  object_ as ObjDType,
12
12
  str_ as StrDType,
13
- uint8 as EnumDType,
14
13
  )
15
14
 
15
+ from .config import ENUM_ARRAY_DTYPE as EnumDType
16
+
16
17
  #: Type for enum indices arrays.
17
18
  IndexArray: TypeAlias = Array[EnumDType]
18
19
 
@@ -0,0 +1,36 @@
1
+ """Links between entities (Many2One, One2Many, chaining).
2
+
3
+ This module implements a generic link system inspired by LIAM2, enriched
4
+ with OpenFisca's role semantics. Links are orthogonal to the existing
5
+ GroupEntity/Projector machinery: current code keeps working unchanged,
6
+ and links provide additional capabilities (intra-entity links, chaining,
7
+ arbitrary named links).
8
+
9
+ Usage in a country package::
10
+
11
+ from openfisca_core.links import Many2OneLink, One2ManyLink
12
+
13
+ # Declare a person→person link (intra-entity)
14
+ mother = Many2OneLink(
15
+ name="mother",
16
+ link_field="mother_id",
17
+ target_entity_key="person",
18
+ )
19
+
20
+ # Declare a person→employer link (inter-entity)
21
+ employer = Many2OneLink(
22
+ name="employer",
23
+ link_field="employer_id",
24
+ target_entity_key="employer",
25
+ )
26
+ """
27
+
28
+ from .link import Link
29
+ from .many2one import Many2OneLink
30
+ from .one2many import One2ManyLink
31
+
32
+ __all__ = [
33
+ "Link",
34
+ "Many2OneLink",
35
+ "One2ManyLink",
36
+ ]
@@ -0,0 +1,73 @@
1
+ """Implicit links dynamically inferred from OpenFisca's GroupPopulation system."""
2
+
3
+ from __future__ import annotations
4
+
5
+ import numpy
6
+
7
+ from .many2one import Many2OneLink
8
+ from .one2many import One2ManyLink
9
+
10
+
11
+ class ImplicitMany2OneLink(Many2OneLink):
12
+ """A person → group link using GroupPopulation's internal arrays.
13
+
14
+ This bypasses the usual Variable lookup (``simulation.calculate``)
15
+ and directly reads ``members_entity_id`` and ``members_role`` from
16
+ the target GroupPopulation.
17
+ """
18
+
19
+ def __init__(self, group_entity_key: str):
20
+ super().__init__(
21
+ name=group_entity_key,
22
+ link_field="", # Not used
23
+ target_entity_key=group_entity_key,
24
+ )
25
+
26
+ def _get_target_ids(self, period) -> numpy.ndarray:
27
+ return self._target_population.members_entity_id
28
+
29
+ @property
30
+ def role(self) -> numpy.ndarray | None:
31
+ return self._target_population.members_role
32
+
33
+ def _project_implicit(self, result: numpy.ndarray) -> numpy.ndarray:
34
+ # Fully compatible with old Projector logic
35
+ return self._target_population.project(result)
36
+
37
+
38
+ class ImplicitOne2ManyLink(One2ManyLink):
39
+ """A group → person link using GroupPopulation's internal arrays."""
40
+
41
+ def __init__(self, name: str, group_entity_key: str):
42
+ super().__init__(
43
+ name=name,
44
+ link_field="", # Not used
45
+ target_entity_key="person", # The target of the O2M is persons
46
+ )
47
+ self._group_entity_key = group_entity_key
48
+
49
+ def _source_rows(self, period) -> numpy.ndarray:
50
+ # For a group->person O2M, the source is the group, the target is the person.
51
+ # members_entity_id is an array of length person.count, containing the group index.
52
+ # So members_entity_id IS the array of source rows for each target member.
53
+ return self._source_population.members_entity_id
54
+
55
+ def _apply_filters(self, period, values, role, condition):
56
+ source_rows = self._source_rows(period)
57
+ mask = numpy.ones(len(source_rows), dtype=bool)
58
+
59
+ if role is not None:
60
+ roles = self._source_population.members_role
61
+ mask &= roles == role
62
+
63
+ if condition is not None:
64
+ mask &= condition
65
+
66
+ source_rows = source_rows[mask]
67
+ values = values[mask]
68
+
69
+ valid = source_rows >= 0
70
+ return source_rows[valid], values[valid]
71
+
72
+
73
+ __all__ = ["ImplicitMany2OneLink", "ImplicitOne2ManyLink"]
@@ -0,0 +1,109 @@
1
+ """Base Link class for entity relationships."""
2
+
3
+ from __future__ import annotations
4
+
5
+ from typing import TYPE_CHECKING
6
+
7
+ if TYPE_CHECKING:
8
+ import numpy
9
+
10
+
11
+ class Link:
12
+ """A named, directed relationship between two entity populations.
13
+
14
+ A Link is defined by:
15
+
16
+ - A *name* used to access the link from formulas (e.g. "mother", "household").
17
+ - A *link_field*: the name of the Variable (on the source entity) that holds
18
+ the target entity IDs.
19
+ - A *target_entity_key*: the entity key of the target population.
20
+ - Optionally, a *role_field* and *position_field* to attach OpenFisca-style
21
+ role and position metadata to the relationship.
22
+
23
+
24
+ Sub-classes ``Many2OneLink`` and ``One2ManyLink`` add resolution logic.
25
+
26
+ Parameters
27
+ ----------
28
+ name : str
29
+ Human-readable name of the link (e.g. ``"mother"``).
30
+ link_field : str
31
+ Variable name on the **source** entity that holds IDs pointing to
32
+ the target entity.
33
+ target_entity_key : str
34
+ The ``Entity.key`` of the target entity.
35
+ role_field : str or None
36
+ Optional variable name holding the role of each source member
37
+ within the target group.
38
+ position_field : str or None
39
+ Optional variable name holding the positional index of each
40
+ source member within the target group.
41
+ """
42
+
43
+ def __init__(
44
+ self,
45
+ name: str,
46
+ link_field: str,
47
+ target_entity_key: str,
48
+ *,
49
+ role_field: str | None = None,
50
+ position_field: str | None = None,
51
+ ) -> None:
52
+ self.name = name
53
+ self.link_field = link_field
54
+ self.target_entity_key = target_entity_key
55
+ self.role_field = role_field
56
+ self.position_field = position_field
57
+
58
+ # Resolved after simulation setup
59
+ self._source_population = None
60
+ self._target_population = None
61
+
62
+ # -- lifecycle ----------------------------------------------------------
63
+
64
+ def attach(self, source_population) -> None:
65
+ """Bind this link to its source population."""
66
+ self._source_population = source_population
67
+
68
+ def resolve(self, populations: dict) -> None:
69
+ """Resolve ``target_entity_key`` to an actual population object.
70
+
71
+ Parameters
72
+ ----------
73
+ populations : dict[str, Population]
74
+ All populations in the simulation, keyed by entity key.
75
+ """
76
+ if self.target_entity_key not in populations:
77
+ msg = (
78
+ f"Link '{self.name}': target entity "
79
+ f"'{self.target_entity_key}' not found in populations "
80
+ f"{list(populations.keys())}"
81
+ )
82
+ raise KeyError(msg)
83
+ self._target_population = populations[self.target_entity_key]
84
+
85
+ # -- helpers ------------------------------------------------------------
86
+
87
+ @property
88
+ def is_resolved(self) -> bool:
89
+ return (
90
+ self._source_population is not None and self._target_population is not None
91
+ )
92
+
93
+ def _get_link_ids(self, period) -> numpy.ndarray:
94
+ """Return the array of target IDs for every source member.
95
+
96
+ This reads the ``link_field`` variable from the source population.
97
+ """
98
+ return self._source_population(self.link_field, period)
99
+
100
+ def __repr__(self) -> str:
101
+ return (
102
+ f"{self.__class__.__name__}("
103
+ f"name={self.name!r}, "
104
+ f"link_field={self.link_field!r}, "
105
+ f"target={self.target_entity_key!r})"
106
+ )
107
+
108
+
109
+ __all__ = ["Link"]