Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Make airflowctl command generation safe to read more than once - #73097

Open
Eason09053360 wants to merge 1 commit into
apache:mainfrom
Eason09053360:fix-airflowctl-command-factory-idempotent
Open

Make airflowctl command generation safe to read more than once#73097
Eason09053360 wants to merge 1 commit into
apache:mainfrom
Eason09053360:fix-airflowctl-command-factory-idempotent

Conversation

@Eason09053360

@Eason09053360 Eason09053360 commented Sep 13, 2026

Copy link
Copy Markdown
Contributor

Why

CommandFactory.group_commands in airflow-ctl/src/airflowctl/ctl/cli_config.py is a plain
@property, so every access re-runs the four builder methods. Those builders append to
self.operations, self.commands_map and self.group_commands_list instead of replacing them,
and the GroupCommands hold the commands_map lists by reference. Reading the property a second
time therefore doubles the command tree:

read #1:  14 groups,  7 `connections` subcommands
read #2:  28 groups, 21 `connections` subcommands   (still only 7 distinct names)

Two groups named connections is not something argparse accepts, so the second read leaves
airflowctl unable to build its parser at all.

This is preventive — there is no user-visible bug today, because the only access is the single
import-time one at cli_config.py:1305. What makes it worth fixing now is that command_factory
is a module-level singleton any caller can import, and the existing tests construct
CommandFactory() in a dozen places. The likely way in is a routine refactor that shares one
factory instance across test cases; the resulting failure would point nowhere near this property.

What

  • cli_config.py: group_commands becomes a cached_property, so the non-idempotent builders
    run once per instance. The docstring records why the caching is load-bearing rather than an
    optimisation, since reverting it to @property would keep every current test green.
  • test_cli_config.py: adds test_group_commands_is_stable_across_repeated_access. Both accesses
    return the same list object, so the test snapshots (name, len(subcommands)) before the second
    access — comparing the lists directly would compare a list against itself and pass either way.

Nothing mutates the cached list: merge_commands and add_auth_token_to_all_commands both copy
before extending and rebuild the namedtuples via _replace.


Was generative AI tooling used to co-author this PR?
  • Yes — Claude Code (Opus 5)

Generated-by: Claude Code (Opus 5) following the guidelines

The generated command tree is exposed through a module-level CommandFactory
singleton that anyone can import, so a second read of the property is a
reachable state rather than a hypothetical one. Today only the single
import-time access exists, which is why nothing is visibly broken; the most
likely way in is a routine test refactor that shares one factory instance
across cases, which would then fail in a way that points nowhere near the
cause.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant