From 5564bae44d68ac45cacbbaca3115701cf9ae8bed Mon Sep 17 00:00:00 2001 From: Matti Schneider Date: Tue, 23 Mar 2021 11:25:29 +0000 Subject: [PATCH 01/17] Validate OpenAPI spec --- setup.py | 1 + tests/web_api/test_spec.py | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/setup.py b/setup.py index 3726a3bf4a..a8682f9fe6 100644 --- a/setup.py +++ b/setup.py @@ -55,6 +55,7 @@ 'flake8-print >= 3.1.0, < 4.0.0', 'flake8-rst-docstrings == 0.2.3', 'mypy == 0.910', + 'openapi-spec-validator >= 0.3.0', 'pycodestyle >= 2.8.0, < 2.9.0', 'pylint == 2.10.2', 'xdoctest >= 1.0.0, < 2.0.0', diff --git a/tests/web_api/test_spec.py b/tests/web_api/test_spec.py index 24668dac17..b39d4b89cc 100644 --- a/tests/web_api/test_spec.py +++ b/tests/web_api/test_spec.py @@ -3,6 +3,8 @@ import pytest from http import client +from openapi_spec_validator import validate_v2_spec + def assert_items_equal(x, y): assert sorted(x) == sorted(y) @@ -53,3 +55,7 @@ def test_situation_definition(body): def test_host(body): assert 'http' not in body['host'] + + +def test_respects_spec(): + validate_v2_spec(body) From 4b0c4cd4c019f172b7d6893e578d67049d55a562 Mon Sep 17 00:00:00 2001 From: Matti Schneider Date: Tue, 23 Mar 2021 13:19:38 +0000 Subject: [PATCH 02/17] Document array type in parameters values --- openfisca_web_api/openAPI.yml | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index d0c52f9a14..b9850b4d7a 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -305,10 +305,23 @@ definitions: Values: description: All keys are ISO dates. Values can be numbers, booleans, or arrays of a single type (number, boolean or string). type: "object" - additionalProperties: true + additionalProperties: + $ref: "#/definitions/Value" # 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 # pattern: "^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$" # all keys are ISO dates + Value: + oneOf: + - type: "boolean" + - type: "number" + format: "float" + - type: "array" + items: + type: + oneOf: + - "string" + - "number" + Entities: type: "object" properties: From b7fa6127cc203c8aab5d3ec1b42720c2b9c3b537 Mon Sep 17 00:00:00 2001 From: Matti Schneider Date: Tue, 23 Mar 2021 13:20:02 +0000 Subject: [PATCH 03/17] Validate Country-Package-Version header --- openfisca_web_api/openAPI.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index b9850b4d7a..4b9a853930 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -385,3 +385,4 @@ commons: Country-Package-Version: description: "The version of the country package currently loaded in this API server" type: "string" + pattern: "^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" # from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string From 858c9deaa0a81c0248edc609f34a3b38e0acd79a Mon Sep 17 00:00:00 2001 From: Matti Schneider Date: Tue, 23 Mar 2021 13:23:07 +0000 Subject: [PATCH 04/17] Use JSON Schema-compatible regexp --- openfisca_web_api/openAPI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index 4b9a853930..cf5d19b97e 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -385,4 +385,4 @@ commons: Country-Package-Version: description: "The version of the country package currently loaded in this API server" type: "string" - pattern: "^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$" # from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" # adapted from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string From bbdc0e2ae79ca2929924fd9a1185059c10926389 Mon Sep 17 00:00:00 2001 From: Matti Schneider Date: Tue, 23 Mar 2021 16:34:38 +0000 Subject: [PATCH 05/17] Switch to OpenAPI v3 --- openfisca_web_api/openAPI.yml | 2 +- tests/web_api/test_spec.py | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index cf5d19b97e..19dbc24105 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -1,4 +1,4 @@ -swagger: "2.0" +openapi: "3.0" info: title: "{COUNTRY_PACKAGE_NAME} Web API" description: "The OpenFisca Web API lets you get up-to-date information and formulas included in the {COUNTRY_PACKAGE_NAME} legislation." diff --git a/tests/web_api/test_spec.py b/tests/web_api/test_spec.py index b39d4b89cc..a5139ee7b9 100644 --- a/tests/web_api/test_spec.py +++ b/tests/web_api/test_spec.py @@ -3,7 +3,7 @@ import pytest from http import client -from openapi_spec_validator import validate_v2_spec +from openapi_spec_validator import validate_v3_spec def assert_items_equal(x, y): @@ -58,4 +58,4 @@ def test_host(body): def test_respects_spec(): - validate_v2_spec(body) + validate_v3_spec(body) From a5358d10aa4223702e84f43295a0f68079f52eb8 Mon Sep 17 00:00:00 2001 From: Matti Schneider Date: Tue, 23 Mar 2021 16:34:50 +0000 Subject: [PATCH 06/17] Reuse headers in OpenAPI definition --- openfisca_web_api/openAPI.yml | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index 19dbc24105..fb554f4a8e 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -51,17 +51,17 @@ paths: 200: description: "The calculation result is sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" schema: $ref: "#/definitions/SituationOutput" 404: 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" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" 400: description: "The request is invalid. Details about the error are sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" /parameters: get: tags: @@ -74,7 +74,7 @@ paths: 200: description: "The list of parameters is sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" schema: $ref: "#/definitions/Parameters" /parameter/{parameterID}: @@ -95,13 +95,13 @@ paths: 200: description: "The requested parameter's information is sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" schema: $ref: "#/definitions/Parameter" 404: description: "The requested parameter does not exist" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" /variables: get: tags: @@ -114,7 +114,7 @@ paths: 200: description: "The list of variables is sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" schema: $ref: "#/definitions/Variables" /variable/{variableID}: @@ -135,13 +135,13 @@ paths: 200: description: "The requested variable's information is sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" schema: $ref: "#/definitions/Variable" 404: description: "The requested variable does not exist" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" /entities: get: tags: @@ -154,7 +154,7 @@ paths: 200: description: "The list of the entities as well as their information is sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" schema: $ref: "#/definitions/Entities" /trace: @@ -178,17 +178,17 @@ paths: 200: description: "The calculation details are sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" schema: $ref: "#/definitions/Trace" 404: 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" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" 400: description: "The request is invalid. Details about the error are sent back in the response body" headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" /spec: get: summary: Provide the API documentation in an OpenAPI format @@ -201,7 +201,7 @@ paths: 200: description: The API documentation is sent back in the response body headers: - $ref: "#/commons/Headers" + $ref: "#/components/headers" definitions: Parameter: @@ -377,8 +377,8 @@ definitions: example: null -commons: - Headers: +components: + headers: Country-Package: description: "The name of the country package currently loaded in this API server" type: "string" From a36733f39b3aca4d3776c4b1c1657003b5adb5ca Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Fri, 2 Apr 2021 11:36:00 +0200 Subject: [PATCH 07/17] Use semver for openapi version --- openfisca_web_api/openAPI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index fb554f4a8e..8e5e62490b 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -1,4 +1,4 @@ -openapi: "3.0" +openapi: "3.0.0" info: title: "{COUNTRY_PACKAGE_NAME} Web API" description: "The OpenFisca Web API lets you get up-to-date information and formulas included in the {COUNTRY_PACKAGE_NAME} legislation." From 67ec4b38436058d3396435c39d1fc7d90438faef Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Fri, 2 Apr 2021 11:39:39 +0200 Subject: [PATCH 08/17] Use dpath to set country package's version --- openfisca_web_api/loader/spec.py | 3 ++- openfisca_web_api/openAPI.yml | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/openfisca_web_api/loader/spec.py b/openfisca_web_api/loader/spec.py index 92d617c057..9c5b38ef6e 100644 --- a/openfisca_web_api/loader/spec.py +++ b/openfisca_web_api/loader/spec.py @@ -18,9 +18,10 @@ def build_openAPI_specification(api_data): file = open(OPEN_API_CONFIG_FILE, 'r') spec = yaml.safe_load(file) country_package_name = api_data['country_package_metadata']['name'].title() + country_package_version = api_data['country_package_metadata']['version'] dpath.util.new(spec, 'info/title', spec['info']['title'].replace("{COUNTRY_PACKAGE_NAME}", country_package_name)) dpath.util.new(spec, 'info/description', spec['info']['description'].replace("{COUNTRY_PACKAGE_NAME}", country_package_name)) - dpath.util.new(spec, 'info/version', api_data['country_package_metadata']['version']) + dpath.util.new(spec, 'info/version', spec['info']['version'].replace("{COUNTRY_PACKAGE_VERSION}", country_package_version)) for entity in tax_benefit_system.entities: name = entity.key.title() diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index 8e5e62490b..b1657f110e 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -2,7 +2,7 @@ openapi: "3.0.0" info: title: "{COUNTRY_PACKAGE_NAME} Web API" description: "The OpenFisca Web API lets you get up-to-date information and formulas included in the {COUNTRY_PACKAGE_NAME} legislation." - version: null + version: "{COUNTRY_PACKAGE_VERSION}" termsOfService: "https://openfisca.org/doc/licence.html" contact: email: "contact@openfisca.org" From 1425867b6d96f7b0a4eb00873337386b02d489f5 Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Sun, 16 Oct 2022 02:12:31 +0200 Subject: [PATCH 09/17] Fix OAS 3.0 paths --- openfisca_web_api/openAPI.yml | 146 +++++++++++++++++++--------------- 1 file changed, 84 insertions(+), 62 deletions(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index b1657f110e..ec4d796704 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -1,4 +1,5 @@ openapi: "3.0.0" + info: title: "{COUNTRY_PACKAGE_NAME} Web API" description: "The OpenFisca Web API lets you get up-to-date information and formulas included in the {COUNTRY_PACKAGE_NAME} legislation." @@ -9,26 +10,30 @@ info: license: name: "AGPL" url: "https://www.gnu.org/licenses/agpl-3.0" -host: null -schemes: null + tags: - name: "Parameters" description: "A parameter is a numeric property of the legislation that can evolve over time." externalDocs: description: "Parameters documentation" url: "https://openfisca.org/doc/key-concepts/parameters.html" + - name: "Variables" description: "A variable depends on a person, or an entity (e.g. zip code, salary, income tax)." externalDocs: description: "Variables documentation" url: "https://openfisca.org/doc/key-concepts/variables.html" + - name: "Entities" description: "An entity is a person of a group of individuals (such as a household)." externalDocs: description: "Entities documentation" url: "https://openfisca.org/doc/key-concepts/person,_entities,_role.html" + - name: "Calculations" + - name: "Documentation" + paths: /calculate: post: @@ -36,172 +41,189 @@ paths: tags: - Calculations operationId: "calculate" - consumes: - - "application/json" - produces: - - "application/json" - parameters: - - in: "body" - name: "Situation" + requestBody: 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" required: true - schema: - $ref: "#/definitions/SituationInput" + content: + application/json: + schema: + $ref: "#/definitions/SituationInput" responses: 200: description: "The calculation result is sent back in the response body" + content: + application/json: + schema: + $ref: "#/definitions/SituationOutput" headers: - $ref: "#/components/headers" - schema: - $ref: "#/definitions/SituationOutput" + schema: + $ref: "#/components/headers" 404: 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" headers: - $ref: "#/components/headers" + schema: + $ref: "#/components/headers" 400: description: "The request is invalid. Details about the error are sent back in the response body" headers: - $ref: "#/components/headers" + schema: + $ref: "#/components/headers" + /parameters: get: tags: - "Parameters" summary: "List all available parameters" operationId: "getParameters" - produces: - - "application/json" responses: 200: description: "The list of parameters is sent back in the response body" + content: + application/json: + schema: + $ref: "#/definitions/Parameters" headers: - $ref: "#/components/headers" - schema: - $ref: "#/definitions/Parameters" + schema: + $ref: "#/components/headers" + /parameter/{parameterID}: get: tags: - "Parameters" summary: "Get information about a specific parameter" operationId: "getParameter" - produces: - - "application/json" parameters: - name: "parameterID" in: "path" description: "ID of parameter. IDs can be obtained by enumerating the /parameters endpoint" required: true - type: "string" + schema: + type: "string" responses: 200: description: "The requested parameter's information is sent back in the response body" + content: + application/json: + schema: + $ref: "#/definitions/Parameter" headers: - $ref: "#/components/headers" - schema: - $ref: "#/definitions/Parameter" + schema: + $ref: "#/components/headers" 404: description: "The requested parameter does not exist" headers: - $ref: "#/components/headers" + schema: + $ref: "#/components/headers" + /variables: get: tags: - "Variables" summary: "List all available variables" operationId: "getVariables" - produces: - - "application/json" responses: 200: description: "The list of variables is sent back in the response body" + content: + application/json: + schema: + $ref: "#/definitions/Variables" headers: - $ref: "#/components/headers" - schema: - $ref: "#/definitions/Variables" + schema: + $ref: "#/components/headers" + /variable/{variableID}: get: tags: - "Variables" summary: "Get information about a specific variable" operationId: "getVariable" - produces: - - "application/json" parameters: - name: "variableID" in: "path" description: "ID of a variable. IDs can be obtained by enumerating the /variables endpoint." required: true - type: "string" + schema: + type: "string" responses: 200: description: "The requested variable's information is sent back in the response body" + content: + application/json: + schema: + $ref: "#/definitions/Variable" headers: - $ref: "#/components/headers" - schema: - $ref: "#/definitions/Variable" + schema: + $ref: "#/components/headers" 404: description: "The requested variable does not exist" headers: - $ref: "#/components/headers" + schema: + $ref: "#/components/headers" + /entities: get: tags: - "Entities" summary: "List all available Entities" operationId: "getVariables" - produces: - - "application/json" responses: 200: description: "The list of the entities as well as their information is sent back in the response body" + content: + application/json: + schema: + $ref: "#/definitions/Entities" headers: - $ref: "#/components/headers" - schema: - $ref: "#/definitions/Entities" + schema: + $ref: "#/components/headers" + /trace: post: summary: "Explore a simulation's steps in details." tags: - Calculations operationId: "trace" - consumes: - - "application/json" - produces: - - "application/json" - parameters: - - in: "body" - name: "Situation" + requestBody: description: "Describe the situation (persons and entities). Add the variable you wish to calculate in the proper entity, with null as the value." required: true - schema: - $ref: "#/definitions/SituationInput" + content: + application/json: + schema: + $ref: "#/definitions/SituationInput" responses: 200: description: "The calculation details are sent back in the response body" + content: + application/json: + schema: + $ref: "#/definitions/Trace" headers: - $ref: "#/components/headers" - schema: - $ref: "#/definitions/Trace" + schema: + $ref: "#/components/headers" 404: 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" headers: - $ref: "#/components/headers" + schema: + $ref: "#/components/headers" 400: description: "The request is invalid. Details about the error are sent back in the response body" headers: - $ref: "#/components/headers" + schema: + $ref: "#/components/headers" + /spec: get: summary: Provide the API documentation in an OpenAPI format tags: - Documentation operationId: spec - produces: - - application/json responses: 200: description: The API documentation is sent back in the response body headers: - $ref: "#/components/headers" + schema: + $ref: "#/components/headers" definitions: Parameter: From fb958b35466b14c87b03e9e641de6836d9f1eb7f Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Sun, 16 Oct 2022 02:57:45 +0200 Subject: [PATCH 10/17] Fix OAS 3.0 headers --- openfisca_web_api/loader/spec.py | 2 +- openfisca_web_api/openAPI.yml | 469 ++++++++++++++++--------------- tests/web_api/test_spec.py | 4 +- 3 files changed, 253 insertions(+), 222 deletions(-) diff --git a/openfisca_web_api/loader/spec.py b/openfisca_web_api/loader/spec.py index 9c5b38ef6e..0fbb4ca90c 100644 --- a/openfisca_web_api/loader/spec.py +++ b/openfisca_web_api/loader/spec.py @@ -116,7 +116,7 @@ def get_situation_json_schema(tax_benefit_system): entity.plural: { 'type': 'object', 'additionalProperties': { - "$ref": "#/definitions/{}".format(entity.key.title()) + "$ref": "#/components/schemas/{}".format(entity.key.title()) } } for entity in tax_benefit_system.entities diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index ec4d796704..92fb52e162 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -34,6 +34,191 @@ tags: - name: "Documentation" +components: + schemas: + Parameter: + type: "object" + properties: + values: + $ref: "#/components/schemas/Values" + brackets: + type: "object" + additionalProperties: + $ref: "#/components/schemas/Brackets" + subparams: + type: "object" + additionalProperties: + type: "object" + properties: + definition: + type: "string" + metadata: + type: "object" + description: + type: "string" + id: + type: "integer" + format: "string" + source: + type: "string" + example: null + + Parameters: + type: "object" + additionalProperties: + type: "object" + properties: + description: + type: "string" + href: + type: "string" + + Variable: + type: "object" + properties: + defaultValue: + type: "string" + definitionPeriod: + type: string + enum: + - MONTH + - YEAR + - ETERNITY + description: + type: "string" + entity: + type: "string" + formulas: + type: "object" + additionalProperties: + $ref: "#/components/schemas/Formula" + id: + type: "string" + reference: + type: "array" + items: + type: "string" + source: + type: "string" + valueType: + type: "string" + enum: + - Int + - Float + - Boolean + - Date + - String + example: null + + Variables: + type: "object" + additionalProperties: + type: "object" + properties: + description: + type: "string" + href: + type: "string" + + Formula: + type: "object" + properties: + content: + type: "string" + source: + type: "string" + + Brackets: + type: "object" + additionalProperties: + type: "number" + format: "float" + + Values: + description: All keys are ISO dates. Values can be numbers, booleans, or arrays of a single type (number, boolean or string). + type: "object" + additionalProperties: + $ref: "#/components/schemas/Value" + # 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 + # pattern: "^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$" # all keys are ISO dates + + Value: + oneOf: + - type: "boolean" + - type: "number" + format: "float" + - type: "array" + items: + oneOf: + - type: "string" + - type: "number" + + Entities: + type: "object" + properties: + description: + type: "string" + documentation: + type: "string" + plural: + type: "string" + roles: + type: "object" + additionalProperties: + $ref: "#/components/schemas/Roles" + Roles: + type: "object" + properties: + description: + type: "string" + max: + type: "integer" + plural: + type: "string" + SituationInput: null + SituationOutput: null + + Trace: + type: object + properties: + requestedCalculations: + type: array + items: + type: string + entitiesDescription: + type: object + properties: null # Will be dynamically added by the Web API + trace: + type: object + additionalProperties: + type: object + properties: + value: + type: array + items: {} + dependencies: + type: array + items: + type: string + parameters: + type: object + additionalProperties: + type: object + + example: null + + headers: + Country-Package: + description: "The name of the country package currently loaded in this API server" + schema: + type: "string" + + Country-Package-Version: + description: "The version of the country package currently loaded in this API server" + schema: + type: "string" + pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" # adapted from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string + paths: /calculate: post: @@ -47,27 +232,33 @@ paths: content: application/json: schema: - $ref: "#/definitions/SituationInput" + $ref: "#/components/schemas/SituationInput" responses: 200: description: "The calculation result is sent back in the response body" content: application/json: schema: - $ref: "#/definitions/SituationOutput" + $ref: "#/components/schemas/SituationOutput" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" 404: 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" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" 400: description: "The request is invalid. Details about the error are sent back in the response body" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" /parameters: get: @@ -81,10 +272,12 @@ paths: content: application/json: schema: - $ref: "#/definitions/Parameters" + $ref: "#/components/schemas/Parameters" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" /parameter/{parameterID}: get: @@ -105,15 +298,19 @@ paths: content: application/json: schema: - $ref: "#/definitions/Parameter" + $ref: "#/components/schemas/Parameter" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" 404: description: "The requested parameter does not exist" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" /variables: get: @@ -127,10 +324,12 @@ paths: content: application/json: schema: - $ref: "#/definitions/Variables" + $ref: "#/components/schemas/Variables" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" /variable/{variableID}: get: @@ -151,15 +350,19 @@ paths: content: application/json: schema: - $ref: "#/definitions/Variable" + $ref: "#/components/schemas/Variable" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" 404: description: "The requested variable does not exist" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" /entities: get: @@ -173,10 +376,12 @@ paths: content: application/json: schema: - $ref: "#/definitions/Entities" + $ref: "#/components/schemas/Entities" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" /trace: post: @@ -190,27 +395,33 @@ paths: content: application/json: schema: - $ref: "#/definitions/SituationInput" + $ref: "#/components/schemas/SituationInput" responses: 200: description: "The calculation details are sent back in the response body" content: application/json: schema: - $ref: "#/definitions/Trace" + $ref: "#/components/schemas/Trace" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" 404: 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" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" 400: description: "The request is invalid. Details about the error are sent back in the response body" headers: - schema: - $ref: "#/components/headers" + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" /spec: get: @@ -222,189 +433,9 @@ paths: 200: description: The API documentation is sent back in the response body headers: - schema: - $ref: "#/components/headers" - -definitions: - Parameter: - type: "object" - properties: - values: - $ref: "#/definitions/Values" - brackets: - type: "object" - additionalProperties: - $ref: "#/definitions/Brackets" - subparams: - type: "object" - additionalProperties: - type: "object" - properties: - definition: - type: "string" - metadata: - type: "object" - description: - type: "string" - id: - type: "integer" - format: "string" - source: - type: "string" - example: null - - Parameters: - type: "object" - additionalProperties: - type: "object" - properties: - description: - type: "string" - href: - type: "string" - - Variable: - type: "object" - properties: - defaultValue: - type: "string" - definitionPeriod: - type: string - enum: - - MONTH - - YEAR - - ETERNITY - description: - type: "string" - entity: - type: "string" - formulas: - type: "object" - additionalProperties: - $ref: "#/definitions/Formula" - id: - type: "string" - reference: - type: "array" - items: - type: "string" - source: - type: "string" - valueType: - type: "string" - enum: - - Int - - Float - - Boolean - - Date - - String - example: null - - Variables: - type: "object" - additionalProperties: - type: "object" - properties: - description: - type: "string" - href: - type: "string" - - Formula: - type: "object" - properties: - content: - type: "string" - source: - type: "string" - - Brackets: - type: "object" - additionalProperties: - type: "number" - format: "float" - - Values: - description: All keys are ISO dates. Values can be numbers, booleans, or arrays of a single type (number, boolean or string). - type: "object" - additionalProperties: - $ref: "#/definitions/Value" -# 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 -# pattern: "^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$" # all keys are ISO dates - - Value: - oneOf: - - type: "boolean" - - type: "number" - format: "float" - - type: "array" - items: - type: - oneOf: - - "string" - - "number" - - Entities: - type: "object" - properties: - description: - type: "string" - documentation: - type: "string" - plural: - type: "string" - roles: - type: "object" - additionalProperties: - $ref: "#/definitions/Roles" - Roles: - type: "object" - properties: - description: - type: "string" - max: - type: "integer" - plural: - type: "string" - SituationInput: null - SituationOutput: null + Country-Package: + $ref: "#/components/headers/Country-Package" + Country-Package-Version: + $ref: "#/components/headers/Country-Package-Version" - Trace: - type: object - properties: - requestedCalculations: - type: array - items: - type: string - entitiesDescription: - type: object - properties: null # Will be dynamically added by the Web API - trace: - type: object - additionalProperties: - type: object - properties: - value: - type: array - items: - type: any - dependencies: - type: array - items: - type: string - parameters: - type: object - additionalProperties: - type: object - - example: null -components: - headers: - Country-Package: - description: "The name of the country package currently loaded in this API server" - type: "string" - Country-Package-Version: - description: "The version of the country package currently loaded in this API server" - type: "string" - pattern: "^(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)\\.(0|[1-9][0-9]*)(?:-((?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*)(?:\\.(?:0|[1-9][0-9]*|[0-9]*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\\+([0-9a-zA-Z-]+(?:\\.[0-9a-zA-Z-]+)*))?$" # adapted from https://semver.org/#is-there-a-suggested-regular-expression-regex-to-check-a-semver-string diff --git a/tests/web_api/test_spec.py b/tests/web_api/test_spec.py index a5139ee7b9..18dd2579d7 100644 --- a/tests/web_api/test_spec.py +++ b/tests/web_api/test_spec.py @@ -49,8 +49,8 @@ def test_situation_definition(body): for situation in situation_input, situation_output: assert 'households' in dpath.util.get(situation, '/properties') assert 'persons' in dpath.util.get(situation, '/properties') - assert "#/definitions/Household" == dpath.util.get(situation, '/properties/households/additionalProperties/$ref') - assert "#/definitions/Person" == dpath.util.get(situation, '/properties/persons/additionalProperties/$ref') + assert "#/components/schemas/Household" == dpath.util.get(situation, '/properties/households/additionalProperties/$ref') + assert "#/components/schemas/Person" == dpath.util.get(situation, '/properties/persons/additionalProperties/$ref') def test_host(body): From 5d1fe170389135873d9ed017ac5a4c63366f3c57 Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Sun, 16 Oct 2022 04:21:59 +0200 Subject: [PATCH 11/17] Update OAS 2 syntax in tests --- openfisca_web_api/loader/spec.py | 24 ++++++++++++------------ tests/web_api/test_spec.py | 14 +++++++------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/openfisca_web_api/loader/spec.py b/openfisca_web_api/loader/spec.py index 0fbb4ca90c..d36fd53aa6 100644 --- a/openfisca_web_api/loader/spec.py +++ b/openfisca_web_api/loader/spec.py @@ -25,12 +25,12 @@ def build_openAPI_specification(api_data): for entity in tax_benefit_system.entities: name = entity.key.title() - spec['definitions'][name] = get_entity_json_schema(entity, tax_benefit_system) + spec['components']['schemas'][name] = get_entity_json_schema(entity, tax_benefit_system) situation_schema = get_situation_json_schema(tax_benefit_system) - dpath.util.new(spec, 'definitions/SituationInput', situation_schema) - dpath.util.new(spec, 'definitions/SituationOutput', situation_schema.copy()) - dpath.util.new(spec, 'definitions/Trace/properties/entitiesDescription/properties', { + dpath.util.new(spec, 'components/schemas/SituationInput', situation_schema) + dpath.util.new(spec, 'components/schemas/SituationOutput', situation_schema.copy()) + dpath.util.new(spec, 'components/schemas/Trace/properties/entitiesDescription/properties', { entity.plural: {'type': 'array', 'items': {"type": "string"}} for entity in tax_benefit_system.entities }) @@ -43,24 +43,24 @@ def build_openAPI_specification(api_data): parameter_example = api_data['parameters'][parameter_path] else: parameter_example = next(iter(api_data['parameters'].values())) - dpath.util.new(spec, 'definitions/Parameter/example', parameter_example) + dpath.util.new(spec, 'components/schemas/Parameter/example', parameter_example) if tax_benefit_system.open_api_config.get('variable_example'): variable_example = api_data['variables'][tax_benefit_system.open_api_config['variable_example']] else: variable_example = next(iter(api_data['variables'].values())) - dpath.util.new(spec, 'definitions/Variable/example', variable_example) + dpath.util.new(spec, 'components/schemas/Variable/example', variable_example) if tax_benefit_system.open_api_config.get('simulation_example'): simulation_example = tax_benefit_system.open_api_config['simulation_example'] - dpath.util.new(spec, 'definitions/SituationInput/example', simulation_example) - dpath.util.new(spec, 'definitions/SituationOutput/example', handlers.calculate(tax_benefit_system, deepcopy(simulation_example))) # calculate has side-effects - dpath.util.new(spec, 'definitions/Trace/example', handlers.trace(tax_benefit_system, simulation_example)) + dpath.util.new(spec, 'components/schemas/SituationInput/example', simulation_example) + dpath.util.new(spec, 'components/schemas/SituationOutput/example', handlers.calculate(tax_benefit_system, deepcopy(simulation_example))) # calculate has side-effects + dpath.util.new(spec, 'components/schemas/Trace/example', handlers.trace(tax_benefit_system, simulation_example)) else: message = "No simulation example has been defined for this tax and benefit system. If you are the maintainer of {}, you can define an example by following this documentation: https://openfisca.org/doc/openfisca-web-api/config-openapi.html".format(country_package_name) - dpath.util.new(spec, 'definitions/SituationInput/example', message) - dpath.util.new(spec, 'definitions/SituationOutput/example', message) - dpath.util.new(spec, 'definitions/Trace/example', message) + dpath.util.new(spec, 'components/schemas/SituationInput/example', message) + dpath.util.new(spec, 'components/schemas/SituationOutput/example', message) + dpath.util.new(spec, 'components/schemas/Trace/example', message) return spec diff --git a/tests/web_api/test_spec.py b/tests/web_api/test_spec.py index 18dd2579d7..0bf5682fc8 100644 --- a/tests/web_api/test_spec.py +++ b/tests/web_api/test_spec.py @@ -36,16 +36,16 @@ def test_paths(body): def test_entity_definition(body): - assert 'parents' in dpath.util.get(body, 'definitions/Household/properties') - assert 'children' in dpath.util.get(body, 'definitions/Household/properties') - assert 'salary' in dpath.util.get(body, 'definitions/Person/properties') - assert 'rent' in dpath.util.get(body, 'definitions/Household/properties') - assert 'number' == dpath.util.get(body, 'definitions/Person/properties/salary/additionalProperties/type') + assert 'parents' in dpath.util.get(body, 'components/schemas/Household/properties') + assert 'children' in dpath.util.get(body, 'components/schemas/Household/properties') + assert 'salary' in dpath.util.get(body, 'components/schemas/Person/properties') + assert 'rent' in dpath.util.get(body, 'components/schemas/Household/properties') + assert 'number' == dpath.util.get(body, 'components/schemas/Person/properties/salary/additionalProperties/type') def test_situation_definition(body): - situation_input = body['definitions']['SituationInput'] - situation_output = body['definitions']['SituationOutput'] + situation_input = body['components']['schemas']['SituationInput'] + situation_output = body['components']['schemas']['SituationOutput'] for situation in situation_input, situation_output: assert 'households' in dpath.util.get(situation, '/properties') assert 'persons' in dpath.util.get(situation, '/properties') From a487d0515b8a1b66fa1f7b3177a821dce81cccb5 Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Thu, 3 Nov 2022 23:49:47 +0100 Subject: [PATCH 12/17] Cleanup --- openfisca_web_api/openAPI.yml | 59 +++++++++++++++++------------------ tests/web_api/test_spec.py | 13 +++----- 2 files changed, 34 insertions(+), 38 deletions(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index 92fb52e162..b3e45367e6 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -79,11 +79,11 @@ components: defaultValue: type: "string" definitionPeriod: - type: string + type: "string" enum: - - MONTH - - YEAR - - ETERNITY + - "MONTH" + - "YEAR" + - "ETERNITY" description: type: "string" entity: @@ -103,11 +103,11 @@ components: valueType: type: "string" enum: - - Int - - Float - - Boolean - - Date - - String + - "Int" + - "Float" + - "Boolean" + - "Date" + - "String" example: null Variables: @@ -135,7 +135,7 @@ components: format: "float" Values: - description: All keys are ISO dates. Values can be numbers, booleans, or arrays of a single type (number, boolean or string). + description: "All keys are ISO dates. Values can be numbers, booleans, or arrays of a single type (number, boolean or string)." type: "object" additionalProperties: $ref: "#/components/schemas/Value" @@ -175,36 +175,37 @@ components: type: "integer" plural: type: "string" + SituationInput: null + SituationOutput: null Trace: - type: object + type: "object" properties: requestedCalculations: - type: array + type: "array" items: - type: string + type: "string" entitiesDescription: - type: object - properties: null # Will be dynamically added by the Web API + type: "object" + additionalProperties: false # Will be dynamically added by the Web API trace: - type: object + type: "object" additionalProperties: - type: object + type: "object" properties: value: - type: array + type: "array" items: {} dependencies: - type: array + type: "array" items: - type: string + type: "string" parameters: - type: object + type: "object" additionalProperties: - type: object - + type: "object" example: null headers: @@ -387,7 +388,7 @@ paths: post: summary: "Explore a simulation's steps in details." tags: - - Calculations + - "Calculations" operationId: "trace" requestBody: description: "Describe the situation (persons and entities). Add the variable you wish to calculate in the proper entity, with null as the value." @@ -425,17 +426,15 @@ paths: /spec: get: - summary: Provide the API documentation in an OpenAPI format + summary: "Provide the API documentation in an OpenAPI format" tags: - - Documentation - operationId: spec + - "Documentation" + operationId: "spec" responses: 200: - description: The API documentation is sent back in the response body + description: "The API documentation is sent back in the response body" headers: Country-Package: $ref: "#/components/headers/Country-Package" Country-Package-Version: $ref: "#/components/headers/Country-Package-Version" - - diff --git a/tests/web_api/test_spec.py b/tests/web_api/test_spec.py index 0bf5682fc8..34dc1a559b 100644 --- a/tests/web_api/test_spec.py +++ b/tests/web_api/test_spec.py @@ -1,9 +1,9 @@ import dpath.util import json -import pytest from http import client -from openapi_spec_validator import validate_v3_spec +from openapi_spec_validator import openapi_v3_spec_validator +import pytest def assert_items_equal(x, y): @@ -53,9 +53,6 @@ def test_situation_definition(body): assert "#/components/schemas/Person" == dpath.util.get(situation, '/properties/persons/additionalProperties/$ref') -def test_host(body): - assert 'http' not in body['host'] - - -def test_respects_spec(): - validate_v3_spec(body) +def test_respects_spec(body): + for error in openapi_v3_spec_validator.iter_errors(body): + assert not error.path From 0b1f26a9fd8bf67d8cbab9d947348c6431801662 Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Thu, 17 Nov 2022 21:28:36 +0000 Subject: [PATCH 13/17] Apply suggestions from code review Co-authored-by: Matti Schneider --- CHANGELOG.md | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 38bed40483..7e943f66a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,17 @@ # Changelog +# 38.0.0 [#989](https://github.com/openfisca/openfisca-core/pull/989) + +#### New Features + +- Upgrade Web API specification to OpenAPI v3. +- Continuously validate OpenAPI specification. + +#### Breaking changes + +- Drop support for OpenAPI specification v2 and prior. + - Users relying on OpenAPI v2 can use [Swagger Converter](https://converter.swagger.io/api/convert?url=OAS2_YAML_OR_JSON_URL) to migrate ([example](https://web.archive.org/web/20221103230822/https://converter.swagger.io/api/convert?url=https://api.demo.openfisca.org/latest/spec)). + ### 37.0.2 [#1170](https://github.com/openfisca/openfisca-core/pull/1170) #### Technical changes From 047c79d0dd9056957d43db2ed5db02afff978ad6 Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Fri, 18 Nov 2022 00:15:48 +0100 Subject: [PATCH 14/17] Fix host/schemes --- openfisca_web_api/app.py | 9 ++++++--- tests/web_api/test_spec.py | 3 +-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/openfisca_web_api/app.py b/openfisca_web_api/app.py index e2244e9ba2..2117fdb631 100644 --- a/openfisca_web_api/app.py +++ b/openfisca_web_api/app.py @@ -118,10 +118,13 @@ def get_entities(): @app.route('/spec') def get_spec(): + scheme = request.environ["wsgi.url_scheme"] + host = request.host + url = f"{scheme}://{host}" + return jsonify({ - **data['openAPI_spec'], - **{'host': request.host}, - **{'schemes': [request.environ['wsgi.url_scheme']]} + **data["openAPI_spec"], + **{"servers": [{"url": url}]}, }) def handle_invalid_json(error): diff --git a/tests/web_api/test_spec.py b/tests/web_api/test_spec.py index 34dc1a559b..4c34532b73 100644 --- a/tests/web_api/test_spec.py +++ b/tests/web_api/test_spec.py @@ -54,5 +54,4 @@ def test_situation_definition(body): def test_respects_spec(body): - for error in openapi_v3_spec_validator.iter_errors(body): - assert not error.path + assert not [error for error in openapi_v3_spec_validator.iter_errors(body)] From 8fbae03b8d3e21e34fbac8b6a09c1030d3981010 Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Fri, 18 Nov 2022 00:17:13 +0100 Subject: [PATCH 15/17] Fix duplicated id --- openfisca_web_api/openAPI.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index b3e45367e6..364df633fb 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -370,7 +370,7 @@ paths: tags: - "Entities" summary: "List all available Entities" - operationId: "getVariables" + operationId: "getEntities" responses: 200: description: "The list of the entities as well as their information is sent back in the response body" From 8be2ec4e7b598c70111a30458ebe6d8e40d96abc Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Fri, 18 Nov 2022 00:20:32 +0100 Subject: [PATCH 16/17] Remove empty components --- openfisca_web_api/openAPI.yml | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/openfisca_web_api/openAPI.yml b/openfisca_web_api/openAPI.yml index 364df633fb..5eb1d8cf5c 100644 --- a/openfisca_web_api/openAPI.yml +++ b/openfisca_web_api/openAPI.yml @@ -1,4 +1,4 @@ -openapi: "3.0.0" +openapi: "3.1.0" info: title: "{COUNTRY_PACKAGE_NAME} Web API" @@ -61,7 +61,6 @@ components: format: "string" source: type: "string" - example: null Parameters: type: "object" @@ -108,7 +107,6 @@ components: - "Boolean" - "Date" - "String" - example: null Variables: type: "object" @@ -139,8 +137,8 @@ components: type: "object" additionalProperties: $ref: "#/components/schemas/Value" - # 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 - # pattern: "^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$" # all keys are ISO dates + 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 + pattern: "^[12][0-9]{3}-[01][0-9]-[0-3][0-9]$" # all keys are ISO dates Value: oneOf: @@ -166,6 +164,7 @@ components: type: "object" additionalProperties: $ref: "#/components/schemas/Roles" + Roles: type: "object" properties: @@ -176,10 +175,6 @@ components: plural: type: "string" - SituationInput: null - - SituationOutput: null - Trace: type: "object" properties: @@ -206,7 +201,6 @@ components: type: "object" additionalProperties: type: "object" - example: null headers: Country-Package: @@ -225,7 +219,7 @@ paths: post: summary: "Run a simulation" tags: - - Calculations + - "Calculations" operationId: "calculate" requestBody: 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" From be3dee5236d9a3f1c9b758dbf2d2223b66ba4c5e Mon Sep 17 00:00:00 2001 From: Mauko Quiroga Date: Fri, 4 Nov 2022 00:12:29 +0100 Subject: [PATCH 17/17] Bump version --- CHANGELOG.md | 2 +- setup.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7e943f66a6..601cdab211 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,7 @@ #### New Features -- Upgrade Web API specification to OpenAPI v3. +- Upgrade OpenAPI specification of the API to v3 from Swagger v2. - Continuously validate OpenAPI specification. #### Breaking changes diff --git a/setup.py b/setup.py index a8682f9fe6..2543121ac8 100644 --- a/setup.py +++ b/setup.py @@ -63,7 +63,7 @@ setup( name = 'OpenFisca-Core', - version = '37.0.2', + version = '38.0.0', author = 'OpenFisca Team', author_email = 'contact@openfisca.org', classifiers = [