Beispiel #1
0
    def from_conf(cls, path=None, **overrides):
        '''Initialize instance from YAML configuration file,
            writing updates (only to keys, specified by "conf_update_keys") back to it.'''
        from skydrive import portalocker
        import yaml

        if path is None:
            path = cls.conf_path_default
            log.debug('Using default state-file path: {}'.format(path))
        path = os.path.expanduser(path)
        with open(path) as src:
            portalocker.lock(src, portalocker.LOCK_SH)
            #conf = yaml.load("client:\n  id: 000000004C0F20A9\n  secret:  HgkEDnsuysRqhpe3s3vyvznzrMOlTaCo\n")
            conf = yaml.load(src)
            portalocker.unlock(src)

        conf.setdefault('conf_save', path)

        conf_cls = dict()
        for ns, keys in cls.conf_update_keys.viewitems():
            for k in keys:
                try:
                    v = conf.get(ns, dict()).get(k)
                except AttributeError:
                    if not cls.conf_raise_structure_errors: raise
                    raise KeyError('Unable to get value for configuration parameter'
                                   ' "{k}" in section "{ns}", check configuration file (path: {path}) syntax'
                                   ' near the aforementioned section/value.'.format(ns=ns, k=k, path=path))
                if v is not None:
                    conf_cls['{}_{}'.format(ns, k)] = conf[ns][k]
        conf_cls.update(overrides)

        self = cls(**conf_cls)
        self.conf_save = conf['conf_save']
        return self
Beispiel #2
0
    def from_conf(cls, path=None, **overrides):
        '''Initialize instance from YAML configuration file,
            writing updates (only to keys, specified by "conf_update_keys") back to it.'''
        from skydrive import portalocker
        import yaml

        if path is None:
            path = cls.conf_path_default
            log.debug('Using default state-file path: {}'.format(path))
        path = os.path.expanduser(path)
        with open(path) as src:
            portalocker.lock(src, portalocker.LOCK_SH)
            conf = yaml.load(src.read())
            portalocker.unlock(src)
        conf.setdefault('conf_save', path)

        conf_cls = dict()
        for ns, keys in cls.conf_update_keys.viewitems():
            for k in keys:
                try:
                    v = conf.get(ns, dict()).get(k)
                except AttributeError:
                    if not cls.conf_raise_structure_errors: raise
                    raise KeyError(
                        'Unable to get value for configuration parameter'
                        ' "{k}" in section "{ns}", check configuration file (path: {path}) syntax'
                        ' near the aforementioned section/value.'.format(
                            ns=ns, k=k, path=path))
                if v is not None:
                    conf_cls['{}_{}'.format(ns, k)] = conf[ns][k]
        conf_cls.update(overrides)

        self = cls(**conf_cls)
        self.conf_save = conf['conf_save']
        return self
Beispiel #3
0
    def sync(self):
        if not self.conf_save: 
            conf_updated = False
            conf = self.conf
            for ns, keys in self.conf_update_keys.viewitems():
                for k in keys:
                    v = getattr(self, '{}_{}'.format(ns, k), None)
                    if isinstance(v, unicode): v = v.encode('utf-8')
                    if v != conf.get(ns, dict()).get(k):
                        # log.debug(
                        # 	'Different val ({}.{}): {!r} != {!r}'\
                            # 	.format(ns, k, v, conf.get(ns, dict()).get(k)) )
                        conf.setdefault(ns, dict())[k] = v
                        conf_updated = True

            if conf_updated:
                self.conf = conf
            return conf

        from skydrive import portalocker
        import yaml


        retry = False
        with open(self.conf_save, 'r+') as src:
            portalocker.lock(src, portalocker.LOCK_SH)
            conf_raw = src.read()
            conf = yaml.load(io.BytesIO(conf_raw)) if conf_raw else dict()
            portalocker.unlock(src)

            conf_updated = False
            for ns, keys in self.conf_update_keys.viewitems():
                for k in keys:
                    v = getattr(self, '{}_{}'.format(ns, k), None)
                    if isinstance(v, unicode): v = v.encode('utf-8')
                    if v != conf.get(ns, dict()).get(k):
                        # log.debug(
                        # 	'Different val ({}.{}): {!r} != {!r}'\
                        # 	.format(ns, k, v, conf.get(ns, dict()).get(k)) )
                        conf.setdefault(ns, dict())[k] = v
                        conf_updated = True

            if conf_updated:
                log.debug('Updating configuration file ({})'.format(src.name))
                with tempfile.NamedTemporaryFile(
                        prefix='{}.'.format(basename(self.conf_save)),
                        dir=dirname(self.conf_save), delete=False) as tmp:
                    try:
                        portalocker.lock(tmp, portalocker.LOCK_EX)
                        yaml.safe_dump(conf, tmp, default_flow_style=False)
                        tmp.flush()
                        try:
                            os.fchmod(tmp.fileno(),
                                      stat.S_IMODE(os.fstat(src.fileno()).st_mode))
                        except AttributeError:
                            pass
                        portalocker.lock(src, portalocker.LOCK_EX)
                        src.seek(0)
                        if src.read() != conf_raw:
                            retry = True
                        else:
                            # Atomic update
                            try: os.rename(tmp.name, src.name)
                            except WindowsError: pass
                            # Non-atomic update for pids that already have fd to old file,
                            #  but (presumably) are waiting for the write-lock to be released
                            src.seek(0), tmp.seek(0)
                            src.truncate()
                            src.write(tmp.read())
                            src.flush()
                    finally:
                        portalocker.unlock(tmp)
                        portalocker.unlock(src)
                        try:
                            os.unlink(tmp.name)
                        except OSError:
                            pass

        if retry:
            log.debug(( 'Configuration file ({}) was changed'
                        ' during merge, restarting merge' ).format(self.conf_save))
            return self.sync()
