def get_config(config_path=None): """reads the config file, validates it and return a config dict :param config_path: path to a custom config file, if none is given the default locations will be searched :type config_path: str :returns: configuration :rtype: dict """ if config_path is None: config_path = _find_configuration_file() logger.debug('using the config file at {}'.format(config_path)) config = ConfigObj(DEFAULTSPATH, interpolation=False) try: user_config = ConfigObj(config_path, configspec=SPECPATH, interpolation=False, file_error=True, ) except ConfigObjError as error: logger.fatal('parsing the config file file with the following error: ' '{}'.format(error)) logger.fatal('if you recently updated khal, the config file format ' 'might have changed, in that case please consult the ' 'CHANGELOG or other documentation') sys.exit(1) fdict = {'timezone': is_timezone, 'expand_path': expand_path, } validator = Validator(fdict) results = user_config.validate(validator, preserve_errors=True) if not results: for entry in flatten_errors(config, results): # each entry is a tuple section_list, key, error = entry if key is not None: section_list.append(key) else: section_list.append('[missing section]') section_string = ', '.join(section_list) if error is False: error = 'Missing value or section.' print(section_string, ' = ', error) raise ValueError # TODO own error class config.merge(user_config) config_checks(config) extras = get_extra_values(user_config) for section, value in extras: if section == (): logger.warn('unknown section "{}" in config file'.format(value)) else: section = sectionize(section) logger.warn('unknown key or subsection "{}" in ' 'section "{}"'.format(value, section)) return config
def prepare_context(ctx, config, verbose): if ctx.obj is not None: return if verbose: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) ctx.obj = {} try: ctx.obj['conf'] = conf = get_config(config) except InvalidSettingsError: sys.exit(1) logger.debug('Using config:') logger.debug(to_unicode(stringify_conf(conf), 'utf-8')) if conf is None: raise click.UsageError('Invalid config file, exiting.')
def dump(self, conf, intro='Using configuration:', tab=0): """Dump the loaded configuration using the logging framework. The values displayed here are the exact values which are seen by the program, and not the raw values as they are read in the configuration file. """ # TODO while this is fully functional it could be prettier logger.debug('{0}{1}'.format('\t' * tab, intro)) if isinstance(conf, (Namespace, dict)): for name, value in sorted(dict.copy(conf).items()): if isinstance(value, (Namespace, dict, list)): self.dump(value, '[' + name + ']', tab=tab + 1) else: logger.debug('{0}{1}: {2}'.format('\t' * (tab + 1), name, value)) elif isinstance(conf, list): for o in conf: self.dump(o, '\t' * tab + intro + ':', tab + 1)
def prepare_context(ctx, config, verbose): if ctx.obj is not None: return if verbose: logger.setLevel(logging.DEBUG) else: logger.setLevel(logging.INFO) ctx.obj = {} try: ctx.obj['conf'] = conf = get_config(config) except InvalidSettingsError: sys.exit(1) out = StringIO() conf.write(out) logger.debug('Using config:') logger.debug(out.getvalue()) if conf is None: raise click.UsageError('Invalid config file, exiting.')
def prepare_context(ctx, config): assert ctx.obj is None ctx.obj = {} try: ctx.obj['conf'] = conf = get_config(config) except InvalidSettingsError: sys.exit(1) logger.debug('khal %s' % __version__) logger.debug('Using config:') logger.debug(to_unicode(stringify_conf(conf), 'utf-8')) if conf is None: raise click.UsageError('Invalid config file, exiting.')
def prepare_context(ctx, config): assert ctx.obj is None ctx.obj = {} try: ctx.obj['conf'] = conf = get_config(config) except InvalidSettingsError: sys.exit(1) logger.debug('khal %s' % __version__) logger.debug('Using config:') logger.debug(stringify_conf(conf)) if conf is None: raise click.UsageError('Invalid config file, exiting.')
def write(text): logger.debug('{}{}'.format(_tab * _tabchar, text))
def khal_list(collection, daterange=None, conf=None, agenda_format=None, day_format=None, once=False, notstarted=False, width=False, env=None, datepoint=None): assert daterange is not None or datepoint is not None """returns a list of all events in `daterange`""" # because empty strings are also Falsish if agenda_format is None: agenda_format = conf['view']['agenda_event_format'] if daterange is not None: if day_format is None: day_format = conf['view']['agenda_day_format'] start, end = start_end_from_daterange( daterange, conf['locale'], default_timedelta_date=conf['default']['timedelta'], default_timedelta_datetime=conf['default']['timedelta'], ) logger.debug('Getting all events between {} and {}'.format(start, end)) elif datepoint is not None: if not datepoint: datepoint = ['now'] try: start, allday = utils.guessdatetimefstr(datepoint, conf['locale'], date.today()) except ValueError: raise FatalError('Invalid value of `{}` for a datetime'.format( ' '.join(datepoint))) if allday: logger.debug('Got date {}'.format(start)) raise FatalError('Please supply a datetime, not a date.') end = start + timedelta(seconds=1) if day_format is None: day_format = style( start.strftime(conf['locale']['longdatetimeformat']), bold=True, ) logger.debug('Getting all events between {} and {}'.format(start, end)) event_column = [] once = set() if once else None if env is None: env = {} original_start = conf['locale']['local_timezone'].localize(start) while start < end: if start.date() == end.date(): day_end = end else: day_end = datetime.combine(start.date(), time.max) current_events = get_events_between( collection, locale=conf['locale'], agenda_format=agenda_format, start=start, end=day_end, notstarted=notstarted, original_start=original_start, env=env, seen=once, width=width, ) if day_format and (conf['default']['show_all_days'] or current_events): event_column.append( format_day(start.date(), day_format, conf['locale'])) event_column.extend(current_events) start = datetime(*start.date().timetuple()[:3]) + timedelta(days=1) if event_column == []: event_column = [style('No events', bold=True)] return event_column
def main_khal(): capture_user_interruption() # setting the process title so it looks nicer in ps # shows up as 'khal' under linux and as 'python: khal (python2.7)' # under FreeBSD, which is still nicer than the default setproctitle('khal') arguments = docopt(__doc__, version=__productname__ + ' ' + __version__, options_first=False) if arguments['-v']: logger.setLevel(logging.DEBUG) logger.debug('this is {} version {}'.format(__productname__, __version__)) conf = get_config(arguments['-c']) out = StringIO.StringIO() conf.write(out) logger.debug('using config:') logger.debug(out.getvalue()) collection = khalendar.CalendarCollection() for name, cal in conf['calendars'].items(): if (name in arguments['-a'] and arguments['-d'] == list()) or \ (name not in arguments['-d'] and arguments['-a'] == list()): collection.append(khalendar.Calendar( name=name, dbpath=conf['sqlite']['path'], path=cal['path'], readonly=cal['readonly'], color=cal['color'], unicode_symbols=conf['locale']['unicode_symbols'], local_tz=conf['locale']['local_timezone'], default_tz=conf['locale']['default_timezone'] )) collection._default_calendar_name = conf['default']['default_calendar'] commands = ['agenda', 'calendar', 'new', 'interactive', 'printcalendars'] if not any([arguments[com] for com in commands]): arguments = docopt(__doc__, version=__productname__ + ' ' + __version__, argv=[conf['default']['default_command']] + sys.argv[1:]) days = int(arguments['--days']) if arguments['--days'] else None events = int(arguments['--events']) if arguments['--events'] else None if arguments['calendar']: controllers.Calendar(collection, date=arguments['DATE'], firstweekday=conf['locale']['firstweekday'], encoding=conf['locale']['encoding'], dateformat=conf['locale']['dateformat'], longdateformat=conf['locale']['longdateformat'], days=days, events = events) elif arguments['agenda']: controllers.Agenda(collection, date=arguments['DATE'], firstweekday=conf['locale']['firstweekday'], encoding=conf['locale']['encoding'], dateformat=conf['locale']['dateformat'], longdateformat=conf['locale']['longdateformat'], days=days, events=events) elif arguments['new']: controllers.NewFromString(collection, conf, arguments['DESCRIPTION']) elif arguments['interactive']: controllers.Interactive(collection, conf) elif arguments['printcalendars']: print('\n'.join(collection.names))