Skip to content

Commit cd8e6f3

Browse files
committed
Allow arrays in legislation parameters
2 parents f769804 + 77d5808 commit cd8e6f3

6 files changed

Lines changed: 66 additions & 48 deletions

File tree

CHANGELOG.md

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,18 @@
11
# Changelog
22

3+
## 35.2.0 [#982](https://github.com/openfisca/openfisca-core/pull/982)
4+
5+
#### Technical changes
6+
7+
- Allow parameters to be arrays.
8+
39
### 35.1.1 [#981](https://github.com/openfisca/openfisca-core/pull/981)
410

511
#### Technical changes
612

713
- Fix false negative web API test following an update in the country template used for testing.
814

9-
### 35.1.0 [#973](https://github.com/openfisca/openfisca-core/pull/973)
15+
## 35.1.0 [#973](https://github.com/openfisca/openfisca-core/pull/973)
1016

1117
#### Technical changes
1218

openfisca_core/parameters.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@
3636
# 'unit' and 'reference' are only listed here for backward compatibility.
3737
# It is now recommended to include them in metadata, until a common consensus emerges.
3838
COMMON_KEYS = {'description', 'metadata', 'unit', 'reference', 'documentation'}
39-
ALLOWED_PARAM_TYPES = (float, int, bool, type(None))
39+
ALLOWED_PARAM_TYPES = (float, int, bool, type(None), List)
4040

4141

4242
def date_constructor(loader, node):
@@ -319,7 +319,7 @@ def validate(self, data):
319319
)
320320
if not isinstance(value, ALLOWED_PARAM_TYPES):
321321
raise ParameterParsingError(
322-
"Invalid value in {} : {}".format(self.name, value),
322+
"Value in {} has type {}, which is not one of the allowed types ({}): {}".format(self.name, type(value), ALLOWED_PARAM_TYPES, value),
323323
self.file_path
324324
)
325325

