Repository: tox-dev/tox

Issue:
Pass through ProgramFiles* and ProgramData by default
I'd like to follow up on #1673. I couldn't comment or even +1 that issue.

I believe the characterization of the issue as setuptools-specific was incorrect.

Although the issue does affect Setuptools and not Flit, that's only because Setuptools supports building C extensions on Windows.

The issue can't be fixed in Setuptools. By the time tox has masked the ProgramFiles env var, Setuptools has little hope of recovering that setting.

We're not asking tox to patch Setuptools. Instead, we're asking tox to consider honoring the system's intrinsic environment configuration by passing through system-level variables, variables that would be unlikely to be configured by the user and which are necessary for basic operation on the platform (similar to `PATH`, `SYSTEMDRIVE`, and `SYSTEMROOT`).

Failing to support this model will instead require every project that builds extension modules on Windows to bypass this setting in their tox config. I believe this issue was largely missed until recently because most users were still testing on older platforms/compilers that did not rely on vswhere for discovery, but now that Windows 2022 is the default in Github, it's affecting a wide array of users. I contend:

- this exemption is required in every case it affects
- there is no known case that this masking is currently important
- the number of affected projects is large.

I can put together a repro that doesn't involve Setuptools if that helps persuade.

Comments:

Patch:
diff --git a/CONTRIBUTORS b/CONTRIBUTORS
index f3fc3407..15f58597 100644
--- a/CONTRIBUTORS
+++ b/CONTRIBUTORS
@@ -55,6 +55,7 @@ Isaac Pedisich
 Itxaka Serrano
 Jake Windle
 Jannis Leidel
+Jason R. Coombs
 Jesse Schwartzentruber
 Joachim Brandon LeBlanc
 Johannes Christ
diff --git a/docs/changelog/2382.feature.rst b/docs/changelog/2382.feature.rst
new file mode 100644
index 00000000..59a75852
--- /dev/null
+++ b/docs/changelog/2382.feature.rst
@@ -0,0 +1,1 @@
+On Windows ``PROGRAMFILES``, ``PROGRAMFILES(X86)``, and ``PROGRAMDATA`` environment variables are now passed through, unmasking system values necessary to locate resources such as a C compiler.
diff --git a/docs/config.rst b/docs/config.rst
index c579733e..2ca82e3a 100644
--- a/docs/config.rst
+++ b/docs/config.rst
@@ -469,7 +469,8 @@ Complete list of settings that you can put into ``testenv*`` sections:
       ``REQUESTS_CA_BUNDLE``, ``SSL_CERT_FILE``,
       ``HTTP_PROXY``, ``HTTPS_PROXY``, ``NO_PROXY``
     * Windows: ``SYSTEMDRIVE``, ``SYSTEMROOT``, ``PATHEXT``, ``TEMP``, ``TMP``
-       ``NUMBER_OF_PROCESSORS``, ``USERPROFILE``, ``MSYSTEM``
+       ``NUMBER_OF_PROCESSORS``, ``USERPROFILE``, ``MSYSTEM``,
+       ``PROGRAMFILES``, ``PROGRAMFILES(X86)``, ``PROGRAMDATA``
     * Others (e.g. UNIX, macOS): ``TMPDIR``
 
     You can override these variables with the ``setenv`` option.
diff --git a/src/tox/config/__init__.py b/src/tox/config/__init__.py
index b155fd1c..b49c06f6 100644
--- a/src/tox/config/__init__.py
+++ b/src/tox/config/__init__.py
@@ -807,6 +807,10 @@ def tox_addoption(parser):
             passenv.add("PROCESSOR_ARCHITECTURE")  # platform.machine()
             passenv.add("USERPROFILE")  # needed for `os.path.expanduser()`
             passenv.add("MSYSTEM")  # fixes #429
+            # PROGRAM* required for compiler tool discovery #2382
+            passenv.add("PROGRAMFILES")
+            passenv.add("PROGRAMFILES(X86)")
+            passenv.add("PROGRAMDATA")
         else:
             passenv.add("TMPDIR")
 


Test patch:
diff --git a/tests/unit/config/test_config.py b/tests/unit/config/test_config.py
index 6949bf93..3408de02 100644
--- a/tests/unit/config/test_config.py
+++ b/tests/unit/config/test_config.py
@@ -1518,6 +1518,9 @@ class TestConfigTestEnv:
             assert "PROCESSOR_ARCHITECTURE" in envconfig.passenv
             assert "USERPROFILE" in envconfig.passenv
             assert "MSYSTEM" in envconfig.passenv
+            assert "PROGRAMFILES" in envconfig.passenv
+            assert "PROGRAMFILES(X86)" in envconfig.passenv
+            assert "PROGRAMDATA" in envconfig.passenv
         else:
             assert "TMPDIR" in envconfig.passenv
             if sys.platform != "win32":
@@ -1562,6 +1565,9 @@ class TestConfigTestEnv:
             assert "SYSTEMROOT" in envconfig.passenv
             assert "TEMP" in envconfig.passenv
             assert "TMP" in envconfig.passenv
+            assert "PROGRAMFILES" in envconfig.passenv
+            assert "PROGRAMFILES(X86)" in envconfig.passenv
+            assert "PROGRAMDATA" in envconfig.passenv
         else:
             assert "TMPDIR" in envconfig.passenv
         assert "PATH" in envconfig.passenv