-
Notifications
You must be signed in to change notification settings - Fork 3.3k
[Storage] Fix #14054: 'NoneType' object has no attribute '__name__' #16993
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
Conversation
|
Storage |
|
@evelyn-ys Good PR description, I like it. |
| 'block': lambda ctx: get_sdk(ctx, ResourceType.DATA_STORAGE, 'BlockBlobService', mod='blob', checked=False), | ||
| 'page': lambda ctx: get_sdk(ctx, ResourceType.DATA_STORAGE, 'PageBlobService', mod='blob', checked=False), | ||
| 'append': lambda ctx: get_sdk(ctx, ResourceType.DATA_STORAGE, 'AppendBlobService', mod='blob', checked=False) |
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.
I would really prefer to make checked=False the default for get_sdk, otherwise it is not universal and 'NoneType' object has no attribute '__name__' will continue to happen in other command modules. (#15776 (comment))
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.
I already made checked=False the default for _get_attr in #14690
azure-cli/src/azure-cli-core/azure/cli/core/profiles/_shared.py
Lines 534 to 535 in 301ba06
| def _get_attr(sdk_path, mod_attr_path, checked=False): | |
| """If `checked` is True, None is returned in case of import failure.""" |
but it only applies to get_client_class which calls _get_attr without checked:
azure-cli/src/azure-cli-core/azure/cli/core/profiles/_shared.py
Lines 552 to 553 in 301ba06
| def get_client_class(resource_type): | |
| return _get_attr(resource_type.import_prefix, '#' + resource_type.client_name) |
get_versioned_sdk will default checked to True via
azure-cli/src/azure-cli-core/azure/cli/core/profiles/_shared.py
Lines 573 to 574 in 301ba06
| def get_versioned_sdk(api_profile, resource_type, *attr_args, **kwargs): | |
| checked = kwargs.get('checked', True) |
| loaded_obj = _get_attr(sdk_path, mod_attr_path, checked) |
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.
Personally I totally agree with you. It's just I was afraid of making great changes to all modules. Should we discuss whether to change the behavior or not with all module owners?
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.
We can go ahead and make the change. If CI passes, we are fine.
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.
Python's import statement raises ImportError in case of non-existing module.
Also, checking whether the result is None is against the look before you leap practice.
get_sdk to raise ImportError when sdk not found
|
|
||
| def get_versioned_sdk(api_profile, resource_type, *attr_args, **kwargs): | ||
| checked = kwargs.get('checked', True) | ||
| checked = kwargs.get('checked', None) |
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.
This still overwrites the default checked=False of _get_attr. It is coincident that False and None have the same effect.
If the default is checked=True, it will be overwritten as None.
|
|
||
| def get_versioned_sdk(api_profile, resource_type, *attr_args, **kwargs): | ||
| checked = kwargs.get('checked', True) | ||
| checked = kwargs.get('checked', None) |
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.
The current implementation of get_models is indeed a design flaw that can't distinguish
- expected import failure caused by incompatible SDK profile (API version)
- corrupted SDK installation
When the SDK installation is corrupted, this will trigger unclear error message like #14054 in many places:
| c.argument('encryption_type', min_api='2019-07-01', arg_type=get_enum_type(self.get_models('EncryptionType')), |
azure-cli/src/azure-cli/azure/cli/command_modules/vm/custom.py
Lines 301 to 302 in 0804c75
| Disk, CreationData, DiskCreateOption, Encryption = cmd.get_models( | |
| 'Disk', 'CreationData', 'DiskCreateOption', 'Encryption') |
A better pattern is to
- call
get_modelslazily only whenmin_apiormax_apiis satisfied - error out if import failure happens
This requires large amount of effort inspecting the whole code base.
9fc1d46 to
bbe3048
Compare
get_sdk to raise ImportError when sdk not found
Description
Fix #14054
In previous design, if
get_sdkcan't find the dependency, the default behavior will returnNone. This will cause follow-up questions ifNoneis not handled.This PR exposes the real exception while getting sdk, which is
ModuleNotFoundErrorTesting Guide
Rename azure.multiapi.storage package(to azure.multiapi.storagev1 for example) to reproduce issue AttributeError: 'NoneType' object has no attribute '__name__' #14054
Run
az storage container create -n testingHistory 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 feature.
This 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.