kopia lustrzana https://github.com/collective/icalendar
Create VAVAILABLE and VAVAILABILITY classes
rodzic
ef3f1c6e8d
commit
0a33b4c482
|
|
@ -17,10 +17,10 @@ This package is compatible with the following standards:
|
|||
- :rfc:`6868` - Parameter Value Encoding in iCalendar and vCard
|
||||
- :rfc:`7529` - Non-Gregorian Recurrence Rules in the Internet Calendaring and Scheduling Core Object Specification (iCalendar)
|
||||
- :rfc:`9074` - "VALARM" Extensions for iCalendar
|
||||
- :rfc:`7953` - Calendar Availability
|
||||
|
||||
We do not claim compatibility to the following RFCs. They might work though.
|
||||
|
||||
- :rfc:`7953` - Calendar Availability
|
||||
- :rfc:`7986` - New Properties for iCalendar
|
||||
- :rfc:`9073` - Event Publishing Extensions to iCalendar
|
||||
- :rfc:`9253` - Support for iCalendar Relationships
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ from icalendar.alarms import (
|
|||
)
|
||||
from icalendar.cal import (
|
||||
Alarm,
|
||||
Availability,
|
||||
Available,
|
||||
Calendar,
|
||||
Component,
|
||||
ComponentFactory,
|
||||
|
|
@ -76,6 +78,8 @@ __all__ = [
|
|||
"Alarm",
|
||||
"AlarmTime",
|
||||
"Alarms",
|
||||
"Availability",
|
||||
"Available",
|
||||
"Calendar",
|
||||
"Component",
|
||||
"ComponentEndMissing",
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Optional, Sequence, Union
|
|||
|
||||
from icalendar.error import InvalidCalendar
|
||||
from icalendar.parser_tools import SEQUENCE_TYPES
|
||||
from icalendar.prop import vCategory, vDDDTypes, vDuration, vRecur, vText
|
||||
from icalendar.prop import vCalAddress, vCategory, vDDDTypes, vDuration, vRecur, vText
|
||||
from icalendar.timezone import tzp
|
||||
|
||||
if TYPE_CHECKING:
|
||||
|
|
@ -962,6 +962,48 @@ Examples:
|
|||
""", # noqa: E501
|
||||
)
|
||||
|
||||
|
||||
def _get_organizer(self: Component) -> Optional[vCalAddress]:
|
||||
"""ORGANIZER defines the organizer for a calendar component.
|
||||
|
||||
Property Parameters:
|
||||
IANA, non-standard, language, common name,
|
||||
directory entry reference, and sent-by property parameters can be
|
||||
specified on this property.
|
||||
|
||||
Conformance:
|
||||
This property MUST be specified in an iCalendar object
|
||||
that specifies a group-scheduled calendar entity. This property
|
||||
MUST be specified in an iCalendar object that specifies the
|
||||
publication of a calendar user's busy time. This property MUST
|
||||
NOT be specified in an iCalendar object that specifies only a time
|
||||
zone definition or that defines calendar components that are not
|
||||
group-scheduled components, but are components only on a single
|
||||
user's calendar.
|
||||
|
||||
Description:
|
||||
This property is specified within the "VEVENT",
|
||||
"VTODO", and "VJOURNAL" calendar components to specify the
|
||||
organizer of a group-scheduled calendar entity. The property is
|
||||
specified within the "VFREEBUSY" calendar component to specify the
|
||||
calendar user requesting the free or busy time. When publishing a
|
||||
"VFREEBUSY" calendar component, the property is used to specify
|
||||
the calendar that the published busy time came from.
|
||||
|
||||
The property has the property parameters "CN", for specifying the
|
||||
common or display name associated with the "Organizer", "DIR", for
|
||||
specifying a pointer to the directory information associated with
|
||||
the "Organizer", "SENT-BY", for specifying another calendar user
|
||||
that is acting on behalf of the "Organizer". The non-standard
|
||||
parameters may also be specified on this property. If the
|
||||
"LANGUAGE" property parameter is specified, the identified
|
||||
language applies to the "CN" parameter value.
|
||||
"""
|
||||
return self.get("ORGANIZER")
|
||||
|
||||
|
||||
organizer_property = property(_get_organizer)
|
||||
|
||||
__all__ = [
|
||||
"categories_property",
|
||||
"color_property",
|
||||
|
|
@ -970,6 +1012,7 @@ __all__ = [
|
|||
"descriptions_property",
|
||||
"exdates_property",
|
||||
"multi_language_text_property",
|
||||
"organizer_property",
|
||||
"property_del_duration",
|
||||
"property_doc_duration_template",
|
||||
"property_get_duration",
|
||||
|
|
|
|||
|
|
@ -5,6 +5,8 @@ These are the defined components.
|
|||
"""
|
||||
|
||||
from .alarm import Alarm
|
||||
from .avaiable import Available
|
||||
from .availability import Availability
|
||||
from .calendar import Calendar
|
||||
from .component import Component
|
||||
from .component_factory import ComponentFactory
|
||||
|
|
@ -16,6 +18,8 @@ from .todo import Todo
|
|||
|
||||
__all__ = [
|
||||
"Alarm",
|
||||
"Availability",
|
||||
"Available",
|
||||
"Calendar",
|
||||
"Component",
|
||||
"ComponentFactory",
|
||||
|
|
|
|||
|
|
@ -0,0 +1,38 @@
|
|||
"""This implements the sub-component "AVAILABLE" of "VAVAILABILITY".
|
||||
|
||||
This is specified in :rfc:`7953`.
|
||||
"""
|
||||
|
||||
from .component import Component
|
||||
|
||||
|
||||
class Available(Component):
|
||||
"""Sub-component of "VAVAILABILITY from :rfc:`7953`.
|
||||
|
||||
Description:
|
||||
"AVAILABLE" subcomponents are used to indicate periods of free
|
||||
time within the time range of the enclosing "VAVAILABILITY"
|
||||
component. "AVAILABLE" subcomponents MAY include recurrence
|
||||
properties to specify recurring periods of time, which can be
|
||||
overridden using normal iCalendar recurrence behavior (i.e., use
|
||||
of the "RECURRENCE-ID" property).
|
||||
|
||||
Examples:
|
||||
This is a recurring "AVAILABLE" subcomponent:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
BEGIN:AVAILABLE
|
||||
UID:57DD4AAF-3835-46B5-8A39-B3B253157F01
|
||||
SUMMARY:Monday to Friday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Denver:20111023T090000
|
||||
DTEND;TZID=America/Denver:20111023T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
|
||||
LOCATION:Denver
|
||||
END:AVAILABLE
|
||||
"""
|
||||
|
||||
name = "VAVAILABLE"
|
||||
|
||||
|
||||
__all__ = ["Available"]
|
||||
|
|
@ -0,0 +1,184 @@
|
|||
"""This implementes the VAVAILABILITY component.
|
||||
|
||||
This is specified in :rfc:`7953`.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from icalendar.attr import organizer_property
|
||||
|
||||
from .component import Component
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from icalendar.cal.avaiable import Available
|
||||
|
||||
|
||||
class Availability(Component):
|
||||
"""VAVAILABILITY component from :rfc:`7953`.
|
||||
|
||||
This provides a grouping of component properties and
|
||||
subcomponents that describe the availability associated with a
|
||||
calendar user.
|
||||
|
||||
Description:
|
||||
A "VAVAILABILITY" component indicates a period of time
|
||||
within which availability information is provided. A
|
||||
"VAVAILABILITY" component can specify a start time and an end time
|
||||
or duration. If "DTSTART" is not present, then the start time is
|
||||
unbounded. If "DTEND" or "DURATION" are not present, then the end
|
||||
time is unbounded. Within the specified time period, availability
|
||||
defaults to a free-busy type of "BUSY-UNAVAILABLE" (see
|
||||
Section 3.2), except for any time periods corresponding to
|
||||
"AVAILABLE" subcomponents.
|
||||
|
||||
"AVAILABLE" subcomponents are used to indicate periods of free
|
||||
time within the time range of the enclosing "VAVAILABILITY"
|
||||
component. "AVAILABLE" subcomponents MAY include recurrence
|
||||
properties to specify recurring periods of time, which can be
|
||||
overridden using normal iCalendar recurrence behavior (i.e., use
|
||||
of the "RECURRENCE-ID" property).
|
||||
|
||||
If specified, the "DTSTART" and "DTEND" properties in
|
||||
"VAVAILABILITY" components and "AVAILABLE" subcomponents MUST be
|
||||
"DATE-TIME" values specified as either the date with UTC time or
|
||||
the date with local time and a time zone reference.
|
||||
|
||||
The iCalendar object containing the "VAVAILABILITY" component MUST
|
||||
contain appropriate "VTIMEZONE" components corresponding to each
|
||||
unique "TZID" parameter value used in any DATE-TIME properties in
|
||||
all components, unless [RFC7809] is in effect.
|
||||
|
||||
When used to publish available time, the "ORGANIZER" property
|
||||
specifies the calendar user associated with the published
|
||||
available time.
|
||||
|
||||
If the "PRIORITY" property is specified in "VAVAILABILITY"
|
||||
components, it is used to determine how that component is combined
|
||||
with other "VAVAILABILITY" components. See Section 4.
|
||||
|
||||
Other calendar properties MAY be specified in "VAVAILABILITY" or
|
||||
"AVAILABLE" components and are considered attributes of the marked
|
||||
block of time. Their usage is application specific. For example,
|
||||
the "LOCATION" property might be used to indicate that a person is
|
||||
available in one location for part of the week and a different
|
||||
location for another part of the week (but see Section 9 for when
|
||||
it is appropriate to add additional data like this).
|
||||
|
||||
Example:
|
||||
The following is an example of a "VAVAILABILITY" calendar
|
||||
component used to represent the availability of a user, always
|
||||
available Monday through Friday, 9:00 am to 5:00 pm in the
|
||||
America/Montreal time zone:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
BEGIN:VAVAILABILITY
|
||||
ORGANIZER:mailto:bernard@example.com
|
||||
UID:0428C7D2-688E-4D2E-AC52-CD112E2469DF
|
||||
DTSTAMP:20111005T133225Z
|
||||
BEGIN:AVAILABLE
|
||||
UID:34EDA59B-6BB1-4E94-A66C-64999089C0AF
|
||||
SUMMARY:Monday to Friday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Montreal:20111002T090000
|
||||
DTEND;TZID=America/Montreal:20111002T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
|
||||
END:AVAILABLE
|
||||
END:VAVAILABILITY
|
||||
|
||||
The following is an example of a "VAVAILABILITY" calendar
|
||||
component used to represent the availability of a user available
|
||||
Monday through Thursday, 9:00 am to 5:00 pm, at the main office,
|
||||
and Friday, 9:00 am to 12:00 pm, in the branch office in the
|
||||
America/Montreal time zone between October 2nd and December 2nd
|
||||
2011:
|
||||
|
||||
.. code-block:: text
|
||||
|
||||
BEGIN:VAVAILABILITY
|
||||
ORGANIZER:mailto:bernard@example.com
|
||||
UID:84D0F948-7FC6-4C1D-BBF3-BA9827B424B5
|
||||
DTSTAMP:20111005T133225Z
|
||||
DTSTART;TZID=America/Montreal:20111002T000000
|
||||
DTEND;TZID=America/Montreal:20111202T000000
|
||||
BEGIN:AVAILABLE
|
||||
UID:7B33093A-7F98-4EED-B381-A5652530F04D
|
||||
SUMMARY:Monday to Thursday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Montreal:20111002T090000
|
||||
DTEND;TZID=America/Montreal:20111002T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH
|
||||
LOCATION:Main Office
|
||||
END:AVAILABLE
|
||||
BEGIN:AVAILABLE
|
||||
UID:DF39DC9E-D8C3-492F-9101-0434E8FC1896
|
||||
SUMMARY:Friday from 9:00 to 12:00
|
||||
DTSTART;TZID=America/Montreal:20111006T090000
|
||||
DTEND;TZID=America/Montreal:20111006T120000
|
||||
RRULE:FREQ=WEEKLY
|
||||
LOCATION:Branch Office
|
||||
END:AVAILABLE
|
||||
END:VAVAILABILITY
|
||||
|
||||
For more examples, have a look at :rfc:`5545`.
|
||||
|
||||
"""
|
||||
|
||||
name = "VAVAILABILITY"
|
||||
|
||||
canonical_order = (
|
||||
"DTSTART",
|
||||
"DTEND",
|
||||
"DURATION",
|
||||
"DTSTAMP",
|
||||
"UID",
|
||||
"SEQUENCE",
|
||||
"SUMMARY",
|
||||
"DESCRIPTION",
|
||||
"ORGANIZER",
|
||||
)
|
||||
|
||||
required = (
|
||||
"DTSTART",
|
||||
"DTSTAMP",
|
||||
"UID",
|
||||
)
|
||||
|
||||
singletons = (
|
||||
"DTSTAMP",
|
||||
"UID",
|
||||
"BUSYTYPE",
|
||||
"CLASS",
|
||||
"CREATED",
|
||||
"DESCRIPTION",
|
||||
"DTSTART",
|
||||
"LAST-MODIFIED",
|
||||
"LOCATION",
|
||||
"ORGANIZER",
|
||||
"PRIORITY",
|
||||
"SEQUENCE",
|
||||
"SUMMARY",
|
||||
"URL",
|
||||
"DTEND",
|
||||
"DURATION",
|
||||
)
|
||||
|
||||
exclusive = (
|
||||
"DTEND",
|
||||
"DURATION",
|
||||
)
|
||||
|
||||
organizer = organizer_property
|
||||
|
||||
@property
|
||||
def available(self) -> list[Available]:
|
||||
"""All event components in the calendar.
|
||||
|
||||
This is a shortcut to get all VAVAILABLE sub-components.
|
||||
Modifications do not change the calendar.
|
||||
Use :py:meth:`Component.add_component`.
|
||||
"""
|
||||
return self.walk("VAVAILABLE")
|
||||
|
||||
|
||||
__all__ = ["Availability"]
|
||||
|
|
@ -14,6 +14,8 @@ class ComponentFactory(CaselessDict):
|
|||
"""Set keys to upper for initial dict."""
|
||||
super().__init__(*args, **kwargs)
|
||||
from icalendar.cal.alarm import Alarm
|
||||
from icalendar.cal.avaiable import Available
|
||||
from icalendar.cal.availability import Availability
|
||||
from icalendar.cal.calendar import Calendar
|
||||
from icalendar.cal.event import Event
|
||||
from icalendar.cal.free_busy import FreeBusy
|
||||
|
|
@ -30,6 +32,8 @@ class ComponentFactory(CaselessDict):
|
|||
self["DAYLIGHT"] = TimezoneDaylight
|
||||
self["VALARM"] = Alarm
|
||||
self["VCALENDAR"] = Calendar
|
||||
self["AVAILABLE"] = Available
|
||||
self["VAVAILABILITY"] = Availability
|
||||
|
||||
|
||||
__all__ = ["ComponentFactory"]
|
||||
|
|
|
|||
|
|
@ -0,0 +1,12 @@
|
|||
BEGIN:VAVAILABILITY
|
||||
ORGANIZER:mailto:bernard@example.com
|
||||
UID:0428C7D2-688E-4D2E-AC52-CD112E2469DF
|
||||
DTSTAMP:20111005T133225Z
|
||||
BEGIN:AVAILABLE
|
||||
UID:34EDA59B-6BB1-4E94-A66C-64999089C0AF
|
||||
SUMMARY:Monday to Friday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Montreal:20111002T090000
|
||||
DTEND;TZID=America/Montreal:20111002T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
|
||||
END:AVAILABLE
|
||||
END:VAVAILABILITY
|
||||
|
|
@ -0,0 +1,23 @@
|
|||
BEGIN:VAVAILABILITY
|
||||
ORGANIZER:mailto:bernard@example.com
|
||||
UID:84D0F948-7FC6-4C1D-BBF3-BA9827B424B5
|
||||
DTSTAMP:20111005T133225Z
|
||||
DTSTART;TZID=America/Montreal:20111002T000000
|
||||
DTEND;TZID=America/Montreal:20111202T000000
|
||||
BEGIN:AVAILABLE
|
||||
UID:7B33093A-7F98-4EED-B381-A5652530F04D
|
||||
SUMMARY:Monday to Thursday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Montreal:20111002T090000
|
||||
DTEND;TZID=America/Montreal:20111002T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH
|
||||
LOCATION:Main Office
|
||||
END:AVAILABLE
|
||||
BEGIN:AVAILABLE
|
||||
UID:DF39DC9E-D8C3-492F-9101-0434E8FC1896
|
||||
SUMMARY:Friday from 9:00 to 12:00
|
||||
DTSTART;TZID=America/Montreal:20111006T090000
|
||||
DTEND;TZID=America/Montreal:20111006T120000
|
||||
RRULE:FREQ=WEEKLY
|
||||
LOCATION:Branch Office
|
||||
END:AVAILABLE
|
||||
END:VAVAILABILITY
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
BEGIN:VAVAILABILITY
|
||||
ORGANIZER:mailto:bernard@example.com
|
||||
UID:BE082249-7BDD-4FE0-BDBA-DE6598C32FC9
|
||||
DTSTAMP:20111005T133225Z
|
||||
DTSTART;TZID=America/Montreal:20111002T000000
|
||||
DTEND;TZID=America/Montreal:20111023T030000
|
||||
BEGIN:AVAILABLE
|
||||
UID:54602321-CEDB-4620-9099-757583263981
|
||||
SUMMARY:Monday to Friday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Montreal:20111002T090000
|
||||
DTEND;TZID=America/Montreal:20111002T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
|
||||
LOCATION:Montreal
|
||||
END:AVAILABLE
|
||||
END:VAVAILABILITY
|
||||
BEGIN:VAVAILABILITY
|
||||
ORGANIZER:mailto:bernard@example.com
|
||||
UID:A1FF55E3-555C-433A-8548-BF4864B5621E
|
||||
DTSTAMP:20111005T133225Z
|
||||
DTSTART;TZID=America/Denver:20111023T000000
|
||||
DTEND;TZID=America/Denver:20111030T000000
|
||||
BEGIN:AVAILABLE
|
||||
UID:57DD4AAF-3835-46B5-8A39-B3B253157F01
|
||||
SUMMARY:Monday to Friday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Denver:20111023T090000
|
||||
DTEND;TZID=America/Denver:20111023T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
|
||||
LOCATION:Denver
|
||||
END:AVAILABLE
|
||||
END:VAVAILABILITY
|
||||
BEGIN:VAVAILABILITY
|
||||
ORGANIZER:mailto:bernard@example.com
|
||||
UID:1852F9E1-E0AA-4572-B4C4-ED1680A4DA40
|
||||
DTSTAMP:20111005T133225Z
|
||||
DTSTART;TZID=America/Montreal:20111030T030000
|
||||
BEGIN:AVAILABLE
|
||||
UID:D27C421F-16C2-4ECB-8352-C45CA352C72A
|
||||
SUMMARY:Monday to Friday from 9:00 to 17:00
|
||||
DTSTART;TZID=America/Montreal:20111030T090000
|
||||
DTEND;TZID=America/Montreal:20111030T170000
|
||||
RRULE:FREQ=WEEKLY;BYDAY=MO,TU,WE,TH,FR
|
||||
LOCATION:Montreal
|
||||
END:AVAILABLE
|
||||
END:VAVAILABILITY
|
||||
|
|
@ -5,7 +5,6 @@ except ImportError:
|
|||
from datetime import datetime, timezone
|
||||
from typing import Generator
|
||||
|
||||
from icalendar import TypesFactory
|
||||
import pytest
|
||||
|
||||
import icalendar
|
||||
|
|
@ -14,6 +13,7 @@ import icalendar.cal.calendar
|
|||
import icalendar.cal.component_factory
|
||||
import icalendar.cal.event
|
||||
import icalendar.cal.timezone
|
||||
from icalendar import TypesFactory
|
||||
from icalendar.cal.component import Component
|
||||
|
||||
from . import timezone_ids
|
||||
|
|
@ -108,6 +108,7 @@ CALENDARS_FOLDER = HERE / "calendars"
|
|||
TIMEZONES_FOLDER = HERE / "timezones"
|
||||
EVENTS_FOLDER = HERE / "events"
|
||||
ALARMS_FOLDER = HERE / "alarms"
|
||||
AVAILABILITIES_FOLDER = HERE / "availabilities"
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
|
|
@ -130,6 +131,11 @@ def alarms(tzp):
|
|||
return DataSource(ALARMS_FOLDER, icalendar.cal.alarm.Alarm.from_ical)
|
||||
|
||||
|
||||
@pytest.fixture(scope="module")
|
||||
def availabilities(tzp):
|
||||
return DataSource(AVAILABILITIES_FOLDER, icalendar.cal.alarm.Alarm.from_ical)
|
||||
|
||||
|
||||
@pytest.fixture(params=PYTZ_UTC + [zoneinfo.ZoneInfo("UTC"), tz.UTC, tz.gettz("UTC")])
|
||||
def utc(request, tzp):
|
||||
return request.param
|
||||
|
|
@ -190,6 +196,7 @@ def types_factory():
|
|||
"""Return a new types factory."""
|
||||
return TypesFactory()
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def x_sometime(types_factory):
|
||||
"""Map x_sometime to time"""
|
||||
|
|
|
|||
|
|
@ -0,0 +1,33 @@
|
|||
"""This tests the parsing of the VAVAILABILITY component as defined in :rfc:`7953`."""
|
||||
|
||||
from datetime import datetime
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from icalendar import Availability
|
||||
|
||||
|
||||
def test_uid(availabilities):
|
||||
"""Test the UID property."""
|
||||
availability: Availability = availabilities.rfc_7953_1
|
||||
assert availability.uid == "0428C7D2-688E-4D2E-AC52-CD112E2469DF"
|
||||
|
||||
|
||||
def test_organizer(availabilities):
|
||||
"""Test the ORGANIZER property."""
|
||||
availability: Availability = availabilities.rfc_7953_1
|
||||
assert availability.organizer == "mailto:bernard@example.com"
|
||||
assert availability.organizer.email == "bernard@example.com"
|
||||
|
||||
|
||||
def test_dtstamp(availabilities, tzp):
|
||||
"""Test the DTSTAMP property."""
|
||||
availability: Availability = availabilities.rfc_7953_1
|
||||
assert availability.DTSTAMP == tzp.localize_utc(datetime(2011, 10, 5, 13, 32, 25))
|
||||
|
||||
|
||||
def test_subcomponents(availabilities):
|
||||
"""Test the subcomponents."""
|
||||
availability: Availability = availabilities.rfc_7953_1
|
||||
assert len(availability.subcomponents) == 1
|
||||
assert availability.available == availability.subcomponents
|
||||
Ładowanie…
Reference in New Issue