Repository: python-pillow/Pillow
Pull request: Do not raise an error if os.environ does not contain PATH
Resolves #6934

https://github.com/python-pillow/Pillow/blob/7e3bed6834e639cd0f5a410abfd8224d4e5725c5/setup.py#L245-L249
presumes that `os.environ` contains a "PATH" key.

This PR changes the code no longer raise an error if it doesn't.

Problem statement:
setup.py build fails without PATH
### What did you do?
```
$ env - python3.9 setup.py build
```
### What did you expect to happen?

The build succeeds.

### What actually happened?
```pytb
$ env - python3.9 setup.py build
... (skipped many lines) ...
writing manifest file 'src/Pillow.egg-info/SOURCES.txt'
running build_ext
Traceback (most recent call last):
  File "$(BUILD_DIR)/setup.py", line 993, in <module>
    setup(
  File "/usr/lib/python3.9/vendor-packages/setuptools/__init__.py", line 108, in setup
    return distutils.core.setup(**attrs)
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/core.py", line 185, in setup
    return run_commands(dist)
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/core.py", line 201, in run_commands
    dist.run_commands()
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/dist.py", line 969, in run_commands
    self.run_command(cmd)
  File "/usr/lib/python3.9/vendor-packages/setuptools/dist.py", line 1213, in run_command
    super().run_command(command)
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/dist.py", line 988, in run_command
    cmd_obj.run()
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/command/build.py", line 132, in run
    self.run_command(cmd_name)
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/cmd.py", line 318, in run_command
    self.distribution.run_command(command)
  File "/usr/lib/python3.9/vendor-packages/setuptools/dist.py", line 1213, in run_command
    super().run_command(command)
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/dist.py", line 988, in run_command
    cmd_obj.run()
  File "/usr/lib/python3.9/vendor-packages/setuptools/command/build_ext.py", line 84, in run
    _build_ext.run(self)
  File "/usr/lib/python3.9/vendor-packages/Cython/Distutils/old_build_ext.py", line 186, in run
    _build_ext.build_ext.run(self)
  File "/usr/lib/python3.9/vendor-packages/setuptools/_distutils/command/build_ext.py", line 346, in run
    self.build_extensions()
  File "$(BUILD_DIR)/setup.py", line 438, in build_extensions
    if _cmd_exists(os.environ.get("PKG_CONFIG", "pkg-config")):
  File "$(BUILD_DIR)/setup.py", line 248, in _cmd_exists
    for path in os.environ["PATH"].split(os.pathsep)
  File "/usr/lib/python3.9/os.py", line 679, in __getitem__
    raise KeyError(key) from None
KeyError: 'PATH'
$
```
### What are your OS, Python and Pillow versions?

* OS: OpenIndiana
* Python: 3.9.16
* Pillow: 9.4.0

Hints from issue discussion:
I'm not sure that we can reasonably expect a build to work if there's no `PATH`? We have to be able to find compilers, linkers, and pkg-config. 

Are there any binary packages that build with this configuration?
@radarhere, https://github.com/radarhere/Pillow/commit/02b976b6be75e3dfbdb48aa2730fecd20387716a fixed the problem.  Now `env - python3.9 setup.py build` works as expected.  Thank you.

Commit message: Do not raise an error if os.environ does not contain PATH

Patch to review:
diff --git a/setup.py b/setup.py
index 8f7f223f8cd..0c8b390dec5 100755
--- a/setup.py
+++ b/setup.py
@@ -243,6 +243,8 @@ def _find_include_dir(self, dirname, include):
 
 
 def _cmd_exists(cmd):
+    if "PATH" not in os.environ:
+        return
     return any(
         os.access(os.path.join(path, cmd), os.X_OK)
         for path in os.environ["PATH"].split(os.pathsep)


Code review comments:
diff_hunk: @@ -243,6 +243,8 @@ def _find_include_dir(self, dirname, include):
 
 
 def _cmd_exists(cmd):
+    if "PATH" not in os.environ:
+        return
path: setup.py
text: @user1:
Let's be explicit about the return type (we use it in an `if`), and add type hints as well.

```suggestion
def _cmd_exists(cmd: str) -> bool:
    if "PATH" not in os.environ:
        return False
```