Source code for stoqlib.lib.settings

# -*- coding: utf-8 -*-
# vi:si:et:sw=4:sts=4:ts=4

## Copyright (C) 2012 Async Open Source
## This program is free software; you can redistribute it and/or
## modify it under the terms of the GNU General Public License
## as published by the Free Software Foundation; either version 2
## of the License, or (at your option) any later version.
## This program is distributed in the hope that it will be useful,
## but WITHOUT ANY WARRANTY; without even the implied warranty of
## GNU Lesser General Public License for more details.
## You should have received a copy of the GNU General Public License
## along with this program; if not, write to the Free Software
## Foundation, Inc., or visit:
##  Author(s): Stoq Team <>
"""Routines for parsing user configuration settings"""

from decimal import Decimal
import errno
import json
import logging
import os

from stoqlib.lib.osutils import get_application_dir

log = logging.getLogger(__name__)

def _decode_list(data):
    rv = []
    for item in data:
        if isinstance(item, unicode):
            item = item.encode('utf-8')
        elif isinstance(item, list):
            item = _decode_list(item)
        elif isinstance(item, dict):
            item = _decode_dict(item)
    return rv

def _decode_dict(data):
    rv = {}
    for key, value in data.items():
        if isinstance(key, unicode):
            key = key.encode('utf-8')
        if isinstance(value, unicode):
            value = value.encode('utf-8')
        elif isinstance(value, list):
            value = _decode_list(value)
        elif isinstance(value, dict):
            value = _decode_dict(value)
        rv[key] = value
    return rv

def _encode_object(obj):
    if hasattr(obj, 'isoformat'):
        return obj.isoformat()
    if isinstance(obj, Decimal):
        return str(obj)

    raise TypeError(
        'Object of type %s with value of %r '
        'is not JSON serializable' % (type(obj), obj))

def _fix_name(name):
    name = name.replace('_', '-')
    return name.encode('utf-8')

[docs]class UserSettings(object): domain = 'stoq' def __init__(self, filename=None): self._root = {} self._read(filename)
[docs] def set(self, name, value): self._root[_fix_name(name)] = value
[docs] def get(self, name, default=None): name = _fix_name(name) if not name in self._root: self.set(name, default) value = self._root[name] return value
[docs] def remove(self, name): name = _fix_name(name) if name in self._root: del self._root[name]
[docs] def items(self): return list(self._root.items())
[docs] def reset(self): self._root = {}
[docs] def flush(self): data = json.dumps(self._root, indent=2, sort_keys=True, default=_encode_object) self._write(data)
[docs] def get_filename(self): config_dir = get_application_dir(self.domain) return os.path.join(config_dir, 'settings')
# Private def _read(self, filename): filename = filename or self.get_filename() try: fd = open(filename) except IOError as e: if e.errno == errno.ENOENT: return raise data = fd.close() try: self._root = json.loads(data, object_hook=_decode_dict) except ValueError: self._root = {} def _write(self, data): filename = self.get_filename() fd = open(filename, 'w') try: fd.write(data + '\n') except OSError as e: # Permission denied, oh well. if e.errno == errno.EACCES: return # configuration directory missing, don't try to # recreate it as someone probably just removed it elif e.errno == errno.ENOENT: return fd.close()
_settings = None
[docs]def get_settings(): global _settings if _settings is None: _settings = UserSettings() return _settings
if __name__ == '__main__': # pragma nocover s = UserSettings() columns = s.get('list-columns', []) columns.append({}) columns.append({"foo": {}}) s.flush()