kopia lustrzana https://github.com/collective/icalendar
Add VCALENDAR properties NAME, DESCRIPTION and COLOR as attributes
rodzic
8add6bfe64
commit
800e990d70
|
@ -0,0 +1,40 @@
|
|||
"""Attributes of Components and properties."""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Optional
|
||||
|
||||
|
||||
def multi_language_text_property(main_prop:str, compatibility_prop:str, doc:str) -> property:
|
||||
"""This creates a text property.
|
||||
|
||||
This property can be defined several times with different LANGAUGE parameters.
|
||||
|
||||
Args:
|
||||
|
||||
main_prop: The property to set and get, e.g. NAME
|
||||
compatibility_prop: An old property used before, e.g. X-WR-CALNAME
|
||||
doc: The documentation string
|
||||
"""
|
||||
def fget(self) -> Optional[str]:
|
||||
"""Get the property"""
|
||||
result = self.get(main_prop, self.get(compatibility_prop))
|
||||
if isinstance(result, list):
|
||||
for item in result:
|
||||
if "LANGUAGE" not in item.params:
|
||||
return item
|
||||
return result
|
||||
|
||||
def fset(self, value:str):
|
||||
"""Set the property."""
|
||||
fdel(self)
|
||||
self.add(main_prop, value)
|
||||
|
||||
def fdel(self):
|
||||
"""Delete the property."""
|
||||
self.pop(main_prop, None)
|
||||
self.pop(compatibility_prop, None)
|
||||
|
||||
return property(fget, fset, fdel, doc)
|
||||
|
||||
|
||||
__all__ = ["multi_language_text_property"]
|
|
@ -16,6 +16,7 @@ from typing import TYPE_CHECKING, List, NamedTuple, Optional, Tuple, Union
|
|||
import dateutil.rrule
|
||||
import dateutil.tz
|
||||
|
||||
from icalendar.attr import multi_language_text_property
|
||||
from icalendar.caselessdict import CaselessDict
|
||||
from icalendar.parser import Contentline, Contentlines, Parameters, q_join, q_split
|
||||
from icalendar.parser_tools import DEFAULT_ENCODING
|
||||
|
@ -1898,6 +1899,10 @@ class Calendar(Component):
|
|||
"PRODID",
|
||||
"CALSCALE",
|
||||
"METHOD",
|
||||
"NAME",
|
||||
"X-WR-CALNAME",
|
||||
"DESCRIPTION",
|
||||
"X-WR-CALDESC",
|
||||
)
|
||||
required = (
|
||||
"PRODID",
|
||||
|
@ -2055,6 +2060,107 @@ class Calendar(Component):
|
|||
continue
|
||||
self.add_component(timezone)
|
||||
|
||||
calendar_name = multi_language_text_property(
|
||||
"NAME", "X-WR-CALNAME",
|
||||
"""This property specifies the name of the calendar
|
||||
|
||||
This takes care of :rfc:`7986` ``NAME`` and ``X-WR-CALNAME``.
|
||||
|
||||
Property Parameters:
|
||||
|
||||
IANA, non-standard, alternate text
|
||||
representation, and language property parameters can be specified
|
||||
on this property.
|
||||
|
||||
Conformance:
|
||||
|
||||
This property can be specified multiple times in an
|
||||
iCalendar object. However, each property MUST represent the name
|
||||
of the calendar in a different language.
|
||||
|
||||
Description:
|
||||
|
||||
This property is used to specify a name of the
|
||||
iCalendar object that can be used by calendar user agents when
|
||||
presenting the calendar data to a user. Whilst a calendar only
|
||||
has a single name, multiple language variants can be specified by
|
||||
including this property multiple times with different "LANGUAGE"
|
||||
parameter values on each.
|
||||
|
||||
>>> from icalendar import Calendar
|
||||
>>> calendar = Calendar()
|
||||
>>> calendar.calendar_name = "My Calendar"
|
||||
>>> print(calendar.to_ical())
|
||||
BEGIN:VCALENDAR
|
||||
NAME:My Calendar
|
||||
END:VCALENDAR
|
||||
""")
|
||||
|
||||
description = calendar_description = multi_language_text_property(
|
||||
"DESCRIPTION", "X-WR-CALDESC",
|
||||
"""This property specifies the description of the calendar.
|
||||
|
||||
This takes care of :rfc:`7986` ``DESCRIPTION`` and ``X-WR-CALDESC``.
|
||||
|
||||
Conformance:
|
||||
|
||||
This property can be specified multiple times in an
|
||||
iCalendar object. However, each property MUST represent the
|
||||
description of the calendar in a different language.
|
||||
|
||||
Description:
|
||||
|
||||
This property is used to specify a lengthy textual
|
||||
description of the iCalendar object that can be used by calendar
|
||||
user agents when describing the nature of the calendar data to a
|
||||
user. Whilst a calendar only has a single description, multiple
|
||||
language variants can be specified by including this property
|
||||
multiple times with different "LANGUAGE" parameter values on each.
|
||||
|
||||
>>> from icalendar import Calendar
|
||||
>>> calendar = Calendar()
|
||||
>>> calendar.description = "This is a calendar"
|
||||
>>> print(calendar.to_ical())
|
||||
BEGIN:VCALENDAR
|
||||
DESCRIPTION:This is a calendar
|
||||
END:VCALENDAR
|
||||
""")
|
||||
|
||||
color = calendar_color = multi_language_text_property(
|
||||
"COLOR", "X-APPLE-CALENDAR-COLOR",
|
||||
"""This property specifies a color used for displaying the calendar.
|
||||
|
||||
This takes care of :rfc:`7986` ``COLOR`` and ``X-APPLE-CALENDAR-COLOR``.
|
||||
|
||||
Property Parameters:
|
||||
|
||||
IANA and non-standard property parameters can
|
||||
be specified on this property.
|
||||
|
||||
Conformance:
|
||||
|
||||
This property can be specified once in an iCalendar
|
||||
object or in "VEVENT", "VTODO", or "VJOURNAL" calendar components.
|
||||
|
||||
Description:
|
||||
|
||||
This property specifies a color that clients MAY use
|
||||
when presenting the relevant data to a user. Typically, this
|
||||
would appear as the "background" color of events or tasks. The
|
||||
value is a case-insensitive color name taken from the CSS3 set of
|
||||
names, defined in Section 4.3 of [W3C.REC-css3-color-20110607].
|
||||
|
||||
Example: ``"turquoise"``, ``"#ffffff"``
|
||||
|
||||
>>> from icalendar import Calendar
|
||||
>>> calendar = Calendar()
|
||||
>>> calendar.color = "black"
|
||||
>>> print(calendar.to_ical())
|
||||
BEGIN:VCALENDAR
|
||||
COLOR:black
|
||||
END:VCALENDAR
|
||||
"""
|
||||
)
|
||||
|
||||
# These are read only singleton, so one instance is enough for the module
|
||||
types_factory = TypesFactory()
|
||||
|
|
|
@ -0,0 +1,114 @@
|
|||
"""This tests additional attributes from RFC 7986.
|
||||
|
||||
Some attributes are also available as X-... attributes.
|
||||
They are also considered.
|
||||
"""
|
||||
|
||||
import pytest
|
||||
|
||||
from icalendar import Calendar
|
||||
from icalendar.prop import vText
|
||||
|
||||
|
||||
@pytest.fixture()
|
||||
def calendar() -> Calendar:
|
||||
"""Empty calendar"""
|
||||
return Calendar()
|
||||
|
||||
|
||||
param_name = pytest.mark.parametrize("name", ["Company Vacation Days", "Calendar Name"])
|
||||
param_prop = pytest.mark.parametrize("prop", ["NAME", "X-WR-CALNAME"])
|
||||
|
||||
|
||||
@param_prop
|
||||
@param_name
|
||||
def test_get_calendar_name(prop, name, calendar):
|
||||
"""Get the name of the calendar."""
|
||||
calendar.add(prop, name)
|
||||
assert calendar.calendar_name == name
|
||||
|
||||
|
||||
@param_name
|
||||
def test_set_calendar_name(name, calendar):
|
||||
"""Setting the name overrides the old attributes."""
|
||||
calendar.calendar_name = name
|
||||
assert calendar.calendar_name == name
|
||||
assert calendar["NAME"] == name
|
||||
|
||||
|
||||
@param_name
|
||||
@param_prop
|
||||
def test_replace_name(name, prop, calendar):
|
||||
"""Setting the name overrides the old attributes."""
|
||||
calendar[prop] = "Other Name"
|
||||
calendar.calendar_name = name
|
||||
assert calendar.calendar_name == name
|
||||
|
||||
|
||||
@param_name
|
||||
@param_prop
|
||||
def test_del_name(name, calendar, prop):
|
||||
"""Delete the name."""
|
||||
calendar.add(prop, name)
|
||||
del calendar.calendar_name
|
||||
assert calendar.calendar_name is None
|
||||
|
||||
|
||||
def test_default_name(calendar):
|
||||
"""We have no name by default."""
|
||||
assert calendar.calendar_name is None
|
||||
|
||||
|
||||
@param_name
|
||||
def test_setting_the_name_deletes_the_non_standard_attribute(calendar, name):
|
||||
"""The default_attr is deleted when setting the name."""
|
||||
calendar["X-WR-CALNAME"] = name
|
||||
assert "X-WR-CALNAME" in calendar
|
||||
calendar.calendar_name = "other name"
|
||||
assert "X-WR-CALNAME" not in calendar
|
||||
|
||||
|
||||
@param_name
|
||||
@pytest.mark.parametrize("order", [1, 2])
|
||||
def test_multiple_names_use_the_one_without_a_language(calendar, name, order):
|
||||
"""Add several names and use the one without a language param."""
|
||||
if order == 1:
|
||||
calendar.add("NAME", name)
|
||||
calendar.add("NAME", vText("Kalendername", params={"LANGUAGE":"de"}))
|
||||
if order == 2:
|
||||
calendar.add("NAME", name)
|
||||
assert calendar.calendar_name == name
|
||||
|
||||
|
||||
@param_name
|
||||
def test_name_is_preferred(calendar, name):
|
||||
"""NAME is more important that X-WR-CALNAME"""
|
||||
calendar.add("NAME", name)
|
||||
calendar.add("X-WR-CALNAME", "asd")
|
||||
assert calendar.calendar_name == name
|
||||
|
||||
|
||||
|
||||
# For description, we would use the same tests as name but we also use the
|
||||
# same code, so it is alright.
|
||||
|
||||
param_color = pytest.mark.parametrize("desc", ["DESCRIPTION", "X-WR-CALDESC"])
|
||||
|
||||
@param_color
|
||||
@param_name
|
||||
def test_description(calendar, desc, name):
|
||||
"""Get the value"""
|
||||
calendar.add(desc, name)
|
||||
assert calendar.calendar_description == name
|
||||
|
||||
# For color, we would use the same tests as name but we also use the
|
||||
# same code, so it is alright.
|
||||
|
||||
param_color = pytest.mark.parametrize("color", ["COLOR", "X-APPLE-CALENDAR-COLOR"])
|
||||
|
||||
@param_color
|
||||
@param_name
|
||||
def test_color(calendar, color, name):
|
||||
"""Get the value"""
|
||||
calendar.add(color, name)
|
||||
assert calendar.calendar_color == name
|
Ładowanie…
Reference in New Issue