Created
September 3, 2013 16:10
-
-
Save mtomwing/6425988 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import ConfigParser | |
from ..core import ConfigManager | |
class ConfigParserManager(ConfigManager): | |
def __init__(self, manager, filename): | |
super(ConfigParserManager, self).__init__(manager, filename) | |
self.parser = ConfigParser.ConfigParser() | |
self.parser.read([self.filepath]) | |
def load(self, config_class, section): | |
config_instance = config_class() | |
for name, option in config_instance.options.iteritems(): | |
if not self.parser.has_option(section, name): | |
continue | |
raw = self.parser.get(section, name) | |
clean = option.decode(raw) | |
config_instance.set_value(name, option, clean) | |
return config_instance | |
def store(self, config_instance, section): | |
# TODO: Should probably make sure there's a value for every | |
# option before irreversibly removing a section. | |
self.parser.remove_section(section) | |
self.parser.add_section(section) | |
for name, option in config_instance.options.iteritems(): | |
raw = config_instance.get_value(name, option) | |
clean = option.encode(raw) | |
self.parser.set(section, name, clean) | |
def save(self): | |
with open(self.filepath, 'wc') as config_fd: | |
self.parser.write(config_fd) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import abc | |
import functools | |
import os | |
from .exceptions import ( | |
InvalidOptionValueError, | |
OptionValueNotSetError, | |
) | |
class Option(object): | |
__metaclass__ = abc.ABCMeta | |
class NotSpecified(object): | |
pass | |
def __init__(self, default=NotSpecified): | |
self.default = default | |
def is_required(self): | |
return self.default == self.NotSpecified | |
def post_get(self, value): | |
pass | |
def post_set(self, value): | |
pass | |
# Override these! | |
@abc.abstractmethod | |
def is_valid(self, value): | |
pass | |
@abc.abstractmethod | |
def encode(self, value): | |
''' | |
Encodes value into a string. | |
Should raise something if unable to encode. | |
''' | |
pass | |
@abc.abstractmethod | |
def decode(self, value): | |
''' | |
Decodes value into a proper Option value. | |
Should raise something if unable to decode. | |
''' | |
pass | |
class ConfigBase(abc.ABCMeta): | |
def __new__(meta, name, bases, dct): | |
dct, options = meta.find_options(dct) | |
dct['options'] = options | |
cls = super(ConfigBase, meta).__new__(meta, name, bases, dct) | |
for opt_name, option in options.iteritems(): | |
opt_get = functools.partial(cls.get_value, name=opt_name, option=option) | |
opt_set = functools.partial(cls._set_value, name=opt_name, option=option) | |
setattr(cls, opt_name, property(opt_get, opt_set)) | |
return cls | |
@staticmethod | |
def find_options(dct): | |
new_dct = {} | |
options = {} | |
for name, attr in dct.iteritems(): | |
if name.startswith('_') or not isinstance(attr, Option): | |
new_dct[name] = attr | |
else: | |
options[name] = attr | |
return new_dct, options | |
class Config(object): | |
__metaclass__ = ConfigBase | |
def __init__(self): | |
self.values = {} | |
self.set_defaults() | |
def _set_value(self, value, name, option): | |
self.set_value(name, option, value) | |
def set_defaults(self): | |
for name, option in self.options.iteritems(): | |
if not option.is_required(): | |
self.set_value(name, option, option.default) | |
# You probably will not need to override these: | |
def get_value(self, name, option): | |
if name in self.values: | |
value = self.values[name] | |
option.post_get(value) | |
return value | |
else: | |
raise OptionValueNotSetError(name, option) | |
def set_value(self, name, option, value): | |
if option.is_valid(value): | |
self.values[name] = value | |
option.post_set(value) | |
else: | |
raise InvalidOptionValueError(name, option) | |
class ProfileManager(object): | |
def __init__(self, folder, name): | |
self.name = name | |
self.folder = folder | |
self.full_path = os.path.join(folder, name) | |
if not os.path.exists(self.full_path): | |
os.makedirs(self.full_path) | |
def get_filepath(self, name): | |
return os.path.join(self.full_path, name) | |
class ConfigManager(object): | |
__metaclass__ = abc.ABCMeta | |
def __init__(self, manager, filename): | |
self.manager = manager | |
self.filename = filename | |
self.filepath = manager.get_filepath(filename) | |
# Override these! | |
@abc.abstractmethod | |
def load(self, config_class): | |
''' | |
Populates the Config from somewhere. | |
It should iterate over all options in self.options and determine the | |
value to store by using option.decode(..). | |
''' | |
pass | |
@abc.abstractmethod | |
def store(self, config_instance): | |
''' | |
Persists the Config to somewhere. | |
It should iterate over all options in self.options and determine the | |
value to persis by using option.encode(..). | |
''' | |
pass | |
@abc.abstractmethod | |
def save(self): | |
# TODO: Persist config somewhere | |
pass |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from freeseer.framework.config.core import Config, ProfileManager | |
from freeseer.framework.config.persist import ( | |
ConfigParserManager, | |
JSONConfigManager, | |
) | |
import freeseer.framework.config.options as options | |
class FreeseerConfig(Config): | |
videodir = options.FolderOption('/home/mtomwing/Videos', auto_create=True) | |
auto_hide = options.BooleanOption(True) | |
resolution = options.ChoiceOption([ | |
'default', | |
'240p', | |
'360p', | |
'480p', | |
'720p', | |
'1080p', | |
], 'default') | |
if __name__ == '__main__': | |
profile = ProfileManager('/tmp/freeseer/profiles', 'mtomwing') | |
managers = [ | |
[ConfigParserManager, '.conf'], | |
[JSONConfigManager, '.json'], | |
] | |
for Manager, ext in managers: | |
storage = Manager(profile, 'freeseer' + ext) | |
config = storage.load(FreeseerConfig, 'Global') | |
storage.store(config, 'Global') | |
config.auto_hide = False | |
storage.store(config, 'Something Else') | |
storage.save() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment