swagger2.0 & process command demo & pdf handler
Showing
6 changed files
with
152 additions
and
158 deletions
| 1 | import time | ||
| 2 | import signal | ||
| 3 | |||
| 4 | from django.core.management import BaseCommand | ||
| 5 | |||
| 6 | |||
| 7 | class Command(BaseCommand): | ||
| 8 | |||
| 9 | def __init__(self): | ||
| 10 | super().__init__() | ||
| 11 | self.switch = True | ||
| 12 | signal.signal(signal.SIGTERM, self.signal_handler) | ||
| 13 | |||
| 14 | def signal_handler(self, sig, frame): | ||
| 15 | self.switch = False | ||
| 16 | print('get sig: {0}'.format(sig)) | ||
| 17 | |||
| 18 | def handle(self, *args, **kwargs): | ||
| 19 | while self.switch: | ||
| 20 | print('process start') | ||
| 21 | time.sleep(5) | ||
| 22 | print('process success') | ||
| 23 | print('process stop') |
| ... | @@ -65,78 +65,20 @@ class DocView(GenericView): | ... | @@ -65,78 +65,20 @@ class DocView(GenericView): |
| 65 | return response.ok() | 65 | return response.ok() |
| 66 | 66 | ||
| 67 | post.openapi_doc = ''' | 67 | post.openapi_doc = ''' |
| 68 | tags: [doc] | ||
| 68 | summary: POS系统上传文件信息 | 69 | summary: POS系统上传文件信息 |
| 69 | tags: [POS] | 70 | consumes: [application/json] |
| 70 | requestBody: | 71 | produces: [application/json] |
| 72 | parameters: | ||
| 73 | - in: body | ||
| 74 | name: body | ||
| 71 | required: true | 75 | required: true |
| 72 | content: | ||
| 73 | application/json: | ||
| 74 | schema: | 76 | schema: |
| 75 | type: object | 77 | $ref: "#/definitions/Doc" |
| 76 | properties: | ||
| 77 | applicationData: | ||
| 78 | description: 申请信息 | ||
| 79 | type: object | ||
| 80 | properties: | ||
| 81 | applicationId: | ||
| 82 | description: 申请id | ||
| 83 | type: string | ||
| 84 | example: CH-B0011010101 | ||
| 85 | applicantData: | ||
| 86 | description: 申请人信息 | ||
| 87 | type: object | ||
| 88 | properties: | ||
| 89 | mainApplicantName: | ||
| 90 | description: 主申请人 | ||
| 91 | type: string | ||
| 92 | example: 王明阳 | ||
| 93 | coApplicantName: | ||
| 94 | description: 共同申请人 | ||
| 95 | type: string | ||
| 96 | example: 王明月 | ||
| 97 | guarantor1Name: | ||
| 98 | description: 担保人1 | ||
| 99 | type: string | ||
| 100 | example: 王明日 | ||
| 101 | guarantor2Name: | ||
| 102 | description: 担保人2 | ||
| 103 | type: string | ||
| 104 | example: 王明雨 | ||
| 105 | document: | ||
| 106 | description: 文件信息 | ||
| 107 | type: object | ||
| 108 | properties: | ||
| 109 | documentName: | ||
| 110 | description: 文件名 | ||
| 111 | type: string | ||
| 112 | example: CH-B0011010101王明阳申请表 | ||
| 113 | documentScheme: | ||
| 114 | description: 文件格式? | ||
| 115 | type: string | ||
| 116 | example: CO00001 | ||
| 117 | businessType: | ||
| 118 | description: 业务类型 | ||
| 119 | type: string | ||
| 120 | example: HIL | ||
| 121 | uploadFinishTime: | ||
| 122 | description: 上传完成时间 | ||
| 123 | type: string | ||
| 124 | example: '2020-09-01 12:21:11' | ||
| 125 | dataSource: | ||
| 126 | description: 数据源 | ||
| 127 | type: string | ||
| 128 | example: POS | ||
| 129 | metadataVersionId: | ||
| 130 | description: 元数据版本ID | ||
| 131 | type: string | ||
| 132 | example: '8410480' | ||
| 133 | 78 | ||
| 134 | responses: | 79 | responses: |
| 135 | 200: | 80 | 200: |
| 136 | description: ok | 81 | description: ok |
| 137 | content: | ||
| 138 | application/json: | ||
| 139 | schema: | 82 | schema: |
| 140 | type: object | 83 | $ref: '#/definitions/ApiResponse' |
| 141 | $ref: '#/components/schemas/ApiResponse' | ||
| 142 | ''' | 84 | ''' | ... | ... |
| 1 | |||
| 2 | base_part = ''' | 1 | base_part = ''' |
| 3 | openapi: 3.0.0 | 2 | swagger: "2.0" |
| 4 | info: | 3 | info: |
| 5 | title: 接口文档 | 4 | title: 接口文档 |
| 6 | description: 宝马ocr/biz_logic接口文档 | 5 | description: 宝马ocr/biz_logic接口文档 |
| 7 | version: 1.0.0 | 6 | version: 1.0.0 |
| 8 | servers: | 7 | host: "staging-bmw-ocr.situdata.com" |
| 9 | - url: 'http://127.0.0.1:8000' | 8 | basePath: "/" |
| 10 | description: Development server | ||
| 11 | - url: 'http://staging-bmw-ocr.situdata.com' | ||
| 12 | description: sit | ||
| 13 | - url: 'http://127.0.0.1:8000' | ||
| 14 | description: uat | ||
| 15 | - url: 'http://127.0.0.1:8000' | ||
| 16 | description: prd | ||
| 17 | tags: | 9 | tags: |
| 18 | - name: POS | 10 | - name: doc |
| 19 | description: POS系统交互 | 11 | description: 文件 |
| 20 | 12 | schemes: | |
| 21 | security: | 13 | - "http" |
| 22 | - bearerAuth: [] | ||
| 23 | ''' | 14 | ''' |
| 24 | # scheme: bearer | ||
| 25 | security_schemes = ''' | ||
| 26 | bearerAuth: # arbitrary name for the security scheme | ||
| 27 | type: http | ||
| 28 | scheme: bearer | ||
| 29 | bearerFormat: JWT | ||
| 30 | description: > | ||
| 31 | token过期标志 | ||
| 32 | |||
| 33 | 1. Response Headers中的WWW-Authenticate中的status | ||
| 34 | |||
| 35 | status: -1 Invalid Authorization header | ||
| 36 | |||
| 37 | status: -2 Signature has expired beacause of expire_time | ||
| 38 | |||
| 39 | status: -3 Error decoding signature | ||
| 40 | |||
| 41 | status: -4 Signature has expired beacause new signature is generated | ||
| 42 | |||
| 43 | status: 0 valid Authorization | ||
| 44 | 15 | ||
| 45 | status: 1 new create, only login would set | 16 | # scheme: bearer |
| 46 | 17 | security_definitions = ''' | |
| 47 | 2. Response Body中的meta -> status == 1 | ||
| 48 | ''' | 18 | ''' |
| 49 | 19 | ||
| 50 | responses = ''' | 20 | responses = ''' |
| 51 | ErrorResponse: | 21 | ErrorResponse: |
| 52 | description: 调用异常, 具体情况请参考`HTTP`状态码和`code`字段 | 22 | description: 调用异常, 具体情况请参考`HTTP`状态码和`code`字段 |
| 53 | content: | ||
| 54 | application/json: | ||
| 55 | schema: | 23 | schema: |
| 56 | $ref: '#/components/schemas/ApiResponse' | 24 | $ref: '#/definitions/ApiResponse' |
| 57 | NoContent: | 25 | NoContent: |
| 58 | description: 后台接收请求,但是没有响应内容 | 26 | description: 后台接收请求,但是没有响应内容 |
| 59 | content: | ||
| 60 | application/json: | ||
| 61 | schema: | 27 | schema: |
| 62 | $ref: '#/components/schemas/ApiResponse' | 28 | $ref: '#/definitions/ApiResponse' |
| 63 | ''' | 29 | ''' |
| 64 | 30 | ||
| 65 | parameters = '' | 31 | parameters = '' |
| 66 | 32 | ||
| 67 | schemas = ''' | 33 | definitions = ''' |
| 34 | Doc: | ||
| 35 | type: object | ||
| 36 | required: [applicationData, applicantData, document] | ||
| 37 | properties: | ||
| 38 | applicationData: | ||
| 39 | description: 申请信息 | ||
| 40 | type: object | ||
| 41 | required: [applicationId] | ||
| 42 | properties: | ||
| 43 | applicationId: | ||
| 44 | description: 申请id | ||
| 45 | type: string | ||
| 46 | example: CH-B0011010101 | ||
| 47 | applicantData: | ||
| 48 | description: 申请人信息 | ||
| 49 | type: object | ||
| 50 | required: [mainApplicantName, coApplicantName, guarantor1Name, guarantor2Name] | ||
| 51 | properties: | ||
| 52 | mainApplicantName: | ||
| 53 | description: 主申请人 | ||
| 54 | type: string | ||
| 55 | example: 王明阳 | ||
| 56 | coApplicantName: | ||
| 57 | description: 共同申请人 | ||
| 58 | type: string | ||
| 59 | example: 王明月 | ||
| 60 | guarantor1Name: | ||
| 61 | description: 担保人1 | ||
| 62 | type: string | ||
| 63 | example: 王明日 | ||
| 64 | guarantor2Name: | ||
| 65 | description: 担保人2 | ||
| 66 | type: string | ||
| 67 | example: 王明雨 | ||
| 68 | document: | ||
| 69 | description: 文件信息 | ||
| 70 | type: object | ||
| 71 | required: [documentName, documentScheme, businessType, uploadFinishTime, dataSource, metadataVersionId] | ||
| 72 | properties: | ||
| 73 | documentName: | ||
| 74 | description: 文件名 | ||
| 75 | type: string | ||
| 76 | example: CH-B0011010101王明阳申请表 | ||
| 77 | documentScheme: | ||
| 78 | description: 文件格式? | ||
| 79 | type: string | ||
| 80 | example: CO00001 | ||
| 81 | businessType: | ||
| 82 | description: 业务类型 | ||
| 83 | type: string | ||
| 84 | example: HIL | ||
| 85 | uploadFinishTime: | ||
| 86 | description: 上传完成时间 | ||
| 87 | type: string | ||
| 88 | example: '2020-09-01 12:21:11' | ||
| 89 | dataSource: | ||
| 90 | description: 数据源 | ||
| 91 | type: string | ||
| 92 | example: POS | ||
| 93 | metadataVersionId: | ||
| 94 | description: 元数据版本ID | ||
| 95 | type: string | ||
| 96 | example: '8410480' | ||
| 97 | |||
| 68 | ApiResponse: | 98 | ApiResponse: |
| 69 | description: 响应对象,code字段用于表示响应的状态; data字段用于存放响应内容 | 99 | description: 响应对象,code字段用于表示响应的状态; data字段用于存放响应内容 |
| 70 | type: object | 100 | type: object |
| 101 | required: [code, msg] | ||
| 71 | properties: | 102 | properties: |
| 72 | code: | 103 | code: |
| 73 | type: integer | 104 | type: integer |
| 105 | format: uint8 | ||
| 74 | description: '0: success | 106 | description: '0: success |
| 75 | 1: need login | 107 | 1: need login |
| 76 | 2: invalid params | 108 | 2: invalid params |
| ... | @@ -79,33 +111,11 @@ ApiResponse: | ... | @@ -79,33 +111,11 @@ ApiResponse: |
| 79 | 5: async wait | 111 | 5: async wait |
| 80 | 6: no permission | 112 | 6: no permission |
| 81 | 7: illegal operation' | 113 | 7: illegal operation' |
| 114 | example: 0 | ||
| 115 | enum: [0, 1, 2, 3, 4, 5, 6, 7] | ||
| 82 | msg: | 116 | msg: |
| 83 | type: string | 117 | type: string |
| 84 | nullable: true | 118 | example: success |
| 85 | data: | 119 | data: |
| 86 | oneOf: | ||
| 87 | - type: object | ||
| 88 | nullable: true | ||
| 89 | - type: integer | ||
| 90 | nullable: true | ||
| 91 | - type: array | ||
| 92 | nullable: true | ||
| 93 | |||
| 94 | Pagination: | ||
| 95 | description: 分页参数 | ||
| 96 | type: object | 120 | type: object |
| 97 | properties: | ||
| 98 | current: | ||
| 99 | description: 当前页面 | ||
| 100 | type: integer | ||
| 101 | total: | ||
| 102 | description: 所有元素个数 | ||
| 103 | type: integer | ||
| 104 | page_size: | ||
| 105 | description: 页面大小 | ||
| 106 | type: integer | ||
| 107 | required: | ||
| 108 | - current | ||
| 109 | - total | ||
| 110 | - pageSize | ||
| 111 | ''' | 121 | ''' |
| ... | \ No newline at end of file | ... | \ No newline at end of file | ... | ... |
| ... | @@ -7,7 +7,7 @@ from django.urls.resolvers import get_resolver | ... | @@ -7,7 +7,7 @@ from django.urls.resolvers import get_resolver |
| 7 | import yaml | 7 | import yaml |
| 8 | from yaml.scanner import ScannerError | 8 | from yaml.scanner import ScannerError |
| 9 | 9 | ||
| 10 | from common.api_doc import (base_part, security_schemes, responses, schemas) | 10 | from common.api_doc import (base_part, security_definitions, responses, definitions) |
| 11 | 11 | ||
| 12 | _mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG | 12 | _mapping_tag = yaml.resolver.BaseResolver.DEFAULT_MAPPING_TAG |
| 13 | 13 | ||
| ... | @@ -73,18 +73,16 @@ class Command(BaseCommand): | ... | @@ -73,18 +73,16 @@ class Command(BaseCommand): |
| 73 | except ScannerError as err: | 73 | except ScannerError as err: |
| 74 | raise Exception( | 74 | raise Exception( |
| 75 | 'failed to load doc: """%s"""\nerr: %s' % (doc, err)) | 75 | 'failed to load doc: """%s"""\nerr: %s' % (doc, err)) |
| 76 | if doc.get('parameters'): | 76 | # if doc.get('parameters'): |
| 77 | for parameter in doc['parameters']: | 77 | # for parameter in doc['parameters']: |
| 78 | if parameter['name'] in path_parameters: | 78 | # if parameter['name'] in path_parameters: |
| 79 | doc['parameters'].pop(parameter) | 79 | # doc['parameters'].pop(parameter) |
| 80 | api_doc_dct[url_path][method] = doc | 80 | api_doc_dct[url_path][method] = doc |
| 81 | doc_dct = yaml.load(base_part) | 81 | doc_dct = yaml.load(base_part) |
| 82 | doc_dct['paths'] = api_doc_dct | 82 | doc_dct['paths'] = api_doc_dct |
| 83 | doc_dct['components'] = { | 83 | # doc_dct['securityDefinitions'] = yaml.load(security_definitions) |
| 84 | 'securitySchemes': yaml.load(security_schemes), | 84 | doc_dct['responses'] = yaml.load(responses) |
| 85 | 'responses': yaml.load(responses), | 85 | doc_dct['definitions'] = yaml.load(definitions) |
| 86 | 'schemas': yaml.load(schemas), | ||
| 87 | } | ||
| 88 | 86 | ||
| 89 | doc_str = yaml.dump( | 87 | doc_str = yaml.dump( |
| 90 | doc_dct, default_flow_style=False, allow_unicode=True) | 88 | doc_dct, default_flow_style=False, allow_unicode=True) | ... | ... |
src/common/tools/pdf_tools.py
0 → 100644
| 1 | import fitz | ||
| 2 | import os | ||
| 3 | |||
| 4 | |||
| 5 | class PdfHandler: | ||
| 6 | |||
| 7 | def __init__(self, pdf_path): | ||
| 8 | self.pdf_path = pdf_path | ||
| 9 | self.pdf_name = os.path.splitext(os.path.basename(pdf_path))[0] | ||
| 10 | |||
| 11 | def to_pix_img(self, save_dir_path, zoom_x, zoom_y): | ||
| 12 | trans = fitz.Matrix(zoom_x, zoom_y).preRotate(0) # zoom factor 2 in each dimension | ||
| 13 | with fitz.Document(self.pdf_path) as pdf: | ||
| 14 | # print(pdf.metadata) | ||
| 15 | for page in pdf: | ||
| 16 | pm = page.getPixmap(matrix=trans, alpha=False) # 获得每一页的流对象 | ||
| 17 | save_path = os.path.join(save_dir_path, '{0}_{1}.png'.format(self.pdf_name, page.number)) | ||
| 18 | pm.writePNG(save_path) | ||
| 19 | |||
| 20 | def to_svg_img(self, save_dir_path): | ||
| 21 | with fitz.Document(self.pdf_path) as pdf: | ||
| 22 | for page in pdf: | ||
| 23 | svg = page.getSVGimage(matrix=fitz.Identity) # UTF-8 string svg | ||
| 24 | save_path = os.path.join(save_dir_path, '{0}_{1}.svg'.format(self.pdf_name, page.number)) | ||
| 25 | with open(save_path, 'w') as f: | ||
| 26 | f.write(svg) | ||
| 27 | |||
| 28 | |||
| 29 | if __name__ == '__main__': | ||
| 30 | pdf_handler = PdfHandler('/Users/clay/Desktop/biz/pdf_test/test.pdf') | ||
| 31 | # pdf_handler.to_pix_img('/Users/clay/Desktop/biz/pdf_test/', 1.0, 1.0) | ||
| 32 | # pdf_handler.to_svg_img('/Users/clay/Desktop/biz/pdf_test/') |
-
Please register or sign in to post a comment