-
Notifications
You must be signed in to change notification settings - Fork 3.1k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
{Core} Add dict transformation for typespec generated SDKs #30339
Conversation
️✔️AzureCLI-FullTest
|
️✔️AzureCLI-BreakingChangeTest
|
Thank you for your contribution! We will review the pull request and get back to you soon. |
@microsoft-github-policy-service rerun |
@microsoft-github-policy-service rerun |
if hasattr(obj, 'as_dict') and not hasattr(obj, '_attribute_map'): | ||
result = {to_camel_case(k): todict(v, post_processor) for k, v in obj.as_dict().items()} | ||
return post_processor(obj, result) if post_processor else result |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A good question from @kairu-ms, what if the REST spec defines a asDict
property?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For now there is no such a property: https://github.com/search?q=repo%3AAzure%2Fazure-rest-api-specs%20asDict&type=code. If there is one in the future, we could rename it.
# This is the only difference with knack.util.todict because for typespec generated SDKs | ||
# The base model stores data in obj.__dict__['_data'] instead of in obj.__dict__ | ||
# We need to call obj.as_dict() to extract data for this kind of model | ||
if hasattr(obj, 'as_dict') and not hasattr(obj, '_attribute_map'): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Another approach to detect if obj
is an SDK model is something similar to
type(obj).__base__.__name__ == 'Model'
str(type(obj).__base__)
returns
"<class 'azure.cli.command_modules.keyvault.vendored_sdks.azure_keyvault_securitydomain._model_base.Model'>"
However, this is also not very reliable as the name Model
may change at any time.
Using isinstance()
is impossible as Model
is defined in each SDK, such as azure.cli.command_modules.keyvault.vendored_sdks.azure_keyvault_securitydomain._model_base.Model
, instead of in azure.core
. There is no single Model
that is the base class of all SDK objects.
Also, using isinstance()
requires importing the Model
class which impairs the performance.
As an example, remove_additional_prop_layer
previously imports Model
with
from msrest.serialization import Model
#13843 changed it to use a try... catch...
strategy:
azure-cli/src/azure-cli-core/azure/cli/core/commands/__init__.py
Lines 899 to 908 in 375b34d
@staticmethod | |
def remove_additional_prop_layer(obj, converted_dic): | |
# Follow EAFP to flatten `additional_properties` auto-generated by SDK | |
# See https://docs.python.org/3/glossary.html#term-eafp | |
try: | |
if 'additionalProperties' in converted_dic and isinstance(obj.additional_properties, dict): | |
converted_dic.update(converted_dic.pop('additionalProperties')) | |
except AttributeError: | |
pass | |
return converted_dic |
Thus, there is no need to import Model
for non-Model
objects.
Related command
Description
SDK models have changed when we move from swagger generated to typespec generated. This cause issues for
knack.util.todict
to do the formatter over command output. We callazure-cli/src/azure-cli-core/azure/cli/core/commands/__init__.py
Line 718 in eb55296
knack
:Currently working with swagger generated models, it runs into
hasattr(obj, '__dict__')
and transformsobj.__dict__.items()
one by one if the item isn't private starting with_
.But now for typespec generated models, a new base model is designed to store all data in
__dict__['_data']
. In such case, we won't get anything by iterating__dict__
as before. The new model provides aas_dict
func instead to transform the model object to dict.Here's an example for swagger generated models(old) and typespec generated models(new)
There are three workarounds:
obj.as_dict()
or get needed attributes by themselves (eg. {Keyvault}az keyvault security-domain
: Migrate security domain to use track2 SDK #30252 (comment))knack.util.todict
to detecthasattr(obj, 'as_dict')
knack.util.todict
inazure.cli.core
to detecthasattr(obj, 'as_dict')
This PR works for the third solution.
Testing Guide
History Notes
[Component Name 1] BREAKING CHANGE:
az command a
: Make some customer-facing breaking change[Component Name 2]
az command b
: Add some customer-facing featureThis checklist is used to make sure that common guidelines for a pull request are followed.
The PR title and description has followed the guideline in Submitting Pull Requests.
I adhere to the Command Guidelines.
I adhere to the Error Handling Guidelines.