Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
ddf31b5
Make PrefixTrie public and implement LazyCommand class to defer loadi…
aemous May 11, 2026
dab19fb
Remove parts of functional/test_lazy.py that depend on LazyInitEmitter.
aemous May 11, 2026
494bd6a
Add license header to awscli/lazy.py.
aemous May 11, 2026
40f4027
Switch new test suite to use PyTest instead of unittest.TestCase.
aemous May 13, 2026
fdddde1
Formatting.
aemous May 13, 2026
c8b4b7b
Wrap plugins that directly register against events in handlers.py in …
aemous May 13, 2026
975f57a
Add handlers_registry.py which maps events to plugins and declares co…
aemous May 13, 2026
75d5343
Formatting.
aemous May 13, 2026
511d6cb
Update test_handlers_registry against the simplified format of handle…
aemous May 13, 2026
11b07cd
Add new functional tests to assert that all modules referenced in han…
aemous May 13, 2026
844dcce
Formatting.
aemous May 13, 2026
a454da3
Merge pull request #10299 from aws/pr/prefix-trie-lazy-command
aemous May 13, 2026
15dbbb6
Update MAIN_COMMAND_TABLE_OPS to use an enum.
aemous May 20, 2026
789f94a
Formatting.
aemous May 20, 2026
b48b0d6
Import annotations.
aemous May 20, 2026
b151d12
Merge pull request #10305 from aws/pr/handlers-registry
aemous May 21, 2026
a71fa98
Implement LazyInitEmitter for lazily loading plugins when events they…
aemous May 22, 2026
806814a
Formatting.
aemous May 22, 2026
5787b98
[v2] Implement LazyInitEmitter for deferred plugin-loading (#10343)
aemous May 27, 2026
97db2bb
Implement lazy plugin initialization.
aemous May 27, 2026
330ea61
Delete handlers.py and migrate the registry-loading code into plugin.py.
aemous May 27, 2026
369d8f4
Add eager-loading fallback to plugin.py.
aemous May 29, 2026
44c3ce9
Formatting.
aemous May 29, 2026
bf9aa0c
Switch to using single dispatch in plugin.py.
aemous May 29, 2026
34dfb7e
[v2] Implement lazy plugin initialization (#10356) from aws/pr/lazy-p…
aemous May 29, 2026
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
5 changes: 5 additions & 0 deletions .changes/next-release/enhancement-Performance-9167.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"type": "enhancement",
"category": "Performance",
"description": "Defer loading of built-in plugins until they are actually needed to reduce initialization overhead."
}
7 changes: 7 additions & 0 deletions awscli/argprocess.py
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,13 @@ def _is_complex_shape(model):
return True


def register_param_shorthand_parser(event_emitter):
event_emitter.register(
'process-cli-arg',
ParamShorthandParser(),
)


class ParamShorthand:
def _uses_old_list_case(self, command_name, operation_name, argument_name):
"""
Expand Down
4 changes: 2 additions & 2 deletions awscli/botocore/hooks.py
Original file line number Diff line number Diff line change
Expand Up @@ -196,7 +196,7 @@ def __init__(self):
# read only access (we never modify self._handlers).
# A cache of event name to handler list.
self._lookup_cache = {}
self._handlers = _PrefixTrie()
self._handlers = PrefixTrie()
# This is used to ensure that unique_id's are only
# registered once.
self._unique_id_handlers = {}
Expand Down Expand Up @@ -398,7 +398,7 @@ def __copy__(self):
return new_instance


class _PrefixTrie:
class PrefixTrie:
"""Specialized prefix trie that handles wildcards.

The prefixes in this case are based on dot separated
Expand Down
14 changes: 13 additions & 1 deletion awscli/clidriver.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,13 @@
construct_entry_point_handlers_chain,
)
from awscli.formatter import get_formatter
from awscli.handlers_registry import MAIN_COMMAND_TABLE_OPS
from awscli.help import (
OperationHelpCommand,
ProviderHelpCommand,
ServiceHelpCommand,
)
from awscli.lazy_emitter import LazyInitEmitter
from awscli.logger import (
disable_crt_logging,
enable_crt_logging,
Expand Down Expand Up @@ -117,7 +119,10 @@ def create_clidriver(args=None):
parser = FirstPassGlobalArgParser()
args, _ = parser.parse_known_args(args)
debug = args.debug
session = botocore.session.Session()
lazy_emitter = LazyInitEmitter(
main_command_table_ops=MAIN_COMMAND_TABLE_OPS
)
session = botocore.session.Session(event_hooks=lazy_emitter)
_set_user_agent_for_session(session)
load_plugins(
session.full_config.get('plugins', {}),
Expand Down Expand Up @@ -214,6 +219,13 @@ def _set_user_agent_for_session(session):
add_session_id_component_to_user_agent_extra(session)


def register_no_pager_handler(event_emitter):
event_emitter.register(
'session-initialized',
no_pager_handler,
)


def no_pager_handler(session, parsed_args, **kwargs):
if parsed_args.no_cli_pager:
config_store = session.get_component('config_store')
Expand Down
13 changes: 13 additions & 0 deletions awscli/customizations/addexamples.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,19 @@
LOG = logging.getLogger(__name__)


def register_docs_add_examples(event_emitter):
# The following will get fired for every option we are
# documenting. It will attempt to add an example_fn on to
# the parameter object if the parameter supports shorthand
# syntax. The documentation event handlers will then use
# the examplefn to generate the sample shorthand syntax
# in the docs. Registering here should ensure that this
# handler gets called first, but it still feels a bit brittle.
# event_handlers.register('doc-option-example.*.*.*',
# param_shorthand.add_example_fn)
event_emitter.register('doc-examples.*.*', add_examples)


def add_examples(help_command, **kwargs):
doc_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.abspath(__file__))), 'examples'
Expand Down
7 changes: 7 additions & 0 deletions awscli/customizations/binaryformat.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,13 @@
from awscli.shorthand import ModelVisitor


