diff options
-rw-r--r-- | INSTALL.md | 4 | ||||
-rw-r--r-- | README.md | 52 | ||||
-rwxr-xr-x | calendar-cli.py | 36 | ||||
-rw-r--r-- | setup.py | 52 |
4 files changed, 127 insertions, 17 deletions
@@ -6,6 +6,6 @@ No packaging available yet; it's just to copy the python executable into the pat There are two dependencies; * icalendar library - I've used https://pypi.python.org/pypi/icalendar -* caldav library - I've used http://trac.calendarserver.org/wiki/CalDAVClientLibrary (perhaps https://pypi.python.org/pypi/caldav would be a better option?) +* caldav library - I've used http://trac.calendarserver.org/wiki/CalDAVClientLibrary - but I'm strongly considering to switch to https://pypi.python.org/pypi/caldav -Both of those are under development, and has to be installed manually. +All of those are under development and has to be installed manually. @@ -3,6 +3,19 @@ calendar-cli Simple command-line CalDav client, for adding and browsing calendar items, todo list items, etc +Support +------- + +#calendar-cli at irc.freenode.org + +Status +------ + +This is work in progress. Writing to calendars seems to work, and I'm using it actively for adding stuff to my calendars - taking out the agenda is not completed yet. + +This is written in python2 as some of the libraries being used aren't +available in python3. + Rationale --------- @@ -18,7 +31,7 @@ Synopsis calendar-cli.py [global options] [command] [command options] [subcommand] [subcommand options] [subcommand arguments] ... -cli.py should be symlinked to the various commands. +I'm intending to make it easier by allowing calendar-cli.py to be symlinked to the various commands. ### Global options @@ -30,22 +43,25 @@ Always consult --help for up-to-date and complete listings of options. The list below will only contain the most important options and may not be up-to-date and may contain features not implemented yet. -* --interactive, -i: stop and query the user rather often +* --interactive: stop and query the user rather often * --caldav-url, --caldav-user, --caldav-pass: how to connect to the CalDAV server. Fits better into a configuration file. * --config-file: use a specific configuration file (default: $HOME/.calendar-cli.conf) * --config-section: use a specific section from the config file (i.e. to select a different caldav-server to connect to) -* --icalendar: instead of connecting to a CalDAV server, write an icalendar file to stdout +* --icalendar: Write or read icalendar to/from stdout/stdin +* --nocaldav: don't connect to a caldav server ### Commands * cal - access/modify a calendar - * subcommands: add, agenda + * subcommands: add, addics (for uploading events in ical format), agenda * todo - access/modify a todo-list * subcommands: add, agenda +(only "cal add" and "cal addics" works as of v0.06 / 2013-12-02) + ### Event time specification -Supported in v0.01: +Supported in v0.06: * anything recognized by dateutil.parser.parse() @@ -58,7 +74,7 @@ All of those would eventually be supported in future versions if it's not too di * weekday instead of an ISO date * clock time without the date; event will be assumed to start within 24 hours. -Alternatively, endtime or duration can be given through options. +Alternatively, endtime or duration can be given through options (not supported as of 0.06. All events are considered to be one hour long). Configuration file ------------------ @@ -96,6 +112,7 @@ Objectives * It should be possible to get out lists ("agenda") of calendar items and todo-items. * Interface for copying calendar items between calendars, even between calendars on distinct caldav servers +<<<<<<< HEAD Milestones ---------- @@ -119,3 +136,26 @@ Status 2013-10-05: version 0.04 - no need to specify URL for the default calendar 2013-12 - 2014-03: helped cyrilrbt on making a new release of the caldav library 2014-03-07: version 0.05 - rewrote parts of the tool to using the caldav library. Nice!!! +======= +Roadmap +------- +* Allow specification of event duration when adding events to calendar +* Show agenda. Hope to have this in place during January 2014. (I've obeen hitting a snag in the underlying library, and will probably have to replace it). +* Delete events. Needed for making a functional test suite. +* Fix a functional test suite. +* CLI-interface for creating ical todo events +* Wrap it into an easy-to-install package +* Fix easy-to-use symlinks + +History +------- + +* 2013-09-15: Made a repository at github and wrote up this README. +* 2013-09-24: version 0.01 - supports creating an ical-file based on command line parameters +* 2013-09-28: version 0.02 - possible to add a calendar item to the caldav server +* 2013-10-02: version 0.03 - support for configuration file +* 2013-10-05: version 0.04 - no need to specify URL for the default calendar +* 2013-10-10: Attempts on implementing "agenda" stalled a bit due to problems with the library used. Considering to switch library. +* 2013-11-30: version 0.05 - added the calendar "addics" command for adding an ics file +* 2013-12-02: Some merging of work between the "agenda" branch and the master branch; causing a minor API change (new option --nocaldav has to be specified if running the utility without connecting to a caldav server) +>>>>>>> master diff --git a/calendar-cli.py b/calendar-cli.py index 4985e25..8961356 100755 --- a/calendar-cli.py +++ b/calendar-cli.py @@ -5,6 +5,7 @@ import argparse import urlparse import pytz +import tzlocal from datetime import datetime, timedelta import dateutil.parser from icalendar import Calendar,Event @@ -15,7 +16,7 @@ import os import logging import sys -__version__ = "0.5.1" +__version__ = "0.6.1" __author__ = "Tobias Brox" __author_short__ = "tobixen" __copyright__ = "Copyright 2013, Tobias Brox" @@ -35,7 +36,6 @@ def caldav_connect(args): # Create the account return caldav.DAVClient(url=args.caldav_url, username=args.caldav_user, password=args.caldav_pass) -## TODO def find_calendar(caldav_conn, args): if args.calendar_url: if '/' in args.calendar_url: @@ -107,9 +107,8 @@ def calendar_add(caldav_conn, args): cal = Calendar() cal.add('prodid', '-//{author_short}//{product}//{language}'.format(author_short=__author_short__, product=__product__, language=args.language)) cal.add('version', '2.0') - if args.timezone: - tz = pytz.timezone(args.timezone) event = Event() + ## TODO: timezone ## read timestamps from arguments dtstart = dateutil.parser.parse(args.event_time) event.add('dtstart', dtstart) @@ -138,14 +137,28 @@ def calendar_agenda(caldav_conn, args): dtend = dtstart + timedelta(1,0) ## TODO: time zone ## No need with "expand" - as for now the method below throws away the expanded data :-( We get a list of URLs, and then we need to do a get on each and one of them ... - events = caldav_conn.date_search(dtstart, dtend) + events_ = find_calendar(caldav_conn, args).date_search(dtstart, dtend) + events = [] if args.icalendar: - for ical in events: + for ical in events_: print ical.data else: - import pdb; pdb.set_trace() - events = [Calendar.from_ical(event.data) for event in events] - niy("parse calendar events and print them in a nice format") + ## flatten. A recurring event may be a list of events. + for event_cal in events_: + for event in event_cal.instance.components(): + dtstart = event.dtstart.value + if not dtstart.tzinfo: + dtstart = args.timezone.localize(dtstart) + events.append({'dtstart': dtstart, 'instance': event}) + events.sort(lambda a,b: cmp(a['dtstart'], b['dtstart'])) + for event in events: + dtime = event['dtstart'].strftime("%F %H:%M") + summary = "" + for summary_attr in ('summary', 'location'): + if hasattr(event['instance'], summary_attr): + summary = getattr(event['instance'], summary_attr).value + break + print "%s %s" % (dtime, summary) def main(): ## This boilerplate pattern is from @@ -223,6 +236,11 @@ def main(): todo_parser.set_defaults(func=niy) args = parser.parse_args(remaining_argv) + if args.timezone: + args.timezone = pytz.timezone(args.timezone) + else: + args.timezone = tzlocal.get_localzone() + if not args.nocaldav: caldav_conn = caldav_connect(args) diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..9fecdd9 --- /dev/null +++ b/setup.py @@ -0,0 +1,52 @@ +#!/usr/bin/env python + +import sys +import os + +try: + from setuptools import setup +except ImportError: + from distutils.core import setup + + +setup( + name='calendar-cli', + version='0.1', + description='Simple command-line CalDav client, for adding and browsing calendar items, todo list items, etc.', + url='https://github.com/tobixen/calendar-cli', + #packages=['', + # ], + license='GPLv3+', + author='Tobias Brox', + author_email='t-calendar-cli@tobixen.no', + classifiers=[ + #"Development Status :: 5 - Production/Stable", + "Environment :: Web Environment", + "Intended Audience :: Developers", + #"License :: OSI Approved :: Apache Software License", + "Operating System :: POSIX", + "Programming Language :: Python", + "Topic :: Internet :: WWW/HTTP", + "Topic :: Internet :: WWW/HTTP :: Dynamic Content :: CGI Tools/Libraries", + "Topic :: Software Development :: Libraries :: Python Modules", + ], + scripts=['calendar-cli.py'], + dependency_links = [ + # The package doesn't seem to be on pypi. + # We assume a low version number in case it gets uploaded + # so that the higher version is chosen over the git version + # + # There is a mirror here: + 'https://github.com/skarra/CalDAVClientLibrary/tarball/master#egg=caldavclientlibrary-0.0.1', + 'git+https://github.com/skarra/CalDAVClientLibrary.git#egg=caldavclientlibrary-0.0.1', + # We should prefer the official SVN + 'svn+http://svn.calendarserver.org/repository/calendarserver/CalDAVClientLibrary/trunk#egg=caldavclientlibrary-0.0.2', + # But there is an issue with the upstream setup.py, it does not have a name='' + # So we load the patched version + 'git+https://github.com/muelli/CalDAVClientLibrary.git#egg=caldavclientlibrary-0.0.3', + ], + install_requires=[ + 'icalendar', + 'caldavclientlibrary', + ], +) |