OpenFisca-Core-test 46.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (237) hide show
  1. openfisca_core/__init__.py +0 -0
  2. openfisca_core/commons/__init__.py +18 -0
  3. openfisca_core/commons/dummy.py +25 -0
  4. openfisca_core/commons/formulas.py +121 -0
  5. openfisca_core/commons/misc.py +109 -0
  6. openfisca_core/commons/py.typed +0 -0
  7. openfisca_core/commons/rates.py +114 -0
  8. openfisca_core/commons/tests/__init__.py +0 -0
  9. openfisca_core/commons/tests/test_dummy.py +9 -0
  10. openfisca_core/commons/tests/test_formulas.py +75 -0
  11. openfisca_core/commons/tests/test_rates.py +26 -0
  12. openfisca_core/data_storage/__init__.py +7 -0
  13. openfisca_core/data_storage/in_memory_storage.py +198 -0
  14. openfisca_core/data_storage/on_disk_storage.py +307 -0
  15. openfisca_core/data_storage/types.py +14 -0
  16. openfisca_core/entities/__init__.py +23 -0
  17. openfisca_core/entities/_core_entity.py +217 -0
  18. openfisca_core/entities/_description.py +55 -0
  19. openfisca_core/entities/entity.py +60 -0
  20. openfisca_core/entities/group_entity.py +123 -0
  21. openfisca_core/entities/helpers.py +165 -0
  22. openfisca_core/entities/py.typed +0 -0
  23. openfisca_core/entities/role.py +92 -0
  24. openfisca_core/entities/tests/__init__.py +0 -0
  25. openfisca_core/entities/tests/test_entity.py +10 -0
  26. openfisca_core/entities/tests/test_group_entity.py +70 -0
  27. openfisca_core/entities/tests/test_role.py +11 -0
  28. openfisca_core/entities/types.py +44 -0
  29. openfisca_core/errors/__init__.py +64 -0
  30. openfisca_core/errors/cycle_error.py +2 -0
  31. openfisca_core/errors/empty_argument_error.py +39 -0
  32. openfisca_core/errors/nan_creation_error.py +2 -0
  33. openfisca_core/errors/parameter_not_found_error.py +16 -0
  34. openfisca_core/errors/parameter_parsing_error.py +18 -0
  35. openfisca_core/errors/period_mismatch_error.py +9 -0
  36. openfisca_core/errors/situation_parsing_error.py +26 -0
  37. openfisca_core/errors/spiral_error.py +2 -0
  38. openfisca_core/errors/variable_name_config_error.py +2 -0
  39. openfisca_core/errors/variable_not_found_error.py +29 -0
  40. openfisca_core/experimental/__init__.py +9 -0
  41. openfisca_core/experimental/_errors.py +5 -0
  42. openfisca_core/experimental/_memory_config.py +41 -0
  43. openfisca_core/formula_helpers.py +9 -0
  44. openfisca_core/holders/__init__.py +33 -0
  45. openfisca_core/holders/helpers.py +93 -0
  46. openfisca_core/holders/holder.py +328 -0
  47. openfisca_core/holders/tests/__init__.py +0 -0
  48. openfisca_core/holders/tests/test_helpers.py +134 -0
  49. openfisca_core/holders/types.py +3 -0
  50. openfisca_core/indexed_enums/__init__.py +18 -0
  51. openfisca_core/indexed_enums/_enum_type.py +79 -0
  52. openfisca_core/indexed_enums/_errors.py +35 -0
  53. openfisca_core/indexed_enums/_guards.py +209 -0
  54. openfisca_core/indexed_enums/_utils.py +180 -0
  55. openfisca_core/indexed_enums/config.py +6 -0
  56. openfisca_core/indexed_enums/enum.py +218 -0
  57. openfisca_core/indexed_enums/enum_array.py +316 -0
  58. openfisca_core/indexed_enums/py.typed +0 -0
  59. openfisca_core/indexed_enums/tests/__init__.py +0 -0
  60. openfisca_core/indexed_enums/tests/test_enum.py +135 -0
  61. openfisca_core/indexed_enums/tests/test_enum_array.py +30 -0
  62. openfisca_core/indexed_enums/types.py +49 -0
  63. openfisca_core/memory_config.py +9 -0
  64. openfisca_core/model_api.py +71 -0
  65. openfisca_core/parameters/__init__.py +71 -0
  66. openfisca_core/parameters/at_instant_like.py +17 -0
  67. openfisca_core/parameters/config.py +55 -0
  68. openfisca_core/parameters/helpers.py +106 -0
  69. openfisca_core/parameters/parameter.py +217 -0
  70. openfisca_core/parameters/parameter_at_instant.py +75 -0
  71. openfisca_core/parameters/parameter_node.py +176 -0
  72. openfisca_core/parameters/parameter_node_at_instant.py +57 -0
  73. openfisca_core/parameters/parameter_scale.py +121 -0
  74. openfisca_core/parameters/parameter_scale_bracket.py +7 -0
  75. openfisca_core/parameters/values_history.py +5 -0
  76. openfisca_core/parameters/vectorial_parameter_node_at_instant.py +179 -0
  77. openfisca_core/periods/__init__.py +77 -0
  78. openfisca_core/periods/_errors.py +28 -0
  79. openfisca_core/periods/_parsers.py +122 -0
  80. openfisca_core/periods/config.py +20 -0
  81. openfisca_core/periods/date_unit.py +110 -0
  82. openfisca_core/periods/helpers.py +314 -0
  83. openfisca_core/periods/instant_.py +226 -0
  84. openfisca_core/periods/period_.py +919 -0
  85. openfisca_core/periods/py.typed +0 -0
  86. openfisca_core/periods/tests/__init__.py +0 -0
  87. openfisca_core/periods/tests/helpers/__init__.py +0 -0
  88. openfisca_core/periods/tests/helpers/test_helpers.py +65 -0
  89. openfisca_core/periods/tests/helpers/test_instant.py +73 -0
  90. openfisca_core/periods/tests/helpers/test_period.py +134 -0
  91. openfisca_core/periods/tests/test_instant.py +32 -0
  92. openfisca_core/periods/tests/test_parsers.py +129 -0
  93. openfisca_core/periods/tests/test_period.py +283 -0
  94. openfisca_core/populations/__init__.py +64 -0
  95. openfisca_core/populations/_core_population.py +454 -0
  96. openfisca_core/populations/_errors.py +65 -0
  97. openfisca_core/populations/group_population.py +326 -0
  98. openfisca_core/populations/population.py +142 -0
  99. openfisca_core/populations/tests/__init__.py +0 -0
  100. openfisca_core/populations/tests/test_members_position.py +116 -0
  101. openfisca_core/populations/types.py +110 -0
  102. openfisca_core/projectors/__init__.py +39 -0
  103. openfisca_core/projectors/entity_to_person_projector.py +12 -0
  104. openfisca_core/projectors/first_person_to_entity_projector.py +13 -0
  105. openfisca_core/projectors/helpers.py +139 -0
  106. openfisca_core/projectors/projector.py +38 -0
  107. openfisca_core/projectors/typing.py +27 -0
  108. openfisca_core/projectors/unique_role_to_entity_projector.py +14 -0
  109. openfisca_core/rates.py +9 -0
  110. openfisca_core/reforms/__init__.py +24 -0
  111. openfisca_core/reforms/in_yaml_test_reform.py +28 -0
  112. openfisca_core/reforms/reform.py +86 -0
  113. openfisca_core/scripts/__init__.py +106 -0
  114. openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.3.3.pyc +0 -0
  115. openfisca_core/scripts/__pycache__/__init__.cpython-310-pytest-8.4.2.pyc +0 -0
  116. openfisca_core/scripts/__pycache__/__init__.cpython-310.pyc +0 -0
  117. openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.3.3.pyc +0 -0
  118. openfisca_core/scripts/__pycache__/__init__.cpython-311-pytest-8.4.2.pyc +0 -0
  119. openfisca_core/scripts/__pycache__/__init__.cpython-311.pyc +0 -0
  120. openfisca_core/scripts/__pycache__/__init__.cpython-312-pytest-8.4.2.pyc +0 -0
  121. openfisca_core/scripts/__pycache__/__init__.cpython-312.pyc +0 -0
  122. openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.3.3.pyc +0 -0
  123. openfisca_core/scripts/__pycache__/__init__.cpython-313-pytest-8.4.2.pyc +0 -0
  124. openfisca_core/scripts/__pycache__/__init__.cpython-313.pyc +0 -0
  125. openfisca_core/scripts/__pycache__/find_placeholders.cpython-311.pyc +0 -0
  126. openfisca_core/scripts/__pycache__/find_placeholders.cpython-313.pyc +0 -0
  127. openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-311.pyc +0 -0
  128. openfisca_core/scripts/__pycache__/measure_numpy_condition_notations.cpython-313.pyc +0 -0
  129. openfisca_core/scripts/__pycache__/measure_performances.cpython-311.pyc +0 -0
  130. openfisca_core/scripts/__pycache__/measure_performances.cpython-313.pyc +0 -0
  131. openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-311.pyc +0 -0
  132. openfisca_core/scripts/__pycache__/measure_performances_fancy_indexing.cpython-313.pyc +0 -0
  133. openfisca_core/scripts/__pycache__/openfisca_command.cpython-310.pyc +0 -0
  134. openfisca_core/scripts/__pycache__/openfisca_command.cpython-311.pyc +0 -0
  135. openfisca_core/scripts/__pycache__/openfisca_command.cpython-312.pyc +0 -0
  136. openfisca_core/scripts/__pycache__/openfisca_command.cpython-313.pyc +0 -0
  137. openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-311.pyc +0 -0
  138. openfisca_core/scripts/__pycache__/remove_fuzzy.cpython-313.pyc +0 -0
  139. openfisca_core/scripts/__pycache__/run_test.cpython-310.pyc +0 -0
  140. openfisca_core/scripts/__pycache__/run_test.cpython-311.pyc +0 -0
  141. openfisca_core/scripts/__pycache__/run_test.cpython-312.pyc +0 -0
  142. openfisca_core/scripts/__pycache__/run_test.cpython-313.pyc +0 -0
  143. openfisca_core/scripts/__pycache__/simulation_generator.cpython-311.pyc +0 -0
  144. openfisca_core/scripts/__pycache__/simulation_generator.cpython-313.pyc +0 -0
  145. openfisca_core/scripts/assets/__init__.py +0 -0
  146. openfisca_core/scripts/assets/__pycache__/__init__.cpython-311.pyc +0 -0
  147. openfisca_core/scripts/assets/__pycache__/__init__.cpython-313.pyc +0 -0
  148. openfisca_core/scripts/assets/index.html +140 -0
  149. openfisca_core/scripts/find_placeholders.py +51 -0
  150. openfisca_core/scripts/measure_numpy_condition_notations.py +137 -0
  151. openfisca_core/scripts/measure_performances.py +291 -0
  152. openfisca_core/scripts/measure_performances_fancy_indexing.py +89 -0
  153. openfisca_core/scripts/migrations/__init__.py +0 -0
  154. openfisca_core/scripts/migrations/__pycache__/__init__.cpython-311.pyc +0 -0
  155. openfisca_core/scripts/migrations/__pycache__/__init__.cpython-313.pyc +0 -0
  156. openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-311.pyc +0 -0
  157. openfisca_core/scripts/migrations/__pycache__/v24_to_25.cpython-313.pyc +0 -0
  158. openfisca_core/scripts/migrations/v16_2_to_v17/__init__.py +0 -0
  159. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-311.pyc +0 -0
  160. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/__init__.cpython-313.pyc +0 -0
  161. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-311.pyc +0 -0
  162. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_country_template.cpython-313.pyc +0 -0
  163. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-311.pyc +0 -0
  164. openfisca_core/scripts/migrations/v16_2_to_v17/__pycache__/xml_to_yaml_extension_template.cpython-313.pyc +0 -0
  165. openfisca_core/scripts/migrations/v16_2_to_v17/legislation.xsd +102 -0
  166. openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_country_template.py +30 -0
  167. openfisca_core/scripts/migrations/v16_2_to_v17/xml_to_yaml_extension_template.py +26 -0
  168. openfisca_core/scripts/migrations/v24_to_25.py +156 -0
  169. openfisca_core/scripts/openfisca_command.py +192 -0
  170. openfisca_core/scripts/remove_fuzzy.py +213 -0
  171. openfisca_core/scripts/run_test.py +51 -0
  172. openfisca_core/scripts/simulation_generator.py +90 -0
  173. openfisca_core/simulation_builder.py +16 -0
  174. openfisca_core/simulations/__init__.py +45 -0
  175. openfisca_core/simulations/_build_default_simulation.py +158 -0
  176. openfisca_core/simulations/_build_from_variables.py +230 -0
  177. openfisca_core/simulations/_type_guards.py +298 -0
  178. openfisca_core/simulations/helpers.py +111 -0
  179. openfisca_core/simulations/simulation.py +618 -0
  180. openfisca_core/simulations/simulation_builder.py +855 -0
  181. openfisca_core/simulations/typing.py +203 -0
  182. openfisca_core/taxbenefitsystems/__init__.py +26 -0
  183. openfisca_core/taxbenefitsystems/tax_benefit_system.py +584 -0
  184. openfisca_core/taxscales/__init__.py +35 -0
  185. openfisca_core/taxscales/abstract_rate_tax_scale.py +41 -0
  186. openfisca_core/taxscales/abstract_tax_scale.py +53 -0
  187. openfisca_core/taxscales/amount_tax_scale_like.py +55 -0
  188. openfisca_core/taxscales/helpers.py +44 -0
  189. openfisca_core/taxscales/linear_average_rate_tax_scale.py +76 -0
  190. openfisca_core/taxscales/marginal_amount_tax_scale.py +34 -0
  191. openfisca_core/taxscales/marginal_rate_tax_scale.py +286 -0
  192. openfisca_core/taxscales/rate_tax_scale_like.py +214 -0
  193. openfisca_core/taxscales/single_amount_tax_scale.py +32 -0
  194. openfisca_core/taxscales/tax_scale_like.py +65 -0
  195. openfisca_core/tools/__init__.py +94 -0
  196. openfisca_core/tools/parallel_plugin.py +55 -0
  197. openfisca_core/tools/simulation_dumper.py +137 -0
  198. openfisca_core/tools/test_runner.py +802 -0
  199. openfisca_core/tracers/__init__.py +40 -0
  200. openfisca_core/tracers/computation_log.py +196 -0
  201. openfisca_core/tracers/flat_trace.py +87 -0
  202. openfisca_core/tracers/full_tracer.py +172 -0
  203. openfisca_core/tracers/performance_log.py +133 -0
  204. openfisca_core/tracers/simple_tracer.py +64 -0
  205. openfisca_core/tracers/trace_node.py +121 -0
  206. openfisca_core/tracers/tracing_parameter_node_at_instant.py +81 -0
  207. openfisca_core/types.py +548 -0
  208. openfisca_core/variables/__init__.py +26 -0
  209. openfisca_core/variables/config.py +53 -0
  210. openfisca_core/variables/helpers.py +67 -0
  211. openfisca_core/variables/tests/__init__.py +0 -0
  212. openfisca_core/variables/tests/test_definition_period.py +43 -0
  213. openfisca_core/variables/variable.py +474 -0
  214. openfisca_core/warnings/__init__.py +25 -0
  215. openfisca_core/warnings/libyaml_warning.py +2 -0
  216. openfisca_core/warnings/tempfile_warning.py +2 -0
  217. openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/CHANGELOG.md +4209 -0
  218. openfisca_core_test-46.0.0.data/data/share/openfisca/openfisca-core/README.md +152 -0
  219. openfisca_core_test-46.0.0.dist-info/METADATA +194 -0
  220. openfisca_core_test-46.0.0.dist-info/RECORD +237 -0
  221. openfisca_core_test-46.0.0.dist-info/WHEEL +5 -0
  222. openfisca_core_test-46.0.0.dist-info/entry_points.txt +3 -0
  223. openfisca_core_test-46.0.0.dist-info/licenses/LICENSE +661 -0
  224. openfisca_core_test-46.0.0.dist-info/top_level.txt +2 -0
  225. openfisca_web_api/__init__.py +0 -0
  226. openfisca_web_api/app.py +226 -0
  227. openfisca_web_api/errors.py +11 -0
  228. openfisca_web_api/handlers.py +90 -0
  229. openfisca_web_api/loader/__init__.py +22 -0
  230. openfisca_web_api/loader/entities.py +28 -0
  231. openfisca_web_api/loader/parameters.py +122 -0
  232. openfisca_web_api/loader/spec.py +168 -0
  233. openfisca_web_api/loader/tax_benefit_system.py +27 -0
  234. openfisca_web_api/loader/variables.py +121 -0
  235. openfisca_web_api/openAPI.yml +434 -0
  236. openfisca_web_api/scripts/__init__.py +0 -0
  237. openfisca_web_api/scripts/serve.py +99 -0
