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.
Files changed (26) hide show
  1. jentic/apitools/openapi/datamodels/low/context.py +21 -0
  2. jentic/apitools/openapi/datamodels/low/extractors.py +126 -0
  3. jentic/apitools/openapi/datamodels/low/fields.py +45 -0
  4. jentic/apitools/openapi/datamodels/low/model_builder.py +113 -0
  5. jentic/apitools/openapi/datamodels/low/py.typed +0 -0
  6. jentic/apitools/openapi/datamodels/low/sources.py +89 -0
  7. jentic/apitools/openapi/datamodels/low/v30/__init__.py +0 -28
  8. jentic/apitools/openapi/datamodels/low/v30/discriminator.py +53 -78
  9. jentic/apitools/openapi/datamodels/low/v30/external_documentation.py +47 -61
  10. jentic/apitools/openapi/datamodels/low/v30/oauth_flow.py +54 -123
  11. jentic/apitools/openapi/datamodels/low/v30/oauth_flows.py +102 -151
  12. jentic/apitools/openapi/datamodels/low/v30/reference.py +43 -44
  13. jentic/apitools/openapi/datamodels/low/v30/schema.py +316 -607
  14. jentic/apitools/openapi/datamodels/low/v30/security_requirement.py +82 -72
  15. jentic/apitools/openapi/datamodels/low/v30/security_scheme.py +94 -286
  16. jentic/apitools/openapi/datamodels/low/v30/tag.py +88 -119
  17. jentic/apitools/openapi/datamodels/low/v30/xml.py +46 -120
  18. jentic_openapi_datamodels-1.0.0a13.dist-info/METADATA +211 -0
  19. jentic_openapi_datamodels-1.0.0a13.dist-info/RECORD +23 -0
  20. jentic/apitools/openapi/datamodels/low/v30/specification_object.py +0 -217
  21. jentic_openapi_datamodels-1.0.0a11.dist-info/METADATA +0 -52
  22. jentic_openapi_datamodels-1.0.0a11.dist-info/RECORD +0 -18
  23. /jentic/apitools/openapi/datamodels/low/{v30/py.typed → __init__.py} +0 -0
  24. {jentic_openapi_datamodels-1.0.0a11.dist-info → jentic_openapi_datamodels-1.0.0a13.dist-info}/WHEEL +0 -0
  25. {jentic_openapi_datamodels-1.0.0a11.dist-info → jentic_openapi_datamodels-1.0.0a13.dist-info}/licenses/LICENSE +0 -0
  26. {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,,