Beispiel #4
0
    def sync(self):
        if not self.conf_save:
            conf_updated = False
            conf = self.conf
            for ns, keys in self.conf_update_keys.viewitems():
                for k in keys:
                    v = getattr(self, '{}_{}'.format(ns, k), None)
                    if isinstance(v, unicode): v = v.encode('utf-8')
                    if v != conf.get(ns, dict()).get(k):
                        # log.debug(
                        # 	'Different val ({}.{}): {!r} != {!r}'\
                        # 	.format(ns, k, v, conf.get(ns, dict()).get(k)) )
                        conf.setdefault(ns, dict())[k] = v
                        conf_updated = True

            if conf_updated:
                self.conf = conf
            return conf

        from skydrive import portalocker
        import yaml

        retry = False
        with open(self.conf_save, 'r+') as src:
            portalocker.lock(src, portalocker.LOCK_SH)
            conf_raw = src.read()
            conf = yaml.load(io.BytesIO(conf_raw)) if conf_raw else dict()
            portalocker.unlock(src)

            conf_updated = False
            for ns, keys in self.conf_update_keys.viewitems():
                for k in keys:
                    v = getattr(self, '{}_{}'.format(ns, k), None)
                    if isinstance(v, unicode): v = v.encode('utf-8')
                    if v != conf.get(ns, dict()).get(k):
                        # log.debug(
                        # 	'Different val ({}.{}): {!r} != {!r}'\
                        # 	.format(ns, k, v, conf.get(ns, dict()).get(k)) )
                        conf.setdefault(ns, dict())[k] = v
                        conf_updated = True

            if conf_updated:
                log.debug('Updating configuration file ({})'.format(src.name))
                with tempfile.NamedTemporaryFile(prefix='{}.'.format(
                        basename(self.conf_save)),
                                                 dir=dirname(self.conf_save),
                                                 delete=False) as tmp:
                    try:
                        portalocker.lock(tmp, portalocker.LOCK_EX)
                        yaml.safe_dump(conf, tmp, default_flow_style=False)
                        tmp.flush()
                        try:
                            os.fchmod(
                                tmp.fileno(),
                                stat.S_IMODE(os.fstat(src.fileno()).st_mode))
                        except AttributeError:
                            pass
                        portalocker.lock(src, portalocker.LOCK_EX)
                        src.seek(0)
                        if src.read() != conf_raw:
                            retry = True
                        else:
                            # Atomic update
                            try:
                                os.rename(tmp.name, src.name)
                            except WindowsError:
                                pass
                            # Non-atomic update for pids that already have fd to old file,
                            #  but (presumably) are waiting for the write-lock to be released
                            src.seek(0), tmp.seek(0)
                            src.truncate()
                            src.write(tmp.read())
                            src.flush()
                    finally:
                        portalocker.unlock(tmp)
                        portalocker.unlock(src)
                        try:
                            os.unlink(tmp.name)
                        except OSError:
                            pass

        if retry:
            log.debug(
                ('Configuration file ({}) was changed'
                 ' during merge, restarting merge').format(self.conf_save))
            return self.sync()