Files
DocsGPT/docsgpt/parser/file/openapi3_parser.py
T
Alex b3326b3c33 chore(deps): redis 8, tiktoken 0.14, openapi3-parser 2, daytona 0.211, reportlab 5
Major bumps whose ceilings had to move. redis 8.1.0, tiktoken 0.14.0 and
daytona 0.211.2 needed no code change (the Daytona client, filesystem and
process signatures the sandbox calls are unchanged; redis 8 was checked
against a live server through the app's own sync and async clients).
reportlab 5.0.1 is test-only.

openapi-parser 2.0.0 is a rewrite onto pydantic spec models: `paths` is now
a dict keyed by URL rather than a list of objects carrying their own `url`,
and a path item exposes one field per HTTP method instead of an `operations`
list. `OpenAPI3Parser` reads both accordingly, iterating methods in the
order the spec declares them, and its rendered output is byte-identical to
before. The rewrite also drops prance, openapi-spec-validator and five more
transitive packages.

tokenizers stays at 0.22.2: transformers 5.8.1 caps it at <=0.23.0 and no
such release exists, so it moves with the transformers cap or not at all.
2026-09-12 17:28:58 +01:00

73 lines
2.5 KiB
Python

from typing import Dict, Iterable, Optional, Tuple
from urllib.parse import urlparse
from openapi_parser import parse
try:
from docsgpt.parser.file.base_parser import BaseParser
except ModuleNotFoundError:
from base_parser import BaseParser
# openapi-parser 2.x models a path item as one field per HTTP method rather
# than an ``operations`` list, so the methods are read in the order the
# OpenAPI spec declares them.
_HTTP_METHODS: Tuple[str, ...] = (
"get",
"put",
"post",
"delete",
"options",
"head",
"patch",
"trace",
)
class OpenAPI3Parser(BaseParser):
def init_parser(self) -> None:
return super().init_parser()
def get_base_urls(self, urls):
base_urls = []
for i in urls:
parsed_url = urlparse(i)
base_url = parsed_url.scheme + "://" + parsed_url.netloc
if base_url not in base_urls:
base_urls.append(base_url)
return base_urls
def get_operations(self, path_item) -> Iterable[Tuple[str, object]]:
"""Yield ``(method, operation)`` for every method the path item defines."""
for method in _HTTP_METHODS:
operation = getattr(path_item, method, None)
if operation is not None:
yield method, operation
def get_info_from_paths(self, path_item) -> str:
"""Render one line per method as ``\\n<method>=<first response description>``."""
info = ""
for method, operation in self.get_operations(path_item):
responses = operation.responses or {}
first = next(iter(responses.values()), None)
description = getattr(first, "description", None)
info += f"\n{method}={description}"
return info
def parse_file(self, file_path):
data = parse(file_path)
results = ""
base_urls = self.get_base_urls(link.url for link in data.servers)
base_urls = ",".join([base_url for base_url in base_urls])
results += f"Base URL:{base_urls}\n"
paths: Optional[Dict] = data.paths or {}
for i, (url, path_item) in enumerate(paths.items(), start=1):
info = self.get_info_from_paths(path_item)
results += (
f"Path{i}: {url}\n"
f"description: {path_item.description}\n"
f"parameters: {path_item.parameters or []}\nmethods: {info}\n"
)
with open("results.txt", "w") as f:
f.write(results)
return results