pax_global_header 0000666 0000000 0000000 00000000064 15241340336 0014513 g ustar 00root root 0000000 0000000 52 comment=138c8453db34fbb584bbcbc592fd7bd4b972e8ef
collective-icalendar-138c845/ 0000775 0000000 0000000 00000000000 15241340336 0016045 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/.claude/ 0000775 0000000 0000000 00000000000 15241340336 0017360 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/.claude/settings.json 0000664 0000000 0000000 00000001035 15241340336 0022112 0 ustar 00root root 0000000 0000000 {
"hooks": {
"UserPromptSubmit": [
{
"hooks": [
{
"id": "ai-prompt-auto-commit",
"type": "command",
"command": "input=$(cat); ts=$(date +%Y-%m-%dT%H-%M-%S); model=$(printf '%s' \"$input\" | jq -r '.model // \"claude-sonnet-4-6\"'); root=$(git rev-parse --show-toplevel 2>/dev/null || pwd); mkdir -p \"$root/.prompts\"; printf '%s' \"$input\" | jq -r '.prompt' > \"$root/.prompts/${ts}_${model}.txt\"",
"version": "0.0.9"
}
]
}
]
}
}
collective-icalendar-138c845/.coveragerc 0000664 0000000 0000000 00000000257 15241340336 0020172 0 ustar 00root root 0000000 0000000 # Exclude type checking block
# See https://github.com/nedbat/coveragepy/issues/831#issuecomment-517778185
[report]
exclude_lines =
pragma: no cover
if TYPE_CHECKING: collective-icalendar-138c845/.github/ 0000775 0000000 0000000 00000000000 15241340336 0017405 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/.github/CODEOWNERS 0000664 0000000 0000000 00000002351 15241340336 0021001 0 ustar 00root root 0000000 0000000 # CODEOWNERS file for automatic PR review assignment
# See https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners
# Default owners
* @niccokunzmann @stevepiercy
# Documentation, except docstrings in `src`
*.md @stevepiercy
*.rst @stevepiercy
/.readthedocs.yml @stevepiercy @niccokunzmann
/.vale.ini @stevepiercy
/CONTRIBUTING.md @niccokunzmann @stevepiercy
/docs/ @stevepiercy
/docs/tutorials/ @stevepiercy @peskypotato
/Makefile @stevepiercy
/styles @stevepiercy
# Core calendar logic
/src/ @niccokunzmann @SashankBhamidi @stevepiercy @angatha
# Tests
/src/icalendar/tests/ @niccokunzmann @SashankBhamidi
# Fuzzing
/src/icalendar/fuzzing/ @ennamarie19 @niccokunzmann @SashankBhamidi
# CI and infrastructure
/.coveragerc @niccokunzmann
/.github/ @niccokunzmann @SashankBhamidi @stevepiercy
/.pre-commit-config.yaml @niccokunzmann @SashankBhamidi @stevepiercy
/bootstrap.py @niccokunzmann @stevepiercy
/buildout.cfg @niccokunzmann @stevepiercy
/pyproject.toml @niccokunzmann @stevepiercy
/tox.ini @niccokunzmann @stevepiercy
# Security
/SECURITY.md @niccokunzmann @stevepiercy @angatha
# Release stuff
/CHANGES.rst @niccokunzmann @stevepiercy
/MANIFEST.in @niccokunzmann
collective-icalendar-138c845/.github/FUNDING.yml 0000664 0000000 0000000 00000001501 15241340336 0021217 0 ustar 00root root 0000000 0000000 # These are supported funding model platforms
github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
patreon: # Replace with a single Patreon username
open_collective: python-icalendar
ko_fi: # Replace with a single Ko-fi username
tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
liberapay: # Replace with a single Liberapay username
issuehunt: # Replace with a single IssueHunt username
lfx_crowdfunding: # Replace with a single LFX Crowdfunding project-name e.g., cloud-foundry
polar: # Replace with a single Polar username
buy_me_a_coffee: # Replace with a single Buy Me a Coffee username
custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
collective-icalendar-138c845/.github/ISSUE_TEMPLATE/ 0000775 0000000 0000000 00000000000 15241340336 0021570 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/.github/ISSUE_TEMPLATE/bug_report.md 0000664 0000000 0000000 00000003100 15241340336 0024254 0 ustar 00root root 0000000 0000000 ---
name: Bug report
about: Create a bug report to help us improve icalendar
title: '[Bug] '
labels: ''
assignees: ''
type: 'Bug'
---
## Describe the bug
## To reproduce
```python
import icalendar
### ...
```
Output:
```pycon
```
## Expected behavior
## Environment
- [ ] Operating system:
- [ ] Python version:
- [ ] `icalendar` version:
## Additional context
- [ ] I tested it with the latest version. For example, I used the command `pip3 install --upgrade https://github.com/collective/icalendar.git`.
- [ ] I attached the `.ics` sample file, or there is no `.ics` sample file.
To remove private information, use icalendar-anonymizer either through its [website](https://icalendar-anonymizer.com/) or [install it locally](https://docs.icalendar-anonymizer.com/latest/installation.html). collective-icalendar-138c845/.github/ISSUE_TEMPLATE/config.yml 0000664 0000000 0000000 00000000271 15241340336 0023560 0 ustar 00root root 0000000 0000000 blank_issues_enabled: false
contact_links:
- name: Discussions
url: https://github.com/collective/icalendar/discussions
about: For questions, ideas, and community discussions
collective-icalendar-138c845/.github/ISSUE_TEMPLATE/empty-issue.md 0000664 0000000 0000000 00000001270 15241340336 0024376 0 ustar 00root root 0000000 0000000 ---
name: Blank issue
about: Unstructured template for anything not covered by bug reports
title: ''
labels: ''
assignees: ''
---
collective-icalendar-138c845/.github/assistant-guidelines.md 0000664 0000000 0000000 00000004677 15241340336 0024104 0 ustar 00root root 0000000 0000000 ---
version: "0.0.8"
---
# Assistant guidelines for `.prompts` storage
These guidelines tell the assistant exactly how to write prompt files in this repository.
- Store every user prompt in the `.prompts/` directory.
- Use one file per prompt.
- When a user prompt is received, automatically create a new file in `.prompts/`.
- File names must follow the pattern:
`YYYY-MM-DDTHH-MM-SS-XXX_raptor-mini-preview.txt`
- `_` and `T` are important.
- `XXX` is a zero-padded sequence number.
- `YYYY-MM-DD` is the current date.
- `HH-MM-SS` is the current time.
- `raptor-mini-preview` is the model name.
Replace this model name with the actual AI model that you use.
- Use `date +%Y-%m-%d%H-%M-%S` to get the current date and time.
- File content must contain only the raw prompt text from the user.
- Do not add headings, bullets, annotations, or any markup.
- Do not store assistant responses or metadata inside these files.
- If a file name already exists, choose the next available sequence number.
- If `.prompts/` does not exist, create it.
- `.prompts/committed` is reserved for prompts that are already included in commit messages.
- Do not create new user prompt files in `.prompts/committed`.
- Do not duplicate `.prompts/committed` entries as files directly in `.prompts/`.
- Do not use `/memories/` or any workspace-local memory for this storage rule.
- For a fresh clone, use this file as the canonical instruction source.
- If the user asks to store new prompts, then assure there is one file for each and all of the uncommitted prompts of that session.
- Read the latest prompt file and find the prompts in your memory. Then store all prompts that came after this.
- Use the following command to find the latest prompt file:
```shell
(find .prompts -maxdepth 1 -type f -printf '%f\n'; find .prompts/committed/ -maxdepth 1 -type f -printf '%f\n' ) | sort
```
- Check that prompts that are in the `.prompts/` directory are not duplicates.
- Create a new file for each prompt that was prompted to you by the user in this session if it does not already exist.
- Follow all above guidelines.
- Saying "Store all prompts" or "Store new prompts" or "dump prompts" or "save prompts" means this:
> Read the last stored prompt that you stored and from that prompt onward, for this chat, create a new prompt file according to the assistant guidelines for each prompt that I have written since.
collective-icalendar-138c845/.github/dependabot.yml 0000664 0000000 0000000 00000001006 15241340336 0022232 0 ustar 00root root 0000000 0000000 # https://docs.github.com/en/code-security/dependabot/working-with-dependabot/keeping-your-actions-up-to-date-with-dependabot
# https://docs.github.com/en/code-security/dependabot/dependabot-version-updates/configuration-options-for-the-dependabot.yml-file#package-ecosystem
version: 2
updates:
- package-ecosystem: github-actions
directory: /
groups:
github-actions:
patterns:
- "*" # Group all Actions updates into a single larger pull request
schedule:
interval: weekly
collective-icalendar-138c845/.github/pull_request_template.md 0000664 0000000 0000000 00000004451 15241340336 0024352 0 ustar 00root root 0000000 0000000 ` delimiters, inclusively, may be removed.
-->
## Linked issue
- Closes #ISSUE_NUMBER
- See #ISSUE_NUMBER
## Description
## Checklist
- [ ] I added a change log entry, following the instructions in [Change log entry format](https://icalendar.readthedocs.io/en/latest/contribute/#change-log-entry-format).
- [ ] I followed icalendar's [Artificial intelligence policy](https://icalendar.readthedocs.io/en/latest/contribute/index.html#artificial-intelligence-policy) and disclosed my [Responsible AI use](https://icalendar.readthedocs.io/en/latest/contribute/index.html#responsible-ai-use) in my commit messages, if applicable.
- [ ] I added or updated tests, if applicable.
- [ ] I ran and ensured all tests pass locally by following [Run tests](https://icalendar.readthedocs.io/en/latest/contribute/development.html#run-tests).
- [ ] I added or edited documentation as necessary, both as docstrings to be rendered in the API documentation and narrative documentation, following the [Style guide](https://icalendar.readthedocs.io/en/latest/contribute/documentation/style-guide.html).
## Additional information
Upload screenshots, videos, links to documentation, or any other relevant information.
collective-icalendar-138c845/.github/workflows/ 0000775 0000000 0000000 00000000000 15241340336 0021442 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/.github/workflows/cifuzz.yml 0000664 0000000 0000000 00000002356 15241340336 0023505 0 ustar 00root root 0000000 0000000 name: CIFuzz
on: [pull_request]
permissions: {}
jobs:
Fuzzing:
runs-on: ubuntu-latest
permissions:
security-events: write
steps:
- name: Build Fuzzers
id: build
uses: google/oss-fuzz/infra/cifuzz/actions/build_fuzzers@master
with:
oss-fuzz-project-name: 'icalendar'
language: python
- name: Run Fuzzers
uses: google/oss-fuzz/infra/cifuzz/actions/run_fuzzers@master
with:
oss-fuzz-project-name: 'icalendar'
language: python
fuzz-seconds: 600
output-sarif: true
- name: Upload Crash
uses: actions/upload-artifact@v7
if: failure() && steps.build.outcome == 'success'
with:
name: artifacts
path: ./out/artifacts
- name: Upload Sarif
if: always() && steps.build.outcome == 'success'
uses: github/codeql-action/upload-sarif@v4
with:
# Path to SARIF file relative to the root of the repository
sarif_file: cifuzz-sarif/results.sarif
checkout_path: cifuzz-sarif
check-distribution:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Do not include Apache files in the distribution.
run: |
src/icalendar/tests/test_create_release.sh
collective-icalendar-138c845/.github/workflows/documentation.yml 0000664 0000000 0000000 00000003220 15241340336 0025033 0 ustar 00root root 0000000 0000000 name: Check news fragments filenames, build documentation, check links, spelling, grammar, and style
on:
push:
branches:
- main
paths:
- 'docs/**'
# Build pull requests
pull_request:
paths:
- 'docs/**'
- 'Makefile'
- 'src/icalendar/*.py'
- 'src/icalendar/cal/*.py'
- 'src/icalendar/prop/*.py'
- 'src/icalendar/timezone/*.py'
- 'styles/**'
- '.github/workflows/documentation.yml'
- '.readthedocs.yaml'
- '.vale.ini'
- 'uv.lock'
- 'news/*.*'
jobs:
docs:
name: Documentation
runs-on: ubuntu-latest
strategy:
matrix:
python-version: ['3.11', '3.14']
steps:
- uses: actions/checkout@v7
with:
fetch-depth: 0
fetch-tags: true
- name: Install uv
uses: astral-sh/setup-uv@v7
with:
# Install a specific version of uv.
version: "0.9.3"
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: ${{ matrix.python-version }}
- name: Create Python virtual environment, install requirements
run: make .venv PYTHONVERSION=${{ matrix.python-version }}
- name: Check news fragments filenames
run: make changes-check PYTHONVERSION=${{ matrix.python-version }}
- name: Build HTML documentation
run: make html PYTHONVERSION=${{ matrix.python-version }}
- name: Run vale
run: make vale VALEOPTS="--minAlertLevel='warning'" PYTHONVERSION=${{ matrix.python-version }}
- name: Check for broken links
run: make linkcheckbroken PYTHONVERSION=${{ matrix.python-version }}
collective-icalendar-138c845/.github/workflows/generate_matrix.py 0000775 0000000 0000000 00000010530 15241340336 0025174 0 ustar 00root root 0000000 0000000 #!/usr/bin/env python3
"""Generate the test matrix.
Parameters:
0: The branch or tag that triggered the workflow
1: The state of the pull request
Documentation:
- for python versions
https://github.com/actions/setup-python/tree/v6/?tab=readme-ov-file#basic-usage
- for pull request approval
https://stackoverflow.com/a/70441157/1320237
Run tests with:
pytest .github/workflows/test_generate_matrix.py
"""
import json
import re
import sys
#
# Configuration
#
PYTHON_MINOR_VERSION_MIN = 10
# Update this when a new Python minor version is released
PYTHON_MINOR_VERSION_MAX = 14
COMMAND_TEST = "uv run tox -e py"
def generate_matrix(git_ref, review):
"""Generate a matrix of test runs.
Parameters:
arg_ref: The branch or tag that triggered the workflow
arg_pr: The state of the pull request
"""
#
# Analyze the reference
#
runs_on_main = git_ref == "refs/heads/main"
runs_on_stable = bool(re.match(r"refs/heads/\d+\.x", git_ref))
runs_on_release = git_ref.startswith("refs/heads/release-")
runs_on_tag = git_ref.startswith("refs/tags/v")
#
# Analyze the trigger
#
# Analyze the review that triggered the workflow
review_submitted = review != ""
review_approved = review == "approved"
# Which push to a branch or tag triggered the workflow
# The trigger is either a push or a review, never both
triggered_by_push_to_main = runs_on_main and not review_submitted
triggered_by_push_to_release = runs_on_release and not review_submitted
triggered_by_push_to_stable = runs_on_stable and not review_submitted
triggered_by_push_to_tag = runs_on_tag and not review_submitted
run_all_jobs = (
triggered_by_push_to_tag
or triggered_by_push_to_main
or triggered_by_push_to_release
or triggered_by_push_to_stable
or review_approved
)
run_no_jobs = review_submitted and not review_approved
#
# Debug conditions
#
for k, v in sorted(locals().items()):
if isinstance(v, (bool, str, int)) and not k.startswith("_"):
print(f"{k} = {v!r}") # noqa: T201
#
# Create matrix
#
matrix: list[dict[str, str | bool]] = []
#
# minimal set of jobs
#
# RULE: always test the lowest allowed version
matrix.append(
{
"python_version": f"3.{PYTHON_MINOR_VERSION_MIN}",
"skip": run_no_jobs,
}
)
# RULE: use lowest allowed version for nopytz
matrix.append(
{
"test_command": "uv run tox -e nopytz",
"test_name": f"3.{PYTHON_MINOR_VERSION_MIN} (nopytz)",
"python_version": f"3.{PYTHON_MINOR_VERSION_MIN}",
"skip": run_no_jobs,
}
)
# RULE: always test the latest version
matrix.append(
{
"python_version": f"3.{PYTHON_MINOR_VERSION_MAX}",
"skip": run_no_jobs,
}
)
#
# create full job list if required
#
for minor_python_version in range(
PYTHON_MINOR_VERSION_MIN + 1, PYTHON_MINOR_VERSION_MAX
):
matrix.append(
{
"python_version": f"3.{minor_python_version}",
"skip": not run_all_jobs,
}
)
# pypy is slow but good to test
matrix.insert(
0,
{
"python_version": "pypy3.11",
"test_name": "pypy3",
"skip": not run_all_jobs,
},
)
#
# Generate tests names for the matrix
#
# Note: If you change test names, also make sure that the
# branch protection rules are adjusted to the new names.
# https://github.com/collective/icalendar/settings/branches
#
for run in matrix:
run.setdefault("test_name", run["python_version"])
run.setdefault("test_command", COMMAND_TEST)
include = list(matrix)
skipped = [run["test_name"] for run in matrix if run["skip"]]
return {"include": include, "skipped": skipped}
if __name__ == "__main__":
#
# always debug to stderr
#
stdout = sys.stdout
sys.stdout = sys.stderr
#
# Parse parameters
#
arg_ref = sys.argv[1] # github.ref
arg_review = sys.argv[2] # github.event.review.state
matrix = generate_matrix(arg_ref, arg_review)
print(json.dumps(matrix, indent=2)) # noqa: T201
stdout.write(json.dumps(matrix))
collective-icalendar-138c845/.github/workflows/pr-quality.yml 0000664 0000000 0000000 00000002442 15241340336 0024276 0 ustar 00root root 0000000 0000000 # This workflow checks the quality of pull requests.
# For configuration options, see:
# https://github.com/marketplace/actions/anti-slop
name: PR Quality
permissions:
contents: read
issues: read
pull-requests: write
on:
pull_request_target:
types: [opened, reopened]
jobs:
anti-slop:
runs-on: ubuntu-latest
steps:
- uses: peakoss/anti-slop@v0
with:
max-failures: 1
max-description-length: 1500
max-emoji-count: 1
max-code-references: 3
require-linked-issue: true
require-pr-template: true
strict-pr-template-sections: Linked issue,Description,Checklist
optional-pr-template-sections: 'Additional information'
blocked-commit-authors: github-automation@zo.computer
max-daily-forks: 3
exempt-users: abe-101,angatha,niccokunzmann,sashankbhamidi,stevepiercy,maurits,tobixen
success-add-pr-labels: 'PR quality: good'
failure-add-pr-labels: 'ai-suspicion'
failure-pr-message: 'This pull request did not pass quality checks and AI use is suspected. Please review [Contribute](https://icalendar.readthedocs.io/en/latest/contribute/index.html) and make any necessary amendments.'
close-pr: false
min-profile-completeness: 1
collective-icalendar-138c845/.github/workflows/profile-contributors.yml 0000664 0000000 0000000 00000004040 15241340336 0026356 0 ustar 00root root 0000000 0000000 # Run gh-profiler against the author of each new issue and PR.
# See https://github.com/ehmatthes/gh-profiler
name: Profile contributors
on:
issues:
types: [opened]
pull_request_target:
types: [opened]
permissions:
contents: read
issues: write
pull-requests: write
jobs:
profile-author:
runs-on: ubuntu-latest
steps:
- uses: astral-sh/setup-uv@d0d8abe699bfb85fec6de9f7adb5ae17292296ff # v6
- name: Install gh-profiler
run: uv tool install gh-profiler==0.8.3
- name: Determine target login and issue number
id: meta
run: |
set -euo pipefail
if [ "${{ github.event_name }}" = "issues" ]; then
echo "login=${{ github.event.issue.user.login }}" >> "$GITHUB_OUTPUT"
echo "number=${{ github.event.issue.number }}" >> "$GITHUB_OUTPUT"
else
echo "login=${{ github.event.pull_request.user.login }}" >> "$GITHUB_OUTPUT"
echo "number=${{ github.event.pull_request.number }}" >> "$GITHUB_OUTPUT"
fi
- name: Run gh-profiler
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
gh-profiler "${{ steps.meta.outputs.login }}" --concise > concise.txt
gh-profiler "${{ steps.meta.outputs.login }}" > full.txt
- name: Comment on issue or PR
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
set -euo pipefail
{
echo "Profile summary:"
echo
echo '```text'
cat concise.txt
echo '```'
echo
echo ''
echo 'Full profile
'
echo
echo '```text'
cat full.txt
echo '```'
echo
echo ' '
} > body.txt
jq -Rs '{body: .}' body.txt > payload.json
gh api \
repos/${{ github.repository }}/issues/${{ steps.meta.outputs.number }}/comments \
--input payload.json
collective-icalendar-138c845/.github/workflows/ruff.yml 0000664 0000000 0000000 00000002274 15241340336 0023134 0 ustar 00root root 0000000 0000000 name: Check code style with ruff
on: [push, pull_request]
jobs:
ruff:
runs-on: ubuntu-latest
env:
MESSAGE: |
Your code is not formatted!
Please set up your development environment and run the formatting command.
https://icalendar.readthedocs.io/en/stable/contribute/development.html#code-format
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: 3.14
cache: pip
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install . --group formatting
sudo apt install -y git-delta
- name: Run the ruff formatter to change files
run: ruff format .
- name: Fail if we detect any changes on the file system
run: |
git diff | delta --light --keep-plus-minus-markers
if ! git diff --exit-code --quiet; then
echo "$MESSAGE"
exit 1;
fi
env:
FORCE_COLOR: '1'
- name: Run ruff checks on the files
run: |
if ! ruff check; then
echo "$MESSAGE"
exit 1;
fi
collective-icalendar-138c845/.github/workflows/test_generate_matrix.py 0000664 0000000 0000000 00000007564 15241340336 0026245 0 ustar 00root root 0000000 0000000 """Test that we get the right output under all conditions.
Run with:
pytest .github/workflows/test_generate_matrix.py
"""
import pytest
from generate_matrix import generate_matrix
CASES_ALL = {"3.10", "3.11", "3.12", "3.13", "3.14", "3.10 (nopytz)", "pypy3"}
CASES_MIN = {"3.10", "3.14", "3.10 (nopytz)"}
CASES_0 = set()
@pytest.fixture(
params=[
# push
("", CASES_ALL, "refs/heads/main"),
("", CASES_ALL, "refs/heads/7.x"),
("", CASES_ALL, "refs/heads/6.x"),
("", CASES_ALL, "refs/heads/5.x"),
("", CASES_ALL, "refs/heads/release-1"),
("", CASES_ALL, "refs/tags/v7.0.2"),
("", CASES_MIN, "refs/heads/pr-branch"),
# review
("changes_requested", CASES_0, "refs/heads/main"),
("changes_requested", CASES_0, "refs/heads/7.x"),
("changes_requested", CASES_0, "refs/heads/6.x"),
("changes_requested", CASES_0, "refs/heads/5.x"),
("changes_requested", CASES_0, "refs/heads/release-2"),
("changes_requested", CASES_0, "refs/tags/v7.0.2"),
("changes_requested", CASES_0, "refs/heads/pr-branch"),
("approved", CASES_ALL, "refs/heads/main"),
("approved", CASES_ALL, "refs/heads/7.x"),
("approved", CASES_ALL, "refs/heads/6.x"),
("approved", CASES_ALL, "refs/heads/5.x"),
("approved", CASES_ALL, "refs/heads/release-3"),
("approved", CASES_ALL, "refs/tags/v7.0.2"),
("approved", CASES_ALL, "refs/heads/pr-branch"),
],
)
def cases(request):
"""All test cases."""
return request.param
@pytest.fixture
def arg_pr(cases):
"""The pr event name."""
return cases[0]
@pytest.fixture
def arg_ref(cases):
"""The branch or tag reference."""
return cases[2]
@pytest.fixture
def expected(cases):
"""All expected case names."""
return cases[1]
@pytest.fixture
def matrix(arg_ref, arg_pr):
"""The generated test matrix."""
matrix = generate_matrix(arg_ref, arg_pr)
print("Cases:")
for case in sorted(matrix["include"], key=lambda case: case["test_name"]):
print(f"- running\t{case['test_name']}")
for case in sorted(matrix["skipped"]):
print(f"- skipped\t{case}")
return matrix
@pytest.fixture
def skipped_names(matrix):
"""All skipped test cases."""
return set(matrix["skipped"])
@pytest.fixture
def running_names(matrix):
"""All running test cases"""
return {case["test_name"] for case in matrix["include"] if not case["skip"]}
def test_count_test_runs(running_names, expected):
"""Check which values we get."""
assert running_names == expected, (
f"Expected {len(expected)} test runs, got {len(running_names)}"
)
def test_running_is_not_skipped(running_names, skipped_names):
"""Running means not skipped."""
assert running_names.isdisjoint(skipped_names)
def test_all_cases_are_always_included(running_names, skipped_names, matrix):
"""The matrix always needs to be complete or we might wait for required checks."""
assert running_names | skipped_names == CASES_ALL
all_in_matrix = {case["test_name"] for case in matrix["include"]}
assert all_in_matrix == CASES_ALL
@pytest.mark.parametrize(
"attribute",
[
"test_name",
"python_version",
"skip",
"test_command",
],
)
def test_parameters_are_present(matrix, attribute):
for case in matrix["include"]:
assert attribute in case, f"Missing {attribute} in {case}"
@pytest.mark.parametrize(
("arg_pr", "arg_ref"),
[
# push
("", "refs/heads/main"),
("approved", "refs/heads/6.x"),
],
)
def test_pypy_is_first(arg_ref, arg_pr):
"""PyPy takes longest to run, so it should be triggered first.
See https://github.com/collective/icalendar/pull/1239#discussion_r2868711107
"""
result = generate_matrix(arg_ref, arg_pr)
assert result["include"][0]["test_name"] == "pypy3"
collective-icalendar-138c845/.github/workflows/tests.yml 0000664 0000000 0000000 00000013346 15241340336 0023336 0 ustar 00root root 0000000 0000000 name: tests
on:
push:
branches:
- main
- 7.x
tags:
- v*
pull_request:
schedule:
- cron: '14 7 * * 0' # run once a week on Sunday
workflow_dispatch:
pull_request_review:
types: [submitted]
jobs:
generate-matrix:
runs-on: ubuntu-latest
outputs:
# See https://docs.github.com/en/actions/writing-workflows/choosing-what-your-workflow-does/passing-information-between-jobs#example-defining-outputs-for-a-job
include: ${{ steps.set-matrix.outputs.include }}
steps:
- uses: actions/checkout@v7
- name: Set matrix
id: set-matrix
run: |
matrix_json="$(python .github/workflows/generate_matrix.py '${{ github.ref }}' '${{ github.event.review.state }}' )"
echo "include=$(echo "$matrix_json" | python -c 'import json,sys; print(json.dumps(json.load(sys.stdin)["include"]))')" >> $GITHUB_OUTPUT
run-tests:
needs: generate-matrix
strategy:
matrix:
include: ${{ fromJSON(needs.generate-matrix.outputs.include) }}
runs-on: ubuntu-latest
name: ${{ matrix.test_name }}
steps:
- name: Skip notice
if: ${{ matrix.skip }}
run: echo "Skipped ${{ matrix.test_name }} (not required for this trigger)"
- uses: actions/checkout@v7
if: ${{ !matrix.skip }}
- name: Install uv and Python ${{ matrix.python_version }}
if: ${{ !matrix.skip }}
uses: astral-sh/setup-uv@v7
with:
enable-cache: true
# Install a specific version of uv.
version: "0.11.6"
python-version: ${{ matrix.python_version }}
- name: Install dependencies
if: ${{ !matrix.skip }}
run: |
make dev PYTHONVERSION=${{ matrix.python_version }}
uv tree
- name: Test
if: ${{ !matrix.skip }}
run: ${{ matrix.test_command }}
- name: Coveralls Parallel
if: ${{ !matrix.skip }}
uses: coverallsapp/github-action@v2
with:
flag-name: run-${{ matrix.test_name }}
parallel: true
file: coverage.xml
allow-empty: true
fail-on-error: false
coverage:
# parallel test coverage upload
# see https://coveralls-python.readthedocs.io/en/latest/usage/configuration.html#github-actions-support
name: Submit test coverage
needs: run-tests
# always finalize coverage aftest tests ran
# see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-not-requiring-successful-dependent-jobs
if: ${{ always() }}
runs-on: ubuntu-latest
steps:
- name: Coveralls Finished
uses: coverallsapp/github-action@v2
with:
parallel-finished: true
format: cobertura
fail-on-error: false
test-distribution:
name: Check built package
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.14"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: Build distribution files
run: python -m build # same as in deploy-tag-to-pypi
- name: Check distribution files
run: twine check dist/*
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
- test-distribution
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@v7
- name: Set up Python
uses: actions/setup-python@v7
with:
python-version: "3.14"
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install build twine
- name: remove old files
run: rm -rf dist/*
- name: build distribution files
run: python -m build # same as in test-distribution
- 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/*
deploy-github-release:
# only deploy on tags, see https://stackoverflow.com/a/58478262/1320237
if: startsWith(github.ref, 'refs/tags/v')
needs:
- run-tests
- test-distribution
runs-on: ubuntu-latest
environment:
name: github-release
steps:
- uses: actions/checkout@v7
- name: Create GitHub release from tag
uses: ncipollo/release-action@v1
with:
allowUpdates: true
body: "To view the changes, please see the [Changelog](https://icalendar.readthedocs.io/en/latest/reference/changelog.html). This release can be installed from [PyPI](https://pypi.org/project/icalendar/#history)."
generateReleaseNotes: false
collective-icalendar-138c845/.github/workflows/zizmor.yml 0000664 0000000 0000000 00000001353 15241340336 0023521 0 ustar 00root root 0000000 0000000 name: zizmor static analysis
on:
pull_request:
push:
branches: [main]
permissions:
contents: read
jobs:
zizmor:
runs-on: ubuntu-latest
permissions:
contents: read
security-events: write
steps:
- name: Checkout repository
uses: actions/checkout@3d3c42e5aac5ba805825da76410c181273ba90b1 # v7.0.1
with:
persist-credentials: false
- name: Install zizmor
run: pip install zizmor==1.29.0
- name: Run zizmor
run: zizmor --format sarif .github/workflows/ > zizmor-results.sarif
- name: Upload SARIF file
uses: github/codeql-action/upload-sarif@f205ea1c3313d32999d8d6a48b4f6530d4437b38
with:
sarif_file: zizmor-results.sarif
collective-icalendar-138c845/.gitignore 0000664 0000000 0000000 00000000630 15241340336 0020034 0 ustar 00root root 0000000 0000000 *.mo
*.py?
*.sw?
*~
.*
_build/
bin/
build/
coverage-*
develop-eggs/
dist/
eggs/
htmlcov/
include/
lib/
lib64
parts/
pip-selfcheck.json
src/icalendar.egg-info/
!.gitattributes
!.github
!.gitignore
venv
/docs/styles/Microsoft/
/ical_fuzzer.pkg.spec
/src/icalendar/_version.py
uv.lock
coverage.xml
!.coveragerc
!.well-known
/.prompts/
/ical_fuzzer/
# from tutorials
/example.ics
!.claude/
!.claude/settings.json collective-icalendar-138c845/.pre-commit-config.yaml 0000664 0000000 0000000 00000001313 15241340336 0022324 0 ustar 00root root 0000000 0000000 default_install_hook_types: [pre-commit, prepare-commit-msg, post-commit]
repos:
- repo: https://github.com/pycalendar/ai-prompt-auto-commit
rev: v0.0.9
hooks:
- id: prepare-ai-repository
- id: unstage-ai-prompts
- id: append-ai-prompts
- id: archive-ai-prompts
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: debug-statements
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.15.2 # also update pyproject.toml
hooks:
# Run the linter.
- id: ruff-check
args: [--config, "pyproject.toml", --fix]
# Run the formatter.
- id: ruff-format
args: [--config, "pyproject.toml"]
collective-icalendar-138c845/.readthedocs.yml 0000664 0000000 0000000 00000002357 15241340336 0021142 0 ustar 00root root 0000000 0000000 # .readthedocs.yml
# Read the Docs configuration file
# See https://docs.readthedocs.io/en/stable/config-file/v2.html for details
# Required
version: 2
# Optionally build your docs in additional formats such as PDF and ePub
formats: all
build:
os: ubuntu-22.04
tools:
python: "3.13"
commands:
# Cancel building pull requests when there aren't changes in the docs directory or YAML file.
# You can add any other files or directories that you'd like here as well,
# like your docs requirements file, or other files that will change your docs build.
#
# If there are no changes (git diff exits with 0) we force the command to return with 183.
# This is a special exit code on Read the Docs that will cancel the build immediately.
- |
if [ "$READTHEDOCS_VERSION_TYPE" = "external" ] && git diff --quiet origin/main -- . docs/ \
src/icalendar/**/*.py \
.github/workflows/documentation.yml \
.readthedocs.yml \
.vale.ini \
CHANGES.rst \
Makefile \
pyproject.toml \
':!src/icalendar/fuzzing' \
':!src/icalendar/tests' \
':!src/icalendar/timezone';
then
exit 183;
fi
- git fetch --tags || true
- make rtd-pr-preview
collective-icalendar-138c845/.vale.ini 0000664 0000000 0000000 00000000627 15241340336 0017560 0 ustar 00root root 0000000 0000000 StylesPath = docs/styles
MinAlertLevel = suggestion
Vocab = Base,icalendar
Packages = Microsoft
[*]
BasedOnStyles = Vale, Microsoft
Microsoft.Contractions = suggestion
Microsoft.GeneralURL = No
Microsoft.Units = suggestion
# Ignore Sphinx Python object roles, such as ":class:" and ":meth:",
# to prevent false positives from Microsoft.Spacing on dotted Python names.
TokenIgnores = :[a-z]+:\x60.+\x60
collective-icalendar-138c845/.well-known/ 0000775 0000000 0000000 00000000000 15241340336 0020220 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/.well-known/funding-manifest-urls 0000664 0000000 0000000 00000000075 15241340336 0024366 0 ustar 00root root 0000000 0000000 https://github.com/collective/icalendar/raw/main/funding.json collective-icalendar-138c845/CHANGES.rst 0000664 0000000 0000000 00000341130 15241340336 0017651 0 ustar 00root root 0000000 0000000 ==========
Change log
==========
.. py:currentmodule:: icalendar
.. Do *NOT* add new change log entries to this file.
Instead create a file in the news directory.
For helpful instructions, see:
https://icalendar.readthedocs.io/en/latest/contribute/#change-log-entry-format
.. towncrier release notes start
7.3.0 (2026-08-19)
------------------
Removals and deprecations
~~~~~~~~~~~~~~~~~~~~~~~~~
- :attr:`~icalendar.prop.binary.vBinary.obj` is deprecated in favor of :attr:`~icalendar.prop.binary.vBinary.bytes`. It is retained as a lossy string view of the value for backward compatibility, and will be removed in icalendar 8. The ``test_ical_value_rejects_non_base64_characters`` test was removed because :attr:`vBinary.ical_value ` no longer validates or decodes Base64. @uwezkhan (`Issue #1356 `_)
- `Issue #1362 `_
New features
~~~~~~~~~~~~
- Created an :meth:`~cal.journal.Journal.example` method for the :class:`~cal.journal.Journal` component and an :meth:`~cal.free_busy.FreeBusy.example` method for the :class:`~cal.free_busy.FreeBusy` component, added the :rfc:`5545` examples that they load, and documented their usage in both class docstrings. AI assistance: Kiro CLI with the claude-opus-5 model was used to draft this change. @Souptik96 (`Issue #743 `_)
- Add :meth:`Alarm.new_display() `, :meth:`Alarm.new_audio() `, and :meth:`Alarm.new_email() ` factory methods for creating :rfc:`5545#section-3.6.6` VALARM components. @klouds27 (`Issue #865 `_)
- :class:`~icalendar.prop.binary.vBinary` now stores the raw ``bytes`` of the value internally, so non-UTF-8 binary data round-trips losslessly. With the release of icalendar 7.1.0, and previous to this bug fix, :attr:`vBinary.ical_value ` Base64-decoded the raw stored bytes and raised :class:`ValueError` for non-Base64 input. :attr:`vBinary.ical_value ` now returns the raw stored bytes instead of Base64-decoding them, and no longer raises :class:`ValueError` for non-Base64 input. @uwezkhan (`Issue #1356 `_)
- Added :attr:`icalendar.prop.binary.vBinary.bytes`, exposing the raw binary value of a BINARY property. @uwezkhan (`Issue #1356 `_)
- Added the :exc:`~icalendar.error.ICalParsingError` exception as a public API for programmatic handling of iCalendar parsing failures. AI assistance: ChatGPT was used to help debug terminal errors encountered during development. @GAUTAMSANSWAL (`Issue #1536 `_)
- Created a script to automatically generate the :mod:`~icalendar.timezone.windows_to_olson` module from the Unicode Consortium's CLDR GitHub repository. Added lxml as a new development dependency. Added the target ``wo`` to the ``Makefile`` to generate the file from the root of the repository with `make wo`. @stevepiercy (`Issue #1548 `_)
- Added :attr:`vBinary.base64data `, a getter/setter for the Base64 string view of a BINARY property's value, so callers no longer need to call :func:`base64.b64encode` or :func:`base64.b64decode` manually. @gagana2023 (`Issue #1550 `_)
- Added :attr:`Alarm.ACTION ` and :attr:`AlarmTime.action ` access to the :rfc:`5545#section-3.8.6.1` ``ACTION`` property. I used OpenAI Codex with GPT-5 to assist with this change, then reviewed and tested the result. @bm1016bm-svg (`Issue #1569 `_)
- Record the exact CLDR commit used to generate the Windows-to-Olson timezone mapping and fetch the mapping from that pinned revision. I used AI to assist me with this change. @patrickswedish (`Issue #1575 `_)
- Used :meth:`vBinary.from_ical() ` in :attr:`Image.data ` for consistent Base64 validation, removing the manual :func:`base64.b64decode` call. @klouds27 (`Issue #1638 `_)
- Added :attr:`REQUEST_STATUS` property to :class:`~icalendar.event.Event`, :class:`~icalendar.todo.Todo`, :class:`~icalendar.journal.Journal`, and :class:`~icalendar.free_busy.FreeBusy` with ``request_status`` parameter in ``new()`` constructors per :rfc:`5545#section-3.8.8.3`. I used AI to assist with this change. @SemTiOne (`Issue #1666 `_)
- Improved :exc:`~icalendar.error.ICalParsingError` by including optional value, line, and line number information in exception messages for more consistent iCalendar parsing error reporting. AI assistance: ChatGPT was used to help debug terminal errors encountered during development. @GAUTAMSANSWAL
- Made :exc:`~icalendar.error.JCalParsingError` inherit from :exc:`~icalendar.error.InvalidCalendar` for consistency with :exc:`~icalendar.error.ICalParsingError`. AI assistance: ChatGPT was used to help debug terminal errors encountered during development. @GAUTAMSANSWAL
Bug fixes
~~~~~~~~~
- Resolve the timezone of a "globally unique" :rfc:`5545#section-3.2.19` ``TZID`` such as ``/freeassociation.sourceforge.net/Europe/Berlin``, which is emitted by some clients, including libical and Evolution. :meth:`TZP.timezone ` now strips the leading vendor prefix and resolves the trailing Olson identifier, so the value is parsed as timezone-aware instead of being silently treated as naive. Prepared with AI assistance. @vjsai (`Issue #313 `_)
- Fixed the `equivalent_timezone_ids.py` script after the call to generate the timezone Python code was removed. @gjabell (`Issue #1392 `_)
- Values of unrecognized properties and ``X-`` properties without a ``VALUE`` parameter were altered by escaping when parsed, serialized, or converted to and from jCal, so they did not round-trip unchanged as :rfc:`7265` specifies. These values are now preserved verbatim. Additionally, the ``PROXIMITY`` property (:rfc:`9074`) was treated as an unknown value type instead of ``TEXT`` and is now recognized correctly. AI disclosure: I used Claude Code (Anthropic's Claude Opus) to draft and refine this change and its tests; I reviewed the output and validated the change locally. @lcampanella98 (`Issue #1445 `_)
- Ship :file:`funding.json` in PyPI source distributions so packaging and test runs from the sdist no longer fail with :class:`FileNotFoundError`. @Hishamkhashman1 (`Issue #1493 `_)
- Avoid folding content lines between escape prefixes and their escaped characters. AI disclosure: I used GPT-5 Codex to help draft and refine this change and its tests; I reviewed and validated the output locally. @kingrubic (`Issue #1501 `_)
- Preserve ``URI`` value parameters on a jCal round-trip. :meth:`vUri.from_jcal ` previously passed the parameters positionally, but ``vUri.__new__`` takes ``encoding`` as its second positional parameter. As a result, the ``URI`` value parameters were consumed as ``encoding`` and dropped. For example, ``ATTACH;FMTTYPE=...`` or ``CONFERENCE;FEATURE=...`` lost their parameters. They are now passed as the ``params`` keyword. Prepared with the assistance of an AI coding agent (Anthropic's Claude Opus 4.8). @gaoflow (`Issue #1526 `_)
- Updated the Windows timezone mapping for ``Mountain Standard Time (Mexico)`` to ``America/Mazatlan``, so dates after Mexico's 2022 timezone changes use the correct UTC-7 offset instead of UTC-6. Prepared with AI assistance. @RobHannay (`Issue #1546 `_)
- ``IMAGE`` properties now use their explicitly declared ``VALUE`` type instead of always being parsed as unknown, while ``IMAGE`` without a ``VALUE`` parameter remains unknown. I used OpenAI Codex with GPT-5 to assist with this change. @floze-the-genius (`Issue #1561 `_)
- Removed ``ATTACH`` from :attr:`Alarm.singletons `. An "email" ``VALARM`` may carry more than one ``ATTACH`` per :rfc:`5545#section-3.6.6`, so ``ATTACH`` belongs in ``multiple`` only; it was previously listed in both ``singletons`` and ``multiple``. Added a regression test that ``singletons`` and ``multiple`` are disjoint for every registered component. Prepared with the assistance of an AI coding agent (Anthropic's Claude Opus 4.8). @vtino17 (`Issue #1569 `_)
- :attr:`Alarm.REPEAT `, :attr:`Alarm.repeat `, :attr:`Event.sequence `, and :attr:`Event.priority ` now reject non-integers (including booleans) with :exc:`TypeError` and negative values with :exc:`~icalendar.error.InvalidCalendar`. @heyncth (`Issue #1594 `_)
- Added the missing ``BINARY`` member to :class:`icalendar.enums.VALUE`, per :rfc:`5545#section-3.2.20`. ``VALUE.BINARY`` previously raised ``AttributeError``. Prepared with the assistance of an AI coding agent (Anthropic's Claude Opus 4.8). @vtino17 (`Issue #1607 `_)
- A ``PERIOD`` value written with dates instead of datetimes, such as ``RDATE;VALUE=PERIOD:19970101/19970102``, was accepted when a calendar was parsed and then raised an :exc:`AttributeError` when it was written out again, or a :exc:`TypeError` where only one half was a date. Such a value is now read as midnight, in the timezone of the other half where it has one. I used AI to assist me with this change. @lcampanella98 (`Issue #1633 `_)
- When :func:`icalendar.use_pytz` was in effect, a date parsed with a ``TZID``, such as ``RDATE;TZID=America/New_York;VALUE=DATE:19970101``, was given the timezone's oldest known offset, its local mean time, so the value was minutes off. It is now read with the offset that applied on that date. Calendars read with zoneinfo, the default, were not affected. I used AI to assist me with this change. @lcampanella98 (`Issue #1633 `_)
- Escape a lone ``\r`` as ``\n`` in :func:`icalendar.parser.string._escape_char`, used by :meth:`vText.to_ical `. A carriage return not followed by a line feed was previously left raw in the serialized content line, so a ``SUMMARY`` or ``DESCRIPTION`` built from untrusted text could carry a control character into the iCalendar stream and split the line for lenient consumers. ``\r\n`` and ``\n`` were already escaped, and the parameter escaper already mapped ``\r`` to ``^n``. @alhudz (`Pull Request #1462 `_)
- Reject non-ASCII digits in the ``ordwk`` part of :class:`~icalendar.prop.recur.weekday.vWeekday` (``BYDAY``, ``BYWEEKDAY``, and ``WKST``). The value validation regular expression ``\d`` matches non-ASCII digits, such as the Arabic-Indic ``١٢``. A value such as ``١٢MO`` was silently accepted as ``relative == 12``, instead of being rejected, as required by :rfc:`5545#section-3.3.10` (``ordwk = 1*2DIGIT``). This mirrors the earlier :class:`~icalendar.prop.recur.month.vMonth` fix. Drafted with AI assistance (Claude Opus 4.8); reviewed, tested, and verified by the author. @Labib-Bin-Salam
- Reject raw CR and LF in :class:`~icalendar.prop.uri.vUri`, :class:`~icalendar.prop.cal_address.vCalAddress`, :class:`~icalendar.prop.inline.vInline`, and :class:`~icalendar.prop.xml_reference.vXmlReference`. These value types are not escaped on serialization, so a lone ``\r`` in the value was written straight into the content line, slipping past the newline-only assertion in ``Contentline`` and reparsing as a separate property. This was reachable from untrusted jCal via ``URL``, ``ATTENDEE``, and ``ORGANIZER``. @alhudz
- jCal property names, parameter names, and ``RRULE`` part names are now validated as lowercase iCalendar tokens when parsing jCal (RFC 7265 sections :rfc:`7265#section-3.4`, :rfc:`7265#section-3.5`, and :rfc:`7265#section-3.6.10`). They were kept verbatim and re-emitted into the content line on serialization, so a name containing ``:``, ``;``, or a lone carriage return could inject parameters or a new content line for consumers that treat a bare ``\r`` as a break. @alhudz
Documentation
~~~~~~~~~~~~~
- Added return type annotations to the ``new()`` factory methods of the :mod:`icalendar.cal` components, such as :meth:`Event.new `. @ShirayukiRin (`Issue #938 `_)
- Added a return type hint to the :meth:`TZP.use_default ` method. @Vishwa0223 (`Issue #938 `_)
- Added type annotations to ``__init__`` methods across the package. @ShirayukiRin (`Issue #938 `_)
- Added a return type annotation to :meth:`~icalendar.alarms.Alarms.add_component`. I used OpenAI GPT-5 Codex to identify the scoped method, draft the annotation and test, and review the validation results. @kudala-bharani (`Issue #938 `_)
- Added a ``bool`` return type annotation to :meth:`~icalendar.parser.parameter.Parameters.is_utc`. I used OpenAI Codex (GPT-5) to identify the method. @Ace-0 (`Issue #938 `_)
- Improved docstrings in :mod:`icalendar.error` to follow the project's Google-style docstring format, adding ``Parameters`` and ``Returns`` sections where appropriate. I used AI to assist me with this change. @Vrinda0211 (`Issue #1072 `_)
- Added a docstring to the :func:`~icalendar.cli.main` function to follow the project's Google Style guide. @Areej-cs (`Issue #1072 `_)
- Documented the construction and truth-value usage of :class:`~icalendar.prop.boolean.vBoolean`. I used OpenAI Codex with GPT-5 to assist with drafting and validation. @sahilmathur254 (`Issue #1118 `_)
- Fixed unqualified ``InvalidCalendar`` and ``IncompleteComponent`` references in :class:`~icalendar.cal.todo.Todo` docstrings so they link in the API docs. I used AI to assist me with this change. @mitre88 (`Issue #1158 `_)
- Fixed the broken link to :meth:`Component.to_ical ` in the documentation of how to handle parsing errors. AI disclosure: used Claude Sonnet 5 with the prompt "Fix broken links to Python objects in parse-errors.rst" to assist with this change. @SemTiOne (`Issue #1158 `_)
- Replaced RFC copy-paste text in docstrings with Pythonic docstrings for calendar components. @ykd007 (`Issue #1244 `_)
- Corrected the :meth:`Journal.new ` documentation so its parameter list matches the public method signature. I used AI to assist with this change. @w3lld1 (`Issue #1473 `_)
- Corrected the ``FreeBusy.new()`` docstring, which described the method as creating an alarm instead of a FreeBusy component. Written with assistance from Claude Opus 4.5 (Anthropic). @andycheng2018 (`Issue #1473 `_)
- Correct public docstrings whose prose looked like unsupported section headings. This contribution was drafted with AI assistance and reviewed by @kingrubic. (`Issue #1481 `_)
- Clarified optional parameters and auto-generated ``UID`` and ``DTSTAMP`` values in the :meth:`~icalendar.cal.event.Event.new` docstring. AI disclosure: Grok assisted with reviewing RFC terminology and drafting the docstring update. @checkzhao8888 (`Issue #1504 `_)
- Mention `icalendar-anonymizer `_ to remove private information from iCalendar files for bug reports and `Python Calendaring Ecosystem `_ as a resource. @stevepiercy (`Issue #1511 `_)
- Consolidate and alphabetize the docstring parameters of the :class:`~icalendar.cal.alarm.Alarm` factory methods :meth:`~icalendar.cal.alarm.Alarm.new_display`, :meth:`~icalendar.cal.alarm.Alarm.new_audio`, and :meth:`~icalendar.cal.alarm.Alarm.new_email`. Prefixed required parameters with ``Required.`` @Solaris-star (`Issue #1591 `_)
- Revised the security policy to use GitHub Security Advisory procedure instead of emailing the Plone security team, and clarified language. @stevepiercy (`Issue #1612 `_)
- Revised how to document parameters in docstrings, specifically their order of appearance and usage of type hints. Revised guidance to write docstrings only for a class, and not their ``__init__`` or ``__new__`` methods. @stevepiercy (`Issue #1618 `_)
- Updated the ``categories`` property documentation to include the ``Available``
and ``Availability`` components and its RFC 7953 conformance reference. (`Issue #1624 `_)
- Changed ``date-time`` to ``datetime`` in the narrative parts of the ``RECURRENCE-ID`` and ``ACKNOWLEDGED`` documentation. AI-assisted. @atirna (`Issue #1655 `_)
- Adapt pull request requirements to better handle AI slop. @stevepiercy
- Add an RFC cross-reference and a ``Returns`` section to the :meth:`Contentline.value_separator_index ` docstring. @alhudz
- Added a bullet point for reviewing pull requests to "Examples of how to contribute." @stevepiercy
- Consolidate maintainers list with an include. @stevepiercy
- Documented how to join the icalendar team. @stevepiercy
- Restored the removed docstrings under the :class:`~icalendar.prop.integer.vInt` attribute declarations for :attr:`~icalendar.prop.integer.vInt.max` and :attr:`~icalendar.prop.integer.vInt.min`. @stevepiercy
Internal changes
~~~~~~~~~~~~~~~~
- Renamed the internal ``timezone_datetime_property`` helper in ``icalendar.attr`` to ``_timezone_datetime_property``. It was never part of the public API (not listed in ``__all__``) and is only used at import time to build ``rfc_7953_dtstart_property`` and ``rfc_7953_dtend_property``, so no deprecation warning was added. I used AI to assist me with this change. @AhmedYoussef98 (`Issue #1011 `_)
- Added automated tests for docstring structure and quality. @KartavyaDikshit (`Issue #1481 `_)
- Added zizmor static analysis workflow for GitHub Actions security auditing. @srurora (`Issue #1487 `_)
- Ensure that news fragment filenames are valid in CI. @stevepiercy (`Issue #1499 `_)
- Add Commit-Check GitHub Action to detect commits by automated AI agents and bots. @stevepiercy (`Issue #1514 `_)
- The Windows-to-Olson mapping test now verifies each mapped timezone resolves to the expected identifier. I used OpenAI Codex with GPT-5 to assist with this change. @floze-the-genius (`Issue #1562 `_)
- Bumped maximum pull request description character count to 1500. Added instructions as comments in the pull request template. @stevepiercy (`Issue #1602 `_)
- Added a ``make zizmor`` target that runs zizmor static analysis on the GitHub Actions workflows in the repository, matching the version and command used in the continuous integration workflow. Added zizmor usage documentation. AI disclosure: used Claude Sonnet 5 with the prompt "Create a make zizmor target for local static analysis of GitHub Actions workflows" to assist with this change. @SemTiOne (`Issue #1639 `_)
- Removed two unreachable code branches from :meth:`vOrg.from_ical ` and :meth:`vOrg.from_jcal `. I used Claude Code (Anthropic's Claude Sonnet 5) to identify and remove the dead branches and to update the accompanying coverage tests; I reviewed the diff and ran the test suite locally. @vjymisal0 (`Issue #1641 `_)
- Added ``security`` as a valid news fragment. @stevepiercy
- Added anti-slop GitHub Action to detect commits by automated AI agents and bots. Removed useless Commit-Check GitHub Action. See related `discussion `_. @stevepiercy
- Adjusted the anti-slop GitHub Action settings of ``max-failures`` to ``1`` to surface any number of failures, and the ``min-profile-completeness`` setting from its default of ``4`` to ``1`` to require at least one human-added profile attribute. @stevepiercy
- Don't close pull requests automatically when the anti-slop GitHub Action fails. @stevepiercy
- Made "Instructions" not a section heading in the pull request template. "Instructions" was interpreted as a section heading, even though it is in a comment. @stevepiercy
- Rename anti-slop action. @stevepiercy
Other tasks
~~~~~~~~~~~
- `Issue #698 `_, `Issue #698 `_, `Issue #698 `_, `Issue #743 `_, `Issue #1541 `_, `Issue #1549 `_, `Issue #1573 `_, `Issue #1592 `_
7.2.2 (2026-07-20)
------------------
Documentation
~~~~~~~~~~~~~
- Fixed duplicate ``vInt.min`` and ``vInt.max`` descriptions in the API reference that caused the Read the Docs build to fail.
7.2.1 (2026-07-20)
------------------
Security fixes
~~~~~~~~~~~~~~
- Fixed `GHSA-qjcq-q7h7-r74v `_: a crafted ``REPEAT`` on a ``VALARM`` could exhaust memory or CPU via :attr:`Alarm.triggers ` and :class:`~icalendar.alarms.Alarms`. Expansion is now capped at ``icalendar.config.MAX_ALARM_REPEAT``. Its default is ``10000``. Set to ``-1`` to disable the cap. :class:`~icalendar.prop.integer.vInt` now also enforces the :rfc:`5545` signed 32-bit integer range on parse. @SashankBhamidi
7.2.0 (2026-06-23)
------------------
Removals and deprecations
~~~~~~~~~~~~~~~~~~~~~~~~~
- Deprecated :func:`icalendar.parser.string.foldline` as a private function for icalendar version 8. @IoannaGiag (`Issue #1011 `_)
- Deprecated :func:`icalendar.parser.string.escape_char`, :func:`icalendar.parser.string.unescape_char`, :func:`icalendar.parser.string.escape_string`, and :func:`icalendar.parser.string.unescape_string` using the standard ``deprecate_for_version_8`` wrapper as per issue #1405. (`Issue #1405 `_)
New features
~~~~~~~~~~~~
- Created an :attr:`~icalendar.prop.recur.frequency.vFrequency.ical_value` property for the :class:`~icalendar.prop.recur.frequency.vFrequency` component, mirroring the existing pattern on :class:`~icalendar.prop.recur.weekday.vWeekday`. @mvanhorn (`Issue #876 `_)
- Created an :attr:`~icalendar.prop.geo.vGeo.ical_value` property for the :class:`~icalendar.prop.geo.vGeo` component. @IoannaGiag (`Issue #876 `_)
- Added type hints to component methods. @Priyanshu-pulak (`Issue #938 `_)
- Added test coverage for :func:`icalendar.compatibility.deprecate_for_version_8`. AI disclosure: I used GPT-5 Codex to help draft and refine the test and pull request text. I reviewed the output and validated the change locally. @iccccccccccccc (`Issue #1407 `_)
- The :attr:`Alarm.uid ` accessor now falls back to vendor-specific UID properties (the existing ``X-ALARMUID`` and the newly added ``X-EVOLUTION-ALARM-UID``) when no canonical ``UID`` is present, so alarms exported by Evolution/GNOME Calendar expose a usable identifier. ``single_string_property`` now accepts an ordered list of fallback keys so further vendor aliases can be added later. AI disclosure: I used GPT-5 Codex (via the Codex CLI) to draft and refine this change and its tests; I reviewed and validated the output locally. @mvanhorn (`Issue #1421 `_)
- The ``rdates`` and ``exdates`` properties are now writable: assigning a list replaces the ``RDATE``/``EXDATE`` values, ``del`` (or assigning an empty list or ``None``) clears them, and assigning the value the getter returns round-trips. Prepared with the assistance of an AI coding agent (Anthropic's Claude). @gaoflow (`Issue #1442 `_)
Bug fixes
~~~~~~~~~
- Strictly validate :class:`~icalendar.prop.dt.datetime.vDatetime` values in :meth:`~icalendar.prop.dt.datetime.vDatetime.from_ical` and reject malformed input. This also improves handling of values with a ``TZID`` prefix, per :rfc:`5545#section-3.3.5`, Form #3. @uwezkhan (`Issue #1361 `_)
- Preserve an explicit ``VALUE`` parameter (for example ``RDATE;VALUE=PERIOD`` or ``TRIGGER;VALUE=DATE-TIME``) when converting from jCal. Previously :meth:`Component.from_jcal ` dropped the value type, which is encoded in the jCal type field rather than as a parameter. Prepared with the assistance of an AI coding agent (Anthropic's Claude Opus 4). @gaoflow @lcampanella98 (`Issue #1426 `_)
- For a newline-free string that the operating system can't use as a file path—for example, one containing an embedded null byte or one that is too long—treat it as calendar data, instead of propagating an :exc:`OSError` from :meth:`Component.from_ical `. Such input now raises a consistent :exc:`ValueError` across platforms. The string-versus-path boundary is now covered by tests. @uwezkhan (`Issue #1436 `_)
- Accept the ``(dt, None)`` form that ``rdates``/``exdates`` return for a single date when adding ``RDATE`` or ``EXDATE``, so ``event.add("RDATE", (dt, None))`` no longer raises :exc:`TypeError` and the value round-trips. Prepared with the assistance of an AI coding agent (Anthropic's Claude Opus 4). @gaoflow @texttheater (`Issue #1439 `_)
- Anchored the value validation regular expressions with ``\Z`` instead of ``$`` in :class:`~icalendar.prop.recur.weekday.vWeekday`, :meth:`vDuration.from_ical `, :class:`~icalendar.prop.dt.time.vTime` and :class:`~icalendar.prop.dt.utc_offset.vUTCOffset`. ``$`` matches just before a final ``\n``, so a value with a trailing line break was accepted; for ``vWeekday`` the newline survived in the ``str`` value and was re-emitted into RECUR output. @alhudz
- For iCalendar files that have thousands of bare line breaks, reduce the content line parse time by a quadratic order of magnitude when reading a component with :meth:`Component.from_ical `. @alhudz
- Parse a ``CATEGORIES`` value that contains an unescaped colon correctly. ``TEXT`` values do not escape ``:``, so a category such as ``CATEGORIES:CONFIDENTIAL,http://example.com/tag`` was truncated to a single ``//example.com/tag`` because the value boundary was found with the last colon on the line instead of the first one outside the parameters. @alhudz
- Parse and serialize jCal iteratively so that deeply nested components no longer raise an uncaught :exc:`RecursionError`. :meth:`Component.from_jcal ` and :meth:`Component.to_jcal ` now handle arbitrary nesting depth, matching the iterative iCal parser and serializer. @arshsmith
- Preserve literal percent escapes in parameter values. The parameter parser used ``%2C``/``%3A``/``%3B``/``%5C`` as internal markers for backslash-escaped delimiters, so a value that already contained those sequences (e.g. ``ALTREP="http://x/a%2Cb"``) was silently decoded to ``http://x/a,b``. The internal transport encoding now escapes ``%`` itself, leaving real percent-encoded values untouched. @alhudz
- Raise :class:`~icalendar.error.InvalidCalendar` instead of leaking :exc:`OverflowError` when a ``DURATION`` value is too large for :class:`datetime.timedelta`, for example, ``P999999999999999999W``. Parsing a whole calendar now records such a value as an error, like any other invalid property, rather than aborting the parse. @arshsmith
- Reject non-ASCII digits in :class:`~icalendar.prop.recur.month.vMonth` (``BYMONTH``). ``str.isdigit`` is ``True`` for digits like the Arabic-Indic ``١٢``, which was silently accepted and normalized to month ``12``, while characters such as ``²`` cleared the same guard and then leaked a raw ``int()`` error. :meth:`vMonth.from_ical ` now rejects both. @alhudz
- Reject non-finite FLOAT values in :meth:`vFloat.from_ical() ` and :meth:`vGeo.from_ical() `. Inputs such as ``nan``, ``inf`` or an overflowing magnitude like ``1e999`` were silently accepted, producing ``NaN``/``Infinity`` tokens in :meth:`Component.to_json ` output that are not valid JSON. @alhudz
- Strictly validate :class:`~icalendar.prop.dt.date.vDate` and :class:`~icalendar.prop.dt.time.vTime` values in their ``from_ical`` methods and reject malformed input, matching the strictness added to :class:`~icalendar.prop.dt.datetime.vDatetime`. Trailing data and ``int()`` quirks (underscores, whitespace, signs) are no longer silently accepted, per :rfc:`5545#section-3.3.4` and :rfc:`5545#section-3.3.12`. This change was prepared with AI assistance (Anthropic Claude, Opus model, via Claude Code) used to research the relevant RFC grammar and draft the validation and tests, all reviewed and verified locally. @alhudz
Documentation
~~~~~~~~~~~~~
- Switch :file:`docs/how-to/usage.rst` from the deprecated ``.. code:: pycon`` directive to ``.. code-block:: pycon`` for consistency with the rest of the documentation. @mvanhorn (`Issue #626 `_)
- Added type hint for ``encoding`` parameter in :func:`~icalendar.parser_tools.data_encode`. @cybs-joe (`Issue #938 `_)
- Converted docstring of :meth:`~icalendar.cal.component.Component.add` to Google style. @mvanhorn (`Issue #1072 `_)
- Fixed broken links and removed `:py` prefix in :class:`icalendar.cal.calendar.Calendar` documentation. @lcampanella98 (`Issue #1158 `_)
- Fixed broken link and removed `:py` prefix in the :func:`~icalendar.parser.unescape_backslash` docstring. @vincere-mori (`Issue #1158 `_)
- Fixed broken documentation links in :mod:`icalendar.alarms` and :mod:`icalendar.cal.alarm`. @lcampanella98 (`Issue #1158 `_)
- Fix unqualified cross-references in :attr:`Event.start ` and :attr:`Event.start ` docstrings. @Esneider1107 (`Issue #1158 `_)
- Fixed broken links in :mod:`icalendar.cal.free_busy` documentation by using fully qualified :class:`icalendar.cal.component.Component` attribute targets. @tsai135 (`Issue #1158 `_)
- Qualify ambiguous cross-references and remove remaining ``:py`` prefixed roles. @wahajahmed010 (`Issue #1158 `_)
- Fixed broken documentation links in :mod:`icalendar.cal.availability`. @lcampanella98 (`Issue #1158 `_)
- Replaced the RFC quotation in the docstring for :class:`vBoolean ` with a Pythonic description, including parsing behavior, a conformance reference, and a working example. @tsai135 (`Issue #1244 `_)
- Improved the documentation for ``attr.url_property`` by converting raw RFC text into a comprehensive Python docstring with usage examples and explicit RFC cross-references. Assisting tool: Gemini 1.5. @samrodri911 (`Issue #1244 `_)
- Improved the :attr:`~icalendar.cal.component.Component.LAST_MODIFIED` docstring to a clearer Pythonic docstring. Assisting tool: Claude Haiku 4.5 @valemm13 (`Issue #1244 `_)
- Tidied the auto-generated property docstrings by removing the redundant accepted values sentence and formatting return and error details as Sphinx sections. @mvanhorn (`Issue #1259 `_)
- Fix Read the Docs administrative instructions in maintenance documentation by removing the obsolete step to check the default branch and adding a step to manually trigger the "latest" version. @stevepiercy (`Issue #1397 `_)
- Clarified that :meth:`Calendar.new ` automatically sets not only required, but recommended properties too. @scop (`Issue #1459 `_)
- Add how to report security issues. @stevepiercy (`Issue #1463 `_)
- Added NixOS installation instructions to the documentation. @MichaelFehdrau0205
- Added instructions to :ref:`change-log` in Contribute documentation for how to avoid a filename conflict when adding a change log entry. @stevepiercy
- Collect only documentation files for doctest. @stevepiercy
- Documented :meth:`Calendar.from_ical ` as a direct :class:`~icalendar.cal.calendar.Calendar` API member so Sphinx can link to it from the custom components guide. Prepared with AI assistance. @xjn2005
Internal changes
~~~~~~~~~~~~~~~~
- Added tests for :attr:`FreeBusy.duration ` coverage. @kyriakikrimitza (`Issue #698 `_)
- Refactored :file:`test_error_tolerant_parsing.py` to use ``.ics`` fixture files. @lcampanella98 (`Issue #1081 `_)
- Added :file:`.pre-commit-config.yaml` configuration and documentation to automatically record AI prompts in commit messages with :program:`ai-prompt-auto-commit`. @AniruthKarthik (`Issue #1320 `_)
- Support keeping a linked issue open in the pull request template when the pull request fixes only a part of the original issue. @stevepiercy (`Issue #1394 `_)
- Trigger the creation of a comment with links to Read the Docs of the changed files to review in a pull request preview build. @stevepiercy (`Issue #1396 `_)
- Add gh-profiler workflow to help triage AI-generated contributions. @SashankBhamidi (`Issue #1484 `_)
- Added validation test for :attr:`FreeBusy.duration `. @kyriakikrimitza
- Remove redundant and deprecated pull request preview feature on Read the Docs. We now use the RTD GitHub app, making this file redundant to pull request preview builds. Additionally the call to the old GitHub Action was deprecated on 2025-07-01, per its `README.md `_. @stevepiercy
Other tasks
~~~~~~~~~~~
- Added type hints to all methods in the module :mod:`~icalendar.error`. @Priyanshu-pulak (`Issue #938 `_)
7.1.3 (2026-06-15)
------------------
Bug fixes
~~~~~~~~~
- Comparing components with ``Component.__eq__`` is no longer exponential in the subcomponent nesting depth, removing a denial-of-service vector where a deeply nested component could take minutes to compare. See `GHSA-cv84-9p8j-fj68 `_. @tidusec
7.1.2 (2026-05-22)
------------------
Bug fixes
~~~~~~~~~
- Replaced the recursive :meth:`Component.__repr__ ` implementation with an iterative stack-based walk so that deeply nested calendars no longer raise :exc:`RecursionError` when formatted via ``repr()``, ``str()``, or f-strings. The output format is unchanged for normally-shaped calendars. @gistrec (`Issue #1370 `_)
Documentation
~~~~~~~~~~~~~
- Update maintenance documentation. Fix the version switcher on "stable" on Read the Docs. @stevepiercy (`Issue #1352 `_)
7.1.1 (2026-05-18)
------------------
New features
~~~~~~~~~~~~
- Created an :attr:`~icalendar.prop.dt.period.vPeriod.ical_value` property for the :class:`~icalendar.prop.dt.period.vPeriod` component. @ZairKSM (`Issue #876 `_)
- Created a :meth:`~icalendar.prop.recur.weekday.vWeekday.ical_value` property for the :class:`~icalendar.prop.recur.weekday.vWeekday` component, mirroring the existing pattern on :class:`~icalendar.prop.boolean.vBoolean`. @mvanhorn (`Issue #1360 `_)
Bug fixes
~~~~~~~~~
- Strictly validate BINARY property values in :attr:`vBinary.from_ical() ` and reject malformed Base64 input instead of silently accepting invalid characters. @uwezkhan (`Issue #1349 `_)
Documentation
~~~~~~~~~~~~~
- Replace the RFC quotations in the docstrings for :attr:`Alarm.REPEAT ` and :attr:`Alarm.DURATION ` with Pythonic descriptions, including parameter notes, conformance references, and worked examples. @tmchow (`Issue #1244 `_)
- Edited contributor documentation for how to add a change log entry, and maintenance documentation for how to process news fragments. @stevepiercy (`Issue #1256 `_)
- Updated release process documentation. @niccokunzmann @stevepiercy @SashankBhamidi (`Issue #1293 `_)
Dependency changes
~~~~~~~~~~~~~~~~~~
- Added `towncrier `_ to development dependencies. @stevepiercy (`Issue #1256 `_)
Internal changes
~~~~~~~~~~~~~~~~
- Switched from manual change log management to `towncrier `_ to automate the process. @stevepiercy (`Issue #1256 `_)
- Bump PyPy from 3.10 to 3.11 for testing. @stevepiercy (`Issue #1383 `_)
7.1.0 (2026-04-30)
------------------
Minor changes
~~~~~~~~~~~~~
- Deprecate ``icalendar.parser.escape_string`` and ``icalendar.parser.unescape_string`` for icalendar version 8. Use ``_escape_string`` and ``_unescape_string`` internally. :issue:`1011`
- Added behavioral tests for :class:`~icalendar.cal.lazy.LazyCalendar` covering serialization round-trips, ``.todos``, ``.journals``, forward timezone references, and ``with_uid()`` substring false-positives. :issue:`1050`
- Added edge case tests for :class:`~icalendar.prop.conference.Conference` parameter normalization covering string passthrough, empty list filtering, and ``None`` omission. :issue:`925`
- Make icalendar an explicit editable install for clarity. :pr:`1268`
- Do not run some tests until a pull request is approved. :pr:`1246`
- Mark skipped CI tasks as skipped instead of running them. :issue:`1286`
- Created an :meth:`~icalendar.prop.boolean.vBoolean.ical_value` property for the :class:`~icalendar.prop.boolean.vBoolean` component. :issue:`876`
- Created an :meth:`~icalendar.prop.float.vFloat.ical_value` property for the :class:`~icalendar.prop.float.vFloat` component. :issue:`876`
- Created an :meth:`~icalendar.prop.integer.vInt.ical_value` property for the :class:`~icalendar.prop.integer.vInt` component. :issue:`876`
- Created an :meth:`~icalendar.prop.binary.vBinary.ical_value` property for the :class:`~icalendar.prop.binary.vBinary` component. :issue:`876`
- Put the link check as the last documentation CI task, allowing the documentation build and Vale to run first and fail faster. :pr:`1295`
- Extended :func:`~icalendar.timezone.tzp.TZP.localize` to support localizing both :class:`datetime.datetime` and :class:`datetime.time` objects, returning timezone-aware :class:`datetime.time` objects for the latter. :issue:`1142`
- Add type hints to tests directory functions. :issue:`938`
- Update to Contributor Covenant 3.0 Code of Conduct, hosted at https://pycal.org/code-of-conduct/.
New features
~~~~~~~~~~~~
- Added :class:`~icalendar.cal.lazy.LazyCalendar` for lazy parsing of subcomponents. :issue:`158`, :issue:`1050`
- Updated :func:`icalendar.prop.dt.time.vTime.from_ical` to support parsing time values with TZID parameters, returning timezone-aware :class:`datetime.time` objects. :issue:`1142`
- Added ``subcomponents`` parameter to :meth:`Component.new `, :meth:`Event.new `, :meth:`Todo.new `, and :meth:`Availability.new `. :issue:`1065`
- Switch to uv for development. :issue:`1102`
Bug fixes
~~~~~~~~~
- Allow lenient parsing of content lines with optional whitespace around property and parameter delimiters (for example, ``REFRESH - INTERVAL; VALUE = DURATION:PT48H``) when parsing calendars with ``strict=False``. :issue:`351`
- X-properties with a ``VALUE`` parameter are now parsed using the correct type instead of falling back to :class:`~icalendar.prop.unkown.vUnknown`. :issue:`1238`
- Test that the ``DURATION`` property catches :class:`datetime.timedelta` objects without vProperty wrappers. :issue:`884`
- Fixed :func:`~icalendar.attr.get_end_property` to avoid allowing the creating of VEVENT components with negative durations. Only VTODO components are allowed to have negative durations. :issue:`999`
- GitHub Actions: conditional tests now show as "skipped" instead of "pending". :issue:`1264`
- Fixed :meth:`Component.__eq__ ` method not being commutative when comparing subcomponents. :issue:`1224`
- Verified that the ``VALUE`` parameter of jCal components is used for the type of the component property. :issue:`1237`
- Fix :func:`~icalendar.parser.string.escape_char` handling of ``bytes`` input by converting with :func:`icalendar.parser_tools.to_unicode` before escaping. :issue:`1226`
- Fixed ``RecursionError`` in ``walk()``, ``property_items()``, and ``to_ical()`` by using iterative implementations for component traversal and property extraction. :pr:`1348`
Documentation
~~~~~~~~~~~~~
- Convert docstring of :func:`~icalendar.param.string_parameter` to Google style. :issue:`1072`, :pr:`1316`
- Run ``sphinx-build`` with ``-W`` to turn warnings into errors. :issue:`1306`
- Added `sphinx-llms-txt `_ extension to generate :file:`llms.txt` and :file:`llms-full.txt` files for AI/LLM documentation consumption. :issue:`1302`
- Fixed CI Vale check reporting and resolved Vale errors. :issue:`1277`
- Include :file:`Makefile` in documentation workflow path filters so documentation CI runs when Makefile logic changes, and keep Vale failures visible in CI output. :issue:`1277`
- Document how to install icalendar on Alpine Linux. :pr:`1290`
- Add documentation for usage of the Sphinx extension `sphinx-icalendar `_. :pr:`1268`
- Add Repology badge and distribution installation instructions to install documentation. :issue:`1119`
- Updated references to :class:`~icalendar.prop.uri.vUri` and :class:`~icalendar.enums.RELTYPE` classes in :file:`attr.py`. :issue:`1158`
- Convert docstrings in :file:`attr.py` and :file:`cal/calendar.py` to Google Style format. :issue:`1072`
- Explained import shortcuts in :doc:`../explanation/api-design` documentation. :issue:`1161`
- Added tutorial for creating a calendar with events with attendees. :pr:`1262`
- Added recognition of NLnet Foundation for its funding and Open Collective for donations to the documentation footer. :issue:`1214`
- Documented ``vText`` properties according to :rfc:`5545#section-3.3.11`. :issue:`742`
- Convert docstrings in :mod:`icalendar.caselessdict` to Google Style format with ``Parameters``, ``Returns``, ``Raises``, and ``Example`` sections as appropriate. :issue:`1072`
- Fix broken docstring for :meth:`~icalendar.cal.component.Component.add_component` link in :attr:`~icalendar.cal.availability.Availability.available`. :issue:`1158`
- Revise AI policy, per NLnet advice. See discussion under `pycal.org issue #24 `_.
- Add documentation for how to use uv for development. :issue:`1102`
- Reorganize Design documentation. :issue:`1292`
- Improve docstring for ``categories_property``, which renders to HTML in :attr:`Calendar.categories `, :attr:`Event.categories `, :attr:`Journal.categories `, and :attr:`Todo.categories `. :issue:`1244`
- Fixed Python object cross-references in ``icalendar.cal.component.Component._infer_value_type``. :issue:`1158`, :pr:`1344`
7.0.3 (2026-03-03)
------------------
Minor changes
~~~~~~~~~~~~~
- Show colorful required code changes in the CI output to help contributors solve the formatting issues. :pr:`1216`
- Use ruff 0.15.0 for code formatting in :file:`tox.ini`. :pr:`1215`
New features
~~~~~~~~~~~~
- Added :attr:`Event.RECURRENCE_ID `, :attr:`Todo.RECURRENCE_ID `, and :attr:`Journal.RECURRENCE_ID ` properties, including support in their ``new()`` constructors. :issue:`1231`
Bug fixes
~~~~~~~~~
- Fixed :func:`~icalendar.timezone.tzid.tzids_from_tzinfo` not recognizing
``dateutil.tz.win.tzwin`` objects on Windows. UTC datetimes using
``dateutil.tz.gettz("UTC")`` now correctly serialize with the ``Z`` suffix
instead of ``TZID=Coordinated Universal Time``. :issue:`1056`
- Fixed :meth:`Calendar.get_missing_tzids `
raising ``KeyError`` when a VTIMEZONE exists for a timezone not referenced by any event TZID,
for example, when added by the ``x-wr-timezone`` conversion. :issue:`1124`
- Fixed :meth:`Calendar.get_missing_tzids `
and :meth:`Calendar.add_missing_timezones `
generating a spurious ``VTIMEZONE`` for UTC. :rfc:`5545#section-3.2.19` requires UTC datetimes
to use the ``Z`` suffix; no ``VTIMEZONE`` component is needed or permitted. :issue:`1124`
- Fixed :meth:`Parameters.update_tzid_from `
incorrectly setting ``TZID=UTC`` on UTC datetimes. :rfc:`5545#section-3.2.19` requires UTC datetimes to
use the ``Z`` suffix without a ``TZID`` parameter. :issue:`1124`
- Renamed the public functions ``escape_char`` and ``unescape_char`` to implicit private methods ``_escape_char`` and ``_unescape_char``
Fixed regression from :issue:`1008` by restoring :func:`~icalendar.parser.string.escape_char` and :func:`~icalendar.parser.string.unescape_char` as public functions.
The public functions :func:`~icalendar.parser.string.escape_char` and :func:`~icalendar.parser.string.unescape_char` are now deprecated with warnings for external users.
:pr:`1241`
Documentation
~~~~~~~~~~~~~
- Add ``icalendar`` as a local workspace dependency to the ``docs`` dependency group in :file:`pyproject.toml` to fix dependency resolution issues with ``uv lock`` during documentation builds. :issue:`1253` :pr:`1254`
- Use ``sphinx-icalendar`` to add syntax highlighting to iCalendar text
7.0.2 (2026-02-24)
------------------
Minor changes
~~~~~~~~~~~~~
- Show required code changes in the CI output to help contributors solve the formatting issues. :pr:`1216`
- Use ruff 0.15.0 for code formatting in :file:`tox.ini`. :pr:`1215`
New features
~~~~~~~~~~~~
- Enabled :meth:`Calendar.from_ical ` to read calendars from files. :issue:`756`
- Added :attr:`Calendar.journals ` property to retrieve all journal components. :issue:`1230`
Documentation
~~~~~~~~~~~~~
- Removed methods of ``str``, ``int``, and other classes and methods in the Python standard library from the documentation.
7.0.1 (2026-02-17)
------------------
Minor changes
~~~~~~~~~~~~~
- Setting :attr:`~cal.calendar.Calendar.calendar_name` now also writes ``X-WR-CALNAME``, and setting :attr:`~cal.calendar.Calendar.description` now also writes ``X-WR-CALDESC``, for improved client compatibility. :issue:`918`
Bug fixes
~~~~~~~~~
- Make ``typing_extensions`` a dependency. :issue:`1202`
Documentation
~~~~~~~~~~~~~
- Fixed the version switcher on Read the Docs, and documented the process for a major release. :issue:`1194`
- Added usage examples for reading calendars from files and URL. :issue:`756`
- Add type hints and convert docstrings to Google Style in :file:`cli.py`. :issue:`938`
7.0.0 (2026-02-11)
------------------
Minor changes
~~~~~~~~~~~~~
- Created an :meth:`~cal.todo.Todo.example` method for the :class:`~cal.todo.Todo` component. :issue:`743`
- Created an :meth:`~cal.alarm.Alarm.example` method for the :class:`~cal.alarm.Alarm` component. :issue:`743`
- Move property classes from :mod:`icalendar.prop` into their own files with sub-packages :mod:`icalendar.prop.recur` and :mod:`icalendar.prop.dt`. :issue:`987`
- Move classes and functions in :mod:`icalendar.parser` into their own files. :issue:`987`
- Clarified custom component (X-* and IANA-registered) parsing behavior through enhanced documentation and comprehensive how-to guide. Custom components are automatically handled by the library with no special configuration required. :issue:`432`
- Reorganized custom component tests into a dedicated :file:`test_custom_components.py` file with expanded test coverage for :meth:`Component.from_ical `, :meth:`Calendar.from_ical `, and :class:`~icalendar.cal.component_factory.ComponentFactory` usage. :issue:`433`
- The ``typing-extensions`` dependency on Python < 3.13 is now optional, part of the ``test`` extra.
- The :func:`icalendar.tools.is_pytz_dt` return value is now hinted as ``TypeGuard[datetime]``, not ``TypeIs[datetime]``, since returning ``False`` should not allow narrowing it as non-datetime.
- Regroup dependencies in, and remove obsolete ones, from :file:`pyproject.toml`. :issue:`906`
- Add type hints to internal helper functions. :issue:`938`
- Add type hints to prop value classes (vBoolean, vFloat, vUri, vBinary, vInline). :issue:`938`
- Add type hints to remaining prop value classes (vText, vCalAddress, vCategory, vGeo, vN, vOrg, vAdr, vBroken, vUid, Conference, Image). :issue:`938`
- Added type hints and overloads to :meth:`Calendar.from_ical ` and :meth:`Component.from_ical ` to support ``multiple=True/False`` return types. :issue:`1129`
- CI: Print a link to Vale documentation when the spell checker fails.
- Remove :file:`bootstrap.py` and :file:`buildout.cfg` files as they are old build configurations. :pr:`1171`
- Enforce ruff formatting and linting across the entire codebase, with CI check to prevent regressions.
:issue:`672`, :pr:`1171`, :pr:`1172`, :pr:`1173`, :pr:`1174`, :pr:`1175`, :pr:`1176`, :pr:`1177`, :pr:`1178`, :pr:`1179`, :pr:`1180`, and :pr:`1181`
- Fix type annotations, typos, and validation logic in prop module: corrected return type hints in ``parse_jcal_value`` methods, fixed ``to_ical()`` return type in vDDDTypes, updated ClassVar type hint in TypesFactory, removed dead code, fixed "abbrevation" typo in vWeekday, and corrected validation logic in vMonth. :issue:`1185`
- Rename :class:`~icalendar.prop.vBrokenProperty` to :class:`~icalendar.prop.vBroken` to match naming convention. :class:`~icalendar.prop.vBroken` now stores the actual exception object in ``parse_error`` instead of a string, and raises :class:`~icalendar.error.BrokenCalendarProperty` when accessing attributes like ``.dt`` that the expected type would have. :issue:`1087`
Breaking changes
~~~~~~~~~~~~~~~~
- Drop support for Python 3.8 and 3.9. :issue:`977`
- ``DURATION_REGEX`` moved from :mod:`icalendar.prop` to :mod:`icalendar.prop.dt.duration`. :issue:`987`
- ``WEEKDAY_RULE`` moved from :mod:`icalendar.prop` to :mod:`icalendar.prop.recur.weekday`. :issue:`987`
- Removed ``tzid_from_dt`` and ``tzid_from_tzinfo`` from :mod:`icalendar.prop` as they exist in :mod:`icalendar.timezone`. :issue:`987`
- :meth:`Component.decoded` now returns a string instead of bytes for text properties.
- Remove constants ``FOLD``, ``NAME``, ``NEWLINE``, ``QUNSAFE_CHAR``, ``QUOTABLE``, ``UFOLD``, and ``UNSAFE_CHAR`` from :mod:`icalendar.parser`'s export. :issue:`987`
New features
~~~~~~~~~~~~
- Added ``recursive`` parameter to :meth:`Component.copy` to control copying of subcomponents and properties. :issue:`899`
- Event components now have error-tolerant property parsing. Properties with parsing errors fall back to :class:`~icalendar.prop.vBroken`, preserving the raw value and allowing access to other valid properties. Errors are recorded in ``component.errors``. Partially addresses :issue:`158`
- Added :class:`~icalendar.prop.AdrFields` and :class:`~icalendar.prop.NFields` named tuples for structured access to vCard ADR and N property fields. The ``fields`` attribute and ``from_ical()`` return value of :class:`~icalendar.prop.vAdr` and :class:`~icalendar.prop.vN` now return these typed named tuples, enabling access like ``adr.fields.street`` and ``n.fields.family``. Since named tuples are tuple subclasses, existing code using tuple indexing or unpacking remains compatible. Added ``name`` and ``units`` properties to :class:`~icalendar.prop.vOrg` for convenient access to the organization name and organizational units. Added ``ical_value`` property to all three classes. :issue:`1060`
- Added ``with_uid`` method to ``Component`` to filter subcomponents by UID. :issue:`950`
- Enforce linting of code with Ruff in CI. :issue:`672`
Bug fixes
~~~~~~~~~
- Fixed :meth:`Calendar.new ` to automatically generate a UID when not provided, matching the documented behavior. Previously, the documentation stated that ``uid`` would be set to a new :func:`uuid.uuid4` if ``None``, but the implementation did not generate it. :issue:`1066`
- Fixed import failure in Pyodide/WebAssembly environments by using lazy initialization for timezone data in the zoneinfo provider. The library can now be imported in environments without timezone data (e.g., Cloudflare Workers, PyScript, JupyterLite). :issue:`1073`
- Fixed :meth:`icalendar.caselessdict.CaselessDict.__eq__` to return ``NotImplemented`` when comparing with non-dict types instead of raising ``AttributeError``. :issue:`1016`
- Fixed decoding of categories. :issue:`279`
- Link ``timedelta`` to :py:class:`datetime.timedelta` in the Python standard library documentation. :issue:`951`
- Fix round-trip parsing of :class:`~icalendar.prop.vCategory` (CATEGORIES property) when category values contain commas. Categories like ``'Meeting, John'`` now correctly survive round trips between :meth:`Component.to_ical ` and :meth:`Component.from_ical ` instead of being split into multiple categories. Added :func:`~icalendar.parser.split_on_unescaped_comma` helper function. :issue:`127`
- Fixed semicolon escaping in vCard structured properties (ADR, N, ORG). Semicolons are now correctly treated as field separators per :rfc:`6350`, not escaped as in iCalendar TEXT values. Added :func:`~icalendar.parser.split_on_unescaped_semicolon` helper function and :class:`~icalendar.prop.vAdr`, :class:`~icalendar.prop.vN`, :class:`~icalendar.prop.vOrg` property types. :issue:`137`
- Fix :meth:`Image.from_property_value ` to raise ``TypeError`` instead of ``AttributeError`` when ``value.params`` isn't valid (most notably, isn't dict-like). :issue:`909`
Documentation
~~~~~~~~~~~~~
- Improved docstrings and formatting for the :class:`~icalendar.alarms.AlarmTime` class. :issue:`1072`
- Added how-to guide for handling parsing errors with :class:`~icalendar.prop.vBroken` and the ``component.errors`` attribute. :issue:`1085`
- Updated 11 function docstrings in :mod:`icalendar.parser` to follow the Google Style guide, improving API documentation clarity and consistency. :issue:`1072`
- Applied Google-style docstrings to :mod:`icalendar.tools` utility functions with Args, Returns, and Example sections. :issue:`1072`
- Simplify contributors and add supporters in credits. :issue:`1035`
- Add a section in the change log for Documentation. :issue:`1043`
- Fixed multiple ``more than one target found for cross-reference`` warnings, and stopped using ``sphinx.ext.autosectionlabel``, in documentation. :issue:`952`
- Add ``funding.json`` manifest for funding information. :issue:`1047`
- Resolved ``Cannot resolve forward reference in type annotations`` warning in documentation.
Added ``SPHINX_APIDOC_OPTIONS`` to ``make apidoc`` command, excluding ``__all__`` items from being duplicated in the documentation, and rebuilt the API documentation source files.
:issue:`952`
- Document how to create and read attendee information in events. :issue:`130`
- Add usage examples. :issue:`443`
- Improve documentation contribution guide by adding chapters for small edits, builds and checks, and a style guide. Added details for Vale usage, Diátaxis framework, narrative and API documentation, and fixing all spelling errors. :issue:`991`
- Document dictionary and property accessors. :issue:`124`
- Moved content from the README into documentation to reduce maintenance and point to the authoritative source of information.
:issue:`1006`
- Added "Code conventions" section to the Development contributing guide.
:issue:`1004`
- Use Google style docstrings in :mod:`~icalendar.parser_tools`
:issue:`1017`
- Document compatibility of icalendar with RFCs. :issue:`1147`
- Added Upgrade guide. :issue:`997`
- Fixed links in jCal usage documentation.
- Enable sphinx-issues extension. :issue:`1091`
- Replaced "Arguments" and "Args" with "Parameters". :issue:`1076`
- Added documentation of how to set up a development environment with git. :issue:`906`
- Documented how to install and use pre-commit. :issue:`996`
- Added a new rule to our docstring style guide to escape docstrings, and added a new section for type hints in the code conventions section. :issue:`1080`
- Documented ``__init__`` methods. :issue:`1079`
- Moved "Edit this page" link to above the page table of contents. :issue:`1106`
- Added Good First Issue link and fixed Up For Grabs link in Contribute guide. :issue:`1095`
- Updated ``CONTRIBUTING.rst`` to explicitly state not to use Args sections in docstrings. :issue:`1076`
- Document ``vInt.__new__`` method parameters in class docstring with :rfc:`5545` examples. :issue:`1118`
- Improved ``make vale`` command to provide guidance on failure or success. :issue:`1137`
- Add ``sphinx_copybutton`` configuration to exclude line numbers, prompts, and console output when copying code blocks.
- Change Sphinx configuration to convert ``--`` to en dash ``-``, ``---`` to em dash ``—``, and ``...`` to ellipsis ``…``, but doesn't transform quote marks as they should be preserved.
This restores cleaner and consistent rendering of docstrings in the :doc:`API Reference <../reference/api/icalendar>`.
See `smartquotes_action `_.
- Fix incorrect return type annotation in :meth:`Component.from_ical `. :issue:`1141`
- Fixed broken links in ``docs/how-to/usage.rst`` documentation. Part of :issue:`1158`
- Enhanced the first-time contributors section, in hopes that fewer contributors ask permission before starting work. :issue:`1165`
- Changed Sphinx configuration to inherit from ``CaselessDict``, displaying all of its class members in the in-page navigation.
Fixed broken cross-component links in ``Availability.new()``. :issue:`994`
- Configured Sphinx to append the docstring from the ``__init__`` method into its class docstring. :issue:`1156`
7.0.0a3 (2025-12-19)
--------------------
Minor changes
~~~~~~~~~~~~~
- Add static ``[project.urls]`` to ``pyproject.toml`` for GitHub dependency graph compatibility. :issue:`1035`
- Created an :meth:`~cal.todo.Todo.example` method for the :class:`~cal.todo.Todo` component. :issue:`743`
- Add type hints to :mod:`icalendar.caselessdict` file. :issue:`938`
- For releases, added a step to update the version switcher for documentation.
New features
~~~~~~~~~~~~
- Added contributor list format and sorting instructions.
Bug fixes
~~~~~~~~~
- Fix double-unescaping in :meth:`vText.from_ical` and :meth:`vCategory.from_ical` by removing ``unescape_char()``. :issue:`1008`
7.0.0a2 (2025-11-29)
--------------------
Minor changes
~~~~~~~~~~~~~
- Convert changelog section labels to reStructuredText subheadings for improved Read the Docs navigation. :issue:`982`
- Move sections in Table of Content of Reference guide.
- Improve :py:class:`icalendar.prop.vDatetime` documentation. :issue:`946`
- CLI now writes output files using UTF-8 explicitly instead of relying on the system default. :issue:`1005`
New features
~~~~~~~~~~~~
- Add compatibility to :rfc:`9253`:
- Add new property types :class:`vUid` and :class:`vXmlReference`
- Add properties to all components: :attr:`Component.concepts`, :attr:`Component.links`, :attr:`Component.refids`, :attr:`Component.related_to`
- Add new values to :class:`RELTYPE`
- Add ``LABEL``, ``GAP``, and ``VALUE`` parameters to property values affected by :rfc:`9253`
- Allow setting default values in :class:`Parameters`
- Allow ``None`` as an argument to :class:`Parameters`
- Add ``ical_value`` to several property values. :issue:`876`
- Add PyData Theme version switcher to documentation. :issue:`825`
- Test compatibility with Python 3.14. :issue:`973`
- Added documentation of Vale usage for icalender documentation style guide. :issue:`815`
- Added funding link to :file:`pyproject.toml`. :issue:`800`
- Added documentation of docstring format. :issue:`747`
- Add ``TypeAlias`` ``icalendar.VPROPERTY`` as a type for all properties.
- Allow access to :class:`icalendar.TypesFactory` via :func:`icalendar.TypesFactory.instance`
- Classes in :mod:`icalendar.prop` can all be initialized with parameters now.
- Allow passing :class:`icalendar.vDDDTypes` as arguments to :class:`icalendar.vDDDLists`
- Add support for :class:`datetime.timezone` identification.
- Add :func:`icalendar.is_utc` to check if a timezone is UTC.
- Add support for JCal parsing and serialization. :issue:`978`
- Add :class:`icalendar.JCalParsingError` exception for jCal parsing.
- Add :attr:`icalendar.Parameters.tzid` and :func:`icalendar.Parameters.is_utc` for timezone handling.
- Add :class:`icalendar.vUnknown` which is the default now for unknown properties and the same as :class:`icalendar.vText`
- Add :func:`icalendar.ComponentFactory.get_component_class` that also creates a new component class when it does not exist.
- Add :func:`icalendar.ComponentFactory.add_component_class` to have a unified interface to add component classes.
- Add :func:`icalendar.Component.to_json`, :func:`icalendar.Component.to_jcal`, and :func:`icalendar.Component.from_jcal` methods so all components can be serialized and parsed.
- Classes in :mod:`icalendar.prop` receive the following updates:
- Add ``to_jcal`` and ``from_jcal`` for serialization.
- Add ``default_value`` class attribute for the default ``VALUE`` parameter.
- Add ``VALUE`` parameter property.
- Add ``examples()`` classmethod that returns examples for testing.
- Added documentation of how to fuzz icalendar. :issue:`905`
- Added first-time contributors section to Contributing. :issue:`934`
- Revised check of which files trigger a documentation build on Read the Docs. :issue:`848`
- Created a separate path to contribute to documentation. :issue:`929`
- Added a code of conduct. :issue:`907`
- Added redirects of moved files and 404 not found page to catch any other obsolete URLs. :issue:`959`
- Added artificial intelligence (AI) policy. :issue:`933`
Bug fixes
~~~~~~~~~
- Correct ``name`` of ``AVAILABLE`` component.
- Fix ical serialization of :class:`icalendar.vTime`
- Make sure a component's ``conferences`` property adds ``VALUE=URI`` if the conference is created as a URI.
- Fix CLI deprecated :py:class:`argparse.FileType` usage and remove ``PendingDeprecationWarning``. :issue:`1005`.
6.3.2 (2025-11-03)
------------------
Minor changes
~~~~~~~~~~~~~
- Add PyData Theme version switcher to documentation. See :issue:`825`.
5.0.14 (2025-11-03)
-------------------
Minor changes
~~~~~~~~~~~~~
- Add PyData Theme version switcher to documentation. See :issue:`825`.
4.1.2 (2025-11-03)
------------------
Minor changes
~~~~~~~~~~~~~
- Add PyData Theme version switcher to documentation. See :issue:`825`.
7.0.0a1 (28-10-2025)
--------------------
Minor changes
~~~~~~~~~~~~~
- Split up ``cal.py`` into different files as sub-package.
- Format more source code with ruff.
- Exclude type checking block from test coverage.
- Add private ``icalendar.compatibility`` module to merge functionality for older Python versions into one place.
- Add type annotation to ``from_ical()``.
- Fix enum documentation.
- ``DTSTAMP``, ``LAST_MODIFIED``, and ``CREATED`` can now be set to ``None`` to delete the value.
- Enhanced ``Calendar.new()`` to support organization and language parameters for automatic ``PRODID`` generation.
- Added ``duration`` setter to ``Event`` class for more intuitive event creation.
- Added ``validate()`` method to ``Calendar`` class for explicit validation of required properties and components.
- Add improved setters for ``start``, ``duration``, and ``end`` properties with explicit locking mechanisms to provide more flexible property manipulation while maintaining RFC 5545 compliance. The implementation includes comprehensive test coverage to ensure proper behavior and backward compatibility.
- Add ``new()`` method to ``vCalAddress`` class for consistent API usage. The method supports all RFC 5545 parameters including ``CN``, ``CUTYPE``, ``DELEGATED-FROM``, ``DELEGATED-TO``, ``DIR``, ``LANGUAGE``, ``PARTSTAT``, ``ROLE``, ``RSVP``, and ``SENT-BY``, with automatic ``mailto:`` prefix handling. See :issue:`870`.
- Refactor ``set_duration`` methods in ``Event`` and ``Todo`` classes to eliminate code duplication by extracting common logic into shared ``set_duration_with_locking()`` function in ``icalendar.attr``. See :issue:`886`.
- Consolidate duplicate logic patterns between ``Event`` and ``Todo`` classes by extracting shared functions in ``icalendar.attr`` for property setters, validation logic, and property access. This eliminates approximately 150 lines of duplicate code while maintaining 100% backward compatibility and RFC 5545 compliance. See :issue:`891`.
- Accept and ignore non-standard empty ``RDATE`` fields when parsing ICS files.
- Improve contributing documentation by adding a change log requirement, adding a pull request template, adding clear CI enforcement warnings, and updating ``README.rst``. See :issue:`890`.
- Make coverage submission optional for CI.
- Bump ``actions/setup-python`` version from 5 to 6 for CI.
- Add comment explaining tzdata dependency purpose to prevent confusion. See :issue:`900`.
- Fix duplicate blank issue template by adding config.yml to disable GitHub's default blank option. See :issue:`777`.
- Add PEP 561 py.typed marker to enable type checking support. The package now distributes inline type annotations for mypy and other type checkers. See :issue:`395`.
- Bump ``github/codeql-action`` from 3 to 4 in CI fuzzing workflow.
- Add docstring for ``vDatetime``. See :issue:`742`.
- Update LICENSE file heading formatting.
- Document ``icalendar.version`` module.
- Use ``CONTRIBUTING.md`` in favour of ``.rst`` file.
- Add type hints to ``icalendar.tools`` module.
- Fix more examples link failed in ``README.md`` by renewing its link. See :issue:`958`.
- Fix Contributing, Changelog, License links failed in ``README.md`` by renewing its link. See :issue:`959`.
- Fix more examples link in ``README.md``. See :issue:`958`.
- Add ``CODEOWNERS`` file for automatic pull request review assignment. See :issue:`945`.
Breaking changes
~~~~~~~~~~~~~~~~
- Correctly throw a ``TypeError`` for wrong types during property creation where a ``ValueError`` was thrown before.
- Move ``types_factory`` into ``Component.types_factory``
- Move ``components_factory`` into ``Component.get_component_class``
- Move ``icalendar.cal.IncompleteComponent`` error into ``icalendar.error``.
- Remove ``icalendar.UIDGenerator``. Use Python's built-in `uuid library `_ instead.
New features
~~~~~~~~~~~~
- Add ``new()`` to ``icalendar.Calendar`` to set required attributes. See :pr:`569`.
- Add ``new()`` to ``Alarm``, ``Event``, ``Todo``, ``FreeBusy``, ``Component``, and ``Journal`` components. See :issue:`843`.
- Add ``value`` to ``Parameters`` to access the ``VALUE`` parameter.
- Add ``Availability`` and ``Available`` components from :rfc:`7953`. See :issue:`654` and :issue:`864`.
- Add ``stamp``, ``last_modified``, ``created``, ``CREATED``, ``busy_type``, ``class``, ``comments``, ``contacts``, ``location``, ``organizer``, ``priority``, and ``url`` properties to components that use them.
- Add ``availabilities`` attribtue to ``Calendar``.
- Add ``status``, ``transparency``, and ``attendees`` properties. See :issue:`841`.
- Add ``uid`` property that is ``''`` by default and set automatically with ``new()``. See :issue:`315`.
- Make icalendar compatible with `RFC 7986 `_.
- Add ``url``, ``source``, ``refresh_interval``, ``conferences``, and ``images`` properties to components.
- Add ``td`` property to ``vDDDTypes`` to make it compatible with ``timedelta`` value types.
- Add documentation for how to install icalendar on Fedora. See :issue:`704`.
- Add documentation linkchecker to make and CI configuration. See :issue:`854`.
- Add support for Vale as spell and style checker.
- For ``make livehtml`` watch all files in ``src/icalendar``, but ignore ``.typed`` and contents of the ``tests`` and ``fuzzing`` directories. See :issue:`931`.
- Restructure documentation, following Diátaxis framework. See :issue:`820` which included the following tasks.
- Start building API Reference documentation.
- Add Vale with Microsoft Writing Guide style checker.
- Add :file:`Makefile` to automate all documentation builds with a single command for each.
- Write documentation of how to build documentation.
- Move "History" into "Credits".
- Add a Glossary of terms.
- Add version module to API reference.
- Exclude private Python methods and test modules from the API reference.
- Fix display of credits to use reStructuredText.
- Fix the documentation version display.
- Show older versions of documentation on Read the Docs.
- Fix the PyPI icon.
- Add a Security Policy.
- Consolidate Contributing files into the how-to Contributing guide.
- Move the change log into the Reference guide.
- Remove all rights reserved from the License file and remove from documentation, leaving it in the repository root.
- Move Maintenance into the Contribute guide.
- Move icalendar contributors into the Contribute guide.
- Merge about the project into Credits.
- Split :file:`api.rst` into separate modules.
- Move "icalendar utility" into a how-to guide for command line interface.
- Move "icalendar package" into a how-to usage guide and API reference guide.
- Split installation into how-to guides for usage and contributing.
- Redesigned home page to reflect the new structure and point readers to the proper location.
- Fix various Sphinx build warnings and errors.
- Use text for lexer of ical files.
- Update :file:`README.rst` to align with new documentation structure.
- Add documentation builds to continuous integration.
- Review pull requests that involve source docstrings, continuous integration, or documentation, and provide suggestions and corrections.
- Add spell checking to documentation. See :issue:`853`.
- Add link check to docs test. See :issue:`854`.
- Document installation of icalendar on Fedora. See :issue:`704`.
- Miscellaneous documentation follow-up fixes. See :issue:`919`.
Bug fixes
~~~~~~~~~
- Fix ``Todo.end`` to return ``start`` for date-only ``DTSTART`` (not ``start + 1 day``). Events keep existing behavior. See :issue:`898`.
- Fix ``AssertionError`` when converting ``VTIMEZONE`` components with only ``DAYLIGHT`` subcomponent (no ``STANDARD``) to pytz timezones. The code now handles cases where a timezone definition contains only DST transitions by calculating the DST offset from ``TZOFFSETFROM`` and ``TZOFFSETTO``. Test case contributed by @niccokunzmann in :pr:`379`. See :issue:`321`.
- Normalize Conference parameter lists (FEATURE/LABEL/LANGUAGE) to comma-separated values. See :issue:`908`.
- Fix read from stdin issue - See :issue:`821`.
- Fix invalid calendar: Parsing a date with TZID results in a datetime to not loose the timezone. See :issue:`187`.
- Fix timezone placement in ``add_missing_timezones()``: ``VTIMEZONE`` components now appear before ``VEVENT`` and other components that reference them. See :issue:`844`.
- Fixed ``Todo.duration`` and ``Event.duration`` to return ``DURATION`` property when set, even without ``DTSTART``. See :issue:`867`.
- Fix ``VALUE`` parameter handling: ``datetime.date`` objects now correctly set ``VALUE=DATE`` parameter when added to properties like ``EXDATE``, ``RDATE``, and ``DTSTART``. The ``VALUE`` parameter is also properly used when parsing iCalendar data. See :issue:`349`.
- Fix URL-encoded characters being incorrectly unescaped during content line parsing. The parser now properly handles backslash escaping and double-quoted sections without corrupting URL-encoded values like ``%3A`` (colon) in DESCRIPTION fields. Added ``unescape_backslash()`` function to separate :rfc:`5545` backslash escaping from URL encoding. Optimized implementation using regex for single-pass processing. Added type hints to ``Contentline.parts()`` method and comprehensive unit tests. See :issue:`355`.
- `make livehtml` now reloads with code changes. See :issue:`931`.
- Added tests for tools, vFloat, vBinary, vGeo, and vTodo to improve unit test coverage. :issue:`698`
6.3.1 (2025-05-20)
------------------
Bug fixes
~~~~~~~~~
- Remove forced quoting from parameters with space and single quote. See :issue:`836`.
6.3.0 (2025-05-15)
------------------
Minor changes
~~~~~~~~~~~~~
- Deprecate ``icalendar.UIDGenerator``. See :issue:`816`.
New features
~~~~~~~~~~~~
- Add the ``uid`` property to ``Alarm``, ``Event``, ``Calendar``, ``Todo``, and ``Journal`` components. See :issue:`740`.
Bug fixes
~~~~~~~~~
- Fix component equality where timezones differ for the datetimes but the times are actually equal. See :issue:`828`.
- Test that we can add an RRULE as a string. See :issue:`301`.
- Test that we support dateutil timezones as outlined in :issue:`336`.
- Build documentation on Read the Docs with the version identifier. See :issue:`826`.
6.2.0 (2025-05-07)
------------------
Minor changes
~~~~~~~~~~~~~
- Use ``ruff`` to format the source code.
- Update project metadata to use License-Expression.
- Use ``tzp.localize(dt, None)`` to remove the timezone from a datetime.
- Remove the HTML documentation when building with ``tox`` to force rebuild.
- Switch to PyData Sphinx Theme for documentation. See :pr:`803`.
New features
~~~~~~~~~~~~
- Add getters ``rrules``, ``rdates``, and ``exdates`` for unified and simple access to these properties. See `Discussion 662`_.
- Add attributes to the calendar for properties ``NAME``, ``DESCRIPTION``, and ``COLOR``. See :issue:`655`.
- Add a ``color`` attribute to ``Event``, ``Todo``, and ``Journal`` components. See :issue:`655`.
- Add ``sequence`` attribute to ``Event``, ``Todo``, and ``Journal`` components. See :issue:`802`.
- Add ``categories`` attribute to ``Calendar``, ``Event``, ``Todo``, and ``Journal`` components. See :issue:`655`.
- Add compatibility to :rfc:`6868`. See :issue:`652`.
- Add ``freebusy`` property to the ``Calendar`` to get this type of subcomponents easier.
- Add parameters from :rfc:`5545` to properties ``ALTREP``, ``CN``, ``CUTYPE``, ``DELEGATED_FROM``, ``DELEGATED_TO``, ``DIR``, ``FBTYPE``, ``LANGUAGE``, ``MEMBER``, ``PARTSTAT``, ``RANGE``, ``RELATED``, ``ROLE``, ``RSVP``, ``SENT_BY``, ``TZID``, and ``RELTYPE``. See :issue:`798`.
- New properties from :rfc:`7986` can occur multiple times in ``VCALENDAR``. See :pr:`808`.
Bug fixes
~~~~~~~~~
- Fix ``STANDARD`` and ``DAYLIGHT`` components that have a date as ``DTSTART``. See :issue:`218`
- Move import at the end of ``icalendar.parser`` into a function to mitigate import errors, see :issue:`781`.
- ``ALTREP``, ``DELEGATED-FROM``, ``DELEGATED-TO``, ``DIR``, ``MEMBER``, and ``SENT-BY`` require double quotes. These are now always added.
- Classify ``CATEGORIES`` as multiple in ``VEVENT``. See :pr:`808`.
6.1.3 (2025-03-19)
------------------
Bug fixes
~~~~~~~~~
- Fix to permit TZID forward references to ``VTIMEZONE``\ s
- Stabelize timezone id lookup, see :issue:`780`.
6.1.2 (2025-03-19)
------------------
Minor changes
~~~~~~~~~~~~~
- Add funding link to Tidelift.
- Link to related package.
- Shorten first example in documentation.
- Add ``name`` and ``email`` properties to ``vCalAddress``.
- Add type hint for property ``params`` in ``icalendar.prop``.
- Set default value for ``params`` as ``params={}`` in mulitple constructors in ``icalendar.prop`` to improve usability.
- Improve object initialization performance in ``icalendar.prop``.
- Add type hint for ``params`` in multiple constructors in ``icalendar.prop``.
Bug fixes
~~~~~~~~~
- Restrict timezones tested, see :issue:`763`
6.1.1 (2025-01-18)
------------------
Minor changes
~~~~~~~~~~~~~
- Add a ``weekday`` attribute to :class:`icalendar.prop.vWeekday` components. See :issue:`749`.
- Document :class:`icalendar.prop.vRecur` property. See :issue:`758`.
- Print failure of doctest to aid debugging.
- Improve documentation of :class:`icalendar.prop.vGeo`
- Fix tests, improve code readability, fix typing. See :pr:`766` and :pr:`765`.
Breaking changes
~~~~~~~~~~~~~~~~
- The ``relative`` attribute of ``vWeekday`` components has the correct sign now. See :issue:`749`.
New features
~~~~~~~~~~~~
- Add `Security Policy `_
- Python types in documentation now link to their documentation pages using ``intersphinx``.
6.1.0 (2024-11-22)
------------------
Minor changes
~~~~~~~~~~~~~
- Add ``end``, ``start``, ``duration``, ``DTSTART``, ``DUE``, and ``DURATION`` attributes to ``Todo`` components. See `Discussion 662`_.
- Add ``DTSTART``, ``TZOFFSETTO`` and ``TZOFFSETFROM`` properties to ``TimezoneStandard`` and ``TimezoneDaylight``. See `Discussion 662`_.
- Format test code with Ruff. See :issue:`672`.
- Document the Debian package. See :issue:`701`.
- Document ``vDatetime.from_ical``
- Allow passing a ``datetime.date`` to ``TZP.localize_utc`` and ``TZP.localize`` methods.
- Document component classes with description from :rfc:`5545`.
- Merge "File Structure" and "Overview" sections in the docs. See :issue:`626`.
- Update code blocks in ``usage.rst`` with the correct lexer.
- Tidy up the docstring for ``icalendar.prop.vPeriod``.
- Improve typing and fix typing issues
New features
~~~~~~~~~~~~
- Add ``VALARM`` properties for :rfc:`9074`. See :issue:`657`
- Test compatibility with Python 3.13
- Add ``Timezone.from_tzinfo()`` and ``Timezone.from_tzid()`` to create a ``Timezone`` component from a ``datetime.tzinfo`` timezone. See :issue:`722`.
- Add ``icalendar.prop.tzid_from_tzinfo``.
- Add ``icalendar.alarms`` module to calculate alarm times. See :issue:`716`.
- Add ``Event.alarms`` and ``Todo.alarms`` to access alarm calculation.
- Add ``Component.DTSTAMP`` and ``Component.LAST_MODIFIED`` properties for datetime in UTC.
- Add ``Component.is_thunderbird()`` to check if the component uses custom properties by Thunderbird.
- Add ``X_MOZ_SNOOZE_TIME`` and ``X_MOZ_LASTACK`` properties to ``Event`` and ``Todo``.
- Add ``Alarm.ACKNOWLEDGED``, ``Alarm.TRIGGER``, ``Alarm.REPEAT``, and ``Alarm.DURATION`` properties
as well as ``Alarm.triggers`` to calculate alarm triggers.
- Add ``__doc__`` string documentation for ``vDate``, ``vBoolean``, ``vCalAddress``, ``vDuration``, ``vFloat``, ``vGeo``, ``vInt``, ``vPeriod``, ``vTime``, ``vUTCOffset`` and ``vUri``. See :issue:`742`.
- Add ``DTSTART``, ``TZOFFSETTO``, and ``TZOFFSETFROM`` to ``TimezoneStandard`` and ``TimezoneDaylight``
- Use ``example`` methods of components without arguments.
- Add ``events``, ``timezones``, and ``todos`` property to ``Calendar`` for nicer access.
- To calculate which timezones are in use and add them to the ``Calendar`` when needed these methods are added: ``get_used_tzids``, ``get_missing_tzids``, and ``add_missing_timezones()``.
- Identify the TZID of more timezones from dateutil.
- Identify totally unknown timezones using a UTC offset lookup tree generated in ``icalendar.timezone.equivalent_timezone_ids`` and stored in ``icalendar.timezone.equivalent_timezone_ids``.
- Add ``icalendar.timezone.tzid`` to identify a timezone's TZID.
Bug fixes
~~~~~~~~~
- Add ``icalendar.timezone`` to the documentation.
6.0.1 (2024-10-13)
------------------
New features
~~~~~~~~~~~~
- Added ``end``, ``start``, ``duration``, ``DTSTART``, ``DUE``, and ``DURATION`` attributes to ``Event`` components. See `Discussion 662`_.
- Added ``end``, ``start``, ``duration``, and ``DTSTART`` attributes to ``Journal`` components. See `Discussion 662`_.
Bug fixes
~~~~~~~~~
- Fix a few ``__all__`` variables.
- Added missing ``docs`` folder to distribution packages. See :issue:`712`.
.. _`Discussion 662`: https://github.com/collective/icalendar/discussions/662
6.0.0 (2024-09-28)
------------------
Minor changes
~~~~~~~~~~~~~
- Add ``__all__`` variable to each modules in ``icalendar`` package
- Improve test coverage.
- Adapt ``test_with_doctest.py`` to correctly run on Windows.
- Measure branch coverage when running tests.
- Export ``Component`` base class for typing
New features
~~~~~~~~~~~~
- Use ``pyproject.toml`` file instead of ``setup.py``
Bug fixes
~~~~~~~~~
- Fix link to stable release of tox in documentation.
- Fix a bad ``bytes`` replace in ``unescape_char``.
- Handle ``ValueError`` in ``vBinary.from_ical``.
- Ignore the BOM character in incorrectly encoded ics files.
6.0.0a0 (2024-07-03)
--------------------
Minor changes
~~~~~~~~~~~~~
- Test that all code works with both ``pytz`` and ``zoneinfo``.
- Add message to GitHub release, pointing to the changelog
- Make coverage report submission optional for pull requests
- Parallelize coverage
- Rename ``master`` branch to ``main``, see `Issue
`_
- Update ``docs/usage.rst`` to use zoneinfo instead of pytz.
- Added missing public classes and functions to API documentation.
- Improved namespace management in the ``icalendar`` directory.
- Add Python version badge and badge for test coverage
- Remove 4.x badge
- Update list of ``tox`` environments
- Use Coveralls' GitHub Action
- Check distribution in CI
Breaking changes
~~~~~~~~~~~~~~~~
- Use ``zoneinfo`` for ``icalendar`` objects created from strings,
see :issue:`609`.
This is an tested extension of the functionality, not a restriction:
If you create ``icalendar`` objects with ``pytz`` timezones in your code,
``icalendar`` will continue to work in the same way.
Your code is not affected.
``zoneinfo`` will be used for those **objects that** ``icalendar``
**creates itself**.
This happens for example when parsing an ``.ics`` file, strings or bytes with
``from_ical()``.
If you rely on ``icalendar`` providing timezones from ``pytz``, you can add
one line to your code to get the behavior of versions below 6:
.. code:: Python
import icalendar
icalendar.use_pytz()
- Replaced ``pkg_resources.get_distribution`` with ``importlib.metadata`` in
``docs/conf.py`` to allow building docs on Python 3.12.
- Remove ``is_broken`` property. Use ``errors`` instead to check if a
component had suppressed parsing errors.
See :issue:`424`.
- Remove untested and broken ``LocalTimezone`` and ``FixedOffset`` tzinfo
sub-classes, see :issue:`67`
- Remove Python 3.7 as compatible. icalendar is compatible with Python
versions 3.8 - 3.12, and PyPy3.
- Remove ``pytz`` as a dependency of ``icalendar``. If you require ``pytz``,
add it to your dependency list or install it additionally with::
pip install icalendar==6.* pytz
New features
~~~~~~~~~~~~
- Check code quality with `Ruff `_, optional report
- Test compatibility with Python 3.12
- Add function ``icalendar.use_pytz()``.
- Allows selecting components with ``walk(select=func)`` where ``func`` takes a
component and returns ``True`` or ``False``.
- Add compatibility to :rfc:`7529`, adding ``vMonth`` and ``vSkip``
- Add ``sphinx-autobuild`` for ``livehtml`` Makefile target.
- Add pull request preview on Read the Docs, building only on changes to documentation-related files.
- Add link to pull request preview builds in the pull request description only when there are changes to documentation-related files.
- Add documentation of live HTML preview of documentation and clean up of ``install.rst``.
- Add ``sphinx-copybutton`` to allow copying code blocks with a single click of a button.
Bug fixes
~~~~~~~~~
- Change documentation to represent compatibility with Python 3.8 - 3.12, and PyPy3.
- Rename RFC 2445 to RFC 5545, see `Issue 278
`_
5.0.13 (2024-06-20)
-------------------
Minor changes
~~~~~~~~~~~~~
- Guide to delete the build folder before running tests
- Add funding information
- Make documentation build with Python 3.12
- Update windows to olson conversion for Greenland Standard Time
- Extend examples in Usage with alarm and recurrence
- Document how to serve the built documentation to view with the browser
- Improve test coverage
New features
~~~~~~~~~~~~
- Create GitHub releases for each tag.
Bug fixes
~~~~~~~~~
- Parse calendars with X-COMMENT properties at the end the file by ignoring these properites
5.0.12 (2024-03-19)
-------------------
Minor changes
~~~~~~~~~~~~~
- Analyse code coverage of test files
- Added corpus to fuzzing directory
- Added exclusion of fuzzing corpus in MANIFEST.in
- Augmented fuzzer to optionally convert multiple calendars from a source string
- Add script to convert OSS FUZZ test cases to Python/pytest test cases
- Added additional exception handling of defined errors to fuzzer, to allow fuzzer to explore deeper
- Added more instrumentation to fuzz-harness
- Rename "contributor" to "collaborator" in documentation
- Correct the outdated "icalendar view myfile.ics" command in documentation. #588
- Update GitHub Actions steps versions
- Keep GitHub Actions up to date with GitHub's Dependabot
Bug fixes
~~~~~~~~~
- Fixed index error in cal.py when attempting to pop from an empty stack
- Fixed type error in prop.py when attempting to join strings into a byte-string
- Caught Wrong Date Format in ical_fuzzer to resolve fuzzing coverage blocker
5.0.11 (2023-11-03)
-------------------
Minor changes
~~~~~~~~~~~~~
- The cli utility now displays start and end datetimes in the user's local timezone.
Ref: #561
[vimpostor]
New features
~~~~~~~~~~~~
- Added fuzzing harnesses, for integration to OSSFuzz.
- icalendar releases are deployed to Github releases
Fixes: #563
[jacadzaca]
Bug fixes
~~~~~~~~~
- CATEGORIES field now accepts a string as argument
Ref: #322
[jacadzaca]
- Multivalue FREEBUSY property is now parsed properly
Ref: #27
[jacadzaca]
- Compare equality and inequality of calendars more completely
Ref: #570
- Use non legacy timezone name.
Ref: #567
- Add some compare functions.
Ref: #568
- Change OSS Fuzz build script to point to harnesses in fuzzing directory
Ref: #574
5.0.10 (2023-09-26)
-------------------
Bug fixes
~~~~~~~~~
- Component._encode stops ignoring parameters argument on native values, now merges them
Fixes: #557
[zocker1999net]
5.0.9 (2023-09-24)
------------------
Bug fixes
~~~~~~~~~
- PERIOD values now set the timezone of their start and end. #556
5.0.8 (2023-09-18)
------------------
Minor changes
~~~~~~~~~~~~~
- Update build configuration to build readthedocs. #538
- No longer run the ``plone.app.event`` tests.
- Add documentation on how to parse ``.ics`` files. #152
- Move pip caching into Python setup action.
- Check that issue #165 can be closed.
- Updated about.rst for issue #527
- Avoid ``vText.__repr__`` BytesWarning.
Bug fixes
~~~~~~~~~
- Calendar components are now properly compared
Ref: #550
Fixes: #526
[jacadzaca]
5.0.7 (2023-05-29)
------------------
Bug fixes
~~~~~~~~~
- to_ical() now accepts RRULE BYDAY values>=10 #518
5.0.6 (2023-05-26)
------------------
Minor changes
~~~~~~~~~~~~~
- Adjusted duration regex
5.0.5 (2023-04-13)
------------------
Minor changes
~~~~~~~~~~~~~
- Added support for BYWEEKDAY in vRecur ref: #268
Bug fixes
~~~~~~~~~
- Fix problem with ORGANIZER in FREE/BUSY #348
5.0.4 (2022-12-29)
------------------
Minor changes
~~~~~~~~~~~~~
- Improved documentation
Ref: #503, #504
Bug fixes
~~~~~~~~~
- vBoolean can now be used as an parameter
Ref: #501
Fixes: #500
[jacadzaca]
5.0.3 (2022-11-23)
------------------
New features
~~~~~~~~~~~~
- vDDDTypes is hashable #487 #492 [niccokunzmann]
Bug fixes
~~~~~~~~~
- vDDDTypes' equality also checks the dt attribute #497 #492 [niccokunzmann]
5.0.2 (2022-11-03)
------------------
Minor changes
~~~~~~~~~~~~~
- Refactored cal.py, tools.py and completed remaining minimal refactoring in parser.py. Ref: #481 [pronoym99]
- Calendar.from_ical no longer throws long errors
Ref: #473
Fixes: #472
[jacadzaca]
- Make datetime value shorter by removing the value parameter where possible.
Fixes: #318
[jacadzaca], [niccokunzmann]
New features
~~~~~~~~~~~~
- source code in documentation is tested using doctest #445 [niccokunzmann]
Bug fixes
~~~~~~~~~
- broken properties are not added to the parent component
Ref: #471
Fixes: #464
[jacadzaca]
5.0.1 (2022-10-22)
------------------
Minor changes
~~~~~~~~~~~~~
- fixed setuptools deprecation warnings [mgorny]
Bug fixes
~~~~~~~~~
- a well-known timezone timezone prefixed with a `/` is treated as if the slash wasn't present
Ref: #467
Fixes: #466
[jacadzaca]
5.0.0 (2022-10-17)
------------------
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]
- icalendar now takes a ics file directly as an input
- icalendar's CLI utility program's output is different
- Drop Support for Python 3.6. Versions 3.7 - 3.11 are supported and tested.
New features
~~~~~~~~~~~~
- icalendar utility outputs a 'Duration' row
- icalendar can take multiple ics files as an input
Bug fixes
~~~~~~~~~
- Changed tools.UIDGenerator instance methods to static methods
Ref: #345
[spralja]
- proper handling of datetime objects with `tzinfo` generated through zoneinfo.ZoneInfo.
Ref: #334
Fixes: #333
[tobixen]
- Timestamps in UTC does not need tzid
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)
--------------------
Breaking changes
~~~~~~~~~~~~~~~~
- Drop support for Python 3.4, 3.5 and PyPy2. [maurits]
New features
~~~~~~~~~~~~
- Document development setup
Ref: #358
[niccokunzmann]
Bug fixes
~~~~~~~~~
- Test with GitHub Actions. [maurits]
4.1.0 (2022-07-11)
------------------
New features
~~~~~~~~~~~~
- No longer test on Python 3.4, 3.5 and PyPy2, because we cannot get it to work.
Technically it should still work, it is just no longer tested.
Do not expect much development on branch 4.x anymore.
The main branch will be for the remaining Python versions that we support.
[maurits]
Bug fixes
~~~~~~~~~
- Test with GitHub Actions. [maurits]
4.0.9 (2021-10-16)
------------------
Bug fixes
~~~~~~~~~
- Fix vCategories for correct en/de coding.
[thet]
- vDuration property value: Fix changing duration sign after multiple ``to_ical`` calls.
Ref: #320
Fixes: #319
[barlik]
4.0.8 (2021-10-07)
------------------
Bug fixes
~~~~~~~~~
- Support added for Python 3.9 and 3.10 (no code changes needed).
- Replace bare 'except:' with 'except Exception:' (#281)
4.0.7 (2020-09-07)
------------------
Bug fixes
~~~~~~~~~
- fixed rrule handling, re-enabled test_create_america_new_york()
4.0.6 (2020-05-06)
------------------
Bug fixes
~~~~~~~~~
- Use ``vText`` as default type, when convert recurrence definition to ical string. [kam193]
4.0.5 (2020-03-21)
------------------
Bug fixes
~~~~~~~~~
- Fixed a docs issue related to building on Read the Docs [davidfischer]
4.0.4 (2019-11-25)
------------------
Bug fixes
~~~~~~~~~
- Reduce Hypothesis iterations to speed up testing, allowing PRs to pass
[UniversalSuperBox]
4.0.3 (2018-10-10)
------------------
Bug fixes
~~~~~~~~~
- Categories are comma separated not 1 per line #265. [cleder]
- mark test with mixed timezoneaware and naive datetimes as an expected failure. [cleder]
4.0.2 (2018-06-20)
------------------
Bug fixes
~~~~~~~~~
- Update all pypi.python.org URLs to pypi.org
[jon.dufresne]
4.0.1 (2018-02-11)
------------------
- Added rudimentary command line interface.
[jfjlaros]
- Readme, setup and travis updates.
[jdufresne, PabloCastellano]
4.0.0 (2017-11-08)
------------------
Breaking changes
~~~~~~~~~~~~~~~~
- Drop support for Python 2.6 and 3.3.
3.12 (2017-11-07)
-----------------
New features
~~~~~~~~~~~~
- Accept Windows timezone identifiers as valid. #242 [geier]
Bug fixes
~~~~~~~~~
- Fix ResourceWarnings in setup.py when Python warnings are enabled. #244 [jdufresne]
- Fix invalid escape sequences in string and bytes literals. #245 [jdufresne]
- Include license file in the generated wheel package. #243 [jdufresne]
- Fix non-ASCII TZID and TZNAME parameter handling. #238 [clivest]
- Docs: update install instructions. #240 [Ekran]
3.11.7 (2017-08-27)
-------------------
New features
~~~~~~~~~~~~
- added vUTCOffset.ignore_exceptions to allow surpressing of failed TZOFFSET
parsing (for now this ignores the check for offsets > 24h) [geier]
3.11.6 (2017-08-04)
-------------------
Bug fixes
~~~~~~~~~
- Fix ``VTIMEZONE``\ s including RDATEs #234. [geier]
3.11.5 (2017-07-03)
-------------------
Bug fixes
~~~~~~~~~
- added an assertion that ``VTIMEZONE`` sub-components' DTSTART must be of type
DATETIME [geier]
- Fix handling of ``VTIMEZONE``\ s with subcomponents with the same DTSTARTs and
OFFSETs but which are of different types [geier]
3.11.4 (2017-05-10)
-------------------
Bug fixes
~~~~~~~~~
- Don't break on parameter values which contain equal signs, e.g. base64 encoded
binary data [geier]
- Fix handling of ``VTIMEZONE``\ s with subcomponents with the same DTSTARTs.
[geier]
3.11.3 (2017-02-15)
-------------------
Bug fixes
~~~~~~~~~
- Removed ``setuptools`` as a dependency as it was only required by setup.py
and not by the package.
- Don't split content lines on the unicode ``LINE SEPARATOR`` character
``\u2028`` but only on ``CRLF`` or ``LF``.
3.11.2 (2017-01-12)
-------------------
Bug fixes
~~~~~~~~~
- Run tests with python 3.5 and 3.6.
[geier]
- Allow tests failing with pypy3 on travis.ci.
[geier]
3.11.1 (2016-12-19)
-------------------
Bug fixes
~~~~~~~~~
- Encode error message before adding it to the stack of collected error messages.
3.11 (2016-11-18)
-----------------
Fixes:
- Successfully test with pypy and pypy3. [gforcada]
- Minor documentation update. [tpltnt]
3.10 (2016-05-26)
-----------------
New:
- Updated components description to better comply with RFC 5545.
Refs #183.
[stlaz]
- Added PERIOD value type to date types.
Also fixes incompatibilities described in #184.
Refs #189.
[stlaz]
Fixes:
- Fix testsuite for use with ``dateutil>=2.5``.
Refs #195.
[untitaker]
- Reintroduce cal.Component.is_broken that was removed with 3.9.2.
Refs #185.
[geier]
3.9.2 (2016-02-05)
------------------
New:
- Defined ``test_suite`` in setup.py.
Now tests can be run via ``python setup.py test``.
[geier]
Fixes:
- Fixed cal.Component.from_ical() representing an unknown component as one of the known.
[stlaz]
- Fixed possible IndexError exception during parsing of an ical string.
[stlaz]
- When doing a boolean test on ``icalendar.cal.Component``, always return ``True``.
Before it was returning ``False`` due to CaselessDict, if it didn't contain any items.
[stlaz]
- Fixed date-time being recognized as date or time during parsing.
Added better error handling to parsing from ical strings.
[stlaz]
- Added __version__ attribute to init.py.
[TomTry]
- Documentation fixes.
[TomTry]
- Pep 8, UTF 8 headers, dict/list calls to literals.
[thet]
3.9.1 (2015-09-08)
------------------
- Fix ``vPeriod.__repr__``.
[spacekpe]
- Improve foldline() performance. This improves the foldline performance,
especially for large strings like base64-encoded inline attachements. In some
cases (1MB string) from 7 Minutes to less than 20ms for ASCII data and 500ms
for non-ASCII data. Ref: #163.
[emfree]
3.9.0 (2015-03-24)
------------------
- Creating timezone objects from ``VTIMEZONE`` components.
[geier]
- Make ``python-dateutil`` a dependency.
[geier]
- Made RRULE tolerant of trailing semicolons.
[sleeper]
- Documentation fixes.
[t-8ch, thet]
3.8.4 (2014-11-01)
------------------
- Add missing BYWEEKNO to recurrence rules.
[russkel]
3.8.3 (2014-08-26)
------------------
- PERCENT property in VTODO renamed to PERCENT-COMPLETE, according to RFC5545.
[thomascube]
3.8.2 (2014-07-22)
------------------
- Exclude editor backup files from egg distributions. Fixes #144.
[thet]
3.8.1 (2014-07-17)
------------------
- The representation of CaselessDicts in 3.8 changed the name attribute of
Components and therefore broke the external API. This has been fixed.
[untitaker]
3.8 (2014-07-17)
----------------
- Allow dots in property names (Needed for vCard compatibility). Refs #143.
[untitaker]
- Change class representation for CaselessDict objects to always include the
class name or the class' name attribute, if available. Also show
subcomponents for Component objects.
[thet]
- Don't use data_encode for CaselessDict class representation but use dict's
__repr__ method.
[t-8ch]
- Handle parameters with multiple values, which is needed for vCard 3.0.
Refs #142.
[t-8ch]
3.7 (2014-06-02)
----------------
- For components with ``ignore_exceptions`` set to ``True``, mark unparseable
lines as broken instead rising a ``ValueError``. ``VEVENT`` components have
``ignore_exceptions`` set to ``True`` by default. Ref #131. Fixes #104.
[jkiang13]
- Make ``python-dateutil`` a soft-dependency.
[boltnev]
- Add optional ``sorted`` parameter to ``Component.to_ical``. Setting it to
false allows the user to preserve the original property and parameter order.
Ref #136. Fixes #133.
[untitaker]
- Fix tests for latest ``pytz``. Don't set ``tzinfo`` directly on datetime
objects, but use pytz's ``localize`` function. Ref #138.
[untitaker, thet]
- Remove incorrect use of __all__. We don't encourage using ``from package
import *`` imports. Fixes #129.
[eric-wieser]
3.6.2 (2014-04-05)
------------------
- Pep8 and cleanup.
[lasudry]
3.6.1 (2014-01-13)
------------------
- Open text files referenced by setup.py as utf-8, no matter what the locale
settings are set to. Fixes #122.
[sochotnicky]
- Add tox.ini to source tarball, which simplifies testing for in distributions.
[sochotnicky]
3.6 (2014-01-06)
----------------
- Python3 (3.3+) + Python 2 (2.6+) support [geier]
- Made sure to_ical() always returns bytes [geier]
- Support adding lists to a component property, which value already was a list
and remove the Component.set method, which was only used by the add method.
[thet]
- Remove ability to add property parameters via a value's params attribute when
adding via cal.add (that was only possible for custom value objects and makes
up a strange API), but support a parameter attribute on cal.add's method
signature to pass a dictionary with property parameter key/value pairs.
Fixes #116.
[thet]
- Backport some of Regebro's changes from his regebro-refactor branch.
[thet]
- Raise explicit error on another malformed content line case.
[hajdbo]
- Correctly parse datetime component property values with timezone information
when parsed from ical strings.
[untitaker]
3.5 (2013-07-03)
----------------
- Let to_unicode be more graceful for non-unicode strings, as like CMFPlone's
safe_unicode does it.
[thet]
3.4 (2013-04-24)
----------------
- Switch to unicode internally. This should fix all en/decoding errors.
[thet]
- Support for non-ascii parameter values. Fixes #88.
[warvariuc]
- Added functions to transform chars in string with '\\' + any of r'\,;:' chars
into '%{:02X}' form to avoid splitting on chars escaped with '\\'.
[warvariuc]
- Allow seconds in vUTCOffset properties. Fixes #55.
[thet]
- Let ``Component.decode`` better handle vRecur and vDDDLists properties.
Fixes #70.
[thet]
- Don't let ``Component.add`` re-encode already encoded values. This simplifies
the API, since there is no need explicitly pass ``encode=False``. Fixes #82.
[thet]
- Rename tzinfo_from_dt to tzid_from_dt, which is what it does.
[thet]
- More support for dateutil parsed tzinfo objects. Fixes #89.
[leo-naeka]
- Remove python-dateutil version fix at all. Current python-dateutil has Py3
and Py2 compatibility.
[thet]
- Declare the required python-dateutil dependency in setup.py. Fixes #90.
[kleink]
- Raise test coverage.
[thet]
- Remove interfaces module, as it is unused.
[thet]
- Remove ``test_doctests.py``, test suite already created properly in
``test_icalendar.py``.
[rnix]
- Transformed doctests into unittests, Test fixes and cleanup.
[warvariuc]
3.3 (2013-02-08)
----------------
- Drop support for Python < 2.6.
[thet]
- Allow vGeo to be instantiated with list and not only tuples of geo
coordinates. Fixes #83.
[thet]
- Don't force to pass a list to vDDDLists and allow setting individual RDATE
and EXDATE values without having to wrap them in a list.
[thet]
- Fix encoding function to allow setting RDATE and EXDATE values and not to
have bypass encoding with an icalendar property.
[thet]
- Allow setting of timezone for vDDDLists and support timezone properties for
RDATE and EXDATE component properties.
[thet]
- Move setting of TZID properties to vDDDTypes, where it belongs to.
[thet]
- Use @staticmethod decorator instead of wrapper function.
[warvariuc, thet]
- Extend quoting of parameter values to all of those characters: ",;: ’'".
This fixes an outlook incompatibility with some characters. Fixes: #79,
Fixes: #81.
[warvariuc]
- Define VTIMETZONE subcomponents STANDARD and DAYLIGHT for RFC5545 compliance.
[thet]
3.2 (2012-11-27)
----------------
- Documentation file layout restructuring.
[thet]
- Fix time support. vTime events can be instantiated with a datetime.time
object, and do not inherit from datetime.time itself.
[rdunklau]
- Correctly handle tzinfo objects parsed with dateutil. Fixes #77.
[warvariuc, thet]
- Text values are escaped correclty. Fixes #74.
[warvariuc]
- Returned old folding algorithm, as the current implementation fails in some
cases. Fixes #72, Fixes #73.
[warvariuc]
- Supports to_ical() on date/time properties for dates prior to 1900.
[cdevienne]
3.1 (2012-09-05)
----------------
- Make sure parameters to certain properties propagate to the ical output.
[kanarip]
- Re-include doctests.
[rnix]
- Ensure correct datatype at instance creation time in ``prop.vCalAddress``
and ``prop.vText``.
[rnix]
- Apply TZID parameter to datetimes parsed from RECURRENCE-ID
[dbstovall]
- Localize datetimes for timezones to avoid DST transition errors.
[dbstovall]
- Allow UTC-OFFSET property value data types in seconds, which follows RFC5545
specification.
[nikolaeff]
- Remove utctz and normalized_timezone methods to simplify the codebase. The
methods were too tiny to be useful and just used at one place.
[thet]
- When using Component.add() to add icalendar properties, force a value
conversion to UTC for CREATED, DTSTART and LAST-MODIFIED. The RFC expects UTC
for those properties.
[thet]
- Removed last occurrences of old API (from_string).
[Rembane]
- Add 'recursive' argument to property_items() to switch recursive listing.
For example when parsing a text/calendar text including multiple components
(e.g. a ``VCALENDAR`` with 5 ``VEVENT``s), the previous situation required us to look
over all properties in ``VEVENT``s even if we just want the properties under the
``VCALENDAR`` component (VERSION, PRODID, CALSCALE, METHOD).
[dmikurube]
- All unit tests fixed.
[mikaelfrykholm]
3.0.1b2 (2012-03-01)
--------------------
- For all TZID parameters in DATE-TIME properties, use timezone identifiers
(e.g. Europe/Vienna) instead of timezone names (e.g. CET), as required by
RFC5545. Timezone names are used together with timezone identifiers in the
Timezone components.
[thet]
- Timezone parsing, issues and test fixes.
[mikaelfrykholm, garbas, tgecho]
- Since we use pytz for timezones, also use UTC tzinfo object from the pytz
library instead of own implementation.
[thet]
3.0.1b1 (2012-02-24)
--------------------
- Update Release information.
[thet]
3.0
---
- Add API for proper Timezone support. Allow creating ical DATE-TIME strings
with timezone information from Python datetimes with pytz based timezone
information and vice versa.
[thet]
- Unify API to only use to_ical and from_ical and remove string casting as a
requirement for Python 3 compatibility:
New: to_ical.
Old: ical, string, as_string and string casting via __str__ and str.
New: from_ical.
Old: from_string.
[thet]
2.2 (2011-08-24)
----------------
- migration to https://github.com/collective/icalendar using svn2git preserving
tags, branches and authors.
[garbas]
- using tox for testing on python 2.4, 2.5, 2.6, 2.6.
[garbas]
- fixed tests so they pass also under python 2.7.
[garbas]
- running tests on ``https://jenkins.plone.org/job/icalendar`` (only 2.6 for now)
with some other metrics (pylint, clonedigger, coverage).
[garbas]
- review and merge changes from ``https://github.com/cozi/icalendar`` fork.
[garbas]
- created sphinx documentation and started documenting development and goals.
[garbas]
- hook out github repository to https://about.readthedocs.com service so sphinx
documentation is generated on each commit (for main). Documentation can be
visible on: https://icalendar.readthedocs.io/en/latest/
[garbas]
2.1 (2009-12-14)
----------------
- Fix deprecation warnings about ``object.__init__`` taking no parameters.
- Set the VALUE parameter correctly for date values.
- Long binary data would be base64 encoded with newlines, which made the
iCalendar files incorrect. (This still needs testing).
- Correctly handle content lines which include newlines.
2.0.1 (2008-07-11)
------------------
- Made the tests run under Python 2.5+
- Renamed the UTC class to Utc, so it would not clash with the UTC object,
since that rendered the UTC object unpicklable.
2.0 (2008-07-11)
----------------
- EXDATE and RDATE now returns a vDDDLists object, which contains a list
of vDDDTypes objects. This is do that EXDATE and RDATE can contain
lists of dates, as per RFC.
***Note!***: This change is incompatible with earlier behavior, so if you
handle EXDATE and RDATE you will need to update your code.
- When createing a vDuration of -5 hours (which in itself is nonsensical),
the ical output of that was -P1DT19H, which is correct, but ugly. Now
it's '-PT5H', which is prettier.
1.2 (2006-11-25)
----------------
- Fixed a string index out of range error in the new folding code.
1.1 (2006-11-23)
----------------
- Fixed a bug in caselessdicts popitem. (thanks to Michael Smith
)
- The RFC 2445 was a bit unclear on how to handle line folding when it
happened to be in the middle of a UTF-8 character. This has been clarified
in the following discussion:
`[Ietf-calsify] draft-ietf-calsify-rfc2445bis-01.txt / UTF-8 `_.
And this is now implemented in iCalendar. It will not fold in the middle of
a UTF-8 character, but may fold in the middle of a UTF-8 composing character
sequence.
1.0 (2006-08-03)
----------------
- make get_inline and set_inline support non ascii codes.
- Added support for creating a python egg distribution.
0.11 (2005-11-08)
-----------------
- Changed component .from_string to use types_factory instead of hardcoding
entries to 'inline'
- Changed UTC tzinfo to a singleton so the same one is used everywhere
- Made the parser more strict by using regular expressions for key name,
param name and quoted/unquoted safe char as per the RFC
- Added some tests from the schooltool icalendar parser for better coverage
- Be more forgiving on the regex for folding lines
- Allow for multiple top-level components on .from_string
- Fix vWeekdays, wasn't accepting relative param (eg: -3SA vs -SA)
- vDDDTypes didn't accept negative period (eg: -P30M)
- 'N' is also acceptable as newline on content lines, per RFC
0.10 (2005-04-28)
-----------------
- moved code to codespeak.net subversion.
- reorganized package structure so that source code is under 'src' directory.
Non-package files remain in distribution root.
- redid doc/.py files as doc/.txt, using more modern doctest. Before they
were .py files with big docstrings.
- added test.py testrunner, and tests/test_icalendar.py that picks up all
doctests in source code and doc directory, and runs them, when typing::
python2.3 test.py
- renamed iCalendar to lower case package name, lowercased, de-pluralized and
shorted module names, which are mostly implementation detail.
- changed tests so they generate .ics files in a temp directory, not in the
structure itself.
collective-icalendar-138c845/CODE_OF_CONDUCT.md 0000664 0000000 0000000 00000000357 15241340336 0020651 0 ustar 00root root 0000000 0000000 # Contributor Covenant 3.0 Code of Conduct
The icalendar project follows the Contributor Covenant 3.0 Code of Conduct, which is hosted on the Python Calendaring Ecosystem website at the following link.
https://pycal.org/code-of-conduct/
collective-icalendar-138c845/CONTRIBUTING.md 0000664 0000000 0000000 00000000253 15241340336 0020276 0 ustar 00root root 0000000 0000000 # Contributing
See our [contributing guide](https://icalendar.readthedocs.io/en/latest/contribute/index.html) for complete information on how to contribute to icalendar.
collective-icalendar-138c845/LICENSE.rst 0000664 0000000 0000000 00000002441 15241340336 0017662 0 ustar 00root root 0000000 0000000 =======
License
=======
Copyright (c) 2012-2013, Plone Foundation
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
- Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.
- Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
collective-icalendar-138c845/MANIFEST.in 0000664 0000000 0000000 00000000271 15241340336 0017603 0 ustar 00root root 0000000 0000000 include *.rst tox.ini
graft docs
recursive-include src/icalendar *
recursive-exclude src/icalendar *.pyc *~
recursive-exclude src/icalendar/fuzzing *.py *.sh *.ics
include funding.json
collective-icalendar-138c845/Makefile 0000664 0000000 0000000 00000013661 15241340336 0017514 0 ustar 00root root 0000000 0000000 # Makefile for Sphinx documentation
.DEFAULT_GOAL = help
SHELL = bash
# You can set these variables from the command line.
SPHINXOPTS ?=
PAPER ?=
VERSION ?=
# Internal variables.
RUFFPATH = "$(realpath .venv/bin/ruff)"
SPHINXAUTOBUILD = "$(realpath .venv/bin/sphinx-autobuild)"
SPHINXBUILD = "$(realpath .venv/bin/sphinx-build)"
TOWNCRIERPATH = "$(realpath .venv/bin/towncrier)"
DOCS_DIR = ./docs/
BUILDDIR = ../_build
PAPEROPT_a4 = -D latex_paper_size=a4
PAPEROPT_letter = -D latex_paper_size=letter
ALLSPHINXOPTS = -W -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) .
VALEFILES := $(shell find $(DOCS_DIR) -type f -name "*.rst" -print) # Also add `src` for docstrings.
VALEOPTS ?=
ZIZMOROPTS ?=
PYTHONVERSION = >=3.10,<3.15
# Add the following 'help' target to your Makefile
# And add help text after each target name starting with '\#\#'
.PHONY: help
help: # This help message
@grep -E '^[a-zA-Z_-]+:.*?## .*$$' $(MAKEFILE_LIST) | sort | awk 'BEGIN {FS = ":.*?## "}; {printf "\033[36m%-30s\033[0m %s\n", $$1, $$2}'
# environment management
.venv: ## Install required Python, create Python virtual environment, and install package requirements
@uv python install "$(PYTHONVERSION)"
@uv venv --python "$(PYTHONVERSION)"
@uv sync --group dev
@uv run pre-commit install
.PHONY: sync
sync: ## Sync package requirements
@uv sync
.PHONY: init
init: clean clean-python .venv ## Clean docs build directory, Python virtual environment, and initialize Python virtual environment
.PHONY: clean
clean: ## Clean docs build directory
cd $(DOCS_DIR) && rm -rf $(BUILDDIR)/
.PHONY: clean-python
clean-python: clean
rm -rf .venv/
# /environment management
# documentation builders
.PHONY: html
html: .venv ## Build html
cd $(DOCS_DIR) && $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
.PHONY: livehtml
livehtml: .venv ## Rebuild Sphinx documentation on changes, with live-reload in the browser
cd "$(DOCS_DIR)" && ${SPHINXAUTOBUILD} \
--watch "../src/icalendar/" \
--watch "../CHANGES.rst" \
--re-ignore ".*\\.swp|.*\\.typed" \
--ignore "../src/icalendar/tests" \
--ignore "../src/icalendar/fuzzing" \
--port 8050 \
-b html . "$(BUILDDIR)/html" $(SPHINXOPTS) $(O)
.PHONY: dirhtml
dirhtml: .venv
cd $(DOCS_DIR) && $(SPHINXBUILD) -b dirhtml $(ALLSPHINXOPTS) $(BUILDDIR)/dirhtml
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/dirhtml."
.PHONY: singlehtml
singlehtml: .venv
cd $(DOCS_DIR) && $(SPHINXBUILD) -b singlehtml $(ALLSPHINXOPTS) $(BUILDDIR)/singlehtml
@echo
@echo "Build finished. The HTML page is in $(BUILDDIR)/singlehtml."
.PHONY: text
text: .venv
cd $(DOCS_DIR) && $(SPHINXBUILD) -b text $(ALLSPHINXOPTS) $(BUILDDIR)/text
@echo
@echo "Build finished. The text files are in $(BUILDDIR)/text."
.PHONY: sphinx-changes
sphinx-changes: .venv
cd $(DOCS_DIR) && $(SPHINXBUILD) -b changes $(ALLSPHINXOPTS) $(BUILDDIR)/changes
@echo
@echo "The overview file is in $(BUILDDIR)/changes."
# /documentation builders
# test
.PHONY: linkcheck
linkcheck: .venv ## Run linkcheck
cd $(DOCS_DIR) && $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/ ."
.PHONY: linkcheckbroken
linkcheckbroken: .venv ## Run linkcheck and show only broken links
cd $(DOCS_DIR) && $(SPHINXBUILD) -b linkcheck $(ALLSPHINXOPTS) $(BUILDDIR)/linkcheck | GREP_COLORS='0;31' grep -wi "[^.]broken\|redirect" --color=always && if test $$? = 0; then exit 1; fi || test $$? = 1
@echo
@echo "Link check complete; look for any errors in the above output " \
"or in $(BUILDDIR)/linkcheck/ ."
.PHONY: vale
vale: .venv ## Run Vale style, grammar, and spell checks
@uv run vale sync
@uv run vale --no-wrap $(VALEOPTS) $(VALEFILES); \
if [ $$? = 0 ]; then \
echo; \
echo "Vale passed!"; \
else \
echo; \
echo "Vale spell, style, and grammar check failed."; \
echo "Read the error messages above to see what didn't pass."; \
echo "For guidance of how to correct the errors, see:"; \
echo "https://icalendar.readthedocs.io/en/latest/contribute/documentation/build-check.html#spelling-grammar-and-style"; \
exit 1; \
fi
.PHONY: zizmor
zizmor: .venv ## Run zizmor static analysis on GitHub Actions workflows
@uv run zizmor $(ZIZMOROPTS) .github/workflows/
.PHONY: doctest
doctest: .venv ## Test snippets and docstrings in the documentation
@echo;
@pytest src/icalendar/tests/test_with_doctest.py
.PHONY: docs-all
docs-all: .venv clean vale doctest html linkcheckbroken ## Clean docs build, then run vale, doctest, html, and linkcheckbroken
.PHONY: test
test: .venv ## Run code tests and coverage
@uv run tox
# /test
# development
.PHONY: dev
dev: .venv ## Install required Python, create Python virtual environment, install package and development requirements
.PHONY: format
format: .venv ## Format the code base with ruff
$(RUFFPATH) format
$(RUFFPATH) check --fix
# /development
# deployment
.PHONY: rtd-prepare
rtd-prepare: ## Prepare environment on Read the Docs
asdf plugin add uv
asdf install uv latest
asdf global uv latest
.PHONY: rtd-pr-preview
rtd-pr-preview: rtd-prepare .venv ## Build pull request preview on Read the Docs
cd $(DOCS_DIR) && $(SPHINXBUILD) -b html $(ALLSPHINXOPTS) ${READTHEDOCS_OUTPUT}/html/
# /deployment
# release
.PHONY: wo
wo: .venv
@uv run generate_windows_to_olson_mapping.py
$(RUFFPATH) format
.PHONY: changes-check
changes-check: dev
$(TOWNCRIERPATH) check
.PHONY: changes-draft
changes-draft: dev
@test -n "$(VERSION)" || (echo "VERSION is not set. Run 'export VERSION=x.y.z' first." && exit 1)
$(TOWNCRIERPATH) build --draft --version ${VERSION} --yes
.PHONY: changes
changes: dev
@test -n "$(VERSION)" || (echo "VERSION is not set. Run 'export VERSION=x.y.z' first." && exit 1)
$(TOWNCRIERPATH) build --version ${VERSION} --yes
# /release
collective-icalendar-138c845/README.rst 0000664 0000000 0000000 00000012347 15241340336 0017543 0 ustar 00root root 0000000 0000000 ==========================================================
Internet Calendaring and Scheduling (iCalendar) for Python
==========================================================
The `icalendar `_ package is an :rfc:`5545` compatible parser and generator of iCalendar files.
icalendar can create, inspect, and modify calendaring information with Python.
icalendar supports multiple timezone implementations, including `zoneinfo `_, `dateutil.tz `_, and `pytz `_.
----
:Homepage: https://icalendar.readthedocs.io/en/stable/
:Community Discussions: https://github.com/collective/icalendar/discussions
:Issue Tracker: https://github.com/collective/icalendar/issues
:Code: https://github.com/collective/icalendar
:Dependencies: `python-dateutil `_ and `tzdata `_.
:License: `2-Clause BSD License `_
:Contribute: `Contribute to icalendar `_
:Funding: `Open Collective `_
----
.. image:: https://img.shields.io/pypi/v/icalendar
:target: https://pypi.org/project/icalendar/
:alt: Python package version on PyPI
.. image:: https://img.shields.io/github/v/release/collective/icalendar
:target: https://pypi.org/project/icalendar/#history
:alt: Latest release
.. image:: https://img.shields.io/pypi/pyversions/icalendar
:target: https://pypi.org/project/icalendar/
:alt: Supported Python versions
.. image:: https://static.pepy.tech/personalized-badge/icalendar?period=total&units=INTERNATIONAL_SYSTEM&left_color=GREY&right_color=GREEN&left_text=downloads
:target: https://pypistats.org/packages/icalendar
:alt: Downloads from PyPI
.. image:: https://img.shields.io/github/actions/workflow/status/collective/icalendar/tests.yml?branch=main&label=main&logo=github
:target: https://github.com/collective/icalendar/actions/workflows/tests.yml?query=branch%3Amain
:alt: GitHub Actions build status for main
.. image:: https://readthedocs.org/projects/icalendar/badge/?version=latest
:target: https://icalendar.readthedocs.io/en/latest/
:alt: Documentation status
.. image:: https://coveralls.io/repos/github/collective/icalendar/badge.svg?branch=main
:target: https://coveralls.io/github/collective/icalendar?branch=main
:alt: Test coverage
.. image:: https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json
:target: https://github.com/astral-sh/ruff
:alt: Ruff
.. image:: https://img.shields.io/badge/%F0%9F%A4%91-Funding-brightgreen
:target: https://opencollective.com/python-icalendar
:alt: Funding
Install icalendar
=================
See how to `install icalendar `_.
Usage
=====
For how to use icalendar, including how to read, modify, and write iCalendar files, see the `Usage `_ guide.
Related projects
================
`VObject `_
VObject is intended to be a full-featured Python package for parsing and generating Card and Calendar files.
`iCalEvents `_
iCalEvents is built on top of icalendar, and allows you to query iCalendar files to get the events happening on specific dates.
It manages recurrent events as well.
`recurring-ical-events `_
Library to query an ``icalendar.Calendar`` object for events and other components happening at a certain date or within a certain time.
`x-wr-timezone `_
Library and command line tool to make ``icalendar.Calendar`` objects and files from Google Calendar, using the non-standard ``X-WR-TIMEZONE`` property, compliant with the :rfc:`5545` standard.
`ics-query `_
Command line tool to query iCalendar files for occurrences of events and other components.
`icalendar-compatibility `_
Access event data compatible with :rfc:`5545` and different implementations.
`caldav `_
CalDAV is a :rfc:`4791` client library for Python based on icalendar.
`icalendar-anonymizer `_
Anonymize iCalendar files by stripping personal data while preserving technical properties for bug reproduction.
`ical2jcal `_
Convert between iCalendar and jCalendar.
`sphinx-icalendar `_
Provides calendar code blocks and syntax highlighting in a tabbed interface for documentation as an extension to Sphinx.
`Python Calendaring Ecosystem `_
The standards compliant, integrated Python calendar packages.
Change log
==========
See the `change log `_ for the latest updates to icalendar.
collective-icalendar-138c845/SECURITY.md 0000664 0000000 0000000 00000006337 15241340336 0017647 0 ustar 00root root 0000000 0000000 # Security policy
This security policy describes how to privately report _potential_ security issues with icalendar, and how the icalendar security team processes reports, all in a responsible manner.
If you're unsure whether your issue qualifies as a security vulnerability, it's better to err on the side of caution and report it as one, allowing the icalendar security team to evaluate its merits and determine whether it's one.
- [Report a _potential_ security issue](https://github.com/collective/icalendar/security/advisories/new).
- [Security advisories](https://github.com/collective/icalendar/security/advisories)
## Supported versions
Security vulnerabilities are fixed only for the latest version of icalendar.
It is highly recommended to upgrade to the latest release.
## Procedure
The icalendar security team will coordinate with the [Plone security team](https://plone.org/security/report).
If it's determined that your report may be a security vulnerability with the project, the team may contact you for further information.
As volunteers, the team asks that you delay public disclosure of your report for at least ninety (90) days from the date you report it to the team.
This will allow sufficient time for the team to process your report and coordinate disclosure with you.
Once verified and fixed, the following steps will be taken:
- The team will use GitHub's Security Advisory tool to report the vulnerability.
- GitHub will review the Security Advisory report for compliance with Common Vulnerabilities and Exposures (CVE) rules.
If it is compliant, they will submit it to the MITRE Corporation to generate a [CVE](https://www.cve.org/).
This in turn submits the CVE to the [National Vulnerability Database (NVD)](https://nvd.nist.gov/vuln/search).
GitHub notifies the team of their decision.
- Assuming it is compliant, the team then publishes the [Security Advisory](https://github.com/collective/icalendar/security/advisories) on GitHub, which triggers the next steps.
- GitHub will publish the CVE to the CVE List.
- GitHub will broadcast the Security Advisory via the [GitHub Advisory Database](https://github.com/advisories).
- GitHub will send [security alerts](https://docs.github.com/en/code-security/supply-chain-security/managing-vulnerabilities-in-your-projects-dependencies/about-alerts-for-vulnerable-dependencies) to all repositories that use icalendar and have opted into security alerts.
This includes Dependabot alerts.
- The team will make a bug-fix release.
- The team will send an announcement through the usual channels:
- the [change log](https://github.com/collective/icalendar/CHANGES.rst)
- the [GitHub releases of icalendar](https://github.com/collective/icalendar/releases)
- [icalendar Discussions Announcements](https://github.com/collective/icalendar/discussions/categories/announcements)
- [icalendar Open Collective conversations](https://opencollective.com/python-icalendar/conversations)
- [Plone's Security Announcements](https://plone.org/security/announcements)
- [Plone Community Forum Announcements](https://community.plone.org/c/announcements/27)
- The icalendar security team will provide credit to the reporter or researcher in the vulnerability notice.
collective-icalendar-138c845/docs/ 0000775 0000000 0000000 00000000000 15241340336 0016775 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/docs/_include/ 0000775 0000000 0000000 00000000000 15241340336 0020557 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/docs/_include/configure-git-card-dev.inc 0000664 0000000 0000000 00000000365 15241340336 0025503 0 ustar 00root root 0000000 0000000 .. card::
.. image:: ../_static/contributing/development-icalendar-git-workflow.svg
:alt: icalendar git workflow
:target: ../_static/contributing/development-icalendar-git-workflow.svg
+++
*icalendar git workflow*
collective-icalendar-138c845/docs/_include/configure-git-card-doc.inc 0000664 0000000 0000000 00000000373 15241340336 0025471 0 ustar 00root root 0000000 0000000 .. card::
.. image:: ../../_static/contributing/development-icalendar-git-workflow.svg
:alt: icalendar git workflow
:target: ../../_static/contributing/development-icalendar-git-workflow.svg
+++
*icalendar git workflow*
collective-icalendar-138c845/docs/_include/configure-git-steps.inc 0000664 0000000 0000000 00000001360 15241340336 0025150 0 ustar 00root root 0000000 0000000 #. Start by `forking icalendar's repository `_ to your account through the GitHub interface.
.. seealso::
`Fork a repository `_
#. `Clone your forked repository `_.
#. `Configure Git to sync your fork with the upstream repository `_.
.. seealso::
:ref:`branch-policy`
collective-icalendar-138c845/docs/_include/configure-git.inc 0000664 0000000 0000000 00000000757 15241340336 0024025 0 ustar 00root root 0000000 0000000 Configure Git
-------------
Unless you're a maintainer or administrator, you don't have write access to push commits to GitHub repositories under the Collective organization or the icalendar repository.
You can, however, push commits to your fork.
Thus, a typical workflow will be circular in nature.
You'll pull code from the upstream icalendar repository, push your work from your local clone to your remote fork, then make a pull request from your fork to the upstream icalendar repository.
collective-icalendar-138c845/docs/_include/maintainers.inc 0000664 0000000 0000000 00000000306 15241340336 0023563 0 ustar 00root root 0000000 0000000 - `@geier `_
- `@jacadzaca `_
- `@niccokunzmann `_
- `@SashankBhamidi `_
collective-icalendar-138c845/docs/_include/prerequisites.inc 0000664 0000000 0000000 00000003637 15241340336 0024167 0 ustar 00root root 0000000 0000000 Prerequisites
-------------
You'll need to first install prerequisites on, and clone the icalendar repository to, your local computer.
Tests, code formatting, and documentation builds and checks require that you install :program:`GNU Make`, :program:`uv`, and :program:`Git`.
.. note::
:program:`uv` handles the installation of Python and all dependencies for icalendar.
:program:`Make`
'''''''''''''''
:program:`Make` is used to provide an interface to developers to perform repetitive tasks with a single command.
:program:`Make` comes installed on most Linux distributions.
On macOS, you must first `install Xcode `_, then install its command line tools.
On Windows, it is strongly recommended to `Install Linux on Windows with WSL `_, which will include :program:`Make`.
Finally, it is a good idea to update your system's version of :program:`Make`, because some distributions, especially macOS, have an outdated version.
Use your favorite search engine or trusted online resource for how to update :program:`Make`.
uv
''
`uv `_ is used for installing Python, creating a Python virtual environment, and managing dependencies for documentation.
Install :program:`uv`.
Read the console output for further instructions, and follow them, if needed.
.. tab-set::
.. tab-item:: macOS, Linux, and Windows with WSL
.. code-block:: shell
curl -LsSf https://astral.sh/uv/install.sh | sh
.. tab-item:: Windows
.. code-block:: shell
powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
.. tab-item:: Other
`Other uv installation methods `_
Git
'''
Install `Git `_ for your operating system.
collective-icalendar-138c845/docs/_static/ 0000775 0000000 0000000 00000000000 15241340336 0020423 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/docs/_static/contributing/ 0000775 0000000 0000000 00000000000 15241340336 0023132 5 ustar 00root root 0000000 0000000 collective-icalendar-138c845/docs/_static/contributing/development-disable-pre-commit.png 0000664 0000000 0000000 00000160152 15241340336 0031642 0 ustar 00root root 0000000 0000000 ‰PNG
IHDR ľ Ó 1cŢ1 YiCCPICC Profile (‘c``bI,(Čaa``ČÍ+)
rwR��ŚR`ĹŔČ É Ä Ć ™�\\ŕŕT ŁQÁ·k@Ő@pYdÖ¬wâ«T¸ż;ě¨űţĽěâzLő(€+%µ8H˙b䂢F
; Ľ¤ Ä® ˛EЀޞ{@ět{�ťao« r˛O Ůɉ)@ö
[' I<‰ť›SšuČő<©yˇÁ@š�eśL,‚Ü�$Đ8Ôš@Őć30T21d2¤3d0”0(08E
rR�lO†<†d= Ű�Á �Í@aŚv±_«9@«ĽbÁŠŰŠubĘ@ç~b`8° ±(˘ŚßXŠÓŚŤ l Ö˙˙–e``ßĹŔđ·č˙˙ßs˙˙˙»„��ů&Po! ~ßbvľbĘ beXIfMM * ‡i &