Skip to content
This repository has been archived by the owner on Apr 10, 2024. It is now read-only.

Commit

Permalink
Merge pull request #8 from gtema/identity
Browse files Browse the repository at this point in the history
Identity updates
  • Loading branch information
gtema authored Jan 24, 2024
2 parents 69c3f6f + ef7bd4c commit a85f812
Show file tree
Hide file tree
Showing 36 changed files with 1,034 additions and 538 deletions.
3 changes: 1 addition & 2 deletions codegenerator/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def _deep_merge(

class BasePrimitiveType(BaseModel):
lifetimes: set[str] | None = None
imports: set[str] = set()
builder_macros: set[str] = set([])


Expand All @@ -67,7 +66,7 @@ class BaseCompoundType(BaseModel):
def get_openapi_spec(path: str | Path):
"""Load OpenAPI spec from a file"""
with open(path, "r") as fp:
spec_data = jsonref.replace_refs(yaml.safe_load(fp))
spec_data = jsonref.replace_refs(yaml.safe_load(fp), proxies=False)
return Spec.from_dict(spec_data)


Expand Down
14 changes: 12 additions & 2 deletions codegenerator/common/rust.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ class Boolean(BasePrimitiveType):
"""Basic Boolean"""

type_hint: str = "bool"
imports: set[str] = set([])
clap_macros: set[str] = set(["action=clap::ArgAction::Set"])
original_data_type: BaseCompoundType | BaseCompoundType | None = None

Expand All @@ -36,6 +37,7 @@ def get_sample(self):

class Number(BasePrimitiveType):
format: str | None = None
imports: set[str] = set([])
clap_macros: set[str] = set()
original_data_type: BaseCompoundType | BaseCompoundType | None = None

Expand All @@ -54,6 +56,7 @@ def get_sample(self):

class Integer(BasePrimitiveType):
format: str | None = None
imports: set[str] = set([])
clap_macros: set[str] = set()
original_data_type: BaseCompoundType | BaseCompoundType | None = None

Expand Down Expand Up @@ -81,9 +84,16 @@ def get_sample(self):


class String(BasePrimitiveType):
format: str | None = None
type_hint: str = "String"
builder_macros: set[str] = set(["setter(into)"])

# NOTE(gtema): it is not possible to override field with computed
# property, thus it must be a property here
@property
def imports(self) -> set[str]:
return set([])

def get_sample(self):
return '"foo"'

Expand Down Expand Up @@ -271,7 +281,7 @@ class EnumKind(BaseModel):
@property
def type_hint(self):
if isinstance(self.data_type, Struct):
return self.data_type.name
return self.data_type.name + self.data_type.static_lifetime
return self.data_type.type_hint

@property
Expand All @@ -283,6 +293,7 @@ class Enum(BaseCompoundType):
base_type: str = "enum"
kinds: dict[str, EnumKind]
literals: list[Any] | None = None
original_data_type: BaseCompoundType | BaseCompoundType | None = None
_kind_type_class = EnumKind

@property
Expand Down Expand Up @@ -489,7 +500,6 @@ def convert_model(
xtyp = self.primitive_type_mapping.get(type_model.__class__)
if not xtyp:
raise RuntimeError("No mapping for %s" % type_model)
# logging.debug("Returning %s for %s", typ, type_model.__class__)
return xtyp(**type_model.model_dump())

# Composite/Compound type
Expand Down
6 changes: 5 additions & 1 deletion codegenerator/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -131,6 +131,10 @@ def generate(
operation_key = "download"
else:
raise NotImplementedError
elif path == "/v3/users/{user_id}/password":
if method == "post":
operation_key = "update"

elif response_schema and (
method == "get"
and (
Expand Down Expand Up @@ -433,7 +437,7 @@ def generate(
list_mod="list_detailed" if list_detailed_op else "list",
)
res_data.operations["find"] = OperationModel(
operation_id="fake",
operation_id=list_op_.operation_id,
operation_type="find",
targets={"rust-sdk": sdk_params},
)
Expand Down
92 changes: 81 additions & 11 deletions codegenerator/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
# under the License.
#
import copy
import hashlib
import json
import logging
from typing import Any
from typing import Type
Expand All @@ -21,15 +23,24 @@
from codegenerator import common


def dicthash_(data: dict[str, Any]) -> str:
"""Calculate hash of the dictionary"""
dh = hashlib.md5()
encoded = json.dumps(data, sort_keys=True).encode()
dh.update(encoded)
return dh.hexdigest()


class Reference(BaseModel):
"""Reference of the complex type to the occurence instance"""

#: Name of the object that uses the type under reference
name: str
type: Type | None = None
hash_: str | None = None

def __hash__(self):
return hash((self.name, self.type))
return hash((self.name, self.type, self.hash_))


class PrimitiveType(BaseModel):
Expand Down Expand Up @@ -176,33 +187,51 @@ def parse_schema(
schema,
results: list[ADT],
name: str | None = None,
parent_name: str | None = None,
min_ver: str | None = None,
max_ver: str | None = None,
ignore_read_only: bool | None = False,
) -> PrimitiveType | ADT:
type_ = schema.get("type")
if "oneOf" in schema:
return self.parse_oneOf(
schema, results, name=name, ignore_read_only=ignore_read_only
schema,
results,
name=name,
parent_name=parent_name,
ignore_read_only=ignore_read_only,
)
elif "enum" in schema:
return self.parse_enum(
schema, results, name=name, ignore_read_only=ignore_read_only
schema,
results,
name=name,
parent_name=parent_name,
ignore_read_only=ignore_read_only,
)
elif "allOf" in schema:
return self.parse_allOf(
schema, results, name=name, ignore_read_only=ignore_read_only
schema,
results,
name=name,
parent_name=parent_name,
ignore_read_only=ignore_read_only,
)
elif isinstance(type_, list):
return self.parse_typelist(
schema, results, name=name, ignore_read_only=ignore_read_only
schema,
results,
name=name,
parent_name=parent_name,
ignore_read_only=ignore_read_only,
)
elif isinstance(type_, str):
if type_ == "object":
return self.parse_object(
schema,
results,
name=name,
parent_name=parent_name,
min_ver=min_ver,
max_ver=max_ver,
ignore_read_only=ignore_read_only,
Expand All @@ -212,6 +241,7 @@ def parse_schema(
schema,
results,
name=name,
parent_name=parent_name,
ignore_read_only=ignore_read_only,
)
elif type_ == "string":
Expand Down Expand Up @@ -239,6 +269,7 @@ def parse_schema(
schema,
results,
name=name,
parent_name=parent_name,
min_ver=min_ver,
max_ver=max_ver,
ignore_read_only=ignore_read_only,
Expand All @@ -254,6 +285,7 @@ def parse_object(
schema,
results: list[ADT],
name: str | None = None,
parent_name: str | None = None,
min_ver: str | None = None,
max_ver: str | None = None,
ignore_read_only: bool | None = False,
Expand All @@ -277,6 +309,7 @@ def parse_object(
v,
results,
name=k,
parent_name=name,
min_ver=min_ver,
max_ver=max_ver,
ignore_read_only=ignore_read_only,
Expand Down Expand Up @@ -346,10 +379,32 @@ def parse_object(
raise RuntimeError("Object %s is not supported", schema)

if name:
obj.reference = Reference(name=name, type=obj.__class__)
obj.reference = Reference(
name=name, type=obj.__class__, hash_=dicthash_(schema)
)

if obj:
obj.description = schema.get("description")
if (
obj.reference
and f"{obj.reference.name}{obj.reference.type}"
in [
f"{x.reference.name}{x.reference.type}"
for x in results
if x.reference
]
):
# Structure with the same name is already present. Prefix the
# new one with the parent name
if parent_name and name:
new_name = parent_name + "_" + name

if Reference(name=new_name, type=obj.reference.type) in [
x.reference for x in results
]:
raise NotImplementedError
else:
obj.reference.name = new_name
results.append(obj)
return obj

Expand All @@ -358,6 +413,7 @@ def parse_oneOf(
schema,
results: list[ADT],
name: str | None = None,
parent_name: str | None = None,
ignore_read_only: bool | None = False,
):
obj = OneOfType()
Expand All @@ -379,7 +435,9 @@ def parse_oneOf(
else:
obj.kinds.append(kind_type)
if name:
obj.reference = Reference(name=name, type=obj.__class__)
obj.reference = Reference(
name=name, type=obj.__class__, hash_=dicthash_(schema)
)
results.append(obj)
return obj

Expand All @@ -388,6 +446,7 @@ def parse_typelist(
schema,
results: list[ADT],
name: str | None = None,
parent_name: str | None = None,
ignore_read_only: bool | None = False,
):
obj = OneOfType()
Expand All @@ -406,7 +465,9 @@ def parse_typelist(
else:
obj.kinds.append(kind_type)
if name:
obj.reference = Reference(name=name, type=obj.__class__)
obj.reference = Reference(
name=name, type=obj.__class__, hash_=dicthash_(schema)
)
results.append(obj)
return obj

Expand All @@ -415,6 +476,7 @@ def parse_array(
schema,
results: list[ADT],
name: str | None = None,
parent_name: str | None = None,
ignore_read_only: bool | None = False,
):
# todo: decide whether some constraints can be under items
Expand All @@ -430,7 +492,9 @@ def parse_array(
else:
obj = Array(item_type=item_type)
if name:
obj.reference = Reference(name=name, type=obj.__class__)
obj.reference = Reference(
name=name, type=obj.__class__, hash_=dicthash_(schema)
)
results.append(obj)
return obj

Expand All @@ -439,6 +503,7 @@ def parse_enum(
schema,
results: list[ADT],
name: str | None = None,
parent_name: str | None = None,
ignore_read_only: bool | None = False,
):
# todo: decide whether some constraints can be under items
Expand All @@ -454,7 +519,9 @@ def parse_enum(
obj.base_types.append(PrimitiveBoolean)

if name:
obj.reference = Reference(name=name, type=obj.__class__)
obj.reference = Reference(
name=name, type=obj.__class__, hash_=dicthash_(schema)
)
results.append(obj)
return obj

Expand All @@ -463,6 +530,7 @@ def parse_allOf(
schema,
results: list[ADT],
name: str | None = None,
parent_name: str | None = None,
ignore_read_only: bool | None = False,
):
sch = copy.deepcopy(schema)
Expand Down Expand Up @@ -549,7 +617,9 @@ def parse_parameter(self, schema) -> RequestParameter:

if isinstance(dt, ADT):
# Set reference into the data_type so that it doesn't mess with main body types
dt.reference = Reference(name=param_name, type=RequestParameter)
dt.reference = Reference(
name=param_name, type=RequestParameter, hash_=dicthash_(schema)
)

if dt:
return RequestParameter(
Expand Down
2 changes: 1 addition & 1 deletion codegenerator/openapi/glance.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,7 +159,7 @@
"in": "query",
"name": "tag",
"description": LiteralScalarString(
"Filters the response by the specified tag value. May be repeated, but keep in mind that youre making a conjunctive query, so only images containing all the tags specified will appear in the response."
"Filters the response by the specified tag value. May be repeated, but keep in mind that you're making a conjunctive query, so only images containing all the tags specified will appear in the response."
),
"schema": {"type": "array", "items": {"type": "string"}},
"style": "form",
Expand Down
Loading

0 comments on commit a85f812

Please sign in to comment.