Skip to content

Commit ed147c1

Browse files
authored
feat(openapi-transformer): prepare for production use (#33)
Polish the package and prepare for production ready state.
1 parent 8444121 commit ed147c1

File tree

30 files changed

+728
-278
lines changed

30 files changed

+728
-278
lines changed

packages/jentic-openapi-parser/src/jentic/apitools/openapi/parser/core/uri.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# uri_resolution.py
21
from __future__ import annotations
32

43
import logging

packages/jentic-openapi-transformer-redocly/README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# jentic-openapi-transformer-redocly
22

3-
A Python library that provides OpenAPI document bundling functionality using [Redocly CLI](https://redocly.com/docs/cli/). This package is part of the Jentic OpenAPI Tools ecosystem and implements the transformer strategy pattern for bundling OpenAPI documents by resolving external references.
3+
A Python library that provides OpenAPI document bundling functionality using [Redocly CLI](https://redocly.com/docs/cli/). This package is part of the Jentic OpenAPI Tools ecosystem and implements the transformer backend pattern for bundling OpenAPI documents by resolving external references.
44

55
## Features
66

@@ -32,10 +32,10 @@ npm install -g @redocly/cli
3232
### Basic Usage
3333

3434
```python
35-
from jentic.apitools.openapi.transformer.redocly import RedoclyBundler
35+
from jentic.apitools.openapi.transformer.bundler.backends.redocly import RedoclyBundlerBackend
3636

3737
# Create a bundler instance
38-
bundler = RedoclyBundler()
38+
bundler = RedoclyBundlerBackend()
3939

4040
# Bundle an OpenAPI document from a file path
4141
result = bundler.bundle("/path/to/your/openapi.yaml")
@@ -66,7 +66,7 @@ parsed_result = json.loads(result)
6666

6767
```python
6868
# Custom Redocly CLI path and timeout
69-
bundler = RedoclyBundler(
69+
bundler = RedoclyBundlerBackend(
7070
redocly_path="redocly", # Use global redocly installation
7171
timeout=60.0 # 60 second timeout
7272
)
@@ -81,10 +81,10 @@ result = bundler.bundle("https://petstore3.swagger.io/api/v3/openapi.json")
8181
The bundler provides detailed error reporting for various failure scenarios:
8282

8383
```python
84-
from jentic.apitools.openapi.transformer.redocly import RedoclyBundler
84+
from jentic.apitools.openapi.transformer.bundler.backends.redocly import RedoclyBundlerBackend
8585
from jentic.apitools.openapi.common.subproc import SubprocessExecutionError
8686

87-
bundler = RedoclyBundler()
87+
bundler = RedoclyBundlerBackend()
8888

8989
try:
9090
result = bundler.bundle("/path/to/openapi.yaml")
@@ -120,7 +120,7 @@ uv run --package jentic-openapi-transformer-redocly pytest packages/jentic-opena
120120
### RedoclyBundler
121121

122122
```python
123-
class RedoclyBundler(BaseBundlerStrategy):
123+
class RedoclyBundlerBackend(BaseBundlerBackend):
124124
def __init__(
125125
self,
126126
redocly_path: str = "npx @redocly/cli@^2.1.5",

packages/jentic-openapi-transformer-redocly/pyproject.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ package = true
2626

2727
[tool.uv.build-backend]
2828
namespace = true
29-
module-name = "jentic.apitools.openapi.transformer.redocly"
29+
module-name = "jentic.apitools.openapi.transformer.bundler.backends"
3030
module-root = "src/"
3131

3232
[tool.uv.sources]
@@ -37,7 +37,7 @@ jentic-openapi-transformer = { workspace = true }
3737
requires = ["uv_build>=0.8.15,<0.9.0"]
3838
build-backend = "uv_build"
3939

40-
[project.entry-points."jentic.apitools.openapi.transformer.strategies"]
41-
redocly = "jentic.apitools.openapi.transformer.redocly:RedoclyBundler"
40+
[project.entry-points."jentic.apitools.openapi.transformer.bundler.backends"]
41+
redocly = "jentic.apitools.openapi.transformer.bundler.backends.redocly:RedoclyBundlerBackend"
4242

4343

packages/jentic-openapi-transformer-redocly/src/jentic/apitools/openapi/transformer/redocly/__init__.py renamed to packages/jentic-openapi-transformer-redocly/src/jentic/apitools/openapi/transformer/bundler/backends/redocly/__init__.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,14 @@
44
from urllib.parse import urlparse
55
from urllib.request import url2pathname
66

7-
from jentic.apitools.openapi.transformer.strategies.base import BaseBundlerStrategy
7+
from jentic.apitools.openapi.transformer.bundler.backends.base import BaseBundlerBackend
88
from jentic.apitools.openapi.common.subproc import run_subprocess
99

1010

11-
__all__ = ["RedoclyBundler"]
11+
__all__ = ["RedoclyBundlerBackend"]
1212

1313

14-
class RedoclyBundler(BaseBundlerStrategy):
14+
class RedoclyBundlerBackend(BaseBundlerBackend):
1515
def __init__(self, redocly_path: str = "npx @redocly/cli@^2.1.5", timeout: float = 30.0):
1616
"""
1717
Initialize the RedoclyBundler.
@@ -33,7 +33,7 @@ def accepts(self) -> list[str]:
3333
"""
3434
return ["uri", "dict"]
3535

36-
def bundle(self, document: str | dict, base_url: str | None = None) -> str:
36+
def bundle(self, document: str | dict, *, base_url: str | None = None) -> str:
3737
"""
3838
Bundle an OpenAPI document using Redocly CLI.
3939

packages/jentic-openapi-transformer-redocly/src/jentic/apitools/openapi/transformer/redocly/py.typed renamed to packages/jentic-openapi-transformer-redocly/src/jentic/apitools/openapi/transformer/bundler/backends/redocly/py.typed

File renamed without changes.

packages/jentic-openapi-transformer-redocly/tests/conftest.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
import pytest
77

8-
from jentic.apitools.openapi.transformer.redocly import RedoclyBundler
8+
from jentic.apitools.openapi.transformer.bundler.backends.redocly import RedoclyBundlerBackend
99

1010

1111
@pytest.fixture
@@ -27,21 +27,21 @@ def snapshots_dir(fixtures_dir: Path) -> Path:
2727

2828

2929
@pytest.fixture
30-
def redocly_bundler() -> RedoclyBundler:
30+
def redocly_bundler() -> RedoclyBundlerBackend:
3131
"""Return a default RedoclyBundler instance."""
32-
return RedoclyBundler()
32+
return RedoclyBundlerBackend()
3333

3434

3535
@pytest.fixture
36-
def redocly_bundler_with_custom_timeout() -> RedoclyBundler:
36+
def redocly_bundler_with_custom_timeout() -> RedoclyBundlerBackend:
3737
"""Return a RedoclyBundler instance with custom timeout."""
38-
return RedoclyBundler(timeout=60.0)
38+
return RedoclyBundlerBackend(timeout=60.0)
3939

4040

4141
@pytest.fixture
42-
def redocly_bundler_with_custom_path() -> RedoclyBundler:
42+
def redocly_bundler_with_custom_path() -> RedoclyBundlerBackend:
4343
"""Return a RedoclyBundler instance with custom redocly path."""
44-
return RedoclyBundler(redocly_path="/custom/path/to/redocly")
44+
return RedoclyBundlerBackend(redocly_path="/custom/path/to/redocly")
4545

4646

4747
@pytest.fixture

packages/jentic-openapi-transformer-redocly/tests/test_redocly_bundle.py

Lines changed: 21 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
"""Tests for RedoclyBundler functionality."""
1+
"""Tests for RedoclyBundlerBackend functionality."""
22

33
import pytest
44

5-
from jentic.apitools.openapi.transformer.redocly import RedoclyBundler
5+
from jentic.apitools.openapi.transformer.bundler.backends.redocly import RedoclyBundlerBackend
66
from jentic.apitools.openapi.common.subproc import SubprocessExecutionError
77

88

@@ -12,7 +12,7 @@ class TestRedoclyBundlerIntegration:
1212
@pytest.mark.requires_redocly_cli
1313
def test_bundle_valid_openapi_document(
1414
self,
15-
redocly_bundler: RedoclyBundler,
15+
redocly_bundler: RedoclyBundlerBackend,
1616
valid_openapi_uri: str,
1717
expected_bundled_content: str,
1818
):
@@ -23,7 +23,7 @@ def test_bundle_valid_openapi_document(
2323
@pytest.mark.requires_redocly_cli
2424
def test_bundle_malformed_openapi_document(
2525
self,
26-
redocly_bundler: RedoclyBundler,
26+
redocly_bundler: RedoclyBundlerBackend,
2727
malformed_openapi_uri: str,
2828
):
2929
"""Test bundling of a malformed OpenAPI document raises RuntimeError."""
@@ -33,7 +33,7 @@ def test_bundle_malformed_openapi_document(
3333
@pytest.mark.requires_redocly_cli
3434
def test_bundle_with_custom_timeout(
3535
self,
36-
redocly_bundler_with_custom_timeout: RedoclyBundler,
36+
redocly_bundler_with_custom_timeout: RedoclyBundlerBackend,
3737
valid_openapi_uri: str,
3838
expected_bundled_content: str,
3939
):
@@ -44,7 +44,7 @@ def test_bundle_with_custom_timeout(
4444
@pytest.mark.requires_redocly_cli
4545
def test_bundle_dict_document(
4646
self,
47-
redocly_bundler: RedoclyBundler,
47+
redocly_bundler: RedoclyBundlerBackend,
4848
expected_bundled_content: str,
4949
):
5050
"""Test bundling of a dict OpenAPI document."""
@@ -68,26 +68,28 @@ class TestRedoclyBundlerUnit:
6868
"""Unit tests that don't require external dependencies."""
6969

7070
def test_init_with_defaults(self):
71-
"""Test RedoclyBundler initialization with default values."""
72-
bundler = RedoclyBundler()
71+
"""Test RedoclyBundlerBackend initialization with default values."""
72+
bundler = RedoclyBundlerBackend()
7373
assert bundler.redocly_path == "npx @redocly/cli@^2.1.5"
7474
assert bundler.timeout == 30.0
7575

76-
def test_init_with_custom_path(self, redocly_bundler_with_custom_path: RedoclyBundler):
77-
"""Test RedoclyBundler initialization with custom redocly path."""
76+
def test_init_with_custom_path(self, redocly_bundler_with_custom_path: RedoclyBundlerBackend):
77+
"""Test RedoclyBundlerBackend initialization with custom redocly path."""
7878
assert redocly_bundler_with_custom_path.redocly_path == "/custom/path/to/redocly"
7979

80-
def test_init_with_custom_timeout(self, redocly_bundler_with_custom_timeout: RedoclyBundler):
81-
"""Test RedoclyBundler initialization with custom timeout."""
80+
def test_init_with_custom_timeout(
81+
self, redocly_bundler_with_custom_timeout: RedoclyBundlerBackend
82+
):
83+
"""Test RedoclyBundlerBackend initialization with custom timeout."""
8284
assert redocly_bundler_with_custom_timeout.timeout == 60.0
8385

84-
def test_accepts_returns_correct_formats(self, redocly_bundler: RedoclyBundler):
86+
def test_accepts_returns_correct_formats(self, redocly_bundler: RedoclyBundlerBackend):
8587
"""Test that accepts() returns the correct supported formats."""
8688
formats = redocly_bundler.accepts()
8789
assert formats == ["uri", "dict"]
8890
assert isinstance(formats, list)
8991

90-
def test_bundle_with_unsupported_document_type(self, redocly_bundler: RedoclyBundler):
92+
def test_bundle_with_unsupported_document_type(self, redocly_bundler: RedoclyBundlerBackend):
9193
"""Test that bundle() raises TypeError for unsupported document types."""
9294
with pytest.raises(TypeError, match="Unsupported document type"):
9395
redocly_bundler.bundle(42) # type: ignore
@@ -104,28 +106,28 @@ class TestRedoclyBundlerErrorHandling:
104106

105107
def test_bundle_with_nonexistent_cli(self):
106108
"""Test behavior when redocly CLI is not available."""
107-
bundler = RedoclyBundler(redocly_path="nonexistent_redocly")
109+
bundler = RedoclyBundlerBackend(redocly_path="nonexistent_redocly")
108110

109111
with pytest.raises(SubprocessExecutionError):
110112
bundler.bundle("/some/test/file.yaml")
111113

112-
def test_bundle_with_invalid_file_path(self, redocly_bundler: RedoclyBundler):
114+
def test_bundle_with_invalid_file_path(self, redocly_bundler: RedoclyBundlerBackend):
113115
"""Test bundling with invalid file path."""
114116
with pytest.raises(RuntimeError, match="does not exist"):
115117
redocly_bundler.bundle("/nonexistent/path/to/file.yaml")
116118

117119
def test_bundle_with_timeout_configuration(self):
118120
"""Test that timeout is properly configured."""
119-
bundler = RedoclyBundler(timeout=1.0) # Very short timeout
121+
bundler = RedoclyBundlerBackend(timeout=1.0) # Very short timeout
120122
assert bundler.timeout == 1.0
121123

122-
def test_bundle_empty_string_input(self, redocly_bundler: RedoclyBundler):
124+
def test_bundle_empty_string_input(self, redocly_bundler: RedoclyBundlerBackend):
123125
"""Test bundling with empty string input."""
124126
with pytest.raises(RuntimeError, match="Path cannot be empty"):
125127
redocly_bundler.bundle("")
126128

127129
@pytest.mark.requires_redocly_cli
128-
def test_bundle_invalid_dict_input(self, redocly_bundler: RedoclyBundler):
130+
def test_bundle_invalid_dict_input(self, redocly_bundler: RedoclyBundlerBackend):
129131
"""Test bundling with invalid dict input."""
130132
invalid_dict = {"invalid": "not an openapi document"}
131133

0 commit comments

Comments
 (0)