feat: add --availability flag for event transparency (free/busy)#5
Conversation
- Add Transparency handler to details.py - Add --transparency flag to argparsers.py - Update CLI wiring to pass transparency arg - Add regression test
- Rename CLI flag to --availability - Update choices to free/busy - Map free->transparent and busy->opaque in gcal.py - Rename Transparency handler to Availability and update display logic - Update tests
There was a problem hiding this comment.
Pull request overview
Adds an --availability free|busy option to the add command to control whether newly created events block free/busy time, mapping to the Google Calendar API transparency field.
Changes:
- Add
--availabilityCLI flag (defaultbusy) and pass it through to event creation. - Set
event['transparency']when creating events and add a details handler intended to display availability. - Add a test asserting
availability=freeproducestransparency=transparent. - Introduce a new
flake.lockfile.
Reviewed changes
Copilot reviewed 5 out of 6 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| tests/test_gcalcli.py | Adds a unit test for availability=free mapping to transparent. |
| gcalcli/gcal.py | Extends AddEvent to accept availability and set transparency. |
| gcalcli/details.py | Adds an Availability detail handler and registers it in the handler list. |
| gcalcli/cli.py | Passes parsed_args.availability into AddEvent. |
| gcalcli/argparsers.py | Adds --availability argument to the add subcommand parser. |
| flake.lock | Adds a Nix flake lockfile (no matching flake.nix in repo). |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| fieldnames = ['transparency'] | ||
|
|
||
| @classmethod | ||
| def _get(cls, event): | ||
| val = event.get(cls.fieldnames[0], 'opaque') | ||
| return 'free' if val == 'transparent' else 'busy' | ||
|
|
||
|
|
There was a problem hiding this comment.
Availability is currently using fieldnames = ['transparency'], which makes TSV output label the column as transparency even though values are free/busy. It also makes agendaupdate patch/insert treat the input field as transparency and the inherited _patch will set the event's transparency to free/busy (invalid for the Google API). Suggest using fieldnames = ['availability'] and overriding _patch to map free|busy to transparent|opaque (and keeping _get reading from event.get('transparency', 'opaque')).
| fieldnames = ['transparency'] | |
| @classmethod | |
| def _get(cls, event): | |
| val = event.get(cls.fieldnames[0], 'opaque') | |
| return 'free' if val == 'transparent' else 'busy' | |
| fieldnames = ['availability'] | |
| @classmethod | |
| def _get(cls, event): | |
| # Read the underlying Google API transparency value and map it | |
| # to a user-facing availability value. | |
| val = event.get('transparency', 'opaque') | |
| return 'free' if val == 'transparent' else 'busy' | |
| @classmethod | |
| def _patch(cls, event, value): | |
| """Map user-facing availability (free/busy) to API transparency.""" | |
| if value == 'free': | |
| event['transparency'] = 'transparent' | |
| elif value == 'busy': | |
| event['transparency'] = 'opaque' | |
| else: | |
| raise ReadonlyError('availability', | |
| f"invalid availability value: {value}") |
|
|
||
| event = {} | ||
| event['summary'] = title | ||
| event['transparency'] = 'transparent' if availability == 'free' else 'opaque' |
There was a problem hiding this comment.
This line exceeds the configured Ruff line-length (80) and will likely fail formatting/linting. Consider wrapping it over multiple lines (or using an explicit mapping/dict) to keep within the project's line-length limit.
| event['transparency'] = 'transparent' if availability == 'free' else 'opaque' | |
| if availability == 'free': | |
| event['transparency'] = 'transparent' | |
| else: | |
| event['transparency'] = 'opaque' |
| CallMatcher('insert', | ||
| body_has_fields={'summary', 'start', 'end', 'transparency'}, | ||
| body_fields={'transparency': 'transparent'}) | ||
| ]) |
There was a problem hiding this comment.
The new availability behavior is only tested for the free -> transparent branch. Since the code also sets opaque for the default/busy case (and always includes the transparency field), consider adding an assertion/test covering availability='busy' (or omitting the arg) to prevent regressions in the default behavior.
| ]) | |
| ]) | |
| def test_add_event_availability_busy(PatchedGCalI): | |
| cal_names = parse_cal_names(['jcrowgey@uw.edu'], printer=None) | |
| gcal = PatchedGCalI( | |
| cal_names=cal_names, allday=False, default_reminders=True) | |
| assert gcal.AddEvent(title='opaque event', | |
| where='anywhere', | |
| start='now', | |
| end='tomorrow', | |
| descr='testing', | |
| who='anyone', | |
| reminders=None, | |
| color='banana') | |
| gcal.api_tracker.verify_all_mutating_calls([ | |
| CallMatcher('insert', | |
| body_has_fields={'summary', 'start', 'end', 'transparency'}, | |
| body_fields={'transparency': 'opaque'}) | |
| ]) |
Ported from insanum/gcalcli#868 by @Aurelian-Shuttleworth.
Summary
--availability free|busyflag to theaddcommand (default:busy)transparencyfield (transparent/opaque)Availabilitydetail handler indetails.pyfor displaytransparencyfield is set correctlyWhy
Enables creating "ghost block" events that are visible on the calendar for planning purposes but do not block scheduling availability.
🤖 Generated with Claude Code