kopia lustrzana https://github.com/collective/icalendar
Cli (#256)
* Added rudimentary command line interface. * Added documentation on the CLI. * Added example output. * Removed _optional wrapper in favour of the built-in get() method. * Added --version option. * Removed default for 'attendee'. * Looping over all vevents now. * Updated changelog.pull/261/head
rodzic
c880a5b262
commit
e86570b2da
|
|
@ -4,6 +4,9 @@ Changelog
|
||||||
4.0.1 (unreleased)
|
4.0.1 (unreleased)
|
||||||
------------------
|
------------------
|
||||||
|
|
||||||
|
- Added rudimentary command line interface.
|
||||||
|
[jfjlaros]
|
||||||
|
|
||||||
- Readme, setup and travis updates.
|
- Readme, setup and travis updates.
|
||||||
[jdufresne, PabloCastellano]
|
[jdufresne, PabloCastellano]
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,36 @@
|
||||||
|
iCalendar utility
|
||||||
|
=================
|
||||||
|
|
||||||
|
To get more information about the command line interface, use the ``-h``
|
||||||
|
option::
|
||||||
|
|
||||||
|
$ icalendar -h
|
||||||
|
|
||||||
|
view
|
||||||
|
----
|
||||||
|
|
||||||
|
Use the ``view`` subcommand for a human readable summary of an event::
|
||||||
|
|
||||||
|
$ icalendar view myfile.ics
|
||||||
|
|
||||||
|
The output will look something like this::
|
||||||
|
|
||||||
|
Organiser: Secretary <secretary@company.com>
|
||||||
|
Attendees:
|
||||||
|
John Doe <j.doe@company.com>
|
||||||
|
Randy <boss@company.com>
|
||||||
|
Summary: Yearly evaluation.
|
||||||
|
When: Tue 14 Mar 2017 11:00-12:00
|
||||||
|
Location: Randy's office
|
||||||
|
Comment: Reminder.
|
||||||
|
Description:
|
||||||
|
|
||||||
|
Your yearly evaluation is scheduled for next Tuesday. Please be on time.
|
||||||
|
|
||||||
|
To use this in terminal based e-mail clients like mutt, add a new mime type (as
|
||||||
|
root)::
|
||||||
|
|
||||||
|
# cat << EOF > /usr/lib/mime/packages/icalendar
|
||||||
|
text/calendar; icalendar view '%s'; copiousoutput; description=iCalendar text; priority=2
|
||||||
|
EOF
|
||||||
|
# update-mime
|
||||||
|
|
@ -15,6 +15,7 @@ icalendar contributors
|
||||||
- Erik Simmler <tgecho@gmail.com>
|
- Erik Simmler <tgecho@gmail.com>
|
||||||
- George V. Reilly <george@reilly.org>
|
- George V. Reilly <george@reilly.org>
|
||||||
- Jannis Leidel <jannis@leidel.info>
|
- Jannis Leidel <jannis@leidel.info>
|
||||||
|
- Jeroen F.J. Laros <jlaros@fixedpoint.nl>
|
||||||
- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>
|
- Jeroen van Meeuwen (Kolab Systems) <vanmeeuwen@kolabsys.com>
|
||||||
- Jordan Kiang <jordan@cozi.com>
|
- Jordan Kiang <jordan@cozi.com>
|
||||||
- Klaus Klein <kleink+github@kleink.org>
|
- Klaus Klein <kleink+github@kleink.org>
|
||||||
|
|
|
||||||
|
|
@ -10,5 +10,6 @@ Contents
|
||||||
install
|
install
|
||||||
usage
|
usage
|
||||||
api
|
api
|
||||||
|
cli
|
||||||
credits
|
credits
|
||||||
license
|
license
|
||||||
|
|
|
||||||
1
setup.py
1
setup.py
|
|
@ -57,6 +57,7 @@ setuptools.setup(
|
||||||
zip_safe=False,
|
zip_safe=False,
|
||||||
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
python_requires=">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*",
|
||||||
install_requires=install_requires,
|
install_requires=install_requires,
|
||||||
|
entry_points = {'console_scripts': ['icalendar = icalendar.cli:main']},
|
||||||
extras_require={
|
extras_require={
|
||||||
'test': tests_require
|
'test': tests_require
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,111 @@
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""iCalendar utility"""
|
||||||
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import sys
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
from . import Calendar, __version__
|
||||||
|
|
||||||
|
|
||||||
|
_template = """Organiser: {organiser}
|
||||||
|
Attendees:
|
||||||
|
{attendees}
|
||||||
|
Summary: {summary}
|
||||||
|
When: {time_from}-{time_to}
|
||||||
|
Location: {location}
|
||||||
|
Comment: {comment}
|
||||||
|
Description:
|
||||||
|
|
||||||
|
{description}
|
||||||
|
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
def _format_name(address):
|
||||||
|
"""Retrieve the e-mail and optionally the name from an address.
|
||||||
|
|
||||||
|
:arg vCalAddress address: An address object.
|
||||||
|
|
||||||
|
:returns str: The name and optionally the e-mail address.
|
||||||
|
"""
|
||||||
|
if not address:
|
||||||
|
return ''
|
||||||
|
|
||||||
|
email = address.title().split(':')[1]
|
||||||
|
if 'cn' in address.params:
|
||||||
|
return '{} <{}>'.format(address.params['cn'], email)
|
||||||
|
|
||||||
|
return email
|
||||||
|
|
||||||
|
|
||||||
|
def _format_attendees(attendees):
|
||||||
|
"""Format the list of attendees.
|
||||||
|
|
||||||
|
:arg any attendees: Either a list, a string or a vCalAddress object.
|
||||||
|
|
||||||
|
:returns str: Formatted list of attendees.
|
||||||
|
"""
|
||||||
|
if type(attendees) == list:
|
||||||
|
return '\n '.join(map(_format_name, attendees))
|
||||||
|
return _format_name(attendees)
|
||||||
|
|
||||||
|
|
||||||
|
def view(input_handle, output_handle):
|
||||||
|
"""Make a human readable summary of an iCalendar file.
|
||||||
|
|
||||||
|
:arg stream handle: Open readable handle to an iCalendar file.
|
||||||
|
|
||||||
|
:returns str: Human readable summary.
|
||||||
|
"""
|
||||||
|
cal = Calendar.from_ical(input_handle.read())
|
||||||
|
|
||||||
|
for event in cal.walk('vevent'):
|
||||||
|
output_handle.write(_template.format(
|
||||||
|
organiser=_format_name(event.get('organizer', '')),
|
||||||
|
attendees=_format_attendees(event.get('attendee')),
|
||||||
|
summary=event.get('summary', ''),
|
||||||
|
time_from=datetime.strftime(
|
||||||
|
event.get('dtstart').dt, '%a %d %b %Y %H:%M'),
|
||||||
|
time_to=datetime.strftime(event.get('dtend').dt, '%H:%M'),
|
||||||
|
location=event.get('location', ''),
|
||||||
|
comment=event.get('comment', ''),
|
||||||
|
description=event.get('description', '')).encode('utf-8'))
|
||||||
|
|
||||||
|
|
||||||
|
def main():
|
||||||
|
"""Main entry point."""
|
||||||
|
parser = argparse.ArgumentParser(
|
||||||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||||||
|
description=__doc__)
|
||||||
|
parser.add_argument(
|
||||||
|
'-v', '--version', action='version',
|
||||||
|
version='{} version {}'.format(parser.prog, __version__))
|
||||||
|
|
||||||
|
# This seems a bit of an overkill now, but we will probably add more
|
||||||
|
# functionality later, e.g., iCalendar to JSON / YAML and vice versa.
|
||||||
|
subparsers = parser.add_subparsers(dest='subcommand')
|
||||||
|
|
||||||
|
subparser = subparsers.add_parser(
|
||||||
|
'view', description=view.__doc__.split('\n\n')[0])
|
||||||
|
subparser.add_argument(
|
||||||
|
'input_handle', metavar='INPUT', type=argparse.FileType('r'),
|
||||||
|
help='iCalendar file')
|
||||||
|
subparser.add_argument(
|
||||||
|
'-o', dest='output_handle', metavar='OUTPUT',
|
||||||
|
type=argparse.FileType('w'), default=sys.stdout,
|
||||||
|
help='output file (default=<stdout>)')
|
||||||
|
subparser.set_defaults(func=view)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
try:
|
||||||
|
args.func(**{k: v for k, v in vars(args).items()
|
||||||
|
if k not in ('func', 'subcommand')})
|
||||||
|
except ValueError as error:
|
||||||
|
parser.error(error)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
main()
|
||||||
Ładowanie…
Reference in New Issue