We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
A utility for hashing a checkpoint file
### 🚀 Feature

By default Ignite save a checkpoint with the following structure `{filename_prefix}_{name}_{suffix}.{ext}` which is great.
At first, I would like to add an argument for hashing a checkpoint in `Checkpoint` class. But that could occur a read + write overhead if we turn on hashing which may not be used very often during development.

So instead, I would like to propose to add a utility in `ignite.util` for hashing a saved checkpoint file so that we could use `torch.hub.load_state_dict_from_url` with `check_hash=True`.

Implementation (stripped down and untested version):

```py
def hash_checkpoint(checkpoint):
  with open(checkpoint, 'rb') as f:
    hash = hashlib.sha256(f.read()).hexdigest()

  checkpoint_prefix = checkpoint.strip('.pt')
  filname = '-'.join([checkpoint_prefix, hash[:8]]) + '.pt'
  shutil.move(checkpoint, filename)
  return filename
```

Implementation in Code-Generator:

https://github.com/pytorch-ignite/code-generator/blob/a2ed5f771e7cf8a57c6f68b5a3797792f4676433/templates/single/utils.py#L134

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `ignite/utils.py`
Content:
```
1 import collections.abc as collections
2 import functools
3 import logging
4 import random
5 import warnings
6 from typing import Any, Callable, Dict, Optional, TextIO, Tuple, Type, TypeVar, Union, cast
7 
8 import torch
9 
10 __all__ = ["convert_tensor", "apply_to_tensor", "apply_to_type", "to_onehot", "setup_logger", "manual_seed"]
11 
12 
13 def convert_tensor(
14     x: Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes],
15     device: Optional[Union[str, torch.device]] = None,
16     non_blocking: bool = False,
17 ) -> Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes]:
18     """Move tensors to relevant device.
19 
20     Args:
21         x: input tensor or mapping, or sequence of tensors.
22         device: device type to move ``x``.
23         non_blocking: convert a CPU Tensor with pinned memory to a CUDA Tensor
24             asynchronously with respect to the host if possible
25     """
26 
27     def _func(tensor: torch.Tensor) -> torch.Tensor:
28         return tensor.to(device=device, non_blocking=non_blocking) if device is not None else tensor
29 
30     return apply_to_tensor(x, _func)
31 
32 
33 def apply_to_tensor(
34     x: Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes], func: Callable
35 ) -> Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes]:
36     """Apply a function on a tensor or mapping, or sequence of tensors.
37 
38     Args:
39         x: input tensor or mapping, or sequence of tensors.
40         func: the function to apply on ``x``.
41     """
42     return apply_to_type(x, torch.Tensor, func)
43 
44 
45 def apply_to_type(
46     x: Union[Any, collections.Sequence, collections.Mapping, str, bytes],
47     input_type: Union[Type, Tuple[Type[Any], Any]],
48     func: Callable,
49 ) -> Union[Any, collections.Sequence, collections.Mapping, str, bytes]:
50     """Apply a function on an object of `input_type` or mapping, or sequence of objects of `input_type`.
51 
52     Args:
53         x: object or mapping or sequence.
54         input_type: data type of ``x``.
55         func: the function to apply on ``x``.
56     """
57     if isinstance(x, input_type):
58         return func(x)
59     if isinstance(x, (str, bytes)):
60         return x
61     if isinstance(x, collections.Mapping):
62         return cast(Callable, type(x))({k: apply_to_type(sample, input_type, func) for k, sample in x.items()})
63     if isinstance(x, tuple) and hasattr(x, "_fields"):  # namedtuple
64         return cast(Callable, type(x))(*(apply_to_type(sample, input_type, func) for sample in x))
65     if isinstance(x, collections.Sequence):
66         return cast(Callable, type(x))([apply_to_type(sample, input_type, func) for sample in x])
67     raise TypeError((f"x must contain {input_type}, dicts or lists; found {type(x)}"))
68 
69 
70 def to_onehot(indices: torch.Tensor, num_classes: int) -> torch.Tensor:
71     """Convert a tensor of indices of any shape `(N, ...)` to a
72     tensor of one-hot indicators of shape `(N, num_classes, ...)` and of type uint8. Output's device is equal to the
73     input's device`.
74 
75     Args:
76         indices: input tensor to convert.
77         num_classes: number of classes for one-hot tensor.
78 
79     .. versionchanged:: 0.4.3
80         This functions is now torchscriptable.
81     """
82     new_shape = (indices.shape[0], num_classes) + indices.shape[1:]
83     onehot = torch.zeros(new_shape, dtype=torch.uint8, device=indices.device)
84     return onehot.scatter_(1, indices.unsqueeze(1), 1)
85 
86 
87 def setup_logger(
88     name: Optional[str] = "ignite",
89     level: int = logging.INFO,
90     stream: Optional[TextIO] = None,
91     format: str = "%(asctime)s %(name)s %(levelname)s: %(message)s",
92     filepath: Optional[str] = None,
93     distributed_rank: Optional[int] = None,
94     reset: bool = False,
95 ) -> logging.Logger:
96     """Setups logger: name, level, format etc.
97 
98     Args:
99         name: new name for the logger. If None, the standard logger is used.
100         level: logging level, e.g. CRITICAL, ERROR, WARNING, INFO, DEBUG.
101         stream: logging stream. If None, the standard stream is used (sys.stderr).
102         format: logging format. By default, `%(asctime)s %(name)s %(levelname)s: %(message)s`.
103         filepath: Optional logging file path. If not None, logs are written to the file.
104         distributed_rank: Optional, rank in distributed configuration to avoid logger setup for workers.
105             If None, distributed_rank is initialized to the rank of process.
106         reset: if True, reset an existing logger rather than keep format, handlers, and level.
107 
108     Returns:
109         logging.Logger
110 
111     Examples:
112         Improve logs readability when training with a trainer and evaluator:
113 
114         .. code-block:: python
115 
116             from ignite.utils import setup_logger
117 
118             trainer = ...
119             evaluator = ...
120 
121             trainer.logger = setup_logger("trainer")
122             evaluator.logger = setup_logger("evaluator")
123 
124             trainer.run(data, max_epochs=10)
125 
126             # Logs will look like
127             # 2020-01-21 12:46:07,356 trainer INFO: Engine run starting with max_epochs=5.
128             # 2020-01-21 12:46:07,358 trainer INFO: Epoch[1] Complete. Time taken: 00:5:23
129             # 2020-01-21 12:46:07,358 evaluator INFO: Engine run starting with max_epochs=1.
130             # 2020-01-21 12:46:07,358 evaluator INFO: Epoch[1] Complete. Time taken: 00:01:02
131             # ...
132 
133         Every existing logger can be reset if needed
134 
135         .. code-block:: python
136 
137             logger = setup_logger(name="my-logger", format="=== %(name)s %(message)s")
138             logger.info("first message")
139             setup_logger(name="my-logger", format="+++ %(name)s %(message)s", reset=True)
140             logger.info("second message")
141 
142             # Logs will look like
143             # === my-logger first message
144             # +++ my-logger second message
145 
146         Change the level of an existing internal logger
147 
148         .. code-block:: python
149 
150             setup_logger(
151                 name="ignite.distributed.launcher.Parallel",
152                 level=logging.WARNING
153             )
154 
155     .. versionchanged:: 0.4.3
156         Added ``stream`` parameter.
157 
158     .. versionchanged:: 0.4.5
159         Added ``reset`` parameter.
160     """
161     # check if the logger already exists
162     existing = name is None or name in logging.root.manager.loggerDict
163 
164     # if existing, get the logger otherwise create a new one
165     logger = logging.getLogger(name)
166 
167     if distributed_rank is None:
168         import ignite.distributed as idist
169 
170         distributed_rank = idist.get_rank()
171 
172     # Remove previous handlers
173     if distributed_rank > 0 or reset:
174 
175         if logger.hasHandlers():
176             for h in list(logger.handlers):
177                 logger.removeHandler(h)
178 
179     if distributed_rank > 0:
180 
181         # Add null handler to avoid multiple parallel messages
182         logger.addHandler(logging.NullHandler())
183 
184     # Keep the existing configuration if not reset
185     if existing and not reset:
186         return logger
187 
188     if distributed_rank == 0:
189         logger.setLevel(level)
190 
191         formatter = logging.Formatter(format)
192 
193         ch = logging.StreamHandler(stream=stream)
194         ch.setLevel(level)
195         ch.setFormatter(formatter)
196         logger.addHandler(ch)
197 
198         if filepath is not None:
199             fh = logging.FileHandler(filepath)
200             fh.setLevel(level)
201             fh.setFormatter(formatter)
202             logger.addHandler(fh)
203 
204     # don't propagate to ancestors
205     # the problem here is to attach handlers to loggers
206     # should we provide a default configuration less open ?
207     if name is not None:
208         logger.propagate = False
209 
210     return logger
211 
212 
213 def manual_seed(seed: int) -> None:
214     """Setup random state from a seed for `torch`, `random` and optionally `numpy` (if can be imported).
215 
216     Args:
217         seed: Random state seed
218 
219     .. versionchanged:: 0.4.3
220         Added ``torch.cuda.manual_seed_all(seed)``.
221 
222     .. versionchanged:: 0.4.5
223         Added ``torch_xla.core.xla_model.set_rng_state(seed)``.
224     """
225     random.seed(seed)
226     torch.manual_seed(seed)
227 
228     if torch.cuda.is_available():
229         torch.cuda.manual_seed_all(seed)
230 
231     try:
232         import torch_xla.core.xla_model as xm
233 
234         xm.set_rng_state(seed)
235     except ImportError:
236         pass
237 
238     try:
239         import numpy as np
240 
241         np.random.seed(seed)
242     except ImportError:
243         pass
244 
245 
246 def deprecated(
247     deprecated_in: str, removed_in: str = "", reasons: Tuple[str, ...] = (), raise_exception: bool = False
248 ) -> Callable:
249 
250     F = TypeVar("F", bound=Callable[..., Any])
251 
252     def decorator(func: F) -> F:
253         func_doc = func.__doc__ if func.__doc__ else ""
254         deprecation_warning = (
255             f"This function has been deprecated since version {deprecated_in}"
256             + (f" and will be removed in version {removed_in}" if removed_in else "")
257             + ".\n Please refer to the documentation for more details."
258         )
259 
260         @functools.wraps(func)
261         def wrapper(*args: Any, **kwargs: Dict[str, Any]) -> Callable:
262             if raise_exception:
263                 raise DeprecationWarning(deprecation_warning)
264             warnings.warn(deprecation_warning, DeprecationWarning, stacklevel=2)
265             return func(*args, **kwargs)
266 
267         appended_doc = f".. deprecated:: {deprecated_in}" + ("\n\n\t" if len(reasons) > 0 else "")
268 
269         for reason in reasons:
270             appended_doc += "\n\t- " + reason
271         wrapper.__doc__ = f"**Deprecated function**.\n\n    {func_doc}{appended_doc}"
272         return cast(F, wrapper)
273 
274     return decorator
275
```
--- 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/ignite/utils.py b/ignite/utils.py
--- a/ignite/utils.py
+++ b/ignite/utils.py
@@ -1,13 +1,24 @@
 import collections.abc as collections
 import functools
+import hashlib
 import logging
 import random
+import shutil
 import warnings
+from pathlib import Path
 from typing import Any, Callable, Dict, Optional, TextIO, Tuple, Type, TypeVar, Union, cast
 
 import torch
 
-__all__ = ["convert_tensor", "apply_to_tensor", "apply_to_type", "to_onehot", "setup_logger", "manual_seed"]
+__all__ = [
+    "convert_tensor",
+    "apply_to_tensor",
+    "apply_to_type",
+    "to_onehot",
+    "setup_logger",
+    "manual_seed",
+    "hash_checkpoint",
+]
 
 
 def convert_tensor(
@@ -272,3 +283,34 @@
         return cast(F, wrapper)
 
     return decorator
+
+
+def hash_checkpoint(checkpoint_path: Union[str, Path], output_dir: Union[str, Path],) -> Tuple[Path, str]:
+    """
+    Hash the checkpoint file in the format of ``<filename>-<hash>.<ext>``
+    to be used with ``check_hash`` of :func:`torch.hub.load_state_dict_from_url`.
+
+    Args:
+        checkpoint_path: Path to the checkpoint file.
+        output_dir: Output directory to store the hashed checkpoint file.
+
+    Returns:
+        Path to the hashed checkpoint file, The 8 digits of SHA256 hash.
+
+    .. versionadded:: 0.5.0
+    """
+
+    if isinstance(checkpoint_path, str):
+        checkpoint_path = Path(checkpoint_path)
+
+    if isinstance(output_dir, str):
+        output_dir = Path(output_dir)
+
+    sha_hash = hashlib.sha256(checkpoint_path.read_bytes()).hexdigest()
+    old_filename = checkpoint_path.stem
+    new_filename = "-".join((old_filename, sha_hash[:8])) + ".pt"
+
+    hash_checkpoint_path = output_dir / new_filename
+    shutil.move(str(checkpoint_path), hash_checkpoint_path)
+
+    return hash_checkpoint_path, sha_hash

{"golden_diff": "diff --git a/ignite/utils.py b/ignite/utils.py\n--- a/ignite/utils.py\n+++ b/ignite/utils.py\n@@ -1,13 +1,24 @@\n import collections.abc as collections\n import functools\n+import hashlib\n import logging\n import random\n+import shutil\n import warnings\n+from pathlib import Path\n from typing import Any, Callable, Dict, Optional, TextIO, Tuple, Type, TypeVar, Union, cast\n \n import torch\n \n-__all__ = [\"convert_tensor\", \"apply_to_tensor\", \"apply_to_type\", \"to_onehot\", \"setup_logger\", \"manual_seed\"]\n+__all__ = [\n+    \"convert_tensor\",\n+    \"apply_to_tensor\",\n+    \"apply_to_type\",\n+    \"to_onehot\",\n+    \"setup_logger\",\n+    \"manual_seed\",\n+    \"hash_checkpoint\",\n+]\n \n \n def convert_tensor(\n@@ -272,3 +283,34 @@\n         return cast(F, wrapper)\n \n     return decorator\n+\n+\n+def hash_checkpoint(checkpoint_path: Union[str, Path], output_dir: Union[str, Path],) -> Tuple[Path, str]:\n+    \"\"\"\n+    Hash the checkpoint file in the format of ``<filename>-<hash>.<ext>``\n+    to be used with ``check_hash`` of :func:`torch.hub.load_state_dict_from_url`.\n+\n+    Args:\n+        checkpoint_path: Path to the checkpoint file.\n+        output_dir: Output directory to store the hashed checkpoint file.\n+\n+    Returns:\n+        Path to the hashed checkpoint file, The 8 digits of SHA256 hash.\n+\n+    .. versionadded:: 0.5.0\n+    \"\"\"\n+\n+    if isinstance(checkpoint_path, str):\n+        checkpoint_path = Path(checkpoint_path)\n+\n+    if isinstance(output_dir, str):\n+        output_dir = Path(output_dir)\n+\n+    sha_hash = hashlib.sha256(checkpoint_path.read_bytes()).hexdigest()\n+    old_filename = checkpoint_path.stem\n+    new_filename = \"-\".join((old_filename, sha_hash[:8])) + \".pt\"\n+\n+    hash_checkpoint_path = output_dir / new_filename\n+    shutil.move(str(checkpoint_path), hash_checkpoint_path)\n+\n+    return hash_checkpoint_path, sha_hash\n", "issue": "A utility for hashing a checkpoint file\n### \ud83d\ude80 Feature\r\n\r\nBy default Ignite save a checkpoint with the following structure `{filename_prefix}_{name}_{suffix}.{ext}` which is great.\r\nAt first, I would like to add an argument for hashing a checkpoint in `Checkpoint` class. But that could occur a read + write overhead if we turn on hashing which may not be used very often during development.\r\n\r\nSo instead, I would like to propose to add a utility in `ignite.util` for hashing a saved checkpoint file so that we could use `torch.hub.load_state_dict_from_url` with `check_hash=True`.\r\n\r\nImplementation (stripped down and untested version):\r\n\r\n```py\r\ndef hash_checkpoint(checkpoint):\r\n  with open(checkpoint, 'rb') as f:\r\n    hash = hashlib.sha256(f.read()).hexdigest()\r\n\r\n  checkpoint_prefix = checkpoint.strip('.pt')\r\n  filname = '-'.join([checkpoint_prefix, hash[:8]]) + '.pt'\r\n  shutil.move(checkpoint, filename)\r\n  return filename\r\n```\r\n\r\nImplementation in Code-Generator:\r\n\r\nhttps://github.com/pytorch-ignite/code-generator/blob/a2ed5f771e7cf8a57c6f68b5a3797792f4676433/templates/single/utils.py#L134\n", "before_files": [{"content": "import collections.abc as collections\nimport functools\nimport logging\nimport random\nimport warnings\nfrom typing import Any, Callable, Dict, Optional, TextIO, Tuple, Type, TypeVar, Union, cast\n\nimport torch\n\n__all__ = [\"convert_tensor\", \"apply_to_tensor\", \"apply_to_type\", \"to_onehot\", \"setup_logger\", \"manual_seed\"]\n\n\ndef convert_tensor(\n    x: Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes],\n    device: Optional[Union[str, torch.device]] = None,\n    non_blocking: bool = False,\n) -> Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes]:\n    \"\"\"Move tensors to relevant device.\n\n    Args:\n        x: input tensor or mapping, or sequence of tensors.\n        device: device type to move ``x``.\n        non_blocking: convert a CPU Tensor with pinned memory to a CUDA Tensor\n            asynchronously with respect to the host if possible\n    \"\"\"\n\n    def _func(tensor: torch.Tensor) -> torch.Tensor:\n        return tensor.to(device=device, non_blocking=non_blocking) if device is not None else tensor\n\n    return apply_to_tensor(x, _func)\n\n\ndef apply_to_tensor(\n    x: Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes], func: Callable\n) -> Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes]:\n    \"\"\"Apply a function on a tensor or mapping, or sequence of tensors.\n\n    Args:\n        x: input tensor or mapping, or sequence of tensors.\n        func: the function to apply on ``x``.\n    \"\"\"\n    return apply_to_type(x, torch.Tensor, func)\n\n\ndef apply_to_type(\n    x: Union[Any, collections.Sequence, collections.Mapping, str, bytes],\n    input_type: Union[Type, Tuple[Type[Any], Any]],\n    func: Callable,\n) -> Union[Any, collections.Sequence, collections.Mapping, str, bytes]:\n    \"\"\"Apply a function on an object of `input_type` or mapping, or sequence of objects of `input_type`.\n\n    Args:\n        x: object or mapping or sequence.\n        input_type: data type of ``x``.\n        func: the function to apply on ``x``.\n    \"\"\"\n    if isinstance(x, input_type):\n        return func(x)\n    if isinstance(x, (str, bytes)):\n        return x\n    if isinstance(x, collections.Mapping):\n        return cast(Callable, type(x))({k: apply_to_type(sample, input_type, func) for k, sample in x.items()})\n    if isinstance(x, tuple) and hasattr(x, \"_fields\"):  # namedtuple\n        return cast(Callable, type(x))(*(apply_to_type(sample, input_type, func) for sample in x))\n    if isinstance(x, collections.Sequence):\n        return cast(Callable, type(x))([apply_to_type(sample, input_type, func) for sample in x])\n    raise TypeError((f\"x must contain {input_type}, dicts or lists; found {type(x)}\"))\n\n\ndef to_onehot(indices: torch.Tensor, num_classes: int) -> torch.Tensor:\n    \"\"\"Convert a tensor of indices of any shape `(N, ...)` to a\n    tensor of one-hot indicators of shape `(N, num_classes, ...)` and of type uint8. Output's device is equal to the\n    input's device`.\n\n    Args:\n        indices: input tensor to convert.\n        num_classes: number of classes for one-hot tensor.\n\n    .. versionchanged:: 0.4.3\n        This functions is now torchscriptable.\n    \"\"\"\n    new_shape = (indices.shape[0], num_classes) + indices.shape[1:]\n    onehot = torch.zeros(new_shape, dtype=torch.uint8, device=indices.device)\n    return onehot.scatter_(1, indices.unsqueeze(1), 1)\n\n\ndef setup_logger(\n    name: Optional[str] = \"ignite\",\n    level: int = logging.INFO,\n    stream: Optional[TextIO] = None,\n    format: str = \"%(asctime)s %(name)s %(levelname)s: %(message)s\",\n    filepath: Optional[str] = None,\n    distributed_rank: Optional[int] = None,\n    reset: bool = False,\n) -> logging.Logger:\n    \"\"\"Setups logger: name, level, format etc.\n\n    Args:\n        name: new name for the logger. If None, the standard logger is used.\n        level: logging level, e.g. CRITICAL, ERROR, WARNING, INFO, DEBUG.\n        stream: logging stream. If None, the standard stream is used (sys.stderr).\n        format: logging format. By default, `%(asctime)s %(name)s %(levelname)s: %(message)s`.\n        filepath: Optional logging file path. If not None, logs are written to the file.\n        distributed_rank: Optional, rank in distributed configuration to avoid logger setup for workers.\n            If None, distributed_rank is initialized to the rank of process.\n        reset: if True, reset an existing logger rather than keep format, handlers, and level.\n\n    Returns:\n        logging.Logger\n\n    Examples:\n        Improve logs readability when training with a trainer and evaluator:\n\n        .. code-block:: python\n\n            from ignite.utils import setup_logger\n\n            trainer = ...\n            evaluator = ...\n\n            trainer.logger = setup_logger(\"trainer\")\n            evaluator.logger = setup_logger(\"evaluator\")\n\n            trainer.run(data, max_epochs=10)\n\n            # Logs will look like\n            # 2020-01-21 12:46:07,356 trainer INFO: Engine run starting with max_epochs=5.\n            # 2020-01-21 12:46:07,358 trainer INFO: Epoch[1] Complete. Time taken: 00:5:23\n            # 2020-01-21 12:46:07,358 evaluator INFO: Engine run starting with max_epochs=1.\n            # 2020-01-21 12:46:07,358 evaluator INFO: Epoch[1] Complete. Time taken: 00:01:02\n            # ...\n\n        Every existing logger can be reset if needed\n\n        .. code-block:: python\n\n            logger = setup_logger(name=\"my-logger\", format=\"=== %(name)s %(message)s\")\n            logger.info(\"first message\")\n            setup_logger(name=\"my-logger\", format=\"+++ %(name)s %(message)s\", reset=True)\n            logger.info(\"second message\")\n\n            # Logs will look like\n            # === my-logger first message\n            # +++ my-logger second message\n\n        Change the level of an existing internal logger\n\n        .. code-block:: python\n\n            setup_logger(\n                name=\"ignite.distributed.launcher.Parallel\",\n                level=logging.WARNING\n            )\n\n    .. versionchanged:: 0.4.3\n        Added ``stream`` parameter.\n\n    .. versionchanged:: 0.4.5\n        Added ``reset`` parameter.\n    \"\"\"\n    # check if the logger already exists\n    existing = name is None or name in logging.root.manager.loggerDict\n\n    # if existing, get the logger otherwise create a new one\n    logger = logging.getLogger(name)\n\n    if distributed_rank is None:\n        import ignite.distributed as idist\n\n        distributed_rank = idist.get_rank()\n\n    # Remove previous handlers\n    if distributed_rank > 0 or reset:\n\n        if logger.hasHandlers():\n            for h in list(logger.handlers):\n                logger.removeHandler(h)\n\n    if distributed_rank > 0:\n\n        # Add null handler to avoid multiple parallel messages\n        logger.addHandler(logging.NullHandler())\n\n    # Keep the existing configuration if not reset\n    if existing and not reset:\n        return logger\n\n    if distributed_rank == 0:\n        logger.setLevel(level)\n\n        formatter = logging.Formatter(format)\n\n        ch = logging.StreamHandler(stream=stream)\n        ch.setLevel(level)\n        ch.setFormatter(formatter)\n        logger.addHandler(ch)\n\n        if filepath is not None:\n            fh = logging.FileHandler(filepath)\n            fh.setLevel(level)\n            fh.setFormatter(formatter)\n            logger.addHandler(fh)\n\n    # don't propagate to ancestors\n    # the problem here is to attach handlers to loggers\n    # should we provide a default configuration less open ?\n    if name is not None:\n        logger.propagate = False\n\n    return logger\n\n\ndef manual_seed(seed: int) -> None:\n    \"\"\"Setup random state from a seed for `torch`, `random` and optionally `numpy` (if can be imported).\n\n    Args:\n        seed: Random state seed\n\n    .. versionchanged:: 0.4.3\n        Added ``torch.cuda.manual_seed_all(seed)``.\n\n    .. versionchanged:: 0.4.5\n        Added ``torch_xla.core.xla_model.set_rng_state(seed)``.\n    \"\"\"\n    random.seed(seed)\n    torch.manual_seed(seed)\n\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed_all(seed)\n\n    try:\n        import torch_xla.core.xla_model as xm\n\n        xm.set_rng_state(seed)\n    except ImportError:\n        pass\n\n    try:\n        import numpy as np\n\n        np.random.seed(seed)\n    except ImportError:\n        pass\n\n\ndef deprecated(\n    deprecated_in: str, removed_in: str = \"\", reasons: Tuple[str, ...] = (), raise_exception: bool = False\n) -> Callable:\n\n    F = TypeVar(\"F\", bound=Callable[..., Any])\n\n    def decorator(func: F) -> F:\n        func_doc = func.__doc__ if func.__doc__ else \"\"\n        deprecation_warning = (\n            f\"This function has been deprecated since version {deprecated_in}\"\n            + (f\" and will be removed in version {removed_in}\" if removed_in else \"\")\n            + \".\\n Please refer to the documentation for more details.\"\n        )\n\n        @functools.wraps(func)\n        def wrapper(*args: Any, **kwargs: Dict[str, Any]) -> Callable:\n            if raise_exception:\n                raise DeprecationWarning(deprecation_warning)\n            warnings.warn(deprecation_warning, DeprecationWarning, stacklevel=2)\n            return func(*args, **kwargs)\n\n        appended_doc = f\".. deprecated:: {deprecated_in}\" + (\"\\n\\n\\t\" if len(reasons) > 0 else \"\")\n\n        for reason in reasons:\n            appended_doc += \"\\n\\t- \" + reason\n        wrapper.__doc__ = f\"**Deprecated function**.\\n\\n    {func_doc}{appended_doc}\"\n        return cast(F, wrapper)\n\n    return decorator\n", "path": "ignite/utils.py"}], "after_files": [{"content": "import collections.abc as collections\nimport functools\nimport hashlib\nimport logging\nimport random\nimport shutil\nimport warnings\nfrom pathlib import Path\nfrom typing import Any, Callable, Dict, Optional, TextIO, Tuple, Type, TypeVar, Union, cast\n\nimport torch\n\n__all__ = [\n    \"convert_tensor\",\n    \"apply_to_tensor\",\n    \"apply_to_type\",\n    \"to_onehot\",\n    \"setup_logger\",\n    \"manual_seed\",\n    \"hash_checkpoint\",\n]\n\n\ndef convert_tensor(\n    x: Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes],\n    device: Optional[Union[str, torch.device]] = None,\n    non_blocking: bool = False,\n) -> Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes]:\n    \"\"\"Move tensors to relevant device.\n\n    Args:\n        x: input tensor or mapping, or sequence of tensors.\n        device: device type to move ``x``.\n        non_blocking: convert a CPU Tensor with pinned memory to a CUDA Tensor\n            asynchronously with respect to the host if possible\n    \"\"\"\n\n    def _func(tensor: torch.Tensor) -> torch.Tensor:\n        return tensor.to(device=device, non_blocking=non_blocking) if device is not None else tensor\n\n    return apply_to_tensor(x, _func)\n\n\ndef apply_to_tensor(\n    x: Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes], func: Callable\n) -> Union[torch.Tensor, collections.Sequence, collections.Mapping, str, bytes]:\n    \"\"\"Apply a function on a tensor or mapping, or sequence of tensors.\n\n    Args:\n        x: input tensor or mapping, or sequence of tensors.\n        func: the function to apply on ``x``.\n    \"\"\"\n    return apply_to_type(x, torch.Tensor, func)\n\n\ndef apply_to_type(\n    x: Union[Any, collections.Sequence, collections.Mapping, str, bytes],\n    input_type: Union[Type, Tuple[Type[Any], Any]],\n    func: Callable,\n) -> Union[Any, collections.Sequence, collections.Mapping, str, bytes]:\n    \"\"\"Apply a function on an object of `input_type` or mapping, or sequence of objects of `input_type`.\n\n    Args:\n        x: object or mapping or sequence.\n        input_type: data type of ``x``.\n        func: the function to apply on ``x``.\n    \"\"\"\n    if isinstance(x, input_type):\n        return func(x)\n    if isinstance(x, (str, bytes)):\n        return x\n    if isinstance(x, collections.Mapping):\n        return cast(Callable, type(x))({k: apply_to_type(sample, input_type, func) for k, sample in x.items()})\n    if isinstance(x, tuple) and hasattr(x, \"_fields\"):  # namedtuple\n        return cast(Callable, type(x))(*(apply_to_type(sample, input_type, func) for sample in x))\n    if isinstance(x, collections.Sequence):\n        return cast(Callable, type(x))([apply_to_type(sample, input_type, func) for sample in x])\n    raise TypeError((f\"x must contain {input_type}, dicts or lists; found {type(x)}\"))\n\n\ndef to_onehot(indices: torch.Tensor, num_classes: int) -> torch.Tensor:\n    \"\"\"Convert a tensor of indices of any shape `(N, ...)` to a\n    tensor of one-hot indicators of shape `(N, num_classes, ...)` and of type uint8. Output's device is equal to the\n    input's device`.\n\n    Args:\n        indices: input tensor to convert.\n        num_classes: number of classes for one-hot tensor.\n\n    .. versionchanged:: 0.4.3\n        This functions is now torchscriptable.\n    \"\"\"\n    new_shape = (indices.shape[0], num_classes) + indices.shape[1:]\n    onehot = torch.zeros(new_shape, dtype=torch.uint8, device=indices.device)\n    return onehot.scatter_(1, indices.unsqueeze(1), 1)\n\n\ndef setup_logger(\n    name: Optional[str] = \"ignite\",\n    level: int = logging.INFO,\n    stream: Optional[TextIO] = None,\n    format: str = \"%(asctime)s %(name)s %(levelname)s: %(message)s\",\n    filepath: Optional[str] = None,\n    distributed_rank: Optional[int] = None,\n    reset: bool = False,\n) -> logging.Logger:\n    \"\"\"Setups logger: name, level, format etc.\n\n    Args:\n        name: new name for the logger. If None, the standard logger is used.\n        level: logging level, e.g. CRITICAL, ERROR, WARNING, INFO, DEBUG.\n        stream: logging stream. If None, the standard stream is used (sys.stderr).\n        format: logging format. By default, `%(asctime)s %(name)s %(levelname)s: %(message)s`.\n        filepath: Optional logging file path. If not None, logs are written to the file.\n        distributed_rank: Optional, rank in distributed configuration to avoid logger setup for workers.\n            If None, distributed_rank is initialized to the rank of process.\n        reset: if True, reset an existing logger rather than keep format, handlers, and level.\n\n    Returns:\n        logging.Logger\n\n    Examples:\n        Improve logs readability when training with a trainer and evaluator:\n\n        .. code-block:: python\n\n            from ignite.utils import setup_logger\n\n            trainer = ...\n            evaluator = ...\n\n            trainer.logger = setup_logger(\"trainer\")\n            evaluator.logger = setup_logger(\"evaluator\")\n\n            trainer.run(data, max_epochs=10)\n\n            # Logs will look like\n            # 2020-01-21 12:46:07,356 trainer INFO: Engine run starting with max_epochs=5.\n            # 2020-01-21 12:46:07,358 trainer INFO: Epoch[1] Complete. Time taken: 00:5:23\n            # 2020-01-21 12:46:07,358 evaluator INFO: Engine run starting with max_epochs=1.\n            # 2020-01-21 12:46:07,358 evaluator INFO: Epoch[1] Complete. Time taken: 00:01:02\n            # ...\n\n        Every existing logger can be reset if needed\n\n        .. code-block:: python\n\n            logger = setup_logger(name=\"my-logger\", format=\"=== %(name)s %(message)s\")\n            logger.info(\"first message\")\n            setup_logger(name=\"my-logger\", format=\"+++ %(name)s %(message)s\", reset=True)\n            logger.info(\"second message\")\n\n            # Logs will look like\n            # === my-logger first message\n            # +++ my-logger second message\n\n        Change the level of an existing internal logger\n\n        .. code-block:: python\n\n            setup_logger(\n                name=\"ignite.distributed.launcher.Parallel\",\n                level=logging.WARNING\n            )\n\n    .. versionchanged:: 0.4.3\n        Added ``stream`` parameter.\n\n    .. versionchanged:: 0.4.5\n        Added ``reset`` parameter.\n    \"\"\"\n    # check if the logger already exists\n    existing = name is None or name in logging.root.manager.loggerDict\n\n    # if existing, get the logger otherwise create a new one\n    logger = logging.getLogger(name)\n\n    if distributed_rank is None:\n        import ignite.distributed as idist\n\n        distributed_rank = idist.get_rank()\n\n    # Remove previous handlers\n    if distributed_rank > 0 or reset:\n\n        if logger.hasHandlers():\n            for h in list(logger.handlers):\n                logger.removeHandler(h)\n\n    if distributed_rank > 0:\n\n        # Add null handler to avoid multiple parallel messages\n        logger.addHandler(logging.NullHandler())\n\n    # Keep the existing configuration if not reset\n    if existing and not reset:\n        return logger\n\n    if distributed_rank == 0:\n        logger.setLevel(level)\n\n        formatter = logging.Formatter(format)\n\n        ch = logging.StreamHandler(stream=stream)\n        ch.setLevel(level)\n        ch.setFormatter(formatter)\n        logger.addHandler(ch)\n\n        if filepath is not None:\n            fh = logging.FileHandler(filepath)\n            fh.setLevel(level)\n            fh.setFormatter(formatter)\n            logger.addHandler(fh)\n\n    # don't propagate to ancestors\n    # the problem here is to attach handlers to loggers\n    # should we provide a default configuration less open ?\n    if name is not None:\n        logger.propagate = False\n\n    return logger\n\n\ndef manual_seed(seed: int) -> None:\n    \"\"\"Setup random state from a seed for `torch`, `random` and optionally `numpy` (if can be imported).\n\n    Args:\n        seed: Random state seed\n\n    .. versionchanged:: 0.4.3\n        Added ``torch.cuda.manual_seed_all(seed)``.\n\n    .. versionchanged:: 0.4.5\n        Added ``torch_xla.core.xla_model.set_rng_state(seed)``.\n    \"\"\"\n    random.seed(seed)\n    torch.manual_seed(seed)\n\n    if torch.cuda.is_available():\n        torch.cuda.manual_seed_all(seed)\n\n    try:\n        import torch_xla.core.xla_model as xm\n\n        xm.set_rng_state(seed)\n    except ImportError:\n        pass\n\n    try:\n        import numpy as np\n\n        np.random.seed(seed)\n    except ImportError:\n        pass\n\n\ndef deprecated(\n    deprecated_in: str, removed_in: str = \"\", reasons: Tuple[str, ...] = (), raise_exception: bool = False\n) -> Callable:\n\n    F = TypeVar(\"F\", bound=Callable[..., Any])\n\n    def decorator(func: F) -> F:\n        func_doc = func.__doc__ if func.__doc__ else \"\"\n        deprecation_warning = (\n            f\"This function has been deprecated since version {deprecated_in}\"\n            + (f\" and will be removed in version {removed_in}\" if removed_in else \"\")\n            + \".\\n Please refer to the documentation for more details.\"\n        )\n\n        @functools.wraps(func)\n        def wrapper(*args: Any, **kwargs: Dict[str, Any]) -> Callable:\n            if raise_exception:\n                raise DeprecationWarning(deprecation_warning)\n            warnings.warn(deprecation_warning, DeprecationWarning, stacklevel=2)\n            return func(*args, **kwargs)\n\n        appended_doc = f\".. deprecated:: {deprecated_in}\" + (\"\\n\\n\\t\" if len(reasons) > 0 else \"\")\n\n        for reason in reasons:\n            appended_doc += \"\\n\\t- \" + reason\n        wrapper.__doc__ = f\"**Deprecated function**.\\n\\n    {func_doc}{appended_doc}\"\n        return cast(F, wrapper)\n\n    return decorator\n\n\ndef hash_checkpoint(checkpoint_path: Union[str, Path], output_dir: Union[str, Path],) -> Tuple[Path, str]:\n    \"\"\"\n    Hash the checkpoint file in the format of ``<filename>-<hash>.<ext>``\n    to be used with ``check_hash`` of :func:`torch.hub.load_state_dict_from_url`.\n\n    Args:\n        checkpoint_path: Path to the checkpoint file.\n        output_dir: Output directory to store the hashed checkpoint file.\n\n    Returns:\n        Path to the hashed checkpoint file, The 8 digits of SHA256 hash.\n\n    .. versionadded:: 0.5.0\n    \"\"\"\n\n    if isinstance(checkpoint_path, str):\n        checkpoint_path = Path(checkpoint_path)\n\n    if isinstance(output_dir, str):\n        output_dir = Path(output_dir)\n\n    sha_hash = hashlib.sha256(checkpoint_path.read_bytes()).hexdigest()\n    old_filename = checkpoint_path.stem\n    new_filename = \"-\".join((old_filename, sha_hash[:8])) + \".pt\"\n\n    hash_checkpoint_path = output_dir / new_filename\n    shutil.move(str(checkpoint_path), hash_checkpoint_path)\n\n    return hash_checkpoint_path, sha_hash\n", "path": "ignite/utils.py"}]}