Repository: napari/napari

Issue:
`File -> Open Folder...` doesn't allow me to select a folder (Mac-OS)
### 🐛 Bug Report

On `main`, if I try to open a folder using the `File` menu option, `File -> Open Folder...`, the built-in Mac-OS dialog doesn't let me select a folder i.e. when I click `Open` in the bottom right-hand corner with a folder selected, it just shows me the contents of the folder (as though I'd double-clicked it) rather than selecting it and reading it. This doesn't happen on `0.4.19.post1`. Drag 'n' drop still works fine on main.

### 💡 Steps to Reproduce

1. Check out 0.4.19.post1
2. Open a folder using `File -> Open Folder...`. 
3. The folder opens normally.
4. Check out main
5. Open a folder using `File -> Open Folder...`.
6. You can't.

### 💡 Expected Behavior

I expected the folder to open as usual.

### 🌎 Environment

```
napari: 0.5.0a2.dev712+ge29593cf
Platform: macOS-10.16-x86_64-i386-64bit
System: MacOS 14.5
Python: 3.10.14 (main, Mar 21 2024, 11:24:58) [Clang 14.0.6 ]
Qt: 5.15.11
PyQt5: 5.15.10
NumPy: 1.26.4
SciPy: 1.13.0
Dask: 2024.4.0
VisPy: 0.14.2
magicgui: 0.8.2
superqt: 0.6.3
in-n-out: 0.2.0
app-model: 0.2.6
npe2: 0.7.5

OpenGL:
- GL version: 2.1 INTEL-22.5.11
- MAX_TEXTURE_SIZE: 16384
- GL_MAX_3D_TEXTURE_SIZE: 2048

Screens:
- screen 1: resolution 1440x900, scale 2.0

Optional:
- numba: 0.59.1
- triangle: 20230923

Settings path:
- /Users/ddoncilapop/Library/Application Support/napari/napari-dev_4bf01cd15eaead7335b2c3834bd2061f518e1da7/settings.yaml
```

### 💡 Additional Context

_No response_
Deprecate/Remove unused arguments from utils functions in `napari/napari/utils/misc.py` ?
## 🧰 Task
In `napari/utils/misc.py` both `def ensure_iterable` and `def is_iterable` seem to have keywords arguments that are never used (`color=False`, and `allow_none=False`), leading to non-covered branches. 

I suggest to deprecate passing the keyword arguments, then open an issue to remove branches.


Discussion:

Hi @Carreau, this is my first PR to such extensive project. Please feel free to guide me to fix things further. Deep regards.
Sorry, I'm not too involved in the project anymore, but will try to comment on your PR.

Resolving patch:
diff --git a/napari/layers/utils/layer_utils.py b/napari/layers/utils/layer_utils.py
--- a/napari/layers/utils/layer_utils.py
+++ b/napari/layers/utils/layer_utils.py
@@ -989,9 +989,7 @@ def _validate_features(
         # a pandas Series with mixed indices as input.
         # This way should handle all array-like objects correctly.
         # See https://github.com/napari/napari/pull/4755 for more details.
-        features = {
-            key: np.array(value, copy=False) for key, value in features.items()
-        }
+        features = {key: np.asarray(value) for key, value in features.items()}
     index = None if num_data is None else range(num_data)
     return pd.DataFrame(data=features, index=index)
 
diff --git a/napari/utils/events/custom_types.py b/napari/utils/events/custom_types.py
--- a/napari/utils/events/custom_types.py
+++ b/napari/utils/events/custom_types.py
@@ -18,6 +18,22 @@
 
     Number = Union[int, float, Decimal]
 
+# In numpy 2, the semantics of the copy argument in np.array changed
+# so that copy=False errors if a copy is needed:
+# https://numpy.org/devdocs/numpy_2_0_migration_guide.html#adapting-to-changes-in-the-copy-keyword
+#
+# In numpy 1, copy=False meant that a copy was avoided unless necessary,
+# but would not error.
+#
+# In most usage like this use np.asarray instead, but sometimes we need
+# to use some of the unique arguments of np.array (e.g. ndmin).
+#
+# This solution assumes numpy 1 by default, and switches to the numpy 2
+# value for any release of numpy 2 on PyPI (including betas and RCs).
+copy_if_needed: Optional[bool] = False
+if np.lib.NumpyVersion(np.__version__) >= '2.0.0b1':
+    copy_if_needed = None
+
 
 class Array(np.ndarray):
     def __class_getitem__(cls, t):
@@ -35,7 +51,9 @@ def validate_type(cls, val):
         else:
             shape = ()
 
-        result = np.array(val, dtype=dtype, copy=False, ndmin=len(shape))
+        result = np.array(
+            val, dtype=dtype, copy=copy_if_needed, ndmin=len(shape)
+        )
 
         if any(
             (shape[i] != -1 and shape[i] != result.shape[i])


Test patch: