Repository: beeware/briefcase

Issue:
Cannot package `setuptools>=73.0.0` for universal builds for macOS
### Describe the bug

The Aug 19 release of `setuptools==73.0.0` started including `dist-info` directories for the vendored packages. One of the vendored copies of `packaging` (since there's more than one...) does not contain a `WHEEL` file.

### Steps to reproduce

Add `setuptools==73.0.1` to `requires` and run `briefcase build` on macOS.

### Expected behavior

Seemingly malformed `dist-info` directories are ignored....or at least don't crash the build.

### Screenshots

_No response_

### Environment

- Operating System: Sonoma
- Python version: any
- Software versions:
  - Briefcase: `0.3.20.dev166+ge29943e7`

### Logs

https://gist.github.com/mribbons/1155fe873e6d7e5c46628767009b4ad4

### Additional context

_No response_


Discussion:
I haven't fully taken in how this conversion process works for macOS....but I do wonder if including vendored packages is really intended. Quickly looking through it, it doesn't appear to have expected vendored packages to have `dist-info` directories.
Oof... this is a weird one. 

I've logged this upstream as pypa/setuptools#4594; it's not clear if the inclusion of dist-info files was intentional, but if it was, the distutils-vendored version of packaging has incomplete data in (at least) the macOS wheel.

My immediate inclination is that the fix here is to restrict the search for binary packages to `dist-info` folders that are direct descendants of the install path, rather than a deep recursive search (so `*/*.dist-info`, rather than `**/*.dist-info`). The overall manifest for the top-level setuptools wheel includes all the files in the vendored packages, so that should give us all the information we need.




Patch:
diff --git a/changes/1970.bugfix.rst b/changes/1970.bugfix.rst
new file mode 100644
index 000000000..6010aab56
--- /dev/null
+++ b/changes/1970.bugfix.rst
@@ -0,0 +1,1 @@
+Packages that include ``.dist-info`` content in vendored dependencies are now ignored as part of the binary widening process on macOS. If a binary package has vendored subpackages, it is assumed that the top-level package includes the vendored packages' files in its wheel manifest.
diff --git a/src/briefcase/platforms/macOS/utils.py b/src/briefcase/platforms/macOS/utils.py
index 16c90b1cf..d08624619 100644
--- a/src/briefcase/platforms/macOS/utils.py
+++ b/src/briefcase/platforms/macOS/utils.py
@@ -41,7 +41,7 @@ def find_binary_packages(
             are in the install path that are non-universal and non-pure.
         """
         binary_packages = []
-        for distinfo in install_path.glob("**/*.dist-info"):
+        for distinfo in install_path.glob("*.dist-info"):
             # Read the WHEEL file in the dist-info folder.
             # Use this to determine if the wheel is "pure", and the tag
             # for the wheel.


Test patch:
diff --git a/tests/platforms/macOS/test_AppPackagesMergeMixin__find_binary_packages.py b/tests/platforms/macOS/test_AppPackagesMergeMixin__find_binary_packages.py
index 9a7c145c5..7f8088572 100644
--- a/tests/platforms/macOS/test_AppPackagesMergeMixin__find_binary_packages.py
+++ b/tests/platforms/macOS/test_AppPackagesMergeMixin__find_binary_packages.py
@@ -37,6 +37,17 @@ def test_find_binary_packages(dummy_command, tmp_path):
         "binary-package-2",
         version="3.4.6",
         tag="macOS_13_arm64",
+        extra_content=[
+            # A vendored, but incomplete .dist-info folder. See #1970
+            ("vendored/nested-incomplete.dist-info/LICENSE", "Nested License", 0o644),
+        ],
+    )
+    # A vendored .dist-info folder. This *isn't* found and processed.
+    create_installed_package(
+        tmp_path / "app-packages/binary-package-2/vendored",
+        "nested-package",
+        version="9.9.9",
+        tag="macOS_13_arm64",
     )
 
     binary_packages = dummy_command.find_binary_packages(