jentic-openapi-parser 1.0.0a19__tar.gz → 1.0.0a20__tar.gz
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.
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/PKG-INFO +50 -6
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/README.md +48 -4
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/pyproject.toml +3 -2
- jentic_openapi_parser-1.0.0a20/src/jentic/apitools/openapi/parser/backends/ruamel_ast.py +56 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/LICENSE +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/NOTICE +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/backends/base.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/backends/py.typed +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/backends/pyyaml.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/backends/ruamel_roundtrip.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/backends/ruamel_safe.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/core/__init__.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/core/exceptions.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/core/loader.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/core/openapi_parser.py +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/core/py.typed +0 -0
- {jentic_openapi_parser-1.0.0a19 → jentic_openapi_parser-1.0.0a20}/src/jentic/apitools/openapi/parser/core/serialization.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: jentic-openapi-parser
|
|
3
|
-
Version: 1.0.
|
|
3
|
+
Version: 1.0.0a20
|
|
4
4
|
Summary: Jentic OpenAPI Parser
|
|
5
5
|
Author: Jentic
|
|
6
6
|
Author-email: Jentic <hello@jentic.com>
|
|
@@ -8,7 +8,7 @@ License-Expression: Apache-2.0
|
|
|
8
8
|
License-File: LICENSE
|
|
9
9
|
License-File: NOTICE
|
|
10
10
|
Requires-Dist: attrs~=25.4.0
|
|
11
|
-
Requires-Dist: jentic-openapi-common~=1.0.
|
|
11
|
+
Requires-Dist: jentic-openapi-common~=1.0.0a20
|
|
12
12
|
Requires-Dist: pyyaml~=6.0.3
|
|
13
13
|
Requires-Dist: requests~=2.32.5
|
|
14
14
|
Requires-Dist: ruamel-yaml~=0.18.15
|
|
@@ -24,7 +24,7 @@ A Python library for parsing OpenAPI documents using pluggable parser backends.
|
|
|
24
24
|
|
|
25
25
|
- **Pluggable Backend Architecture**: Support for multiple parsing strategies via entry points
|
|
26
26
|
- **Multiple Input Formats**: Parse OpenAPI documents from file URIs or text strings (JSON/YAML)
|
|
27
|
-
- **Multiple Parser Backends**: Choose from PyYAML, ruamel.yaml
|
|
27
|
+
- **Multiple Parser Backends**: Choose from PyYAML, ruamel.yaml (safe/roundtrip/AST modes)
|
|
28
28
|
- **Enhanced JSON Serialization**: Built-in support for datetime, UUID, Path, Decimal, Enum, and attrs classes
|
|
29
29
|
- **Type Safety**: Full type hints with overloaded methods for precise return types
|
|
30
30
|
- **Extensible Design**: Easy integration of third-party parser backends
|
|
@@ -53,12 +53,12 @@ doc = parser.parse("file:///path/to/openapi.yaml")
|
|
|
53
53
|
print(doc["info"]["title"])
|
|
54
54
|
|
|
55
55
|
# Parse from JSON string
|
|
56
|
-
json_doc = '{"openapi":"3.1.
|
|
56
|
+
json_doc = '{"openapi":"3.1.2","info":{"title":"My API","version":"1.0.0"}}'
|
|
57
57
|
doc = parser.parse(json_doc)
|
|
58
58
|
|
|
59
59
|
# Parse from YAML string
|
|
60
60
|
yaml_doc = """
|
|
61
|
-
openapi: 3.1.
|
|
61
|
+
openapi: 3.1.2
|
|
62
62
|
info:
|
|
63
63
|
title: My API
|
|
64
64
|
version: 1.0.0
|
|
@@ -95,6 +95,14 @@ parser = OpenAPIParser("ruamel-roundtrip")
|
|
|
95
95
|
doc = parser.parse("file:///path/to/openapi.yaml", return_type=CommentedMap)
|
|
96
96
|
# Access line/column information
|
|
97
97
|
print(doc.lc.line, doc.lc.col)
|
|
98
|
+
|
|
99
|
+
# Use ruamel.yaml AST mode (returns YAML nodes with source tracking)
|
|
100
|
+
from jentic.apitools.openapi.parser.backends.ruamel_ast import MappingNode
|
|
101
|
+
parser = OpenAPIParser("ruamel-ast")
|
|
102
|
+
node = parser.parse("file:///path/to/openapi.yaml", return_type=MappingNode)
|
|
103
|
+
# Access precise line/column for any node
|
|
104
|
+
for key_node, value_node in node.value:
|
|
105
|
+
print(f"{key_node.value} at line {key_node.start_mark.line}")
|
|
98
106
|
```
|
|
99
107
|
|
|
100
108
|
## Configuration Options
|
|
@@ -171,7 +179,7 @@ class OpenAPIParser:
|
|
|
171
179
|
|
|
172
180
|
**Parameters:**
|
|
173
181
|
- `backend`: Parser backend to use. Can be:
|
|
174
|
-
- `str`: Name of a backend registered via entry points (e.g., "pyyaml", "ruamel-safe", "ruamel-roundtrip")
|
|
182
|
+
- `str`: Name of a backend registered via entry points (e.g., "pyyaml", "ruamel-safe", "ruamel-roundtrip", "ruamel-ast")
|
|
175
183
|
- `BaseParserBackend`: Instance of a parser backend
|
|
176
184
|
- `Type[BaseParserBackend]`: Class of a parser backend (will be instantiated)
|
|
177
185
|
- Defaults to `"pyyaml"` if `None`
|
|
@@ -282,6 +290,42 @@ doc = parser.parse(content, return_type=CommentedMap)
|
|
|
282
290
|
print(f"Line: {doc.lc.line}, Column: {doc.lc.col}")
|
|
283
291
|
```
|
|
284
292
|
|
|
293
|
+
### ruamel-ast
|
|
294
|
+
ruamel.yaml AST mode that returns YAML nodes with complete source location tracking. Ideal for building low-level data models with precise error reporting.
|
|
295
|
+
|
|
296
|
+
**Accepts:** `text` (JSON/YAML strings), `uri` (file paths/URLs)
|
|
297
|
+
|
|
298
|
+
**Returns:** `yaml.MappingNode` (YAML AST) instead of dictionaries
|
|
299
|
+
|
|
300
|
+
```python
|
|
301
|
+
from jentic.apitools.openapi.parser.backends.ruamel_ast import MappingNode
|
|
302
|
+
|
|
303
|
+
parser = OpenAPIParser("ruamel-ast")
|
|
304
|
+
node = parser.parse(content, return_type=MappingNode)
|
|
305
|
+
|
|
306
|
+
# Access YAML nodes with source information
|
|
307
|
+
assert isinstance(node, MappingNode)
|
|
308
|
+
|
|
309
|
+
# Get precise line/column information for any node
|
|
310
|
+
for key_node, value_node in node.value:
|
|
311
|
+
print(f"Key: {key_node.value}")
|
|
312
|
+
print(f" Line: {key_node.start_mark.line}, Column: {key_node.start_mark.column}")
|
|
313
|
+
|
|
314
|
+
# Perfect for building low-level datamodels with source tracking
|
|
315
|
+
# Works seamlessly with jentic-openapi-datamodels
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
**Note:** You can also import directly from `ruamel.yaml` if preferred:
|
|
319
|
+
```python
|
|
320
|
+
from ruamel.yaml import MappingNode # Alternative import
|
|
321
|
+
```
|
|
322
|
+
|
|
323
|
+
**Use Cases:**
|
|
324
|
+
- Building low-level data models that preserve source locations
|
|
325
|
+
- Implementing precise error reporting with line/column numbers
|
|
326
|
+
- AST-based transformations and analysis
|
|
327
|
+
- Integration with validation tools that need exact source positions
|
|
328
|
+
|
|
285
329
|
## Testing
|
|
286
330
|
|
|
287
331
|
Run the test suite:
|
|
@@ -6,7 +6,7 @@ A Python library for parsing OpenAPI documents using pluggable parser backends.
|
|
|
6
6
|
|
|
7
7
|
- **Pluggable Backend Architecture**: Support for multiple parsing strategies via entry points
|
|
8
8
|
- **Multiple Input Formats**: Parse OpenAPI documents from file URIs or text strings (JSON/YAML)
|
|
9
|
-
- **Multiple Parser Backends**: Choose from PyYAML, ruamel.yaml
|
|
9
|
+
- **Multiple Parser Backends**: Choose from PyYAML, ruamel.yaml (safe/roundtrip/AST modes)
|
|
10
10
|
- **Enhanced JSON Serialization**: Built-in support for datetime, UUID, Path, Decimal, Enum, and attrs classes
|
|
11
11
|
- **Type Safety**: Full type hints with overloaded methods for precise return types
|
|
12
12
|
- **Extensible Design**: Easy integration of third-party parser backends
|
|
@@ -35,12 +35,12 @@ doc = parser.parse("file:///path/to/openapi.yaml")
|
|
|
35
35
|
print(doc["info"]["title"])
|
|
36
36
|
|
|
37
37
|
# Parse from JSON string
|
|
38
|
-
json_doc = '{"openapi":"3.1.
|
|
38
|
+
json_doc = '{"openapi":"3.1.2","info":{"title":"My API","version":"1.0.0"}}'
|
|
39
39
|
doc = parser.parse(json_doc)
|
|
40
40
|
|
|
41
41
|
# Parse from YAML string
|
|
42
42
|
yaml_doc = """
|
|
43
|
-
openapi: 3.1.
|
|
43
|
+
openapi: 3.1.2
|
|
44
44
|
info:
|
|
45
45
|
title: My API
|
|
46
46
|
version: 1.0.0
|
|
@@ -77,6 +77,14 @@ parser = OpenAPIParser("ruamel-roundtrip")
|
|
|
77
77
|
doc = parser.parse("file:///path/to/openapi.yaml", return_type=CommentedMap)
|
|
78
78
|
# Access line/column information
|
|
79
79
|
print(doc.lc.line, doc.lc.col)
|
|
80
|
+
|
|
81
|
+
# Use ruamel.yaml AST mode (returns YAML nodes with source tracking)
|
|
82
|
+
from jentic.apitools.openapi.parser.backends.ruamel_ast import MappingNode
|
|
83
|
+
parser = OpenAPIParser("ruamel-ast")
|
|
84
|
+
node = parser.parse("file:///path/to/openapi.yaml", return_type=MappingNode)
|
|
85
|
+
# Access precise line/column for any node
|
|
86
|
+
for key_node, value_node in node.value:
|
|
87
|
+
print(f"{key_node.value} at line {key_node.start_mark.line}")
|
|
80
88
|
```
|
|
81
89
|
|
|
82
90
|
## Configuration Options
|
|
@@ -153,7 +161,7 @@ class OpenAPIParser:
|
|
|
153
161
|
|
|
154
162
|
**Parameters:**
|
|
155
163
|
- `backend`: Parser backend to use. Can be:
|
|
156
|
-
- `str`: Name of a backend registered via entry points (e.g., "pyyaml", "ruamel-safe", "ruamel-roundtrip")
|
|
164
|
+
- `str`: Name of a backend registered via entry points (e.g., "pyyaml", "ruamel-safe", "ruamel-roundtrip", "ruamel-ast")
|
|
157
165
|
- `BaseParserBackend`: Instance of a parser backend
|
|
158
166
|
- `Type[BaseParserBackend]`: Class of a parser backend (will be instantiated)
|
|
159
167
|
- Defaults to `"pyyaml"` if `None`
|
|
@@ -264,6 +272,42 @@ doc = parser.parse(content, return_type=CommentedMap)
|
|
|
264
272
|
print(f"Line: {doc.lc.line}, Column: {doc.lc.col}")
|
|
265
273
|
```
|
|
266
274
|
|
|
275
|
+
### ruamel-ast
|
|
276
|
+
ruamel.yaml AST mode that returns YAML nodes with complete source location tracking. Ideal for building low-level data models with precise error reporting.
|
|
277
|
+
|
|
278
|
+
**Accepts:** `text` (JSON/YAML strings), `uri` (file paths/URLs)
|
|
279
|
+
|
|
280
|
+
**Returns:** `yaml.MappingNode` (YAML AST) instead of dictionaries
|
|
281
|
+
|
|
282
|
+
```python
|
|
283
|
+
from jentic.apitools.openapi.parser.backends.ruamel_ast import MappingNode
|
|
284
|
+
|
|
285
|
+
parser = OpenAPIParser("ruamel-ast")
|
|
286
|
+
node = parser.parse(content, return_type=MappingNode)
|
|
287
|
+
|
|
288
|
+
# Access YAML nodes with source information
|
|
289
|
+
assert isinstance(node, MappingNode)
|
|
290
|
+
|
|
291
|
+
# Get precise line/column information for any node
|
|
292
|
+
for key_node, value_node in node.value:
|
|
293
|
+
print(f"Key: {key_node.value}")
|
|
294
|
+
print(f" Line: {key_node.start_mark.line}, Column: {key_node.start_mark.column}")
|
|
295
|
+
|
|
296
|
+
# Perfect for building low-level datamodels with source tracking
|
|
297
|
+
# Works seamlessly with jentic-openapi-datamodels
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
**Note:** You can also import directly from `ruamel.yaml` if preferred:
|
|
301
|
+
```python
|
|
302
|
+
from ruamel.yaml import MappingNode # Alternative import
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
**Use Cases:**
|
|
306
|
+
- Building low-level data models that preserve source locations
|
|
307
|
+
- Implementing precise error reporting with line/column numbers
|
|
308
|
+
- AST-based transformations and analysis
|
|
309
|
+
- Integration with validation tools that need exact source positions
|
|
310
|
+
|
|
267
311
|
## Testing
|
|
268
312
|
|
|
269
313
|
Run the test suite:
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "jentic-openapi-parser"
|
|
3
|
-
version = "1.0.0-alpha.
|
|
3
|
+
version = "1.0.0-alpha.20"
|
|
4
4
|
description = "Jentic OpenAPI Parser"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
authors = [{ name = "Jentic", email = "hello@jentic.com" }]
|
|
@@ -9,7 +9,7 @@ license-files = ["LICENSE", "NOTICE"]
|
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
dependencies = [
|
|
11
11
|
"attrs~=25.4.0",
|
|
12
|
-
"jentic-openapi-common~=1.0.0-alpha.
|
|
12
|
+
"jentic-openapi-common~=1.0.0-alpha.20",
|
|
13
13
|
"pyyaml~=6.0.3",
|
|
14
14
|
"requests~=2.32.5",
|
|
15
15
|
"ruamel-yaml~=0.18.15"
|
|
@@ -37,4 +37,5 @@ build-backend = "uv_build"
|
|
|
37
37
|
pyyaml = "jentic.apitools.openapi.parser.backends.pyyaml:PyYAMLParserBackend"
|
|
38
38
|
ruamel-safe = "jentic.apitools.openapi.parser.backends.ruamel_safe:RuamelSafeParserBackend"
|
|
39
39
|
ruamel-roundtrip = "jentic.apitools.openapi.parser.backends.ruamel_roundtrip:RuamelRoundTripParserBackend"
|
|
40
|
+
ruamel-ast = "jentic.apitools.openapi.parser.backends.ruamel_ast:RuamelASTParserBackend"
|
|
40
41
|
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import logging
|
|
2
|
+
from collections.abc import Sequence
|
|
3
|
+
from typing import Literal
|
|
4
|
+
|
|
5
|
+
from ruamel.yaml import MappingNode, ScalarNode, SequenceNode
|
|
6
|
+
|
|
7
|
+
from jentic.apitools.openapi.common.uri import is_uri_like
|
|
8
|
+
from jentic.apitools.openapi.parser.backends.ruamel_roundtrip import RuamelRoundTripParserBackend
|
|
9
|
+
from jentic.apitools.openapi.parser.core.loader import load_uri
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
__all__ = [
|
|
13
|
+
"RuamelASTParserBackend",
|
|
14
|
+
# Re-export common YAML node types for convenience
|
|
15
|
+
"MappingNode",
|
|
16
|
+
"ScalarNode",
|
|
17
|
+
"SequenceNode",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
class RuamelASTParserBackend(RuamelRoundTripParserBackend):
|
|
22
|
+
def parse(self, document: str, *, logger: logging.Logger | None = None) -> MappingNode: # type: ignore[override]
|
|
23
|
+
logger = logger or logging.getLogger(__name__)
|
|
24
|
+
if is_uri_like(document):
|
|
25
|
+
return self._parse_uri(document, logger)
|
|
26
|
+
return self._parse_text(document, logger)
|
|
27
|
+
|
|
28
|
+
@staticmethod
|
|
29
|
+
def accepts() -> Sequence[Literal["uri", "text"]]:
|
|
30
|
+
"""Return supported input formats.
|
|
31
|
+
|
|
32
|
+
Returns:
|
|
33
|
+
Sequence of supported document format identifiers:
|
|
34
|
+
- "uri": File path or URI pointing to OpenAPI Document
|
|
35
|
+
- "text": String (JSON/YAML) representation
|
|
36
|
+
"""
|
|
37
|
+
return ["uri", "text"]
|
|
38
|
+
|
|
39
|
+
def _parse_uri(self, uri: str, logger: logging.Logger) -> MappingNode: # type: ignore[override]
|
|
40
|
+
logger.debug("Starting download of %s", uri)
|
|
41
|
+
return self._parse_text(load_uri(uri, 5, 10, logger), logger)
|
|
42
|
+
|
|
43
|
+
def _parse_text(self, text: str, logger: logging.Logger) -> MappingNode: # type: ignore[override]
|
|
44
|
+
if not isinstance(text, (bytes, str)):
|
|
45
|
+
raise TypeError(f"Unsupported document type: {type(text)!r}")
|
|
46
|
+
|
|
47
|
+
if isinstance(text, bytes):
|
|
48
|
+
text = text.decode()
|
|
49
|
+
|
|
50
|
+
node: MappingNode = self.yaml.compose(text)
|
|
51
|
+
logger.debug("YAML document successfully parsed")
|
|
52
|
+
|
|
53
|
+
if not isinstance(node, MappingNode):
|
|
54
|
+
raise TypeError(f"Parsed YAML document is not a mapping: {type(node)!r}")
|
|
55
|
+
|
|
56
|
+
return node
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|