Esempio n. 1
0
 def setup(self):
     if self._setup:
         return
     self._setup = True
     # path
     self.setup_path()
     # new configuration
     data = {}
     # runtime
     yml_path = os.path.join(self.data['path'], '.rock.yml')
     if yml_path and os.path.isfile(yml_path):
         data = self.parse(yml_path)
         if not isinstance(data, dict):
             raise ConfigError('.rock.yml syntax error')
         data.update(self.data)
     else:
         data = copy.deepcopy(self.data)
     # project
     for name in ('path', 'runtime'):
         if name not in data:
             raise ConfigError('%s is required' % name)
     # paths
     runtime = self.runtime(data['runtime'])
     etc_path = self.etc_path('runtime')
     runtime_yml = data['runtime'] + '.yml'
     data_path = self.data_path('runtime', runtime_yml)
     if not os.path.exists(data_path):
         file_name = data['runtime'].rstrip('0123456789') + '.yml'
         data_path = self.data_path('runtime', file_name)
     # ensure runtime exists
     if not os.path.isdir(runtime.path()):
         raise ConfigError("runtime path doesn't exist")
     # parse configs
     runtime_config = self.parse(runtime.path('rock.yml'))
     rock_config = self.parse(data_path, require_exists=False)
     etc_config = self.parse(os.path.join(etc_path, runtime_yml),
                             require_exists=False)
     # merge
     self.data = {
         'env': {
             'ROCK_ENV': self.env,
             'ROCK_PATH': data['path'],
             'ROCK_RUNTIME': data['runtime'],
         },
     }
     # merge runtime
     self.merge(runtime_config, self.data)
     # merge runtime config
     self.merge(rock_config, self.data)
     self.merge(etc_config, self.data)
     # merge project
     self.merge(data, self.data)
Esempio n. 2
0
 def parse(path, require_exists=True, require_parses=True):
     """
     Parse and return configuration file.
     """
     if not os.path.isfile(path):
         if require_exists:
             raise ConfigError('not found: ' + path)
         return
     try:
         with open(path) as f:
             return yaml.safe_load(f)
     except Exception as error:
         if require_parses:
             raise ConfigError('parse error: ' + path)
Esempio n. 3
0
 def merge_env(self, src, dst, env=None):
     """
     Merge environment variables.
     """
     env = 'env_%s' % env if env else 'env'
     if env in src:
         if not isinstance(src[env], dict):
             raise ConfigError('%s must be an associative array' % env)
         # evaluate env variables
         for name, value in src[env].items():
             if not isstr(value):
                 if isinstance(value, (int, float)):
                     src[env][name] = str(value)
                 else:
                     raise ConfigError('%s.%s must be a string' %
                                       (env, name))
             dst['env'][name] = string.Template(
                 src[env][name]).safe_substitute(**dst['env'])
         del src[env]
Esempio n. 4
0
 def merge(self, src, dst):
     if src is None:
         return dst
     # merge global environment variables
     self.merge_env(src, dst)
     # merge env-specific environment variables
     self.merge_env(src, dst, self.env)
     # merge sections
     for name in list(src.keys()):
         if name not in dst:
             if isstr(src[name]):
                 src[name] = PARENT_RE.sub('', src[name])
             elif isinstance(src[name], dict):
                 for subname in src[name]:
                     value = src[name][subname]
                     if isstr(value):
                         src[name][subname] = PARENT_RE.sub('', value)
             dst[name] = src[name]
         elif isstr(src[name]):
             if not isstr(dst[name]):
                 raise ConfigError('unable to merge "%s" into "str"' %
                                   type(dst[name]).__name__)
             dst[name] = PARENT_RE.sub(raw(dst[name]), src[name])
         elif isinstance(src[name], dict):
             dst_is_dict = isinstance(dst[name], dict)
             for subname in src[name]:
                 if isstr(dst[name]):
                     src[name][subname] = PARENT_RE.sub(raw(dst[name]),
                                                        src[name][subname])
                 elif dst_is_dict:
                     if subname in dst[name]:
                         src[name][subname] = PARENT_RE.sub(
                             raw(dst[name][subname]),
                             src[name][subname],
                         )
                         del dst[name][subname]
                     else:
                         src[name][subname] = PARENT_RE.sub(
                             '',
                             src[name][subname],
                         )
             if dst_is_dict:
                 src[name].update(dst[name])
             dst[name] = src[name]
         del src[name]
     dst.update(src)
Esempio n. 5
0
 def evaluate(data):
     changed = False
     for _ in range(5):
         changed = False
         for n1, v1 in data.items():
             if not isstr(v1):
                 continue
             n = re.escape(n1)
             r = re.compile(r'\{\{\s*' + n + r'\s*\}\}', re.MULTILINE)
             for n2, v2 in data.items():
                 if not isstr(v2):
                     continue
                 data[n2] = r.sub(raw(data[n1]), data[n2]).rstrip('\n')
                 changed |= v2 != data[n2]
         if not changed:
             break
     if changed:
         raise ConfigError('.rock.yml circular reference')
Esempio n. 6
0
 def run(self):
     if not isexecutable(ROCK_SHELL[0]):
         raise ConfigError('invalid ROCK_SHELL: %s' % ROCK_SHELL)
     os.execl(*(ROCK_SHELL + [self.stdin.getvalue()]))
Esempio n. 7
0
 def check():
     if section not in self.config:
         raise ConfigError('section not found: %s' % section)
     if not isstr(self.config[section]):
         raise ConfigError('section must be a string: %s' % section)