Commit 4adf7006 authored by Kai Chen's avatar Kai Chen
Browse files

add config class

parent f872672f
from .config import *
from .misc import *
from .path import *
from .progressbar import *
......
import os.path as osp
import sys
from argparse import ArgumentParser
from collections import Iterable
from importlib import import_module
from addict import Dict
def add_args(parser, cfg, prefix=''):
for k, v in cfg.items():
if isinstance(v, str):
parser.add_argument('--' + prefix + k)
elif isinstance(v, int):
parser.add_argument('--' + prefix + k, type=int)
elif isinstance(v, float):
parser.add_argument('--' + prefix + k, type=float)
elif isinstance(v, bool):
parser.add_argument('--' + prefix + k, action='store_true')
elif isinstance(v, dict):
add_args(parser, v, k + '.')
elif isinstance(v, Iterable):
parser.add_argument('--' + prefix + k, type=type(v[0]), nargs='+')
else:
print('connot parse key {} of type {}'.format(prefix + k, type(v)))
return parser
class Config(object):
"""A facility for config and config files.
It supports common file formats as configs: python/json/yaml. The interface
is the same as a dict object and also allows access config values as
attributes.
Example:
>>> cfg = Config(dict(a=1, b=dict(b1=[0, 1])))
>>> cfg.a
1
>>> cfg.b
{'b1': [0, 1]}
>>> cfg.b.b1
[0, 1]
>>> cfg = Config.fromfile('tests/data/config/a.py')
>>> cfg.filename
"/home/kchen/projects/mmcv/tests/data/config/a.py"
>>> cfg.item4
'test'
>>> cfg
"Config [path: /home/kchen/projects/mmcv/tests/data/config/a.py]: "
"{'item1': [1, 2], 'item2': {'a': 0}, 'item3': True, 'item4': 'test'}"
"""
@staticmethod
def fromfile(filename):
filename = osp.abspath(osp.expanduser(filename))
if filename.endswith('.py'):
sys.path.append(osp.dirname(filename))
module_name = osp.basename(filename)[:-3]
if '.' in module_name:
raise ValueError('Dots are not allowed in config file path.')
mod = import_module(module_name)
cfg_dict = {
name: value
for name, value in mod.__dict__.items()
if not name.startswith('__')
}
elif filename.endswith(('.yaml', '.json')):
import mmcv
cfg_dict = mmcv.load(filename)
else:
raise IOError('Only py/yaml/json type are supported now!')
return Config(cfg_dict, filename=filename)
@staticmethod
def auto_argparser(description=None):
"""Generate argparser from config file automatically (experimental)
"""
partial_parser = ArgumentParser(description=description)
partial_parser.add_argument('config', help='config file path')
cfg_file = partial_parser.parse_known_args()[0].config
cfg = Config.from_file(cfg_file)
parser = ArgumentParser(description=description)
parser.add_argument('config', help='config file path')
add_args(parser, cfg)
return parser, cfg
def __init__(self, cfg_dict=None, filename=None):
if cfg_dict is None:
cfg_dict = dict()
elif not isinstance(cfg_dict, dict):
raise TypeError('cfg_dict must be a dict, but got {}'.format(
type(cfg_dict)))
super(Config, self).__setattr__('_cfg_dict', Dict(cfg_dict))
super(Config, self).__setattr__('_filename', filename)
if filename:
with open(filename, 'r') as f:
super(Config, self).__setattr__('_text', f.read())
else:
super(Config, self).__setattr__('_text', '')
@property
def filename(self):
return self._filename
@property
def text(self):
return self._text
def __repr__(self):
return 'Config [path: {}]: {}'.format(self.filename,
self._cfg_dict.__repr__())
def __len__(self):
return len(self._cfg_dict)
def __getattr__(self, name):
return getattr(self._cfg_dict, name)
def __getitem__(self, name):
return self._cfg_dict.__getitem__(name)
def __setattr__(self, name, value):
if isinstance(value, dict):
value = Dict(value)
self._cfg_dict.__setattr__(name, value)
def __setitem__(self, name, value):
if isinstance(value, dict):
value = Dict(value)
self._cfg_dict.__setitem__(name, value)
def __iter__(self):
return iter(self._cfg_dict)
import sys
from setuptools import find_packages, setup
install_requires = ['numpy>=1.11.1', 'pyyaml', 'six']
install_requires = ['numpy>=1.11.1', 'pyyaml', 'six', 'addict']
if sys.version_info < (3, 3):
install_requires.append('backports.shutil_get_terminal_size')
if sys.version_info < (3, 4):
......
item1 = [1, 2]
item2 = {'a': 0}
item3 = True
item4 = 'test'
{
"item1": [1, 2],
"item2": {
"a": 0
},
"item3": true,
"item4": "test"
}
\ No newline at end of file
item1: [1, 2]
item2: {'a': 0}
item3: True
item4: 'test'
import os.path as osp
import pytest
from mmcv import Config
def test_empty():
cfg = Config()
assert cfg.filename is None
assert cfg.text == ''
assert len(cfg) == 0
assert cfg._cfg_dict == {}
def test_fromfile():
for filename in ['a.py', 'b.json', 'c.yaml']:
cfg_file = osp.join(osp.dirname(__file__), 'data/config', filename)
cfg = Config.fromfile(cfg_file)
assert isinstance(cfg, Config)
assert cfg.filename == cfg_file
assert cfg.text == open(cfg_file, 'r').read()
with pytest.raises(ValueError):
Config.fromfile('a/b/c.d.py')
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(osp.dirname(__file__), 'data/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']
# 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', 0) == 0
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
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
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment