Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/repo-cleaner.yml
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Delete old workflow runs
uses: Mattraks/delete-workflow-runs@v2
uses: Mattraks/delete-workflow-runs@v2.0.6
with:
retain_days: 15
keep_minimum_runs: 5
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -12,3 +12,5 @@ venv/
*coverage*

new/
AGENTS.md
QWEN.md
6 changes: 3 additions & 3 deletions tests/test_calendar_serialization.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

from .common import TEST_FILE_DIR, get_test_file

tzs_from_file = dateutil.tz.tzical(f"{TEST_FILE_DIR}/timezones.ics").get("US/Pacific")


def test_scratchbuild():
"""CreateCalendar 2.0 format from scratch"""
Expand All @@ -16,9 +18,7 @@ def test_scratchbuild():
cal.add("vevent")
cal.vevent.add("dtstart").value = dt.datetime(2006, 5, 9)
cal.vevent.add("description").value = "Test event"
cal.vevent.add("created").value = dt.datetime(
2006, 1, 1, 10, tzinfo=dateutil.tz.tzical(f"{TEST_FILE_DIR}/timezones.ics").get("US/Pacific")
)
cal.vevent.add("created").value = dt.datetime(2006, 1, 1, 10, tzinfo=tzs_from_file)
cal.vevent.add("uid").value = "Not very random UID"
cal.vevent.add("dtstamp").value = dt.datetime(2017, 6, 26, 0, tzinfo=tzutc())

Expand Down
2 changes: 1 addition & 1 deletion tests/test_change_tz.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from vobjectx.change_tz import change_tz


@dataclass
@dataclass(slots=True)
class Node:
value: str

Expand Down
4 changes: 1 addition & 3 deletions tests/test_cli.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,7 @@
import subprocess
from dataclasses import dataclass


@dataclass
class Cli:
class Cli: # pylint: disable=r0903
ics_diff = "ics_diff"
change_tz = "change_tz"

Expand Down
2 changes: 1 addition & 1 deletion tests/test_from_doctest.py
Original file line number Diff line number Diff line change
Expand Up @@ -127,4 +127,4 @@ def test_vcf_qp():
)
vcf = vo.read_one(vcf)
assert vcf.n.value == Name(given="é")
assert vcf.serialize() == "BEGIN:VCARD\r\nVERSION:2.1\r\nFN:é\r\nN:;é;;;\r\nTEL:0111111111\r\nEND:VCARD\r\n"
assert vcf.serialize() == "BEGIN:VCARD\r\nVERSION:2.1\r\nFN:é\r\nN:;é;;;\r\nTEL;HOME:0111111111\r\nEND:VCARD\r\n"
47 changes: 47 additions & 0 deletions tests/test_icalendar.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,13 @@
from random import sample

import dateutil
import pytest
from dateutil.rrule import MONTHLY, WEEKLY, rrule, rruleset

from vobjectx import base
from vobjectx.behavior import new_from_behavior
from vobjectx.datatypes import Period
from vobjectx.exceptions import ValidateError
from vobjectx.icalendar import (
RecurringComponent,
TimezoneComponent,
Expand Down Expand Up @@ -265,3 +267,48 @@ def test_issue50():
test_file = get_test_file("vobject_0050.ics")
cal = base.read_one(test_file)
assert dt.datetime(2024, 8, 12, 22, 30, tzinfo=UTC_TZ) == cal.vevent.dtend.value


def test_vevent_dtstart_recurrence_id_type_mismatch():
"""
Test that VEVENT validation fails when DTSTART and RECURRENCE-ID have different types.

DTSTART and RECURRENCE-ID must both be either datetime.date or datetime.datetime objects.
This test verifies the validation logic catches type mismatches.
"""
# TODO: may simplify into simple test after redesign
# Create a VEVENT with DTSTART as datetime and RECURRENCE-ID as date (should fail)
vevent = new_from_behavior("VEVENT")
vevent.add("dtstart").value = dt.datetime(2024, 1, 15, 10, 0)
vevent.add("dtstamp").value = dt.datetime(2024, 1, 15, 10, 0)
vevent.add("recurrence_id").value = dt.date(2024, 1, 22)
vevent.add("uid").value = "dfvbdfvbdfljb"

# Validation should raise a ValidateError
with pytest.raises(ValidateError, match="RECURRENCE-ID and DTSTART must be of same type"):
vevent.validate(raise_exception=True)

# Create a VEVENT with DTSTART as date and RECURRENCE-ID as datetime (should fail)
vevent2 = new_from_behavior("VEVENT")
vevent2.add("dtstart").value = dt.date(2024, 1, 15)
vevent2.add("recurrence_id").value = dt.datetime(2024, 1, 22, 10, 0)

# Validation should raise a ValidateError
with pytest.raises(ValidateError, match="RECURRENCE-ID and DTSTART must be of same type"):
vevent2.validate()

# Create a VEVENT with both as datetime (should pass)
# vevent3 = new_from_behavior("VEVENT")
vevent.dtstart.value = dt.datetime(2024, 1, 15, 10, 0)
vevent.recurrence_id.value = dt.datetime(2024, 1, 22, 10, 0)

# Validation should pass
vevent.validate()

# Create a VEVENT with both as date (should pass)
vevent4 = new_from_behavior("VEVENT")
vevent4.add("dtstart").value = dt.date(2024, 1, 15)
vevent4.add("recurrence_id").value = dt.date(2024, 1, 22)

# Validation should pass
vevent4.validate()
3 changes: 3 additions & 0 deletions tests/test_utils.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import datetime as dt
from io import StringIO
from zoneinfo import ZoneInfo

from dateutil.tz import tzutc

Expand All @@ -20,9 +21,11 @@ def test_date_to_string():


def test_datetime_to_string():
tz_0_offset = ZoneInfo("Africa/Dakar")
tc = {
(dt.datetime(2000, 10, 29, 3, 0), False): "20001029T030000",
(dt.datetime(2007, 3, 13, 12, 34, 32, tzinfo=tzutc()), True): "20070313T123432Z",
(dt.datetime(2000, 10, 29, 3, 0, tzinfo=tz_0_offset), False): "20001029T030000Z",
}
for inp, out in tc.items():
assert datetime_to_string(*inp) == out
Expand Down
2 changes: 1 addition & 1 deletion vobjectx/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,4 +95,4 @@ def vCard(): # pylint:disable=invalid-name
return new_from_behavior("vcard", "3.0")


__all__ = ["icalendar", "vcard", "read_components", "read_one", "new_from_behavior", "iCalendar", "vCard"]
__all__ = ["icalendar", "vcard", "read_components", "read_one", "new_from_behavior", "iCalendar", "vCard", "VERSION"]
Loading
Loading