...
This commit is contained in:
98
_archive/openrpc/model/openrpc_spec.py
Normal file
98
_archive/openrpc/model/openrpc_spec.py
Normal file
@@ -0,0 +1,98 @@
|
||||
from typing import Any, Dict, List, Optional, Union
|
||||
|
||||
from heroserver.openrpc.model.common import (
|
||||
ContentDescriptorObject,
|
||||
ExternalDocumentationObject,
|
||||
ReferenceObject,
|
||||
SchemaObject,
|
||||
)
|
||||
from heroserver.openrpc.model.components import ComponentsObject
|
||||
from heroserver.openrpc.model.info import InfoObject
|
||||
from heroserver.openrpc.model.methods import MethodObject
|
||||
from heroserver.openrpc.model.server import ServerObject
|
||||
|
||||
ROOT_OBJ_DEF = "!!define.root_object"
|
||||
|
||||
|
||||
class OpenRPCSpec:
|
||||
def __init__(
|
||||
self,
|
||||
openrpc: str,
|
||||
info: InfoObject,
|
||||
methods: List[MethodObject],
|
||||
servers: Optional[List[ServerObject]] = None,
|
||||
components: Optional[ComponentsObject] = None,
|
||||
externalDocs: Optional[ExternalDocumentationObject] = None,
|
||||
spec_extensions: Optional[Dict[str, Any]] = None,
|
||||
):
|
||||
self.openrpc = openrpc
|
||||
self.info = info
|
||||
self.servers = servers
|
||||
self.methods = methods
|
||||
self.components = components
|
||||
self.externalDocs = externalDocs
|
||||
self.spec_extensions = spec_extensions
|
||||
|
||||
@classmethod
|
||||
def load(cls, data: Dict[str, Any]) -> "OpenRPCSpec":
|
||||
return cls(
|
||||
openrpc=data["openrpc"],
|
||||
info=InfoObject.load(data["info"]),
|
||||
servers=([ServerObject.load(item) for item in data.get("servers", [])] if "servers" in data else None),
|
||||
methods=[MethodObject.load(item) for item in data["methods"]],
|
||||
components=(ComponentsObject.load(data["components"]) if "components" in data else None),
|
||||
externalDocs=(ExternalDocumentationObject.load(data["externalDocs"]) if "externalDocs" in data else None),
|
||||
spec_extensions=data.get("spec_extensions"),
|
||||
)
|
||||
|
||||
def ref_to_schema(self, ref: str) -> Union[SchemaObject, ContentDescriptorObject]:
|
||||
if not ref.startswith("#/"):
|
||||
raise Exception(f"invalid ref: {ref}")
|
||||
|
||||
l = ref.split("/")[1:]
|
||||
obj = self
|
||||
for item in l:
|
||||
# TODO: find root cause of RO_
|
||||
if item.startswith("RO_"):
|
||||
item = item[3:]
|
||||
|
||||
if isinstance(obj, Dict):
|
||||
print("obj contents: ", obj)
|
||||
print("Trying to access key: ", item)
|
||||
obj = obj[item]
|
||||
else:
|
||||
obj = obj.__dict__[item]
|
||||
|
||||
if not isinstance(obj, SchemaObject) and not isinstance(obj, ContentDescriptorObject):
|
||||
raise Exception(f"ref to unsupported type: {ref}")
|
||||
|
||||
return obj
|
||||
|
||||
def get_root_objects(self) -> Dict[str, SchemaObject]:
|
||||
if not self.components:
|
||||
return {}
|
||||
|
||||
objs: Dict[str, SchemaObject] = {}
|
||||
base_ref = ["components", "schemas"]
|
||||
for name, scheme in self.components.schemas.items():
|
||||
if scheme.xtags and "rootobject" in scheme.xtags:
|
||||
objs["/".join(base_ref + [name.lower()])] = scheme
|
||||
|
||||
return objs
|
||||
|
||||
def set_root_objects(self, refs: List[str]):
|
||||
for ref in refs:
|
||||
obj = self.ref_to_schema(ref)
|
||||
if isinstance(obj, ContentDescriptorObject):
|
||||
obj = obj.schema
|
||||
if isinstance(obj, ReferenceObject):
|
||||
self.set_root_objects([obj.ref])
|
||||
continue
|
||||
|
||||
if not obj.description:
|
||||
obj.description = ROOT_OBJ_DEF
|
||||
else:
|
||||
obj.description += f";{ROOT_OBJ_DEF}"
|
||||
|
||||
|
||||
# Note that classes that refer to themselves or each other are handled using string literals in annotations to avoid forward reference issues. Python 3.7+ supports this feature with the use of 'from __future__ import annotations'.
|
Reference in New Issue
Block a user