Merge branch 'master' into release-5.0.0

pull/457/head
Nicco Kunzmann 2022-10-17 09:59:06 +01:00 zatwierdzone przez GitHub
commit 12d4d38d26
Nie znaleziono w bazie danych klucza dla tego podpisu
ID klucza GPG: 4AEE18F83AFDEB23
16 zmienionych plików z 239 dodań i 182 usunięć

Wyświetl plik

@ -0,0 +1,39 @@
---
name: Bug report
about: Create a report to help us improve
title: "[BUG] "
labels: ''
assignees: ''
---
<!-- This template is there to guide you and help us. If you can not complete everything here, that is fine. -->
## Describe the bug
<!-- A clear and concise description of what the bug is. -->
## To Reproduce
<!-- Please add the neccesary code here to reproduce the problem on your machine. -->
```
import icalendar
...
```
Output:
<!-- If applicable, add logs or error outputs to help explain your problem. -->
```
```
## Expected behavior**
<!-- A clear and concise description of what you expected to happen. -->
## Environment
<!-- please complete the following information: -->
- [ ] OS: <!-- e.g. Ubuntu 22 or Windows 10 -->
- [ ] Python version: <!-- e.g. Python 3.10 -->
- [ ] `icalendar` version: <!-- python3 -c 'import icalendar; print(icalendar.__version__)' -->
## Additional context
<!-- Add any other context about the problem here, related issues and pull requests. -->
- [ ] I tested it with the latest version `pip3 install https://github.com/collective/icalendar.git`
- [ ] I attached the ICS source file or there is no ICS source file

Wyświetl plik

@ -0,0 +1,18 @@
---
name: empty issue
about: This is an unstructured issue template to use with issues that are not described,
yet.
title: ''
labels: ''
assignees: ''
---
<!-- This is an unstructured issue template to use if you do not need guidance.
Here are some hints though:
- add ICS example files if you can
- show code if possible
- show error output or output that differs from what you expect
- it is nice to connect to the value of this issue
Thanks for taking your time to report this!
-->

Wyświetl plik

