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 2021-09-17 23:25:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/azure-cli-core (Old)
 and      /work/SRC/openSUSE:Factory/.azure-cli-core.new.1899 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "azure-cli-core"

Fri Sep 17 23:25:42 2021 rev:29 rq:918721 version:2.28.1

Changes:
--------
--- /work/SRC/openSUSE:Factory/azure-cli-core/azure-cli-core.changes    
2021-09-10 23:40:39.386517580 +0200
+++ /work/SRC/openSUSE:Factory/.azure-cli-core.new.1899/azure-cli-core.changes  
2021-09-17 23:25:58.945237832 +0200
@@ -1,0 +2,8 @@
+Fri Sep 10 09:11:43 UTC 2021 - John Paul Adrian Glaubitz 
<adrian.glaub...@suse.com>
+
+- New upstream release
+  + Version 2.28.1
+  + For detailed information about changes see the
+    HISTORY.rst file provided with this package
+
+-------------------------------------------------------------------

Old:
----
  azure-cli-core-2.27.2.tar.gz

New:
----
  azure-cli-core-2.28.1.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ azure-cli-core.spec ++++++
--- /var/tmp/diff_new_pack.UEwMba/_old  2021-09-17 23:25:59.357238199 +0200
+++ /var/tmp/diff_new_pack.UEwMba/_new  2021-09-17 23:25:59.357238199 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           azure-cli-core
-Version:        2.27.2
+Version:        2.28.1
 Release:        0
 Summary:        Microsoft Azure CLI Core Module
 License:        MIT

++++++ azure-cli-core-2.27.2.tar.gz -> azure-cli-core-2.28.1.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-core-2.27.2/HISTORY.rst 
new/azure-cli-core-2.28.1/HISTORY.rst
--- old/azure-cli-core-2.27.2/HISTORY.rst       2021-08-23 05:32:32.000000000 
+0200
+++ new/azure-cli-core-2.28.1/HISTORY.rst       2021-09-09 09:00:29.000000000 
+0200
@@ -3,6 +3,14 @@
 Release History
 ===============
 
+2.28.1
+++++++
+* No changes
+
+2.28.0
+++++++
+* Conditional Access: Show `--scope` for `az login` message when failed to 
refresh the access token (#17738)
+
 2.27.2
 ++++++
 * No changes
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-core-2.27.2/PKG-INFO 
new/azure-cli-core-2.28.1/PKG-INFO
--- old/azure-cli-core-2.27.2/PKG-INFO  2021-08-23 05:32:40.267739800 +0200
+++ new/azure-cli-core-2.28.1/PKG-INFO  2021-09-09 09:00:43.452860600 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: azure-cli-core
-Version: 2.27.2
+Version: 2.28.1
 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.27.2/azure/cli/core/__init__.py 
new/azure-cli-core-2.28.1/azure/cli/core/__init__.py
--- old/azure-cli-core-2.27.2/azure/cli/core/__init__.py        2021-08-23 
05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure/cli/core/__init__.py        2021-09-09 
09:00:29.000000000 +0200
@@ -4,7 +4,7 @@
 # 
--------------------------------------------------------------------------------------------
 # pylint: disable=line-too-long
 
-__version__ = "2.27.2"
+__version__ = "2.28.1"
 
 import os
 import sys
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-core-2.27.2/azure/cli/core/_profile.py 
new/azure-cli-core-2.28.1/azure/cli/core/_profile.py
--- old/azure-cli-core-2.27.2/azure/cli/core/_profile.py        2021-08-23 
05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure/cli/core/_profile.py        2021-09-09 
09:00:29.000000000 +0200
@@ -19,7 +19,7 @@
 from azure.cli.core._environment import get_config_dir
 from azure.cli.core._session import ACCOUNT
 from azure.cli.core.util import get_file_json, in_cloud_console, 
open_page_in_browser, can_launch_browser,\
-    is_windows, is_wsl, scopes_to_resource
+    is_windows, is_wsl, scopes_to_resource, resource_to_scopes
 from azure.cli.core.cloud import get_active_cloud, set_cloud_subscription
 
 logger = get_logger(__name__)
@@ -574,11 +574,7 @@
                            "Please run `az login` with a user account or a 
service principal.")
 
         if identity_type is None:
-            def _retrieve_token(sdk_resource=None):
-                # When called by
-                #   - Track 1 SDK, use `resource` specified by CLI
-                #   - Track 2 SDK, use `sdk_resource` specified by SDK and 
ignore `resource` specified by CLI
-                token_resource = sdk_resource or resource
+            def _retrieve_token(token_resource):
                 logger.debug("Retrieving token from ADAL for resource %r", 
token_resource)
 
                 if in_cloud_console() and 
account[_USER_ENTITY].get(_CLOUD_SHELL_ID):
@@ -591,8 +587,7 @@
                                                                               
account[_TENANT_ID],
                                                                               
use_cert_sn_issuer)
 
