Skip to content

Commit

Permalink
Update documentation (ics-py#340)
Browse files Browse the repository at this point in the history
Co-authored-by: Tom Schraitle <[email protected]>
  • Loading branch information
strobeflash and tomschr authored Jul 15, 2022
1 parent 214d5c1 commit bc19f7f
Show file tree
Hide file tree
Showing 8 changed files with 199 additions and 85 deletions.
19 changes: 17 additions & 2 deletions CONTRIBUTING.rst
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,12 @@ on their free time. It might take some time for us to have a look at your
work.


Style guide
-----------

* Code formatting: `TBD <https://github.com/ics-py/ics-py/issues/344>`_
* Docstrings: `Google Python Style Guide <https://google.github.io/styleguide/pyguide.html#38-comments-and-docstrings>`_

How to submit an issue
----------------------

Expand Down Expand Up @@ -103,15 +109,15 @@ To get a list of all available tasks, run :command:`tox -av`.
This also works without having poetry installed.

If you are fixing a bug
Fixing a bug
^^^^^^^^^^^^^^^^^^^^^^^

Please add a test and add a link to it in the PR description
proving that the bug is fixed.
This will help us merge your PR quickly and above all, this will make
sure that we won't re-introduce the bug later by mistake.

If you are adding a feature
Adding a feature
^^^^^^^^^^^^^^^^^^^^^^^^^^^

We will ask you to provide:
Expand All @@ -122,6 +128,15 @@ We will ask you to provide:
* Think about where and how this will affect documentation and amend
the respective section

Working on the documentation
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Ensure correct rendering by generating the HTML pages locally with

:command:`$ tox -e docs`

View the pages at ``.tox/docs_out/index.html``

Last thing
^^^^^^^^^^

Expand Down
26 changes: 13 additions & 13 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -38,21 +38,21 @@ Quickstart
$ pip install ics
.. code-block:: python
from ics import Calendar, Event
c = Calendar()
e = Event()
e.name = "My cool event"
e.begin = '2014-01-01 00:00:00'
c.events.add(e)
c.events
# [<Event 'My cool event' begin:2014-01-01 00:00:00 end:2014-01-01 00:00:01>]
with open('my.ics', 'w') as my_file:
my_file.writelines(c)
# and it's done !
from datetime import datetime
from ics import Calendar, Event
c = Calendar()
e = Event()
e.summary = "My cool event"
e.description = "A meaningful description"
e.begin = datetime.fromisoformat('2022-06-06T12:05:23+02:00')
e.end = datetime.fromisoformat('2022-06-06T13:05:23+02:00')
c.events.append(e)
c
# Calendar(extra=Container('VCALENDAR', []), extra_params={}, version='2.0', prodid='ics.py 0.8.0-dev - http://git.io/lLljaA', scale=None, method=None, events=[Event(extra=Container('VEVENT', []), extra_params={}, timespan=EventTimespan(begin_time=datetime.datetime(2022, 6, 6, 12, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))), end_time=None, duration=None, precision='second'), summary=None, uid='[email protected]', description=None, location=None, url=None, status=None, created=None, last_modified=None, dtstamp=datetime.datetime(2022, 6, 6, 19, 28, 14, 575558, tzinfo=Timezone.from_tzid('UTC')), alarms=[], attach=[], classification=None, transparent=None, organizer=None, geo=None, attendees=[], categories=[])], todos=[])
with open('my.ics', 'w') as f:
f.write(c.serialize())
More examples are available in the
`documentation <http://icspy.readthedocs.org/>`_.
Expand Down
129 changes: 98 additions & 31 deletions doc/howtos/quickstart.rst
Original file line number Diff line number Diff line change
Expand Up @@ -12,53 +12,120 @@ Quickstart
:local:



Importing a Calendar from a File
--------------------------------
Conventions
-----------

.. code-block:: python
from ics import Calendar
import requests
c = ics.Calendar()
e = ics.Event()
a = ics.Attendee()
url = "https://urlab.be/events/urlab.ics"
c = Calendar(requests.get(url).text)
Importing a Calendar from a URL
--------------------------------

c
# <Calendar with 118 events and 0 todo>
c.events
# {<Event 'Visite de "Fab Bike"' begin:2016-06-21T15:00:00+00:00 end:2016-06-21T17:00:00+00:00>,
# <Event 'Le lundi de l'embarqué: Adventure in Espressif Non OS SDK edition' begin:2018-02-19T17:00:00+00:00 end:2018-02-19T22:00:00+00:00>,
# ...}
e = list(c.timeline)[0]
"Event '{}' started {}".format(e.name, e.begin.humanize())
# "Event 'Workshop Git' started 2 years ago"
Download the calender file through requests or any other library.
Error handling is recommended.

.. code-block:: python
from ics import Calendar
import requests
url = "https://urlab.be/events/urlab.ics"
try:
c = Calendar(requests.get(url).text)
except Exception as e:
print(e)
print(c)
# <Calendar with 118 events and 0 todo>
print(c.events[2])
# <Event 'TechMardi 20/2015' begin: 2015-12-08 17:30:00+00:00 fixed end: 2015-12-08 22:00:00+00:00 duration: 4:30:00>
e = list(c.timeline)[0]
print("Event '{}' started {}".format(e.summary, e.begin))
# Event 'Workshop Git' started 2015-11-16 17:30:00+00:00
Creating a new Calendar and Add Events
--------------------------------------

:class:`Calendar` objects each represent an unique RFC 5545 iCalendar. They contain :class:`Event`, :class:`Todo` and :class:`Timeline` iterators.

Time and date are represented as :class:`datetime` objects and can be expressed as ISO 8601 strings or with the class constructor.

.. code-block:: python
from ics import Calendar, Event
c = Calendar()
e = Event()
e.name = "My cool event"
e.begin = '2014-01-01 00:00:00'
c.events.add(e)
c.events
# {<Event 'My cool event' begin:2014-01-01 00:00:00 end:2014-01-01 00:00:01>}
from datetime import datetime, timezone, timedelta
from ics import Calendar, Event
c = Calendar()
e = Event()
e.summary = "My cool event"
e.description = "A meaningful description"
e.begin = datetime.fromisoformat('2022-06-06T12:05:23+02:00')
e.end = datetime(year=2022, month=6, day=6, hour=12, minute=5, second=23, tzinfo=timezone(timedelta(seconds=7200)))
c.events.append(e)
c
# Calendar(extra=Container('VCALENDAR', []), extra_params={}, version='2.0', prodid='ics.py 0.8.0-dev - http://git.io/lLljaA', scale=None, method=None, events=[Event(extra=Container('VEVENT', []), extra_params={}, timespan=EventTimespan(begin_time=datetime.datetime(2022, 6, 6, 12, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))), end_time=datetime.datetime(2022, 6, 6, 12, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))), duration=None, precision='second'), summary='My cool event', uid='[email protected]', description='A meaningful description', location=None, url=None, status=None, created=None, last_modified=None, dtstamp=datetime.datetime(2022, 6, 30, 12, 41, 24, 624188, tzinfo=Timezone.from_tzid('UTC')), alarms=[], attach=[], classification=None, transparent=None, organizer=None, geo=None, attendees=[], categories=[])], todos=[])
Get event datetime object details
---------------------------------

.. code-block:: python
e.cmp_tuple()
# (datetime.datetime(2022, 6, 6, 12, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))), datetime.datetime(2022, 6, 6, 13, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))), 'My cool event')
Converting to all-day event
---------------------------

Transforms event to a rounded-up all-day event.

.. code-block:: python
e.cmp_tuple()
# (datetime.datetime(2022, 6, 6, 12, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))), datetime.datetime(2022, 6, 6, 13, 5, 23, tzinfo=datetime.timezone(datetime.timedelta(seconds=7200))), 'My cool event')
e.make_all_day()
e.cmp_tuple()
# (datetime.datetime(2022, 6, 6, 0, 0, tzinfo=tzlocal()), datetime.datetime(2022, 6, 7, 0, 0, tzinfo=tzlocal()), 'My cool event')
Exporting a Calendar to a File
Exporting a calendar to a file
------------------------------

.. code-block:: python
with open('my.ics', 'w') as f:
f.write(c)
# And it's done !
with open('my.ics', 'w') as f:
f.write(c.serialize())
Managing attendees
------------------

* Adding attendees

.. code-block:: python
from ics import Attendee
a = Attendee('[email protected]')
e.add_attendee(a)
e.attendees
# [Attendee(email='[email protected]', extra={})]
* Modifying attendees, find all possible attributes and values in :class:`Attendee`

.. code-block:: python
e.attendees
# [Attendee(email='[email protected]', extra={})]
e.attendees[0].common_name = 'ALL'
e.attendees
# [Attendee(email='[email protected]', extra={'CN': ['ALL']})]
* Removing attendees

.. code-block:: python
# iCalendar-formatted data is also available in a string
str(c)
# 'BEGIN:VCALENDAR\nPRODID:...
e.attendees
# [Attendee(email='[email protected]', extra={'CN': ['ALL']})]
del e.attendees[0]
e.attendees
# []
8 changes: 7 additions & 1 deletion doc/reference/api.rst
Original file line number Diff line number Diff line change
Expand Up @@ -42,10 +42,16 @@ Alarms
:members:
:special-members:

Attendee
--------

.. autoclass:: ics.Attendee
:members:
:special-members:

Timeline
---------


.. autoclass:: ics.timeline.Timeline
:members:
:special-members:
29 changes: 21 additions & 8 deletions src/ics/attendee.py
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ class PersonAttrs(object):


class Person(PersonAttrs):
"""Abstract class for Attendee and Organizer."""

NAME = "ABSTRACT-PERSON"

def __init__(self, email, extra=None, **kwargs):
Expand All @@ -76,24 +78,35 @@ def __init__(self, email, extra=None, **kwargs):


class Organizer(Person):
"""Organizer of an event or todo."""

NAME = "ORGANIZER"


class Attendee(Person):
"""Attendee of an event or todo.
Possible values according to iCalendar standard, first value is default:
user_type = INDIVIDUAL | GROUP | RESOURCE | ROOM | UNKNOWN
member = Person
role = REQ-PARTICIPANT | CHAIR | OPT-PARTICIPANT | NON-PARTICIPANT
rsvp = False | True
delegated_to = Person
delegated_from = Person
Depending on the Component, different status are possible.
Event:
status = NEEDS-ACTION | ACCEPTED | DECLINED | TENTATIVE | DELEGATED
Todo:
status = NEEDS-ACTION | ACCEPTED | DECLINED | TENTATIVE | DELEGATED | COMPLETED | IN-PROCESS
"""

NAME = "ATTENDEE"

user_type = PersonProperty[str]("CUTYPE", default="INDIVIDUAL")
"""Calendar User Type: INDIVIDUAL, GROUP, RESOURCE, ROOM, UNKNOWN, ..."""
member = PersonMultiProperty("MEMBER", converter=URIConverter)
"""group or list membership"""
role = PersonProperty[str]("ROLE", default="REQ-PARTICIPANT")
"""Role: CHAIR, REQ-PARTICIPANT, OPT-PARTICIPANT, NON-PARTICIPANT"""
status = PersonProperty[str]("PARTSTAT", default="NEEDS-ACTION")
"""Participation Status, possible values differ:
Event, ToDo, Journal: NEEDS-ACTION, ACCEPTED, DECLINED
Event, ToDo: TENTATIVE, DELEGATED
ToDo: COMPLETED, IN-PROCESS"""
rsvp = PersonProperty("RSVP", converter=BooleanConverter, default=False)
"""expectation of a favor of a reply?"""
delegated_to = PersonMultiProperty("DELEGATED-TO", converter=URIConverter)
delegated_from = PersonMultiProperty("DELEGATED-FROM", converter=URIConverter)
3 changes: 3 additions & 0 deletions src/ics/component.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ def to_container(self, context: Optional[ContextDict] = None) -> Container:
return ComponentMeta.BY_TYPE[type(self)].serialize_toplevel(self, context)

def serialize(self, context: Optional[ContextDict] = None) -> str:
"""Creates a serialized string fit for file write.
"""

return self.to_container(context).serialize()

def strip_extras(self, all_extras=False, extra_properties=None, extra_params=None, property_merging=None):
Expand Down
Loading

0 comments on commit bc19f7f

Please sign in to comment.