We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
sunpy.data.manager does not allow for local path object in manager. override_file()
<!-- This comments are hidden when you submit the issue so you do not need to remove them!
Please be sure to check out our contributing guidelines: https://github.com/sunpy/sunpy/blob/master/CONTRIBUTING.rst
Please be sure to check out our code of conduct:
https://github.com/sunpy/sunpy/blob/master/CODE_OF_CONDUCT.rst -->

<!-- Please have a search on our GitHub repository to see if a similar issue has already been posted.
If a similar issue is closed, have a quick look to see if you are satisfied by the resolution.
If not please go ahead and open an issue! -->

### Description
It would be great if `sunpy.data.manager` could take a local file path




--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `sunpy/data/data_manager/manager.py`
Content:
```
1 from typing import Dict
2 import pathlib
3 import functools
4 from contextlib import contextmanager
5 import warnings
6 
7 from sunpy.util.util import hash_file
8 from sunpy.util.exceptions import SunpyUserWarning
9 
10 __all__ = ['DataManager']
11 
12 
13 class DataManager:
14     """
15     This class provides a remote data manager for managing remote files.
16 
17     Parameters
18     ----------
19     cache: `sunpy.data.data_manager.cache.Cache`
20         Cache object to be used by `~sunpy.data.data_manager.manager.DataManager`.
21     """
22 
23     def __init__(self, cache):
24         self._cache = cache
25 
26         self._file_cache = {}
27 
28         self._skip_hash_check = False
29         self._skip_file: Dict[str, str] = {}
30 
31     def require(self, name, urls, sha_hash):
32         """
33         Decorator for informing the data manager about the requirement of
34         a file by a function.
35 
36         Parameters
37         ----------
38         name: `str`
39             The name to reference the file with.
40         urls: `list` or `str`
41             A list of urls to download the file from.
42         sha_hash: `str`
43             SHA-1 hash of file.
44         """
45         if isinstance(urls, str):
46             urls = [urls]
47 
48         def decorator(func):
49             @functools.wraps(func)
50             def wrapper(*args, **kwargs):
51                 replace = self._skip_file.get(name, None)
52                 if replace:
53                     if replace['uri'].startswith('file://'):
54                         file_path = replace['uri'][len('file://'):]
55                         file_hash = hash_file(file_path)
56                     else:
57                         file_path, file_hash, _ = self._cache._download_and_hash([replace['uri']])
58                     if replace['hash'] and file_hash != replace['hash']:
59                         # if hash provided to replace function doesn't match the hash of the file
60                         # raise error
61                         raise ValueError(
62                             "Hash provided to override_file does not match hash of the file.")
63                 elif self._skip_hash_check:
64                     file_path = self._cache.download(urls, redownload=True)
65                 else:
66                     details = self._cache.get_by_hash(sha_hash)
67                     if not details:
68                         # In case we are matching by hash and file does not exist
69                         # That might mean the wrong hash is supplied to decorator
70                         # We match by urls to make sure that is not the case
71                         if self._cache_has_file(urls):
72                             raise ValueError(" Hash provided does not match the hash in database.")
73                         file_path = self._cache.download(urls)
74                         if hash_file(file_path) != sha_hash:
75                             # the hash of the file downloaded does not match provided hash
76                             # this means the file has changed on the server.
77                             # the function should be updated to use the new hash. Raise an error to notify.
78                             raise RuntimeError(
79                                 "Remote file on the server has changed. Update hash of the function.")
80                     else:
81                         # This is to handle the case when the local file appears to be tampered/corrupted
82                         if hash_file(details['file_path']) != details['file_hash']:
83                             warnings.warn("Hashes do not match, the file will be redownloaded (could be be tampered/corrupted)",
84                                           SunpyUserWarning)
85                             file_path = self._cache.download(urls, redownload=True)
86                             # Recheck the hash again, if this fails, we will exit.
87                             if hash_file(file_path) != details['file_hash']:
88                                 raise RuntimeError("Redownloaded file also has the incorrect hash."
89                                                    "The remote file on the server might have changed.")
90                         else:
91                             file_path = details['file_path']
92 
93                 self._file_cache[name] = file_path
94                 return func(*args, **kwargs)
95             return wrapper
96 
97         return decorator
98 
99     @contextmanager
100     def override_file(self, name, uri, sha_hash=None):
101         """
102         Replaces the file by the name with the file provided by the url/path.
103 
104         Parameters
105         ----------
106         name: `str`
107             Name of the file provided in the `require` decorator.
108         uri: `str`
109             URI of the file which replaces original file. Scheme should be
110             one of ``http``, ``https``, ``ftp`` or ``file``.
111         sha_hash: `str`, optional
112             SHA256 hash of the file to compared to after downloading.
113         """
114         try:
115             self._skip_file[name] = {
116                 'uri': uri,
117                 'hash': sha_hash,
118             }
119             yield
120         finally:
121             _ = self._skip_file.pop(name, None)
122 
123     @contextmanager
124     def skip_hash_check(self):
125         """
126         Disables hash checking temporarily
127 
128         Examples
129         --------
130         >>> with remote_data_manager.skip_hash_check():  # doctest: +SKIP
131         ...     myfunction()  # doctest: +SKIP
132         """
133         try:
134             self._skip_hash_check = True
135             yield
136         finally:
137             self._skip_hash_check = False
138 
139     def get(self, name):
140         """
141         Get the file by name.
142 
143         Parameters
144         ----------
145         name: `str`
146             Name of the file given to the data manager, same as the one provided
147             in `~sunpy.data.data_manager.manager.DataManager.require`.
148 
149         Returns
150         -------
151         `pathlib.Path`
152             Path of the file.
153 
154         Raises
155         ------
156         `KeyError`
157             If ``name`` is not in the cache.
158         """
159         return pathlib.Path(self._file_cache[name])
160 
161     def _cache_has_file(self, urls):
162         for url in urls:
163             if self._cache._get_by_url(url):
164                 return True
165         return False
166
```
--- 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/sunpy/data/data_manager/manager.py b/sunpy/data/data_manager/manager.py
--- a/sunpy/data/data_manager/manager.py
+++ b/sunpy/data/data_manager/manager.py
@@ -1,11 +1,12 @@
-from typing import Dict
 import pathlib
+import warnings
 import functools
+from typing import Dict
 from contextlib import contextmanager
-import warnings
+from urllib.parse import urlparse
 
-from sunpy.util.util import hash_file
 from sunpy.util.exceptions import SunpyUserWarning
+from sunpy.util.util import hash_file
 
 __all__ = ['DataManager']
 
@@ -50,8 +51,14 @@
             def wrapper(*args, **kwargs):
                 replace = self._skip_file.get(name, None)
                 if replace:
-                    if replace['uri'].startswith('file://'):
-                        file_path = replace['uri'][len('file://'):]
+                    uri_parse = urlparse(replace['uri'])
+                    if uri_parse.scheme in ("", "file"):
+                        # If a relative file uri is specified (i.e.
+                        # `file://sunpy/test`) this maintains compatibility
+                        # with the original behaviour where this would be
+                        # interpreted as `./sunpy/test` if no scheme is
+                        # specified netloc will be '' by default.
+                        file_path = uri_parse.netloc + uri_parse.path
                         file_hash = hash_file(file_path)
                     else:
                         file_path, file_hash, _ = self._cache._download_and_hash([replace['uri']])
@@ -74,11 +81,13 @@
                         if hash_file(file_path) != sha_hash:
                             # the hash of the file downloaded does not match provided hash
                             # this means the file has changed on the server.
-                            # the function should be updated to use the new hash. Raise an error to notify.
+                            # the function should be updated to use the new
+                            # hash. Raise an error to notify.
                             raise RuntimeError(
                                 "Remote file on the server has changed. Update hash of the function.")
                     else:
-                        # This is to handle the case when the local file appears to be tampered/corrupted
+                        # This is to handle the case when the local file
+                        # appears to be tampered/corrupted
                         if hash_file(details['file_path']) != details['file_hash']:
                             warnings.warn("Hashes do not match, the file will be redownloaded (could be be tampered/corrupted)",
                                           SunpyUserWarning)
@@ -106,8 +115,10 @@
         name: `str`
             Name of the file provided in the `require` decorator.
         uri: `str`
-            URI of the file which replaces original file. Scheme should be
-            one of ``http``, ``https``, ``ftp`` or ``file``.
+            URI of the file which replaces original file. Scheme should be one
+            of ``http``, ``https``, ``ftp`` or ``file``. If no scheme is given
+            the uri will be interpreted as a local path. i.e.
+            ``file:///tmp/test`` and ``/tmp/test`` are the same.
         sha_hash: `str`, optional
             SHA256 hash of the file to compared to after downloading.
         """

{"golden_diff": "diff --git a/sunpy/data/data_manager/manager.py b/sunpy/data/data_manager/manager.py\n--- a/sunpy/data/data_manager/manager.py\n+++ b/sunpy/data/data_manager/manager.py\n@@ -1,11 +1,12 @@\n-from typing import Dict\n import pathlib\n+import warnings\n import functools\n+from typing import Dict\n from contextlib import contextmanager\n-import warnings\n+from urllib.parse import urlparse\n \n-from sunpy.util.util import hash_file\n from sunpy.util.exceptions import SunpyUserWarning\n+from sunpy.util.util import hash_file\n \n __all__ = ['DataManager']\n \n@@ -50,8 +51,14 @@\n             def wrapper(*args, **kwargs):\n                 replace = self._skip_file.get(name, None)\n                 if replace:\n-                    if replace['uri'].startswith('file://'):\n-                        file_path = replace['uri'][len('file://'):]\n+                    uri_parse = urlparse(replace['uri'])\n+                    if uri_parse.scheme in (\"\", \"file\"):\n+                        # If a relative file uri is specified (i.e.\n+                        # `file://sunpy/test`) this maintains compatibility\n+                        # with the original behaviour where this would be\n+                        # interpreted as `./sunpy/test` if no scheme is\n+                        # specified netloc will be '' by default.\n+                        file_path = uri_parse.netloc + uri_parse.path\n                         file_hash = hash_file(file_path)\n                     else:\n                         file_path, file_hash, _ = self._cache._download_and_hash([replace['uri']])\n@@ -74,11 +81,13 @@\n                         if hash_file(file_path) != sha_hash:\n                             # the hash of the file downloaded does not match provided hash\n                             # this means the file has changed on the server.\n-                            # the function should be updated to use the new hash. Raise an error to notify.\n+                            # the function should be updated to use the new\n+                            # hash. Raise an error to notify.\n                             raise RuntimeError(\n                                 \"Remote file on the server has changed. Update hash of the function.\")\n                     else:\n-                        # This is to handle the case when the local file appears to be tampered/corrupted\n+                        # This is to handle the case when the local file\n+                        # appears to be tampered/corrupted\n                         if hash_file(details['file_path']) != details['file_hash']:\n                             warnings.warn(\"Hashes do not match, the file will be redownloaded (could be be tampered/corrupted)\",\n                                           SunpyUserWarning)\n@@ -106,8 +115,10 @@\n         name: `str`\n             Name of the file provided in the `require` decorator.\n         uri: `str`\n-            URI of the file which replaces original file. Scheme should be\n-            one of ``http``, ``https``, ``ftp`` or ``file``.\n+            URI of the file which replaces original file. Scheme should be one\n+            of ``http``, ``https``, ``ftp`` or ``file``. If no scheme is given\n+            the uri will be interpreted as a local path. i.e.\n+            ``file:///tmp/test`` and ``/tmp/test`` are the same.\n         sha_hash: `str`, optional\n             SHA256 hash of the file to compared to after downloading.\n         \"\"\"\n", "issue": "sunpy.data.manager does not allow for local path object in manager. override_file()\n<!-- This comments are hidden when you submit the issue so you do not need to remove them!\r\nPlease be sure to check out our contributing guidelines: https://github.com/sunpy/sunpy/blob/master/CONTRIBUTING.rst\r\nPlease be sure to check out our code of conduct:\r\nhttps://github.com/sunpy/sunpy/blob/master/CODE_OF_CONDUCT.rst -->\r\n\r\n<!-- Please have a search on our GitHub repository to see if a similar issue has already been posted.\r\nIf a similar issue is closed, have a quick look to see if you are satisfied by the resolution.\r\nIf not please go ahead and open an issue! -->\r\n\r\n### Description\r\nIt would be great if `sunpy.data.manager` could take a local file path\r\n\r\n\r\n\n", "before_files": [{"content": "from typing import Dict\nimport pathlib\nimport functools\nfrom contextlib import contextmanager\nimport warnings\n\nfrom sunpy.util.util import hash_file\nfrom sunpy.util.exceptions import SunpyUserWarning\n\n__all__ = ['DataManager']\n\n\nclass DataManager:\n    \"\"\"\n    This class provides a remote data manager for managing remote files.\n\n    Parameters\n    ----------\n    cache: `sunpy.data.data_manager.cache.Cache`\n        Cache object to be used by `~sunpy.data.data_manager.manager.DataManager`.\n    \"\"\"\n\n    def __init__(self, cache):\n        self._cache = cache\n\n        self._file_cache = {}\n\n        self._skip_hash_check = False\n        self._skip_file: Dict[str, str] = {}\n\n    def require(self, name, urls, sha_hash):\n        \"\"\"\n        Decorator for informing the data manager about the requirement of\n        a file by a function.\n\n        Parameters\n        ----------\n        name: `str`\n            The name to reference the file with.\n        urls: `list` or `str`\n            A list of urls to download the file from.\n        sha_hash: `str`\n            SHA-1 hash of file.\n        \"\"\"\n        if isinstance(urls, str):\n            urls = [urls]\n\n        def decorator(func):\n            @functools.wraps(func)\n            def wrapper(*args, **kwargs):\n                replace = self._skip_file.get(name, None)\n                if replace:\n                    if replace['uri'].startswith('file://'):\n                        file_path = replace['uri'][len('file://'):]\n                        file_hash = hash_file(file_path)\n                    else:\n                        file_path, file_hash, _ = self._cache._download_and_hash([replace['uri']])\n                    if replace['hash'] and file_hash != replace['hash']:\n                        # if hash provided to replace function doesn't match the hash of the file\n                        # raise error\n                        raise ValueError(\n                            \"Hash provided to override_file does not match hash of the file.\")\n                elif self._skip_hash_check:\n                    file_path = self._cache.download(urls, redownload=True)\n                else:\n                    details = self._cache.get_by_hash(sha_hash)\n                    if not details:\n                        # In case we are matching by hash and file does not exist\n                        # That might mean the wrong hash is supplied to decorator\n                        # We match by urls to make sure that is not the case\n                        if self._cache_has_file(urls):\n                            raise ValueError(\" Hash provided does not match the hash in database.\")\n                        file_path = self._cache.download(urls)\n                        if hash_file(file_path) != sha_hash:\n                            # the hash of the file downloaded does not match provided hash\n                            # this means the file has changed on the server.\n                            # the function should be updated to use the new hash. Raise an error to notify.\n                            raise RuntimeError(\n                                \"Remote file on the server has changed. Update hash of the function.\")\n                    else:\n                        # This is to handle the case when the local file appears to be tampered/corrupted\n                        if hash_file(details['file_path']) != details['file_hash']:\n                            warnings.warn(\"Hashes do not match, the file will be redownloaded (could be be tampered/corrupted)\",\n                                          SunpyUserWarning)\n                            file_path = self._cache.download(urls, redownload=True)\n                            # Recheck the hash again, if this fails, we will exit.\n                            if hash_file(file_path) != details['file_hash']:\n                                raise RuntimeError(\"Redownloaded file also has the incorrect hash.\"\n                                                   \"The remote file on the server might have changed.\")\n                        else:\n                            file_path = details['file_path']\n\n                self._file_cache[name] = file_path\n                return func(*args, **kwargs)\n            return wrapper\n\n        return decorator\n\n    @contextmanager\n    def override_file(self, name, uri, sha_hash=None):\n        \"\"\"\n        Replaces the file by the name with the file provided by the url/path.\n\n        Parameters\n        ----------\n        name: `str`\n            Name of the file provided in the `require` decorator.\n        uri: `str`\n            URI of the file which replaces original file. Scheme should be\n            one of ``http``, ``https``, ``ftp`` or ``file``.\n        sha_hash: `str`, optional\n            SHA256 hash of the file to compared to after downloading.\n        \"\"\"\n        try:\n            self._skip_file[name] = {\n                'uri': uri,\n                'hash': sha_hash,\n            }\n            yield\n        finally:\n            _ = self._skip_file.pop(name, None)\n\n    @contextmanager\n    def skip_hash_check(self):\n        \"\"\"\n        Disables hash checking temporarily\n\n        Examples\n        --------\n        >>> with remote_data_manager.skip_hash_check():  # doctest: +SKIP\n        ...     myfunction()  # doctest: +SKIP\n        \"\"\"\n        try:\n            self._skip_hash_check = True\n            yield\n        finally:\n            self._skip_hash_check = False\n\n    def get(self, name):\n        \"\"\"\n        Get the file by name.\n\n        Parameters\n        ----------\n        name: `str`\n            Name of the file given to the data manager, same as the one provided\n            in `~sunpy.data.data_manager.manager.DataManager.require`.\n\n        Returns\n        -------\n        `pathlib.Path`\n            Path of the file.\n\n        Raises\n        ------\n        `KeyError`\n            If ``name`` is not in the cache.\n        \"\"\"\n        return pathlib.Path(self._file_cache[name])\n\n    def _cache_has_file(self, urls):\n        for url in urls:\n            if self._cache._get_by_url(url):\n                return True\n        return False\n", "path": "sunpy/data/data_manager/manager.py"}], "after_files": [{"content": "import pathlib\nimport warnings\nimport functools\nfrom typing import Dict\nfrom contextlib import contextmanager\nfrom urllib.parse import urlparse\n\nfrom sunpy.util.exceptions import SunpyUserWarning\nfrom sunpy.util.util import hash_file\n\n__all__ = ['DataManager']\n\n\nclass DataManager:\n    \"\"\"\n    This class provides a remote data manager for managing remote files.\n\n    Parameters\n    ----------\n    cache: `sunpy.data.data_manager.cache.Cache`\n        Cache object to be used by `~sunpy.data.data_manager.manager.DataManager`.\n    \"\"\"\n\n    def __init__(self, cache):\n        self._cache = cache\n\n        self._file_cache = {}\n\n        self._skip_hash_check = False\n        self._skip_file: Dict[str, str] = {}\n\n    def require(self, name, urls, sha_hash):\n        \"\"\"\n        Decorator for informing the data manager about the requirement of\n        a file by a function.\n\n        Parameters\n        ----------\n        name: `str`\n            The name to reference the file with.\n        urls: `list` or `str`\n            A list of urls to download the file from.\n        sha_hash: `str`\n            SHA-1 hash of file.\n        \"\"\"\n        if isinstance(urls, str):\n            urls = [urls]\n\n        def decorator(func):\n            @functools.wraps(func)\n            def wrapper(*args, **kwargs):\n                replace = self._skip_file.get(name, None)\n                if replace:\n                    uri_parse = urlparse(replace['uri'])\n                    if uri_parse.scheme in (\"\", \"file\"):\n                        # If a relative file uri is specified (i.e.\n                        # `file://sunpy/test`) this maintains compatibility\n                        # with the original behaviour where this would be\n                        # interpreted as `./sunpy/test` if no scheme is\n                        # specified netloc will be '' by default.\n                        file_path = uri_parse.netloc + uri_parse.path\n                        file_hash = hash_file(file_path)\n                    else:\n                        file_path, file_hash, _ = self._cache._download_and_hash([replace['uri']])\n                    if replace['hash'] and file_hash != replace['hash']:\n                        # if hash provided to replace function doesn't match the hash of the file\n                        # raise error\n                        raise ValueError(\n                            \"Hash provided to override_file does not match hash of the file.\")\n                elif self._skip_hash_check:\n                    file_path = self._cache.download(urls, redownload=True)\n                else:\n                    details = self._cache.get_by_hash(sha_hash)\n                    if not details:\n                        # In case we are matching by hash and file does not exist\n                        # That might mean the wrong hash is supplied to decorator\n                        # We match by urls to make sure that is not the case\n                        if self._cache_has_file(urls):\n                            raise ValueError(\" Hash provided does not match the hash in database.\")\n                        file_path = self._cache.download(urls)\n                        if hash_file(file_path) != sha_hash:\n                            # the hash of the file downloaded does not match provided hash\n                            # this means the file has changed on the server.\n                            # the function should be updated to use the new\n                            # hash. Raise an error to notify.\n                            raise RuntimeError(\n                                \"Remote file on the server has changed. Update hash of the function.\")\n                    else:\n                        # This is to handle the case when the local file\n                        # appears to be tampered/corrupted\n                        if hash_file(details['file_path']) != details['file_hash']:\n                            warnings.warn(\"Hashes do not match, the file will be redownloaded (could be be tampered/corrupted)\",\n                                          SunpyUserWarning)\n                            file_path = self._cache.download(urls, redownload=True)\n                            # Recheck the hash again, if this fails, we will exit.\n                            if hash_file(file_path) != details['file_hash']:\n                                raise RuntimeError(\"Redownloaded file also has the incorrect hash.\"\n                                                   \"The remote file on the server might have changed.\")\n                        else:\n                            file_path = details['file_path']\n\n                self._file_cache[name] = file_path\n                return func(*args, **kwargs)\n            return wrapper\n\n        return decorator\n\n    @contextmanager\n    def override_file(self, name, uri, sha_hash=None):\n        \"\"\"\n        Replaces the file by the name with the file provided by the url/path.\n\n        Parameters\n        ----------\n        name: `str`\n            Name of the file provided in the `require` decorator.\n        uri: `str`\n            URI of the file which replaces original file. Scheme should be one\n            of ``http``, ``https``, ``ftp`` or ``file``. If no scheme is given\n            the uri will be interpreted as a local path. i.e.\n            ``file:///tmp/test`` and ``/tmp/test`` are the same.\n        sha_hash: `str`, optional\n            SHA256 hash of the file to compared to after downloading.\n        \"\"\"\n        try:\n            self._skip_file[name] = {\n                'uri': uri,\n                'hash': sha_hash,\n            }\n            yield\n        finally:\n            _ = self._skip_file.pop(name, None)\n\n    @contextmanager\n    def skip_hash_check(self):\n        \"\"\"\n        Disables hash checking temporarily\n\n        Examples\n        --------\n        >>> with remote_data_manager.skip_hash_check():  # doctest: +SKIP\n        ...     myfunction()  # doctest: +SKIP\n        \"\"\"\n        try:\n            self._skip_hash_check = True\n            yield\n        finally:\n            self._skip_hash_check = False\n\n    def get(self, name):\n        \"\"\"\n        Get the file by name.\n\n        Parameters\n        ----------\n        name: `str`\n            Name of the file given to the data manager, same as the one provided\n            in `~sunpy.data.data_manager.manager.DataManager.require`.\n\n        Returns\n        -------\n        `pathlib.Path`\n            Path of the file.\n\n        Raises\n        ------\n        `KeyError`\n            If ``name`` is not in the cache.\n        \"\"\"\n        return pathlib.Path(self._file_cache[name])\n\n    def _cache_has_file(self, urls):\n        for url in urls:\n            if self._cache._get_by_url(url):\n                return True\n        return False\n", "path": "sunpy/data/data_manager/manager.py"}]}