-            def _retrieve_tokens_from_external_tenants(sdk_resource=None):
-                token_resource = sdk_resource or resource
+            def _retrieve_tokens_from_external_tenants(token_resource):
                 logger.debug("Retrieving token from ADAL for external tenants 
and resource %r", token_resource)
 
                 external_tokens = []
@@ -607,7 +602,8 @@
 
             from azure.cli.core.adal_authentication import AdalAuthentication
             auth_object = AdalAuthentication(_retrieve_token,
-                                             
_retrieve_tokens_from_external_tenants if external_tenants_info else None)
+                                             
_retrieve_tokens_from_external_tenants if external_tenants_info else None,
+                                             resource=resource)
         else:
             if self._msi_creds is None:
                 self._msi_creds = 
MsiAccountTypes.msi_auth_factory(identity_type, identity_id, resource)
@@ -630,6 +626,19 @@
         import posixpath
         authority = 
posixpath.join(self.cli_ctx.cloud.endpoints.active_directory, tenant)
 
+        # Raise error for managed identity and Cloud Shell
+        not_support_message = "VM SSH currently doesn't support {}."
+
+        # managed identity
+        managed_identity_type, _ = Profile._try_parse_msi_account_name(account)
+        if managed_identity_type:
+            raise CLIError(not_support_message.format("managed identity"))
+
+        # Cloud Shell
+        if in_cloud_console() and account[_USER_ENTITY].get(_CLOUD_SHELL_ID):
+            raise CLIError(not_support_message.format("Cloud Shell"))
+
+        # user
         if identity_type == _USER:
             # Use ARM as resource to get the refresh token from ADAL token 
cache
             resource = 
self.cli_ctx.cloud.endpoints.active_directory_resource_id
@@ -649,6 +658,7 @@
                 token_entry = self._login_with_authorization_code_flow(tenant, 
scopes_to_resource(scopes))
                 result = 
cred.acquire_token_by_refresh_token(token_entry['refreshToken'], scopes, 
data=data)
 
+        # service principal
         elif identity_type == _SERVICE_PRINCIPAL:
             from azure.cli.core.msal_authentication import 
ServicePrincipalCredential
 
@@ -656,11 +666,12 @@
             sp_credential = 
self._creds_cache.retrieve_cred_for_service_principal(sp_id)
             cred = ServicePrincipalCredential(sp_id, 
secret_or_certificate=sp_credential, authority=authority)
             result = cred.get_token(scopes=scopes, data=data)
+
         else:
-            raise CLIError("Identity type {} is currently 
unsupported".format(identity_type))
+            raise CLIError("Unknown identity type {}".format(identity_type))
 
         if 'error' in result:
-            from azure.cli.core.adal_authentication import aad_error_handler
+            from azure.cli.core.auth.util import aad_error_handler
             aad_error_handler(result)
 
         return username_or_sp_id, result["access_token"]
@@ -706,7 +717,7 @@
                                                                                
    use_cert_sn_issuer)
             except adal.AdalError as ex:
                 from azure.cli.core.adal_authentication import 
