Skip to content

Commit

Permalink
feat: add agenda --tsv --details length and agendaupdate length
Browse files Browse the repository at this point in the history
… detail

* feat: add `agenda --tsv --details length`
* feat: `agendaupdate`: add `length` detail
  • Loading branch information
michaelmhoffman authored Jan 31, 2025
1 parent 5810f4f commit 4f84787
Show file tree
Hide file tree
Showing 2 changed files with 49 additions and 3 deletions.
19 changes: 19 additions & 0 deletions gcalcli/actions.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,21 @@ def _iter_field_handlers(row):
yield fieldname, handler, value


def _check_writable_fields(row):
"""Check no potentially conflicting fields for a writing action."""
keys = row.keys()

# XXX: instead of preventing use of end_date/end_time and length in the
# same input, use successively complex conflict resolution plans:
#
# 1. allow it as long as they don't conflict by row
# 2. conflict resolution by option
# 3. conflict resolution interactively

if 'length' in keys and ('end_date' in keys or 'end_time' in keys):
raise NotImplementedError


def patch(row, cal, interface):
"""Patch event with new data."""
event_id = row['id']
Expand All @@ -22,6 +37,8 @@ def patch(row, cal, interface):
mod_event = {}
cal_id = cal['id']

_check_writable_fields(row)

for fieldname, handler, value in _iter_field_handlers(row):
if fieldname in FIELDNAMES_READONLY:
# Instead of changing mod_event, the Handler.patch() for
Expand Down Expand Up @@ -56,6 +73,8 @@ def insert(row, cal, interface):
event = {}
cal_id = cal['id']

_check_writable_fields(row)

for fieldname, handler, value in _iter_field_handlers(row):
if fieldname in FIELDNAMES_READONLY:
raise ReadonlyError("Cannot specify value on insert.")
Expand Down
33 changes: 30 additions & 3 deletions gcalcli/details.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from dateutil.parser import isoparse, parse

from .exceptions import ReadonlyCheckError, ReadonlyError
from .utils import is_all_day
from .utils import get_timedelta_from_str, is_all_day

FMT_DATE = '%Y-%m-%d'
FMT_TIME = '%H:%M'
Expand Down Expand Up @@ -124,6 +124,33 @@ def patch(cls, cal, event, fieldname, value):
instant['timeZone'] = cal['timeZone']


class Length(Time):
"""Handler for event duration."""

fieldnames = ['length']

@classmethod
def get(cls, event):
return [str(event['e'] - event['s'])]

@classmethod
def patch(cls, cal, event, fieldname, value):
# start_date and start_time must be an earlier TSV field than length
start = event['start']
end = event['end'] = {}

if start['date']:
# XXX: handle all-day events
raise NotImplementedError

start_datetime = isoparse(start['dateTime'])
end_datetime = start_datetime + get_timedelta_from_str(value)

end['date'] = None # clear all-day date, for good measure
end['dateTime'] = end_datetime.isoformat()
end['timeZone'] = cal['timeZone']


class Url(Handler):
"""Handler for HTML and legacy Hangout links."""

Expand Down Expand Up @@ -259,6 +286,7 @@ def _get(cls, event):

HANDLERS = OrderedDict([('id', ID),
('time', Time),
('length', Length),
('url', Url),
('conference', Conference),
('title', Title),
Expand All @@ -279,8 +307,7 @@ def _get(cls, event):
in FIELD_HANDLERS.items()
if handler in HANDLERS_READONLY)

_DETAILS_WITHOUT_HANDLERS = ['length', 'reminders', 'attendees',
'attachments', 'end']
_DETAILS_WITHOUT_HANDLERS = ['reminders', 'attendees', 'attachments', 'end']

DETAILS = list(HANDLERS.keys()) + _DETAILS_WITHOUT_HANDLERS
DETAILS_DEFAULT = {'time', 'title'}

0 comments on commit 4f84787

Please sign in to comment.