@@ -0,0 +1,140 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <!-- source: https://github.com/spiermar/d3-flame-graph/blob/4603adf4a0ed788dc1d9d51e198bd5d21c48fd77/index.html -->
5
+ <!-- BSD 3 Clause - Copyright Mike Bostock -->
6
+ <meta charset="utf-8">
7
+ <meta http-equiv="X-UA-Compatible" content="IE=edge">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+
10
+ <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css">
11
+ <link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/gh/spiermar/d3-flame-graph@2.0.3/dist/d3-flamegraph.css">
12
+
13
+ <style>
14
+
15
+ /* Space out content a bit */
16
+ body {
17
+ padding-top: 20px;
18
+ padding-bottom: 20px;
19
+ }
20
+
21
+ /* Custom page header */
22
+ .header {
23
+ padding-bottom: 20px;
24
+ padding-right: 15px;
25
+ padding-left: 15px;
26
+ border-bottom: 1px solid #e5e5e5;
27
+ }
28
+
29
+ /* Make the masthead heading the same height as the navigation */
30
+ .header h3 {
31
+ margin-top: 0;
32
+ margin-bottom: 0;
33
+ line-height: 40px;
34
+ }
35
+
36
+ /* Customize container */
37
+ .container {
38
+ max-width: 990px;
39
+ }
40
+ </style>
41
+
42
+ <title>Performance log</title>
43
+
44
+ <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
45
+ <!--[if lt IE 9]>
46
+ <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
47
+ <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
48
+ <![endif]-->
49
+ </head>
50
+ <body>
51
+ <div class="container">
52
+ <div class="header clearfix">
53
+ <nav>
54
+ <div class="pull-right">
55
+ <form class="form-inline" id="form">
56
+ <a class="btn" href="javascript: resetZoom();">Reset zoom</a>
57
+ <a class="btn" href="javascript: clear();">Clear</a>
58
+ <div class="form-group">
59
+ <input type="text" class="form-control" id="term">
60
+ </div>
61
+ <a class="btn btn-primary" href="javascript: search();">Search</a>
62
+ </form>
63
+ </div>
64
+ </nav>
65
+ <h3 class="text-muted">Performance log</h3>
66
+ </div>
67
+ <div id="chart">
68
+ </div>
69
+ <hr>
70
+ <div id="details">
71
+ </div>
72
+ </div>
73
+
74
+ <!-- D3.js -->
75
+ <script src="https://d3js.org/d3.v4.min.js" charset="utf-8"></script>
76
+
77
+ <!-- d3-tip -->
78
+ <script type="text/javascript" src=https://cdnjs.cloudflare.com/ajax/libs/d3-tip/0.9.1/d3-tip.min.js></script>
79
+
80
+ <!-- d3-flamegraph -->
81
+ <script type="text/javascript" src="https://cdn.jsdelivr.net/gh/spiermar/d3-flame-graph@2.0.3/dist/d3-flamegraph.min.js"></script>
82
+
83
+ <script type="text/javascript">
84
+ var data = {{data}}
85
+ var flameGraph = d3.flamegraph()
86
+ .width(960)
87
+ .cellHeight(18)
88
+ .transitionDuration(750)
89
+ .minFrameSize(2)
90
+ .transitionEase(d3.easeCubic)
91
+ .sort(function(a, b) {
92
+ return (a.data.value < b.data.value) ? 1 : -1;
93
+ })
94
+ .title("")
95
+ .onClick(onClick)
96
+ .differential(false)
97
+ .selfValue(false);
98
+
99
+ var details = document.getElementById("details");
100
+ flameGraph.setDetailsElement(details);
101
+
102
+ flameGraph.label(function(d) {
103
+ var timeInSec = d.data.value.toPrecision(3) + "s"
104
+ var label = d.data.name + ": " + timeInSec
105
+ if (d.parent) {
106
+ var percentageOfParent = (d.data.value / d.parent.value) * 100
107
+ label += " (" + percentageOfParent.toPrecision(3) + "%)"
108
+ }
109
+ return label
110
+ });
111
+
112
+ d3.select("#chart")
113
+ .datum(data)
114
+ .call(flameGraph);
115
+
116
+ document.getElementById("form").addEventListener("submit", function(event){
117
+ event.preventDefault();
118
+ search();
119
+ });
120
+
121
+ function search() {
122
+ var term = document.getElementById("term").value;
123
+ flameGraph.search(term);
124
+ }
125
+
126
+ function clear() {
127
+ document.getElementById('term').value = '';
128
+ flameGraph.clear();
129
+ }
130
+
131
+ function resetZoom() {
132
+ flameGraph.resetZoom();
133
+ }
134
+
135
+ function onClick(d) {
136
+ console.info("Clicked on " + d.data.name);
137
+ }
138
+ </script>
139
+ </body>
140
+ </html>
@@ -0,0 +1,51 @@
1
+ # flake8: noqa T001
2
+
3
+ import fnmatch
4
+ import os
5
+ import sys
6
+
7
+ from bs4 import BeautifulSoup
8
+
9
+
10
+ def find_param_files(input_dir):
11
+ param_files = []
12
+ for root, _dirnames, filenames in os.walk(input_dir):
13
+ for filename in fnmatch.filter(filenames, "*.xml"):
14
+ param_files.append(os.path.join(root, filename))
15
+
16
+ return param_files
17
+
18
+
19
+ def find_placeholders(filename_input):
20
+ with open(filename_input) as f:
21
+ xml_content = f.read()
22
+
23
+ xml_parsed = BeautifulSoup(xml_content, "lxml-xml")
24
+
25
+ placeholders = xml_parsed.find_all("PLACEHOLDER")
26
+
27
+ output_list = []
28
+ for placeholder in placeholders:
29
+ parent_list = list(placeholder.parents)[:-1]
30
+ path = ".".join(
31
+ [p.attrs["code"] for p in parent_list if "code" in p.attrs][::-1],
32
+ )
33
+
34
+ deb = placeholder.attrs["deb"]
35
+
36
+ output_list.append((deb, path))
37
+
38
+ return sorted(output_list, key=lambda x: x[0])
39
+
40
+
41
+ if __name__ == "__main__":
42
+ assert len(sys.argv) == 2
43
+ input_dir = sys.argv[1]
44
+
45
+ param_files = find_param_files(input_dir)
46
+
47
+ for filename_input in param_files:
48
+ output_list = find_placeholders(filename_input)
49
+
50
+ for _deb, _path in output_list:
51
+ pass
@@ -0,0 +1,137 @@
1
+ #! /usr/bin/env python
2
+ # flake8: noqa T001
3
+
4
+
5
+ """Measure and compare different vectorial condition notations:
6
+ - using multiplication notation: (choice == 1) * choice_1_value + (choice == 2) * choice_2_value
7
+ - using numpy.select: the same than multiplication but more idiomatic like a "switch" control-flow statement
8
+ - using numpy.fromiter: iterates in Python over the array and calculates lazily only the required values.
9
+
10
+ The aim of this script is to compare the time taken by the calculation of the values
11
+ """
12
+
13
+ import argparse
14
+ import sys
15
+ import time
16
+ from contextlib import contextmanager
17
+
18
+ import numpy
19
+
20
+ args = None
21
+
22
+
23
+ @contextmanager
24
+ def measure_time(title):
25
+ time.time()
26
+ yield
27
+ time.time()
28
+
29
+
30
+ def switch_fromiter(conditions, function_by_condition, dtype):
31
+ value_by_condition = {}
32
+
33
+ def get_or_store_value(condition):
34
+ if condition not in value_by_condition:
35
+ value = function_by_condition[condition]()
36
+ value_by_condition[condition] = value
37
+ return value_by_condition[condition]
38
+
39
+ return numpy.fromiter(
40
+ (get_or_store_value(condition) for condition in conditions),
41
+ dtype,
42
+ )
43
+
44
+
45
+ def switch_select(conditions, value_by_condition):
46
+ condlist = [conditions == condition for condition in value_by_condition]
47
+ return numpy.select(condlist, value_by_condition.values())
48
+
49
+
50
+ def calculate_choice_1_value() -> int:
51
+ time.sleep(args.calculate_time)
52
+ return 80
53
+
54
+
55
+ def calculate_choice_2_value() -> int:
56
+ time.sleep(args.calculate_time)
57
+ return 90
58
+
59
+
60
+ def calculate_choice_3_value() -> int:
61
+ time.sleep(args.calculate_time)
62
+ return 95
63
+
64
+
65
+ def test_multiplication(choice):
66
+ choice_1_value = calculate_choice_1_value()
67
+ choice_2_value = calculate_choice_2_value()
68
+ choice_3_value = calculate_choice_3_value()
69
+ return (
70
+ (choice == 1) * choice_1_value
71
+ + (choice == 2) * choice_2_value
72
+ + (choice == 3) * choice_3_value
73
+ )
74
+
75
+
76
+ def test_switch_fromiter(choice):
77
+ return switch_fromiter(
78
+ choice,
79
+ {
80
+ 1: calculate_choice_1_value,
81
+ 2: calculate_choice_2_value,
82
+ 3: calculate_choice_3_value,
83
+ },
84
+ dtype=int,
85
+ )
86
+
87
+
88
+ def test_switch_select(choice):
89
+ choice_1_value = calculate_choice_1_value()
90
+ choice_2_value = calculate_choice_2_value()
91
+ choice_3_value = calculate_choice_2_value()
92
+ return switch_select(
93
+ choice,
94
+ {
95
+ 1: choice_1_value,
96
+ 2: choice_2_value,
97
+ 3: choice_3_value,
98
+ },
99
+ )
100
+
101
+
102
+ def test_all_notations() -> None:
103
+ # choice is an array with 1 and 2 items like [2, 1, ..., 1, 2]
104
+ choice = numpy.random.randint(2, size=args.array_length) + 1
105
+
106
+ with measure_time("multiplication"):
107
+ test_multiplication(choice)
108
+
109
+ with measure_time("switch_select"):
110
+ test_switch_select(choice)
111
+
112
+ with measure_time("switch_fromiter"):
113
+ test_switch_fromiter(choice)
114
+
115
+
116
+ def main() -> None:
117
+ parser = argparse.ArgumentParser(description=__doc__)
118
+ parser.add_argument(
119
+ "--array-length",
120
+ default=1000,
121
+ type=int,
122
+ help="length of the array",
123
+ )
124
+ parser.add_argument(
125
+ "--calculate-time",
126
+ default=0.1,
127
+ type=float,
128
+ help="time taken by the calculation in seconds",
129
+ )
130
+ global args
131
+ args = parser.parse_args()
132
+
133
+ test_all_notations()
134
+
135
+
136
+ if __name__ == "__main__":
137
+ sys.exit(main())
@@ -0,0 +1,291 @@
1
+ #! /usr/bin/env python
2
+ # flake8: noqa T001
3
+
4
+
5
+ """Measure performances of a basic tax-benefit system to compare to other OpenFisca implementations."""
6
+
7
+ import argparse
8
+ import logging
9
+ import sys
10
+ import time
11
+
12
+ import numpy
13
+ from numpy.core.defchararray import startswith
14
+
15
+ from openfisca_core import periods, simulations
16
+ from openfisca_core.entities import build_entity
17
+ from openfisca_core.periods import DateUnit
18
+ from openfisca_core.taxbenefitsystems import TaxBenefitSystem
19
+ from openfisca_core.tools import assert_near
20
+ from openfisca_core.variables import Variable
21
+
22
+ args = None
23
+
24
+
25
+ def timeit(method):
26
+ def timed(*args, **kwargs):
27
+ time.time()
28
+ return method(*args, **kwargs)
29
+ # print '%r (%r, %r) %2.9f s' % (method.__name__, args, kw, time.time() - start_time)
30
+
31
+ return timed
32
+
33
+
34
+ # Entities
35
+
36
+ Famille = build_entity(
37
+ key="famille",
38
+ plural="familles",
39
+ label="Famille",
40
+ roles=[
41
+ {
42
+ "key": "parent",
43
+ "plural": "parents",
44
+ "label": "Parents",
45
+ "subroles": ["demandeur", "conjoint"],
46
+ },
47
+ {
48
+ "key": "enfant",
49
+ "plural": "enfants",
50
+ "label": "Enfants",
51
+ },
52
+ ],
53
+ )
54
+
55
+
56
+ Individu = build_entity(
57
+ key="individu",
58
+ plural="individus",
59
+ label="Individu",
60
+ is_person=True,
61
+ )
62
+
63
+ # Input variables
64
+
65
+
66
+ class age_en_mois(Variable):
67
+ value_type = int
68
+ entity = Individu
69
+ label = "Âge (en nombre de mois)"
70
+
71
+
72
+ class birth(Variable):
73
+ value_type = "Date"
74
+ entity = Individu
75
+ label = "Date de naissance"
76
+
77
+
78
+ class city_code(Variable):
79
+ value_type = "FixedStr"
80
+ max_length = 5
81
+ entity = Famille
82
+ definition_period = DateUnit.ETERNITY
83
+ label = """Code INSEE "city_code" de la commune de résidence de la famille"""
84
+
85
+
86
+ class salaire_brut(Variable):
87
+ value_type = float
88
+ entity = Individu
89
+ label = "Salaire brut"
90
+
91
+
92
+ # Calculated variables
93
+
94
+
95
+ class age(Variable):
96
+ value_type = int
97
+ entity = Individu
98
+ label = "Âge (en nombre d'années)"
99
+
100
+ def formula(self, simulation, period):
101
+ birth = simulation.get_array("birth", period)
102
+ if birth is None:
103
+ age_en_mois = simulation.get_array("age_en_mois", period)
104
+ if age_en_mois is not None:
105
+ return age_en_mois // 12
106
+ birth = simulation.calculate("birth", period)
107
+ return (numpy.datetime64(period.date) - birth).astype("timedelta64[Y]")
108
+
109
+
110
+ class dom_tom(Variable):
111
+ value_type = "Bool"
112
+ entity = Famille
113
+ label = "La famille habite-t-elle les DOM-TOM ?"
114
+
115
+ def formula(self, simulation, period):
116
+ period = period.start.period(DateUnit.YEAR).offset("first-of")
117
+ city_code = simulation.calculate("city_code", period)
118
+ return numpy.logical_or(
119
+ startswith(city_code, "97"), startswith(city_code, "98")
120
+ )
121
+
122
+
123
+ class revenu_disponible(Variable):
124
+ value_type = float
125
+ entity = Individu
126
+ label = "Revenu disponible de l'individu"
127
+
128
+ def formula(self, simulation, period):
129
+ period = period.start.period(DateUnit.YEAR).offset("first-of")
130
+ rsa = simulation.calculate("rsa", period)
131
+ salaire_imposable = simulation.calculate("salaire_imposable", period)
132
+ return rsa + salaire_imposable * 0.7
133
+
134
+
135
+ class rsa(Variable):
136
+ value_type = float
137
+ entity = Individu
138
+ label = "RSA"
139
+
140
+ def formula_2010_01_01(self, simulation, period):
141
+ period = period.start.period(DateUnit.MONTH).offset("first-of")
142
+ salaire_imposable = simulation.calculate("salaire_imposable", period)
143
+ return (salaire_imposable < 500) * 100.0
144
+
145
+ def formula_2011_01_01(self, simulation, period):
146
+ period = period.start.period(DateUnit.MONTH).offset("first-of")
147
+ salaire_imposable = simulation.calculate("salaire_imposable", period)
148
+ return (salaire_imposable < 500) * 200.0
149
+
150
+ def formula_2013_01_01(self, simulation, period):
151
+ period = period.start.period(DateUnit.MONTH).offset("first-of")
152
+ salaire_imposable = simulation.calculate("salaire_imposable", period)
153
+ return (salaire_imposable < 500) * 300
154
+
155
+
156
+ class salaire_imposable(Variable):
157
+ value_type = float
158
+ entity = Individu
159
+ label = "Salaire imposable"
160
+
161
+ def formula(self, period):
162
+ period = period.start.period(DateUnit.YEAR).offset("first-of")
163
+ dom_tom = self.famille("dom_tom", period)
164
+ salaire_net = self("salaire_net", period)
165
+ return salaire_net * 0.9 - 100 * dom_tom
166
+
167
+
168
+ class salaire_net(Variable):
169
+ value_type = float
170
+ entity = Individu
171
+ label = "Salaire net"
172
+
173
+ def formula(self, simulation, period):
174
+ period = period.start.period(DateUnit.YEAR).offset("first-of")
175
+ salaire_brut = simulation.calculate("salaire_brut", period)
176
+ return salaire_brut * 0.8
177
+
178
+
179
+ # TaxBenefitSystem instance declared after formulas
180
+
181
+
182
+ tax_benefit_system = TaxBenefitSystem([Famille, Individu])
183
+ tax_benefit_system.add_variables(
184
+ age_en_mois,
185
+ birth,
186
+ city_code,
187
+ salaire_brut,
188
+ age,
189
+ dom_tom,
190
+ revenu_disponible,
191
+ rsa,
192
+ salaire_imposable,
193
+ salaire_net,
194
+ )
195
+
196
+
197
+ @timeit
198
+ def check_revenu_disponible(year, city_code, expected_revenu_disponible) -> None:
199
+ simulation = simulations.Simulation(
200
+ period=periods.period(year),
201
+ tax_benefit_system=tax_benefit_system,
202
+ )
203
+ famille = simulation.populations["famille"]
204
+ famille.count = 3
205
+ famille.roles_count = 2
206
+ famille.step_size = 1
207
+ individu = simulation.populations["individu"]
208
+ individu.count = 6
209
+ individu.step_size = 2
210
+ simulation.get_or_new_holder("city_code").array = numpy.array(
211
+ [city_code, city_code, city_code],
212
+ )
213
+ famille.members_entity_id = numpy.array([0, 0, 1, 1, 2, 2])
214
+ simulation.get_or_new_holder("salaire_brut").array = numpy.array(
215
+ [0.0, 0.0, 50000.0, 0.0, 100000.0, 0.0],
216
+ )
217
+ revenu_disponible = simulation.calculate("revenu_disponible")
218
+ assert_near(
219
+ revenu_disponible,
220
+ expected_revenu_disponible,
221
+ absolute_error_margin=0.005,
222
+ )
223
+
224
+
225
+ def main() -> None:
226
+ parser = argparse.ArgumentParser(description=__doc__)
227
+ parser.add_argument(
228
+ "-v",
229
+ "--verbose",
230
+ action="store_true",
231
+ default=False,
232
+ help="increase output verbosity",
233
+ )
234
+ global args
235
+ args = parser.parse_args()
236
+ logging.basicConfig(
237
+ level=logging.DEBUG if args.verbose else logging.WARNING,
238
+ stream=sys.stdout,
239
+ )
240
+
241
+ check_revenu_disponible(2009, "75101", numpy.array([0, 0, 25200, 0, 50400, 0]))
242
+ check_revenu_disponible(
243
+ 2010,
244
+ "75101",
245
+ numpy.array([1200, 1200, 25200, 1200, 50400, 1200]),
246
+ )
247
+ check_revenu_disponible(
248
+ 2011,
249
+ "75101",
250
+ numpy.array([2400, 2400, 25200, 2400, 50400, 2400]),
251
+ )
252
+ check_revenu_disponible(
253
+ 2012,
254
+ "75101",
255
+ numpy.array([2400, 2400, 25200, 2400, 50400, 2400]),
256
+ )
257
+ check_revenu_disponible(
258
+ 2013,
259
+ "75101",
260
+ numpy.array([3600, 3600, 25200, 3600, 50400, 3600]),
261
+ )
262
+
263
+ check_revenu_disponible(
264
+ 2009,
265
+ "97123",
266
+ numpy.array([-70.0, -70.0, 25130.0, -70.0, 50330.0, -70.0]),
267
+ )
268
+ check_revenu_disponible(
269
+ 2010,
270
+ "97123",
271
+ numpy.array([1130.0, 1130.0, 25130.0, 1130.0, 50330.0, 1130.0]),
272
+ )
273
+ check_revenu_disponible(
274
+ 2011,
275
+ "98456",
276
+ numpy.array([2330.0, 2330.0, 25130.0, 2330.0, 50330.0, 2330.0]),
277
+ )
278
+ check_revenu_disponible(
279
+ 2012,
280
+ "98456",
281
+ numpy.array([2330.0, 2330.0, 25130.0, 2330.0, 50330.0, 2330.0]),
282
+ )
283
+ check_revenu_disponible(
284
+ 2013,
285
+ "98456",
286
+ numpy.array([3530.0, 3530.0, 25130.0, 3530.0, 50330.0, 3530.0]),
287
+ )
288
+
289
+
290
+ if __name__ == "__main__":
291
+ sys.exit(main())
@@ -0,0 +1,89 @@
1
+ # flake8: noqa T001
2
+
3
+ import timeit
4
+
5
+ import numpy
6
+ from openfisca_france import CountryTaxBenefitSystem
7
+
8
+ tbs = CountryTaxBenefitSystem()
9
+ N = 200000
10
+ al_plaf_acc = tbs.get_parameters_at_instant("2015-01-01").prestations.al_plaf_acc
11
+ zone_apl = numpy.random.choice([1, 2, 3], N)
12
+ al_nb_pac = numpy.random.choice(6, N)
13
+ couple = numpy.random.choice([True, False], N)
14
+ formatted_zone = concat(
15
+ "plafond_pour_accession_a_la_propriete_zone_",
16
+ zone_apl,
17
+ ) # zone_apl returns 1, 2 or 3 but the parameters have a long name
18
+
19
+
20
+ def formula_with():
21
+ plafonds = al_plaf_acc[formatted_zone]
22
+
23
+ return (
24
+ plafonds.personne_isolee_sans_enfant * not_(couple) * (al_nb_pac == 0)
25
+ + plafonds.menage_seul * couple * (al_nb_pac == 0)
26
+ + plafonds.menage_ou_isole_avec_1_enfant * (al_nb_pac == 1)
27
+ + plafonds.menage_ou_isole_avec_2_enfants * (al_nb_pac == 2)
28
+ + plafonds.menage_ou_isole_avec_3_enfants * (al_nb_pac == 3)
29
+ + plafonds.menage_ou_isole_avec_4_enfants * (al_nb_pac == 4)
30
+ + plafonds.menage_ou_isole_avec_5_enfants * (al_nb_pac >= 5)
31
+ + plafonds.menage_ou_isole_par_enfant_en_plus
32
+ * (al_nb_pac > 5)
33
+ * (al_nb_pac - 5)
34
+ )
35
+
36
+
37
+ def formula_without():
38
+ z1 = al_plaf_acc.plafond_pour_accession_a_la_propriete_zone_1
39
+ z2 = al_plaf_acc.plafond_pour_accession_a_la_propriete_zone_2
40
+ z3 = al_plaf_acc.plafond_pour_accession_a_la_propriete_zone_3
41
+
42
+ return (
43
+ (zone_apl == 1)
44
+ * (
45
+ z1.personne_isolee_sans_enfant * not_(couple) * (al_nb_pac == 0)
46
+ + z1.menage_seul * couple * (al_nb_pac == 0)
47
+ + z1.menage_ou_isole_avec_1_enfant * (al_nb_pac == 1)
48
+ + z1.menage_ou_isole_avec_2_enfants * (al_nb_pac == 2)
49
+ + z1.menage_ou_isole_avec_3_enfants * (al_nb_pac == 3)
50
+ + z1.menage_ou_isole_avec_4_enfants * (al_nb_pac == 4)
51
+ + z1.menage_ou_isole_avec_5_enfants * (al_nb_pac >= 5)
52
+ + z1.menage_ou_isole_par_enfant_en_plus * (al_nb_pac > 5) * (al_nb_pac - 5)
53
+ )
54
+ + (zone_apl == 2)
55
+ * (
56
+ z2.personne_isolee_sans_enfant * not_(couple) * (al_nb_pac == 0)
57
+ + z2.menage_seul * couple * (al_nb_pac == 0)
58
+ + z2.menage_ou_isole_avec_1_enfant * (al_nb_pac == 1)
59
+ + z2.menage_ou_isole_avec_2_enfants * (al_nb_pac == 2)
60
+ + z2.menage_ou_isole_avec_3_enfants * (al_nb_pac == 3)
61
+ + z2.menage_ou_isole_avec_4_enfants * (al_nb_pac == 4)
62
+ + z2.menage_ou_isole_avec_5_enfants * (al_nb_pac >= 5)
63
+ + z2.menage_ou_isole_par_enfant_en_plus * (al_nb_pac > 5) * (al_nb_pac - 5)
64
+ )
65
+ + (zone_apl == 3)
66
+ * (
67
+ z3.personne_isolee_sans_enfant * not_(couple) * (al_nb_pac == 0)
68
+ + z3.menage_seul * couple * (al_nb_pac == 0)
69
+ + z3.menage_ou_isole_avec_1_enfant * (al_nb_pac == 1)
70
+ + z3.menage_ou_isole_avec_2_enfants * (al_nb_pac == 2)
71
+ + z3.menage_ou_isole_avec_3_enfants * (al_nb_pac == 3)
72
+ + z3.menage_ou_isole_avec_4_enfants * (al_nb_pac == 4)
73
+ + z3.menage_ou_isole_avec_5_enfants * (al_nb_pac >= 5)
74
+ + z3.menage_ou_isole_par_enfant_en_plus * (al_nb_pac > 5) * (al_nb_pac - 5)
75
+ )
76
+ )
77
+
78
+
79
+ if __name__ == "__main__":
80
+ time_with = timeit.timeit(
81
+ "formula_with()",
82
+ setup="from __main__ import formula_with",
83
+ number=50,
84
+ )
85
+ time_without = timeit.timeit(
86
+ "formula_without()",
87
+ setup="from __main__ import formula_without",
88
+ number=50,
89
+ )
File without changes