adal_error_handler
-                adal_error_handler(ex)
+                adal_error_handler(ex, scopes=resource_to_scopes(resource))
         return (creds,
                 None if tenant else str(account[_SUBSCRIPTION_ID]),
                 str(tenant if tenant else account[_TENANT_ID]))
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-core-2.27.2/azure/cli/core/adal_authentication.py 
new/azure-cli-core-2.28.1/azure/cli/core/adal_authentication.py
--- old/azure-cli-core-2.27.2/azure/cli/core/adal_authentication.py     
2021-08-23 05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure/cli/core/adal_authentication.py     
2021-09-09 09:00:29.000000000 +0200
@@ -9,7 +9,7 @@
 from msrest.authentication import Authentication
 from msrestazure.azure_active_directory import MSIAuthentication
 from azure.core.credentials import AccessToken
-from azure.cli.core.util import in_cloud_console, scopes_to_resource
+from azure.cli.core.util import in_cloud_console, scopes_to_resource, 
resource_to_scopes
 
 from knack.util import CLIError
 from knack.log import get_logger
@@ -19,7 +19,7 @@
 
 class AdalAuthentication(Authentication):  # pylint: 
disable=too-few-public-methods
 
-    def __init__(self, token_retriever, external_tenant_token_retriever=None):
+    def __init__(self, token_retriever, external_tenant_token_retriever=None, 
resource=None):
         # DO NOT call _token_retriever from outside azure-cli-core. It is only 
available for user or
         # Service Principal credential (AdalAuthentication), but not for 
Managed Identity credential
         # (MSIAuthenticationWrapper).
@@ -28,16 +28,23 @@
         #   - AdalAuthentication.get_token, which is designed for Track 2 SDKs
         self._token_retriever = token_retriever
         self._external_tenant_token_retriever = external_tenant_token_retriever
+        self._resource = resource
 
     def _get_token(self, sdk_resource=None):
         """
         :param sdk_resource: `resource` converted from Track 2 SDK's `scopes`
         """
+
+        # When called by
+        #   - Track 1 SDK, use `resource` specified by CLI
+        #   - Track 2 SDK, use `sdk_resource` specified by SDK and ignore 
`resource` specified by CLI
+        token_resource = sdk_resource or self._resource
+
         external_tenant_tokens = None
         try:
-            scheme, token, token_entry = self._token_retriever(sdk_resource)
+            scheme, token, token_entry = self._token_retriever(token_resource)
             if self._external_tenant_token_retriever:
-                external_tenant_tokens = 
self._external_tenant_token_retriever(sdk_resource)
+                external_tenant_tokens = 
self._external_tenant_token_retriever(token_resource)
         except CLIError as err:
             if in_cloud_console():
                 AdalAuthentication._log_hostname()
@@ -45,7 +52,7 @@
         except adal.AdalError as err:
             if in_cloud_console():
                 AdalAuthentication._log_hostname()
-            adal_error_handler(err)
+            adal_error_handler(err, scopes=resource_to_scopes(token_resource))
         except requests.exceptions.SSLError as err:
             from .util import SSLERROR_TEMPLATE
             raise CLIError(SSLERROR_TEMPLATE.format(str(err)))
@@ -236,24 +243,11 @@
     return dt.timestamp()
 
 
-def aad_error_handler(error: dict):
-    """ Handle the error from AAD server returned by ADAL or MSAL. """
-    login_message = ("To re-authenticate, please {}. If the problem persists, "
-                     "please contact your tenant administrator."
-                     .format("refresh Azure Portal" if in_cloud_console() else 
"run `az login`"))
-
-    # 
https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes
-    # Search for an error code at https://login.microsoftonline.com/error
-    msg = error.get('error_description')
-
-    from azure.cli.core.azclierror import AuthenticationError
-    raise AuthenticationError(msg, login_message)
-
-
-def adal_error_handler(err: adal.AdalError):
+def adal_error_handler(err: adal.AdalError, **kwargs):
     """ Handle AdalError. """
     try:
-        aad_error_handler(err.error_response)
+        from azure.cli.core.auth.util import aad_error_handler
+        aad_error_handler(err.error_response, **kwargs)
     except AttributeError:
         # In case of AdalError created as
         #   AdalError('More than one token matches the criteria. The result is 
