import inspect import warnings import yaml class OpenAPIDocstringParser: def __init__(self, docstring: str): """ Args: docstring (str): docstring of function to be parsed """ if docstring is None: docstring = "" self.docstring = inspect.cleandoc(docstring) def to_openAPI_2(self) -> dict: """ Returns: json style dict: dict to be read for the path by swagger 2.0 UI """ raise NotImplementedError() def to_openAPI_3(self) -> dict: """ Returns: json style dict: dict to be read for the path by swagger 3.0.0 UI """ raise NotImplementedError() class YamlStyleParametersParser(OpenAPIDocstringParser): def _parse_no_yaml(self, doc: str) -> dict: """ Args: doc (str): section of doc before yaml, or full section of doc Returns: json style dict: dict to be read for the path by swagger UI """ # clean again in case further indentation can be removed, # usually this do nothing... doc = inspect.cleandoc(doc) if len(doc) == 0: return {} lines = doc.split("\n") if len(lines) == 1: return {"summary": lines[0]} else: summary = lines.pop(0) # remove empty lines at the beginning of the description while len(lines) and lines[0].strip() == "": lines.pop(0) if len(lines) == 0: return {"summary": summary} else: # use html tag to preserve linebreaks return {"summary": summary, "description": "
".join(lines)} def _parse_yaml(self, doc: str) -> dict: """ Args: doc (str): section of doc detected as openapi yaml Returns: json style dict: dict to be read for the path by swagger UI Warns: UserWarning if the yaml couldn't be parsed """ try: return yaml.safe_load(doc) except Exception as e: warnings.warn(f"error parsing openAPI yaml, ignoring it. ({e})") return {} def _parse_all(self) -> dict: if "openapi:\n" not in self.docstring: return self._parse_no_yaml(self.docstring) predoc, yamldoc = self.docstring.split("openapi:\n", 1) conf = self._parse_no_yaml(predoc) conf.update(self._parse_yaml(yamldoc)) return conf def to_openAPI_2(self) -> dict: return self._parse_all() def to_openAPI_3(self) -> dict: return self._parse_all()