Skip to content

Commit 2739e0d

Browse files
authored
update for new dpg model (#34849)
1 parent e65220d commit 2739e0d

File tree

1 file changed

+65
-14
lines changed

1 file changed

+65
-14
lines changed

tools/azure-sdk-tools/packaging_tools/code_report.py

Lines changed: 65 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
import types
1212
import tempfile
1313
import re
14-
from typing import Dict, Any, Optional, List
14+
from typing import Dict, Any, Optional, List, ForwardRef
1515

1616
# Because I'm subprocessing myself, I need to do weird thing as import.
1717
try:
@@ -41,6 +41,10 @@ def create_empty_report():
4141
return {"client": {}, "models": {"enums": {}, "exceptions": {}, "models": {}}, "operations": {}}
4242

4343

44+
def is_model(model_cls: object, is_new_model: bool) -> bool:
45+
return hasattr(model_cls, "_is_model" if is_new_model else "_attribute_map")
46+
47+
4448
def create_report(module_name: str) -> Dict[str, Any]:
4549
module_to_generate = importlib.import_module(module_name)
4650
client_name = getattr(module_to_generate, "__all__")
@@ -54,14 +58,15 @@ def create_report(module_name: str) -> Dict[str, Any]:
5458

5559
# Look for models first
5660
model_names = [model_name for model_name in dir(module_to_generate.models) if model_name[0].isupper()]
61+
is_new_model = hasattr(module_to_generate, "_model_base")
5762
for model_name in model_names:
5863
model_cls = getattr(module_to_generate.models, model_name)
59-
if hasattr(model_cls, "_attribute_map"):
60-
report["models"]["models"][model_name] = create_model_report(model_cls)
64+
if is_model(model_cls, is_new_model):
65+
report["models"]["models"][model_name] = create_model_report(model_cls, is_new_model)
6166
elif issubclass(model_cls, Exception): # If not, might be an exception
62-
report["models"]["exceptions"][model_name] = create_model_report(model_cls)
67+
report["models"]["exceptions"][model_name] = create_model_report(model_cls, is_new_model)
6368
else:
64-
report["models"]["enums"][model_name] = create_model_report(model_cls)
69+
report["models"]["enums"][model_name] = create_model_report(model_cls, is_new_model)
6570
# Look for operation groups
6671
try:
6772
operations_classes = [op_name for op_name in dir(module_to_generate.operations) if op_name[0].isupper()]
@@ -83,22 +88,69 @@ def create_report(module_name: str) -> Dict[str, Any]:
8388
return report
8489

8590

86-
def create_model_report(model_cls):
91+
def get_attr_map(model_cls: object, is_new_model: bool) -> Dict[str, Any]:
92+
if is_new_model:
93+
return getattr(model_cls(), "_attr_to_rest_field")
94+
return getattr(model_cls, "_attribute_map")
95+
96+
97+
def get_type_annotation(model_cls: object, attribute: str) -> List[str]:
98+
# make sure to get the annotations from the base class
99+
mros = model_cls.__mro__[:-3][::-1]
100+
annotations = {
101+
k: v
102+
for mro_class in mros
103+
if hasattr(mro_class, "__annotations__") # pylint: disable=no-member
104+
for k, v in mro_class.__annotations__.items() # pylint: disable=no-member
105+
}
106+
attr_type = annotations.get(attribute)
107+
type_list = getattr(attr_type, "__args__", [attr_type])
108+
return sorted(
109+
[
110+
item.__forward_arg__.replace("_models.", "")
111+
if isinstance(item, ForwardRef)
112+
else getattr(item, "__name__", str(item))
113+
for item in type_list
114+
]
115+
)
116+
117+
118+
def get_type(model_cls: object, attribute: str, conf: Dict[str, Any], is_new_model: bool) -> str:
119+
if is_new_model:
120+
return " or ".join(filter(lambda x: x != "NoneType", get_type_annotation(model_cls, attribute)))
121+
return conf["type"]
122+
123+
124+
def _get_validation(model_cls: object, attribute: str) -> Dict[str, Any]:
125+
return getattr(model_cls, "_validation", {}).get(attribute, {})
126+
127+
128+
def is_required(model_cls: object, attribute: str, is_new_model: bool) -> bool:
129+
if is_new_model:
130+
return "NoneType" not in get_type_annotation(model_cls, attribute)
131+
return _get_validation(model_cls, attribute).get("required", False)
132+
133+
134+
def is_readonly(model_cls: object, attribute: str, is_new_model: bool) -> bool:
135+
if is_new_model:
136+
return getattr(getattr(model_cls, "_attr_to_rest_field").get(attribute), "_visibility") == ["read"]
137+
return _get_validation(model_cls, attribute).get("readonly", False)
138+
139+
140+
def create_model_report(model_cls: object, is_new_model: bool):
87141
result = {
88142
"name": model_cls.__name__,
89143
}
90144
# If _attribute_map, it's a model
91-
if hasattr(model_cls, "_attribute_map"):
145+
if is_model(model_cls, is_new_model):
92146
result["type"] = "Model"
93-
for attribute, conf in model_cls._attribute_map.items():
94-
attribute_validation = getattr(model_cls, "_validation", {}).get(attribute, {})
95-
147+
for attribute, conf in get_attr_map(model_cls, is_new_model).items():
96148
result.setdefault("parameters", {})[attribute] = {
97149
"name": attribute,
98150
"properties": {
99-
"type": conf["type"],
100-
"required": attribute_validation.get("required", False),
101-
"readonly": attribute_validation.get("readonly", False),
151+
"type": get_type(model_cls, attribute, conf, is_new_model),
152+
"required": is_required(model_cls, attribute, is_new_model),
153+
"readonly": is_readonly(model_cls, attribute, is_new_model),
102154
},
103155
}
104156
elif issubclass(model_cls, Exception): # If not, might be an exception
@@ -190,7 +242,6 @@ def main(
190242
metadata_path: Optional[str] = None,
191243
last_pypi_stable: bool = False,
192244
):
193-
194245
output_msg = output if output else "default folder"
195246
_LOGGER.info(
196247
f"Building code report of {input_parameter} for version {version} in {output_msg} ({no_venv}/{pypi}/{last_pypi})"

0 commit comments

Comments
 (0)