ambiguous.')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-core-2.27.2/azure/cli/core/auth/__init__.py 
new/azure-cli-core-2.28.1/azure/cli/core/auth/__init__.py
--- old/azure-cli-core-2.27.2/azure/cli/core/auth/__init__.py   1970-01-01 
01:00:00.000000000 +0100
+++ new/azure-cli-core-2.28.1/azure/cli/core/auth/__init__.py   2021-09-09 
09:00:29.000000000 +0200
@@ -0,0 +1,4 @@
+# 
--------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for 
license information.
+# 
--------------------------------------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-core-2.27.2/azure/cli/core/auth/util.py 
new/azure-cli-core-2.28.1/azure/cli/core/auth/util.py
--- old/azure-cli-core-2.27.2/azure/cli/core/auth/util.py       1970-01-01 
01:00:00.000000000 +0100
+++ new/azure-cli-core-2.28.1/azure/cli/core/auth/util.py       2021-09-09 
09:00:29.000000000 +0200
@@ -0,0 +1,45 @@
+# 
--------------------------------------------------------------------------------------------
+# Copyright (c) Microsoft Corporation. All rights reserved.
+# Licensed under the MIT License. See License.txt in the project root for 
license information.
+# 
--------------------------------------------------------------------------------------------
+
+
+def aad_error_handler(error, **kwargs):
+    """ Handle the error from AAD server returned by ADAL or MSAL. """
+
+    # 
https://docs.microsoft.com/en-us/azure/active-directory/develop/reference-aadsts-error-codes
+    # Search for an error code at https://login.microsoftonline.com/error
+    msg = error.get('error_description')
+    login_message = _generate_login_message(**kwargs)
+
+    from azure.cli.core.azclierror import AuthenticationError
+    raise AuthenticationError(msg, recommendation=login_message)
+
+
+def _generate_login_command(scopes=None):
+    login_command = ['az login']
+
+    if scopes:
+        login_command.append('--scope {}'.format(' '.join(scopes)))
+
+    return ' '.join(login_command)
+
+
+def _generate_login_message(**kwargs):
+    from azure.cli.core.util import in_cloud_console
+    login_command = _generate_login_command(**kwargs)
+
+    msg = "To re-authenticate, please {}" .format(
+        "refresh Azure Portal." if in_cloud_console() else 
"run:\n{}".format(login_command))
+
+    return msg
+
+
+def decode_access_token(access_token):
+    # Decode the access token. We can do the same with https://jwt.ms
+    from msal.oauth2cli.oidc import decode_part
+    import json
+
+    # Access token consists of headers.claims.signature. Decode the claim part
+    decoded_str = decode_part(access_token.split('.')[1])
+    return json.loads(decoded_str)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-core-2.27.2/azure/cli/core/extension/operations.py 
new/azure-cli-core-2.28.1/azure/cli/core/extension/operations.py
--- old/azure-cli-core-2.27.2/azure/cli/core/extension/operations.py    
2021-08-23 05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure/cli/core/extension/operations.py    
2021-09-09 09:00:29.000000000 +0200
@@ -18,7 +18,7 @@
 from packaging.version import parse
 
 from azure.cli.core import CommandIndex
-from azure.cli.core.util import CLIError, reload_module
+from azure.cli.core.util import CLIError, reload_module, rmtree_with_retry
 from azure.cli.core.extension import (extension_exists, build_extension_path, 
get_extensions, get_extension_modname,
                                       get_extension, ext_compat_with_cli,
                                       EXT_METADATA_ISPREVIEW, 
EXT_METADATA_ISEXPERIMENTAL,
@@ -559,22 +559,3 @@
                      "for your distribution or change the above file 
accordingly.")
         logger.debug("Linux distro check: %s has '%s', current distro is '%s'",
                      LIST_FILE_PATH, stored_linux_dist_name, 
current_linux_dist_name)
-
-
-def rmtree_with_retry(path):
-    # A workaround for https://bugs.python.org/issue33240
-    # Retry shutil.rmtree several times, but even if it fails after several 
retries, don't block the command execution.
-    retry_num = 3
-    import time
-    while True:
-        try:
-            shutil.rmtree(path)
-            return
-        except OSError as err:
-            if retry_num > 0:
-                logger.warning("Failed to delete '%s': %s. Retrying ...", 
path, err)
-                retry_num -= 1
-                time.sleep(1)
-            else:
-                logger.warning("Failed to delete '%s': %s. You may try to 
delete it manually.", path, err)
-                break
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-core-2.27.2/azure/cli/core/profiles/_shared.py 
new/azure-cli-core-2.28.1/azure/cli/core/profiles/_shared.py
--- old/azure-cli-core-2.27.2/azure/cli/core/profiles/_shared.py        
2021-08-23 05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure/cli/core/profiles/_shared.py        
2021-09-09 09:00:29.000000000 +0200
@@ -63,7 +63,7 @@
     MGMT_APPSERVICE = ('azure.mgmt.web', 'WebSiteManagementClient')
     MGMT_IOTCENTRAL = ('azure.mgmt.iotcentral', 'IotCentralClient')
     MGMT_IOTHUB = ('azure.mgmt.iothub', 'IotHubClient')
-    MGMT_ARO = ('azure.mgmt.redhatopenshift', 'AzureRedHatOpenShiftClient')
+    MGMT_ARO = ('azure.mgmt.redhatopenshift', 'AzureRedHatOpenShift4Client')
     MGMT_DATABOXEDGE = ('azure.mgmt.databoxedge', 
'DataBoxEdgeManagementClient')
     MGMT_CUSTOMLOCATION = ('azure.mgmt.extendedlocation', 'CustomLocations')
     MGMT_CONTAINERSERVICE = ('azure.mgmt.containerservice', 
'ContainerServiceClient')
@@ -143,7 +143,7 @@
     'latest': {
         ResourceType.MGMT_STORAGE: '2021-04-01',
         ResourceType.MGMT_NETWORK: '2021-02-01',
-        ResourceType.MGMT_COMPUTE: SDKProfile('2021-03-01', {
+        ResourceType.MGMT_COMPUTE: SDKProfile('2021-04-01', {
             'resource_skus': '2019-04-01',
             'disks': '2020-12-01',
             'disk_encryption_sets': '2020-12-01',
@@ -153,9 +153,9 @@
             'gallery_images': '2020-09-30',
             'gallery_image_versions': '2020-09-30',
             'shared_galleries': '2020-09-30',
-            'virtual_machine_scale_sets': '2021-03-01'
+            'virtual_machine_scale_sets': '2021-04-01'
         }),
-        ResourceType.MGMT_RESOURCE_FEATURES: '2015-12-01',
+        ResourceType.MGMT_RESOURCE_FEATURES: '2021-07-01',
         ResourceType.MGMT_RESOURCE_LINKS: '2016-09-01',
         ResourceType.MGMT_RESOURCE_LOCKS: '2016-09-01',
         ResourceType.MGMT_RESOURCE_POLICY: '2020-09-01',
@@ -220,12 +220,12 @@
             'subscription_diagnostic_settings': '2017-05-01-preview'
         }),
         ResourceType.MGMT_APPSERVICE: '2020-09-01',
-        ResourceType.MGMT_IOTHUB: '2021-03-31',
+        ResourceType.MGMT_IOTHUB: '2021-07-01',
         ResourceType.MGMT_IOTCENTRAL: '2018-09-01',
         ResourceType.MGMT_ARO: '2020-04-30',
         ResourceType.MGMT_DATABOXEDGE: '2021-02-01-preview',
         ResourceType.MGMT_CUSTOMLOCATION: '2021-03-15-preview',
-        ResourceType.MGMT_CONTAINERSERVICE: SDKProfile('2021-05-01', {
+        ResourceType.MGMT_CONTAINERSERVICE: SDKProfile('2021-07-01', {
             'container_services': '2017-07-01',
             'open_shift_managed_clusters': '2019-09-30-preview'
         })
@@ -245,7 +245,7 @@
             'virtual_machine_scale_sets': '2020-06-01'
         }),
         ResourceType.MGMT_KEYVAULT: '2016-10-01',
-        ResourceType.MGMT_RESOURCE_FEATURES: '2015-12-01',
+        ResourceType.MGMT_RESOURCE_FEATURES: '2021-07-01',
         ResourceType.MGMT_RESOURCE_LINKS: '2016-09-01',
         ResourceType.MGMT_RESOURCE_LOCKS: '2016-09-01',
         ResourceType.MGMT_RESOURCE_POLICY: '2016-12-01',
@@ -253,7 +253,7 @@
         ResourceType.MGMT_RESOURCE_SUBSCRIPTIONS: '2016-06-01',
         ResourceType.MGMT_RESOURCE_TEMPLATESPECS: '2015-01-01',
         ResourceType.MGMT_NETWORK_DNS: '2016-04-01',
-        ResourceType.MGMT_AUTHORIZATION: SDKProfile('2016-09-01', {
+        ResourceType.MGMT_AUTHORIZATION: SDKProfile('2015-07-01', {
             'classic_administrators': '2015-06-01',
             'policy_assignments': '2016-12-01',
             'policy_definitions': '2016-12-01'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-core-2.27.2/azure/cli/core/style.py 
new/azure-cli-core-2.28.1/azure/cli/core/style.py
--- old/azure-cli-core-2.27.2/azure/cli/core/style.py   2021-08-23 
05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure/cli/core/style.py   2021-09-09 
09:00:29.000000000 +0200
@@ -152,12 +152,15 @@
     if isinstance(theme, str):
         theme = get_theme_dict(theme)
 
-    # Cache the value of is_legacy_powershell
-    if not hasattr(format_styled_text, "_is_legacy_powershell"):
-        from azure.cli.core.util import get_parent_proc_name
-        is_legacy_powershell = not is_modern_terminal() and 
get_parent_proc_name() == "powershell.exe"
-        setattr(format_styled_text, "_is_legacy_powershell", 
is_legacy_powershell)
-    is_legacy_powershell = getattr(format_styled_text, "_is_legacy_powershell")
+    # If style is enabled, cache the value of is_legacy_powershell.
+    # Otherwise if theme is None, is_legacy_powershell is meaningless.
+    is_legacy_powershell = None
+    if theme:
+        if not hasattr(format_styled_text, "_is_legacy_powershell"):
+            from azure.cli.core.util import get_parent_proc_name
+            is_legacy_powershell = not is_modern_terminal() and 
get_parent_proc_name() == "powershell.exe"
+            setattr(format_styled_text, "_is_legacy_powershell", 
is_legacy_powershell)
+        is_legacy_powershell = getattr(format_styled_text, 
"_is_legacy_powershell")
 
     # 
https://python-prompt-toolkit.readthedocs.io/en/stable/pages/printing_text.html#style-text-tuples
     formatted_parts = []
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-core-2.27.2/azure/cli/core/util.py 
new/azure-cli-core-2.28.1/azure/cli/core/util.py
--- old/azure-cli-core-2.27.2/azure/cli/core/util.py    2021-08-23 
05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure/cli/core/util.py    2021-09-09 
09:00:29.000000000 +0200
@@ -4,17 +4,18 @@
 # 
--------------------------------------------------------------------------------------------
 # pylint: disable=too-many-lines
 
-import sys
-import json
-import getpass
 import base64
 import binascii
+import getpass
+import json
+import logging
+import os
 import platform
-import ssl
 import re
-import logging
-
+import ssl
+import sys
 from urllib.request import urlopen
+
 from knack.log import get_logger
 from knack.util import CLIError, to_snake_case
 
@@ -271,7 +272,7 @@
 def get_latest_from_github(package_path='azure-cli'):
     try:
         import requests
-        git_url = 
"https://raw.githubusercontent.com/Azure/azure-cli/master/src/{}/setup.py".format(package_path)
+        git_url = 
"https://raw.githubusercontent.com/Azure/azure-cli/main/src/{}/setup.py".format(package_path)
         response = requests.get(git_url, timeout=10)
         if response.status_code != 200:
             logger.info("Failed to fetch the latest version from '%s' with 
status code '%s' and reason '%s'",
@@ -379,7 +380,6 @@
             else:
                 _print(ext.name.ljust(20) + (ext.version or 
'Unknown').rjust(20))
         _print()
-    import os
     _print("Python location '{}'".format(os.path.abspath(sys.executable)))
     _print("Extensions directory '{}'".format(EXTENSIONS_DIR))
     if os.path.isdir(EXTENSIONS_SYS_DIR) and os.listdir(EXTENSIONS_SYS_DIR):
@@ -522,8 +522,8 @@
                              
"https://docs.microsoft.com/cli/azure/use-cli-effectively#quoting-issues";
 
             # Recommendation especially for PowerShell
-            parent_proc = get_parent_proc_name().lower()
-            if parent_proc in ("powershell.exe", "pwsh.exe"):
+            parent_proc = get_parent_proc_name()
+            if parent_proc and parent_proc.lower() in ("powershell.exe", 
"pwsh.exe"):
                 recommendation += "\nPowerShell requires additional quoting 
rules. See " \
                                   
"https://github.com/Azure/azure-cli/blob/dev/doc/quoting-issues-with-powershell.md";
 
@@ -581,7 +581,6 @@
 
 
 def in_cloud_console():
-    import os
     return os.environ.get('ACC_CLOUD', None)
 
 
@@ -610,7 +609,6 @@
 
 
 def should_disable_connection_verify():
-    import os
     return bool(os.environ.get(DISABLE_VERIFY_VARIABLE_NAME))
 
 
@@ -657,7 +655,8 @@
         try:
             # 
https://docs.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_powershell_exe
             # Ampersand (&) should be quoted
-            return subprocess.Popen(['powershell.exe', '-NoProfile', 
'-Command', 'Start-Process "{}"'.format(url)])
+            return subprocess.Popen(
+                ['powershell.exe', '-NoProfile', '-Command', 'Start-Process 
"{}"'.format(url)]).wait()
         except OSError:  # WSL might be too old  # FileNotFoundError 
introduced in Python 3
             pass
     elif platform_name == 'darwin':
@@ -695,7 +694,6 @@
 
 
 def can_launch_browser():
-    import os
     import webbrowser
     platform_name, _ = _get_platform_info()
     if is_wsl() or platform_name != 'linux':
@@ -829,7 +827,6 @@
     # Borrow AZURE_HTTP_USER_AGENT from msrest
     # 
https://github.com/Azure/msrest-for-python/blob/4cc8bc84e96036f03b34716466230fb257e27b36/msrest/pipeline/universal.py#L70
     _ENV_ADDITIONAL_USER_AGENT = 'AZURE_HTTP_USER_AGENT'
-    import os
     if _ENV_ADDITIONAL_USER_AGENT in os.environ:
         agents.append(os.environ[_ENV_ADDITIONAL_USER_AGENT])
 
@@ -1097,7 +1094,6 @@
 
     agents = ["AZURECLI/{}".format(core_version)]
 
-    import os
     from azure.cli.core._environment import _ENV_AZ_INSTALLER
     if _ENV_AZ_INSTALLER in os.environ:
         agents.append('({})'.format(os.environ[_ENV_AZ_INSTALLER]))
@@ -1240,28 +1236,33 @@
         logger.debug(ex)
         return None
 
-    import os
-    parent = psutil.Process(os.getpid()).parent()
+    try:
+        parent = psutil.Process(os.getpid()).parent()
 
-    # On Windows, when CLI is run inside a virtual env, there will be 2 
python.exe.
-    if parent and parent.name().lower() == 'python.exe':
-        parent = parent.parent()
-
-    if parent:
-        # On Windows, powershell.exe launches cmd.exe to launch python.exe.
-        grandparent = parent.parent()
-        if grandparent:
-            grandparent_name = grandparent.name().lower()
-            if grandparent_name in ("powershell.exe", "pwsh.exe"):
-                return grandparent.name()
-        # if powershell.exe or pwsh.exe is not the grandparent, simply return 
the parent's name.
-        return parent.name()
+        # On Windows, when CLI is run inside a virtual env, there will be 2 
python.exe.
+        if parent and parent.name().lower() == 'python.exe':
+            parent = parent.parent()
+
+        if parent:
+            # On Windows, powershell.exe launches cmd.exe to launch python.exe.
+            grandparent = parent.parent()
+            if grandparent:
+                grandparent_name = grandparent.name().lower()
+                if grandparent_name in ("powershell.exe", "pwsh.exe"):
+                    return grandparent.name()
+            # if powershell.exe or pwsh.exe is not the grandparent, simply 
return the parent's name.
+            return parent.name()
+    except psutil.AccessDenied as ex:
+        # Ignore due to https://github.com/giampaolo/psutil/issues/1980
+        logger.debug(ex)
     return None
 
 
 def get_parent_proc_name():
     # This function wraps _get_parent_proc_name, as psutil calls are 
time-consuming, so use a
     # function-level cache to save the result.
+    # NOTE: The return value may be None if getting parent proc name fails, so 
always remember to
+    # check it first before calling string methods like lower().
     if not hasattr(get_parent_proc_name, "return_value"):
         parent_proc_name = _get_parent_proc_name()
         setattr(get_parent_proc_name, "return_value", parent_proc_name)
@@ -1272,3 +1273,23 @@
     """In addition to knack.util.is_modern_terminal, detect Cloud Shell."""
     import knack.util
     return knack.util.is_modern_terminal() or in_cloud_console()
+
+
+def rmtree_with_retry(path):
+    # A workaround for https://bugs.python.org/issue33240
+    # Retry shutil.rmtree several times, but even if it fails after several 
retries, don't block the command execution.
+    retry_num = 3
+    import time
+    while True:
+        try:
+            import shutil
+            shutil.rmtree(path)
+            return
+        except OSError as err:
+            if retry_num > 0:
+                logger.warning("Failed to delete '%s': %s. Retrying ...", 
path, err)
+                retry_num -= 1
+                time.sleep(1)
+            else:
+                logger.warning("Failed to delete '%s': %s. You may try to 
delete it manually.", path, err)
+                break
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/azure-cli-core-2.27.2/azure_cli_core.egg-info/PKG-INFO 
new/azure-cli-core-2.28.1/azure_cli_core.egg-info/PKG-INFO
--- old/azure-cli-core-2.27.2/azure_cli_core.egg-info/PKG-INFO  2021-08-23 
05:32:40.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure_cli_core.egg-info/PKG-INFO  2021-09-09 
09:00:43.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: azure-cli-core
-Version: 2.27.2
+Version: 2.28.1
 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.27.2/azure_cli_core.egg-info/SOURCES.txt 
new/azure-cli-core-2.28.1/azure_cli_core.egg-info/SOURCES.txt
--- old/azure-cli-core-2.27.2/azure_cli_core.egg-info/SOURCES.txt       
2021-08-23 05:32:40.000000000 +0200
+++ new/azure-cli-core-2.28.1/azure_cli_core.egg-info/SOURCES.txt       
2021-09-09 09:00:43.000000000 +0200
@@ -32,6 +32,8 @@
 azure/cli/core/style.py
 azure/cli/core/telemetry.py
 azure/cli/core/util.py
+azure/cli/core/auth/__init__.py
+azure/cli/core/auth/util.py
 azure/cli/core/auth_landing_pages/fail.html
 azure/cli/core/auth_landing_pages/ok.html
 azure/cli/core/commands/__init__.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/azure-cli-core-2.27.2/setup.py 
new/azure-cli-core-2.28.1/setup.py
--- old/azure-cli-core-2.27.2/setup.py  2021-08-23 05:32:32.000000000 +0200
+++ new/azure-cli-core-2.28.1/setup.py  2021-09-09 09:00:29.000000000 +0200
@@ -8,7 +8,7 @@
 from codecs import open
 from setuptools import setup, find_packages
 
-VERSION = "2.27.2"
+VERSION = "2.28.1"
 
 # If we have source, validate that our version numbers match
 # This should prevent uploading releases with mismatched versions.

Reply via email to