mirror of
https://github.com/open-mmlab/mmcv.git
synced 2025-06-03 21:54:52 +08:00
* config dump fix dump should not depend on how config was loaded only where it is dumped changed checks for type to the given filename instead of the source filename * defined test_fromdict and fixed dump function it might be more convoluted than it needs to be but the formatting depends on the extension of the argument or the extension of the self.filename * config dump defaults to returning pretty_text, test_fromdict renamed to test_dump_from_dict * some reformatting in docstrings * refine unittest * fix unit test as comment * Refine docstring * minor refinement * import mmcv * fix lint Co-authored-by: HAOCHENYE <21724054@zju.edu.cn> Co-authored-by: Zaida Zhou <58739961+zhouzaida@users.noreply.github.com>
612 lines
21 KiB
Python
612 lines
21 KiB
Python
# Copyright (c) OpenMMLab. All rights reserved.
|
|
import argparse
|
|
import copy
|
|
import json
|
|
import os
|
|
import os.path as osp
|
|
import shutil
|
|
import tempfile
|
|
from pathlib import Path
|
|
|
|
import pytest
|
|
import yaml
|
|
|
|
from mmcv import Config, ConfigDict, DictAction, dump, load
|
|
|
|
data_path = osp.join(osp.dirname(osp.dirname(__file__)), 'data')
|
|
|
|
|
|
def test_construct():
|
|
cfg = Config()
|
|
assert cfg.filename is None
|
|
assert cfg.text == ''
|
|
assert len(cfg) == 0
|
|
assert cfg._cfg_dict == {}
|
|
|
|
with pytest.raises(TypeError):
|
|
Config([0, 1])
|
|
|
|
cfg_dict = dict(item1=[1, 2], item2=dict(a=0), item3=True, item4='test')
|
|
# test a.py
|
|
cfg_file = osp.join(data_path, 'config/a.py')
|
|
cfg_file_path = Path(cfg_file)
|
|
file_list = [cfg_file, cfg_file_path]
|
|
for item in file_list:
|
|
cfg = Config(cfg_dict, filename=item)
|
|
assert isinstance(cfg, Config)
|
|
assert isinstance(cfg.filename, str) and cfg.filename == str(item)
|
|
assert cfg.text == open(item, 'r').read()
|
|
assert cfg.dump() == cfg.pretty_text
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
dump_file = osp.join(temp_config_dir, 'a.py')
|
|
cfg.dump(dump_file)
|
|
assert cfg.dump() == open(dump_file, 'r').read()
|
|
assert Config.fromfile(dump_file)
|
|
|
|
# test b.json
|
|
cfg_file = osp.join(data_path, 'config/b.json')
|
|
cfg = Config(cfg_dict, filename=cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
assert cfg.text == open(cfg_file, 'r').read()
|
|
assert cfg.dump() == json.dumps(cfg_dict)
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
dump_file = osp.join(temp_config_dir, 'b.json')
|
|
cfg.dump(dump_file)
|
|
assert cfg.dump() == open(dump_file, 'r').read()
|
|
assert Config.fromfile(dump_file)
|
|
|
|
# test c.yaml
|
|
cfg_file = osp.join(data_path, 'config/c.yaml')
|
|
cfg = Config(cfg_dict, filename=cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
assert cfg.text == open(cfg_file, 'r').read()
|
|
assert cfg.dump() == yaml.dump(cfg_dict)
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
dump_file = osp.join(temp_config_dir, 'c.yaml')
|
|
cfg.dump(dump_file)
|
|
assert cfg.dump() == open(dump_file, 'r').read()
|
|
assert Config.fromfile(dump_file)
|
|
|
|
# test h.py
|
|
cfg_file = osp.join(data_path, 'config/h.py')
|
|
path = osp.join(osp.dirname(__file__), 'data', 'config')
|
|
# the value of osp.dirname(__file__) may be `D:\a\xxx` in windows
|
|
# environment. When dumping the cfg_dict to file, `D:\a\xxx` will be
|
|
# converted to `D:\x07\xxx` and it will cause unexpected result when
|
|
# checking whether `D:\a\xxx` equals to `D:\x07\xxx`. Therefore, we forcely
|
|
# convert a string representation of the path with forward slashes (/)
|
|
path = Path(path).as_posix()
|
|
cfg_dict = dict(item1='h.py', item2=path, item3='abc_h')
|
|
cfg = Config(cfg_dict, filename=cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
assert cfg.text == open(cfg_file, 'r').read()
|
|
assert cfg.dump() == cfg.pretty_text
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
dump_file = osp.join(temp_config_dir, 'h.py')
|
|
cfg.dump(dump_file)
|
|
assert cfg.dump() == open(dump_file, 'r').read()
|
|
assert Config.fromfile(dump_file)
|
|
assert Config.fromfile(dump_file)['item1'] == cfg_dict['item1']
|
|
assert Config.fromfile(dump_file)['item2'] == cfg_dict['item2']
|
|
assert Config.fromfile(dump_file)['item3'] == cfg_dict['item3']
|
|
|
|
# test no use_predefined_variable
|
|
cfg_dict = dict(
|
|
item1='{{fileBasename}}',
|
|
item2='{{ fileDirname}}',
|
|
item3='abc_{{ fileBasenameNoExtension }}')
|
|
assert Config.fromfile(cfg_file, False)
|
|
assert Config.fromfile(cfg_file, False)['item1'] == cfg_dict['item1']
|
|
assert Config.fromfile(cfg_file, False)['item2'] == cfg_dict['item2']
|
|
assert Config.fromfile(cfg_file, False)['item3'] == cfg_dict['item3']
|
|
|
|
# test p.yaml
|
|
cfg_file = osp.join(data_path, 'config/p.yaml')
|
|
cfg_dict = dict(item1=osp.join(osp.dirname(__file__), 'data', 'config'))
|
|
cfg = Config(cfg_dict, filename=cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
assert cfg.text == open(cfg_file, 'r').read()
|
|
assert cfg.dump() == yaml.dump(cfg_dict)
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
dump_file = osp.join(temp_config_dir, 'p.yaml')
|
|
cfg.dump(dump_file)
|
|
assert cfg.dump() == open(dump_file, 'r').read()
|
|
assert Config.fromfile(dump_file)
|
|
assert Config.fromfile(dump_file)['item1'] == cfg_dict['item1']
|
|
|
|
# test no use_predefined_variable
|
|
assert Config.fromfile(cfg_file, False)
|
|
assert Config.fromfile(cfg_file, False)['item1'] == '{{ fileDirname }}'
|
|
|
|
# test o.json
|
|
cfg_file = osp.join(data_path, 'config/o.json')
|
|
cfg_dict = dict(item1=osp.join(osp.dirname(__file__), 'data', 'config'))
|
|
cfg = Config(cfg_dict, filename=cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
assert cfg.text == open(cfg_file, 'r').read()
|
|
assert cfg.dump() == json.dumps(cfg_dict)
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
dump_file = osp.join(temp_config_dir, 'o.json')
|
|
cfg.dump(dump_file)
|
|
assert cfg.dump() == open(dump_file, 'r').read()
|
|
assert Config.fromfile(dump_file)
|
|
assert Config.fromfile(dump_file)['item1'] == cfg_dict['item1']
|
|
|
|
# test no use_predefined_variable
|
|
assert Config.fromfile(cfg_file, False)
|
|
assert Config.fromfile(cfg_file, False)['item1'] == '{{ fileDirname }}'
|
|
|
|
|
|
def test_fromfile():
|
|
for filename in ['a.py', 'a.b.py', 'b.json', 'c.yaml']:
|
|
cfg_file = osp.join(data_path, 'config', filename)
|
|
cfg_file_path = Path(cfg_file)
|
|
file_list = [cfg_file, cfg_file_path]
|
|
for item in file_list:
|
|
cfg = Config.fromfile(item)
|
|
assert isinstance(cfg, Config)
|
|
assert isinstance(cfg.filename, str) and cfg.filename == str(item)
|
|
assert cfg.text == osp.abspath(osp.expanduser(item)) + '\n' + \
|
|
open(item, 'r').read()
|
|
|
|
# test custom_imports for Config.fromfile
|
|
cfg_file = osp.join(data_path, 'config', 'q.py')
|
|
imported_file = osp.join(data_path, 'config', 'r.py')
|
|
target_pkg = osp.join(osp.dirname(__file__), 'r.py')
|
|
|
|
# Since the imported config will be regarded as a tmp file
|
|
# it should be copied to the directory at the same level
|
|
shutil.copy(imported_file, target_pkg)
|
|
Config.fromfile(cfg_file, import_custom_modules=True)
|
|
|
|
assert os.environ.pop('TEST_VALUE') == 'test'
|
|
os.remove(target_pkg)
|
|
|
|
with pytest.raises(FileNotFoundError):
|
|
Config.fromfile('no_such_file.py')
|
|
with pytest.raises(IOError):
|
|
Config.fromfile(osp.join(data_path, 'color.jpg'))
|
|
|
|
|
|
def test_fromstring():
|
|
for filename in ['a.py', 'a.b.py', 'b.json', 'c.yaml']:
|
|
cfg_file = osp.join(data_path, 'config', filename)
|
|
file_format = osp.splitext(filename)[-1]
|
|
in_cfg = Config.fromfile(cfg_file)
|
|
|
|
out_cfg = Config.fromstring(in_cfg.pretty_text, '.py')
|
|
assert in_cfg._cfg_dict == out_cfg._cfg_dict
|
|
|
|
cfg_str = open(cfg_file, 'r').read()
|
|
out_cfg = Config.fromstring(cfg_str, file_format)
|
|
assert in_cfg._cfg_dict == out_cfg._cfg_dict
|
|
|
|
# test pretty_text only supports py file format
|
|
cfg_file = osp.join(data_path, 'config', 'b.json')
|
|
in_cfg = Config.fromfile(cfg_file)
|
|
with pytest.raises(Exception):
|
|
Config.fromstring(in_cfg.pretty_text, '.json')
|
|
|
|
# test file format error
|
|
cfg_str = open(cfg_file, 'r').read()
|
|
with pytest.raises(Exception):
|
|
Config.fromstring(cfg_str, '.py')
|
|
|
|
|
|
def test_merge_from_base():
|
|
cfg_file = osp.join(data_path, 'config/d.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
base_cfg_file = osp.join(data_path, 'config/base.py')
|
|
merge_text = osp.abspath(osp.expanduser(base_cfg_file)) + '\n' + \
|
|
open(base_cfg_file, 'r').read()
|
|
merge_text += '\n' + osp.abspath(osp.expanduser(cfg_file)) + '\n' + \
|
|
open(cfg_file, 'r').read()
|
|
assert cfg.text == merge_text
|
|
assert cfg.item1 == [2, 3]
|
|
assert cfg.item2.a == 1
|
|
assert cfg.item3 is False
|
|
assert cfg.item4 == 'test_base'
|
|
|
|
with pytest.raises(TypeError):
|
|
Config.fromfile(osp.join(data_path, 'config/e.py'))
|
|
|
|
|
|
def test_merge_from_multiple_bases():
|
|
cfg_file = osp.join(data_path, 'config/l.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
# cfg.field
|
|
assert cfg.item1 == [1, 2]
|
|
assert cfg.item2.a == 0
|
|
assert cfg.item3 is False
|
|
assert cfg.item4 == 'test'
|
|
assert cfg.item5 == dict(a=0, b=1)
|
|
assert cfg.item6 == [dict(a=0), dict(b=1)]
|
|
assert cfg.item7 == dict(a=[0, 1, 2], b=dict(c=[3.1, 4.2, 5.3]))
|
|
|
|
with pytest.raises(KeyError):
|
|
Config.fromfile(osp.join(data_path, 'config/m.py'))
|
|
|
|
|
|
def test_base_variables():
|
|
for file in ['t.py', 't.json', 't.yaml']:
|
|
cfg_file = osp.join(data_path, f'config/{file}')
|
|
cfg = Config.fromfile(cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
# cfg.field
|
|
assert cfg.item1 == [1, 2]
|
|
assert cfg.item2.a == 0
|
|
assert cfg.item3 is False
|
|
assert cfg.item4 == 'test'
|
|
assert cfg.item5 == dict(a=0, b=1)
|
|
assert cfg.item6 == [dict(a=0), dict(b=1)]
|
|
assert cfg.item7 == dict(a=[0, 1, 2], b=dict(c=[3.1, 4.2, 5.3]))
|
|
assert cfg.item8 == file
|
|
assert cfg.item9 == dict(a=0)
|
|
assert cfg.item10 == [3.1, 4.2, 5.3]
|
|
|
|
# test nested base
|
|
for file in ['u.py', 'u.json', 'u.yaml']:
|
|
cfg_file = osp.join(data_path, f'config/{file}')
|
|
cfg = Config.fromfile(cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
# cfg.field
|
|
assert cfg.base == '_base_.item8'
|
|
assert cfg.item1 == [1, 2]
|
|
assert cfg.item2.a == 0
|
|
assert cfg.item3 is False
|
|
assert cfg.item4 == 'test'
|
|
assert cfg.item5 == dict(a=0, b=1)
|
|
assert cfg.item6 == [dict(a=0), dict(b=1)]
|
|
assert cfg.item7 == dict(a=[0, 1, 2], b=dict(c=[3.1, 4.2, 5.3]))
|
|
assert cfg.item8 == 't.py'
|
|
assert cfg.item9 == dict(a=0)
|
|
assert cfg.item10 == [3.1, 4.2, 5.3]
|
|
assert cfg.item11 == 't.py'
|
|
assert cfg.item12 == dict(a=0)
|
|
assert cfg.item13 == [3.1, 4.2, 5.3]
|
|
assert cfg.item14 == [1, 2]
|
|
assert cfg.item15 == dict(
|
|
a=dict(b=dict(a=0)),
|
|
b=[False],
|
|
c=['test'],
|
|
d=[[{
|
|
'e': 0
|
|
}], [{
|
|
'a': 0
|
|
}, {
|
|
'b': 1
|
|
}]],
|
|
e=[1, 2])
|
|
|
|
# test reference assignment for py
|
|
cfg_file = osp.join(data_path, 'config/v.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
assert cfg.item21 == 't.py'
|
|
assert cfg.item22 == 't.py'
|
|
assert cfg.item23 == [3.1, 4.2, 5.3]
|
|
assert cfg.item24 == [3.1, 4.2, 5.3]
|
|
assert cfg.item25 == dict(
|
|
a=dict(b=[3.1, 4.2, 5.3]),
|
|
b=[[3.1, 4.2, 5.3]],
|
|
c=[[{
|
|
'e': 't.py'
|
|
}], [{
|
|
'a': 0
|
|
}, {
|
|
'b': 1
|
|
}]],
|
|
e='t.py')
|
|
|
|
|
|
def test_merge_recursive_bases():
|
|
cfg_file = osp.join(data_path, 'config/f.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
assert isinstance(cfg, Config)
|
|
assert cfg.filename == cfg_file
|
|
# cfg.field
|
|
assert cfg.item1 == [2, 3]
|
|
assert cfg.item2.a == 1
|
|
assert cfg.item3 is False
|
|
assert cfg.item4 == 'test_recursive_bases'
|
|
|
|
|
|
def test_merge_from_dict():
|
|
cfg_file = osp.join(data_path, 'config/a.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
input_options = {'item2.a': 1, 'item2.b': 0.1, 'item3': False}
|
|
cfg.merge_from_dict(input_options)
|
|
assert cfg.item2 == dict(a=1, b=0.1)
|
|
assert cfg.item3 is False
|
|
|
|
cfg_file = osp.join(data_path, 'config/s.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
|
|
# Allow list keys
|
|
input_options = {'item.0.a': 1, 'item.1.b': 1}
|
|
cfg.merge_from_dict(input_options, allow_list_keys=True)
|
|
assert cfg.item == [{'a': 1}, {'b': 1, 'c': 0}]
|
|
|
|
# allow_list_keys is False
|
|
input_options = {'item.0.a': 1, 'item.1.b': 1}
|
|
with pytest.raises(TypeError):
|
|
cfg.merge_from_dict(input_options, allow_list_keys=False)
|
|
|
|
# Overflowed index number
|
|
input_options = {'item.2.a': 1}
|
|
with pytest.raises(KeyError):
|
|
cfg.merge_from_dict(input_options, allow_list_keys=True)
|
|
|
|
|
|
def test_merge_delete():
|
|
cfg_file = osp.join(data_path, 'config/delete.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
# cfg.field
|
|
assert cfg.item1 == dict(a=0)
|
|
assert cfg.item2 == dict(a=0, b=0)
|
|
assert cfg.item3 is True
|
|
assert cfg.item4 == 'test'
|
|
assert '_delete_' not in cfg.item2
|
|
|
|
# related issue: https://github.com/open-mmlab/mmcv/issues/1570
|
|
assert type(cfg.item1) == ConfigDict
|
|
assert type(cfg.item2) == ConfigDict
|
|
|
|
|
|
def test_merge_intermediate_variable():
|
|
|
|
cfg_file = osp.join(data_path, 'config/i_child.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
# cfg.field
|
|
assert cfg.item1 == [1, 2]
|
|
assert cfg.item2 == dict(a=0)
|
|
assert cfg.item3 is True
|
|
assert cfg.item4 == 'test'
|
|
assert cfg.item_cfg == dict(b=2)
|
|
assert cfg.item5 == dict(cfg=dict(b=1))
|
|
assert cfg.item6 == dict(cfg=dict(b=2))
|
|
|
|
|
|
def test_fromfile_in_config():
|
|
cfg_file = osp.join(data_path, 'config/code.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
# cfg.field
|
|
assert cfg.cfg.item1 == [1, 2]
|
|
assert cfg.cfg.item2 == dict(a=0)
|
|
assert cfg.cfg.item3 is True
|
|
assert cfg.cfg.item4 == 'test'
|
|
assert cfg.item5 == 1
|
|
|
|
|
|
def test_dict():
|
|
cfg_dict = dict(item1=[1, 2], item2=dict(a=0), item3=True, item4='test')
|
|
|
|
for filename in ['a.py', 'b.json', 'c.yaml']:
|
|
cfg_file = osp.join(data_path, 'config', filename)
|
|
cfg = Config.fromfile(cfg_file)
|
|
|
|
# len(cfg)
|
|
assert len(cfg) == 4
|
|
# cfg.keys()
|
|
assert set(cfg.keys()) == set(cfg_dict.keys())
|
|
assert set(cfg._cfg_dict.keys()) == set(cfg_dict.keys())
|
|
# cfg.values()
|
|
for value in cfg.values():
|
|
assert value in cfg_dict.values()
|
|
# cfg.items()
|
|
for name, value in cfg.items():
|
|
assert name in cfg_dict
|
|
assert value in cfg_dict.values()
|
|
# cfg.field
|
|
assert cfg.item1 == cfg_dict['item1']
|
|
assert cfg.item2 == cfg_dict['item2']
|
|
assert cfg.item2.a == 0
|
|
assert cfg.item3 == cfg_dict['item3']
|
|
assert cfg.item4 == cfg_dict['item4']
|
|
with pytest.raises(AttributeError):
|
|
cfg.not_exist
|
|
# field in cfg, cfg[field], cfg.get()
|
|
for name in ['item1', 'item2', 'item3', 'item4']:
|
|
assert name in cfg
|
|
assert cfg[name] == cfg_dict[name]
|
|
assert cfg.get(name) == cfg_dict[name]
|
|
assert cfg.get('not_exist') is None
|
|
assert cfg.get('not_exist', 0) == 0
|
|
with pytest.raises(KeyError):
|
|
cfg['not_exist']
|
|
assert 'item1' in cfg
|
|
assert 'not_exist' not in cfg
|
|
# cfg.update()
|
|
cfg.update(dict(item1=0))
|
|
assert cfg.item1 == 0
|
|
cfg.update(dict(item2=dict(a=1)))
|
|
assert cfg.item2.a == 1
|
|
|
|
|
|
@pytest.mark.parametrize('file', ['a.json', 'b.py', 'c.yaml', 'd.yml', None])
|
|
def test_dump(file):
|
|
# config loaded from dict
|
|
cfg_dict = dict(item1=[1, 2], item2=dict(a=0), item3=True, item4='test')
|
|
cfg = Config(cfg_dict=cfg_dict)
|
|
assert cfg.item1 == cfg_dict['item1']
|
|
assert cfg.item2 == cfg_dict['item2']
|
|
assert cfg.item3 == cfg_dict['item3']
|
|
assert cfg.item4 == cfg_dict['item4']
|
|
assert cfg._filename is None
|
|
if file is not None:
|
|
# dump without a filename argument is only returning pretty_text.
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
cfg_file = osp.join(temp_config_dir, file)
|
|
cfg.dump(cfg_file)
|
|
dumped_cfg = Config.fromfile(cfg_file)
|
|
assert dumped_cfg._cfg_dict == cfg._cfg_dict
|
|
else:
|
|
assert cfg.dump() == cfg.pretty_text
|
|
|
|
# The key of json must be a string, so key `1` will be converted to `'1'`.
|
|
def compare_json_cfg(ori_cfg, dumped_json_cfg):
|
|
for key, value in ori_cfg.items():
|
|
assert str(key) in dumped_json_cfg
|
|
if not isinstance(value, dict):
|
|
assert ori_cfg[key] == dumped_json_cfg[str(key)]
|
|
else:
|
|
compare_json_cfg(value, dumped_json_cfg[str(key)])
|
|
|
|
# config loaded from file
|
|
cfg_file = osp.join(data_path, 'config/n.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
if file is not None:
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
cfg_file = osp.join(temp_config_dir, file)
|
|
cfg.dump(cfg_file)
|
|
dumped_cfg = Config.fromfile(cfg_file)
|
|
if not file.endswith('.json'):
|
|
assert dumped_cfg._cfg_dict == cfg._cfg_dict
|
|
else:
|
|
compare_json_cfg(cfg._cfg_dict, dumped_cfg._cfg_dict)
|
|
else:
|
|
assert cfg.dump() == cfg.pretty_text
|
|
|
|
|
|
def test_setattr():
|
|
cfg = Config()
|
|
cfg.item1 = [1, 2]
|
|
cfg.item2 = {'a': 0}
|
|
cfg['item5'] = {'a': {'b': None}}
|
|
assert cfg._cfg_dict['item1'] == [1, 2]
|
|
assert cfg.item1 == [1, 2]
|
|
assert cfg._cfg_dict['item2'] == {'a': 0}
|
|
assert cfg.item2.a == 0
|
|
assert cfg._cfg_dict['item5'] == {'a': {'b': None}}
|
|
assert cfg.item5.a.b is None
|
|
|
|
|
|
def test_pretty_text():
|
|
cfg_file = osp.join(data_path, 'config/l.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
text_cfg_filename = osp.join(temp_config_dir, '_text_config.py')
|
|
with open(text_cfg_filename, 'w') as f:
|
|
f.write(cfg.pretty_text)
|
|
text_cfg = Config.fromfile(text_cfg_filename)
|
|
assert text_cfg._cfg_dict == cfg._cfg_dict
|
|
|
|
|
|
def test_dict_action():
|
|
parser = argparse.ArgumentParser(description='Train a detector')
|
|
parser.add_argument(
|
|
'--options', nargs='+', action=DictAction, help='custom options')
|
|
# Nested brackets
|
|
args = parser.parse_args(
|
|
['--options', 'item2.a=a,b', 'item2.b=[(a,b), [1,2], false]'])
|
|
out_dict = {'item2.a': ['a', 'b'], 'item2.b': [('a', 'b'), [1, 2], False]}
|
|
assert args.options == out_dict
|
|
# Single Nested brackets
|
|
args = parser.parse_args(['--options', 'item2.a=[[1]]'])
|
|
out_dict = {'item2.a': [[1]]}
|
|
assert args.options == out_dict
|
|
# Imbalance bracket
|
|
with pytest.raises(AssertionError):
|
|
parser.parse_args(['--options', 'item2.a=[(a,b), [1,2], false'])
|
|
# Normal values
|
|
args = parser.parse_args([
|
|
'--options', 'item2.a=1', 'item2.b=0.1', 'item2.c=x', 'item3=false',
|
|
'item4=none', 'item5=None'
|
|
])
|
|
out_dict = {
|
|
'item2.a': 1,
|
|
'item2.b': 0.1,
|
|
'item2.c': 'x',
|
|
'item3': False,
|
|
'item4': 'none',
|
|
'item5': None,
|
|
}
|
|
assert args.options == out_dict
|
|
cfg_file = osp.join(data_path, 'config/a.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
cfg.merge_from_dict(args.options)
|
|
assert cfg.item2 == dict(a=1, b=0.1, c='x')
|
|
assert cfg.item3 is False
|
|
|
|
|
|
def test_reserved_key():
|
|
cfg_file = osp.join(data_path, 'config/g.py')
|
|
with pytest.raises(KeyError):
|
|
Config.fromfile(cfg_file)
|
|
|
|
|
|
def test_syntax_error():
|
|
# the name can not be used to open the file a second time in windows,
|
|
# so `delete` should be set as `False` and we need to manually remove it
|
|
# more details can be found at https://github.com/open-mmlab/mmcv/pull/1077
|
|
temp_cfg_file = tempfile.NamedTemporaryFile(suffix='.py', delete=False)
|
|
temp_cfg_path = temp_cfg_file.name
|
|
# write a file with syntax error
|
|
with open(temp_cfg_path, 'w') as f:
|
|
f.write('a=0b=dict(c=1)')
|
|
with pytest.raises(
|
|
SyntaxError, match='There are syntax errors in config file'):
|
|
Config.fromfile(temp_cfg_path)
|
|
temp_cfg_file.close()
|
|
os.remove(temp_cfg_path)
|
|
|
|
|
|
def test_pickle_support():
|
|
cfg_file = osp.join(data_path, 'config/n.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
|
|
with tempfile.TemporaryDirectory() as temp_config_dir:
|
|
pkl_cfg_filename = osp.join(temp_config_dir, '_pickle.pkl')
|
|
dump(cfg, pkl_cfg_filename)
|
|
pkl_cfg = load(pkl_cfg_filename)
|
|
|
|
assert pkl_cfg._cfg_dict == cfg._cfg_dict
|
|
|
|
|
|
def test_deprecation():
|
|
deprecated_cfg_files = [
|
|
osp.join(data_path, 'config/deprecated.py'),
|
|
osp.join(data_path, 'config/deprecated_as_base.py')
|
|
]
|
|
|
|
for cfg_file in deprecated_cfg_files:
|
|
with pytest.warns(DeprecationWarning):
|
|
cfg = Config.fromfile(cfg_file)
|
|
assert cfg.item1 == 'expected'
|
|
|
|
|
|
def test_deepcopy():
|
|
cfg_file = osp.join(data_path, 'config/n.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
new_cfg = copy.deepcopy(cfg)
|
|
|
|
assert isinstance(new_cfg, Config)
|
|
assert new_cfg._cfg_dict == cfg._cfg_dict
|
|
assert new_cfg._cfg_dict is not cfg._cfg_dict
|
|
assert new_cfg._filename == cfg._filename
|
|
assert new_cfg._text == cfg._text
|
|
|
|
|
|
def test_copy():
|
|
cfg_file = osp.join(data_path, 'config/n.py')
|
|
cfg = Config.fromfile(cfg_file)
|
|
new_cfg = copy.copy(cfg)
|
|
|
|
assert isinstance(new_cfg, Config)
|
|
assert new_cfg is not cfg
|
|
assert new_cfg._cfg_dict is cfg._cfg_dict
|
|
assert new_cfg._filename == cfg._filename
|
|
assert new_cfg._text == cfg._text
|