From 646d05c25989e9f91daade966b520e1b12867a9b Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 13:08:25 +0000 Subject: [PATCH 01/18] Add some logging for failed parsing of docstrings. --- flask_swagger.py | 45 +++++++++++++++++++++++++-------------------- 1 file changed, 25 insertions(+), 20 deletions(-) diff --git a/flask_swagger.py b/flask_swagger.py index d594fdb..c6b73b8 100644 --- a/flask_swagger.py +++ b/flask_swagger.py @@ -8,12 +8,14 @@ - Added basic_path parameter """ import inspect +import logging import yaml import re import os from collections import defaultdict +logger = logging.getLogger(__name__) def _sanitize(comment): return comment.replace('\n', '
') if comment else comment @@ -47,27 +49,30 @@ def _doc_from_file(path): def _parse_docstring(obj, process_doc, from_file_keyword, base_path): - first_line, other_lines, swag = None, None, None - full_doc = inspect.getdoc(obj) - if full_doc: - if from_file_keyword is not None: - from_file = _find_from_file(full_doc, from_file_keyword, base_path) - if from_file: - full_doc_from_file = _doc_from_file(from_file) - if full_doc_from_file: - full_doc = full_doc_from_file - line_feed = full_doc.find('\n') - if line_feed != -1: - first_line = process_doc(full_doc[:line_feed]) - yaml_sep = full_doc[line_feed+1:].find('---') - if yaml_sep != -1: - other_lines = process_doc(full_doc[line_feed+1:line_feed+yaml_sep]) - swag = yaml.full_load(full_doc[line_feed+yaml_sep:]) + try: + first_line, other_lines, swag = None, None, None + full_doc = inspect.getdoc(obj) + if full_doc: + if from_file_keyword is not None: + from_file = _find_from_file(full_doc, from_file_keyword, base_path) + if from_file: + full_doc_from_file = _doc_from_file(from_file) + if full_doc_from_file: + full_doc = full_doc_from_file + line_feed = full_doc.find('\n') + if line_feed != -1: + first_line = process_doc(full_doc[:line_feed]) + yaml_sep = full_doc[line_feed+1:].find('---') + if yaml_sep != -1: + other_lines = process_doc(full_doc[line_feed+1:line_feed+yaml_sep]) + swag = yaml.full_load(full_doc[line_feed+yaml_sep:]) + else: + other_lines = process_doc(full_doc[line_feed+1:]) else: - other_lines = process_doc(full_doc[line_feed+1:]) - else: - first_line = full_doc - return first_line, other_lines, swag + first_line = full_doc + return first_line, other_lines, swag + except Exception as e: + logger.error("Failed to parse docstring for %s: %s", obj, e) def _extract_definitions(alist, level=None): From 36303db4bbc3eb3859880f0c256c5dbd44f478a4 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 13:56:33 +0000 Subject: [PATCH 02/18] Generate PlantUML diagrams in docs. --- flask_swagger.py | 11 ++++++--- plantuml_docs.py | 64 ++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 72 insertions(+), 3 deletions(-) create mode 100644 plantuml_docs.py diff --git a/flask_swagger.py b/flask_swagger.py index c6b73b8..e9fdf51 100644 --- a/flask_swagger.py +++ b/flask_swagger.py @@ -15,6 +15,8 @@ from collections import defaultdict +from plantuml_docs import generate_plantuml + logger = logging.getLogger(__name__) def _sanitize(comment): @@ -65,6 +67,7 @@ def _parse_docstring(obj, process_doc, from_file_keyword, base_path): yaml_sep = full_doc[line_feed+1:].find('---') if yaml_sep != -1: other_lines = process_doc(full_doc[line_feed+1:line_feed+yaml_sep]) + other_lines = generate_plantuml(other_lines) swag = yaml.full_load(full_doc[line_feed+yaml_sep:]) else: other_lines = process_doc(full_doc[line_feed+1:]) @@ -129,7 +132,8 @@ def _extract_array_defs(source): def swagger(app, prefix=None, process_doc=_sanitize, - from_file_keyword=None, template=None, base_path=""): + from_file_keyword=None, template=None, base_path="", + title="Cool product name", version="0.0.0", description=""): """ Call this from an @app.route method like this @app.route('/spec.json') @@ -151,8 +155,9 @@ def spec(): output = { "swagger": "2.0", "info": { - "version": "0.0.0", - "title": "Cool product name", + "version": version, + "title": title, + "description": generate_plantuml(description) } } paths = defaultdict(dict) diff --git a/plantuml_docs.py b/plantuml_docs.py new file mode 100644 index 0000000..010a481 --- /dev/null +++ b/plantuml_docs.py @@ -0,0 +1,64 @@ +import hashlib +import os +import re + +try: + import plantuml +except ImportError: + plantuml = None + +_PLANTUML_RE = re.compile("(@startuml.*?@enduml)") +FLASK_SWAGGER_PLANTUML_SERVER = 'FLASK_SWAGGER_PLANTUML_SERVER' +FLASK_SWAGGER_PLANTUML_FOLDER = 'FLASK_SWAGGER_PLANTUML_FOLDER' + +def generate_plantuml(docstring, app): + """ + Generate PlantUML diagrams from the given docstring. + + If the plantuml Python package is not installed, the docstring is returned + unaltered. Otherwise, it performs the following steps: + * Looks for any `@startuml...@enduml` pairs. + * When it finds one, extracts the diagram text and sends it to a PlantUML + server. The default is the public server, but this can be configured by + setting the `FLASK_SWAGGER_PLANTUML_SERVER` in the flask app config. + * The image returned from the server is placed into the application's static + files folder. The location of the static folder is determined from the + `app` object. The subfolder defaults to `uml` but can be configured by + setting the `FLASK_SWAGGER_PLANTUML_FOLDER` in the flask app config. + * The original diagram text is replaced with a markdown link to the generated + image. + """ + if not plantuml: + return docstring + + if FLASK_SWAGGER_PLANTUML_SERVER in app.config: + server = plantuml.PlantUML(url=app.config.get('FLASK_SWAGGER_PLANTUML_SERVER')) + else: + server = plantuml.PlantUML() + + subfolder = app.config.get(FLASK_SWAGGER_PLANTUML_FOLDER, 'uml') + folder = os.path.join(app.static_folder, subfolder) + + while True: + match = _PLANTUML_RE.search(docstring) + if not match: + break + uml = match.group(1) + # The same UML data will produce the same filename + filename = hashlib.sha256(uml.encode('utf-8')).decode('utf-8') + '.png' + output_file = os.path.join(folder, filename) + try: + image_data = server.processes(uml) + with open(output_file, 'wb') as file: + file.write(image_data) + docstring = match.sub(f"![{filename}][/static/{subfolder}/{filename}]") + except plantuml.PlantUMLConnectionError as e: + docstring = match.sub(f"Failed to connect to the PlantUML server: {e}") + except plantuml.PlantUMLHTTPError as e: + docstring = match.sub(f"HTTP error while connection to the PlantUML server: {e}") + except plantuml.PlantUMLError as e: + docstring = match.sub(f"PlantUML error: {e}") + + return docstring + + From 25e852849dedd6361c86b33118115b64bf16ecab Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 16:08:35 +0000 Subject: [PATCH 03/18] Make regex match multiline. --- plantuml_docs.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 010a481..78f3927 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -1,13 +1,16 @@ import hashlib +import logging import os import re +logger = logging.getLogger(__name__) + try: import plantuml except ImportError: plantuml = None -_PLANTUML_RE = re.compile("(@startuml.*?@enduml)") +_PLANTUML_RE = re.compile("(@startuml.*?@enduml)", re.MULTILINE) FLASK_SWAGGER_PLANTUML_SERVER = 'FLASK_SWAGGER_PLANTUML_SERVER' FLASK_SWAGGER_PLANTUML_FOLDER = 'FLASK_SWAGGER_PLANTUML_FOLDER' @@ -29,15 +32,20 @@ def generate_plantuml(docstring, app): image. """ if not plantuml: + logger.info("PlantUML not installed; not generating diagrams") return docstring - if FLASK_SWAGGER_PLANTUML_SERVER in app.config: - server = plantuml.PlantUML(url=app.config.get('FLASK_SWAGGER_PLANTUML_SERVER')) + url=app.config.get('FLASK_SWAGGER_PLANTUML_SERVER') + if url: + logger.info("User PlantUML server %s", url) + server = plantuml.PlantUML(url=url) else: + logger.info("Using default public PlantUML server") server = plantuml.PlantUML() subfolder = app.config.get(FLASK_SWAGGER_PLANTUML_FOLDER, 'uml') folder = os.path.join(app.static_folder, subfolder) + logger.info("Outputting diagrams to %s", folder) while True: match = _PLANTUML_RE.search(docstring) From 4022fced62160dc063b4a581e6ab0f13648f4251 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 16:34:26 +0000 Subject: [PATCH 04/18] Add to setup.py --- setup.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.py b/setup.py index cef6457..5865868 100644 --- a/setup.py +++ b/setup.py @@ -12,7 +12,7 @@ description='Extract swagger specs from your flask project', author='Atli Thorbjornsson', license='MIT', - py_modules=['flask_swagger', 'build_swagger_spec'], + py_modules=['flask_swagger', 'build_swagger_spec', 'plantuml_docs'], long_description=long_description, install_requires=['Flask>=0.10', 'PyYAML>=5.1'], classifiers=[ From e1c87c34498c17f3a21ba50721bb3446f87b8ca0 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 16:37:40 +0000 Subject: [PATCH 05/18] Testing fixes --- flask_swagger.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/flask_swagger.py b/flask_swagger.py index e9fdf51..671ab42 100644 --- a/flask_swagger.py +++ b/flask_swagger.py @@ -50,7 +50,7 @@ def _doc_from_file(path): return doc -def _parse_docstring(obj, process_doc, from_file_keyword, base_path): +def _parse_docstring(obj, process_doc, from_file_keyword, base_path, app): try: first_line, other_lines, swag = None, None, None full_doc = inspect.getdoc(obj) @@ -67,7 +67,7 @@ def _parse_docstring(obj, process_doc, from_file_keyword, base_path): yaml_sep = full_doc[line_feed+1:].find('---') if yaml_sep != -1: other_lines = process_doc(full_doc[line_feed+1:line_feed+yaml_sep]) - other_lines = generate_plantuml(other_lines) + other_lines = generate_plantuml(other_lines, app) swag = yaml.full_load(full_doc[line_feed+yaml_sep:]) else: other_lines = process_doc(full_doc[line_feed+1:]) @@ -157,7 +157,7 @@ def spec(): "info": { "version": version, "title": title, - "description": generate_plantuml(description) + "description": generate_plantuml(description, app) } } paths = defaultdict(dict) @@ -193,7 +193,8 @@ def spec(): operations = dict() for verb, method in methods.items(): summary, description, swag = _parse_docstring(method, process_doc, - from_file_keyword, base_path) + from_file_keyword, base_path, + app) if swag is not None: # we only add endpoints with swagger data in the docstrings defs = swag.get('definitions', []) defs = _extract_definitions(defs) From c35b5e82962cdc92e78275b6858dcde942ca1803 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 16:46:25 +0000 Subject: [PATCH 06/18] Fix default plantuml server --- plantuml_docs.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 78f3927..2b09a4d 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -35,13 +35,9 @@ def generate_plantuml(docstring, app): logger.info("PlantUML not installed; not generating diagrams") return docstring - url=app.config.get('FLASK_SWAGGER_PLANTUML_SERVER') - if url: - logger.info("User PlantUML server %s", url) - server = plantuml.PlantUML(url=url) - else: - logger.info("Using default public PlantUML server") - server = plantuml.PlantUML() + url=app.config.get('FLASK_SWAGGER_PLANTUML_SERVER', 'http://www.plantuml.com/plantuml/img/') + logger.info("User PlantUML server %s", url) + server = plantuml.PlantUML(url=url) subfolder = app.config.get(FLASK_SWAGGER_PLANTUML_FOLDER, 'uml') folder = os.path.join(app.static_folder, subfolder) From d9e96e381135b116742517766a97a033149b3e04 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 17:07:13 +0000 Subject: [PATCH 07/18] More testing fixes --- plantuml_docs.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 2b09a4d..0b01b68 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -10,7 +10,7 @@ except ImportError: plantuml = None -_PLANTUML_RE = re.compile("(@startuml.*?@enduml)", re.MULTILINE) +_PLANTUML_RE = re.compile("(@startuml.*?@enduml)", re.MULTILINE|re.DOTALL) FLASK_SWAGGER_PLANTUML_SERVER = 'FLASK_SWAGGER_PLANTUML_SERVER' FLASK_SWAGGER_PLANTUML_FOLDER = 'FLASK_SWAGGER_PLANTUML_FOLDER' @@ -49,7 +49,7 @@ def generate_plantuml(docstring, app): break uml = match.group(1) # The same UML data will produce the same filename - filename = hashlib.sha256(uml.encode('utf-8')).decode('utf-8') + '.png' + filename = hashlib.sha256(uml.encode('utf-8')).hexdigest() + '.png' output_file = os.path.join(folder, filename) try: image_data = server.processes(uml) From 75202c99cacae9c466b3eea5068783a51fe86299 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 17:11:08 +0000 Subject: [PATCH 08/18] Create output folder --- plantuml_docs.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plantuml_docs.py b/plantuml_docs.py index 0b01b68..5ee89e1 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -41,6 +41,8 @@ def generate_plantuml(docstring, app): subfolder = app.config.get(FLASK_SWAGGER_PLANTUML_FOLDER, 'uml') folder = os.path.join(app.static_folder, subfolder) + if not os.path.exists(): + os.mkdir(folder) logger.info("Outputting diagrams to %s", folder) while True: From ca00c2f841b367d6f1498fcbf22272de225fda27 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 17:13:08 +0000 Subject: [PATCH 09/18] Stupid defect. --- plantuml_docs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 5ee89e1..9d43b6e 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -41,7 +41,7 @@ def generate_plantuml(docstring, app): subfolder = app.config.get(FLASK_SWAGGER_PLANTUML_FOLDER, 'uml') folder = os.path.join(app.static_folder, subfolder) - if not os.path.exists(): + if not os.path.exists(folder): os.mkdir(folder) logger.info("Outputting diagrams to %s", folder) From c2290b77a5ac84ff28c2e18f99ea7d92a0e88654 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 17:25:54 +0000 Subject: [PATCH 10/18] Fix regex replace --- plantuml_docs.py | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 9d43b6e..e307d31 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -14,6 +14,9 @@ FLASK_SWAGGER_PLANTUML_SERVER = 'FLASK_SWAGGER_PLANTUML_SERVER' FLASK_SWAGGER_PLANTUML_FOLDER = 'FLASK_SWAGGER_PLANTUML_FOLDER' +def sub(string, match, replacement): + return string[:match.start()] + replacement + string[match.end():] + def generate_plantuml(docstring, app): """ Generate PlantUML diagrams from the given docstring. @@ -57,13 +60,13 @@ def generate_plantuml(docstring, app): image_data = server.processes(uml) with open(output_file, 'wb') as file: file.write(image_data) - docstring = match.sub(f"![{filename}][/static/{subfolder}/{filename}]") + docstring = sub(docstring, match, f"![{filename}][/static/{subfolder}/{filename}]") except plantuml.PlantUMLConnectionError as e: - docstring = match.sub(f"Failed to connect to the PlantUML server: {e}") + docstring = sub(docstring, match, f"Failed to connect to the PlantUML server: {e}") except plantuml.PlantUMLHTTPError as e: - docstring = match.sub(f"HTTP error while connection to the PlantUML server: {e}") + docstring = sub(docstring, match, f"HTTP error while connection to the PlantUML server: {e}") except plantuml.PlantUMLError as e: - docstring = match.sub(f"PlantUML error: {e}") + docstring = sub(docstring, match, f"PlantUML error: {e}") return docstring From 187e6cf9d0cfe0975721305defcbb446a6796189 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Wed, 17 Nov 2021 17:29:33 +0000 Subject: [PATCH 11/18] Output img tags instead of markdown --- plantuml_docs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index e307d31..84703c1 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -60,7 +60,7 @@ def generate_plantuml(docstring, app): image_data = server.processes(uml) with open(output_file, 'wb') as file: file.write(image_data) - docstring = sub(docstring, match, f"![{filename}][/static/{subfolder}/{filename}]") + docstring = sub(docstring, match, f'{filename}') except plantuml.PlantUMLConnectionError as e: docstring = sub(docstring, match, f"Failed to connect to the PlantUML server: {e}") except plantuml.PlantUMLHTTPError as e: From ac9facf59f0f8d31c511c6d5bd1f15085a647418 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Thu, 18 Nov 2021 08:23:56 +0000 Subject: [PATCH 12/18] Switch back to Markdown format. --- plantuml_docs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 84703c1..9dc5898 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -60,7 +60,7 @@ def generate_plantuml(docstring, app): image_data = server.processes(uml) with open(output_file, 'wb') as file: file.write(image_data) - docstring = sub(docstring, match, f'{filename}') + docstring = sub(docstring, match, f'![{filename}](/static/{subfolder}/{filename}])') except plantuml.PlantUMLConnectionError as e: docstring = sub(docstring, match, f"Failed to connect to the PlantUML server: {e}") except plantuml.PlantUMLHTTPError as e: From 6fe3cdbc4d9261dc039185db69df2770c8f61b9a Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Thu, 18 Nov 2021 08:25:50 +0000 Subject: [PATCH 13/18] Stray bracket. --- plantuml_docs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 9dc5898..9e4d72a 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -60,7 +60,7 @@ def generate_plantuml(docstring, app): image_data = server.processes(uml) with open(output_file, 'wb') as file: file.write(image_data) - docstring = sub(docstring, match, f'![{filename}](/static/{subfolder}/{filename}])') + docstring = sub(docstring, match, f'![{filename}](/static/{subfolder}/{filename})') except plantuml.PlantUMLConnectionError as e: docstring = sub(docstring, match, f"Failed to connect to the PlantUML server: {e}") except plantuml.PlantUMLHTTPError as e: From 5bbd6b7d6ad6f9ea0973ae92b3611a3f80281991 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Thu, 18 Nov 2021 09:40:28 +0000 Subject: [PATCH 14/18] Propagate exception --- flask_swagger.py | 1 + 1 file changed, 1 insertion(+) diff --git a/flask_swagger.py b/flask_swagger.py index c6b73b8..82432c0 100644 --- a/flask_swagger.py +++ b/flask_swagger.py @@ -73,6 +73,7 @@ def _parse_docstring(obj, process_doc, from_file_keyword, base_path): return first_line, other_lines, swag except Exception as e: logger.error("Failed to parse docstring for %s: %s", obj, e) + raise def _extract_definitions(alist, level=None): From 2b319170f3f2765472d164b3f65a0a3c89786e6f Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Thu, 18 Nov 2021 09:50:01 +0000 Subject: [PATCH 15/18] Actually use the constants we define, what? --- plantuml_docs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 9e4d72a..85a0e8c 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -38,7 +38,7 @@ def generate_plantuml(docstring, app): logger.info("PlantUML not installed; not generating diagrams") return docstring - url=app.config.get('FLASK_SWAGGER_PLANTUML_SERVER', 'http://www.plantuml.com/plantuml/img/') + url=app.config.get(FLASK_SWAGGER_PLANTUML_SERVER, 'http://www.plantuml.com/plantuml/img/') logger.info("User PlantUML server %s", url) server = plantuml.PlantUML(url=url) From 1ad9f7ce4fb80a52994ee39c9674d8780f1caa6d Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Thu, 18 Nov 2021 09:56:35 +0000 Subject: [PATCH 16/18] Use app config for static url path. --- plantuml_docs.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index 85a0e8c..e50b417 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -60,7 +60,7 @@ def generate_plantuml(docstring, app): image_data = server.processes(uml) with open(output_file, 'wb') as file: file.write(image_data) - docstring = sub(docstring, match, f'![{filename}](/static/{subfolder}/{filename})') + docstring = sub(docstring, match, f'![{filename}]({app.static_url_path}/{subfolder}/{filename})') except plantuml.PlantUMLConnectionError as e: docstring = sub(docstring, match, f"Failed to connect to the PlantUML server: {e}") except plantuml.PlantUMLHTTPError as e: From 0fafbab9f9ddd7c299ec7aafb530ddee345a89c2 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Thu, 18 Nov 2021 17:44:41 +0000 Subject: [PATCH 17/18] Turn down the logging. --- plantuml_docs.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/plantuml_docs.py b/plantuml_docs.py index e50b417..154293d 100644 --- a/plantuml_docs.py +++ b/plantuml_docs.py @@ -35,18 +35,18 @@ def generate_plantuml(docstring, app): image. """ if not plantuml: - logger.info("PlantUML not installed; not generating diagrams") + logger.debug("PlantUML not installed; not generating diagrams") return docstring url=app.config.get(FLASK_SWAGGER_PLANTUML_SERVER, 'http://www.plantuml.com/plantuml/img/') - logger.info("User PlantUML server %s", url) + logger.debug("Using PlantUML server %s", url) server = plantuml.PlantUML(url=url) subfolder = app.config.get(FLASK_SWAGGER_PLANTUML_FOLDER, 'uml') folder = os.path.join(app.static_folder, subfolder) if not os.path.exists(folder): os.mkdir(folder) - logger.info("Outputting diagrams to %s", folder) + logger.debug("Outputting diagrams to %s", folder) while True: match = _PLANTUML_RE.search(docstring) From b3041202f9b588b45fcfb8a35f76d37cf69e4722 Mon Sep 17 00:00:00 2001 From: Tom Cook Date: Thu, 18 Nov 2021 17:50:25 +0000 Subject: [PATCH 18/18] Fix order of operations for endpoint descriptions. --- flask_swagger.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/flask_swagger.py b/flask_swagger.py index b57a1f0..dab4d80 100644 --- a/flask_swagger.py +++ b/flask_swagger.py @@ -66,8 +66,9 @@ def _parse_docstring(obj, process_doc, from_file_keyword, base_path, app): first_line = process_doc(full_doc[:line_feed]) yaml_sep = full_doc[line_feed+1:].find('---') if yaml_sep != -1: - other_lines = process_doc(full_doc[line_feed+1:line_feed+yaml_sep]) + other_lines = full_doc[line_feed+1:line_feed+yaml_sep] other_lines = generate_plantuml(other_lines, app) + other_lines = process_doc(other_lines) swag = yaml.full_load(full_doc[line_feed+yaml_sep:]) else: other_lines = process_doc(full_doc[line_feed+1:])