jentic-openapi-datamodels 1.0.0a11__py3-none-any.whl → 1.0.0a13__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.
- jentic/apitools/openapi/datamodels/low/context.py +21 -0
- jentic/apitools/openapi/datamodels/low/extractors.py +126 -0
- jentic/apitools/openapi/datamodels/low/fields.py +45 -0
- jentic/apitools/openapi/datamodels/low/model_builder.py +113 -0
- jentic/apitools/openapi/datamodels/low/py.typed +0 -0
- jentic/apitools/openapi/datamodels/low/sources.py +89 -0
- jentic/apitools/openapi/datamodels/low/v30/__init__.py +0 -28
- jentic/apitools/openapi/datamodels/low/v30/discriminator.py +53 -78
- jentic/apitools/openapi/datamodels/low/v30/external_documentation.py +47 -61
- jentic/apitools/openapi/datamodels/low/v30/oauth_flow.py +54 -123
- jentic/apitools/openapi/datamodels/low/v30/oauth_flows.py +102 -151
- jentic/apitools/openapi/datamodels/low/v30/reference.py +43 -44
- jentic/apitools/openapi/datamodels/low/v30/schema.py +316 -607
- jentic/apitools/openapi/datamodels/low/v30/security_requirement.py +82 -72
- jentic/apitools/openapi/datamodels/low/v30/security_scheme.py +94 -286
- jentic/apitools/openapi/datamodels/low/v30/tag.py +88 -119
- jentic/apitools/openapi/datamodels/low/v30/xml.py +46 -120
- jentic_openapi_datamodels-1.0.0a13.dist-info/METADATA +211 -0
- jentic_openapi_datamodels-1.0.0a13.dist-info/RECORD +23 -0
- jentic/apitools/openapi/datamodels/low/v30/specification_object.py +0 -217
- jentic_openapi_datamodels-1.0.0a11.dist-info/METADATA +0 -52
- jentic_openapi_datamodels-1.0.0a11.dist-info/RECORD +0 -18
- /jentic/apitools/openapi/datamodels/low/{v30/py.typed → __init__.py} +0 -0
- {jentic_openapi_datamodels-1.0.0a11.dist-info → jentic_openapi_datamodels-1.0.0a13.dist-info}/WHEEL +0 -0
- {jentic_openapi_datamodels-1.0.0a11.dist-info → jentic_openapi_datamodels-1.0.0a13.dist-info}/licenses/LICENSE +0 -0
- {jentic_openapi_datamodels-1.0.0a11.dist-info → jentic_openapi_datamodels-1.0.0a13.dist-info}/licenses/NOTICE +0 -0
|
@@ -1,217 +0,0 @@
|
|
|
1
|
-
"""Base class for OpenAPI specification objects."""
|
|
2
|
-
|
|
3
|
-
from abc import ABC
|
|
4
|
-
from collections.abc import Mapping, MutableMapping, Sequence
|
|
5
|
-
from copy import copy
|
|
6
|
-
from typing import Any, Iterator, TypeVar
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
__all__ = ["SpecificationObject"]
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
T = TypeVar("T", bound="SpecificationObject")
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
class SpecificationObject(ABC, MutableMapping[str, Any]):
|
|
16
|
-
"""
|
|
17
|
-
Base class for OpenAPI specification objects.
|
|
18
|
-
|
|
19
|
-
Implements a MutableMapping interface with data stored in __dict__.
|
|
20
|
-
Subclasses become dict-like objects where all attributes are accessible
|
|
21
|
-
via both attribute access (obj.foo) and item access (obj["foo"]).
|
|
22
|
-
|
|
23
|
-
Class Attributes:
|
|
24
|
-
_supports_extensions: Whether this object type supports x-* specification extensions.
|
|
25
|
-
Default is True. Set to False for objects like Security Requirement
|
|
26
|
-
that are pure maps where x-* are regular keys.
|
|
27
|
-
"""
|
|
28
|
-
|
|
29
|
-
_supports_extensions: bool = False
|
|
30
|
-
|
|
31
|
-
def __init__(self, data: Mapping[str, Any] | None = None):
|
|
32
|
-
"""
|
|
33
|
-
Initialize a SpecificationObject.
|
|
34
|
-
|
|
35
|
-
Args:
|
|
36
|
-
data: Optional mapping to initialize the object with
|
|
37
|
-
"""
|
|
38
|
-
if data:
|
|
39
|
-
for key, value in data.items():
|
|
40
|
-
self[key] = self._copy_value(value)
|
|
41
|
-
|
|
42
|
-
# MutableMapping abstract methods
|
|
43
|
-
def __getitem__(self, key: str) -> Any:
|
|
44
|
-
"""Get an item."""
|
|
45
|
-
return self.__dict__[key]
|
|
46
|
-
|
|
47
|
-
def __setitem__(self, key: str, value: Any) -> None:
|
|
48
|
-
"""Set an item."""
|
|
49
|
-
self.__dict__[key] = value
|
|
50
|
-
|
|
51
|
-
def __delitem__(self, key: str) -> None:
|
|
52
|
-
"""Delete an item."""
|
|
53
|
-
del self.__dict__[key]
|
|
54
|
-
|
|
55
|
-
def __iter__(self) -> Iterator[str]:
|
|
56
|
-
"""Iterate over keys."""
|
|
57
|
-
return iter(self.__dict__)
|
|
58
|
-
|
|
59
|
-
def __len__(self) -> int:
|
|
60
|
-
"""Return the number of items."""
|
|
61
|
-
return len(self.__dict__)
|
|
62
|
-
|
|
63
|
-
def __getattr__(self, name: str) -> Any:
|
|
64
|
-
"""
|
|
65
|
-
Get an attribute via attribute access.
|
|
66
|
-
|
|
67
|
-
This allows both dict-style (obj["key"]) and attribute-style (obj.key) access.
|
|
68
|
-
Called only when the attribute is not found through normal lookup.
|
|
69
|
-
"""
|
|
70
|
-
try:
|
|
71
|
-
return self[name]
|
|
72
|
-
except KeyError:
|
|
73
|
-
raise AttributeError(f"'{self.__class__.__name__}' object has no attribute '{name}'")
|
|
74
|
-
|
|
75
|
-
def __setattr__(self, name: str, value: Any) -> None:
|
|
76
|
-
"""
|
|
77
|
-
Set an attribute via attribute access.
|
|
78
|
-
|
|
79
|
-
This allows both dict-style (obj["key"] = val) and attribute-style (obj.key = val).
|
|
80
|
-
For properties and other descriptors, delegates to the descriptor.
|
|
81
|
-
"""
|
|
82
|
-
# Check if this is a data descriptor (property, etc.) on the class
|
|
83
|
-
cls = type(self)
|
|
84
|
-
if hasattr(cls, name):
|
|
85
|
-
attr = getattr(cls, name)
|
|
86
|
-
# If it's a data descriptor (has __set__), use normal attribute setting
|
|
87
|
-
if hasattr(attr, "__set__"):
|
|
88
|
-
object.__setattr__(self, name, value)
|
|
89
|
-
return
|
|
90
|
-
# Otherwise, store in the dict
|
|
91
|
-
self[name] = value
|
|
92
|
-
|
|
93
|
-
def get_extensions(self) -> Mapping[str, Any]:
|
|
94
|
-
"""
|
|
95
|
-
Get specification extensions (x-* fields).
|
|
96
|
-
|
|
97
|
-
Returns a filtered view of fields starting with 'x-'.
|
|
98
|
-
If this object type doesn't support extensions (_supports_extensions=False),
|
|
99
|
-
returns an empty mapping.
|
|
100
|
-
|
|
101
|
-
Returns:
|
|
102
|
-
Mapping of extension fields (keys starting with 'x-')
|
|
103
|
-
"""
|
|
104
|
-
if not type(self)._supports_extensions:
|
|
105
|
-
return {}
|
|
106
|
-
return {k: v for k, v in self.items() if isinstance(k, str) and k.startswith("x-")}
|
|
107
|
-
|
|
108
|
-
def get_fields(self) -> Mapping[str, Any]:
|
|
109
|
-
"""
|
|
110
|
-
Get regular fields (non-extension fields).
|
|
111
|
-
|
|
112
|
-
Returns a filtered view excluding fields starting with 'x-'.
|
|
113
|
-
If this object type doesn't support extensions (_supports_extensions=False),
|
|
114
|
-
returns all fields (x-* are treated as regular fields).
|
|
115
|
-
|
|
116
|
-
Returns:
|
|
117
|
-
Mapping of regular fields (excluding x-* if extensions are supported)
|
|
118
|
-
"""
|
|
119
|
-
if not type(self)._supports_extensions:
|
|
120
|
-
return dict(self)
|
|
121
|
-
return {k: v for k, v in self.items() if isinstance(k, str) and not k.startswith("x-")}
|
|
122
|
-
|
|
123
|
-
@classmethod
|
|
124
|
-
def from_mapping(cls: type[T], data: Mapping[str, Any]) -> T:
|
|
125
|
-
"""
|
|
126
|
-
Create an instance from a mapping.
|
|
127
|
-
|
|
128
|
-
This method does not validate the structure. Use a separate
|
|
129
|
-
validator to ensure the data conforms to the OpenAPI specification.
|
|
130
|
-
|
|
131
|
-
Args:
|
|
132
|
-
data: Mapping to create the object from
|
|
133
|
-
|
|
134
|
-
Returns:
|
|
135
|
-
Instance of the class
|
|
136
|
-
|
|
137
|
-
Raises:
|
|
138
|
-
TypeError: If data is not a Mapping
|
|
139
|
-
"""
|
|
140
|
-
if not isinstance(data, Mapping):
|
|
141
|
-
raise TypeError(f"Expected Mapping, got {type(data).__name__}")
|
|
142
|
-
return cls(data=data)
|
|
143
|
-
|
|
144
|
-
def to_mapping(self) -> dict[str, Any]:
|
|
145
|
-
"""
|
|
146
|
-
Convert to a plain dictionary representation.
|
|
147
|
-
|
|
148
|
-
Recursively converts nested SpecificationObject instances to plain dicts.
|
|
149
|
-
Useful for serialization to JSON/YAML.
|
|
150
|
-
|
|
151
|
-
Returns:
|
|
152
|
-
Plain dictionary with all nested objects converted
|
|
153
|
-
"""
|
|
154
|
-
return {key: self._marshal_value(value) for key, value in MutableMapping.items(self)}
|
|
155
|
-
|
|
156
|
-
@classmethod
|
|
157
|
-
def _marshal_value(cls, value: Any) -> Any:
|
|
158
|
-
"""
|
|
159
|
-
Helper to recursively marshal values to plain types.
|
|
160
|
-
|
|
161
|
-
Uses the actual class (or subclass) to support custom marshaling behavior.
|
|
162
|
-
"""
|
|
163
|
-
if isinstance(value, SpecificationObject):
|
|
164
|
-
return value.to_mapping()
|
|
165
|
-
elif isinstance(value, (list, tuple)):
|
|
166
|
-
return type(value)(cls._marshal_value(item) for item in value)
|
|
167
|
-
elif isinstance(value, dict):
|
|
168
|
-
return {k: cls._marshal_value(v) for k, v in value.items()}
|
|
169
|
-
else:
|
|
170
|
-
return value
|
|
171
|
-
|
|
172
|
-
@staticmethod
|
|
173
|
-
def _copy_value(value: Any) -> Any:
|
|
174
|
-
"""
|
|
175
|
-
Defensive shallow copy for mutable collections.
|
|
176
|
-
|
|
177
|
-
Copies mutable types (list, dict, etc.) to prevent unintended mutation
|
|
178
|
-
of input data. Does not copy SpecificationObjects (already defensive).
|
|
179
|
-
|
|
180
|
-
Args:
|
|
181
|
-
value: Value to potentially copy
|
|
182
|
-
|
|
183
|
-
Returns:
|
|
184
|
-
Copy of value if mutable collection, otherwise value itself
|
|
185
|
-
"""
|
|
186
|
-
|
|
187
|
-
# Don't copy SpecificationObjects (already create new instances)
|
|
188
|
-
if isinstance(value, SpecificationObject):
|
|
189
|
-
return value
|
|
190
|
-
|
|
191
|
-
# Copy mutable collections (dict, list, etc.)
|
|
192
|
-
# Exclude strings (they're Sequence but immutable)
|
|
193
|
-
if isinstance(value, (Mapping, Sequence)) and not isinstance(value, str):
|
|
194
|
-
return copy(value)
|
|
195
|
-
|
|
196
|
-
# Primitives and immutables - no copy needed
|
|
197
|
-
return value
|
|
198
|
-
|
|
199
|
-
def __repr__(self) -> str:
|
|
200
|
-
"""Return a developer-friendly string representation."""
|
|
201
|
-
class_name = self.__class__.__name__
|
|
202
|
-
|
|
203
|
-
# Count regular fields and extensions separately
|
|
204
|
-
extensions = self.get_extensions()
|
|
205
|
-
ext_count = len(extensions)
|
|
206
|
-
field_count = len(self) - ext_count
|
|
207
|
-
|
|
208
|
-
# Build field part
|
|
209
|
-
field_word = "field" if field_count == 1 else "fields"
|
|
210
|
-
parts = [f"{field_count} {field_word}"]
|
|
211
|
-
|
|
212
|
-
# Add extensions part if any
|
|
213
|
-
if ext_count > 0:
|
|
214
|
-
ext_word = "specification extension" if ext_count == 1 else "specification extensions"
|
|
215
|
-
parts.append(f"{ext_count} {ext_word}")
|
|
216
|
-
|
|
217
|
-
return f"<{class_name} {', '.join(parts)}>"
|
|
@@ -1,52 +0,0 @@
|
|
|
1
|
-
Metadata-Version: 2.4
|
|
2
|
-
Name: jentic-openapi-datamodels
|
|
3
|
-
Version: 1.0.0a11
|
|
4
|
-
Summary: Jentic OpenAPI Data Models
|
|
5
|
-
Author: Jentic
|
|
6
|
-
Author-email: Jentic <hello@jentic.com>
|
|
7
|
-
License-Expression: Apache-2.0
|
|
8
|
-
License-File: LICENSE
|
|
9
|
-
License-File: NOTICE
|
|
10
|
-
Requires-Python: >=3.11
|
|
11
|
-
Project-URL: Homepage, https://github.com/jentic/jentic-openapi-tools
|
|
12
|
-
Description-Content-Type: text/markdown
|
|
13
|
-
|
|
14
|
-
# jentic-openapi-datamodels
|
|
15
|
-
|
|
16
|
-
Low-level and high-level data models for OpenAPI specifications.
|
|
17
|
-
|
|
18
|
-
## Overview
|
|
19
|
-
|
|
20
|
-
This package provides data model classes for representing OpenAPI specification objects in Python. The models are designed to be:
|
|
21
|
-
|
|
22
|
-
- **Dict-like**: Implement `MutableMapping` for easy data access
|
|
23
|
-
- **Unvalidated**: Separate parsing from validation for performance
|
|
24
|
-
- **Extensible**: Support OpenAPI specification extensions (x-* fields)
|
|
25
|
-
- **Version-aware**: Currently implements OpenAPI 3.0.x (3.1.x planned)
|
|
26
|
-
|
|
27
|
-
## Structure
|
|
28
|
-
|
|
29
|
-
- `datamodels.low.v30`: Low-level models for OpenAPI 3.0.x
|
|
30
|
-
|
|
31
|
-
## Usage
|
|
32
|
-
|
|
33
|
-
```python
|
|
34
|
-
from jentic.apitools.openapi.datamodels.low.v30 import Schema
|
|
35
|
-
|
|
36
|
-
# Create a schema from raw data
|
|
37
|
-
schema = Schema({
|
|
38
|
-
"type": "object",
|
|
39
|
-
"properties": {
|
|
40
|
-
"name": {"type": "string"}
|
|
41
|
-
}
|
|
42
|
-
})
|
|
43
|
-
|
|
44
|
-
# Access via properties
|
|
45
|
-
print(schema.type) # "object"
|
|
46
|
-
|
|
47
|
-
# Access via dict
|
|
48
|
-
print(schema["type"]) # "object"
|
|
49
|
-
|
|
50
|
-
# Convert back to dict
|
|
51
|
-
data = schema.to_mapping()
|
|
52
|
-
```
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
jentic/apitools/openapi/datamodels/low/v30/__init__.py,sha256=8AUc3qAlQeUD4GZ2JfARDBkLZT8eAjEeYaIWOTprZUM,692
|
|
2
|
-
jentic/apitools/openapi/datamodels/low/v30/discriminator.py,sha256=za2gNfp8k3plfJczMnmNNa-ajlEAxcsbnnYywg3eOuU,2725
|
|
3
|
-
jentic/apitools/openapi/datamodels/low/v30/external_documentation.py,sha256=X_XbyILIQxeIgRk9lHOavv4KmSEwkRn_wQ1ahvMHVMk,2061
|
|
4
|
-
jentic/apitools/openapi/datamodels/low/v30/oauth_flow.py,sha256=TCJBzDvO5sTwWq5v1BCRB8uBLyd4Xc96QvDfg2GAToE,4162
|
|
5
|
-
jentic/apitools/openapi/datamodels/low/v30/oauth_flows.py,sha256=S3ZPwYEUEo57CWZTBHnxGCOXnr-AUHj43jUJByiE7kw,5218
|
|
6
|
-
jentic/apitools/openapi/datamodels/low/v30/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
|
-
jentic/apitools/openapi/datamodels/low/v30/reference.py,sha256=CeyIeFPChvZ37skuraN20jPNUbxJX44BwZ13I2PWj1M,1782
|
|
8
|
-
jentic/apitools/openapi/datamodels/low/v30/schema.py,sha256=39jR2xVfyiMYn9Q1xPNnEs_Tf8mVaWrN6ZdXN-M45oo,19305
|
|
9
|
-
jentic/apitools/openapi/datamodels/low/v30/security_requirement.py,sha256=GTMKm84DMPZeAj9Xd8V1LAv87LxhSo2wOqmX_dVIMsg,3005
|
|
10
|
-
jentic/apitools/openapi/datamodels/low/v30/security_scheme.py,sha256=FW_AJxV-J8D3BFm7jYZVhkUu-fJrZZOpFXPfPHb7rRw,8128
|
|
11
|
-
jentic/apitools/openapi/datamodels/low/v30/specification_object.py,sha256=h5Tk5DH34LBQxIxPjGKuTHUpPMvlunfCQ4LCsO4f31I,7502
|
|
12
|
-
jentic/apitools/openapi/datamodels/low/v30/tag.py,sha256=ka03JPcuJHZyzPhKneDncCHIaiRgbMlBJgj5L3XGH88,3817
|
|
13
|
-
jentic/apitools/openapi/datamodels/low/v30/xml.py,sha256=bMdf80c22nqw7tDVLiwtYyhlwB1BHjE_CdGZPOEbLYY,3434
|
|
14
|
-
jentic_openapi_datamodels-1.0.0a11.dist-info/licenses/LICENSE,sha256=WNHhf_5RCaeuKWyq_K39vmp9F28LxKsB4SpomwSZ2L0,11357
|
|
15
|
-
jentic_openapi_datamodels-1.0.0a11.dist-info/licenses/NOTICE,sha256=pAOGW-rGw9KNc2cuuLWZkfx0GSTV4TicbgBKZSLPMIs,168
|
|
16
|
-
jentic_openapi_datamodels-1.0.0a11.dist-info/WHEEL,sha256=eh7sammvW2TypMMMGKgsM83HyA_3qQ5Lgg3ynoecH3M,79
|
|
17
|
-
jentic_openapi_datamodels-1.0.0a11.dist-info/METADATA,sha256=GXX9b1_46cw2S5LOOT39UALjZEcYRKHhTDAPoW0bSYs,1346
|
|
18
|
-
jentic_openapi_datamodels-1.0.0a11.dist-info/RECORD,,
|
|
File without changes
|
{jentic_openapi_datamodels-1.0.0a11.dist-info → jentic_openapi_datamodels-1.0.0a13.dist-info}/WHEEL
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|