diff --git a/ci/extra_requirements.txt b/ci/extra_requirements.txt
index 70a45f6230..590f2f0b2f 100644
--- a/ci/extra_requirements.txt
+++ b/ci/extra_requirements.txt
@@ -1,3 +1,3 @@
 cartopy==0.22.0
-dask==2024.3.0
+dask==2024.3.1
 shapely==2.0.3
diff --git a/ci/linting_requirements.txt b/ci/linting_requirements.txt
index a67d1f70f0..1d739578d5 100644
--- a/ci/linting_requirements.txt
+++ b/ci/linting_requirements.txt
@@ -1,4 +1,4 @@
-ruff==0.3.2
+ruff==0.3.3
 
 flake8==7.0.0
 pycodestyle==2.11.1
diff --git a/src/metpy/calc/basic.py b/src/metpy/calc/basic.py
index 0e164e1b04..a290e3df12 100644
--- a/src/metpy/calc/basic.py
+++ b/src/metpy/calc/basic.py
@@ -52,6 +52,13 @@ def wind_speed(u, v):
     --------
     wind_components
 
+    Examples
+    --------
+    >>> from metpy.calc import wind_speed
+    >>> from metpy.units import units
+    >>> wind_speed(10. * units('m/s'), 10. * units('m/s'))
+    <Quantity(14.1421356, 'meter / second')>
+
     """
     return np.hypot(u, v)
 
@@ -88,6 +95,13 @@ def wind_direction(u, v, convention='from'):
     In the case of calm winds (where `u` and `v` are zero), this function returns a direction
     of 0.
 
+    Examples
+    --------
+    >>> from metpy.calc import wind_direction
+    >>> from metpy.units import units
+    >>> wind_direction(10. * units('m/s'), 10. * units('m/s'))
+    <Quantity(225.0, 'degree')>
+
     """
     wdir = units.Quantity(90., 'deg') - np.arctan2(-v, -u)
     origshape = wdir.shape
@@ -141,7 +155,7 @@ def wind_components(speed, wind_direction):
     >>> from metpy.calc import wind_components
     >>> from metpy.units import units
     >>> wind_components(10. * units('m/s'), 225. * units.deg)
-     (<Quantity(7.07106781, 'meter / second')>, <Quantity(7.07106781, 'meter / second')>)
+    (<Quantity(7.07106781, 'meter / second')>, <Quantity(7.07106781, 'meter / second')>)
 
     .. versionchanged:: 1.0
        Renamed ``wdir`` parameter to ``wind_direction``
diff --git a/src/metpy/calc/tools.py b/src/metpy/calc/tools.py
index c34453c8f3..12640a6561 100644
--- a/src/metpy/calc/tools.py
+++ b/src/metpy/calc/tools.py
@@ -1825,6 +1825,13 @@ def angle_to_direction(input_angle, full=False, level=3):
     direction
         The directional text
 
