Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions src/azure-cli-core/azure/cli/core/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -115,12 +115,12 @@ def refresh_request_id(self):
import uuid
self.data['headers']['x-ms-client-request-id'] = str(uuid.uuid1())

def get_progress_controller(self, det=False):
def get_progress_controller(self, det=False, spinner=None):
import azure.cli.core.commands.progress as progress
if not self.progress_controller:
self.progress_controller = progress.ProgressHook()

self.progress_controller.init_progress(progress.get_progress_view(det))
self.progress_controller.init_progress(progress.get_progress_view(det, spinner=spinner))
return self.progress_controller

def get_cli_version(self):
Expand Down
19 changes: 12 additions & 7 deletions src/azure-cli-core/azure/cli/core/commands/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@
get_command_type_kwarg, read_file_content, get_arg_list, poller_classes)
from azure.cli.core.local_context import LocalContextAction
import azure.cli.core.telemetry as telemetry

from azure.cli.core.commands.progress import IndeterminateProgressBar

from knack.arguments import CLICommandArgument
from knack.commands import CLICommand, CommandGroup, PREVIEW_EXPERIMENTAL_CONFLICT_ERROR
Expand Down Expand Up @@ -869,14 +869,16 @@ def _validate_arg_level(self, ns, **_): # pylint: disable=no-self-use


class LongRunningOperation: # pylint: disable=too-few-public-methods
def __init__(self, cli_ctx, start_msg='', finish_msg='', poller_done_interval_ms=1000.0):
def __init__(self, cli_ctx, start_msg='', finish_msg='', poller_done_interval_ms=500.0,
progress_bar=None):

self.cli_ctx = cli_ctx
self.start_msg = start_msg
self.finish_msg = finish_msg
self.poller_done_interval_ms = poller_done_interval_ms
self.deploy_dict = {}
self.last_progress_report = datetime.datetime.now()
self.progress_bar = progress_bar if progress_bar is not None else IndeterminateProgressBar(cli_ctx)

def _delay(self):
time.sleep(self.poller_done_interval_ms / 1000.0)
Expand Down Expand Up @@ -948,16 +950,17 @@ def __call__(self, poller):
from msrest.exceptions import ClientException

correlation_message = ''
self.cli_ctx.get_progress_controller().begin()
self.progress_bar.begin()
correlation_id = None

cli_logger = get_logger() # get CLI logger which has the level set through command lines
is_verbose = any(handler.level <= logs.INFO for handler in cli_logger.handlers)

telemetry.poll_start()
poll_flag = False
while not poller.done():
poll_flag = True
self.cli_ctx.get_progress_controller().add(message='Running')

try:
# pylint: disable=protected-access
correlation_id = json.loads(
Expand All @@ -975,22 +978,24 @@ def __call__(self, poller):
except Exception as ex: # pylint: disable=broad-except
logger.warning('%s during progress reporting: %s', getattr(type(ex), '__name__', type(ex)), ex)
try:
self.progress_bar.update_progress()
self._delay()
except KeyboardInterrupt:
self.cli_ctx.get_progress_controller().stop()
self.progress_bar.stop()
logger.error('Long-running operation wait cancelled. %s', correlation_message)
raise

try:
result = poller.result()
except ClientException as client_exception:
from azure.cli.core.commands.arm import handle_long_running_operation_exception
self.cli_ctx.get_progress_controller().stop()
self.progress_bar.stop()
handle_long_running_operation_exception(client_exception)

self.cli_ctx.get_progress_controller().end()
self.progress_bar.end()
if poll_flag:
telemetry.poll_end()

return result


Expand Down
33 changes: 29 additions & 4 deletions src/azure-cli-core/azure/cli/core/commands/progress.py
Original file line number Diff line number Diff line change
Expand Up @@ -103,10 +103,10 @@ def is_running(self):

class IndeterminateStandardOut(ProgressViewBase):
""" custom output for progress reporting """
def __init__(self, out=None):
def __init__(self, out=None, spinner=None):
super(IndeterminateStandardOut, self).__init__(
out if out else sys.stderr)
self.spinner = None
self.spinner = spinner

def write(self, args):
"""
Expand Down Expand Up @@ -166,8 +166,33 @@ def flush(self):
self.out.flush()


def get_progress_view(determinant=False, outstream=sys.stderr):
def get_progress_view(determinant=False, outstream=sys.stderr, spinner=None):
""" gets your view """
if determinant:
return DeterminateStandardOut(out=outstream)
return IndeterminateStandardOut(out=outstream)
return IndeterminateStandardOut(out=outstream, spinner=spinner)


class IndeterminateProgressBar:
""" Define progress bar update view """
def __init__(self, cli_ctx, message="Running"):
self.cli_ctx = cli_ctx
Copy link
Member

@jiasli jiasli Mar 11, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider dropping cli_ctx reference if it is unused.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is used in L181 to get progress controller

self.message = message
self.hook = self.cli_ctx.get_progress_controller(
det=False,
spinner=humanfriendly.Spinner( # pylint: disable=no-member
label='Running',
stream=sys.stderr,
hide_cursor=False))

def begin(self):
self.hook.begin()

def stop(self):
self.hook.stop()

def update_progress(self):
self.hook.add(message=self.message)

def end(self):
self.hook.end()
Original file line number Diff line number Diff line change
Expand Up @@ -412,7 +412,7 @@ def test_what_if_exclude_change_types(self, long_running_operation_stub):
])

# Act.
result = _what_if_deploy_arm_template_core(cmd, mock.MagicMock(), True, ["create", "igNoRE"])
result = _what_if_deploy_arm_template_core(cmd.cli_ctx, mock.MagicMock(), True, ["create", "igNoRE"])

# Assert.
self.assertEqual(1, len(result.changes))
Expand Down