@@ -851,7 +851,7 @@ def load_parameter_file(file_path, name = ''):
851851
:returns: An instance of :any:`ParameterNode` or :any:`Scale` or :any:`Parameter`.
852852
"""
853853
if not os.path.exists(file_path):
854-
raise ValueError("{} doest not exist".format(file_path))
854+
raise ValueError("{} does not exist".format(file_path))
855855
if os.path.isdir(file_path):
856856
return ParameterNode(name, directory_path = file_path)
857857
data = _load_yaml_file(file_path)

openfisca_web_api/openAPI.yml

Lines changed: 41 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -34,49 +34,49 @@ paths:
3434
post:
3535
summary: "Run a simulation"
3636
tags:
37-
- Calculations
37+
- Calculations
3838
operationId: "calculate"
3939
consumes:
40-
- "application/json"
40+
- "application/json"
4141
produces:
42-
- "application/json"
42+
- "application/json"
4343
parameters:
4444
- in: "body"
4545
name: "Situation"
46-
description: 'Describe the situation (persons and entities). Add the variable you wish to calculate in the proper entity, with null as the value. Learn more in our official documentation: https://openfisca.org/doc/openfisca-web-api/input-output-data.html'
46+
description: "Describe the situation (persons and entities). Add the variable you wish to calculate in the proper entity, with null as the value. Learn more in our official documentation: https://openfisca.org/doc/openfisca-web-api/input-output-data.html"
4747
required: true
4848
schema:
49-
$ref: '#/definitions/SituationInput'
49+
$ref: "#/definitions/SituationInput"
5050
responses:
5151
200:
5252
description: "The calculation result is sent back in the response body"
5353
headers:
54-
$ref: '#/commons/Headers'
54+
$ref: "#/commons/Headers"
5555
schema:
56-
$ref: '#/definitions/SituationOutput'
56+
$ref: "#/definitions/SituationOutput"
5757
404:
5858
description: "A variable mentioned in the input situation does not exist in the loaded tax and benefit system. Details are sent back in the response body"
5959
headers:
60-
$ref: '#/commons/Headers'
60+
$ref: "#/commons/Headers"
6161
400:
6262
description: "The request is invalid. Details about the error are sent back in the response body"
6363
headers:
64-
$ref: '#/commons/Headers'
64+
$ref: "#/commons/Headers"
6565
/parameters:
6666
get:
6767
tags:
68-
- "Parameters"
68+
- "Parameters"
6969
summary: "List all available parameters"
7070
operationId: "getParameters"
7171
produces:
72-
- "application/json"
72+
- "application/json"
7373
responses:
7474
200:
7575
description: "The list of parameters is sent back in the response body"
7676
headers:
77-
$ref: '#/commons/Headers'
77+
$ref: "#/commons/Headers"
7878
schema:
79-
$ref: '#/definitions/Parameters'
79+
$ref: "#/definitions/Parameters"
8080
/parameter/{parameterID}:
8181
get:
8282
tags:
@@ -95,13 +95,13 @@ paths:
9595
200:
9696
description: "The requested parameter's information is sent back in the response body"
9797
headers:
98-
$ref: '#/commons/Headers'
98+
$ref: "#/commons/Headers"
9999
schema:
100100
$ref: "#/definitions/Parameter"
101101
404:
102102
description: "The requested parameter does not exist"
103103
headers:
104-
$ref: '#/commons/Headers'
104+
$ref: "#/commons/Headers"
105105
/variables:
106106
get:
107107
tags:
@@ -114,7 +114,7 @@ paths:
114114
200:
115115
description: "The list of variables is sent back in the response body"
116116
headers:
117-
$ref: '#/commons/Headers'
117+
$ref: "#/commons/Headers"
118118
schema:
119119
$ref: "#/definitions/Variables"
120120
/variable/{variableID}:
@@ -135,13 +135,13 @@ paths:
135135
200:
136136
description: "The requested variable's information is sent back in the response body"
137137
headers:
138-
$ref: '#/commons/Headers'
138+
$ref: "#/commons/Headers"
139139
schema:
140140
$ref: "#/definitions/Variable"
141141
404:
142142
description: "The requested variable does not exist"
143143
headers:
144-
$ref: '#/commons/Headers'
144+
$ref: "#/commons/Headers"
145145
/entities:
146146
get:
147147
tags:
@@ -154,61 +154,61 @@ paths:
154154
200:
155155
description: "The list of the entities as well as their information is sent back in the response body"
156156
headers:
157-
$ref: '#/commons/Headers'
157+
$ref: "#/commons/Headers"
158158
schema:
159159
$ref: "#/definitions/Entities"
160160
/trace:
161161
post:
162162
summary: "Explore a simulation's steps in details."
163163
tags:
164-
- Calculations
164+
- Calculations
165165
operationId: "trace"
166166
consumes:
167-
- "application/json"
167+
- "application/json"
168168
produces:
169-
- "application/json"
169+
- "application/json"
170170
parameters:
171171
- in: "body"
172172
name: "Situation"
173-
description: 'Describe the situation (persons and entities). Add the variable you wish to calculate in the proper entity, with null as the value.'
173+
description: "Describe the situation (persons and entities). Add the variable you wish to calculate in the proper entity, with null as the value."
174174
required: true
175175
schema:
176-
$ref: '#/definitions/SituationInput'
176+
$ref: "#/definitions/SituationInput"
177177
responses:
178178
200:
179179
description: "The calculation details are sent back in the response body"
180180
headers:
181-
$ref: '#/commons/Headers'
181+
$ref: "#/commons/Headers"
182182
schema:
183-
$ref: '#/definitions/Trace'
183+
$ref: "#/definitions/Trace"
184184
404:
185185
description: "A variable mentioned in the input situation does not exist in the loaded tax and benefit system. Details are sent back in the response body"
186186
headers:
187-
$ref: '#/commons/Headers'
187+
$ref: "#/commons/Headers"
188188
400:
189189
description: "The request is invalid. Details about the error are sent back in the response body"
190190
headers:
191-
$ref: '#/commons/Headers'
191+
$ref: "#/commons/Headers"
192192
/spec:
193193
get:
194194
summary: Provide the API documentation in an OpenAPI format
195195
tags:
196-
- Documentation
196+
- Documentation
197197
operationId: spec
198198
produces:
199-
- application/json
199+
- application/json
200200
responses:
201201
200:
202202
description: The API documentation is sent back in the response body
203203
headers:
204-
$ref: '#/commons/Headers'
204+
$ref: "#/commons/Headers"
205205

206206
definitions:
207207
Parameter:
208208
type: "object"
209209
properties:
210210
values:
211-
$ref: '#/definitions/Values'
211+
$ref: "#/definitions/Values"
212212
brackets:
213213
type: "object"
214214
additionalProperties:
@@ -219,7 +219,7 @@ definitions:
219219
type: "object"
220220
properties:
221221
definition:
222-
type: 'string'
222+
type: "string"
223223
metadata:
224224
type: "object"
225225
description:
@@ -237,9 +237,9 @@ definitions:
237237
type: "object"
238238
properties:
239239
description:
240-
type: 'string'
240+
type: "string"
241241
href:
242-
type: 'string'
242+
type: "string"
243243

244244
Variable:
245245
type: "object"
@@ -284,9 +284,9 @@ definitions:
284284
type: "object"
285285
properties:
286286
description:
287-
type: 'string'
287+
type: "string"
288288
href:
289-
type: 'string'
289+
type: "string"
290290

291291
Formula:
292292
type: "object"
@@ -303,10 +303,11 @@ definitions:
303303
format: "float"
304304

305305
Values:
306+
description: All keys are ISO dates. Values can be numbers, booleans, or arrays of a single type (number, boolean or string).
306307
type: "object"
307-
additionalProperties:
308-
type: "number"
309-
format: "float"
308+
additionalProperties: true
309+
# propertyNames: # this keyword is part of JSON Schema but is not supported in OpenAPI Specification at the time of writing, see https://swagger.io/docs/specification/data-models/keywords/#unsupported
310+
# pattern: "^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$" # all keys are ISO dates
310311

311312
Entities:
312313
type: "object"

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@
3737

3838
setup(
3939
name = 'OpenFisca-Core',
40-
version = '35.1.1',
40+
version = '35.2.0',
4141
author = 'OpenFisca Team',
4242
author_email = 'contact@openfisca.org',
4343
classifiers = [
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
description: Array types should be allowed.
2+
values:
3+
2013-01-01:
4+
value: [ FR ]
5+
2018-06-01:
6+
value: [ ES, FR, IT, NZ ]

tests/core/parameter_validation/test_parameter_validation.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
year = 2016
99

1010

11-
def check(file_name, keywords):
11+
def check_fails_with_message(file_name, keywords):
1212
path = os.path.join(BASE_DIR, file_name) + '.yaml'
1313
try:
1414
load_parameter_file(path, file_name)
@@ -22,7 +22,7 @@ def check(file_name, keywords):
2222
@pytest.mark.parametrize("test", [
2323
('indentation', {'Invalid YAML', 'indentation.yaml', 'line 2', 'mapping values are not allowed'}),
2424
('wrong_scale', {'Unexpected property', 'scale[1]', 'treshold'}),
25-
('wrong_value', {'Invalid value', 'wrong_value[2015-12-01]', '1A'}),
25+
('wrong_value', {'not one of the allowed types', 'wrong_value[2015-12-01]', '1A'}),
2626
('unexpected_key_in_parameter', {'Unexpected property', 'unexpected_key'}),
2727
('wrong_type_in_parameter', {'must be of type object'}),
2828
('wrong_type_in_value_history', {'must be of type object'}),
@@ -37,7 +37,12 @@ def check(file_name, keywords):
3737
])
3838
def test_parsing_errors(test):
3939
with pytest.raises(ParameterParsingError):
40-
check(*test)
40+
check_fails_with_message(*test)
41+
42+
43+
def test_array_type():
44+
path = os.path.join(BASE_DIR, 'array_type.yaml')
45+
load_parameter_file(path, 'array_type')
4146

4247

4348
def test_filesystem_hierarchy():

0 commit comments

Comments
 (0)