Skip to content

Commit dd2a672

Browse files
authored
{Core} Lazy imports & lighter stdlib replacements (#33055)
1 parent 9a8aa57 commit dd2a672

File tree

17 files changed

+82
-56
lines changed

17 files changed

+82
-56
lines changed

src/azure-cli-core/azure/cli/core/__init__.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,7 @@
99
import os
1010
import sys
1111
import json
12-
import timeit
13-
import concurrent.futures
14-
from concurrent.futures import ThreadPoolExecutor
12+
import time
1513

1614
from knack.cli import CLI
1715
from knack.commands import CLICommandsLoader
@@ -322,14 +320,14 @@ def _update_command_table_from_modules(args, command_modules=None):
322320
except ImportError as e:
323321
logger.warning(e)
324322

325-
start_time = timeit.default_timer()
323+
start_time = time.perf_counter()
326324
logger.debug("Loading command modules...")
327325
results = self._load_modules(args, command_modules)
328326

329327
count, cumulative_group_count, cumulative_command_count = \
330328
self._process_results_with_timing(results)
331329

332-
total_elapsed_time = timeit.default_timer() - start_time
330+
total_elapsed_time = time.perf_counter() - start_time
333331
# Summary line
334332
logger.debug(self.item_format_string,
335333
"Total ({})".format(count), total_elapsed_time,
@@ -404,7 +402,7 @@ def _filter_modname(extensions):
404402
# Add to the map. This needs to happen before we load commands as registering a command
405403
# from an extension requires this map to be up-to-date.
406404
# self._mod_to_ext_map[ext_mod] = ext_name
407-
start_time = timeit.default_timer()
405+
start_time = time.perf_counter()
408406
extension_command_table, extension_group_table, extension_command_loader = \
409407
_load_extension_command_loader(self, args, ext_mod)
410408
import_extension_breaking_changes(ext_mod)
@@ -427,7 +425,7 @@ def _filter_modname(extensions):
427425
self.command_table.update(extension_command_table)
428426
self.command_group_table.update(extension_group_table)
429427

430-
elapsed_time = timeit.default_timer() - start_time
428+
elapsed_time = time.perf_counter() - start_time
431429
logger.debug(self.item_ext_format_string, ext_name, elapsed_time,
432430
len(extension_group_table), len(extension_command_table),
433431
ext_dir)
@@ -667,6 +665,8 @@ def load_arguments(self, command=None):
667665

668666
def _load_modules(self, args, command_modules):
669667
"""Load command modules using ThreadPoolExecutor with timeout protection."""
668+
import concurrent.futures
669+
from concurrent.futures import ThreadPoolExecutor
670670
from azure.cli.core.commands import BLOCKED_MODS
671671

672672
results = []
@@ -708,10 +708,10 @@ def _load_single_module(self, mod, args):
708708
from azure.cli.core.commands import _load_module_command_loader
709709
import traceback
710710
try:
711-
start_time = timeit.default_timer()
711+
start_time = time.perf_counter()
712712
module_command_table, module_group_table, command_loader = _load_module_command_loader(self, args, mod)
713713
import_module_breaking_changes(mod)
714-
elapsed_time = timeit.default_timer() - start_time
714+
elapsed_time = time.perf_counter() - start_time
715715
return ModuleLoadResult(mod, module_command_table, module_group_table, elapsed_time, command_loader=command_loader)
716716
except Exception as ex: # pylint: disable=broad-except
717717
tb_str = traceback.format_exc()
@@ -1227,7 +1227,7 @@ def update(self, command_table):
12271227
12281228
:param command_table: The command table built by azure.cli.core.MainCommandsLoader.load_command_table
12291229
"""
1230-
start_time = timeit.default_timer()
1230+
start_time = time.perf_counter()
12311231
self.INDEX[self._COMMAND_INDEX_VERSION] = __version__
12321232
self.INDEX[self._COMMAND_INDEX_CLOUD_PROFILE] = self.cloud_profile
12331233
from collections import defaultdict
@@ -1242,7 +1242,7 @@ def update(self, command_table):
12421242
if module_name not in index[top_command]:
12431243
index[top_command].append(module_name)
12441244

1245-
elapsed_time = timeit.default_timer() - start_time
1245+
elapsed_time = time.perf_counter() - start_time
12461246
self.INDEX[self._COMMAND_INDEX] = index
12471247

12481248
self.update_extension_index(command_table)

src/azure-cli-core/azure/cli/core/_help_loaders.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
from knack.util import CLIError
1212
from knack.log import get_logger
1313

14-
import yaml
15-
1614
logger = get_logger(__name__)
1715

1816
try:
@@ -132,6 +130,8 @@ def _get_yaml_help_files_list(nouns, cmd_loader_map_ref):
132130

133131
@staticmethod
134132
def _parse_yaml_from_string(text, help_file_path):
133+
import yaml
134+
135135
dir_name, base_name = os.path.split(help_file_path)
136136
pretty_file_path = os.path.join(os.path.basename(dir_name), base_name)
137137

src/azure-cli-core/azure/cli/core/aaz/_client.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
from azure.core.polling.base_polling import LocationPolling, StatusCheckPolling
99
from abc import abstractmethod
1010

11-
from ._poller import AAZNoPolling, AAZBasePolling
1211
from azure.cli.core.cloud import (CloudEndpointNotSetException, CloudSuffixNotSetException,
1312
CloudNameEnum as _CloudNameEnum)
1413

@@ -111,6 +110,7 @@ def send_request(self, request, stream=False, **kwargs): # pylint: disable=argu
111110
def build_lro_polling(self, no_wait, initial_session, deserialization_callback, error_callback,
112111
lro_options=None, path_format_arguments=None):
113112
from azure.core.polling.base_polling import OperationResourcePolling
113+
from ._poller import AAZNoPolling, AAZBasePolling
114114
if no_wait == True: # noqa: E712, pylint: disable=singleton-comparison
115115
polling = AAZNoPolling()
116116
else:
@@ -233,6 +233,7 @@ def _build_per_call_policies(cls, ctx, **kwargs):
233233
def build_lro_polling(self, no_wait, initial_session, deserialization_callback, error_callback,
234234
lro_options=None, path_format_arguments=None):
235235
from azure.mgmt.core.polling.arm_polling import AzureAsyncOperationPolling, BodyContentPolling
236+
from ._poller import AAZNoPolling, AAZBasePolling
236237
if no_wait == True: # noqa: E712, pylint: disable=singleton-comparison
237238
polling = AAZNoPolling()
238239
else:

src/azure-cli-core/azure/cli/core/aaz/_command.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,6 @@
2222
from ._base import AAZUndefined, AAZBaseValue
2323
from ._field_type import AAZObjectType
2424
from ._paging import AAZPaged
25-
from ._poller import AAZLROPoller
2625
from ._command_ctx import AAZCommandCtx
2726
from .exceptions import AAZUnknownFieldError, AAZUnregisteredArg
2827
from .utils import get_aaz_profile_module_name
@@ -235,6 +234,7 @@ def processor(schema, result):
235234
def build_lro_poller(self, executor, extract_result):
236235
""" Build AAZLROPoller instance to support long running operation
237236
"""
237+
from ._poller import AAZLROPoller
238238
polling_generator = executor()
239239
if self.ctx.lro_no_wait:
240240
# run until yield the first polling

src/azure-cli-core/azure/cli/core/commands/__init__.py

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
get_command_type_kwarg, read_file_content, get_arg_list, poller_classes)
3030
from azure.cli.core.local_context import LocalContextAction
3131
from azure.cli.core import telemetry
32-
from azure.cli.core.commands.progress import IndeterminateProgressBar
3332

3433
from knack.arguments import CLICommandArgument
3534
from knack.commands import CLICommand, CommandGroup, PREVIEW_EXPERIMENTAL_CONFLICT_ERROR
@@ -1035,10 +1034,20 @@ def __init__(self, cli_ctx, start_msg='', finish_msg='', poller_done_interval_ms
10351034
self.deploy_dict = {}
10361035
self.last_progress_report = datetime.datetime.now()
10371036

1038-
self.progress_bar = None
1037+
self._progress_bar = None
10391038
disable_progress_bar = self.cli_ctx.config.getboolean('core', 'disable_progress_bar', False)
1040-
if not disable_progress_bar and not cli_ctx.only_show_errors:
1041-
self.progress_bar = progress_bar if progress_bar is not None else IndeterminateProgressBar(cli_ctx)
1039+
self.disable_progress_bar = disable_progress_bar or cli_ctx.only_show_errors
1040+
if not self.disable_progress_bar:
1041+
self._progress_bar = progress_bar
1042+
1043+
@property
1044+
def progress_bar(self):
1045+
if self.disable_progress_bar:
1046+
return None
1047+
if self._progress_bar is None:
1048+
from azure.cli.core.commands.progress import IndeterminateProgressBar
1049+
self._progress_bar = IndeterminateProgressBar(self.cli_ctx)
1050+
return self._progress_bar
10421051

10431052
def _delay(self):
10441053
time.sleep(self.poller_done_interval_ms / 1000.0)

src/azure-cli-core/azure/cli/core/commands/parameters.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
import argparse
8-
import platform
8+
import sys
99

1010
from azure.cli.core import EXCLUDED_PARAMS
1111
from azure.cli.core.commands.constants import CLI_PARAM_KWARGS, CLI_POSITIONAL_PARAM_KWARGS
@@ -274,7 +274,7 @@ def get_location_type(cli_ctx):
274274
validator=generate_deployment_name
275275
)
276276

277-
quotes = '""' if platform.system() == 'Windows' else "''"
277+
quotes = '""' if sys.platform == 'win32' else "''"
278278
quote_text = 'Use {} to clear existing tags.'.format(quotes)
279279

280280
tags_type = CLIArgumentType(

src/azure-cli-core/azure/cli/core/commands/progress.py

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44
# --------------------------------------------------------------------------------------------
55
import sys
66

7-
from humanfriendly.terminal.spinners import Spinner
8-
97
BAR_LEN = 70
108
EMPTY_LINE = ' ' * BAR_LEN
119

@@ -114,6 +112,7 @@ def write(self, args):
114112
:param args: dictionary containing key 'message'
115113
"""
116114
if self.spinner is None:
115+
from humanfriendly.terminal.spinners import Spinner
117116
self.spinner = Spinner( # pylint: disable=no-member
118117
label='In Progress', stream=self.out, hide_cursor=False)
119118
msg = args.get('message', 'In Progress')
@@ -178,10 +177,15 @@ def __init__(self, cli_ctx, message="Running"):
178177
self.message = message
179178
self.hook = self.cli_ctx.get_progress_controller(
180179
det=False,
181-
spinner=Spinner( # pylint: disable=no-member
182-
label='Running',
183-
stream=sys.stderr,
184-
hide_cursor=False))
180+
spinner=self._create_spinner())
181+
182+
@staticmethod
183+
def _create_spinner():
184+
from humanfriendly.terminal.spinners import Spinner
185+
return Spinner( # pylint: disable=no-member
186+
label='Running',
187+
stream=sys.stderr,
188+
hide_cursor=False)
185189

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

src/azure-cli-core/azure/cli/core/commands/validators.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55

66
import argparse
77
import time
8-
import random
98

109
from azure.cli.core.profiles import ResourceType
1110

@@ -67,6 +66,7 @@ def validate_key_value_pairs(string):
6766

6867
def generate_deployment_name(namespace):
6968
if not namespace.deployment_name:
69+
import random
7070
namespace.deployment_name = \
7171
'azurecli{}{}'.format(str(time.time()), str(random.randint(1, 100000)))
7272

src/azure-cli-core/azure/cli/core/decorators.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
that it doesn't import modules other than those in the Python Standard Library
1111
"""
1212

13-
import hashlib
1413
from functools import wraps
1514

1615
from knack.log import get_logger
@@ -43,6 +42,7 @@ def call_once(factory_func):
4342
def _wrapped(*args, **kwargs):
4443
if not factory_func.executed:
4544
factory_func.cached_result = factory_func(*args, **kwargs)
45+
factory_func.executed = True
4646

4747
return factory_func.cached_result
4848

@@ -57,6 +57,7 @@ def hash256_result(func):
5757

5858
@wraps(func)
5959
def _decorator(*args, **kwargs):
60+
import hashlib
6061
val = func(*args, **kwargs)
6162
if val is None:
6263
raise ValueError('Return value is None')

src/azure-cli-core/azure/cli/core/extension/__init__.py

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@
1010
import re
1111
from sysconfig import get_path
1212

13-
import pkginfo
1413
from knack.config import CLIConfig
1514
from knack.log import get_logger
1615
from azure.cli.core._config import GLOBAL_CONFIG_DIR, ENV_VAR_PREFIX
@@ -134,6 +133,7 @@ def get_version(self):
134133

135134
def get_metadata(self):
136135
from glob import glob
136+
import pkginfo
137137

138138
metadata = {}
139139
ext_dir = self.path or get_extension_path(self.name)
@@ -213,6 +213,8 @@ def get_version(self):
213213
return self.metadata.get('version')
214214

215215
def get_metadata(self):
216+
import pkginfo
217+
216218
metadata = {}
217219
ext_dir = self.path
218220
if not ext_dir or not os.path.isdir(ext_dir):

0 commit comments

Comments
 (0)