openapi-spec-generator 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ __version__ = "0.1.0"
@@ -0,0 +1,22 @@
1
+ def call_ai(prompt: str, api_key: str, provider: str) -> str:
2
+ if provider == "claude":
3
+ import anthropic
4
+
5
+ client = anthropic.Anthropic(api_key=api_key)
6
+ with client.messages.stream(
7
+ model="claude-sonnet-4-6",
8
+ max_tokens=4096,
9
+ messages=[{"role": "user", "content": prompt}],
10
+ ) as stream:
11
+ return stream.get_final_message().content[0].text
12
+ elif provider == "openai":
13
+ import openai
14
+
15
+ client = openai.OpenAI(api_key=api_key)
16
+ response = client.chat.completions.create(
17
+ model="gpt-4o",
18
+ messages=[{"role": "user", "content": prompt}],
19
+ )
20
+ return response.choices[0].message.content
21
+ else:
22
+ raise ValueError(f"Unknown provider '{provider}'. Choose 'claude' or 'openai'.")
@@ -0,0 +1,31 @@
1
+ import json
2
+ import click
3
+ from pathlib import Path
4
+ from .generator import generate_spec
5
+
6
+
7
+ @click.command()
8
+ @click.argument("path", type=click.Path(exists=True, file_okay=False, path_type=Path))
9
+ @click.option("--output", "-o", default="openapi.json", show_default=True, help="Output file path.")
10
+ @click.option("--title", default="API", show_default=True, help="API title.")
11
+ @click.option("--version", "api_version", default="1.0.0", show_default=True, help="API version.")
12
+ @click.option(
13
+ "--api-key",
14
+ envvar="OPENAPI_GEN_API_KEY",
15
+ required=True,
16
+ help="AI provider API key (or set OPENAPI_GEN_API_KEY).",
17
+ )
18
+ @click.option(
19
+ "--provider",
20
+ type=click.Choice(["claude", "openai"]),
21
+ default="claude",
22
+ show_default=True,
23
+ help="AI provider to use.",
24
+ )
25
+ def main(path: Path, output: str, title: str, api_version: str, api_key: str, provider: str) -> None:
26
+ """Generate an OpenAPI specification for a REST API project directory."""
27
+ click.echo(f"Scanning {path} ...")
28
+ spec = generate_spec(path, title=title, api_version=api_version, api_key=api_key, provider=provider)
29
+ output_path = Path(output)
30
+ output_path.write_text(json.dumps(spec, indent=2), encoding="utf-8")
31
+ click.echo(f"Wrote JSON spec to {output_path}")
@@ -0,0 +1,37 @@
1
+ import os
2
+ from pathlib import Path
3
+
4
+ _INCLUDE_EXTENSIONS = {".py", ".js", ".ts", ".go", ".java", ".rb", ".php", ".cs"}
5
+ _SKIP_DIRS = {"node_modules", ".git", "__pycache__", "venv", ".venv", "dist", "build", ".eggs"}
6
+
7
+
8
+ def collect_files(project_dir: Path, max_bytes: int = 400_000) -> list[tuple[str, str]]:
9
+ """Walk *project_dir* and return (relative_path, content) for each source file.
10
+
11
+ Stops collecting once the total accumulated size exceeds *max_bytes* to
12
+ avoid exceeding AI model context limits.
13
+ """
14
+ results: list[tuple[str, str]] = []
15
+ total = 0
16
+
17
+ for root, dirs, files in os.walk(project_dir):
18
+ dirs[:] = [d for d in dirs if d not in _SKIP_DIRS]
19
+
20
+ for filename in sorted(files):
21
+ if Path(filename).suffix not in _INCLUDE_EXTENSIONS:
22
+ continue
23
+
24
+ abs_path = Path(root) / filename
25
+ try:
26
+ content = abs_path.read_text(encoding="utf-8")
27
+ except (UnicodeDecodeError, OSError):
28
+ continue
29
+
30
+ total += len(content.encode("utf-8"))
31
+ if total > max_bytes:
32
+ return results
33
+
34
+ rel_path = abs_path.relative_to(project_dir).as_posix()
35
+ results.append((rel_path, content))
36
+
37
+ return results
@@ -0,0 +1,49 @@
1
+ import json
2
+ import re
3
+ from pathlib import Path
4
+
5
+ from .file_collector import collect_files
6
+ from .ai_client import call_ai
7
+
8
+ _SYSTEM_PROMPT = (
9
+ "You are an expert OpenAPI specification writer. "
10
+ "Given source files from a REST API project, produce a complete, valid "
11
+ "OpenAPI 3.0.3 specification in JSON. "
12
+ "Respond with ONLY the raw JSON — no markdown fences, no explanation, no commentary."
13
+ )
14
+
15
+
16
+ def _build_prompt(files: list[tuple[str, str]], title: str, api_version: str) -> str:
17
+ file_blocks = "\n\n".join(
18
+ f"### {path}\n{content}" for path, content in files
19
+ )
20
+ return (
21
+ f"{_SYSTEM_PROMPT}\n\n"
22
+ f"API title: {title}\n"
23
+ f"API version: {api_version}\n\n"
24
+ f"Source files:\n\n{file_blocks}"
25
+ )
26
+
27
+
28
+ def _parse_json(raw: str) -> dict:
29
+ text = raw.strip()
30
+ text = re.sub(r"^```(?:json)?\s*", "", text)
31
+ text = re.sub(r"\s*```$", "", text)
32
+ try:
33
+ return json.loads(text)
34
+ except json.JSONDecodeError as exc:
35
+ raise ValueError(f"AI response was not valid JSON:\n{raw[:500]}") from exc
36
+
37
+
38
+ def generate_spec(
39
+ project_dir: Path,
40
+ *,
41
+ title: str = "API",
42
+ api_version: str = "1.0.0",
43
+ api_key: str,
44
+ provider: str = "claude",
45
+ ) -> dict:
46
+ files = collect_files(project_dir)
47
+ prompt = _build_prompt(files, title, api_version)
48
+ raw = call_ai(prompt, api_key, provider)
49
+ return _parse_json(raw)
@@ -0,0 +1,98 @@
1
+ Metadata-Version: 2.4
2
+ Name: openapi-spec-generator
3
+ Version: 0.1.0
4
+ Summary: Generate OpenAPI specifications for any REST API project directory.
5
+ License: MIT
6
+ Requires-Python: >=3.10
7
+ Description-Content-Type: text/markdown
8
+ Requires-Dist: click>=8.0
9
+ Provides-Extra: claude
10
+ Requires-Dist: anthropic>=0.25; extra == "claude"
11
+ Provides-Extra: openai
12
+ Requires-Dist: openai>=1.0; extra == "openai"
13
+ Provides-Extra: all
14
+ Requires-Dist: anthropic>=0.25; extra == "all"
15
+ Requires-Dist: openai>=1.0; extra == "all"
16
+ Provides-Extra: dev
17
+ Requires-Dist: pytest>=8.0; extra == "dev"
18
+ Requires-Dist: pytest-cov>=5.0; extra == "dev"
19
+
20
+ # OpenAPI Generator
21
+
22
+ A pip-installable CLI tool that uses AI to generate OpenAPI 3.0.3 specifications for any REST API project directory.
23
+
24
+ ## Overview
25
+
26
+ Point this tool at any REST API project and it will scan the source files, send them to an AI model (Claude or OpenAI), and produce a valid OpenAPI 3.0.3 JSON specification.
27
+
28
+ ## Installation
29
+
30
+ ```bash
31
+ # With Claude support (default)
32
+ pip install "openapi-generator[claude]"
33
+
34
+ # With OpenAI support
35
+ pip install "openapi-generator[openai]"
36
+
37
+ # Both providers
38
+ pip install "openapi-generator[all]"
39
+ ```
40
+
41
+ ## Usage
42
+
43
+ ```bash
44
+ openapi-gen <path-to-project> --api-key <your-api-key>
45
+ ```
46
+
47
+ The API key can also be provided via the `OPENAPI_GEN_API_KEY` environment variable:
48
+
49
+ ```bash
50
+ export OPENAPI_GEN_API_KEY=sk-ant-...
51
+ openapi-gen <path-to-project>
52
+ ```
53
+
54
+ ### Options
55
+
56
+ | Option | Default | Description |
57
+ |---|---|---|
58
+ | `<path>` | _(required)_ | Path to the REST API project directory |
59
+ | `--api-key` | `OPENAPI_GEN_API_KEY` env var | AI provider API key |
60
+ | `--provider` | `claude` | AI provider: `claude` or `openai` |
61
+ | `--output`, `-o` | `openapi.json` | Output file path |
62
+ | `--title` | `API` | API title in the spec |
63
+ | `--version` | `1.0.0` | API version in the spec |
64
+
65
+ ### Examples
66
+
67
+ ```bash
68
+ # Generate a spec using Claude (default)
69
+ export OPENAPI_GEN_API_KEY=sk-ant-...
70
+ openapi-gen ./my-api
71
+
72
+ # Generate a spec using OpenAI
73
+ openapi-gen ./my-api --provider openai --api-key sk-...
74
+
75
+ # Specify title, version, and output path
76
+ openapi-gen ./my-api --title "My REST API" --version "2.0.0" --output ./docs/openapi.json
77
+ ```
78
+
79
+ ## Output
80
+
81
+ The generated file follows the [OpenAPI 3.0.3 specification](https://spec.openapis.org/oas/v3.0.3) and can be used directly with tools like Swagger UI, Postman, or any OpenAPI-compatible client generator.
82
+
83
+ ## Supported Languages
84
+
85
+ The tool scans files with the following extensions: `.py`, `.js`, `.ts`, `.go`, `.java`, `.rb`, `.php`, `.cs`
86
+
87
+ ## Development
88
+
89
+ ```bash
90
+ git clone https://github.com/your-org/openapi-generator
91
+ cd openapi-generator
92
+ pip install -e ".[dev]"
93
+ pytest
94
+ ```
95
+
96
+ ## License
97
+
98
+ MIT
@@ -0,0 +1,10 @@
1
+ openapi_generator/__init__.py,sha256=kUR5RAFc7HCeiqdlX36dZOHkUI5wI6V_43RpEcD8b-0,22
2
+ openapi_generator/ai_client.py,sha256=LaQx54jXZRDJauXQ8vFrt8e8FYemcnTXAfU6XIwTO0g,820
3
+ openapi_generator/cli.py,sha256=TuNjNwLauYYKm0QPA1kY1KAENvRR81NCbezPECsOULs,1257
4
+ openapi_generator/file_collector.py,sha256=k74-ZtjyrB7Ojz-nYyVKMYCBJCuIm-n_fqBvGkXp3Ig,1268
5
+ openapi_generator/generator.py,sha256=myz-MHVHXzka7jnrKb6PFmTeroFCJznrb-G2Wb8gteM,1408
6
+ openapi_spec_generator-0.1.0.dist-info/METADATA,sha256=LafjnZWoBsW6AlG7z-jOj1aI2Q763Gb6ptLPx_kxmcE,2773
7
+ openapi_spec_generator-0.1.0.dist-info/WHEEL,sha256=aeYiig01lYGDzBgS8HxWXOg3uV61G9ijOsup-k9o1sk,91
8
+ openapi_spec_generator-0.1.0.dist-info/entry_points.txt,sha256=hFqC1pfJAr_WhteyW7DzVwhWdMfvo8g3Qb7p-u5udCE,59
9
+ openapi_spec_generator-0.1.0.dist-info/top_level.txt,sha256=YODEqCx34asgokWpD2p-Sm7tbt4Fw0Vk8W3eKfcvPAw,18
10
+ openapi_spec_generator-0.1.0.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: setuptools (82.0.1)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1,2 @@
1
+ [console_scripts]
2
+ openapi-gen = openapi_generator.cli:main
@@ -0,0 +1 @@
1
+ openapi_generator