2008年3月6日木曜日

ConfigProxy

このエントリーをブックマークに追加 このエントリーを含むはてなブックマーク
attribute proxyを使って.cfgの中身に.でアクセスできるようにしたコードを用意しました。標準のconfig parserを裸のままではあんまりに使いにくいので。

サンプルとしてはこんな感じ。

.cfg
[connection]
uri = http://hogehoge

.py
import config
print config.active.connection.uri

実行結果
http://hogehoge

また、loadするcfgに、実行の基点となったスクリプトの位置にある、拡張子を.pyから.cfgにしたものを使うようになっています。もちろん明示的にcfgを指定することもできます。メインのスクリプトで指定してあげるのかな。

テスト用(__name__=='__main__'トリック)のconnectionとサービス用のconnectionを、importされるpyで意識せずに書けるのでいいはず。


ちょっと違うが似たようなもの。importされたmoduleは、importしたmoduleについてどのくらい知ることができるかのかに興味があるので、その点で近い。
Can module access global from __main__?



#!/usr/bin/env python
# -*- coding: us-ascii -*-
# vim: syntax=python
#
# Copyright 2006-2008 Noriyuki Hosaka nori@backgammon.gr.jp
#

import os
import sys
import glob
import ConfigParser

__all__ = ['active', 'available', 'load_config']
"""
Assuming that we have config.cfg and config.py(this file) in same directory.


"""
def _example():
"""
>>> import config
>>> available(config.active)
['sample']

>>> config.active.sample.uri
'http://www.asahi.com'
"""
pass


class SectionProxy:
def __init__(self, config, filenames, name):
self.__dict__['_config'] = config
self.__dict__['_filenames'] = filenames
self.__dict__['_name'] = name

def __getattr__(self, option):
return self._config.get(self._name, option)

def __setattr__(self, option, value):
self._config.set(self.name, option, value)

def __delattr__(self, option):
self._config.remove_option(option)

def __repr__(self):
return ""%str(self._filenames)
__str__ = __repr__

def __len__(self):
return len(self._config.options(self._name))

def __iter__(self):
for option in self._config.options(self._name):
yield option

def __contains__(self, option):
return self._config.has_option(self._name, option)


class ConfigProxy(object):
def __init__(self, config, filenames):
self.__dict__['_config'] = config
self.__dict__['_filenames'] = filenames
self._config.read(filenames)

def __getattr__(self, section):
if self._config.has_section(section):
return SectionProxy(self._config, self._filenames, section)
raise ValueError('No such section: %s'%section)

def __setattr__(self, section):
self._config.add_section(section)

def __delattr__(self, section):
self._config.remove_section(section)

def __repr__(self):
return ""%(self._filenames)
__str__ = __repr__

def __len__(self):
return len(self._config.sections())

def __contains__(self, section):
return self._config.has_section(section)

def __iter__(self):
for section in self._config.sections():
yield section


def find_config_path():
caller = sys.modules['__main__']
trunk = caller.__file__.rsplit('.', 2)[0]
return glob.glob(os.path.join(sys.path[0], trunk+'.cfg'))


def load_config(paths):
config = ConfigParser.SafeConfigParser()
active = ConfigProxy(config, paths)
return active

def available(proxy):
return list(proxy)


active = load_config(find_config_path())

if __name__ == '__main__':
import doctest
doctest.testmod()

0 件のコメント: