from collections import OrderedDict
from onegov.core.orm.mixins import content_property, ContentMixin
from onegov.core.orm.types import UTCDateTime
from sedate import to_timezone
from sqlalchemy import Column
from sqlalchemy import String
from sqlalchemy import Text
from sqlalchemy.dialects.postgresql import HSTORE
from sqlalchemy.ext.mutable import MutableDict
from typing import TYPE_CHECKING
if TYPE_CHECKING:
from collections.abc import Iterable
from datetime import datetime
from onegov.core.orm.mixins import dict_property
[docs]
class OccurrenceMixin(ContentMixin):
""" Contains all attributes events and ocurrences share.
The ``start`` and ``end`` date and times are stored in UTC - that is, they
are stored internally without a timezone and are converted to UTC when
getting or setting, see :class:`UTCDateTime`. Use the properties
``localized_start`` and ``localized_end`` to get the localized version of
the date and times.
"""
#: Title of the event
[docs]
title: 'Column[str]' = Column(Text, nullable=False)
#: A nice id for the url, readable by humans
[docs]
name: 'Column[str | None]' = Column(Text)
#: Description of the location of the event
[docs]
location: 'Column[str | None]' = Column(Text, nullable=True)
#: Tags/Categories of the event
@property
# FIXME: asymmetric properties are not supported, if we need to
# be able to set this with arbitrary iterables we need
# to define a custom descriptor
@tags.setter
def tags(self, value: 'Iterable[str]') -> None:
self._tags = {key.strip(): '' for key in value}
#: Filter keywords if organisation settings enabled filters
[docs]
filter_keywords: 'dict_property[dict[str, list[str] | str]]'
filter_keywords = content_property(default=dict)
#: Timezone of the event
[docs]
timezone: 'Column[str]' = Column(String, nullable=False)
#: Start date and time of the event (of the first event if recurring)
[docs]
start: 'Column[datetime]' = Column(UTCDateTime, nullable=False)
@property
[docs]
def localized_start(self) -> 'datetime':
""" The localized version of the start date/time. """
return to_timezone(self.start, self.timezone)
#: End date and time of the event (of the first event if recurring)
[docs]
end: 'Column[datetime]' = Column(UTCDateTime, nullable=False)
@property
[docs]
def localized_end(self) -> 'datetime':
""" The localized version of the end date/time. """
return to_timezone(self.end, self.timezone)
[docs]
def filter_keywords_ordered(
self,
) -> dict[str, list[str] | str | None]:
return OrderedDict((k, sorted(v) if isinstance(v, list) else v)
for k, v in sorted(self.filter_keywords.items()))