We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
Remove usage of `distutils` which has been deprecated
It turns out that `distutils` has been deprecated and will be removed in Python 3.12.  We should stop using it prior to our 0.7 release.  Fortunately I only found one usage in: `plasmapy/plasma/sources/openpmd_hdf5.py`.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `plasmapy/plasma/sources/openpmd_hdf5.py`
Content:
```
1 __all__ = ["HDF5Reader"]
2 
3 import astropy.units as u
4 import numpy as np
5 import os
6 
7 from distutils.version import StrictVersion
8 
9 from plasmapy.plasma.exceptions import DataStandardError
10 from plasmapy.plasma.plasma_base import GenericPlasma
11 
12 _OUTDATED_VERSION = "1.1.0"
13 _NEWER_VERSION = "2.0.0"
14 
15 # This is the order what OpenPMD uses to store unit
16 # dimensions for a record.
17 _UNITS = (u.meter, u.kilogram, u.second, u.ampere, u.Kelvin, u.mol, u.candela)
18 
19 
20 def _fetch_units(openPMD_dims):
21     """Converts a collection of OpenPMD dimensions to astropy.units."""
22 
23     units = u.dimensionless_unscaled
24     for factor, unit in zip(openPMD_dims, _UNITS):
25         units *= unit ** factor
26     units, *_ = units.compose()
27     return units
28 
29 
30 def _valid_version(openPMD_version, outdated=_OUTDATED_VERSION, newer=_NEWER_VERSION):
31     """Checks if the passed version is supported or not."""
32 
33     parsed_version = StrictVersion(openPMD_version)
34     outdated_version = StrictVersion(outdated)
35     newer_version = StrictVersion(newer)
36     return outdated_version <= parsed_version < newer_version
37 
38 
39 class HDF5Reader(GenericPlasma):
40     """
41     .. _OpenPMD: https://www.openpmd.org/
42 
43     Core class for accessing various attributes on HDF5 files that
44     are based on OpenPMD_ standards.
45 
46     Parameters
47     ----------
48     hdf5 : `str`
49         Path to HDF5 file.
50 
51     **kwargs
52         Any keyword accepted by `GenericPlasma`.
53 
54     """
55 
56     def __init__(self, hdf5, **kwargs):
57         super().__init__(**kwargs)
58 
59         if not os.path.isfile(hdf5):
60             raise FileNotFoundError(f"Could not find file: '{hdf5}'")
61         try:
62             import h5py
63         except (ImportError, ModuleNotFoundError) as e:
64             from plasmapy.optional_deps import h5py_import_error
65 
66             raise ImportError(h5py_import_error) from e
67 
68         h5 = h5py.File(hdf5, "r")
69         self.h5 = h5
70 
71         self._check_valid_openpmd_version()
72 
73         self.subname = tuple(self.h5["data"])[0]
74 
75     def __enter__(self):
76         return self.h5
77 
78     def close(self):
79         self.h5.close()
80 
81     def __exit__(self):
82         self.h5.close()
83 
84     def _check_valid_openpmd_version(self):
85         try:
86             openPMD_version = self.h5.attrs["openPMD"].decode("utf-8")
87             if _valid_version(openPMD_version):
88                 return True
89             else:
90                 raise DataStandardError(
91                     f"We currently only support HDF5 versions"
92                     f"starting from v{_OUTDATED_VERSION} and "
93                     f"lower than v{_NEWER_VERSION}. You can "
94                     f"however convert your HDF5 to a supported "
95                     f"version. For more information; see "
96                     f"https://github.com/openPMD/openPMD-updater"
97                 )
98         except KeyError:
99             raise DataStandardError(
100                 "Input HDF5 file does not go on with standards defined by OpenPMD"
101             )
102 
103     @property
104     def electric_field(self):
105         """
106         An (x, y, z) array containing electric field data.  (Returned as an astropy
107         `~astropy.units.Quantity`.)
108         """
109         path = f"data/{self.subname}/fields/E"
110         if path in self.h5:
111             units = _fetch_units(self.h5[path].attrs["unitDimension"])
112             axes = [self.h5[path][axis] for axis in self.h5[path]]
113             return np.array(axes) * units
114         else:
115             raise AttributeError("No electric field data available in HDF5 file")
116 
117     @property
118     def charge_density(self):
119         """
120         An array containing charge density data.  (Returned as an astropy
121         `~astropy.units.Quantity`.)
122         """
123         path = f"data/{self.subname}/fields/rho"
124         if path in self.h5:
125             units = _fetch_units(self.h5[path].attrs["unitDimension"])
126             return np.array(self.h5[path]) * units
127         else:
128             raise AttributeError("No charge density data available in HDF5 file")
129 
130     @property
131     def magnetic_field(self):
132         path = f"data/{self.subname}/fields/B"
133         if path in self.h5:
134             units = _fetch_units(self.h5[path].attrs["unitDimension"])
135             axes = [self.h5[path][axis] for axis in self.h5[path]]
136             return np.array(axes) * units
137         else:
138             raise AttributeError("No magnetic field data available in HDF5 file")
139 
140     @property
141     def electric_current(self):
142         path = f"data/{self.subname}/fields/J"
143         if path in self.h5:
144             units = _fetch_units(self.h5[path].attrs["unitDimension"])
145             axes = [self.h5[path][axis] for axis in self.h5[path]]
146             return np.array(axes) * units
147         else:
148             raise AttributeError("No electric current data available in HDF5 file")
149 
150     @classmethod
151     def is_datasource_for(cls, **kwargs):
152         if "hdf5" not in kwargs:
153             return False
154 
155         hdf5 = kwargs.get("hdf5")
156         openPMD = kwargs.get("openPMD")
157 
158         isfile = os.path.isfile(hdf5)
159         if not isfile:
160             raise FileNotFoundError(f"Could not find file: '{hdf5}'")
161 
162         if "openPMD" not in kwargs:
163             try:
164                 import h5py
165             except (ImportError, ModuleNotFoundError) as e:
166                 from plasmapy.optional_deps import h5py_import_error
167 
168                 raise ImportError(h5py_import_error) from e
169 
170             h5 = h5py.File(hdf5, "r")
171             try:
172                 openPMD = h5.attrs["openPMD"]
173             except KeyError:
174                 openPMD = False
175 
176         return openPMD
177
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/plasmapy/plasma/sources/openpmd_hdf5.py b/plasmapy/plasma/sources/openpmd_hdf5.py
--- a/plasmapy/plasma/sources/openpmd_hdf5.py
+++ b/plasmapy/plasma/sources/openpmd_hdf5.py
@@ -4,7 +4,7 @@
 import numpy as np
 import os
 
-from distutils.version import StrictVersion
+from packaging.version import Version
 
 from plasmapy.plasma.exceptions import DataStandardError
 from plasmapy.plasma.plasma_base import GenericPlasma
@@ -30,9 +30,9 @@
 def _valid_version(openPMD_version, outdated=_OUTDATED_VERSION, newer=_NEWER_VERSION):
     """Checks if the passed version is supported or not."""
 
-    parsed_version = StrictVersion(openPMD_version)
-    outdated_version = StrictVersion(outdated)
-    newer_version = StrictVersion(newer)
+    parsed_version = Version(openPMD_version)
+    outdated_version = Version(outdated)
+    newer_version = Version(newer)
     return outdated_version <= parsed_version < newer_version

{"golden_diff": "diff --git a/plasmapy/plasma/sources/openpmd_hdf5.py b/plasmapy/plasma/sources/openpmd_hdf5.py\n--- a/plasmapy/plasma/sources/openpmd_hdf5.py\n+++ b/plasmapy/plasma/sources/openpmd_hdf5.py\n@@ -4,7 +4,7 @@\n import numpy as np\n import os\n \n-from distutils.version import StrictVersion\n+from packaging.version import Version\n \n from plasmapy.plasma.exceptions import DataStandardError\n from plasmapy.plasma.plasma_base import GenericPlasma\n@@ -30,9 +30,9 @@\n def _valid_version(openPMD_version, outdated=_OUTDATED_VERSION, newer=_NEWER_VERSION):\n     \"\"\"Checks if the passed version is supported or not.\"\"\"\n \n-    parsed_version = StrictVersion(openPMD_version)\n-    outdated_version = StrictVersion(outdated)\n-    newer_version = StrictVersion(newer)\n+    parsed_version = Version(openPMD_version)\n+    outdated_version = Version(outdated)\n+    newer_version = Version(newer)\n     return outdated_version <= parsed_version < newer_version\n", "issue": "Remove usage of `distutils` which has been deprecated\nIt turns out that `distutils` has been deprecated and will be removed in Python 3.12.  We should stop using it prior to our 0.7 release.  Fortunately I only found one usage in: `plasmapy/plasma/sources/openpmd_hdf5.py`.\n", "before_files": [{"content": "__all__ = [\"HDF5Reader\"]\n\nimport astropy.units as u\nimport numpy as np\nimport os\n\nfrom distutils.version import StrictVersion\n\nfrom plasmapy.plasma.exceptions import DataStandardError\nfrom plasmapy.plasma.plasma_base import GenericPlasma\n\n_OUTDATED_VERSION = \"1.1.0\"\n_NEWER_VERSION = \"2.0.0\"\n\n# This is the order what OpenPMD uses to store unit\n# dimensions for a record.\n_UNITS = (u.meter, u.kilogram, u.second, u.ampere, u.Kelvin, u.mol, u.candela)\n\n\ndef _fetch_units(openPMD_dims):\n    \"\"\"Converts a collection of OpenPMD dimensions to astropy.units.\"\"\"\n\n    units = u.dimensionless_unscaled\n    for factor, unit in zip(openPMD_dims, _UNITS):\n        units *= unit ** factor\n    units, *_ = units.compose()\n    return units\n\n\ndef _valid_version(openPMD_version, outdated=_OUTDATED_VERSION, newer=_NEWER_VERSION):\n    \"\"\"Checks if the passed version is supported or not.\"\"\"\n\n    parsed_version = StrictVersion(openPMD_version)\n    outdated_version = StrictVersion(outdated)\n    newer_version = StrictVersion(newer)\n    return outdated_version <= parsed_version < newer_version\n\n\nclass HDF5Reader(GenericPlasma):\n    \"\"\"\n    .. _OpenPMD: https://www.openpmd.org/\n\n    Core class for accessing various attributes on HDF5 files that\n    are based on OpenPMD_ standards.\n\n    Parameters\n    ----------\n    hdf5 : `str`\n        Path to HDF5 file.\n\n    **kwargs\n        Any keyword accepted by `GenericPlasma`.\n\n    \"\"\"\n\n    def __init__(self, hdf5, **kwargs):\n        super().__init__(**kwargs)\n\n        if not os.path.isfile(hdf5):\n            raise FileNotFoundError(f\"Could not find file: '{hdf5}'\")\n        try:\n            import h5py\n        except (ImportError, ModuleNotFoundError) as e:\n            from plasmapy.optional_deps import h5py_import_error\n\n            raise ImportError(h5py_import_error) from e\n\n        h5 = h5py.File(hdf5, \"r\")\n        self.h5 = h5\n\n        self._check_valid_openpmd_version()\n\n        self.subname = tuple(self.h5[\"data\"])[0]\n\n    def __enter__(self):\n        return self.h5\n\n    def close(self):\n        self.h5.close()\n\n    def __exit__(self):\n        self.h5.close()\n\n    def _check_valid_openpmd_version(self):\n        try:\n            openPMD_version = self.h5.attrs[\"openPMD\"].decode(\"utf-8\")\n            if _valid_version(openPMD_version):\n                return True\n            else:\n                raise DataStandardError(\n                    f\"We currently only support HDF5 versions\"\n                    f\"starting from v{_OUTDATED_VERSION} and \"\n                    f\"lower than v{_NEWER_VERSION}. You can \"\n                    f\"however convert your HDF5 to a supported \"\n                    f\"version. For more information; see \"\n                    f\"https://github.com/openPMD/openPMD-updater\"\n                )\n        except KeyError:\n            raise DataStandardError(\n                \"Input HDF5 file does not go on with standards defined by OpenPMD\"\n            )\n\n    @property\n    def electric_field(self):\n        \"\"\"\n        An (x, y, z) array containing electric field data.  (Returned as an astropy\n        `~astropy.units.Quantity`.)\n        \"\"\"\n        path = f\"data/{self.subname}/fields/E\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            axes = [self.h5[path][axis] for axis in self.h5[path]]\n            return np.array(axes) * units\n        else:\n            raise AttributeError(\"No electric field data available in HDF5 file\")\n\n    @property\n    def charge_density(self):\n        \"\"\"\n        An array containing charge density data.  (Returned as an astropy\n        `~astropy.units.Quantity`.)\n        \"\"\"\n        path = f\"data/{self.subname}/fields/rho\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            return np.array(self.h5[path]) * units\n        else:\n            raise AttributeError(\"No charge density data available in HDF5 file\")\n\n    @property\n    def magnetic_field(self):\n        path = f\"data/{self.subname}/fields/B\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            axes = [self.h5[path][axis] for axis in self.h5[path]]\n            return np.array(axes) * units\n        else:\n            raise AttributeError(\"No magnetic field data available in HDF5 file\")\n\n    @property\n    def electric_current(self):\n        path = f\"data/{self.subname}/fields/J\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            axes = [self.h5[path][axis] for axis in self.h5[path]]\n            return np.array(axes) * units\n        else:\n            raise AttributeError(\"No electric current data available in HDF5 file\")\n\n    @classmethod\n    def is_datasource_for(cls, **kwargs):\n        if \"hdf5\" not in kwargs:\n            return False\n\n        hdf5 = kwargs.get(\"hdf5\")\n        openPMD = kwargs.get(\"openPMD\")\n\n        isfile = os.path.isfile(hdf5)\n        if not isfile:\n            raise FileNotFoundError(f\"Could not find file: '{hdf5}'\")\n\n        if \"openPMD\" not in kwargs:\n            try:\n                import h5py\n            except (ImportError, ModuleNotFoundError) as e:\n                from plasmapy.optional_deps import h5py_import_error\n\n                raise ImportError(h5py_import_error) from e\n\n            h5 = h5py.File(hdf5, \"r\")\n            try:\n                openPMD = h5.attrs[\"openPMD\"]\n            except KeyError:\n                openPMD = False\n\n        return openPMD\n", "path": "plasmapy/plasma/sources/openpmd_hdf5.py"}], "after_files": [{"content": "__all__ = [\"HDF5Reader\"]\n\nimport astropy.units as u\nimport numpy as np\nimport os\n\nfrom packaging.version import Version\n\nfrom plasmapy.plasma.exceptions import DataStandardError\nfrom plasmapy.plasma.plasma_base import GenericPlasma\n\n_OUTDATED_VERSION = \"1.1.0\"\n_NEWER_VERSION = \"2.0.0\"\n\n# This is the order what OpenPMD uses to store unit\n# dimensions for a record.\n_UNITS = (u.meter, u.kilogram, u.second, u.ampere, u.Kelvin, u.mol, u.candela)\n\n\ndef _fetch_units(openPMD_dims):\n    \"\"\"Converts a collection of OpenPMD dimensions to astropy.units.\"\"\"\n\n    units = u.dimensionless_unscaled\n    for factor, unit in zip(openPMD_dims, _UNITS):\n        units *= unit ** factor\n    units, *_ = units.compose()\n    return units\n\n\ndef _valid_version(openPMD_version, outdated=_OUTDATED_VERSION, newer=_NEWER_VERSION):\n    \"\"\"Checks if the passed version is supported or not.\"\"\"\n\n    parsed_version = Version(openPMD_version)\n    outdated_version = Version(outdated)\n    newer_version = Version(newer)\n    return outdated_version <= parsed_version < newer_version\n\n\nclass HDF5Reader(GenericPlasma):\n    \"\"\"\n    .. _OpenPMD: https://www.openpmd.org/\n\n    Core class for accessing various attributes on HDF5 files that\n    are based on OpenPMD_ standards.\n\n    Parameters\n    ----------\n    hdf5 : `str`\n        Path to HDF5 file.\n\n    **kwargs\n        Any keyword accepted by `GenericPlasma`.\n\n    \"\"\"\n\n    def __init__(self, hdf5, **kwargs):\n        super().__init__(**kwargs)\n\n        if not os.path.isfile(hdf5):\n            raise FileNotFoundError(f\"Could not find file: '{hdf5}'\")\n        try:\n            import h5py\n        except (ImportError, ModuleNotFoundError) as e:\n            from plasmapy.optional_deps import h5py_import_error\n\n            raise ImportError(h5py_import_error) from e\n\n        h5 = h5py.File(hdf5, \"r\")\n        self.h5 = h5\n\n        self._check_valid_openpmd_version()\n\n        self.subname = tuple(self.h5[\"data\"])[0]\n\n    def __enter__(self):\n        return self.h5\n\n    def close(self):\n        self.h5.close()\n\n    def __exit__(self):\n        self.h5.close()\n\n    def _check_valid_openpmd_version(self):\n        try:\n            openPMD_version = self.h5.attrs[\"openPMD\"].decode(\"utf-8\")\n            if _valid_version(openPMD_version):\n                return True\n            else:\n                raise DataStandardError(\n                    f\"We currently only support HDF5 versions\"\n                    f\"starting from v{_OUTDATED_VERSION} and \"\n                    f\"lower than v{_NEWER_VERSION}. You can \"\n                    f\"however convert your HDF5 to a supported \"\n                    f\"version. For more information; see \"\n                    f\"https://github.com/openPMD/openPMD-updater\"\n                )\n        except KeyError:\n            raise DataStandardError(\n                \"Input HDF5 file does not go on with standards defined by OpenPMD\"\n            )\n\n    @property\n    def electric_field(self):\n        \"\"\"\n        An (x, y, z) array containing electric field data.  (Returned as an astropy\n        `~astropy.units.Quantity`.)\n        \"\"\"\n        path = f\"data/{self.subname}/fields/E\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            axes = [self.h5[path][axis] for axis in self.h5[path]]\n            return np.array(axes) * units\n        else:\n            raise AttributeError(\"No electric field data available in HDF5 file\")\n\n    @property\n    def charge_density(self):\n        \"\"\"\n        An array containing charge density data.  (Returned as an astropy\n        `~astropy.units.Quantity`.)\n        \"\"\"\n        path = f\"data/{self.subname}/fields/rho\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            return np.array(self.h5[path]) * units\n        else:\n            raise AttributeError(\"No charge density data available in HDF5 file\")\n\n    @property\n    def magnetic_field(self):\n        path = f\"data/{self.subname}/fields/B\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            axes = [self.h5[path][axis] for axis in self.h5[path]]\n            return np.array(axes) * units\n        else:\n            raise AttributeError(\"No magnetic field data available in HDF5 file\")\n\n    @property\n    def electric_current(self):\n        path = f\"data/{self.subname}/fields/J\"\n        if path in self.h5:\n            units = _fetch_units(self.h5[path].attrs[\"unitDimension\"])\n            axes = [self.h5[path][axis] for axis in self.h5[path]]\n            return np.array(axes) * units\n        else:\n            raise AttributeError(\"No electric current data available in HDF5 file\")\n\n    @classmethod\n    def is_datasource_for(cls, **kwargs):\n        if \"hdf5\" not in kwargs:\n            return False\n\n        hdf5 = kwargs.get(\"hdf5\")\n        openPMD = kwargs.get(\"openPMD\")\n\n        isfile = os.path.isfile(hdf5)\n        if not isfile:\n            raise FileNotFoundError(f\"Could not find file: '{hdf5}'\")\n\n        if \"openPMD\" not in kwargs:\n            try:\n                import h5py\n            except (ImportError, ModuleNotFoundError) as e:\n                from plasmapy.optional_deps import h5py_import_error\n\n                raise ImportError(h5py_import_error) from e\n\n            h5 = h5py.File(hdf5, \"r\")\n            try:\n                openPMD = h5.attrs[\"openPMD\"]\n            except KeyError:\n                openPMD = False\n\n        return openPMD\n", "path": "plasmapy/plasma/sources/openpmd_hdf5.py"}]}