Skip to content

Adds fallback to newly created environment block for known OS variables. - #432

Merged
zooba merged 9 commits into
python:mainfrom
zooba:gh-427
Oct 23, 2026
Merged

zooba merged 9 commits into
python:mainfrom
zooba:gh-427

Conversation

@zooba

@zooba zooba commented Oct 20, 2026

Copy link
Copy Markdown
Member

Makes it a hard failure for environment variables in paths to be empty.

Fixes #427

@zooba
zooba marked this pull request as ready for review October 21, 2026 17:08

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Path expansion can still select the working directory unexpectedly, and fallback lookup and resource-cleanup defects remain.

4 open issues
What changed in this PR

This PR addresses #427 by recovering missing Windows environment variables during configuration loading, helping prevent Python Manager from resolving installation paths against the working directory.

Changes:

  • Adds a native helper to generate a default Windows environment and exposes it through both builds.
  • Adds configuration fallback lookups and rejects empty substitutions before path separators.
  • Adds absolute-path detection and tests for configuration expansion and fallback behavior.
File Description
tests/​test_pathutils.py Tests absolute and relative Windows paths.
tests/​test_config.py Tests missing variables, fallback values, and configuration resolution.
src/​manage/​pathutils.py Adds absolute-path detection.
src/​manage/​config.py Adds environment fallback and stricter substitution handling.
src/​_native/​misc.cpp Retrieves a default Windows environment block.
_msbuild.py Links and exposes the native environment helper.
_msbuild_test.py Adds native helper support to the test build.

Review effort: Balanced

Comment thread src/_native/misc.cpp
Comment thread src/manage/config.py Outdated
Comment thread src/manage/config.py Outdated
Comment thread src/manage/config.py

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Explicit environment mappings are ignored when empty and are not forwarded during nested configuration resolution.

No open issues 🎉

2 previously missed issues

In code that hasn't changed since last review

Medium severity Forward environ when resolving nested settings

src/​manage/​config.py:259

The new environ argument is not forwarded by the recursive call on line 275. Nested settings such as install.source and list.format therefore use the process environment instead of the supplied mapping, unlike top-level settings. A value consisting solely of a variable supplied only in that mapping is silently removed. Forward environ when resolving nested schemas so all levels use the same environment.

Medium severity Respect explicitly supplied empty environment mappings

src/​manage/​config.py:283

An explicitly supplied empty environment is ignored because {} is falsy. For example, resolving %AppData%/Python with environ={} reads the process environment and OS fallbacks instead of reporting the missing variable. Select the default only when environ is None so an intentionally empty mapping is respected.

4 resolved since last review

Review effort: Balanced

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🟡 Changes recommended

Unresolved configuration fallback, strict path expansion, path utility, and test failures block approval.

1 open issue
2 previously missed issues

In code that hasn't changed since last review

Medium severity Reject empty substitutions in path-valued settings

src/​manage/​config.py:254

This only raises when the placeholder is followed by a path separator. A path-valued setting whose entire value is %TEMP% or %AppData% still expands to an empty string, and resolve_config then deletes the setting, allowing a later default (such as the current directory) instead of failing as promised. Apply strict empty-substitution validation to path-valued settings while preserving optional expansion for non-path settings.

Medium severity Return a boolean from is_absolute drive-root check

src/​manage/​pathutils.py:110

drive and root returns the root string rather than a boolean (for example, an absolute drive path returns "\\"). That makes is_absolute() type-inconsistent with the pathlib-style API and breaks callers that use is True or otherwise require a boolean; return bool(drive and root) instead.

Review effort: Lite

Comment thread tests/test_config.py Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🔵 Needs a closer look

Unresolved moderate issues remain in log-directory fallback, empty-variable validation without separators, and UNC-path absolute detection.

No open issues 🎉

1 previously missed issue

In code that hasn't changed since last review

Medium severity Log path still falls back to the current working directory

src/​manage/​config.py:190

Adding TEMP/TMP here does not protect the log path in the reported minimal-environment case: BaseCommand.get_log_file() still calls os.getenv("TMP") or os.getenv("TEMP") or os.getcwd(), so when both variables are absent it writes into the caller's current directory. Please route log-directory resolution through the same fallback environment (or fail rather than choosing the CWD), otherwise this part of #427 remains reproducible.

1 resolved since last review

Review effort: Lite

@zooba

zooba commented Oct 23, 2026

Copy link
Copy Markdown
Member Author

My other important change needs to build on this, and I don't think this is going to get properly exercised without a beta release (and probably not even without a full release), so I'm merging based on the Copilot reviews being clean (the log path fallback is intentional and won't be changed).

@zooba
zooba merged commit c692c46 into python:main Oct 23, 2026
6 checks passed
@zooba
zooba deleted the gh-427 branch October 23, 2026 12:57
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.

With LOCALAPPDATA unset, install_dir resolves to the current directory; auto-install then deletes registry entries and shortcuts of the real installs

2 participants