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 2022-07-06 15:41:53 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/azure-cli-core (Old) and /work/SRC/openSUSE:Factory/.azure-cli-core.new.1548 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "azure-cli-core" Wed Jul 6 15:41:53 2022 rev:40 rq:986888 version:2.38.0 Changes: -------- --- /work/SRC/openSUSE:Factory/azure-cli-core/azure-cli-core.changes 2022-06-05 00:45:42.700378293 +0200 +++ /work/SRC/openSUSE:Factory/.azure-cli-core.new.1548/azure-cli-core.changes 2022-07-06 15:42:05.622525551 +0200 @@ -1,0 +2,8 @@ +Tue Jul 5 07:58:43 UTC 2022 - John Paul Adrian Glaubitz <adrian.glaub...@suse.com> + +- New upstream release + + Version 2.38.0 + + For detailed information about changes see the + HISTORY.rst file provided with this package + +------------------------------------------------------------------- Old: ---- azure-cli-core-2.37.0.tar.gz New: ---- azure-cli-core-2.38.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ azure-cli-core.spec ++++++ --- /var/tmp/diff_new_pack.i7Mb14/_old 2022-07-06 15:42:06.106526264 +0200 +++ /var/tmp/diff_new_pack.i7Mb14/_new 2022-07-06 15:42:06.110526270 +0200 @@ -17,7 +17,7 @@ Name: azure-cli-core -Version: 2.37.0 +Version: 2.38.0 Release: 0 Summary: Microsoft Azure CLI Core Module License: MIT ++++++ azure-cli-core-2.37.0.tar.gz -> azure-cli-core-2.38.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/HISTORY.rst new/azure-cli-core-2.38.0/HISTORY.rst --- old/azure-cli-core-2.37.0/HISTORY.rst 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/HISTORY.rst 2022-07-01 06:13:48.000000000 +0200 @@ -3,6 +3,10 @@ Release History =============== +2.38.0 +++++++ +* Shorthand syntax: Simplify the escape character usage in Single Quotes String (#22607) + 2.37.0 ++++++ * Codegen v2 support (#20967) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/PKG-INFO new/azure-cli-core-2.38.0/PKG-INFO --- old/azure-cli-core-2.37.0/PKG-INFO 2022-05-23 16:03:19.386597000 +0200 +++ new/azure-cli-core-2.38.0/PKG-INFO 2022-07-01 06:14:18.955989400 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: azure-cli-core -Version: 2.37.0 +Version: 2.38.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.37.0/azure/cli/core/__init__.py new/azure-cli-core-2.38.0/azure/cli/core/__init__.py --- old/azure-cli-core-2.37.0/azure/cli/core/__init__.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/__init__.py 2022-07-01 06:13:48.000000000 +0200 @@ -4,7 +4,7 @@ # -------------------------------------------------------------------------------------------- # pylint: disable=line-too-long -__version__ = "2.37.0" +__version__ = "2.38.0" import os import sys diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_arg.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_arg.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_arg.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_arg.py 2022-07-01 06:13:48.000000000 +0200 @@ -104,6 +104,7 @@ options_list=[*self._options] if self._options else None, required=self._required, help=self._help.get('short-summary', None), + id_part=self._id_part, default=self._default, ) if self._arg_group: @@ -197,11 +198,15 @@ def to_cmd_arg(self, name): from ._help import shorthand_help_messages arg = super().to_cmd_arg(name) - short_summery = arg.type.settings.get('help', None) or '' - if short_summery: - short_summery += ' ' - short_summery += shorthand_help_messages['show-help'] + ' ' + shorthand_help_messages['short-summery'] - arg.help = short_summery + short_summary = arg.type.settings.get('help', None) or '' + if short_summary: + short_summary += ' ' + short_summary += shorthand_help_messages['short-summary'] + ' ' + shorthand_help_messages['show-help'] + if isinstance(self, AAZListArg) and self.singular_options: + singular_options = ' Singular flags: ' + ' '.join( + [f'`{opt}`' for opt in self.singular_options]) + short_summary += singular_options + '.' + arg.help = short_summary return arg diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_arg_action.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_arg_action.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_arg_action.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_arg_action.py 2022-07-01 06:13:48.000000000 +0200 @@ -58,7 +58,9 @@ _str_parser = AAZShortHandSyntaxParser() # support to parse normal string or short hand syntax string def __call__(self, parser, namespace, values, option_string=None): - if getattr(namespace, self.dest) is None or getattr(namespace, self.dest) == AAZUndefined: + if not isinstance(getattr(namespace, self.dest), AAZArgActionOperations): + # overwrite existing namespace value which is not an instance of AAZArgActionOperations. + # especially the default value of argument. setattr(namespace, self.dest, AAZArgActionOperations()) dest_ops = getattr(namespace, self.dest) try: @@ -277,7 +279,9 @@ class AAZListArgAction(AAZCompoundTypeArgAction): def __call__(self, parser, namespace, values, option_string=None): - if getattr(namespace, self.dest) is None or getattr(namespace, self.dest) == AAZUndefined: + if not isinstance(getattr(namespace, self.dest), AAZArgActionOperations): + # overwrite existing namespace value which is not an instance of AAZArgActionOperations. + # especially the default value of argument. setattr(namespace, self.dest, AAZArgActionOperations()) dest_ops = getattr(namespace, self.dest) try: @@ -371,7 +375,7 @@ raise AAZInvalidValueError(f"list type value expected, got '{data}'({type(data)})") -class AAZGenericUpdateAction(Action): +class AAZGenericUpdateAction(Action): # pylint: disable=too-few-public-methods DEST = '_generic_update_args' def __call__(self, parser, namespace, values, option_string=None): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_arg_browser.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_arg_browser.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_arg_browser.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_arg_browser.py 2022-07-01 06:13:48.000000000 +0200 @@ -12,7 +12,7 @@ @classmethod def create(cls, arg): assert isinstance(arg, AAZBaseValue) - return cls(arg_value=arg, arg_data=arg.to_serialized_data()) + return cls(arg_value=arg, arg_data=arg.to_serialized_data(keep_undefined_in_list=True)) def __init__(self, arg_value, arg_data, parent=None): assert isinstance(arg_value, AAZBaseValue) @@ -33,7 +33,7 @@ if key.startswith('.'): names = key[1:].split('.', maxsplit=1) prop_name = names[0] - if prop_name not in self._arg_data: + if self._arg_data is None or prop_name not in self._arg_data: return None sub_value = self._arg_value[prop_name] sub_data = self._arg_data[prop_name] @@ -47,6 +47,10 @@ def get_elements(self): """Iter over sub elements of list or dict.""" + if self._arg_data is None: + # stop iteration + return + if isinstance(self._arg_data, list): for idx, d in enumerate(self._arg_data): # not support to access parent from element args diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_base.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_base.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_base.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_base.py 2022-07-01 06:13:48.000000000 +0200 @@ -21,7 +21,7 @@ self._is_patch = False @abc.abstractmethod - def to_serialized_data(self, processor=None): + def to_serialized_data(self, processor=None, **kwargs): """ serialize value into python build-in type """ raise NotImplementedError() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_command.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_command.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_command.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_command.py 2022-07-01 06:13:48.000000000 +0200 @@ -303,8 +303,12 @@ command_table = {} command_group_table = {} - arg_str = ' '.join(args) - fully_load = os.environ.get(AAZ_PACKAGE_FULL_LOAD_ENV_NAME, 'False').lower() == 'true' # used to disable cut logic + if args is None: + arg_str = '' + fully_load = True + else: + arg_str = ' '.join(args) + fully_load = os.environ.get(AAZ_PACKAGE_FULL_LOAD_ENV_NAME, 'False').lower() == 'true' # disable cut logic if profile_pkg is not None: _load_aaz_pkg(loader, profile_pkg, command_table, command_group_table, arg_str, fully_load) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_content_builder.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_content_builder.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_content_builder.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_content_builder.py 2022-07-01 06:13:48.000000000 +0200 @@ -68,9 +68,15 @@ if isinstance(value[prop_name], AAZSimpleValue): value[prop_name] = sub_arg.data elif isinstance(value[prop_name], AAZList): - value[prop_name] = [] + if sub_arg.data is None: + value[prop_name] = None + else: + value[prop_name] = [] elif isinstance(value[prop_name], (AAZDict, AAZObject)): - value[prop_name] = {} + if sub_arg.data is None: + value[prop_name] = None + else: + value[prop_name] = {} else: raise NotImplementedError() sub_values.append(value[prop_name]) @@ -102,9 +108,15 @@ if isinstance(value[key], AAZSimpleValue): value[key] = sub_arg.data elif isinstance(value[key], AAZList): - value[key] = [] + if sub_arg.data is None: + value[key] = None + else: + value[key] = [] elif isinstance(value[key], (AAZDict, AAZObject)): - value[key] = {} + if sub_arg.data is None: + value[key] = None + else: + value[key] = {} else: raise NotImplementedError() sub_values.append(value[key]) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_field_type.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_field_type.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_field_type.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_field_type.py 2022-07-01 06:13:48.000000000 +0200 @@ -8,6 +8,7 @@ AAZInvalidFieldError # pylint: disable=protected-access, too-few-public-methods, isinstance-second-argument-not-valid-type +# pylint: disable=too-many-instance-attributes # build in types @@ -28,7 +29,12 @@ return AAZValuePatch.build(self) if isinstance(data, AAZSimpleValue): + if data._is_patch: + # return value patch + return AAZValuePatch.build(self) + data = data._data + assert self.DataType is not None and isinstance(data, self.DataType), \ f'Expect {self.DataType}, got {data} ({type(data)}' return data @@ -56,7 +62,12 @@ return AAZValuePatch.build(self) if isinstance(data, AAZSimpleValue): + if data._is_patch: + # return value patch + return AAZValuePatch.build(self) + data = data._data + if isinstance(data, int): # transform int to float if float(data) != data: @@ -153,11 +164,14 @@ return None return AAZValuePatch.build(self) - result = {} + if isinstance(data, AAZObject) and data._is_patch: + # use value patch + result = AAZValuePatch.build(self) + else: + result = {} value = AAZObject(schema=self, data=result) if isinstance(data, AAZObject): - if self._discriminator_field_name: # assign discriminator field first for key in data._data.keys(): @@ -218,11 +232,11 @@ if isinstance(data, AAZObject): data = data._data assert isinstance(data, dict) - if self._discriminator_field_name not in data: - return None - - field_data = data[self._discriminator_field_name] # get discriminator field data - return self._discriminators.get(field_data, None) + for key, field_data in data.items(): + name = self.get_attr_name(key) + if name == self._discriminator_field_name: + return self._discriminators.get(field_data, None) + return None class AAZDictType(AAZBaseType): @@ -261,8 +275,13 @@ return None return AAZValuePatch.build(self) - result = {} + if isinstance(data, AAZDict) and data._is_patch: + # use value patch + result = AAZValuePatch.build(self) + else: + result = {} value = AAZDict(schema=self, data=result) + if isinstance(data, AAZDict): for key in data._data.keys(): value[key] = data[key] @@ -309,7 +328,11 @@ return None return AAZValuePatch.build(self) - result = {} + if isinstance(data, AAZList) and data._is_patch: + # use value patch + result = AAZValuePatch.build(self) + else: + result = {} value = AAZList(schema=self, data=result) if isinstance(data, AAZList): diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_field_value.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_field_value.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_field_value.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_field_value.py 2022-07-01 06:13:48.000000000 +0200 @@ -46,7 +46,7 @@ other = other._data return self._data >= other - def to_serialized_data(self, processor=None): + def to_serialized_data(self, processor=None, **kwargs): result = self._data if processor: result = processor(self._schema, result) @@ -115,22 +115,26 @@ def __ne__(self, other): return not self == other - def to_serialized_data(self, processor=None): - result = {} - schemas = [self._schema] + def to_serialized_data(self, processor=None, **kwargs): + if self._data is None: + result = None - disc_schema = self._schema.get_discriminator(self._data) - if disc_schema: - schemas.append(disc_schema) + else: + result = {} + schemas = [self._schema] - for schema in schemas: - for name, field_schema in schema._fields.items(): - v = self[name].to_serialized_data(processor=processor) - if v == AAZUndefined: - continue - if field_schema._serialized_name: # pylint: disable=protected-access - name = field_schema._serialized_name # pylint: disable=protected-access - result[name] = v + disc_schema = self._schema.get_discriminator(self._data) + if disc_schema: + schemas.append(disc_schema) + + for schema in schemas: + for name, field_schema in schema._fields.items(): + v = self[name].to_serialized_data(processor=processor, **kwargs) + if v == AAZUndefined: + continue + if field_schema._serialized_name: # pylint: disable=protected-access + name = field_schema._serialized_name # pylint: disable=protected-access + result[name] = v if not result and self._is_patch: return AAZUndefined @@ -218,13 +222,17 @@ for key in self._data: yield key, self[key] - def to_serialized_data(self, processor=None): - result = {} - for key, v in self.items(): - v = v.to_serialized_data(processor=processor) - if v == AAZUndefined: - continue - result[key] = v + def to_serialized_data(self, processor=None, **kwargs): + if self._data is None: + result = None + else: + result = {} + for key, v in self.items(): + v = v.to_serialized_data(processor=processor, **kwargs) + if v == AAZUndefined: + continue + result[key] = v + if not result and self._is_patch: return AAZUndefined if processor: @@ -335,11 +343,26 @@ self._data.clear() self._len = 0 - def to_serialized_data(self, processor=None): - result = [] - for v in self: - v = v.to_serialized_data(processor=processor) - result.append(v) + def to_serialized_data(self, processor=None, keep_undefined_in_list=False, # pylint: disable=arguments-differ + **kwargs): + if self._data is None: + result = None + else: + result = [] + has_valid = False + for v in self: + v = v.to_serialized_data( + processor=processor, keep_undefined_in_list=keep_undefined_in_list, **kwargs) + if v == AAZUndefined and not keep_undefined_in_list: + # When AAZUndefined is ignore it, the index of the following value will be changed. + continue + if v != AAZUndefined: + has_valid = True + result.append(v) + if not has_valid: + # when elements are all undefined, the result will be empty. + result = [] + if not result and self._is_patch: return AAZUndefined if processor: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_help.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_help.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_help.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_help.py 2022-07-01 06:13:48.000000000 +0200 @@ -21,8 +21,8 @@ shorthand_help_messages = { "show-help": 'Try `??` to show more.', - "short-summery": 'Shorthand syntax supported.', - "long-summery": 'See https://github.com/Azure/azure-cli/tree/dev/doc/shorthand_syntax.md ' + "short-summary": 'Shorthand syntax supported.', + "long-summary": 'See https://github.com/Azure/azure-cli/tree/dev/doc/shorthand_syntax.md ' 'for more about shorthand syntax.' } @@ -92,11 +92,11 @@ else: _print_indent(f"{key}{FIRST_LINE_PREFIX}{schema_type}", indent=1) - short_summary = cls._build_short_summery(schema) + short_summary = cls._build_short_summary(schema) if short_summary: _print_indent(short_summary, indent=2) - long_summary = cls._build_long_summery(schema) + long_summary = cls._build_long_summary(schema) if long_summary: _print_indent(long_summary, indent=2) @@ -112,7 +112,7 @@ prop_tags = cls._build_schema_tags(prop_schema) prop_name = ' '.join(prop_schema._options) - prop_short_summary = cls._build_short_summery(prop_schema, is_prop=True) + prop_short_summary = cls._build_short_summary(prop_schema, is_prop=True) prop_group_name = prop_schema._arg_group or "" header_len = len(prop_name) + len(prop_tags) + (1 if prop_tags else 0) @@ -149,7 +149,7 @@ return tags @staticmethod - def _build_short_summery(schema, is_prop=False): + def _build_short_summary(schema, is_prop=False): from ._arg import AAZSimpleTypeArg, AAZCompoundTypeArg short_summary = schema._help.get("short-summary", "") @@ -160,14 +160,14 @@ short_summary += ' ' short_summary += 'Allowed values: {}.'.format(', '.join(sorted([str(x) for x in choices]))) elif isinstance(schema, AAZCompoundTypeArg): - if short_summary: - short_summary += ' ' if is_prop: + if short_summary: + short_summary += ' ' short_summary += shorthand_help_messages['show-help'] return short_summary @staticmethod - def _build_long_summery(schema): + def _build_long_summary(schema): from ._arg import AAZCompoundTypeArg lines = [] long_summary = schema._help.get("long-summary", "") @@ -175,7 +175,7 @@ lines.append(long_summary) if isinstance(schema, AAZCompoundTypeArg): - lines.append(shorthand_help_messages['long-summery']) + lines.append(shorthand_help_messages['long-summary']) if schema._is_preview: preview = status_tag_messages['preview'].format("This argument") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_operation.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_operation.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_operation.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_operation.py 2022-07-01 06:13:48.000000000 +0200 @@ -13,7 +13,7 @@ from ._arg_browser import AAZArgBrowser from ._base import AAZUndefined, AAZBaseValue, AAZBaseType from ._content_builder import AAZContentBuilder -from ._field_type import AAZSimpleType +from ._field_type import AAZSimpleType, AAZObjectType, AAZDictType, AAZListType try: from urllib import quote # type: ignore @@ -96,7 +96,7 @@ if isinstance(value, list): value = [process_element(v) - for v in value] + for v in value if v != AAZUndefined] # Determines the format of the array. Possible formats are: # csv - comma separated values 'foo,bar' # ssv - space separated values 'foo bar' @@ -133,7 +133,7 @@ return e if isinstance(value, list): - value = [process_element(v) for v in value] + value = [process_element(v) for v in value if v != AAZUndefined] else: value = process_element(value) value = str(value) @@ -141,20 +141,70 @@ @staticmethod def serialize_content(value, required=False): + def processor(schema, result): if schema._flags.get('read_only', False): # ignore read_only fields when serialize content return AAZUndefined + if result == AAZUndefined or result is None: + return result + + if isinstance(schema, AAZObjectType): + assert isinstance(result, dict) + for _schema in [schema, schema.get_discriminator(result)]: + if not _schema: + continue + for _field_name, _field_schema in _schema._fields.items(): + # verify required and not read only property + _name = _field_schema._serialized_name or _field_name # prefer using serialized name first + if _name in result: + continue + if _field_schema._flags.get('read_only', False): + continue + if not _field_schema._flags.get('required', False): + continue + + if isinstance(_field_schema, AAZObjectType): + # use an empty dict as data for required object property, and process it's sub properties + _field_result = processor(_field_schema, {}) + assert _field_result != AAZUndefined + result[_name] = _field_result + elif isinstance(_field_schema, AAZDictType): + # use an empty dict for required dict property + result[_name] = {} + elif isinstance(_field_schema, AAZListType): + # use an empty dict for required list property + result[_name] = [] + else: + raise ValueError(f"Missing a required field in request content: {_name}") + return result if isinstance(value, AAZBaseValue): - value = value.to_serialized_data(processor=processor) + data = value.to_serialized_data(processor=processor) + flags = value._schema._flags + required = required or flags.get('required', False) and not flags.get('read_only', False) + if data == AAZUndefined and required: + if isinstance(value._schema, AAZObjectType): + # use an empty dict as data for required object, and process it's properties + data = processor(value._schema, {}) + assert data != AAZUndefined + elif isinstance(value._schema, AAZDictType): + # use an empty dict for required dict + data = {} + elif isinstance(value._schema, AAZListType): + # use an empty list for required list + data = [] + else: + raise ValueError("Missing request content") + else: + data = value - if value == AAZUndefined or value == None: # noqa: E711, pylint: disable=singleton-comparison + if data == AAZUndefined or data == None: # noqa: E711, pylint: disable=singleton-comparison if required: - raise ValueError("content is required.") + raise ValueError("Missing request content") return None - return value + return data @staticmethod def deserialize_http_content(session): @@ -171,7 +221,7 @@ """ Create a Content Builder """ assert isinstance(arg_value, AAZBaseValue) - arg_data = arg_value.to_serialized_data() + arg_data = arg_value.to_serialized_data(keep_undefined_in_list=True) if value is None: assert issubclass(typ, AAZBaseType) schema = typ(**typ_kwargs) if typ_kwargs else typ() @@ -187,7 +237,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], @@ -243,7 +293,7 @@ "GET", self.ctx.next_link, {}, self.header_parameters, self.content, self.form_content, None) - elif self.method in ("GET", ): + elif self.method in ("GET",): request = self.client._request( self.method, self.url, self.query_parameters, self.header_parameters, self.content, self.form_content, None) @@ -285,7 +335,7 @@ """ Create a Content Builder """ assert isinstance(arg_value, AAZBaseValue) - arg_data = arg_value.to_serialized_data() + arg_data = arg_value.to_serialized_data(keep_undefined_in_list=True) if value is None: assert issubclass(typ, AAZBaseType) schema = typ(**typ_kwargs) if typ_kwargs else typ() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/aaz/_utils.py new/azure-cli-core-2.38.0/azure/cli/core/aaz/_utils.py --- old/azure-cli-core-2.37.0/azure/cli/core/aaz/_utils.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/aaz/_utils.py 2022-07-01 06:13:48.000000000 +0200 @@ -26,28 +26,28 @@ elif data in self.HELP_EXPRESSIONS: raise AAZShowHelp() elif len(data) and data[0] == "'": - result, length = self.parse_shorthand_quote_string(data) + result, length = self.parse_single_quotes_string(data) if length != len(data): raise AAZInvalidShorthandSyntaxError( data, length, len(data) - length, "Redundant tail for quota expression") else: result = data else: - result, length = self.parse_shorthand_value(data) + result, length = self.parse_value(data) if length != len(data): raise AAZInvalidShorthandSyntaxError(data, length, len(data) - length, "Redundant tail") return result - def parse_shorthand_value(self, remain): + def parse_value(self, remain): if remain.startswith('{'): - return self.parse_shorthand_dict(remain) + return self.parse_dict(remain) if remain.startswith('['): - return self.parse_shorthand_list(remain) + return self.parse_list(remain) - return self.parse_shorthand_string(remain) + return self.parse_string(remain) - def parse_shorthand_dict(self, remain): # pylint: disable=too-many-statements + def parse_dict(self, remain): # pylint: disable=too-many-statements result = OrderedDict() assert remain.startswith('{') idx = 1 @@ -58,7 +58,7 @@ while idx < len(remain): try: - key, length = self.parse_shorthand_string(remain[idx:]) + key, length = self.parse_string(remain[idx:]) except AAZInvalidShorthandSyntaxError as ex: ex.error_data = remain ex.error_at += idx @@ -85,7 +85,7 @@ raise AAZInvalidShorthandSyntaxError(remain, idx, 1, "Cannot parse empty") try: - value, length = self.parse_shorthand_value(remain[idx:]) + value, length = self.parse_value(remain[idx:]) except AAZInvalidShorthandSyntaxError as ex: ex.error_data = remain ex.error_at += idx @@ -113,7 +113,7 @@ return result, idx - def parse_shorthand_list(self, remain): + def parse_list(self, remain): result = [] assert remain.startswith('[') idx = 1 @@ -124,7 +124,7 @@ while idx < len(remain): try: - value, length = self.parse_shorthand_value(remain[idx:]) + value, length = self.parse_value(remain[idx:]) except AAZInvalidShorthandSyntaxError as ex: ex.error_data = remain ex.error_at += idx @@ -150,10 +150,10 @@ raise AAZInvalidShorthandSyntaxError(remain, idx, 1, "Expect character ']'") return result, idx - def parse_shorthand_string(self, remain): + def parse_string(self, remain): idx = 0 if len(remain) and remain[0] == "'": - return self.parse_shorthand_quote_string(remain) + return self.parse_single_quotes_string(remain) while idx < len(remain): if remain[idx] in (',', ':', ']', '}'): @@ -178,43 +178,26 @@ return remain[:idx], idx - def parse_shorthand_quote_string(self, remain): + @staticmethod + def parse_single_quotes_string(remain): assert remain[0] == "'" quote = remain[0] idx = 1 result = '' while idx < len(remain): if remain[idx] == quote: - quote = None - idx += 1 - break - - if remain[idx] == '/': - try: - c, length = self.parse_escape_character(remain[idx:]) - except AAZInvalidShorthandSyntaxError as ex: - ex.error_data = remain - ex.error_at += idx - raise ex - - result += c - idx += length + if len(remain) > idx + 1 and remain[idx + 1] == '/': + # parse '/ as ' + result += quote + idx += 2 + else: + quote = None + idx += 1 + break else: result += remain[idx] idx += 1 + if quote is not None: raise AAZInvalidShorthandSyntaxError(remain, idx, 1, f"Miss end quota character: {quote}") return result, idx - - @staticmethod - def parse_escape_character(remain): - assert remain[0] == '/' - if len(remain) < 2: - raise AAZInvalidShorthandSyntaxError(remain, 0, 1, f"Invalid escape character: {remain}") - if remain[1] == "'": - return "'", 2 - if remain[1] == '/': - return '/', 2 - if remain[1] == '\\': - return '\\', 2 - raise AAZInvalidShorthandSyntaxError(remain, 0, 2, f"Invalid escape character: {remain[:2]}") diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/profiles/_shared.py new/azure-cli-core-2.38.0/azure/cli/core/profiles/_shared.py --- old/azure-cli-core-2.37.0/azure/cli/core/profiles/_shared.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/profiles/_shared.py 2022-07-01 06:13:48.000000000 +0200 @@ -150,17 +150,17 @@ ResourceType.MGMT_NETWORK: '2021-08-01', ResourceType.MGMT_COMPUTE: SDKProfile('2022-03-01', { 'resource_skus': '2019-04-01', - 'disks': '2021-12-01', - 'disk_encryption_sets': '2020-12-01', + 'disks': '2022-03-02', + 'disk_encryption_sets': '2022-03-02', 'disk_accesses': '2020-05-01', 'snapshots': '2021-12-01', 'galleries': '2021-10-01', 'gallery_images': '2021-10-01', 'gallery_image_versions': '2021-10-01', 'gallery_applications': '2021-07-01', - 'gallery_application_versions': '2021-07-01', - 'shared_galleries': '2020-09-30', - 'virtual_machine_scale_sets': '2021-11-01', + 'gallery_application_versions': '2022-01-03', + 'shared_galleries': '2022-01-03', + 'virtual_machine_scale_sets': '2022-03-01', }), ResourceType.MGMT_RESOURCE_FEATURES: '2021-07-01', ResourceType.MGMT_RESOURCE_LINKS: '2016-09-01', @@ -200,7 +200,7 @@ ResourceType.DATA_STORAGE_QUEUE: '2018-03-28', ResourceType.DATA_COSMOS_TABLE: '2017-04-17', ResourceType.MGMT_SERVICEBUS: '2021-06-01-preview', - ResourceType.MGMT_EVENTHUB: '2021-11-01', + ResourceType.MGMT_EVENTHUB: '2022-01-01-preview', ResourceType.MGMT_MONITOR: SDKProfile('2019-06-01', { 'action_groups': '2021-09-01', 'activity_log_alerts': '2017-04-01', @@ -288,7 +288,7 @@ ResourceType.DATA_STORAGE_QUEUE: '2019-07-07', ResourceType.DATA_COSMOS_TABLE: '2017-04-17', ResourceType.MGMT_APPSERVICE: '2018-02-01', - ResourceType.MGMT_EVENTHUB: '2021-11-01', + ResourceType.MGMT_EVENTHUB: '2022-01-01-preview', ResourceType.MGMT_SERVICEBUS: '2021-06-01-preview', ResourceType.MGMT_IOTHUB: '2019-07-01-preview', ResourceType.MGMT_DATABOXEDGE: '2019-08-01', @@ -335,7 +335,7 @@ # to have commands show up in the hybrid profile which happens to have the latest # API versions ResourceType.MGMT_APPSERVICE: '2018-02-01', - ResourceType.MGMT_EVENTHUB: '2021-11-01', + ResourceType.MGMT_EVENTHUB: '2022-01-01-preview', ResourceType.MGMT_SERVICEBUS: '2021-06-01-preview', ResourceType.MGMT_IOTHUB: '2019-03-22', ResourceType.MGMT_DATABOXEDGE: '2019-08-01' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure/cli/core/util.py new/azure-cli-core-2.38.0/azure/cli/core/util.py --- old/azure-cli-core-2.37.0/azure/cli/core/util.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure/cli/core/util.py 2022-07-01 06:13:48.000000000 +0200 @@ -58,7 +58,7 @@ from msrestazure.azure_exceptions import CloudError from msrest.exceptions import HttpOperationError, ValidationError, ClientRequestError from azure.common import AzureException - from azure.core.exceptions import AzureError + from azure.core.exceptions import AzureError, ServiceRequestError from requests.exceptions import SSLError, HTTPError from azure.cli.core import azclierror from msal_extensions.persistence import PersistenceError @@ -79,7 +79,11 @@ az_error = azclierror.InvalidArgumentValueError(error_msg) az_error.set_recommendation(QUERY_REFERENCE) - elif isinstance(ex, SSLError): + # SSLError is raised when making HTTP requests with 'requests' lib behind a proxy that intercepts HTTPS traffic. + # - SSLError is raised when directly calling 'requests' lib, such as MSAL or `az rest` + # - azure.core.exceptions.ServiceRequestError is raised when indirectly calling 'requests' lib with azure.core, + # which wraps the original SSLError + elif isinstance(ex, SSLError) or isinstance(ex, ServiceRequestError) and isinstance(ex.inner_exception, SSLError): az_error = azclierror.AzureConnectionError(error_msg) az_error.set_recommendation(SSLERROR_TEMPLATE) @@ -887,7 +891,12 @@ # try to figure out the correct content type if body: try: - _ = shell_safe_json_parse(body) + body_object = shell_safe_json_parse(body) + # Make sure Unicode characters are escaped as ASCII by utilizing the default ensure_ascii=True kwarg + # of json.dumps, since http.client by default encodes the body as latin-1: + # https://github.com/python/cpython/blob/3.10/Lib/http/client.py#L164 + # https://github.com/python/cpython/blob/3.10/Lib/http/client.py#L1324-L1327 + body = json.dumps(body_object) if 'Content-Type' not in headers: headers['Content-Type'] = 'application/json' except Exception: # pylint: disable=broad-except diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/azure-cli-core-2.37.0/azure_cli_core.egg-info/PKG-INFO new/azure-cli-core-2.38.0/azure_cli_core.egg-info/PKG-INFO --- old/azure-cli-core-2.37.0/azure_cli_core.egg-info/PKG-INFO 2022-05-23 16:03:18.000000000 +0200 +++ new/azure-cli-core-2.38.0/azure_cli_core.egg-info/PKG-INFO 2022-07-01 06:14:18.000000000 +0200 @@ -1,6 +1,6 @@ Metadata-Version: 2.1 Name: azure-cli-core -Version: 2.37.0 +Version: 2.38.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.37.0/setup.py new/azure-cli-core-2.38.0/setup.py --- old/azure-cli-core-2.37.0/setup.py 2022-05-23 16:02:55.000000000 +0200 +++ new/azure-cli-core-2.38.0/setup.py 2022-07-01 06:13:48.000000000 +0200 @@ -8,7 +8,7 @@ from codecs import open from setuptools import setup, find_packages -VERSION = "2.37.0" +VERSION = "2.38.0" # If we have source, validate that our version numbers match # This should prevent uploading releases with mismatched versions.