1 # Copyright 2011-2012 GRNET S.A. All rights reserved.
3 # Redistribution and use in source and binary forms, with or
4 # without modification, are permitted provided that the following
7 # 1. Redistributions of source code must retain the above
8 # copyright notice, this list of conditions and the following
11 # 2. Redistributions in binary form must reproduce the above
12 # copyright notice, this list of conditions and the following
13 # disclaimer in the documentation and/or other materials
14 # provided with the distribution.
16 # THIS SOFTWARE IS PROVIDED BY GRNET S.A. ``AS IS'' AND ANY EXPRESS
17 # OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 # WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
19 # PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL GRNET S.A OR
20 # CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
21 # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
22 # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
23 # USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
24 # AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 # LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
26 # ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
27 # POSSIBILITY OF SUCH DAMAGE.
29 # The views and conclusions contained in the software and
30 # documentation are those of the authors and should not be
31 # interpreted as representing official policies, either expressed
32 # or implied, of GRNET S.A.
36 from collections import defaultdict
37 from ConfigParser import RawConfigParser, NoOptionError, NoSectionError
40 from collections import OrderedDict
42 from ordereddict import OrderedDict
45 # Path to the file that stores the configuration
46 CONFIG_PATH = os.path.expanduser('~/.kamakirc')
47 HISTORY_PATH = os.path.expanduser('~/.kamaki.history')
49 # Name of a shell variable to bypass the CONFIG_PATH value
50 CONFIG_ENV = 'KAMAKI_CONFIG'
53 # Kamaki configuration file
63 'description': 'Configuration commands'
71 'url': 'https://pithos.okeanos.grnet.gr/v1'
74 'url': 'https://cyclades.okeanos.grnet.gr/api/v1.1'
87 'url': 'https://cyclades.okeanos.grnet.gr/plankton'
91 'url': 'https://accounts.okeanos.grnet.gr'
96 class Config(RawConfigParser):
97 def __init__(self, path=None):
98 RawConfigParser.__init__(self, dict_type=OrderedDict)
99 self.path = path or os.environ.get(CONFIG_ENV, CONFIG_PATH)
100 self._overrides = defaultdict(dict)
101 self._load_defaults()
104 def _load_defaults(self):
105 for section, options in DEFAULTS.items():
106 for option, val in options.items():
107 self.set(section, option, val)
110 self = self.__init__(self.path)
113 return [api for api in self.sections() if api != 'global']
115 def get(self, section, option):
116 value = self._overrides.get(section, {}).get(option)
117 if value is not None:
121 return RawConfigParser.get(self, section, option)
122 except (NoSectionError, NoOptionError):
123 return DEFAULTS.get(section, {}).get(option)
125 def set(self, section, option, value):
126 if section not in RawConfigParser.sections(self):
127 self.add_section(section)
128 RawConfigParser.set(self, section, option, value)
130 def remove_option(self, section, option):
132 RawConfigParser.remove_option(self, section, option)
133 except NoSectionError:
136 def items(self, section, include_defaults=False):
138 d = dict(DEFAULTS[section]) if include_defaults else {}
142 d.update(RawConfigParser.items(self, section))
143 except NoSectionError:
147 def override(self, section, option, value):
148 self._overrides[section][option] = value
151 with open(self.path, 'w') as f:
152 os.chmod(self.path, 0600)
153 f.write(HEADER.lstrip())
155 RawConfigParser.write(self, f)