Skip to content

Commit

Permalink
Add attributes for Journal
Browse files Browse the repository at this point in the history
  • Loading branch information
niccokunzmann committed Oct 11, 2024
1 parent 35b15be commit 95b7023
Show file tree
Hide file tree
Showing 2 changed files with 94 additions and 6 deletions.
41 changes: 41 additions & 0 deletions src/icalendar/cal.py
Original file line number Diff line number Diff line change
Expand Up @@ -711,6 +711,19 @@ class Todo(Component):


class Journal(Component):
"""A describtive text at a certain time or associated with a component.
A "VJOURNAL" calendar component is a grouping of
component properties that represent one or more descriptive text
notes associated with a particular calendar date. The "DTSTART"
property is used to specify the calendar date with which the
journal entry is associated. Generally, it will have a DATE value
data type, but it can also be used to specify a DATE-TIME value
data type. Examples of a journal entry include a daily record of
a legislative body or a journal entry of individual telephone
contacts for the day or an ordered list of accomplishments for the
day.
"""

name = 'VJOURNAL'

Expand All @@ -724,6 +737,34 @@ class Journal(Component):
'RELATED', 'RDATE', 'RRULE', 'RSTATUS', 'DESCRIPTION',
)

DTSTART = create_single_property(
"DTSTART", "dt", (datetime, date), date,
'The "DTSTART" property for a "VJOURNAL" that specifies the exact date at which the journal entry was made.')

@property
def start(self) -> date:
"""The start of the Journal.
The "DTSTART"
property is used to specify the calendar date with which the
journal entry is associated.
"""
start = self.DTSTART
if start is None:
raise IncompleteComponent("No DTSTART given.")
return start

@start.setter
def start(self, value: datetime|date) -> None:
"""Set the start of the journal."""
self.DTSTART = value

end = start

@property
def duration(self) -> timedelta:
"""The journal does not last any time."""
return timedelta(0)

class FreeBusy(Component):

Expand Down
59 changes: 53 additions & 6 deletions src/icalendar/tests/test_issue_662_component_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,13 @@
try:
from zoneinfo import ZoneInfo
except ImportError:
from backports.zoneinfo import ZoneInfo # type: ignore
from backports.zoneinfo import ZoneInfo # type: ignore PGH003

from icalendar import (
Event,
IncompleteComponent,
InvalidCalendar,
Journal,
vDDDTypes,
)
from icalendar.prop import vDuration
Expand Down Expand Up @@ -263,14 +264,25 @@ def test_incomplete_event(incomplete_event_end, attr):
(datetime(2024, 10, 11, 10, 20), timedelta(days=1)),
]
)
@pytest.mark.parametrize("attr", ["start", "end", "DTSTART", "DTEND"])
def test_set_invalid_start(invalid_value, attr):
@pytest.mark.parametrize(
("Component", "attr"),
[
(Event,"start"),
(Event,"end"),
(Event,"DTSTART"),
(Event,"DTEND"),
(Journal,"start"),
(Journal,"end"),
(Journal,"DTSTART"),
]
)
def test_set_invalid_start(invalid_value, attr, Component):
"""Check that we get the right error.
- other types that vDDDTypes accepts
- object
"""
event = Event()
event = Component()
with pytest.raises(TypeError) as e:
setattr(event, attr, invalid_value)
assert e.value.args[0] == f"Use datetime or date, not {type(invalid_value).__name__}."
Expand Down Expand Up @@ -318,7 +330,7 @@ def test_setting_duration_deletes_the_end():
assert "DTEND" not in event
assert event.DTEND is None
assert event.DURATION == timedelta(days=1)

valid_values = pytest.mark.parametrize(
("attr", "value"),
[
Expand Down Expand Up @@ -353,4 +365,39 @@ def test_invalid_none(attr):
event = Event()
event[attr] = None
with pytest.raises(InvalidCalendar):
getattr(event, attr)
getattr(event, attr)

@pytest.mark.parametrize("attr", ["DTSTART", "end", "start"])
@pytest.mark.parametrize("start", [
datetime(2024, 10, 11, 10, 20),
date(2024, 10, 11),
datetime(2024, 10, 11, 10, 20, tzinfo=ZoneInfo("Europe/Paris")),
])
def test_journal_start(start, attr):
"""Test that we can set the start of a journal."""
j = Journal()
setattr(j, attr, start)
assert start == j.DTSTART
assert j.start == start
assert j.end == start
assert j.duration == timedelta(0)

@pytest.mark.parametrize("attr", ["start", "end"])
def test_delete_journal_start(attr):
"""Delete the start of the journal."""
j = Journal()
j.start = datetime(2010, 11, 12, 13, 14)
j.DTSTART = None
assert j.DTSTART is None
assert "DTSTART" not in j
with pytest.raises(IncompleteComponent):
getattr(j, attr)

def setting_twice_does_not_duplicate_the_entry():
j = Journal()
j.DTSTART = date(2024, 1,1 )
j.DTSTART = date(2024, 1, 3)
assert date(2024, 1, 3) == j.DTSTART
assert j.start == date(2024, 1, 3)
assert j.end == date(2024, 1, 3)

0 comments on commit 95b7023

Please sign in to comment.