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

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 18 additions & 0 deletions .github/workflows/linkcheck.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
name: Link check

on: [push, pull_request]

jobs:
linkcheck:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Check links with Lychee
uses: lycheeverse/lychee-action@v2
with:
fail: true
args: >-
--timeout 10
--max-retries 2
'**/*.md'
'**/*.rst'
51 changes: 49 additions & 2 deletions .github/workflows/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python: ${{ github.event_name == 'pull_request' && fromJSON('["3.9", "3.14"]') || fromJSON('["3.9", "3.10", "3.11", "3.12", "3.13", "3.14"]') }}
python: ${{ github.event_name == 'pull_request' && fromJSON('["3.10", "3.14"]') || fromJSON('["3.10", "3.11", "3.12", "3.13", "3.14"]') }}
services:
baikal:
image: ckulka/baikal:nginx
Expand Down Expand Up @@ -144,7 +144,7 @@ jobs:
docker exec ${{ job.services.nextcloud.id }} php occ app:disable password_policy || true

# Create test user
docker exec -e OC_PASS="TestPassword123!" ${{ job.services.nextcloud.id }} php occ user:add --password-from-env --display-name="Test User" testuser || echo "User may already exist"
docker exec -e OC_PASS="testpass" ${{ job.services.nextcloud.id }} php occ user:add --password-from-env --display-name="Test User" testuser || echo "User may already exist"

# Enable calendar and contacts apps
docker exec ${{ job.services.nextcloud.id }} php occ app:enable calendar || true
Expand Down Expand Up @@ -326,3 +326,50 @@ jobs:
key: pip|${{ hashFiles('setup.py') }}|${{ hashFiles('tox.ini') }}
- run: pip install tox
- run: tox -e deptry
async-niquests:
# Test that async code works with niquests when httpx is not installed
name: async (niquests fallback)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies without httpx
run: |
pip install --editable .[test]
pip uninstall -y httpx
- name: Verify niquests is used
run: |
python -c "
from caldav.async_davclient import _USE_HTTPX, _USE_NIQUESTS
assert not _USE_HTTPX, 'httpx should not be available'
assert _USE_NIQUESTS, 'niquests should be used'
print('✓ Using niquests for async HTTP')
"
- name: Run async tests with niquests
run: pytest tests/test_async_davclient.py -v
sync-requests:
# Test that sync code works with requests when niquests is not installed
name: sync (requests fallback)
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-python@v5
with:
python-version: "3.12"
- name: Install dependencies with requests instead of niquests
run: |
pip install --editable .[test]
pip uninstall -y niquests
pip install requests
- name: Verify requests is used
run: |
python -c "
from caldav.davclient import _USE_REQUESTS, _USE_NIQUESTS
assert _USE_REQUESTS, 'requests should be available'
assert not _USE_NIQUESTS, 'niquests should not be available'
print('✓ Using requests for sync HTTP')
"
- name: Run sync tests with requests
run: pytest tests/test_caldav.py -v -k "Radicale" --ignore=tests/test_async_integration.py
20 changes: 20 additions & 0 deletions .lycheeignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
# Example domains that don't resolve
https?://your\.server\.example\.com/.*
https?://.*\.example\.com/.*

# Localhost URLs for test servers (not accessible in CI)
http://localhost:\d+/.*

# CalDAV endpoints that require authentication (401/403 expected)
https://caldav\.fastmail\.com/.*
https://caldav\.gmx\.net/.*
https://caldav\.icloud\.com/.*
https://p\d+-caldav\.icloud\.com/.*
https://posteo\.de:\d+/.*
https://purelymail\.com/.*
https://webmail\.all-inkl\.com/.*
https://www\.google\.com/calendar/dav/.*
https://caldav-jp\.larksuite\.com/.*

# Apple namespace URL (returns 404 but is a valid XML namespace reference)
http://apple\.com/ns/ical/
23 changes: 15 additions & 8 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,16 +1,23 @@
---
repos:
- repo: https://github.com/asottile/reorder_python_imports
rev: v3.12.0
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.9.4
hooks:
- id: reorder-python-imports
- repo: https://github.com/psf/black
rev: 23.12.0
hooks:
- id: black
- id: ruff
args: [--fix]
- id: ruff-format

- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.5.0
rev: v5.0.0
hooks:
- id: check-byte-order-marker
- id: trailing-whitespace
- id: end-of-file-fixer

- repo: https://github.com/lycheeverse/lychee
rev: lychee-v0.22.0
hooks:
- id: lychee
args: ["--no-progress", "--timeout", "10"]
types: [markdown, rst]
stages: [manual] # Run with: pre-commit run lychee --hook-stage manual
9 changes: 4 additions & 5 deletions AI_POLICY.md → AI-POLICY.md
Original file line number Diff line number Diff line change
Expand Up @@ -63,11 +63,10 @@ experiences is that the AI performs best when being "supervised" and
<[email protected]>` when it's doing commits, that's also OK.

* **YOU** should be ready to follow up and respond to feedback and
questions on the contribution. If all you do is to relay it to the
AI and relaying the AI output back to the pull request, then
you're not adding value to the project and you're not transparent
and honest. You should at least do a quick QA on the AI-answer and
acknowledge that it was generated by the AI.
questions on the contribution. If you're letting the AI do this for
you, then you're neither honest nor adding value to the project.
You should at least do a quick QA on the AI-answer and acknowledge
that it was generated by the AI.

* The Contributors Guidelines aren't strongly enforced on this project
as of 2025-12, and I can hardly see cases where the AI would break
Expand Down
Loading