Add Alarm.new_display(), new_audio(), and new_email() factory methods - #1417
Conversation
There was a problem hiding this comment.
Pull request overview
Note
Copilot was unable to run its full agentic suite in this review.
Adds convenience factory constructors for RFC 5545 VALARM components and accompanying tests/docs to make alarm creation easier and less error-prone.
Changes:
- Add
Alarm.new_display(),Alarm.new_audio(), andAlarm.new_email()factory methods with validation and docstrings. - Add pytest coverage for the new factory methods and validation behavior.
- Add a news fragment announcing the new public APIs.
Reviewed changes
Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.
| File | Description |
|---|---|
| src/icalendar/cal/alarm.py | Introduces three new Alarm factory classmethods (DISPLAY/AUDIO/EMAIL) with parameter validation and docs. |
| src/icalendar/tests/attr/test_alarm_factory_methods.py | Adds tests asserting correct properties and validation errors for the new factory methods. |
| news/865.feature | Documents the addition of the new factory methods. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
|
@klouds27 would you please respond to the comments from copilot that you requested, and update your branch to |
stevepiercy
left a comment
There was a problem hiding this comment.
This is excellent work. Thank you for improving icalendar! I have a few suggestions for you to consider. Would you please take care?
I also would like a second pair of eyes from a maintainer. @SashankBhamidi @niccokunzmann @angatha
Each method sets ACTION and TRIGGER (required by RFC 5545 §3.6.6) and validates that all action-specific required fields are present, raising InvalidCalendar on missing inputs. DURATION and REPEAT must be supplied together or not at all. Covered by 25 unit tests.
to_ical() sorts properties alphabetically; the docstring examples for new_audio and new_email assumed insertion order, causing doctest failures on Python 3.14. Updated expected output to match sorted order. Also clarified that absolute trigger accepts any datetime (UTC recommended but not enforced), and added the missing repeat-without-duration tests for new_audio and new_email.
- Remove positional-only `/` separator from new_display, new_audio, and new_email so all parameters are keyword-passable - Fix news/865.feature to use :rfc:`5545#section-3.6.6` markup - Replace `e.g.` with `such as` in attach/attendees docstrings - Fix vCalAddress cross-reference to use full module path - Simplify uid docstring to `or None` (uid is optional, not auto-generated) Signed-off-by: klouds27 <adalwolf@gmail.com>
78eabac to
2f4d232
Compare
|
Addressed all review comments:
|
stevepiercy
left a comment
There was a problem hiding this comment.
This looks good to me. Since this is a new feature, I'd like to get a maintainer to review as well. @niccokunzmann @SashankBhamidi @angatha would you please do the honors?
Thank you!
Coverage Report for CI Build 26491460473Coverage increased (+0.01%) to 97.85%Details
Uncovered Changes
Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
SashankBhamidi
left a comment
There was a problem hiding this comment.
Nice work. The factory methods are RFC-correct.
A few things to address before merge. Findings 1, 3, 4, 6 are mechanical. Finding 2 is a design question I'd like to revisit with @niccokunzmann when he's back mid-June, @angatha curious if you have thoughts in the meantime.
Procedural note: if any part of this was AI-assisted, please follow the Responsible AI use policy. Standard reminder.
|
@klouds27 When addressing each finding, please mark the conversation as resolved with a short reply, either confirming the fix in a specific commit, or noting why it's being deferred/skipped if applicable. Same goes for the Copilot review you requested earlier. Helps keep the review state clean. Thanks! |
- Extract repeated duration/repeat validation to _apply_duration_repeat helper - Reject empty string for new_audio attach parameter - Align new_display trigger docstring wording with new_audio and new_email - Add Event.new() integration example to new_display docstring Signed-off-by: klouds27 <adalwolf@gmail.com>
|
Addressed the mechanical findings: extracted repeated duration/repeat validation to a Finding 2 (factory delegation to |
|
About finding 2, personally I would add the parameters from |
|
A property to get the action value should also be added: |
niccokunzmann
left a comment
There was a problem hiding this comment.
Thank you so much for all that work! Let me know if you need anything. I added a few ideas to fit it into the existing structure of the package.
- new_audio: accept bytes for inline binary attachments (vBinary) - new_email: accept single vCalAddress or str for attendees/attachments - parametrize duration/repeat validation tests across all three factory methods Signed-off-by: klouds27 <adalwolf@gmail.com>
|
documented links, related_to, refids, and concepts in all three docstrings. on the guard style: if not description is deliberate — an empty string is semantically invalid for a description, so truthiness is the right check. trigger is None is explicit because None is the only invalid value there, a zero-length timedelta would be valid. |
niccokunzmann
left a comment
There was a problem hiding this comment.
Hi, thanks for the PR! This looks really good to me. The only thing I would request is that the tests at the bottom of the file check the values, so the edge case is properly covered.
Checks that attendee addresses, attachment URIs, and binary attach data match the inputs, not just that the properties exist or have the right type. Also moves the three edge-case tests into their respective sections and lifts the vBinary import to module level. Signed-off-by: klouds27 <adalwolf@gmail.com>
|
added value assertions to all five tests that were checking type or presence only. the three follow-up items you flagged (ACTION attribute, attendees accepting str, uid/links/concepts coverage) can be opened as issues after merge. |
|
@angatha @SashankBhamidi please.have another look and choose which chnages are essential. |
|
TODO as follow-up:
|
|
@niccokunzmann @SashankBhamidi @angatha please resolve unresolved conversations that should be resolved in this issue to allow auto-merge when enabled. |
niccokunzmann
left a comment
There was a problem hiding this comment.
Removing the comments in the test files.
collective#1417 (comment) Co-authored-by: Nicco Kunzmann <niccokunzmann@rambler.ru>
8a61b08
The changes requested have been applied.
`Alarm.new_display()`, `Alarm.new_audio()` and `Alarm.new_email()` were added in collective#1417, but their optional parameters and `Parameters` entries did not follow the alphabetical order that `Alarm.new()` establishes, and none of them carried a `versionadded` admonition. - Order the optional parameters of the three factory methods alphabetically, matching `Alarm.new()`. The required positional parameters keep their existing order, so no call site breaks. - Order the `Parameters` entries in the docstrings the same way. - Add a `.. versionadded:: 7.3.0` admonition to each factory method, which was overlooked in collective#1417. - Add tests that assert the optional parameters of all four factory methods are in alphabetical order, and that `links`, `related_to`, `refids`, `concepts` and `uid` are forwarded to `Alarm.new()`. The three factory methods are not part of any released tag yet, so reordering their keyword parameters is not a breaking change. Fixes collective#1591 AI disclosure: I used Claude Opus 4.5 to help draft this change and its tests. Prompt: work on collective/icalendar issue collective#1591, verify which of its checklist items are actually still open on current main, align the optional parameters and docstring `Parameters` order of the three Alarm factory methods with `Alarm.new()`, add the missing `versionadded` admonitions, and add tests that fail before the change. Output: this commit. I reviewed the result, confirmed the new tests fail on unpatched main and pass with the change, and validated it locally with the full pytest suite (17837 passed), `pytest src/icalendar/tests/test_with_doctest.py` (368 passed) and `ruff check` / `ruff format`.
Closes #865.
What
Adds three class methods to
Alarmfor creating the three standard VALARM action types defined in RFC 5545 §3.6.6:Alarm.new_display(description, trigger, ...)—ACTION:DISPLAYAlarm.new_audio(trigger, attach=None, ...)—ACTION:AUDIOAlarm.new_email(summary, description, trigger, attendees, ...)—ACTION:EMAILEach method sets
ACTIONandTRIGGER(both required by RFC 5545 for every alarm type) and enforces the action-specific required fields, raisingInvalidCalendaron missing or invalid inputs.DURATIONandREPEATare accepted as optional paired parameters by all three methods and raiseInvalidCalendarwhen only one is supplied.Example
Tests
25 unit tests in
src/icalendar/tests/attr/test_alarm_factory_methods.pycovering:ACTIONvalue for each methodATTACHandDURATION/REPEATpairingInvalidCalendarraised for each missing required fieldInvalidCalendarraised whenDURATIONandREPEATare not supplied together📚 Documentation preview 📚: https://icalendar--1417.org.readthedocs.build/en/1417/