Script 'mail_helper' called by obssrc Hello community, here is the log from the commit of package azure-cli-core for openSUSE:Factory checked in at 2023-01-11 14:34:42 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/azure-cli-core (Old) and /work/SRC/openSUSE:Factory/.azure-cli-core.new.32243 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "azure-cli-core" Wed Jan 11 14:34:42 2023 rev:47 rq:1057630 version:2.44.0 Changes: -------- --- /work/SRC/openSUSE:Factory/azure-cli-core/azure-cli-core.changes 2022-12-07 17:36:10.872938692 +0100 +++ /work/SRC/openSUSE:Factory/.azure-cli-core.new.32243/azure-cli-core.changes 2023-01-11 14:36:24.581690560 +0100 @@ -1,0 +2,12 @@ +Tue Jan 10 09:38:44 UTC 2023 - John Paul Adrian Glaubitz <[email protected]> + +- New upstream release + + Version 2.44.0 + + For detailed information about changes see the + HISTORY.rst file provided with this package +- Drop patches for issues fixed upstream + + acc_update-argcomplete.patch +- Relax version dependency for python-packaging + in BuildRequires (bsc#1206869) + +------------------------------------------------------------------- Old: ---- acc_update-argcomplete.patch azure-cli-core-2.43.0.tar.gz New: ---- azure-cli-core-2.44.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ azure-cli-core.spec ++++++ --- /var/tmp/diff_new_pack.9CRXR5/_old 2023-01-11 14:36:25.005692957 +0100 +++ /var/tmp/diff_new_pack.9CRXR5/_new 2023-01-11 14:36:25.009692979 +0100 @@ -1,7 +1,7 @@ # # spec file for package azure-cli-core # -# Copyright (c) 2022 SUSE LLC +# Copyright (c) 2023 SUSE LLC # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -17,7 +17,7 @@ Name: azure-cli-core -Version: 2.43.0 +Version: 2.44.0 Release: 0 Summary: Microsoft Azure CLI Core Module License: MIT @@ -26,7 +26,6 @@ Source: https://files.pythonhosted.org/packages/source/a/azure-cli-core/azure-cli-core-%{version}.tar.gz Source1: LICENSE.txt Patch0: acc_disable-update-check.patch -Patch1: acc_update-argcomplete.patch BuildRequires: azure-cli-nspkg BuildRequires: fdupes BuildRequires: python-rpm-macros @@ -52,7 +51,7 @@ Requires: python3-msal-extensions >= 1.0.0 Requires: python3-msrestazure < 0.7.0 Requires: python3-msrestazure >= 0.6.4 -Requires: python3-packaging < 22.0 +Requires: python3-packaging < 24.0 Requires: python3-packaging >= 20.9 Requires: python3-paramiko < 3.0.0 Requires: python3-paramiko >= 2.0.8 @@ -77,7 +76,6 @@ %prep %setup -q -n azure-cli-core-%{version} %patch0 -p1 -%patch1 -p1 %build install -m 644 %{SOURCE1} %{_builddir}/azure-cli-core-%{version} ++++++ azure-cli-core-2.43.0.tar.gz -> azure-cli-core-2.44.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/HISTORY.rst new/azure-cli-core-2.44.0/HISTORY.rst --- old/azure-cli-core-2.43.0/HISTORY.rst 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/HISTORY.rst 2023-01-06 05:23:51.000000000 +0100 @@ -3,6 +3,11 @@ Release History =============== +2.44.0 +++++++ +* `aaz`: Support subresource selector (#24827) +* `aaz`: Improve generic update arguments to consist with previous behaviors (#24960) + 2.43.0 ++++++ * `aaz`: Fix `has_value` function for list, dict and object arg types (#24625) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/PKG-INFO new/azure-cli-core-2.44.0/PKG-INFO --- old/azure-cli-core-2.43.0/PKG-INFO 2022-12-02 07:07:41.304211400 +0100 +++ new/azure-cli-core-2.44.0/PKG-INFO 2023-01-06 05:24:14.887853000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: azure-cli-core -Version: 2.43.0 +Version: 2.44.0 Summary: Microsoft Azure Command-Line Tools Core Module Home-page: https://github.com/Azure/azure-cli Author: Microsoft Corporation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/__init__.py new/azure-cli-core-2.44.0/azure/cli/core/__init__.py --- old/azure-cli-core-2.43.0/azure/cli/core/__init__.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/__init__.py 2023-01-06 05:23:51.000000000 +0100 @@ -4,7 +4,7 @@ # -------------------------------------------------------------------------------------------- # pylint: disable=line-too-long -__version__ = "2.43.0" +__version__ = "2.44.0" import os import sys diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/__init__.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/__init__.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/__init__.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/__init__.py 2023-01-06 05:23:51.000000000 +0100 @@ -9,7 +9,7 @@ Atomic commands can be generated from rest api by using aaz-dev tool. """ -from ._arg import has_value, AAZArgumentsSchema, AAZArgEnum, AAZStrArg, AAZIntArg, AAZObjectArg, AAZDictArg, \ +from ._arg import AAZArgumentsSchema, AAZArgEnum, AAZStrArg, AAZIntArg, AAZObjectArg, AAZDictArg, \ AAZFreeFormDictArg, AAZFloatArg, AAZBaseArg, AAZBoolArg, AAZListArg, AAZResourceGroupNameArg, \ AAZResourceLocationArg, AAZResourceIdArg, AAZSubscriptionIdArg, AAZUuidArg, AAZDateArg, AAZTimeArg, \ AAZDateTimeArg, AAZDurationArg @@ -17,9 +17,11 @@ AAZDictArgFormat, AAZFreeFormDictArgFormat, AAZListArgFormat, AAZResourceLocationArgFormat, \ AAZResourceIdArgFormat, AAZSubscriptionIdArgFormat, AAZUuidFormat, AAZDateFormat, AAZTimeFormat, \ AAZDateTimeFormat, AAZDurationFormat -from ._base import AAZValuePatch, AAZUndefined +from ._base import has_value, AAZValuePatch, AAZUndefined from ._command import AAZCommand, AAZWaitCommand, AAZCommandGroup, \ register_callback, register_command, register_command_group, load_aaz_command_table from ._field_type import AAZIntType, AAZFloatType, AAZStrType, AAZBoolType, AAZDictType, AAZFreeFormDictType, \ AAZListType, AAZObjectType -from ._operation import AAZHttpOperation, AAZJsonInstanceUpdateOperation, AAZGenericInstanceUpdateOperation +from ._operation import AAZHttpOperation, AAZJsonInstanceUpdateOperation, AAZGenericInstanceUpdateOperation, \ + AAZJsonInstanceDeleteOperation, AAZJsonInstanceCreateOperation +from ._selector import AAZJsonSelector diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/_arg.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/_arg.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/_arg.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/_arg.py 2023-01-06 05:23:51.000000000 +0100 @@ -13,7 +13,7 @@ from ._arg_action import AAZSimpleTypeArgAction, AAZObjectArgAction, AAZDictArgAction, AAZFreeFormDictArgAction, \ AAZListArgAction, AAZGenericUpdateAction, AAZGenericUpdateForceStringAction -from ._base import AAZBaseType, AAZUndefined, AAZBaseValue +from ._base import AAZBaseType, AAZUndefined from ._field_type import AAZObjectType, AAZStrType, AAZIntType, AAZBoolType, AAZFloatType, AAZListType, AAZDictType, \ AAZSimpleType, AAZFreeFormDictType from ._field_value import AAZObject @@ -630,10 +630,3 @@ class Action(AAZGenericUpdateAction): ACTION_NAME = "remove" return Action - - -def has_value(arg_value): - if isinstance(arg_value, AAZBaseValue): - # handle patch value for list, object, dict - return arg_value.to_serialized_data() != AAZUndefined - return arg_value != AAZUndefined diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/_base.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/_base.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/_base.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/_base.py 2023-01-06 05:23:51.000000000 +0100 @@ -151,3 +151,10 @@ # In order to different with `None` value # This value is used in aaz package only. AAZBlankArgValue = _AAZBlankArgValueType() + + +def has_value(arg_value): + if isinstance(arg_value, AAZBaseValue): + # handle patch value for list, object, dict + return arg_value.to_serialized_data() != AAZUndefined + return arg_value != AAZUndefined diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/_command_ctx.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/_command_ctx.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/_command_ctx.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/_command_ctx.py 2023-01-06 05:23:51.000000000 +0100 @@ -12,6 +12,7 @@ from ._base import AAZUndefined from ._field_type import AAZObjectType from ._field_value import AAZObject +from ._selector import AAZSelectors from .exceptions import AAZInvalidArgValueError @@ -32,6 +33,7 @@ self._clients = {} self._vars_schema = AAZObjectType() self.vars = AAZObject(schema=self._vars_schema, data={}) + self.selectors = AAZSelectors() self.generic_update_args = command_args.get(AAZGenericUpdateAction.DEST, None) # support no wait self.lro_no_wait = command_args.get(no_wait_arg, False) if no_wait_arg else False diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/_field_type.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/_field_type.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/_field_type.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/_field_type.py 2023-01-06 05:23:51.000000000 +0100 @@ -9,7 +9,7 @@ from ._field_value import AAZObject, AAZDict, AAZFreeFormDict, AAZList, AAZSimpleValue from ._utils import to_snack_case from .exceptions import AAZUnknownFieldError, AAZConflictFieldDefinitionError, AAZValuePrecisionLossError, \ - AAZInvalidFieldError + AAZInvalidFieldError, AAZInvalidValueError # pylint: disable=protected-access, too-few-public-methods, isinstance-second-argument-not-valid-type # pylint: disable=too-many-instance-attributes @@ -33,6 +33,9 @@ return None return AAZValuePatch.build(self) + if data == AAZUndefined: + return AAZValuePatch.build(self) + if isinstance(data, AAZSimpleValue): if data._is_patch: # return value patch @@ -40,8 +43,10 @@ data = data._data - assert self.DataType is not None and isinstance(data, self.DataType), \ - f'Expect {self.DataType}, got {data} ({type(data)}' + assert self.DataType is not None + if not isinstance(data, self.DataType): + raise AAZInvalidValueError('Expect {}, got {} ({})'.format(self.DataType, data, type(data))) + return data @@ -67,6 +72,9 @@ return None return AAZValuePatch.build(self) + if data == AAZUndefined: + return AAZValuePatch.build(self) + if isinstance(data, AAZSimpleValue): if data._is_patch: # return value patch @@ -79,7 +87,10 @@ if float(data) != data: raise AAZValuePrecisionLossError(data, float(data)) data = float(data) - assert isinstance(data, self.DataType), f'Expect {self.DataType}, got {data} ({type(data)}' + + if not isinstance(data, self.DataType): + raise AAZInvalidValueError('Expect {}, got {} ({})'.format(self.DataType, data, type(data))) + return data @@ -179,6 +190,9 @@ return None return AAZValuePatch.build(self) + if data == AAZUndefined: + return AAZValuePatch.build(self) + if isinstance(data, AAZObject) and data._is_patch: # use value patch result = AAZValuePatch.build(self) @@ -202,7 +216,8 @@ value[key] = data[key] else: - assert isinstance(data, (dict,)) + if not isinstance(data, dict): + raise AAZInvalidValueError("Expect <class 'dict'>, got {} ({})".format(data, type(data))) if self._discriminator_field_name: # assign discriminator field first @@ -246,7 +261,9 @@ return None if isinstance(data, AAZObject): data = data._data - assert isinstance(data, dict) + if not isinstance(data, dict): + raise AAZInvalidValueError("Expect <class 'dict'>, got {} ({})".format(data, type(data))) + for key, field_data in data.items(): name = self.get_attr_name(key) if name == self._discriminator_field_name: @@ -272,6 +289,9 @@ return None return AAZValuePatch.build(self) + if data == AAZUndefined: + return AAZValuePatch.build(self) + if isinstance(data, self._ValueCls) and data._is_patch: # use value patch result = AAZValuePatch.build(self) @@ -284,7 +304,9 @@ for key in data._data.keys(): value[key] = data[key] else: - assert isinstance(data, (dict,)) + if not isinstance(data, dict): + raise AAZInvalidValueError("Expect <class 'dict'>, got {} ({})".format(data, type(data))) + for key, sub_data in data.items(): value[key] = sub_data return result @@ -366,6 +388,9 @@ return None return AAZValuePatch.build(self) + if data == AAZUndefined: + return AAZValuePatch.build(self) + if isinstance(data, AAZList) and data._is_patch: # use value patch result = AAZValuePatch.build(self) @@ -377,7 +402,9 @@ for idx in data._data.keys(): value[idx] = data[idx] else: - assert isinstance(data, list) + if not isinstance(data, list): + raise AAZInvalidValueError("Expect <class 'list'>, got {} ({})".format(data, type(data))) + for idx, sub_data in enumerate(data): value[idx] = sub_data diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/_field_value.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/_field_value.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/_field_value.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/_field_value.py 2023-01-06 05:23:51.000000000 +0100 @@ -73,19 +73,12 @@ def __setitem__(self, key, data): assert not key.startswith('_') attr_schema, name = self._get_attr_schema_and_name(key) - if name is None: - # ignore undefined key - return - self._data[name] = attr_schema.process_data(data, key=name) def __delitem__(self, key): _, name = self._get_attr_schema_and_name(key) - if name in self._data: del self._data[name] - elif name is None: - raise KeyError(f"Attribute {key} not exist") def __getattr__(self, key) -> AAZBaseValue: return self[key] @@ -155,12 +148,13 @@ """ get attribute schema and it's name based in key """ disc_schema = self._schema.get_discriminator(self._data) if not hasattr(self._schema, key) and disc_schema is not None: - attr_schema = disc_schema[key] + attr_schema = disc_schema[key] # will raise error if key not exist schema = disc_schema else: - attr_schema = self._schema[key] + attr_schema = self._schema[key] # will raise error if key not exist schema = self._schema name = schema.get_attr_name(key) + assert name is not None return attr_schema, name diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/_operation.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/_operation.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/_operation.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/_operation.py 2023-01-06 05:23:51.000000000 +0100 @@ -3,18 +3,20 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -# pylint: disable=too-few-public-methods, protected-access +# pylint: disable=too-few-public-methods, protected-access, too-many-nested-blocks, too-many-branches import json from azure.core.exceptions import ClientAuthenticationError, ResourceExistsError, ResourceNotFoundError, \ HttpResponseError +from azure.cli.core.azclierror import InvalidArgumentValueError from ._arg_browser import AAZArgBrowser -from ._base import AAZUndefined, AAZBaseValue, AAZBaseType +from ._base import AAZUndefined, AAZBaseValue, AAZBaseType, has_value from ._content_builder import AAZContentBuilder from ._field_type import AAZSimpleType, AAZObjectType, AAZBaseDictType, AAZListType -from ._field_value import AAZSimpleValue +from ._field_value import AAZList, AAZObject, AAZBaseDictValue +from .exceptions import AAZInvalidValueError try: from urllib import quote # type: ignore @@ -324,9 +326,7 @@ raise HttpResponseError(response=response, error_format=error_format) -class AAZJsonInstanceUpdateOperation(AAZOperation): - """ Instance Update Operation - """ +class AAZJsonInstanceOperationHelper: def __call__(self, *args, **kwargs): raise NotImplementedError() @@ -352,7 +352,7 @@ data=schema.process_data(None) ) else: - assert isinstance(value, AAZBaseValue) + assert isinstance(value, AAZBaseValue), f"Unknown value type: {type(value)}" builder = AAZContentBuilder( values=[value], @@ -361,6 +361,33 @@ return value, builder +class AAZJsonInstanceUpdateOperation(AAZJsonInstanceOperationHelper, AAZOperation): + """ Instance Update Operation + """ + + def __call__(self, *args, **kwargs): + raise NotImplementedError() + + +class AAZJsonInstanceCreateOperation(AAZJsonInstanceOperationHelper, AAZOperation): + """ Json Instance Create Operation + """ + + def __call__(self, *args, **kwargs): + raise NotImplementedError() + + +class AAZJsonInstanceDeleteOperation(AAZJsonInstanceOperationHelper, AAZOperation): + """ Json Instance Delete Operation + """ + + def __call__(self, *args, **kwargs): + raise NotImplementedError() + + def _delete_instance(self, *args, **kwargs): # pylint: disable=unused-argument, no-self-use + return AAZUndefined + + class AAZGenericInstanceUpdateOperation(AAZOperation): """ Generic Instance Update Operation """ @@ -368,48 +395,279 @@ def __call__(self, *args, **kwargs): raise NotImplementedError() - @staticmethod - def _update_instance_by_generic(instance, generic_update_args): # pylint: disable=unused-argument - from azure.cli.core.commands.arm import add_usage, remove_usage, set_usage, \ - add_properties, remove_properties, set_properties - from azure.cli.core.azclierror import InvalidArgumentValueError + def _update_instance_by_generic(self, instance, generic_update_args, client_flatten=True): # pylint: disable=unused-argument + from azure.cli.core.commands.arm import add_usage, remove_usage, set_usage if not generic_update_args or not generic_update_args['actions']: return instance assert isinstance(instance, AAZBaseValue) - data = instance.to_serialized_data() # to raw data force_string = generic_update_args.get('force_string', False) for action_name, values in generic_update_args['actions']: if action_name == "set": try: for expression in values: - set_properties(data, expression, force_string) + self._set_properties(instance, expression, force_string, client_flatten) except ValueError: raise InvalidArgumentValueError('invalid syntax: {}'.format(set_usage)) elif action_name == "add": try: - add_properties(data, values, force_string) + self._add_properties(instance, values, force_string, client_flatten) except ValueError: raise InvalidArgumentValueError('invalid syntax: {}'.format(add_usage)) elif action_name == "remove": try: - remove_properties(data, values) + self._remove_properties(instance, values, client_flatten) except ValueError: raise InvalidArgumentValueError('invalid syntax: {}'.format(remove_usage)) + return instance - # verify and update instance + def _set_properties(self, instance, expression, force_string, flatten): + from azure.cli.core.commands.arm import _split_key_value_pair, shell_safe_json_parse, index_or_filter_regex + key, value = _split_key_value_pair(expression) + + if key is None or key.strip() == '': + raise InvalidArgumentValueError('Empty key in --set. Correct syntax: --set KEY=VALUE [KEY=VALUE ...]') + + if not force_string: + try: + value = shell_safe_json_parse(value) + except (ValueError, InvalidArgumentValueError): + pass + + path = self._get_internal_path(key) + name = path.pop() + instance = self._find_property(instance, path, flatten) # find the parent instance + + match = index_or_filter_regex.match(name) + index_value = int(match.group(1)) if match else None try: - data = instance._schema.process_data(data) - except AssertionError as err: - raise InvalidArgumentValueError(f'invalid argument: {err}') - - if isinstance(instance, AAZSimpleValue): - # should be combined with - # self.ctx.var.instance = _update_instance_by_generic(self.ctx.var.instance, self.ctx.generic_update_args) - instance._data = data + if index_value is not None: + # instance is AAZList or list + if not isinstance(instance, (AAZList, list)): + raise TypeError() + if len(instance) <= index_value: + raise IndexError() + instance[index_value] = value + else: + # instance is in AAZObject or AAZDict or dict + if isinstance(instance, AAZObject): + parent = self._get_property_parent(instance, name, flatten) + if parent is None: + raise AttributeError() + instance = parent + instance[name] = value + except AAZInvalidValueError as err: + raise InvalidArgumentValueError(err) + except IndexError: + raise InvalidArgumentValueError('index {} doesn\'t exist on {}'.format(index_value, path[-1])) + except (AttributeError, KeyError, TypeError): + self._throw_and_show_options(instance, name, key.split('.'), flatten) + + def _add_properties(self, instance, argument_values, force_string, flatten): + from azure.cli.core.commands.arm import shell_safe_json_parse + # The first argument indicates the path to the collection to add to. + argument_values = list(argument_values) + list_attribute_path = self._get_internal_path(argument_values.pop(0)) + list_to_add_to = self._find_property(instance, list_attribute_path, flatten) + + if not isinstance(list_to_add_to, (AAZList, list)): + raise ValueError() + + try: + dict_entry = {} + for argument in argument_values: + if '=' in argument: + # consecutive key=value entries get added to the same dictionary + split_arg = argument.split('=', 1) + argument = split_arg[1] + # Didn't convert argument by shell_safe_json_parse here to keep consist with the behavior in arm.py + dict_entry[split_arg[0]] = argument + else: + if dict_entry: + # if an argument is supplied that is not key=value, append any dictionary entry + # to the list and reset. A subsequent key=value pair will be added to another + # dictionary. + list_to_add_to.append(dict_entry) + dict_entry = {} + + if not force_string: + # attempt to convert anything else to JSON and fallback to string if error + try: + argument = shell_safe_json_parse(argument) + except (ValueError, InvalidArgumentValueError): + pass + list_to_add_to.append(argument) + + # if only key=value pairs used, must check at the end to append the dictionary + if dict_entry: + list_to_add_to.append(dict_entry) + except AAZInvalidValueError as err: + raise InvalidArgumentValueError(err) + + def _remove_properties(self, instance, argument_values, flatten): + # The first argument indicates the path to the collection to remove from. + argument_values = list(argument_values) if isinstance(argument_values, list) else [argument_values] + + list_attribute_path = self._get_internal_path(argument_values.pop(0)) + list_index = None + try: + list_index = argument_values.pop(0) + except IndexError: + pass + + if not list_index: + # parent is in AAZObject or AAZDict or dict + property_val = self._find_property(instance, list_attribute_path, flatten) + parent = self._find_property(instance, list_attribute_path[:-1], flatten) + if isinstance(parent, (AAZObject, AAZBaseDictValue)): + if isinstance(parent, AAZObject): + parent = self._get_property_parent(parent, list_attribute_path[-1], flatten) + if isinstance(property_val, (AAZList, list)): + if has_value(property_val): + # keep consist with the behavior in arm.py + parent[list_attribute_path[-1]] = [] + else: + parent[list_attribute_path[-1]] = AAZUndefined + elif isinstance(parent, dict): + del parent[list_attribute_path[-1]] + else: + # other types + raise ValueError() else: - # in place update _data. Cannot use instance._data = data, because the original _data will not be changed. - assert isinstance(instance._data, dict) - instance._data.clear() - instance._data.update(data) + list_to_remove_from = self._find_property(instance, list_attribute_path, flatten) + try: + if isinstance(list_to_remove_from, AAZList): + del list_to_remove_from[int(list_index)] + elif isinstance(list_to_remove_from, list): + list_to_remove_from.pop(int(list_index)) + else: + raise IndexError() + except IndexError: + raise InvalidArgumentValueError('index {} doesn\'t exist on {}' + .format(list_index, list_attribute_path[-1])) + + def _find_property(self, instance, path, flatten): + from azure.cli.core.commands.arm import index_or_filter_regex, shell_safe_json_parse + try: + for part in path: + index = index_or_filter_regex.match(part) + if index and not isinstance(instance, (AAZList, list)): + raise AttributeError() + + if index and '=' in index.group(1): + key, value = index.group(1).split('=', 1) + try: + value = shell_safe_json_parse(value) + except (ValueError, InvalidArgumentValueError): + pass + matches = [] + for x in instance: + if isinstance(x, dict) and x.get(key, None) == value: + matches.append(x) + elif isinstance(x, (AAZObject, AAZBaseDictValue)): + parent = x + if isinstance(parent, AAZObject): + parent = self._get_property_parent(parent, key, flatten) + if parent is None: + continue + if parent[key].to_serialized_data() == value: + matches.append(x) # should append `x` instead of `parent` + + if len(matches) > 1: + raise InvalidArgumentValueError( + "non-unique key '{}' found multiple matches on {}. Key must be unique." + .format(key, path[-2])) + if len(matches) == 0: + raise InvalidArgumentValueError( + "item with value '{}' doesn\'t exist for key '{}' on {}".format(value, key, path[-2])) + + instance = matches[0] + + elif index: + try: + index_value = int(index.group(1)) + if isinstance(instance, AAZList): + if len(instance) <= index_value: + raise IndexError() + + instance = instance[index_value] + except IndexError: + raise InvalidArgumentValueError('index {} doesn\'t exist on {}'.format(index_value, path[-2])) + + elif isinstance(instance, (dict, AAZBaseDictValue, AAZObject)): + parent = instance + if isinstance(instance, AAZObject): + parent = self._get_property_parent(parent, part, flatten) + if parent is None: + raise AttributeError() + instance = parent[part] + else: + raise AttributeError() + + except (AttributeError, KeyError): + self._throw_and_show_options(instance, part, path, flatten) + return instance + + @staticmethod + def _get_internal_path(path): + from azure.cli.core.commands.arm import _get_internal_path + return _get_internal_path(path) + + def _get_property_parent(self, instance, prop_name, flatten): + if not isinstance(instance, AAZObject): + return None + + # prop_name in current instance + if hasattr(instance, prop_name): + sub_instance = instance[prop_name] + if not flatten or not sub_instance._schema._flags.get('client_flatten', False): + # flatten property should be ignored + return instance + + if not flatten: + return None + + for key in self._iter_aaz_object_keys(instance): + sub_instance = instance[key] + if sub_instance._schema._flags.get('client_flatten', False): + sub_instance = self._get_property_parent(sub_instance, prop_name, flatten) + if sub_instance is not None: + return sub_instance + + return None + + @staticmethod + def _iter_aaz_object_keys(instance): + if not isinstance(instance, AAZObject): + return + schemas = [instance._schema] + disc_schema = instance._schema.get_discriminator(instance) + if disc_schema is not None: + schemas.append(disc_schema) + for schema in schemas: + for key in schema._fields: + yield key + + def _throw_and_show_options(self, instance, part, path, flatten): + parent = '.'.join(path[:-1]).replace('.[', '[') + error_message = "Couldn't find '{}' in '{}'.".format(part, parent) + if isinstance(instance, AAZObject): + options = [] + for key in self._iter_aaz_object_keys(instance): + sub_instance = instance[key] + if flatten and sub_instance._schema._flags.get('client_flatten', False): + options.extend(self._iter_aaz_object_keys(sub_instance)) + else: + options.append(key) + options = sorted(options) + error_message = '{} Available options: {}'.format(error_message, options) + elif isinstance(instance, (AAZBaseDictValue, dict)): + options = sorted(instance.keys()) + error_message = '{} Available options: {}'.format(error_message, options) + elif isinstance(instance, (list, AAZList)): + options = "index into the collection '{}' with [<index>] or [<key=value>]".format(parent) + error_message = '{} Available options: {}'.format(error_message, options) + else: + error_message = "{} '{}' does not support further indexing.".format(error_message, parent) + raise InvalidArgumentValueError(error_message) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/_selector.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/_selector.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/_selector.py 1970-01-01 01:00:00.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/_selector.py 2023-01-06 05:23:51.000000000 +0100 @@ -0,0 +1,60 @@ +# -------------------------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------------------------- +# from azure.core.exceptions import ResourceExistsError, ResourceNotFoundError +from azure.cli.core.azclierror import UserFault + +from ._base import has_value +from .exceptions import AAZUnknownFieldError + + +class AAZSelectors: + + def __init__(self): + self._selectors = {} + + def __getattr__(self, key): + if key not in self._selectors: + raise AAZUnknownFieldError(self, key) + return self._selectors[key] + + def __setattr__(self, key, value): + if key.startswith('_'): + self.__dict__[key] = value + else: + self._selectors[key] = value + + +class AAZSelector: # pylint: disable=too-few-public-methods + + def __init__(self, ctx, name): + self.ctx = ctx + setattr(ctx.selectors, name, self) + + +class AAZJsonSelector(AAZSelector): + + def _get(self): + raise NotImplementedError() + + def _set(self, value): + raise NotImplementedError() + + def get(self): + try: + return self._get() + except StopIteration: + raise UserFault("ResourceNotFoundError") + + def set(self, value): + try: + self._set(value) + except StopIteration: + raise UserFault("ResourceNotFoundError") + + def required(self): + value = self.get() + if not has_value(value): + raise UserFault("ResourceNotFoundError") + return value diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/aaz/utils.py new/azure-cli-core-2.44.0/azure/cli/core/aaz/utils.py --- old/azure-cli-core-2.43.0/azure/cli/core/aaz/utils.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/aaz/utils.py 2023-01-06 05:23:51.000000000 +0100 @@ -4,7 +4,8 @@ # -------------------------------------------------------------------------------------------- # pylint: disable=protected-access -from ._arg import AAZListArg, AAZDictArg, has_value +from ._arg import AAZListArg, AAZDictArg +from ._base import has_value from ._field_value import AAZList, AAZDict from ._base import AAZBaseValue diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/parser.py new/azure-cli-core-2.44.0/azure/cli/core/parser.py --- old/azure-cli-core-2.43.0/azure/cli/core/parser.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/parser.py 2023-01-06 05:23:51.000000000 +0100 @@ -90,9 +90,6 @@ continue command_verb = command_name.split()[-1] - # To work around http://bugs.python.org/issue9253, we artificially add any new - # parsers we add to the "choices" section of the subparser. - subparser.choices[command_verb] = command_verb # inject command_module designer's help formatter -- default is HelpFormatter fc = metadata.formatter_class or argparse.HelpFormatter diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure/cli/core/profiles/_shared.py new/azure-cli-core-2.44.0/azure/cli/core/profiles/_shared.py --- old/azure-cli-core-2.43.0/azure/cli/core/profiles/_shared.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure/cli/core/profiles/_shared.py 2023-01-06 05:23:51.000000000 +0100 @@ -156,7 +156,7 @@ ResourceType.MGMT_NETWORK: '2022-01-01', ResourceType.MGMT_COMPUTE: SDKProfile('2022-08-01', { 'resource_skus': '2019-04-01', - 'disks': '2022-03-02', + 'disks': '2022-07-02', 'disk_encryption_sets': '2022-03-02', 'disk_accesses': '2020-05-01', 'snapshots': '2022-03-02', @@ -247,7 +247,7 @@ ResourceType.MGMT_ARO: '2022-04-01', ResourceType.MGMT_DATABOXEDGE: '2021-02-01-preview', ResourceType.MGMT_CUSTOMLOCATION: '2021-03-15-preview', - ResourceType.MGMT_CONTAINERSERVICE: SDKProfile('2022-09-01', { + ResourceType.MGMT_CONTAINERSERVICE: SDKProfile('2022-11-01', { 'container_services': '2017-07-01', 'open_shift_managed_clusters': '2019-09-30-preview' }), diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure_cli_core.egg-info/PKG-INFO new/azure-cli-core-2.44.0/azure_cli_core.egg-info/PKG-INFO --- old/azure-cli-core-2.43.0/azure_cli_core.egg-info/PKG-INFO 2022-12-02 07:07:40.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure_cli_core.egg-info/PKG-INFO 2023-01-06 05:24:14.000000000 +0100 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: azure-cli-core -Version: 2.43.0 +Version: 2.44.0 Summary: Microsoft Azure Command-Line Tools Core Module Home-page: https://github.com/Azure/azure-cli Author: Microsoft Corporation diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure_cli_core.egg-info/SOURCES.txt new/azure-cli-core-2.44.0/azure_cli_core.egg-info/SOURCES.txt --- old/azure-cli-core-2.43.0/azure_cli_core.egg-info/SOURCES.txt 2022-12-02 07:07:40.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure_cli_core.egg-info/SOURCES.txt 2023-01-06 05:24:14.000000000 +0100 @@ -49,6 +49,7 @@ azure/cli/core/aaz/_operation.py azure/cli/core/aaz/_paging.py azure/cli/core/aaz/_poller.py +azure/cli/core/aaz/_selector.py azure/cli/core/aaz/_utils.py azure/cli/core/aaz/exceptions.py azure/cli/core/aaz/utils.py diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/azure_cli_core.egg-info/requires.txt new/azure-cli-core-2.44.0/azure_cli_core.egg-info/requires.txt --- old/azure-cli-core-2.43.0/azure_cli_core.egg-info/requires.txt 2022-12-02 07:07:40.000000000 +0100 +++ new/azure-cli-core-2.44.0/azure_cli_core.egg-info/requires.txt 2023-01-06 05:24:14.000000000 +0100 @@ -1,4 +1,4 @@ -argcomplete~=1.8 +argcomplete~=2.0 azure-cli-telemetry==1.0.8.* azure-mgmt-core<2,>=1.2.0 cryptography diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.43.0/setup.py new/azure-cli-core-2.44.0/setup.py --- old/azure-cli-core-2.43.0/setup.py 2022-12-02 07:07:20.000000000 +0100 +++ new/azure-cli-core-2.44.0/setup.py 2023-01-06 05:23:51.000000000 +0100 @@ -8,7 +8,7 @@ from codecs import open from setuptools import setup, find_packages -VERSION = "2.43.0" +VERSION = "2.44.0" # If we have source, validate that our version numbers match # This should prevent uploading releases with mismatched versions. @@ -43,7 +43,7 @@ ] DEPENDENCIES = [ - 'argcomplete~=1.8', + 'argcomplete~=2.0', 'azure-cli-telemetry==1.0.8.*', 'azure-mgmt-core>=1.2.0,<2', 'cryptography',
