jsonschema.exceptions.ValidationError in code generated for python-flask
Alive24 opened this issue · 2 comments
Hi there, I tried to get an issue solved when I was using Swagger Editor and the python-flask code it generated, and I was referred to your project.
One of their people believed that
Okay, I think I see now - looks like the validator you're using is looking at the Swagger 2.0 JSON Schema document.
This seems to be a bug with the
swagger_spec_validator
project not being able to consume the Swagger schema correctly, not a problem with Swagger Editor not catching something.I'm going to close this for now, but if you file a bug with that project and they think Swagger Editor is doing something wrong, ping me here and I'd be happy to take another look.
Thanks! 😄
The link to the issue: swagger-api/swagger-editor#1912
Thank you!
I also attached the original post just FYI.
- OS: Win
- Browser: Chrome
- Version: latest
- Method of installation: docker
- Swagger-Editor version: 3.6.16
- Swagger/OpenAPI version:Swagger 2.0,
Content & configuration
Tried to start debugging after installing requirements. Reported error while editor didn't report any.
Swagger/OpenAPI definition:
swagger: "2.0" info: title: ProjectAgora description: >- Optional multiline or single-line description in [CommonMark](http://commonmark.org/help/) or HTML. version: 0.0.1 host: 127.0.0.1:5000 basePath: /v1 schemes: - https consumes: - application/json produces: - application/json securityDefinitions: APIKeyHeader: type: apiKey in: header name: api_key security: - APIKeyHeader: [] definitions: Error: description: 错误 properties: code: type: integer example: 401 message: type: string TokenStatus: description: Token信息 properties: token: type: string expireBy: type: string refreshed: type: boolean LoginRequest: description: 登陆请求 properties: username: type: string password: type: string Learner: description: 学习者 properties: id: description: ID type: integer name: description: 全名 type: string nickname: description: 昵称 type: string isMentor: description: 是否导师 type: boolean gender: description: 性别 type: string status: description: 目前状态,包括在读、在读(游学)、在读(试读)、毕业、导师等;考虑是否需要更换成integer type: string birthday: description: 生日 type: string mainPersonalIdType: description: 证件类型 type: string mainPersonalId: description: 证件号码 type: string age: description: 年龄(应当是计算字段) type: number ethnicity: description: 民族 type: string phoneNumber: description: 电话号码 type: string dateOfRegistration: description: 加入时间 type: string reasonOfRegistration: description: 加入原因 type: string previousStatus: description: 加入前状态 type: string dateOfLeave: description: 离开时间 type: string reasonOfLeave: description: 离开原因 type: string destinationOfLeave: description: 下阶段目的地 type: string notes: description: 备注 type: array items: type: string mentorship: description: 导师关系 (object类型 - 导师类型 - learnerID), 分有负责导师mentorResponsible,协同导师mentorSupportive, 家校沟通导师mentorCommunicative) type: object salaryCard: description: 工资卡号 type: string custodianInfo: description: 监护人信息 type: object properties: name: description: 姓名 type: string relationship: description: 关系 type: string emergentContact: description: 紧急联系人 type: array items: type: object properties: name: description: 紧急联系人姓名 type: string number: description: 紧急联系人电话 type: string weChatContact: description: 微信 type: string QQ: description: QQ type: string mailAddress: description: 收件地址(用以寄送书面文件) type: string email: description: 电子邮箱 type: string medicalNotes: description: 医疗记录 type: object properties: generalHealthStatus: description: 整体健康状况;0 - 很好(基本不生病,从不住院); 1 - 一般(偶尔生病住院); 2 - 欠佳(每个季度都曾生病住院) type: integer enum: [0, 1, 2] bloodType: description: 血型 type: string lastPhysicalExam: description: 最近一次体检时间(以年为单位) type: number previousDiagnosis: description: 既往疾病 type: array items: type: object properties: nameOfDiagnosis: description: 疾病名称 type: string hospitalOfDiagnosis: description: 诊断医院 type: string regularMedication: description: 长期用药 type: array items: type: object properties: nameOfMedication: description: 药品名 type: string instructionOfMedication: description: 用药医嘱 type: string foodAlergy: description: 食物过敏 type: object properties: lactoseIntolerance: description: 奶类过敏(乳糖不耐受) type: boolean eggAllergy: description: 禽蛋类过敏 type: boolean fishAllergy: description: 鱼类过敏 type: boolean shellAllergy: description: 甲壳类(虾蟹、贝类水产等) type: boolean peanutAllergy: description: 花生过敏 type: boolean soyBeanAllergy: description: 大豆过敏 type: boolean nutAllergy: description: 坚果类过敏 type: boolean wheatAllergy: description: 小麦过敏 type: boolean otherFoodAllergy: description: 其他食物过敏 type: array items: type: string medicationAllergy: description: 药物过敏 type: object properties: antibioticsAllergy: description: 抗生素过敏(青霉素、氨基苄青霉素、链霉素、卡那霉素) type: boolean sulfonamidesAllergy: description: 磺胺类药物过敏(磺胺噻唑、磺胺嘧啶、长效磺胺、复方新诺明等) type: boolean painkillerAllergy: description: 解热镇痛药(阿司匹林、去痛片) type: boolean anestheticAllergy: description: 麻醉用药(普鲁卡因) type: boolean vaccineAllergy: description: 疫苗类药物 type: boolean otherMedicationAllergy: description: 其他药物过敏 type: array items: type: string required: - name - isMentor Project: description: 项目 properties: id: description: 项目ID type: integer name: description: 项目名称 type: string createdTime: description: 创建时间 type: string createdBy: description: 创建人ID type: integer relatedCourseId: description: 关联的课程ID;自由项目的课程ID为0 type: integer content: description: 项目记录的条目 type: array items: type: object properties: timestamp: description: 条目时间戳 type: string instruction: description: 课程项目中教师为各条目定义的内容(暂定使用Markdown编码) type: string record: description: 学生记录(暂定使用Markdown编码) type: string required: - name - createdTime - createdBy - relatedCourseId Course: description: 课程 properties: id: description: 课程ID type: integer name: description: 课程名称 type: string createdTime: description: 创建时间 type: string createdBy: description: 创建人ID type: integer paths: /login: get: summary: 获取当前Token信息 tags: - Authentication responses: '200': description: 获取当前Token信息成功 schema: $ref: '#/definitions/TokenStatus' '401': description: 无法获取当前Token信息 headers: WWW_Authenticate: type: string post: summary: 尝试登陆 tags: - Authentication parameters: - in: body name: login required: true schema: $ref: '#/definitions/LoginRequest' responses: '200': description: 登陆成功 schema: $ref: '#/definitions/TokenStatus' '401': description: 登陆失败 schema: $ref: "#/responses/UnauthorizedError" /learner: head: summary: 返回所有Learner的关键信息 tags: - Learner responses: '200': description: 成功 schema: type: object properties: id: type: integer example: 1 name: type: string example: John Appleseed '401': description: 登陆失败 schema: $ref: "#/responses/UnauthorizedError" get: summary: 返回所有的Leaner详细信息 tags: - Learner description: 返回所有的Leaner详细信息 responses: '200': description: A JSON array of user names schema: $ref: '#/definitions/Learner' '401': $ref: "#/responses/UnauthorizedError" post: summary: 创建一个Learner tags: - Learner parameters: - in: body name: login required: true schema: $ref: '#/definitions/Learner' responses: '201': description: 创建成功 schema: description: 成功创建的Learner的ID type: object properties: id: type: integer '401': $ref: "#/responses/UnauthorizedError" '/learner/{learnerId}': get: summary: 返回一个Learner的详细信息 tags: - Learner parameters: - in: path name: learnerId required: true type: integer format: int64 minimum: 1 responses: '200': description: OK schema: $ref: '#/definitions/Learner' '401': $ref: "#/responses/UnauthorizedError" responses: UnauthorizedError: description: API key is missing or invalid headers: WWW_Authenticate: type: stringError information:
Traceback (most recent call last): File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\common.py", line 17, in wrapper return method(*args, **kwargs) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\validator20.py", line 125, in validate_json cls=Draft4Validator) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\ref_validators.py", line 34, in validate instance_cls(schema, *args, **kwargs).validate(instance) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\jsonschema\validators.py", line 130, in validate raise error jsonschema.exceptions.ValidationError: {'description': '登陆失败', 'schema': {'$ref': '#/responses/UnauthorizedError', 'x-scope': ['']}} is not valid under any of the given schemas Failed validating 'oneOf' in schema['properties']['paths']['patternProperties']['^/']['properties']['post']['properties']['responses']['patternProperties']['^([0-9]{3})$|^(default)$']: {'oneOf': [{'$ref': '#/definitions/response'}, {'$ref': '#/definitions/jsonReference'}]} On instance['paths']['/login']['post']['responses']['401']: {'description': '登陆失败', 'schema': {'$ref': '#/responses/UnauthorizedError', 'x-scope': ['']}} During handling of the above exception, another exception occurred: Traceback (most recent call last): File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\runpy.py", line 193, in _run_module_as_main "__main__", mod_spec) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\runpy.py", line 85, in _run_code exec(code, run_globals) File "C:\Users\xct24\Documents\Git-AgoraAcademy\ProjectAgora\server\swagger_server\__main__.py", line 16, in <module> main() File "C:\Users\xct24\Documents\Git-AgoraAcademy\ProjectAgora\server\swagger_server\__main__.py", line 11, in main app.add_api('swagger.yaml', arguments={'title': 'ProjectAgora'}) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\connexion\apps\flask_app.py", line 54, in add_api api = super(FlaskApp, self).add_api(specification, **kwargs) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\connexion\apps\abstract.py", line 159, in add_api options=api_options.as_dict()) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\connexion\apis\abstract.py", line 92, in __init__ validate_spec(spec) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\validator20.py", line 82, in validate_spec http_handlers=http_handlers) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\common.py", line 22, in wrapper sys.exc_info()[2]) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\six.py", line 692, in reraise raise value.with_traceback(tb) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\common.py", line 17, in wrapper return method(*args, **kwargs) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\validator20.py", line 125, in validate_json cls=Draft4Validator) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\swagger_spec_validator\ref_validators.py", line 34, in validate instance_cls(schema, *args, **kwargs).validate(instance) File "C:\ProgramData\Anaconda3\envs\ProjectAgora\lib\site-packages\jsonschema\validators.py", line 130, in validate raise error swagger_spec_validator.common.SwaggerValidationError: {'description': '登陆失败', 'schema': {'$ref': '#/responses/UnauthorizedError', 'x-scope': ['']}} is not valid under any of the given schemas Failed validating 'oneOf' in schema['properties']['paths']['patternProperties']['^/']['properties']['post']['properties']['responses']['patternProperties']['^([0-9]{3})$|^(default)$']: {'oneOf': [{'$ref': '#/definitions/response'}, {'$ref': '#/definitions/jsonReference'}]} On instance['paths']['/login']['post']['responses']['401']: {'description': '登陆失败', 'schema': {'$ref': '#/responses/UnauthorizedError', 'x-scope': ['']}}
I can't find clues of what went wrong as I did follow the docs step by step. Thank you very much!
Hey @xct24 I've just checked your specs and I did found 2 issues on them.
In [1]: from swagger_spec_validator.validator20 import validate_spec_url
In [2]: # NOTE: I'm on OSX so the path could look different
In [3]: validate_spec_url('file:///Users/maci/Desktop/specs.yaml')
...
SwaggerValidationError: ('("{\'description\': \'登陆失败\', \'schema\': {\'$ref\': \'#/responses/UnauthorizedError\', \'x-scope\': [\'file:///Users/maci/Desktop/specs.yaml\']}} is not valid under any of the given schemas\\n\\nFailed validating \'oneOf\' in schema[\'properties\'][\'paths\'][\'patternProperties\'][\'^/\'][\'properties\'][\'head\'][\'properties\'][\'responses\'][\'patternProperties\'][\'^([0-9]{3})$|^(default)$\']:\\n {\'oneOf\': [{\'$ref\': \'#/definitions/response\'},\\n {\'$ref\': \'#/definitions/jsonReference\'}]}\\n\\nOn instance[\'paths\'][\'/learner\'][\'head\'][\'responses\'][\'401\']:\\n {\'description\': \'登陆失败\',\\n \'schema\': {\'$ref\': \'#/responses/UnauthorizedError\',\\n \'x-scope\': [\'file:///Users/maci/Desktop/specs.yaml\']}}", <ValidationError: "{\'description\': \'登陆失败\', \'schema\': {\'$ref\': \'#/responses/UnauthorizedError\', \'x-scope\': [\'file:///Users/maci/Desktop/specs.yaml\']}} is not valid under any of the given schemas">)', SwaggerValidationError("{'description': '登陆失败', 'schema': {'$ref': '#/responses/UnauthorizedError', 'x-scope': ['file:///Users/maci/Desktop/specs.yaml']}} is not valid under any of the given schemas\n\nFailed validating 'oneOf' in schema['properties']['paths']['patternProperties']['^/']['properties']['head']['properties']['responses']['patternProperties']['^([0-9]{3})$|^(default)$']:\n {'oneOf': [{'$ref': '#/definitions/response'},\n {'$ref': '#/definitions/jsonReference'}]}\n\nOn instance['paths']['/learner']['head']['responses']['401']:\n {'description': '登陆失败',\n 'schema': {'$ref': '#/responses/UnauthorizedError',\n 'x-scope': ['file:///Users/maci/Desktop/specs.yaml']}}", <ValidationError: "{'description': '登陆失败', 'schema': {'$ref': '#/responses/UnauthorizedError', 'x-scope': ['file:///Users/maci/Desktop/specs.yaml']}} is not valid under any of the given schemas">))
In [4]: # The issue is not really expressive, so I did extract the inner validation error
In [5]: try:
...: validator20.validate_spec_url('file:///Users/maci/Desktop/specs.yaml')
...: except Exception as e:
...: print(e.args[1].args[1])
...:
{'description': '登陆失败', 'schema': {'$ref': '#/responses/UnauthorizedError', 'x-scope': ['file:///Users/maci/Desktop/specs.yaml']}} is not valid under any of the given schemas
Failed validating 'oneOf' in schema['properties']['paths']['patternProperties']['^/']['properties']['head']['properties']['responses']['patternProperties']['^([0-9]{3})$|^(default)$']:
{'oneOf': [{'$ref': '#/definitions/response'},
{'$ref': '#/definitions/jsonReference'}]}
On instance['paths']['/login']['post']['responses']['401']:
{'description': '登陆失败',
'schema': {'$ref': '#/responses/UnauthorizedError',
'x-scope': ['file:///Users/maci/Desktop/specs.yaml']}}
Checking the specs for instance['paths']['/login']['post']['responses']['401']
I see that it is defined as:
'401':
description: 登陆失败
schema:
$ref: "#/responses/UnauthorizedError"
but #/responses/UnauthorizedError
is a valid response object and not a valid schema object.
Checking other usage of the object in the specs I see something like
'401':
$ref: "#/responses/UnauthorizedError"
By fixing that occurrence and an other one (again reported with the same method above) the validation passes
In [7]: try:
...: validator20.validate_spec_url('file:///Users/maci/Desktop/fixed.yaml')
...: except Exception as e:
...: print(e.args[1].args[1])
...:
In [8]:
Spec diff
--- /Users/maci/Desktop/specs.yaml Thu Dec 13 17:59:57 2018
+++ /Users/maci/Desktop/fixed.yaml Thu Dec 13 18:00:11 2018
@@ -331,9 +331,7 @@
schema:
$ref: '#/definitions/TokenStatus'
'401':
- description: 登陆失败
- schema:
- $ref: "#/responses/UnauthorizedError"
+ $ref: "#/responses/UnauthorizedError"
/learner:
head:
summary: 返回所有Learner的关键信息
@@ -352,9 +350,7 @@
type: string
example: John Appleseed
'401':
- description: 登陆失败
- schema:
- $ref: "#/responses/UnauthorizedError"
+ $ref: "#/responses/UnauthorizedError"
get:
summary: 返回所有的Leaner详细信息
tags:
Thank you! Problem solved