def register_init_binary_formatter(event_emitter):
event_emitter.register(
'session-initialized',
add_binary_formatter,
)


def add_binary_formatter(session, parsed_args, **kwargs):
binary_format = parsed_args.cli_binary_format
if binary_format is None:
Expand Down
8 changes: 4 additions & 4 deletions awscli/customizations/codedeploy/codedeploy.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,11 +22,11 @@
from awscli.customizations.codedeploy.uninstall import Uninstall


def initialize(cli):
"""
The entry point for CodeDeploy high level commands.
"""
def register_rename_codedeploy(cli):
cli.register('building-command-table.main', change_name)


def register_codedeploy(cli):
cli.register('building-command-table.deploy', inject_commands)
cli.register(
'building-argument-table.deploy.get-application-revision',
Expand Down
7 changes: 7 additions & 0 deletions awscli/customizations/ec2/decryptpassword.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,13 @@
password data sent from EC2 will be decrypted before display.</p>"""


def register_ec2_add_priv_launch_key(event_emitter, **kwargs):
event_emitter.register(
'building-argument-table.ec2.get-password-data',
ec2_add_priv_launch_key,
)


def ec2_add_priv_launch_key(
argument_table, operation_model, session, **kwargs
):
Expand Down
14 changes: 14 additions & 0 deletions awscli/customizations/iot.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,20 @@
from awscli.customizations.arguments import QueryOutFileArgument


def register_iot_create_keys_from_csr(event_emitter):
event_emitter.register(
'building-argument-table.iot.create-certificate-from-csr',
register_create_keys_from_csr_arguments,
)


def register_iot_create_keys_and_cert_args(event_emitter):
event_emitter.register(
'building-argument-table.iot.create-keys-and-certificate',
register_create_keys_and_cert_arguments,
)


def register_create_keys_and_cert_arguments(session, argument_table, **kwargs):
"""Add outfile save arguments to create-keys-and-certificate

Expand Down
21 changes: 6 additions & 15 deletions awscli/customizations/s3/s3.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,23 +28,14 @@
)


def awscli_initialize(cli):
"""
This function is require to use the plugin. It calls the functions
required to add all necessary commands and parameters to the CLI.
This function is necessary to install the plugin using a configuration
file
"""
cli.register("building-command-table.main", add_s3)
cli.register('building-command-table.s3_sync', register_sync_strategies)
def register_s3_main(event_handlers):
event_handlers.register('building-command-table.main', add_s3)


def s3_plugin_initialize(event_handlers):
"""
This is a wrapper to make the plugin built-in to the cli as opposed
to specifying it in the configuration file.
"""
awscli_initialize(event_handlers)
def register_s3_sync_strategies(event_handlers):
event_handlers.register(
'building-command-table.s3_sync', register_sync_strategies
)


def add_s3(command_table, session, **kwargs):
Expand Down
7 changes: 7 additions & 0 deletions awscli/customizations/streamingoutputarg.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,13 @@
from awscli.arguments import BaseCLIArgument


def register_streaming_output_arg(event_emitter):
event_emitter.register(
'building-argument-table.*',
add_streaming_output_arg,
)


def add_streaming_output_arg(
argument_table, operation_model, session, **kwargs
):
Expand Down
Loading
Loading