diff options
author | Tobias Brox <tobias@redpill-linpro.com> | 2022-12-03 20:22:09 +0100 |
---|---|---|
committer | Tobias Brox <tobias@redpill-linpro.com> | 2022-12-03 20:22:09 +0100 |
commit | f8ed2e12c456abed6ce491f92e4e9784f9d0cf50 (patch) | |
tree | cacc665bfcbac9a05404c16ccd5d1cc4378050a3 | |
parent | cfea5bde72e2d28ff7d409e40f51fa6e6f2b3a7a (diff) | |
download | calendar-cli-f8ed2e12c456abed6ce491f92e4e9784f9d0cf50.zip |
more work on configuration and misc
-rw-r--r-- | README.md | 51 | ||||
-rw-r--r-- | USER_GUIDE.md | 30 | ||||
-rwxr-xr-x | calendar_cli/cal.py | 65 | ||||
-rwxr-xr-x | calendar_cli/legacy.py | 3 |
4 files changed, 127 insertions, 22 deletions
@@ -127,7 +127,7 @@ The file TASK_MANAGEMENT.md contains some thoughts on how to organize tasks. Configuration file ------------------ -Configuration file is by default located in $HOME/.config/calendar.conf and should be in json syntax. You may run `calendar-cli --interactive-config` if you don't feel comfortable with hand-crafting configuration in json syntax, though this feature is not tested regularly. +Configuration file is by default located in $HOME/.config/calendar.conf. calendar-cli expects it to be in json syntax, kal also accepts yaml format. You may run `calendar-cli --interactive-config` if you don't feel comfortable with hand-crafting configuration in json syntax, though this feature is not tested regularly. (I considered a configuration file in .ini-format, having a "default"-section with default values for any global options, and optionally other sections for different CalDAV-servers. Asking a bit around for recommendations on config file format as well as location, I was told that the .ini-format is not a standard, I'd be better off using a standard like yaml, json or xml. Personally I like json a bit better than yaml - after consulting with a friend I ended up with json. Location ... I think it's "cleaner" to keep it in ~/.config/, and I'd like any calendar application to be able to access the file, hence it got ~/.config/calendar.conf rather than ~/.calendar-cli.conf) @@ -158,7 +158,54 @@ A configuration with multiple sections may look like this: } ``` -Optionally, in addition (or even instead) of "default", other "sections" can be created and selected through the --config-section option. The rationale is to allow configuration for multiple CalDAV-servers, or multiple calendars on the same CalDAV-server to remain in the same configuration file. Later versions will eventually be capable of copying events, or putting events into several calendars. +Sections may also include calendar urls or ids, and sections may inherit other sections: + +```json +{ +"default": + { "caldav_url": "http://foo.bar.example.com/caldav/", + "caldav_user": "luser", + "caldav_pass": "insecure" + }, +"baz": + { "caldav_url": "http://foo.baz.example.com/caldav/", + "caldav_user": "luser2", + "caldav_pass": "insecure2" + } +}, +"bazimportant": + { "inherits": "baz", + "calendar_url": "important" + } +``` + +kal also accepts `calendar_name`, which should match with the display name. + +kal may operate at many calendars at one time, hence it's possible to make a section refer to multiple other sections, like this: + +```yaml +--- +work-calendar: + caldav_url: "http://acme.example.com/caldav/" + caldav_user: drjekyll + caldav_pass: pencilin + calendar_url: mycalendar +work-appointments: + inherits: work-calendar + calendar_url: mypatients +private-calendar: + caldav_url: "https://ecloud.global/remote.php/dav/" + caldav_user: myhyde + caldav_pass: hunter2 + calendar_name: goodgames +sinuous-deeds: + inheritate private-calendar + calendar_name: badgames +work: + contains: [ 'work-calendar', 'work-appointments' ] +private: + contains: [ 'privat-calendar', 'sinous-deeds' ] +``` Remember to `chmod og-r ~/.config/calendar.conf` or `chmod 0600 ~/.config/calendar.conf` diff --git a/USER_GUIDE.md b/USER_GUIDE.md index 50a4a4f..fcfc10a 100644 --- a/USER_GUIDE.md +++ b/USER_GUIDE.md @@ -20,7 +20,7 @@ kal command subcommand --help ## Main commands -* test - verify that it's possible to connect to the server +* list-calendars - verify that it's possible to connect to the server(s) and show the calendar(s) selected * add - for adding things to the calendar(s) * select - for selecting, viewing, editing and deleting things from the calendar(s). @@ -36,7 +36,33 @@ It's recommended to rather use a config file (though not yet supported as of 202 * `--config-file` * `--config-section` -The default (though not yet supported as of 2022-10-09) is to utilize the `default` section under `$HOME/.config/calendar.conf` +The default is to utilize the `default` section under `$HOME/.config/calendar.conf` Here is an example configuration file: + +```yaml +--- +work-calendar: + caldav_url: "http://acme.example.com/caldav/" + caldav_user: drjekyll + caldav_pass: pencilin + calendar_url: mycalendar +work-appointments: + inherits: work-calendar + calendar_url: mypatients +private-calendar: + caldav_url: "https://ecloud.global/remote.php/dav/" + caldav_user: myhyde + caldav_pass: hunter2 + calendar_name: goodgames +sinuous-deeds: + inheritate private-calendar + calendar_name: badgames +work: + contains: [ 'work-calendar', 'work-appointments' ] +private: + contains: [ 'privat-calendar', 'sinous-deeds' ] +``` + +(TODO: the example above haven't been tested) Multiple config sections can be specified, which may be useful for selecting things from multiple calendars. diff --git a/calendar_cli/cal.py b/calendar_cli/cal.py index 3f54dbd..8be1b60 100755 --- a/calendar_cli/cal.py +++ b/calendar_cli/cal.py @@ -34,7 +34,7 @@ import logging import re from icalendar import prop, Timezone from calendar_cli.template import Template -from calendar_cli.config import interactive_config, config_section, read_config +from calendar_cli.config import interactive_config, config_section, read_config, expand_config_section list_type = list @@ -142,7 +142,7 @@ def parse_timespec(timespec): raise NotImplementedError("possibly a ISO time interval") -def find_calendars(args): +def find_calendars(args, raise_errors): def list_(obj): """ For backward compatibility, a string rather than a list can be given as @@ -154,6 +154,18 @@ def find_calendars(args): obj = [ obj ] return obj + def _try(meth, kwargs, errmsg): + try: + ret = meth(**kwargs) + assert(ret) + return ret + except: + logging.error("Problems fetching calendar information: %s - skipping" % errmsg) + if raise_errors: + raise + else: + return None + conn_params = {} for k in args: if k.startswith('caldav_') and args[k]: @@ -166,27 +178,37 @@ def find_calendars(args): calendars = [] if conn_params: client = caldav.DAVClient(**conn_params) - principal = client.principal() + principal = _try(client.principal, {}, conn_params['url']) + if not principal: + return [] calendars = [] + tries = 0 for calendar_url in list_(args.get('calendar_url')): - calendars.append(principal.calendar(cal_id=calendar_url)) + calendar=principal.calendar(cal_id=calendar_url) + tries += 1 + if _try(calendar.get_display_name, {}, calendar.url): + calendars.append(calendar) for calendar_name in list_(args.get('calendar_name')): - calendars.append(principal.calendar(name=calendar_name)) - if not calendars: - calendars = principal.calendars() - return calendars + tries += 1 + calendar = _try(principal.calendar, {'name': calendar_name}, '%s : calendar "%s"' % (conn_params['url'], calendar_name)) + calendars.append(calendar) + if not calendars and tries == 0: + calendars = _try(principal.calendars, {}, "conn_params['url'] - all calendars") + return calendars or [] @click.group() ## TODO: interactive config building ## TODO: language and timezone @click.option('-c', '--config-file', default=f"{os.environ['HOME']}/.config/calendar.conf") +@click.option('--skip-config/--read-config', help="Skip reading the config file") @click.option('--config-section', default=["default"], multiple=True) @click.option('--caldav-url', help="Full URL to the caldav server", metavar='URL') @click.option('--caldav-username', '--caldav-user', help="Full URL to the caldav server", metavar='URL') @click.option('--caldav-password', '--caldav-pass', help="Full URL to the caldav server", metavar='URL') @click.option('--calendar-url', help="Calendar id, path or URL", metavar='cal', multiple=True) @click.option('--calendar-name', help="Calendar name", metavar='cal', multiple=True) +@click.option('--raise-errors/--print-errors', help="Raise errors found on calendar discovery") @click.pass_context def cli(ctx, **kwargs): """ @@ -204,22 +226,33 @@ def cli(ctx, **kwargs): ## TODO: delayed communication with caldav server (i.e. if --help is given to subcommand) ## TODO: catch errors, present nice error messages conns = [] - ctx.obj['calendars'] = find_calendars(kwargs) - config = read_config(kwargs['config_file']) - if config: - for section in kwargs['config_section']: - ctx.obj['calendars'].extend(find_calendars(config_section(config, section))) + ctx.obj['calendars'] = find_calendars(kwargs, kwargs['raise_errors']) + if not kwargs['skip_config']: + config = read_config(kwargs['config_file']) + if config: + for meta_section in kwargs['config_section']: + for section in expand_config_section(config, meta_section): + ctx.obj['calendars'].extend(find_calendars(config_section(config, section), raise_errors=kwargs['raise_errors'])) + +@cli.command() +@click.pass_context +def interactive_config(ctx): + raise NotImplementedError() @cli.command() @click.pass_context -def test(ctx): +def list_calendars(ctx): """ - Will test that we can connect to the caldav server and find the calendars. + Will output all calendars found """ if not ctx.obj['calendars']: _abort("No calendars found!") else: - click.echo("Seems like everything is OK") + output = "Accessible calendars found:\n" + calendar_info = [(x.get_display_name(), x.url) for x in ctx.obj['calendars']] + max_display_name = max([len(x[0]) for x in calendar_info]) + format_str= "%%-%ds %%s" % max_display_name + click.echo_via_pager(output + "\n".join([format_str % x for x in calendar_info]) + "\n") def _set_attr_options_(func, verb): """ diff --git a/calendar_cli/legacy.py b/calendar_cli/legacy.py index cf17bd5..6e15715 100755 --- a/calendar_cli/legacy.py +++ b/calendar_cli/legacy.py @@ -11,7 +11,6 @@ Copyright (C) 2013-2022 Tobias Brox and other contributors. See https://www.gnu.org/licenses/gpl-3.0.en.html for license information. """ - import argparse import tzlocal ## we still need to use pytz, see https://github.com/collective/icalendar/issues/333 @@ -26,7 +25,7 @@ from datetime import time as time_ import dateutil.parser from dateutil.rrule import rrulestr from icalendar import Calendar,Event,Todo,Journal,Alarm -from calendar_cli.config import interactive_config, config_section +from calendar_cli.config import interactive_config, config_section, read_config import vobject import caldav import uuid |