+    Examples
+    --------
+    >>> from metpy.calc import angle_to_direction
+    >>> from metpy.units import units
+    >>> angle_to_direction(225. * units.deg)
+    'SW'
+
     """
     try:  # strip units temporarily
         origin_units = input_angle.units
diff --git a/src/metpy/xarray.py b/src/metpy/xarray.py
index 2ccb36ce0a..ab16f76802 100644
--- a/src/metpy/xarray.py
+++ b/src/metpy/xarray.py
@@ -338,15 +338,16 @@ class MetPyDataArrayAccessor:
     def _generate_coordinate_map(self):
         """Generate a coordinate map via CF conventions and other methods."""
         coords = self._data_array.coords.values()
-        # Parse all the coordinates, attempting to identify x, longitude, y, latitude,
-        # vertical, time
-        coord_lists = {'time': [], 'vertical': [], 'y': [], 'latitude': [], 'x': [],
-                       'longitude': []}
+        # Parse all the coordinates, attempting to identify longitude, latitude, x, y,
+        # time, vertical, in that order.
+        coord_lists = {'longitude': [], 'latitude': [], 'x': [], 'y': [], 'time': [],
+                       'vertical': []}
         for coord_var in coords:
             # Identify the coordinate type using check_axis helper
             for axis in coord_lists:
                 if check_axis(coord_var, axis):
                     coord_lists[axis].append(coord_var)
+                    break  # Ensure a coordinate variable only goes to one axis
 
         # Fill in x/y with longitude/latitude if x/y not otherwise present
         for geometric, graticule in (('y', 'latitude'), ('x', 'longitude')):

diff --git a/ci/test_requirements.txt b/ci/test_requirements.txt
index 4302ff9e96..61b6ff44b9 100644
--- a/ci/test_requirements.txt
+++ b/ci/test_requirements.txt
@@ -2,4 +2,4 @@ packaging==24.0
 pytest==8.1.1
 pytest-mpl==0.17.0
 netCDF4==1.6.5
-coverage==7.4.3
+coverage==7.4.4
diff --git a/tests/test_xarray.py b/tests/test_xarray.py
index a5364f327b..2571944f80 100644
--- a/tests/test_xarray.py
+++ b/tests/test_xarray.py
@@ -273,6 +273,14 @@ def test_missing_grid_mapping_invalid(test_var_multidim_no_xy):
     assert 'metpy_crs' not in data_var.coords
 
 
+def test_xy_not_vertical(test_ds):
+    """Test not detecting x/y as a vertical coordinate based on metadata."""
+    test_ds.x.attrs['positive'] = 'up'
+    test_ds.y.attrs['positive'] = 'up'
+    data_var = test_ds.metpy.parse_cf('Temperature')
+    assert data_var.metpy.vertical.identical(data_var.coords['isobaric'])
+
+
 def test_missing_grid_mapping_var(caplog):
     """Test behavior when we can't find the variable pointed to by grid_mapping."""
     x = xr.DataArray(np.arange(3),

mpcalc.isentropic_interpolation_as_dataset "vertical attribute is not available."
I get an error "vertical attribute is not available." when interpolating bitwise vortices to isentropic surfaces using the mpcalc.isentropic_interpolation_as_dataset function.Here's the code and the specifics of the error reported：

```python
f=xr.open_dataset(r'H:\data\dust\daily_atmosphere_data\daily_mean_era5_pv0.5_198604.nc')
f_1=xr.open_dataset(r'H:\data\dust\daily_atmosphere_data\daily_mean_era5_t0.5_198604.nc')
pv=f.pv.loc['1986-04-01',100000:20000,20:60,30:150] # （level，lat，lon）
t=f_1.t.loc['1986-04-01',100000:20000,20:60,30:150]# （level，lat，lon）
print(t,pv)
isentlevs = [345.] * units.kelvin
print(isen_lev)
isent_data = mpcalc.isentropic_interpolation_as_dataset(isentlevs, t, pv)
```
```
C:\Users\Administrator\AppData\Local\Temp\ipykernel_8224\906077059.py:12: UserWarning: More than one vertical coordinate present for variable  "t".
  isent_data = mpcalc.isentropic_interpolation_as_dataset(isentlevs, t, pv)
```

```pytb
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Input In [20], in <cell line: 12>()
     10 print(isen_lev)
     11 # 调用 isentropic_interpolation_as_dataset 函数
---> 12 isent_data = mpcalc.isentropic_interpolation_as_dataset(isentlevs, t, pv)

File G:\Anaconda\lib\site-packages\metpy\calc\thermo.py:2761, in isentropic_interpolation_as_dataset(levels, temperature, max_iters, eps, bottom_up_search, *args)
   2756 all_args = xr.broadcast(temperature, *args)
   2758 # Obtain result as list of Quantities
   2759 ret = isentropic_interpolation(
   2760     levels,
-> 2761     all_args[0].metpy.vertical,
   2762     all_args[0].metpy.unit_array,
   2763     *(arg.metpy.unit_array for arg in all_args[1:]),
   2764     vertical_dim=all_args[0].metpy.find_axis_number('vertical'),
   2765     temperature_out=True,
   2766     max_iters=max_iters,
   2767     eps=eps,
   2768     bottom_up_search=bottom_up_search
   2769 )
   2771 # Reconstruct coordinates and dims (add isentropic levels, remove isobaric levels)
   2772 vertical_dim = all_args[0].metpy.find_axis_name('vertical')

File G:\Anaconda\lib\site-packages\metpy\xarray.py:486, in MetPyDataArrayAccessor.vertical(self)
    483 @property
    484 def vertical(self):
    485     """Return the vertical coordinate."""
--> 486     return self._axis('vertical')

File G:\Anaconda\lib\site-packages\metpy\xarray.py:418, in MetPyDataArrayAccessor._axis(self, axis)
    416 coord_var = self._metpy_axis_search(axis)
    417 if coord_var is None:
--> 418     raise AttributeError(axis + ' attribute is not available.')
    419 else:
    420     return coord_var

AttributeError: vertical attribute is not available.
```

tests/test_xarray.py::test_xy_not_vertical
tests/test_xarray.py::test_pyproj_projection tests/test_xarray.py::test_no_projection tests/test_xarray.py::test_unit_array tests/test_xarray.py::test_units tests/test_xarray.py::test_units_data tests/test_xarray.py::test_units_percent tests/test_xarray.py::test_magnitude_with_quantity tests/test_xarray.py::test_magnitude_without_quantity tests/test_xarray.py::test_convert_units tests/test_xarray.py::test_convert_to_base_units tests/test_xarray.py::test_convert_coordinate_units tests/test_xarray.py::test_latlon_default_units tests/test_xarray.py::test_quantify tests/test_xarray.py::test_dequantify tests/test_xarray.py::test_dataset_quantify tests/test_xarray.py::test_dataset_dequantify tests/test_xarray.py::test_radian_projection_coords tests/test_xarray.py::test_missing_grid_mapping_valid tests/test_xarray.py::test_missing_grid_mapping_invalid tests/test_xarray.py::test_missing_grid_mapping_var tests/test_xarray.py::test_parsecf_crs tests/test_xarray.py::test_parsecf_existing_scalar_crs tests/test_xarray.py::test_parsecf_existing_vector_crs tests/test_xarray.py::test_preprocess_and_wrap_only_preprocessing tests/test_xarray.py::test_coordinates_basic_by_method tests/test_xarray.py::test_coordinates_basic_by_property tests/test_xarray.py::test_coordinates_specified_by_name_with_dataset tests/test_xarray.py::test_coordinates_specified_by_dataarray_with_dataset tests/test_xarray.py::test_missing_coordinate_type tests/test_xarray.py::test_assign_coordinates_not_overwrite tests/test_xarray.py::test_resolve_axis_conflict_lonlat_and_xy tests/test_xarray.py::test_resolve_axis_conflict_double_lonlat tests/test_xarray.py::test_resolve_axis_conflict_double_xy tests/test_xarray.py::test_resolve_axis_conflict_double_x_with_single_dim tests/test_xarray.py::test_resolve_axis_conflict_double_vertical tests/test_xarray.py::test_check_axis_criterion_match[test_tuple0] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple1] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple2] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple3] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple4] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple5] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple6] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple7] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple8] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple9] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple10] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple11] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple12] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple13] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple14] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple15] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple16] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple17] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple18] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple19] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple20] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple21] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple22] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple23] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple24] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple25] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple26] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple27] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple28] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple29] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple30] tests/test_xarray.py::test_check_axis_criterion_match[test_tuple31] tests/test_xarray.py::test_check_axis_unit_match[test_tuple0] tests/test_xarray.py::test_check_axis_unit_match[test_tuple1] tests/test_xarray.py::test_check_axis_unit_match[test_tuple2] tests/test_xarray.py::test_check_axis_unit_match[test_tuple3] tests/test_xarray.py::test_check_axis_unit_match[test_tuple4] tests/test_xarray.py::test_check_axis_unit_match[test_tuple5] tests/test_xarray.py::test_check_axis_unit_match[test_tuple6] tests/test_xarray.py::test_check_axis_unit_match[test_tuple7] tests/test_xarray.py::test_check_axis_unit_match[test_tuple8] tests/test_xarray.py::test_check_axis_unit_match[test_tuple9] tests/test_xarray.py::test_check_axis_unit_match[test_tuple10] tests/test_xarray.py::test_check_axis_unit_match[test_tuple11] tests/test_xarray.py::test_check_axis_unit_match[test_tuple12] tests/test_xarray.py::test_check_axis_unit_match[test_tuple13] tests/test_xarray.py::test_check_axis_unit_match[test_tuple14] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple0] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple1] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple2] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple3] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple4] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple5] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple6] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple7] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple8] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple9] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple10] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple11] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple12] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple13] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple14] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple15] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple16] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple17] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple18] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple19] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple20] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple21] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple22] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple23] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple24] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple25] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple26] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple27] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple28] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple29] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple30] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple31] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple32] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple33] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple34] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple35] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple36] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple37] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple38] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple39] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple40] tests/test_xarray.py::test_check_axis_regular_expression_match[test_tuple41] tests/test_xarray.py::test_narr_example_variable_without_grid_mapping tests/test_xarray.py::test_coordinates_identical_true tests/test_xarray.py::test_coordinates_identical_false_number_of_coords tests/test_xarray.py::test_coordinates_identical_false_coords_mismatch tests/test_xarray.py::test_check_matching_coordinates tests/test_xarray.py::test_time_deltas tests/test_xarray.py::test_find_axis_name_integer tests/test_xarray.py::test_find_axis_name_axis_type tests/test_xarray.py::test_find_axis_name_dim_coord_name tests/test_xarray.py::test_find_axis_name_bad_identifier tests/test_xarray.py::test_find_axis_number_integer tests/test_xarray.py::test_find_axis_number_axis_type tests/test_xarray.py::test_find_axis_number_dim_coord_number tests/test_xarray.py::test_find_axis_number_bad_identifier tests/test_xarray.py::test_cf_parse_with_grid_mapping tests/test_xarray.py::test_data_array_loc_get_with_units tests/test_xarray.py::test_data_array_loc_set_with_units tests/test_xarray.py::test_data_array_loc_with_ellipsis tests/test_xarray.py::test_data_array_loc_non_tuple tests/test_xarray.py::test_data_array_loc_too_many_indices tests/test_xarray.py::test_data_array_sel_dict_with_units tests/test_xarray.py::test_data_array_sel_kwargs_with_units tests/test_xarray.py::test_dataset_loc_with_units tests/test_xarray.py::test_dataset_sel_kwargs_with_units tests/test_xarray.py::test_dataset_sel_non_dict_pos_arg tests/test_xarray.py::test_dataset_sel_mixed_dict_and_kwarg tests/test_xarray.py::test_dataset_loc_without_dict tests/test_xarray.py::test_dataset_parse_cf_keep_attrs tests/test_xarray.py::test_check_axis_with_bad_unit tests/test_xarray.py::test_dataset_parse_cf_varname_list tests/test_xarray.py::test_coordinate_identification_shared_but_not_equal_coords tests/test_xarray.py::test_one_dimensional_lat_lon tests/test_xarray.py::test_auxilary_lat_lon_with_xy tests/test_xarray.py::test_auxilary_lat_lon_without_xy tests/test_xarray.py::test_auxilary_lat_lon_without_xy_as_xy tests/test_xarray.py::test_assign_crs_error_with_both_attrs tests/test_xarray.py::test_assign_crs_error_with_neither_attrs tests/test_xarray.py::test_assign_latitude_longitude_no_horizontal tests/test_xarray.py::test_assign_y_x_no_horizontal tests/test_xarray.py::test_assign_latitude_longitude_basic_dataarray tests/test_xarray.py::test_assign_latitude_longitude_error_existing_dataarray tests/test_xarray.py::test_assign_latitude_longitude_force_existing_dataarray tests/test_xarray.py::test_assign_latitude_longitude_basic_dataset tests/test_xarray.py::test_assign_y_x_basic_dataarray tests/test_xarray.py::test_assign_y_x_error_existing_dataarray tests/test_xarray.py::test_assign_y_x_force_existing_dataarray tests/test_xarray.py::test_assign_y_x_dataarray_outside_tolerance tests/test_xarray.py::test_assign_y_x_dataarray_transposed tests/test_xarray.py::test_assign_y_x_dataset_assumed_order tests/test_xarray.py::test_assign_y_x_error_existing_dataset tests/test_xarray.py::test_update_attribute_dictionary tests/test_xarray.py::test_update_attribute_callable tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test0-other0-False-expected0] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test1-other1-True-expected1] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test2-other2-False-expected2] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test3-other3-True-expected3] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test4-other4-False-expected4] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test5-other5-True-expected5] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test6-other6-False-expected6] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test7-other7-True-expected7] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test8-other8-False-expected8] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test9-other9-True-expected9] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test10-other10-False-expected10] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test11-other11-False-expected11] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test12-other12-True-expected12] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test13-other13-False-expected13] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg[test14-other14-True-expected14] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg_raising_dimensionality_error[test0-other0] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg_raising_dimensionality_error[test1-other1] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg_raising_dimensionality_error[test2-other2] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg_raising_dimensionality_error[test3-other3] tests/test_xarray.py::test_wrap_with_wrap_like_kwarg_raising_dimensionality_error[test4-other4] tests/test_xarray.py::test_wrap_with_argument_kwarg tests/test_xarray.py::test_preprocess_and_wrap_with_broadcasting tests/test_xarray.py::test_preprocess_and_wrap_broadcasting_error tests/test_xarray.py::test_preprocess_and_wrap_with_to_magnitude tests/test_xarray.py::test_preprocess_and_wrap_with_variable tests/test_xarray.py::test_grid_deltas_from_dataarray_lonlat tests/test_xarray.py::test_grid_deltas_from_dataarray_xy tests/test_xarray.py::test_grid_deltas_from_dataarray_nominal_lonlat tests/test_xarray.py::test_grid_deltas_from_dataarray_lonlat_assumed_order tests/test_xarray.py::test_grid_deltas_from_dataarray_invalid_kind tests/test_xarray.py::test_add_vertical_dim_from_xarray