@ -2,14 +2,17 @@ name: tests
on:
push:
branches: [ main ]
branches:
- main
tags:
- v*
pull_request:
schedule:
- cron: '14 7 * * 0' # run once a week on Sunday
workflow_dispatch:
jobs:
build:
run-tests:
strategy:
matrix:
config:
@ -51,3 +54,61 @@ jobs:
coveralls --service=github
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
deploy-tag-to-pypi:
# only deploy on tags, see https://stackoverflow.com/a/58478262/1320237
if: startsWith(github.ref, 'refs/tags/v')
needs:
- run-tests
runs-on: ubuntu-latest
# This environment stores the TWINE_USERNAME and TWINE_PASSWORD
# see https://docs.github.com/en/actions/deployment/targeting-different-environments/using-environments-for-deployment
environment:
name: PyPI
url: https://pypi.org/project/icalendar/
# after using the environment, we need to make the secrets available
# see https://docs.github.com/en/actions/security-guides/encrypted-secrets#example-using-bash
env:
TWINE_USERNAME: ${{ secrets.TWINE_USERNAME }}
TWINE_PASSWORD: ${{ secrets.TWINE_PASSWORD }}
steps:
- uses: actions/checkout@v2
- name: Set up Python
uses: actions/setup-python@v2
with:
python-version: "3.9"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install wheel twine
- name: Check the tag
run: |
PACKAGE_VERSION=`python setup.py --version`
TAG_NAME=v$PACKAGE_VERSION
echo "Package version $PACKAGE_VERSION with possible tag name $TAG_NAME on $GITHUB_REF_NAME"
# test that the tag represents the version
# see https://docs.github.com/en/actions/learn-github-actions/environment-variables
if [ "$TAG_NAME" != "$GITHUB_REF_NAME" ]; then
echo "ERROR: This tag is for the wrong version. Got \"$GITHUB_REF_NAME\" expected \"$TAG_NAME\"."
exit 1
fi
- name: remove old files
run: rm -rf dist/*
- name: build distribution files
run: python setup.py bdist_wheel sdist
- name: deploy to pypi
run: |
# You will have to set the variables TWINE_USERNAME and TWINE_PASSWORD
# You can use a token specific to your project by setting the user name to
# __token__ and the password to the token given to you by the PyPI project.
# sources:
# - https://shambu2k.hashnode.dev/gitlab-to-pypi
# - http://blog.octomy.org/2020/11/deploying-python-pacakges-to-pypi-using.html?m=1
if [ -z "$TWINE_USERNAME" ]; then
echo "WARNING: TWINE_USERNAME not set!"
fi
if [ -z "$TWINE_PASSWORD" ]; then
echo "WARNING: TWINE_PASSWORD not set!"
fi
twine check dist/*
twine upload dist/*

Wyświetl plik

@ -28,12 +28,15 @@ Minor changes:
- removed deprecated test checks [tuergeist]
- Fix: cli does not support DURATION #354 [mamico]
- Add changelog and contributing to readthedocs documentation #428 [peleccom]
- fixed small typos #323 [rohnsha0]
- unittest to parametrized pytest refactoring [jacadzaca]
Breaking changes:
- Require Python 3.7 as minimum Python version. [maurits] [niccokunzmann]
- icalenar now takes a ics file directly as an input
- icalendar's output is different
- Drop Support for Python 3.6. Versions 3.7 - 3.11 are supported and tested.
New features:
@ -53,6 +56,8 @@ Bug fixes:
Ref: #338
Fixes: #335
[tobixen]
- add ``__eq__`` to ``icalendar.prop.vDDDTypes`` #391 [jacadzaca]
- Refactor deprecated unittest aliases for Python 3.11 compatibility #330 [tirkarthi]
5.0.0a1 (2022-07-11)
--------------------

Wyświetl plik

@ -42,6 +42,7 @@ setuptools.setup(
'Programming Language :: Python :: 3.8',
'Programming Language :: Python :: 3.9',
'Programming Language :: Python :: 3.10',
'Programming Language :: Python :: 3.11',
'Programming Language :: Python :: Implementation :: CPython',
'Programming Language :: Python :: Implementation :: PyPy',
],

Wyświetl plik

@ -0,0 +1,7 @@
BEGIN:VCALENDAR
BEGIN:VEVENT
SUMMARY:An Event with too many semicolons
DTSTART;;VALUE=DATE-TIME:20140409T093000
UID:abc
END:VEVENT
END:VCALENDAR

Wyświetl plik

@ -0,0 +1,23 @@
BEGIN:VCALENDAR
BEGIN:VTIMEZONE
TZID:(UTC-03:00) Brasília
BEGIN:STANDARD
TZNAME:Brasília standard
DTSTART:16010101T235959
TZOFFSETFROM:-0200
TZOFFSETTO:-0300
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=3SA;BYMONTH=2
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:Brasília daylight
DTSTART:16010101T235959
TZOFFSETFROM:-0300
TZOFFSETTO:-0200
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SA;BYMONTH=10
END:DAYLIGHT
END:VTIMEZONE
BEGIN:VEVENT
DTSTART;TZID="(UTC-03:00) Brasília":20170511T133000
DTEND;TZID="(UTC-03:00) Brasília":20170511T140000
END:VEVENT
END:VCALENDAR

Wyświetl plik

@ -1,5 +1,4 @@
import os
import logging
import pytest
import icalendar
import pytz
@ -10,7 +9,6 @@ try:
except ModuleNotFoundError:
from backports import zoneinfo
class DataSource:
'''A collection of parsed ICS elements (e.g calendars, timezones, events)'''
def __init__(self, data_source_folder, parser):
@ -24,7 +22,8 @@ class DataSource:
with open(source_path, 'rb') as f:
raw_ics = f.read()
source = self._parser(raw_ics)
source.raw_ics = raw_ics
if not isinstance(source, list):
source.raw_ics = raw_ics
self.__dict__[attribute] = source
return source
@ -34,10 +33,19 @@ class DataSource:
def __repr__(self):
return repr(self.__dict__)
@property
def multiple(self):
"""Return a list of all components parsed."""
return self.__class__(self._data_source_folder, lambda data: self._parser(data, multiple=True))
HERE = os.path.dirname(__file__)
CALENDARS_FOLDER = os.path.join(HERE, 'calendars')
TIMEZONES_FOLDER = os.path.join(HERE, 'timezones')
EVENTS_FOLDER = os.path.join(HERE, 'events')
CALENDARS_FOLDER = os.path.join(HERE, 'calendars')
@pytest.fixture
def calendars():
return DataSource(CALENDARS_FOLDER, icalendar.Calendar.from_ical)
@pytest.fixture
def timezones():
@ -56,6 +64,10 @@ def events():
def utc(request):
return request.param
@pytest.fixture
def calendars():
return DataSource(CALENDARS_FOLDER, icalendar.Calendar.from_ical)
@pytest.fixture(params=[
lambda dt, tzname: pytz.timezone(tzname).localize(dt),
lambda dt, tzname: dt.replace(tzinfo=tz.gettz(tzname)),
lambda dt, tzname: dt.replace(tzinfo=zoneinfo.ZoneInfo(tzname))
])
def in_timezone(request):
return request.param

Wyświetl plik

@ -1,78 +0,0 @@
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//Meetup//RemoteApi//EN
CALSCALE:GREGORIAN
METHOD:PUBLISH
X-ORIGINAL-URL:http://www.meetup.com/DevOpsDC/events/ical/DevOpsDC/
X-WR-CALNAME:Events - DevOpsDC
BEGIN:VTIMEZONE
TZID:America/New_York
TZURL:http://tzurl.org/zoneinfo-outlook/America/New_York
X-LIC-LOCATION:America/New_York
BEGIN:DAYLIGHT
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
DTSTART:19700308T020000
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=2SU
END:DAYLIGHT
BEGIN:STANDARD
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
DTSTART:19701101T020000
RRULE:FREQ=YEARLY;BYMONTH=11;BYDAY=1SU
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
DTSTAMP:20120605T003759Z
DTSTART;TZID=America/New_York:20120712T183000
DTEND;TZID=America/New_York:20120712T213000
STATUS:CONFIRMED
SUMMARY:DevOps DC Meetup
DESCRIPTION:DevOpsDC\nThursday\, July 12 at 6:30 PM\n\nThis will be a joi
nt meetup / hack night with the DC jQuery Users Group. The idea behind
the hack night: Small teams consisting of at least 1 member...\n\nDeta
ils: http://www.meetup.com/DevOpsDC/events/47635522/
CLASS:PUBLIC
CREATED:20120111T120339Z
GEO:38.90;-77.01
LOCATION:Fathom Creative\, Inc. (1333 14th Street Northwest\, Washington
D.C.\, DC 20005)
URL:http://www.meetup.com/DevOpsDC/events/47635522/
LAST-MODIFIED:20120522T174406Z
UID:event_qtkfrcyqkbnb@meetup.com
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20120605T003759Z
DTSTART;TZID=America/New_York:20120911T183000
DTEND;TZID=America/New_York:20120911T213000
STATUS:CONFIRMED
SUMMARY:DevOps DC Meetup
DESCRIPTION:DevOpsDC\nTuesday\, September 11 at 6:30 PM\n\n \n\nDetails:
http://www.meetup.com/DevOpsDC/events/47635532/
CLASS:PUBLIC
CREATED:20120111T120352Z
GEO:38.90;-77.01
LOCATION:CustomInk\, LLC (7902 Westpark Drive\, McLean\, VA 22102)
URL:http://www.meetup.com/DevOpsDC/events/47635532/
LAST-MODIFIED:20120316T202210Z
UID:event_qtkfrcyqmbpb@meetup.com
END:VEVENT
BEGIN:VEVENT
DTSTAMP:20120605T003759Z
DTSTART;TZID=America/New_York:20121113T183000
DTEND;TZID=America/New_York:20121113T213000
STATUS:CONFIRMED
SUMMARY:DevOps DC Meetup
DESCRIPTION:DevOpsDC\nTuesday\, November 13 at 6:30 PM\n\n \n\nDetails: h
ttp://www.meetup.com/DevOpsDC/events/47635552/
CLASS:PUBLIC
CREATED:20120111T120402Z
GEO:38.90;-77.01
LOCATION:CustomInk\, LLC (7902 Westpark Drive\, McLean\, VA 22102)
URL:http://www.meetup.com/DevOpsDC/events/47635552/
LAST-MODIFIED:20120316T202210Z
UID:event_qtkfrcyqpbrb@meetup.com
END:VEVENT
END:VCALENDAR

Wyświetl plik

@ -1,4 +1,5 @@
import pytest
import datetime
@pytest.mark.parametrize('field, expected_value', [
('PRODID', '-//Plönë.org//NONSGML plone.app.event//EN'),
@ -27,3 +28,41 @@ def test_events_parameter_unicoded(events):
https://github.com/collective/icalendar/issues/101
'''
assert events.issue_101_icalendar_chokes_on_umlauts_in_organizer['ORGANIZER'].params['CN'] == 'acme, ädmin'
def test_parses_event_with_non_ascii_tzid_issue_237(calendars, in_timezone):
"""Issue #237 - Fail to parse timezone with non-ascii TZID
see https://github.com/collective/icalendar/issues/237
"""
start = calendars.issue_237_fail_to_parse_timezone_with_non_ascii_tzid.walk('VEVENT')[0].decoded('DTSTART')
expected = in_timezone(datetime.datetime(2017, 5, 11, 13, 30), 'America/Sao_Paulo')
assert not calendars.issue_237_fail_to_parse_timezone_with_non_ascii_tzid.errors
assert start == expected
def test_parses_timezone_with_non_ascii_tzid_issue_237(timezones):
"""Issue #237 - Fail to parse timezone with non-ascii TZID
see https://github.com/collective/icalendar/issues/237
"""
assert timezones.issue_237_brazilia_standard['tzid'] == '(UTC-03:00) Brasília'
@pytest.mark.parametrize('timezone_name', ['standard', 'daylight'])
def test_parses_timezone_with_non_ascii_tzname_issue_273(timezones, timezone_name):
"""Issue #237 - Fail to parse timezone with non-ascii TZID
see https://github.com/collective/icalendar/issues/237
"""
assert timezones.issue_237_brazilia_standard.walk(timezone_name)[0]['TZNAME'] == f'Brasília {timezone_name}'
def test_broken_property(calendars):
"""
Test if error messages are encoded properly.
"""
for event in calendars.broken_ical.walk('vevent'):
assert len(event.errors) == 1, 'Not the right amount of errors.'
error = event.errors[0][1]
assert error.startswith('Content line could not be parsed into parts')
def test_apple_xlocation(calendars):
"""
Test if we support base64 encoded binary data in parameter values.
"""
for event in calendars.x_location.walk('vevent'):
assert len(event.errors) == 0, 'Got too many errors'

Wyświetl plik

@ -42,47 +42,3 @@ class TestIssues(unittest.TestCase):
event.to_ical(),
icalendar.Event.from_ical(event.to_ical()).to_ical()
)
def test_issue_237(self):
"""Issue #237 - Fail to parse timezone with non-ascii TZID"""
ical_str = ['BEGIN:VCALENDAR',
'BEGIN:VTIMEZONE',
'TZID:(UTC-03:00) Brasília',
'BEGIN:STANDARD',
'TZNAME:Brasília standard',
'DTSTART:16010101T235959',
'TZOFFSETFROM:-0200',
'TZOFFSETTO:-0300',
'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=3SA;BYMONTH=2',
'END:STANDARD',
'BEGIN:DAYLIGHT',
'TZNAME:Brasília daylight',
'DTSTART:16010101T235959',
'TZOFFSETFROM:-0300',
'TZOFFSETTO:-0200',
'RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SA;BYMONTH=10',
'END:DAYLIGHT',
'END:VTIMEZONE',
'BEGIN:VEVENT',
'DTSTART;TZID=\"(UTC-03:00) Brasília\":20170511T133000',
'DTEND;TZID=\"(UTC-03:00) Brasília\":20170511T140000',
'END:VEVENT',
'END:VCALENDAR',
]
cal = icalendar.Calendar.from_ical('\r\n'.join(ical_str))
self.assertEqual(cal.errors, [])
dtstart = cal.walk(name='VEVENT')[0].decoded("DTSTART")
expected = pytz.timezone('America/Sao_Paulo').localize(datetime.datetime(2017, 5, 11, 13, 30))
self.assertEqual(dtstart, expected)
try:
expected_zone = '(UTC-03:00) Brasília'
expected_tzname = 'Brasília standard'
except UnicodeEncodeError:
expected_zone = '(UTC-03:00) Brasília'.encode('ascii', 'replace')
expected_tzname = 'Brasília standard'.encode('ascii', 'replace')
self.assertEqual(dtstart.tzinfo.zone, expected_zone)
self.assertEqual(dtstart.tzname(), expected_tzname)

Wyświetl plik

@ -291,34 +291,3 @@ class IcalendarTestCase (unittest.TestCase):
'Max,Moller,"Rasmussen, Max"')
class TestEncoding(unittest.TestCase):
def test_broken_property(self):
"""
Test if error messages are encode properly.
"""
broken_ical = textwrap.dedent("""
BEGIN:VCALENDAR
BEGIN:VEVENT
SUMMARY:An Event with too many semicolons
DTSTART;;VALUE=DATE-TIME:20140409T093000
UID:abc
END:VEVENT
END:VCALENDAR
""")
cal = icalendar.Calendar.from_ical(broken_ical)
for event in cal.walk('vevent'):
self.assertEqual(len(event.errors), 1, 'Not the right amount of errors.')
error = event.errors[0][1]
self.assertTrue(error.startswith('Content line could not be parsed into parts'))
def test_apple_xlocation(self):
"""
Test if we support base64 encoded binary data in parameter values.
"""
directory = os.path.dirname(__file__)
with open(os.path.join(directory, 'x_location.ics'), 'rb') as fp:
data = fp.read()
cal = icalendar.Calendar.from_ical(data)
for event in cal.walk('vevent'):
self.assertEqual(len(event.errors), 0, 'Got too many errors')

Wyświetl plik

@ -1,27 +1,15 @@
"""An example with multiple VCALENDAR components"""
from icalendar import Calendar
from icalendar.prop import vText
import unittest
import os
class TestMultiple(unittest.TestCase):
"""A example with multiple VCALENDAR components"""
def test_multiple(self):
def test_multiple(calendars):
"""Check opening multiple calendars."""
directory = os.path.dirname(__file__)
with open(os.path.join(directory, 'multiple.ics'), 'rb') as fp:
data = fp.read()
cals = Calendar.from_ical(data, multiple=True)
cals = calendars.multiple.multiple_calendar_components
self.assertEqual(len(cals), 2)
self.assertSequenceEqual([comp.name for comp in cals[0].walk()],
['VCALENDAR', 'VEVENT'])
self.assertSequenceEqual([comp.name for comp in cals[1].walk()],
['VCALENDAR', 'VEVENT', 'VEVENT'])
self.assertEqual(
cals[0]['prodid'],
vText('-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN')
)
assert len(cals) == 2
assert [comp.name for comp in cals[0].walk()] == ['VCALENDAR', 'VEVENT']
assert [comp.name for comp in cals[1].walk()] == ['VCALENDAR', 'VEVENT', 'VEVENT']
assert cals[0]['prodid'] == vText('-//Mozilla.org/NONSGML Mozilla Calendar V1.0//EN')

Wyświetl plik

@ -0,0 +1,17 @@
BEGIN:VTIMEZONE
TZID:(UTC-03:00) Brasília
BEGIN:STANDARD
TZNAME:Brasília standard
DTSTART:16010101T235959
TZOFFSETFROM:-0200
TZOFFSETTO:-0300
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=3SA;BYMONTH=2
END:STANDARD
BEGIN:DAYLIGHT
TZNAME:Brasília daylight
DTSTART:16010101T235959
TZOFFSETFROM:-0300
TZOFFSETTO:-0200
RRULE:FREQ=YEARLY;INTERVAL=1;BYDAY=2SA;BYMONTH=10
END:DAYLIGHT
END:VTIMEZONE