diff --git a/src/azure-cli/azure/cli/command_modules/appconfig/_kv_helpers.py b/src/azure-cli/azure/cli/command_modules/appconfig/_kv_helpers.py index c2f48cdaf68..57cc84dead9 100644 --- a/src/azure-cli/azure/cli/command_modules/appconfig/_kv_helpers.py +++ b/src/azure-cli/azure/cli/command_modules/appconfig/_kv_helpers.py @@ -3,7 +3,7 @@ # Licensed under the MIT License. See License.txt in the project root for license information. # -------------------------------------------------------------------------------------------- -# pylint: disable=line-too-long,too-many-nested-blocks +# pylint: disable=line-too-long,too-many-nested-blocks,too-many-lines import io import json @@ -120,43 +120,66 @@ def validate_import_feature(feature): # File <-> List of KeyValue object - -def __read_kv_from_file(file_path, - format_, - separator=None, - prefix_to_add="", - depth=None, - content_type=None): +def __read_with_appropriate_encoding(file_path, format_): config_data = {} + default_encoding = 'utf-8' + detected_encoding = __check_file_encoding(file_path) + try: - with io.open(file_path, 'r', encoding=__check_file_encoding(file_path)) as config_file: + with io.open(file_path, 'r', encoding=default_encoding) as config_file: + if format_ == 'json': + config_data = json.load(config_file) + + elif format_ == 'yaml': + for yaml_data in list(yaml.safe_load_all(config_file)): + config_data.update(yaml_data) + + elif format_ == 'properties': + config_data = javaproperties.load(config_file) + logger.debug("Importing feature flags from a properties file is not supported. If properties file contains feature flags, they will be imported as regular key-values.") + + except (UnicodeDecodeError, json.JSONDecodeError): + if detected_encoding == default_encoding: + raise + + with io.open(file_path, 'r', encoding=detected_encoding) as config_file: if format_ == 'json': config_data = json.load(config_file) - for feature_management_keyword in FEATURE_MANAGEMENT_KEYWORDS: - # delete all feature management sections in any name format. - # If users have not skipped features, and there are multiple - # feature sections, we will error out while reading features. - if feature_management_keyword in config_data: - del config_data[feature_management_keyword] elif format_ == 'yaml': for yaml_data in list(yaml.safe_load_all(config_file)): config_data.update(yaml_data) - for feature_management_keyword in FEATURE_MANAGEMENT_KEYWORDS: - # delete all feature management sections in any name format. - # If users have not skipped features, and there are multiple - # feature sections, we will error out while reading features. - if feature_management_keyword in config_data: - del config_data[feature_management_keyword] elif format_ == 'properties': config_data = javaproperties.load(config_file) logger.debug("Importing feature flags from a properties file is not supported. If properties file contains feature flags, they will be imported as regular key-values.") - except ValueError: - raise CLIError('The input is not a well formatted %s file.' % (format_)) + return config_data + + +def __read_kv_from_file(file_path, + format_, + separator=None, + prefix_to_add="", + depth=None, + content_type=None): + config_data = {} + try: + config_data = __read_with_appropriate_encoding(file_path, format_) + if format_ in ('json', 'yaml'): + for feature_management_keyword in FEATURE_MANAGEMENT_KEYWORDS: + # delete all feature management sections in any name format. + # If users have not skipped features, and there are multiple + # feature sections, we will error out while reading features. + if feature_management_keyword in config_data: + del config_data[feature_management_keyword] + except ValueError as ex: + raise CLIError('The input is not a well formatted %s file.\nException: %s' % (format_, ex)) + except yaml.YAMLError as ex: + raise CLIError('The input is not a well formatted YAML file.\nException: %s' % (ex)) except OSError: raise CLIError('File is not available.') + flattened_data = {} if format_ == 'json' and content_type and __is_json_content_type(content_type): for key in config_data: @@ -202,17 +225,10 @@ def __read_features_from_file(file_path, format_): return features_dict try: - with io.open(file_path, 'r', encoding=__check_file_encoding(file_path)) as config_file: - if format_ == 'json': - config_data = json.load(config_file) - - elif format_ == 'yaml': - for yaml_data in list(yaml.safe_load_all(config_file)): - config_data.update(yaml_data) - + config_data = __read_with_appropriate_encoding(file_path, format_) found_feature_section = False for index, feature_management_keyword in enumerate(FEATURE_MANAGEMENT_KEYWORDS): - # find the first occurence of feature management section in file. + # find the first occurrence of feature management section in file. # Enforce the same naming convention for 'EnabledFor' keyword # If there are multiple feature sections, we will error out here. if feature_management_keyword in config_data: @@ -223,9 +239,11 @@ def __read_features_from_file(file_path, format_): else: raise CLIError('Unable to proceed because file contains multiple sections corresponding to "Feature Management".') - except ValueError: + except ValueError as ex: raise CLIError( - 'The feature management section of input is not a well formatted %s file.' % (format_)) + 'The feature management section of input is not a well formatted %s file.\nException: %s' % (format_, ex)) + except yaml.YAMLError as ex: + raise CLIError('The feature management section of input is not a well formatted YAML file.\nException: %s' % (ex)) except OSError: raise CLIError('File is not available.')