Skip to content

Implement type hints for Environment and environment utilities#4824

Merged
bdbaddog merged 3 commits intoSCons:masterfrom
Repiteo:type-hints-environment
Feb 14, 2026
Merged

Implement type hints for Environment and environment utilities#4824
bdbaddog merged 3 commits intoSCons:masterfrom
Repiteo:type-hints-environment

Conversation

@Repiteo
Copy link
Contributor

@Repiteo Repiteo commented Feb 2, 2026

Followup to Node type hinting PRs

Hints for Environment are particularly odd, as a lot of cases would technically want to derive from SubstitutionEnvironment instead of Environment.Base. However, I made the type hints act as if Environment.Base is the base class. This is because, in practice, absolutely nobody is using SubstitutionEnvironment, and it might even be refactored away in the future(?). The files adjusted were:

  • SCons/Environment.py
  • SCons/Node/__init__.py (EnvironmentEnvironmentBase)
  • SCons/Node/FS.py (EnvironmentEnvironmentBase)
  • SCons/Script/SConscript.py (Specifically SConsEnvironment and related functions)
  • SCons/Util/envs.py (Utility scripts for environments)

Contributor Checklist:

  • I have created a new test or updated the unit tests to cover the new/changed functionality.
  • I have updated CHANGES.txt and RELEASE.txt (and read the README.rst).
  • I have updated the appropriate documentation

@mwichmann
Copy link
Collaborator

Tackling a big one, I see :-) This will take a bit to review - and it seems to have blown up a few tests. In EnvironmentTests, there seem to be two tests (test_ParseConfig and test_ParseFlags) for tuples which need to be preserved as such (when they're the key, value pair of a cpp define), but which have flipped to lists, and one test (test_AppendENVPath) which hasn't kept the expected ordering. Not sure how typing changes can cause that. UtilTests also has some unexpected ordering changes.

@Repiteo
Copy link
Contributor Author

Repiteo commented Feb 3, 2026

Hmm, I might've left a functional change in there while testing return types; it'd explain the tests acting up anyway. Will take a look later

@Repiteo Repiteo force-pushed the type-hints-environment branch 2 times, most recently from fa49a48 to 43f2960 Compare February 3, 2026 15:58
• Hints operate under the assumption that `Environment.Base` is the "base" class
@bdbaddog
Copy link
Contributor

bdbaddog commented Feb 9, 2026

I asked Gemini for feedback on the type annotations, here's what it came up with. Thoughts?

The changes in this PR introduce extensive type annotations across the SCons codebase, particularly in the core environment and node management modules. After
reviewing the changes in SCons/Environment.py, SCons/Util/envs.py, SCons/Node/FS.py, SCons/Node/init.py, and SCons/Script/SConscript.py, I have identified
several areas where the type annotations could be improved or corrected.

Incorrect or Overly Restrictive Type Annotations

  1. SCons/Environment.py - Alias method:
    The target parameter is annotated as str, but SCons aliases can also be Node objects or lists of strings/Nodes.

    • Current: target: str
    • Corrected: target: str | Node | list[str | Node]
  2. SCons/Environment.py - Dir, File, and Entry methods:
    The name parameter is annotated as str | list[str]. However, these methods frequently accept Node objects (e.g., passing a File node to env.File()).

    • Current: name: str | list[str]
    • Corrected: name: str | Node | list[str | Node] (or more specific Node types like FileNode for File)
  3. SCons/Environment.py - VariantDir method:
    The variant_dir and src_dir parameters are annotated as str, but the implementation explicitly handles DirNode objects.

    • Current: variant_dir: str, src_dir: str
    • Corrected: variant_dir: str | DirNode, src_dir: str | DirNode
  4. SCons/Node/FS.py - invalidate_node_memos function:
    The targets parameter is annotated as str | list[Base | str]. This prevents passing a single Base node directly, even though the implementation supports it.

    • Current: targets: str | list[Base | str]
    • Corrected: Base | str | list[Base | str]
  5. SCons/Environment.py - NoSubstitutionProxy methods:
    The subst and subst_target_source methods are annotated with string: str. However, the base Environment.subst method handles list[str]. If a list is passed
    to the proxy, it will return the list, but the type hint will be incorrect.

    • Current: string: str
    • Corrected: string: str | list[str]

Observations and Fixes

  • EnvironmentBase Alias: The use of EnvironmentBase = Base at the end of SCons/Environment.py is a good pattern to handle circular dependencies and potential
    overrides in type checking.

Overall, the type annotations are a significant improvement, but adjusting the restrictive hints mentioned above would better reflect SCons's flexible API and
prevent unnecessary static analysis errors.

@mwichmann
Copy link
Collaborator

That's weird... the comments in the email show some backward-looking comments in "Observations and Fixes", which has four bullets,,and three of those don't seem to be in the comment in the PR itself, which has one bullet ???? Makes me nervous...

@bdbaddog
Copy link
Contributor

bdbaddog commented Feb 9, 2026

That's weird... the comments in the email show some backward-looking comments in "Observations and Fixes", which has four bullets,,and three of those don't seem to be in the comment in the PR itself, which has one bullet ???? Makes me nervous...

I think it diffed the branch vs master and since this branch branched before some of the fixes in master presently it analyzed more changes than are in this branch. I removed 3 of the 4 observations and fixed section as they referred to changes in master..

@mwichmann
Copy link
Collaborator

That's weird... the comments in the email show some backward-looking comments in "Observations and Fixes", which has four bullets,,and three of those don't seem to be in the comment in the PR itself, which has one bullet ???? Makes me nervous...

I think it diffed the branch vs master and since this branch branched before some of the fixes in master presently it analyzed more changes than are in this branch. I removed 3 of the 4 observations and fixed section as they referred to changes in master..

okay, that would explain it. thanks.

@bdbaddog
Copy link
Contributor

@Repiteo - can you take a look at the Gemini sugguests and make those changes if they seem sane and/or let me know if it's ok for me to?

@mwichmann
Copy link
Collaborator

Seems like we should have a name for the frequently seen str | Node | list[str | Node] pattern....

@mwichmann
Copy link
Collaborator

The numbered observations seem about right to me.

@bdbaddog
Copy link
Contributor

Seems like we should have a name for the frequently seen str | Node | list[str | Node] pattern....

Add that to sctypes ?

@mwichmann
Copy link
Collaborator

Seems like we should have a name for the frequently seen str | Node | list[str | Node] pattern....

Add that to sctypes ?

maybe... but on the other hand, it's a type only for type checking. We had a SCons.Util.sctyping for a while but it's been factored back out.

@Repiteo
Copy link
Contributor Author

Repiteo commented Feb 12, 2026

@bdbaddog Those are fair observations! While passing nodes/lists in many of these contexts is unorthodox and not really documented, tests indeed exists for basically every case mentioned so it's fair to integrate them

@mwichmann iirc, it was removed because the abstraction it provided was able to be substituted in the files themselves by taking advantage of TYPE_CHECKING. Alias shorthands were never part of it originally, and isn't a niche that TYPE_CHECKING would replicate without bloat. I don't think we'd need to bring back sctypingsctypes could fulfill the same purpose—but if we wanted a file exclusively for type hint logic, then I can see merit in that. Not a blocker for this PR in any case, but I'll test a 3.9 environment to see how much typing-specific logic could get centralized

@bdbaddog bdbaddog merged commit 9cf4eb9 into SCons:master Feb 14, 2026
9 checks passed
@mwichmann mwichmann added this to the NextRelease milestone Feb 14, 2026
@Repiteo Repiteo deleted the type-hints-environment branch February 14, 2026 22:59
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants