Skip to content

type Command.force#382

Merged
jaraco merged 2 commits into
pypa:mainfrom
Avasam:type-Command.force
Jul 8, 2026
Merged

type Command.force#382
jaraco merged 2 commits into
pypa:mainfrom
Avasam:type-Command.force

Conversation

@Avasam

@Avasam Avasam commented Nov 2, 2025

Copy link
Copy Markdown
Contributor

self.link_objects = None
self.debug = None
self.force = None
self.force: bool = None # Should always be set in finalize_options

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not actually type-safe and easy to break in the future, but this is only place in distutils we assume a type for after finalize_options.

Alternatively this can be kept as bool | None, which still works everywhere expecting a falsy/truthy value. But in some places where an actual boolean is expected (like https://github.com/pypa/setuptools/blob/d198e86f57231e83de87975c5c82bc40c196da79/setuptools/command/build_ext.py#L225-L227 ) we'd have to coerce to a boolean: bool(self.force)

Comment thread distutils/compilers/C/base.py Outdated
# function) -- authors of new compiler interface classes are
# responsible for updating 'compiler_class'!
compiler_type: ClassVar[str] = None # type: ignore[assignment]
compiler_type: ClassVar[str] = None

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Type ignore is accurate, but technically we ignore all assignment atm, will be added back with #368

@Avasam Avasam force-pushed the type-Command.force branch 3 times, most recently from 4000f6d to c2328c7 Compare July 5, 2026 15:06
Comment thread distutils/cmd.py
@Avasam Avasam force-pushed the type-Command.force branch from c2328c7 to b90852e Compare July 8, 2026 16:06
Comment on lines +114 to +116
self.build_lib: str = None # Should always be set in finalize_options
self.plat_name: str = None # Should always be set in finalize_options
self.build_temp: str = None # Should always be set in finalize_options

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

@Avasam This change was necessary to get the build to pass. Is this also acceptable?

@Avasam Avasam Jul 8, 2026

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Not quite:

  1. By adding -> None to initialize_options, mypy now parses and type-checks this function. So ALL members you initialize and don't explicitly type can only ever be None. (I've very purposefully avoided dealing with that until more of the project's typing could be cleared up) (surely one of the mypy PRs still left would've detected that issue)
  2. The annoying thing with this initialize/finalize setup in general, is that you get false-positives comparing against None in finalize_options. Including user-defined overloads of finalize_options.
    For now, I've been fixing types to X | None when it could still be None after finalize_options. And fixing bad None defaults when that was appropriate. The third case (as per point 1) I've mostly left alone for now ^^"

If you HAVE to decide, I'd say keeping the type accurate to AFTER running finalize_options is best, and it'll just be a known distutils/setuptools typing caveat that there will be false-positives when comparing against None in initialize_options/finalize_options. (so what you have right now, but type ALL members before adding -> None to initialize_options)

But all is not lost, there's one more trick you can use we developed in typeshed: MaybeNone aka "The Any Trick"

(it'll obviously reduce type safety, but false-negatives are generally preferred over false-positives, especially for a legacy system like this)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

In case of doubt, let's keep working through other PRs and I can tackle this more in depth

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

I'm not sure I follow, but this does allow the tests to pass, so let's go with it for now and we can refine subsequently. Thanks.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

See the new failing test results in #368 for what I meant

distutils/command/build_ext.py:114: error: Incompatible types in assignment (expression has type "None", variable has type "str")  [assignment]
distutils/command/build_ext.py:115: error: Incompatible types in assignment (expression has type "None", variable has type "str")  [assignment]
distutils/command/build_ext.py:116: error: Incompatible types in assignment (expression has type "None", variable has type "str")  [assignment]
distutils/command/build_ext.py:128: error: Incompatible types in assignment (expression has type "None", variable has type "bool")  [assignment]
distutils/command/build_ext.py:176: error: Incompatible types in assignment (expression has type "str | None", variable has type "None")  [assignment]
distutils/command/build_ext.py:178: error: Incompatible types in assignment (expression has type "list[Extension] | None", variable has type "None")  [assignment]
distutils/command/build_ext.py:185: error: Incompatible types in assignment (expression has type "list[str]", variable has type "None")  [assignment]
distutils/command/build_ext.py:206: error: Incompatible types in assignment (expression has type "list[Never]", variable has type "None")  [assignment]
distutils/command/build_ext.py:208: error: Incompatible types in assignment (expression has type "list[Never]", variable has type "None")  [assignment]
distutils/command/build_ext.py:213: error: Incompatible types in assignment (expression has type "list[Never]", variable has type "None")  [assignment]
distutils/command/build_ext.py:280: error: Incompatible types in assignment (expression has type "list[Never]", variable has type "None")  [assignment]

@jaraco jaraco merged commit 06c8863 into pypa:main Jul 8, 2026
22 checks passed
@Avasam Avasam deleted the type-Command.force branch July 9, 2026 23:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants