Skip to content

Core flags after a task name are silently consumed as positional values (same root cause as #982, beyond --help) #1084

Description

@Mukller

#982 / #1078 fixed this for --help, but the same defect applies to every other core flag when given after a task name whose positional arguments are not yet filled: the flag is silently consumed as the positional value and the task runs instead of the flag taking effect.

Version: invoke 3.0.3 (release) and current master. Python 3.13, Windows.

Repro

# tasks.py
from invoke import task

@task
def build(ctx, target):
    print(f"BUILDING {target}")
$ invoke build --echo
BUILDING --echo          # task RAN; echo mode not enabled

$ invoke build --dry
BUILDING --dry           # "dry run" executed for real

$ invoke build --debug
BUILDING --debug

$ invoke build --warn-only
BUILDING --warn-only

All four core flags are swallowed as the value of the still-unfilled target positional. Same happens on current master (verified). The --help case was fixed in #1078 by checking it before the positional branch; that PR's commentary explicitly scoped everything else out ("Unlike other initial-context flags..."), but the remaining flags have exactly the same never-a-valid-positional property — no task legitimately wants the literal string --echo as data.

Why this is worse than it looks

--dry being swallowed means a user who believes they are doing a dry run actually executes destructive tasks against real targets. That's a safety-relevant failure mode, not just an inconvenience.

Proposed direction

Generalize the #1078 approach: before the positional-arg branch in Parser.handle, treat any token matching an initial-context core flag as that flag (setting its value / entering flag state), regardless of pending positionals. If backwards compatibility concerns exist for tasks that genuinely accept e.g. --echo as a task-level flag — note those are matched per-context later anyway, so initial-context handling can stay reserved for core flags.

Happy to send a PR generalizing #1078's fix if maintainers agree on the semantics.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions