We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[Bug] metric should be one of \\\'bbox\\\' when using tools/test.py
### Prerequisite

- [X] I have searched [Issues](https://github.com/open-mmlab/mmdetection/issues) and [Discussions](https://github.com/open-mmlab/mmdetection/discussions) but cannot get the expected help.
- [X] I have read the [FAQ documentation](https://mmdetection.readthedocs.io/en/latest/faq.html) but cannot get the expected help.
- [X] The bug has not been fixed in the [latest version (master)](https://github.com/open-mmlab/mmdetection) or [latest version (3.x)](https://github.com/open-mmlab/mmdetection/tree/dev-3.x).

### Task

I have modified the scripts/configs, or I'm working on my own tasks/models/datasets.

### Branch

3.x branch https://github.com/open-mmlab/mmdetection/tree/3.x

### Environment

OrderedDict([('sys.platform', 'linux'),
             ('Python',
              '3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 06:08:21) [GCC 9.4.0]'),
             ('CUDA available', True),
             ('numpy_random_seed', 2147483648),
             ('GPU 0', 'NVIDIA GeForce RTX 3080'),
             ('CUDA_HOME', '/usr/local/cuda-11.5'),
             ('NVCC', 'Cuda compilation tools, release 11.5, V11.5.50'),
             ('GCC', 'gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0'),
             ('PyTorch', '1.12.1+cu113'),
             ('PyTorch compiling details',
              'PyTorch built with:\n  - GCC 9.3\n  - C++ Version: 201402\n  - Intel(R) Math Kernel Library Version 2020.0.0 Product Build 20191122 for Intel(R) 64 architecture applications\n  - Intel(R) MKL-DNN v2.6.0 (Git Hash 52b5f107dd9cf10910aaa19cb47f3abf9b349815)\n  - OpenMP 201511 (a.k.a. OpenMP 4.5)\n  - LAPACK is enabled (usually provided by MKL)\n  - NNPACK is enabled\n  - CPU capability usage: AVX2\n  - CUDA Runtime 11.3\n  - NVCC architecture flags: -gencode;arch=compute_37,code=sm_37;-gencode;arch=compute_50,code=sm_50;-gencode;arch=compute_60,code=sm_60;-gencode;arch=compute_70,code=sm_70;-gencode;arch=compute_75,code=sm_75;-gencode;arch=compute_80,code=sm_80;-gencode;arch=compute_86,code=sm_86\n  - CuDNN 8.3.2  (built against CUDA 11.5)\n  - Magma 2.5.2\n  - Build settings: BLAS_INFO=mkl, BUILD_TYPE=Release, CUDA_VERSION=11.3, CUDNN_VERSION=8.3.2, CXX_COMPILER=/opt/rh/devtoolset-9/root/usr/bin/c++, CXX_FLAGS= -fabi-version=11 -Wno-deprecated -fvisibility-inlines-hidden -DUSE_PTHREADPOOL -fopenmp -DNDEBUG -DUSE_KINETO -DUSE_FBGEMM -DUSE_QNNPACK -DUSE_PYTORCH_QNNPACK -DUSE_XNNPACK -DSYMBOLICATE_MOBILE_DEBUG_HANDLE -DEDGE_PROFILER_USE_KINETO -O2 -fPIC -Wno-narrowing -Wall -Wextra -Werror=return-type -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-function -Wno-unused-result -Wno-unused-local-typedefs -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-stringop-overflow -Wno-psabi -Wno-error=pedantic -Wno-error=redundant-decls -Wno-error=old-style-cast -fdiagnostics-color=always -faligned-new -Wno-unused-but-set-variable -Wno-maybe-uninitialized -fno-math-errno -fno-trapping-math -Werror=format -Werror=cast-function-type -Wno-stringop-overflow, LAPACK_INFO=mkl, PERF_WITH_AVX=1, PERF_WITH_AVX2=1, PERF_WITH_AVX512=1, TORCH_VERSION=1.12.1, USE_CUDA=ON, USE_CUDNN=ON, USE_EXCEPTION_PTR=1, USE_GFLAGS=OFF, USE_GLOG=OFF, USE_MKL=ON, USE_MKLDNN=OFF, USE_MPI=OFF, USE_NCCL=ON, USE_NNPACK=ON, USE_OPENMP=ON, USE_ROCM=OFF, \n'),
             ('TorchVision', '0.13.1+cu113'),
             ('OpenCV', '4.6.0'),
             ('MMEngine', '0.2.0'),
             ('MMDetection', '3.0.0rc2+5897b32')])

### Reproduces the problem - code sample

Here is my config:
```python
test_evaluator = dict(
    type='CocoMetric',
    ann_file='./ballondatasets/balloon/val/annotation_coco.json',
    metric=['bbox', 'segm'],
    format_only=False)
```

if i use `python config checkpoint --out result.pkl`, it will be modified to 
```
```python
test_evaluator = dict(
    type='CocoMetric',
    ann_file='./ballondatasets/balloon/val/annotation_coco.json',
    metric=[None, {
        'type': 'DumpResults',
        'out_file_path': 'ceshi.pkl'
    }],
    format_only=False)
```


### Reproduces the problem - error message

```
  File "/home/sanbu/anaconda3/envs/mmlab2/lib/python3.7/site-packages/mmengine/runner/runner.py", line 1533, in build_test_loop
    evaluator=self._test_evaluator))
  File "/home/sanbu/anaconda3/envs/mmlab2/lib/python3.7/site-packages/mmengine/registry/registry.py", line 421, in build
    return self.build_func(cfg, *args, **kwargs, registry=self)
  File "/home/sanbu/anaconda3/envs/mmlab2/lib/python3.7/site-packages/mmengine/registry/build_functions.py", line 136, in build_from_cfg
    f'class `{obj_cls.__name__}` in '  # type: ignore
KeyError: 'class `TestLoop` in mmengine/runner/loops.py: \'class `CocoMetric` in mmdet/evaluation/metrics/coco_metric.py: "metric should be one of \\\'bbox\\\', \\\'segm\\\', \\\'proposal\\\', \\\'proposal_fast\\\', but got {\\\'type\\\': \\\'DumpResults\\\', \\\'out_file_path\\\': \\\'ceshi.pkl\\\'}."\''

```
### Additional information

I use the tools/test.py to output pkl file but i got the problem,the python file will modify my conifg.

I see the mmdet documentation says that we can use --eval bbox or segm to specify the metric parameter. But the tools/test.py doesn't has the `--eval` option.I don't know if 3.x have implemented the function.

--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `mmdet/utils/__init__.py`
Content:
```
1 # Copyright (c) OpenMMLab. All rights reserved.
2 from .collect_env import collect_env
3 from .compat_config import compat_cfg
4 from .dist_utils import (all_reduce_dict, allreduce_grads, reduce_mean,
5                          sync_random_seed)
6 from .logger import get_caller_name, log_img_scale
7 from .memory import AvoidCUDAOOM, AvoidOOM
8 from .misc import add_dump_metric, find_latest_checkpoint, update_data_root
9 from .replace_cfg_vals import replace_cfg_vals
10 from .setup_env import register_all_modules, setup_multi_processes
11 from .split_batch import split_batch
12 from .typing import (ConfigType, InstanceList, MultiConfig, OptConfigType,
13                      OptInstanceList, OptMultiConfig, OptPixelList, PixelList,
14                      RangeType)
15 
16 __all__ = [
17     'collect_env', 'find_latest_checkpoint', 'update_data_root',
18     'setup_multi_processes', 'get_caller_name', 'log_img_scale', 'compat_cfg',
19     'split_batch', 'register_all_modules', 'replace_cfg_vals', 'AvoidOOM',
20     'AvoidCUDAOOM', 'all_reduce_dict', 'allreduce_grads', 'reduce_mean',
21     'sync_random_seed', 'ConfigType', 'InstanceList', 'MultiConfig',
22     'OptConfigType', 'OptInstanceList', 'OptMultiConfig', 'OptPixelList',
23     'PixelList', 'RangeType', 'add_dump_metric'
24 ]
25
```

Path: `mmdet/utils/misc.py`
Content:
```
1 # Copyright (c) OpenMMLab. All rights reserved.
2 import glob
3 import os
4 import os.path as osp
5 import warnings
6 
7 from mmengine.config import Config, ConfigDict
8 from mmengine.logging import print_log
9 
10 
11 def find_latest_checkpoint(path, suffix='pth'):
12     """Find the latest checkpoint from the working directory.
13 
14     Args:
15         path(str): The path to find checkpoints.
16         suffix(str): File extension.
17             Defaults to pth.
18 
19     Returns:
20         latest_path(str | None): File path of the latest checkpoint.
21     References:
22         .. [1] https://github.com/microsoft/SoftTeacher
23                   /blob/main/ssod/utils/patch.py
24     """
25     if not osp.exists(path):
26         warnings.warn('The path of checkpoints does not exist.')
27         return None
28     if osp.exists(osp.join(path, f'latest.{suffix}')):
29         return osp.join(path, f'latest.{suffix}')
30 
31     checkpoints = glob.glob(osp.join(path, f'*.{suffix}'))
32     if len(checkpoints) == 0:
33         warnings.warn('There are no checkpoints in the path.')
34         return None
35     latest = -1
36     latest_path = None
37     for checkpoint in checkpoints:
38         count = int(osp.basename(checkpoint).split('_')[-1].split('.')[0])
39         if count > latest:
40             latest = count
41             latest_path = checkpoint
42     return latest_path
43 
44 
45 def update_data_root(cfg, logger=None):
46     """Update data root according to env MMDET_DATASETS.
47 
48     If set env MMDET_DATASETS, update cfg.data_root according to
49     MMDET_DATASETS. Otherwise, using cfg.data_root as default.
50 
51     Args:
52         cfg (:obj:`Config`): The model config need to modify
53         logger (logging.Logger | str | None): the way to print msg
54     """
55     assert isinstance(cfg, Config), \
56         f'cfg got wrong type: {type(cfg)}, expected mmengine.Config'
57 
58     if 'MMDET_DATASETS' in os.environ:
59         dst_root = os.environ['MMDET_DATASETS']
60         print_log(f'MMDET_DATASETS has been set to be {dst_root}.'
61                   f'Using {dst_root} as data root.')
62     else:
63         return
64 
65     assert isinstance(cfg, Config), \
66         f'cfg got wrong type: {type(cfg)}, expected mmengine.Config'
67 
68     def update(cfg, src_str, dst_str):
69         for k, v in cfg.items():
70             if isinstance(v, ConfigDict):
71                 update(cfg[k], src_str, dst_str)
72             if isinstance(v, str) and src_str in v:
73                 cfg[k] = v.replace(src_str, dst_str)
74 
75     update(cfg.data, cfg.data_root, dst_root)
76     cfg.data_root = dst_root
77 
78 
79 def add_dump_metric(args, cfg):
80     dump_metric = dict(type='DumpResults', out_file_path=args.out)
81     if isinstance(cfg.test_evaluator, (list, tuple)):
82         cfg.test_evaluator = list(cfg.test_evaluator).append(dump_metric)
83     elif isinstance(cfg.test_evaluator, dict):
84         if isinstance(cfg.test_evaluator.metric, str):
85             cfg.test_evaluator = [cfg.test_evaluator, dump_metric]
86         elif isinstance(cfg.test_evaluator.metric, (list, tuple)):
87             cfg.test_evaluator.metric = list(
88                 cfg.test_evaluator.metric).append(dump_metric)
89         else:
90             cfg.test_evaluator.metric = [
91                 cfg.test_evaluator.metric, dump_metric
92             ]
93
```
--- 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/mmdet/utils/__init__.py b/mmdet/utils/__init__.py
--- a/mmdet/utils/__init__.py
+++ b/mmdet/utils/__init__.py
@@ -5,7 +5,7 @@
                          sync_random_seed)
 from .logger import get_caller_name, log_img_scale
 from .memory import AvoidCUDAOOM, AvoidOOM
-from .misc import add_dump_metric, find_latest_checkpoint, update_data_root
+from .misc import find_latest_checkpoint, update_data_root
 from .replace_cfg_vals import replace_cfg_vals
 from .setup_env import register_all_modules, setup_multi_processes
 from .split_batch import split_batch
@@ -20,5 +20,5 @@
     'AvoidCUDAOOM', 'all_reduce_dict', 'allreduce_grads', 'reduce_mean',
     'sync_random_seed', 'ConfigType', 'InstanceList', 'MultiConfig',
     'OptConfigType', 'OptInstanceList', 'OptMultiConfig', 'OptPixelList',
-    'PixelList', 'RangeType', 'add_dump_metric'
+    'PixelList', 'RangeType'
 ]
diff --git a/mmdet/utils/misc.py b/mmdet/utils/misc.py
--- a/mmdet/utils/misc.py
+++ b/mmdet/utils/misc.py
@@ -74,19 +74,3 @@
 
     update(cfg.data, cfg.data_root, dst_root)
     cfg.data_root = dst_root
-
-
-def add_dump_metric(args, cfg):
-    dump_metric = dict(type='DumpResults', out_file_path=args.out)
-    if isinstance(cfg.test_evaluator, (list, tuple)):
-        cfg.test_evaluator = list(cfg.test_evaluator).append(dump_metric)
-    elif isinstance(cfg.test_evaluator, dict):
-        if isinstance(cfg.test_evaluator.metric, str):
-            cfg.test_evaluator = [cfg.test_evaluator, dump_metric]
-        elif isinstance(cfg.test_evaluator.metric, (list, tuple)):
-            cfg.test_evaluator.metric = list(
-                cfg.test_evaluator.metric).append(dump_metric)
-        else:
-            cfg.test_evaluator.metric = [
-                cfg.test_evaluator.metric, dump_metric
-            ]

{"golden_diff": "diff --git a/mmdet/utils/__init__.py b/mmdet/utils/__init__.py\n--- a/mmdet/utils/__init__.py\n+++ b/mmdet/utils/__init__.py\n@@ -5,7 +5,7 @@\n                          sync_random_seed)\n from .logger import get_caller_name, log_img_scale\n from .memory import AvoidCUDAOOM, AvoidOOM\n-from .misc import add_dump_metric, find_latest_checkpoint, update_data_root\n+from .misc import find_latest_checkpoint, update_data_root\n from .replace_cfg_vals import replace_cfg_vals\n from .setup_env import register_all_modules, setup_multi_processes\n from .split_batch import split_batch\n@@ -20,5 +20,5 @@\n     'AvoidCUDAOOM', 'all_reduce_dict', 'allreduce_grads', 'reduce_mean',\n     'sync_random_seed', 'ConfigType', 'InstanceList', 'MultiConfig',\n     'OptConfigType', 'OptInstanceList', 'OptMultiConfig', 'OptPixelList',\n-    'PixelList', 'RangeType', 'add_dump_metric'\n+    'PixelList', 'RangeType'\n ]\ndiff --git a/mmdet/utils/misc.py b/mmdet/utils/misc.py\n--- a/mmdet/utils/misc.py\n+++ b/mmdet/utils/misc.py\n@@ -74,19 +74,3 @@\n \n     update(cfg.data, cfg.data_root, dst_root)\n     cfg.data_root = dst_root\n-\n-\n-def add_dump_metric(args, cfg):\n-    dump_metric = dict(type='DumpResults', out_file_path=args.out)\n-    if isinstance(cfg.test_evaluator, (list, tuple)):\n-        cfg.test_evaluator = list(cfg.test_evaluator).append(dump_metric)\n-    elif isinstance(cfg.test_evaluator, dict):\n-        if isinstance(cfg.test_evaluator.metric, str):\n-            cfg.test_evaluator = [cfg.test_evaluator, dump_metric]\n-        elif isinstance(cfg.test_evaluator.metric, (list, tuple)):\n-            cfg.test_evaluator.metric = list(\n-                cfg.test_evaluator.metric).append(dump_metric)\n-        else:\n-            cfg.test_evaluator.metric = [\n-                cfg.test_evaluator.metric, dump_metric\n-            ]\n", "issue": "[Bug] metric should be one of \\\\\\'bbox\\\\\\' when using tools/test.py\n### Prerequisite\r\n\r\n- [X] I have searched [Issues](https://github.com/open-mmlab/mmdetection/issues) and [Discussions](https://github.com/open-mmlab/mmdetection/discussions) but cannot get the expected help.\r\n- [X] I have read the [FAQ documentation](https://mmdetection.readthedocs.io/en/latest/faq.html) but cannot get the expected help.\r\n- [X] The bug has not been fixed in the [latest version (master)](https://github.com/open-mmlab/mmdetection) or [latest version (3.x)](https://github.com/open-mmlab/mmdetection/tree/dev-3.x).\r\n\r\n### Task\r\n\r\nI have modified the scripts/configs, or I'm working on my own tasks/models/datasets.\r\n\r\n### Branch\r\n\r\n3.x branch https://github.com/open-mmlab/mmdetection/tree/3.x\r\n\r\n### Environment\r\n\r\nOrderedDict([('sys.platform', 'linux'),\r\n             ('Python',\r\n              '3.7.12 | packaged by conda-forge | (default, Oct 26 2021, 06:08:21) [GCC 9.4.0]'),\r\n             ('CUDA available', True),\r\n             ('numpy_random_seed', 2147483648),\r\n             ('GPU 0', 'NVIDIA GeForce RTX 3080'),\r\n             ('CUDA_HOME', '/usr/local/cuda-11.5'),\r\n             ('NVCC', 'Cuda compilation tools, release 11.5, V11.5.50'),\r\n             ('GCC', 'gcc (Ubuntu 9.4.0-1ubuntu1~20.04.1) 9.4.0'),\r\n             ('PyTorch', '1.12.1+cu113'),\r\n             ('PyTorch compiling details',\r\n              'PyTorch built with:\\n  - GCC 9.3\\n  - C++ Version: 201402\\n  - Intel(R) Math Kernel Library Version 2020.0.0 Product Build 20191122 for Intel(R) 64 architecture applications\\n  - Intel(R) MKL-DNN v2.6.0 (Git Hash 52b5f107dd9cf10910aaa19cb47f3abf9b349815)\\n  - OpenMP 201511 (a.k.a. OpenMP 4.5)\\n  - LAPACK is enabled (usually provided by MKL)\\n  - NNPACK is enabled\\n  - CPU capability usage: AVX2\\n  - CUDA Runtime 11.3\\n  - NVCC architecture flags: -gencode;arch=compute_37,code=sm_37;-gencode;arch=compute_50,code=sm_50;-gencode;arch=compute_60,code=sm_60;-gencode;arch=compute_70,code=sm_70;-gencode;arch=compute_75,code=sm_75;-gencode;arch=compute_80,code=sm_80;-gencode;arch=compute_86,code=sm_86\\n  - CuDNN 8.3.2  (built against CUDA 11.5)\\n  - Magma 2.5.2\\n  - Build settings: BLAS_INFO=mkl, BUILD_TYPE=Release, CUDA_VERSION=11.3, CUDNN_VERSION=8.3.2, CXX_COMPILER=/opt/rh/devtoolset-9/root/usr/bin/c++, CXX_FLAGS= -fabi-version=11 -Wno-deprecated -fvisibility-inlines-hidden -DUSE_PTHREADPOOL -fopenmp -DNDEBUG -DUSE_KINETO -DUSE_FBGEMM -DUSE_QNNPACK -DUSE_PYTORCH_QNNPACK -DUSE_XNNPACK -DSYMBOLICATE_MOBILE_DEBUG_HANDLE -DEDGE_PROFILER_USE_KINETO -O2 -fPIC -Wno-narrowing -Wall -Wextra -Werror=return-type -Wno-missing-field-initializers -Wno-type-limits -Wno-array-bounds -Wno-unknown-pragmas -Wno-unused-parameter -Wno-unused-function -Wno-unused-result -Wno-unused-local-typedefs -Wno-strict-overflow -Wno-strict-aliasing -Wno-error=deprecated-declarations -Wno-stringop-overflow -Wno-psabi -Wno-error=pedantic -Wno-error=redundant-decls -Wno-error=old-style-cast -fdiagnostics-color=always -faligned-new -Wno-unused-but-set-variable -Wno-maybe-uninitialized -fno-math-errno -fno-trapping-math -Werror=format -Werror=cast-function-type -Wno-stringop-overflow, LAPACK_INFO=mkl, PERF_WITH_AVX=1, PERF_WITH_AVX2=1, PERF_WITH_AVX512=1, TORCH_VERSION=1.12.1, USE_CUDA=ON, USE_CUDNN=ON, USE_EXCEPTION_PTR=1, USE_GFLAGS=OFF, USE_GLOG=OFF, USE_MKL=ON, USE_MKLDNN=OFF, USE_MPI=OFF, USE_NCCL=ON, USE_NNPACK=ON, USE_OPENMP=ON, USE_ROCM=OFF, \\n'),\r\n             ('TorchVision', '0.13.1+cu113'),\r\n             ('OpenCV', '4.6.0'),\r\n             ('MMEngine', '0.2.0'),\r\n             ('MMDetection', '3.0.0rc2+5897b32')])\r\n\r\n### Reproduces the problem - code sample\r\n\r\nHere is my config:\r\n```python\r\ntest_evaluator = dict(\r\n    type='CocoMetric',\r\n    ann_file='./ballondatasets/balloon/val/annotation_coco.json',\r\n    metric=['bbox', 'segm'],\r\n    format_only=False)\r\n```\r\n\r\nif i use `python config checkpoint --out result.pkl`, it will be modified to \r\n```\r\n```python\r\ntest_evaluator = dict(\r\n    type='CocoMetric',\r\n    ann_file='./ballondatasets/balloon/val/annotation_coco.json',\r\n    metric=[None, {\r\n        'type': 'DumpResults',\r\n        'out_file_path': 'ceshi.pkl'\r\n    }],\r\n    format_only=False)\r\n```\r\n\r\n\r\n### Reproduces the problem - error message\r\n\r\n```\r\n  File \"/home/sanbu/anaconda3/envs/mmlab2/lib/python3.7/site-packages/mmengine/runner/runner.py\", line 1533, in build_test_loop\r\n    evaluator=self._test_evaluator))\r\n  File \"/home/sanbu/anaconda3/envs/mmlab2/lib/python3.7/site-packages/mmengine/registry/registry.py\", line 421, in build\r\n    return self.build_func(cfg, *args, **kwargs, registry=self)\r\n  File \"/home/sanbu/anaconda3/envs/mmlab2/lib/python3.7/site-packages/mmengine/registry/build_functions.py\", line 136, in build_from_cfg\r\n    f'class `{obj_cls.__name__}` in '  # type: ignore\r\nKeyError: 'class `TestLoop` in mmengine/runner/loops.py: \\'class `CocoMetric` in mmdet/evaluation/metrics/coco_metric.py: \"metric should be one of \\\\\\'bbox\\\\\\', \\\\\\'segm\\\\\\', \\\\\\'proposal\\\\\\', \\\\\\'proposal_fast\\\\\\', but got {\\\\\\'type\\\\\\': \\\\\\'DumpResults\\\\\\', \\\\\\'out_file_path\\\\\\': \\\\\\'ceshi.pkl\\\\\\'}.\"\\''\r\n\r\n```\r\n### Additional information\r\n\r\nI use the tools/test.py to output pkl file but i got the problem,the python file will modify my conifg.\r\n\r\nI see the mmdet documentation says that we can use --eval bbox or segm to specify the metric parameter. But the tools/test.py doesn't has the `--eval` option.I don't know if 3.x have implemented the function.\n", "before_files": [{"content": "# Copyright (c) OpenMMLab. All rights reserved.\nfrom .collect_env import collect_env\nfrom .compat_config import compat_cfg\nfrom .dist_utils import (all_reduce_dict, allreduce_grads, reduce_mean,\n                         sync_random_seed)\nfrom .logger import get_caller_name, log_img_scale\nfrom .memory import AvoidCUDAOOM, AvoidOOM\nfrom .misc import add_dump_metric, find_latest_checkpoint, update_data_root\nfrom .replace_cfg_vals import replace_cfg_vals\nfrom .setup_env import register_all_modules, setup_multi_processes\nfrom .split_batch import split_batch\nfrom .typing import (ConfigType, InstanceList, MultiConfig, OptConfigType,\n                     OptInstanceList, OptMultiConfig, OptPixelList, PixelList,\n                     RangeType)\n\n__all__ = [\n    'collect_env', 'find_latest_checkpoint', 'update_data_root',\n    'setup_multi_processes', 'get_caller_name', 'log_img_scale', 'compat_cfg',\n    'split_batch', 'register_all_modules', 'replace_cfg_vals', 'AvoidOOM',\n    'AvoidCUDAOOM', 'all_reduce_dict', 'allreduce_grads', 'reduce_mean',\n    'sync_random_seed', 'ConfigType', 'InstanceList', 'MultiConfig',\n    'OptConfigType', 'OptInstanceList', 'OptMultiConfig', 'OptPixelList',\n    'PixelList', 'RangeType', 'add_dump_metric'\n]\n", "path": "mmdet/utils/__init__.py"}, {"content": "# Copyright (c) OpenMMLab. All rights reserved.\nimport glob\nimport os\nimport os.path as osp\nimport warnings\n\nfrom mmengine.config import Config, ConfigDict\nfrom mmengine.logging import print_log\n\n\ndef find_latest_checkpoint(path, suffix='pth'):\n    \"\"\"Find the latest checkpoint from the working directory.\n\n    Args:\n        path(str): The path to find checkpoints.\n        suffix(str): File extension.\n            Defaults to pth.\n\n    Returns:\n        latest_path(str | None): File path of the latest checkpoint.\n    References:\n        .. [1] https://github.com/microsoft/SoftTeacher\n                  /blob/main/ssod/utils/patch.py\n    \"\"\"\n    if not osp.exists(path):\n        warnings.warn('The path of checkpoints does not exist.')\n        return None\n    if osp.exists(osp.join(path, f'latest.{suffix}')):\n        return osp.join(path, f'latest.{suffix}')\n\n    checkpoints = glob.glob(osp.join(path, f'*.{suffix}'))\n    if len(checkpoints) == 0:\n        warnings.warn('There are no checkpoints in the path.')\n        return None\n    latest = -1\n    latest_path = None\n    for checkpoint in checkpoints:\n        count = int(osp.basename(checkpoint).split('_')[-1].split('.')[0])\n        if count > latest:\n            latest = count\n            latest_path = checkpoint\n    return latest_path\n\n\ndef update_data_root(cfg, logger=None):\n    \"\"\"Update data root according to env MMDET_DATASETS.\n\n    If set env MMDET_DATASETS, update cfg.data_root according to\n    MMDET_DATASETS. Otherwise, using cfg.data_root as default.\n\n    Args:\n        cfg (:obj:`Config`): The model config need to modify\n        logger (logging.Logger | str | None): the way to print msg\n    \"\"\"\n    assert isinstance(cfg, Config), \\\n        f'cfg got wrong type: {type(cfg)}, expected mmengine.Config'\n\n    if 'MMDET_DATASETS' in os.environ:\n        dst_root = os.environ['MMDET_DATASETS']\n        print_log(f'MMDET_DATASETS has been set to be {dst_root}.'\n                  f'Using {dst_root} as data root.')\n    else:\n        return\n\n    assert isinstance(cfg, Config), \\\n        f'cfg got wrong type: {type(cfg)}, expected mmengine.Config'\n\n    def update(cfg, src_str, dst_str):\n        for k, v in cfg.items():\n            if isinstance(v, ConfigDict):\n                update(cfg[k], src_str, dst_str)\n            if isinstance(v, str) and src_str in v:\n                cfg[k] = v.replace(src_str, dst_str)\n\n    update(cfg.data, cfg.data_root, dst_root)\n    cfg.data_root = dst_root\n\n\ndef add_dump_metric(args, cfg):\n    dump_metric = dict(type='DumpResults', out_file_path=args.out)\n    if isinstance(cfg.test_evaluator, (list, tuple)):\n        cfg.test_evaluator = list(cfg.test_evaluator).append(dump_metric)\n    elif isinstance(cfg.test_evaluator, dict):\n        if isinstance(cfg.test_evaluator.metric, str):\n            cfg.test_evaluator = [cfg.test_evaluator, dump_metric]\n        elif isinstance(cfg.test_evaluator.metric, (list, tuple)):\n            cfg.test_evaluator.metric = list(\n                cfg.test_evaluator.metric).append(dump_metric)\n        else:\n            cfg.test_evaluator.metric = [\n                cfg.test_evaluator.metric, dump_metric\n            ]\n", "path": "mmdet/utils/misc.py"}], "after_files": [{"content": "# Copyright (c) OpenMMLab. All rights reserved.\nfrom .collect_env import collect_env\nfrom .compat_config import compat_cfg\nfrom .dist_utils import (all_reduce_dict, allreduce_grads, reduce_mean,\n                         sync_random_seed)\nfrom .logger import get_caller_name, log_img_scale\nfrom .memory import AvoidCUDAOOM, AvoidOOM\nfrom .misc import find_latest_checkpoint, update_data_root\nfrom .replace_cfg_vals import replace_cfg_vals\nfrom .setup_env import register_all_modules, setup_multi_processes\nfrom .split_batch import split_batch\nfrom .typing import (ConfigType, InstanceList, MultiConfig, OptConfigType,\n                     OptInstanceList, OptMultiConfig, OptPixelList, PixelList,\n                     RangeType)\n\n__all__ = [\n    'collect_env', 'find_latest_checkpoint', 'update_data_root',\n    'setup_multi_processes', 'get_caller_name', 'log_img_scale', 'compat_cfg',\n    'split_batch', 'register_all_modules', 'replace_cfg_vals', 'AvoidOOM',\n    'AvoidCUDAOOM', 'all_reduce_dict', 'allreduce_grads', 'reduce_mean',\n    'sync_random_seed', 'ConfigType', 'InstanceList', 'MultiConfig',\n    'OptConfigType', 'OptInstanceList', 'OptMultiConfig', 'OptPixelList',\n    'PixelList', 'RangeType'\n]\n", "path": "mmdet/utils/__init__.py"}, {"content": "# Copyright (c) OpenMMLab. All rights reserved.\nimport glob\nimport os\nimport os.path as osp\nimport warnings\n\nfrom mmengine.config import Config, ConfigDict\nfrom mmengine.logging import print_log\n\n\ndef find_latest_checkpoint(path, suffix='pth'):\n    \"\"\"Find the latest checkpoint from the working directory.\n\n    Args:\n        path(str): The path to find checkpoints.\n        suffix(str): File extension.\n            Defaults to pth.\n\n    Returns:\n        latest_path(str | None): File path of the latest checkpoint.\n    References:\n        .. [1] https://github.com/microsoft/SoftTeacher\n                  /blob/main/ssod/utils/patch.py\n    \"\"\"\n    if not osp.exists(path):\n        warnings.warn('The path of checkpoints does not exist.')\n        return None\n    if osp.exists(osp.join(path, f'latest.{suffix}')):\n        return osp.join(path, f'latest.{suffix}')\n\n    checkpoints = glob.glob(osp.join(path, f'*.{suffix}'))\n    if len(checkpoints) == 0:\n        warnings.warn('There are no checkpoints in the path.')\n        return None\n    latest = -1\n    latest_path = None\n    for checkpoint in checkpoints:\n        count = int(osp.basename(checkpoint).split('_')[-1].split('.')[0])\n        if count > latest:\n            latest = count\n            latest_path = checkpoint\n    return latest_path\n\n\ndef update_data_root(cfg, logger=None):\n    \"\"\"Update data root according to env MMDET_DATASETS.\n\n    If set env MMDET_DATASETS, update cfg.data_root according to\n    MMDET_DATASETS. Otherwise, using cfg.data_root as default.\n\n    Args:\n        cfg (:obj:`Config`): The model config need to modify\n        logger (logging.Logger | str | None): the way to print msg\n    \"\"\"\n    assert isinstance(cfg, Config), \\\n        f'cfg got wrong type: {type(cfg)}, expected mmengine.Config'\n\n    if 'MMDET_DATASETS' in os.environ:\n        dst_root = os.environ['MMDET_DATASETS']\n        print_log(f'MMDET_DATASETS has been set to be {dst_root}.'\n                  f'Using {dst_root} as data root.')\n    else:\n        return\n\n    assert isinstance(cfg, Config), \\\n        f'cfg got wrong type: {type(cfg)}, expected mmengine.Config'\n\n    def update(cfg, src_str, dst_str):\n        for k, v in cfg.items():\n            if isinstance(v, ConfigDict):\n                update(cfg[k], src_str, dst_str)\n            if isinstance(v, str) and src_str in v:\n                cfg[k] = v.replace(src_str, dst_str)\n\n    update(cfg.data, cfg.data_root, dst_root)\n    cfg.data_root = dst_root\n", "path": "mmdet/utils/misc.py"}]}