Add caldav third-party stubs (#5684)

Co-authored-by: Jelle Zijlstra <jelle.zijlstra@gmail.com>
This commit is contained in:
Sebastian Rittau
2021-06-30 16:28:40 +02:00
committed by GitHub
parent 40b127d46a
commit 2b35ea5f91
17 changed files with 525 additions and 11 deletions

22
.gitignore vendored
View File

@@ -7,17 +7,17 @@ __pycache__/
# Distribution / packaging
.Python
env/
build/
develop-eggs/
dist/
downloads/
eggs/
lib/
lib64/
parts/
sdist/
var/
/env/
/build/
/develop-eggs/
/dist/
/downloads/
/eggs/
/lib/
/lib64/
/parts/
/sdist/
/var/
*.egg-info/
.installed.cfg
*.egg

View File

@@ -27,6 +27,7 @@
"stubs/backports_abc",
"stubs/bleach",
"stubs/boto",
"stubs/caldav",
"stubs/commonmark",
"stubs/cryptography",
"stubs/docutils",

View File

@@ -0,0 +1,13 @@
# **kwargs replaced with actual arguments in stubs
caldav.DAVClient.calendar
caldav.DAVClient.principal
caldav.davclient.DAVClient.calendar
caldav.davclient.DAVClient.principal
# Initialized in class, but immediatly overwritten in __init__
caldav.DAVClient.url
caldav.davclient.DAVClient.url
caldav.davclient.DAVResponse.headers
caldav.elements.base.BaseElement.children
.*.findprop

View File

@@ -0,0 +1,3 @@
version = "0.8"
# also types-lxml, types-vobject, and types-icalendar when those stubs are added
requires = ["types-requests"]

View File

@@ -0,0 +1,2 @@
from .davclient import DAVClient as DAVClient
from .objects import *

View File

@@ -0,0 +1,70 @@
from collections.abc import Iterable, Mapping
from typing import Any
from urllib.parse import ParseResult, SplitResult
from requests.auth import AuthBase
from requests.models import Response
from requests.structures import CaseInsensitiveDict
from .lib.url import URL
from .objects import Calendar, DAVObject, Principal
_Element = Any # actually lxml.etree._Element
class DAVResponse:
reason: str
tree: _Element | None
status: int
headers: CaseInsensitiveDict[str]
objects: dict[str, dict[str, str]] # only defined after call to find_objects_and_props()
def __init__(self, response: Response) -> None: ...
@property
def raw(self) -> str: ...
def validate_status(self, status: str) -> None: ...
def find_objects_and_props(self) -> None: ...
def expand_simple_props(
self, props: Iterable[Any] = ..., multi_value_props: Iterable[Any] = ..., xpath: str | None = ...
) -> dict[str, dict[str, str]]: ...
class DAVClient:
proxy: str | None
url: URL
headers: dict[str, str]
username: str | None
password: str | None
auth: AuthBase | None
ssl_verify_cert: bool | str
ssl_cert: str | tuple[str, str] | None
def __init__(
self,
url: str,
proxy: str | None = ...,
username: str | None = ...,
password: str | None = ...,
auth: AuthBase | None = ...,
ssl_verify_cert: bool | str = ...,
ssl_cert: str | tuple[str, str] | None = ...,
) -> None: ...
def principal(self, *, url: str | ParseResult | SplitResult | URL | None = ...) -> Principal: ...
def calendar(
self,
url: str | ParseResult | SplitResult | URL | None = ...,
parent: DAVObject | None = ...,
name: str | None = ...,
id: str | None = ...,
props: Mapping[Any, Any] = ...,
**extra: Any,
) -> Calendar: ...
def check_dav_support(self) -> str | None: ...
def check_cdav_support(self) -> bool: ...
def check_scheduling_support(self) -> bool: ...
def propfind(self, url: str | None = ..., props: str = ..., depth: int = ...) -> DAVResponse: ...
def proppatch(self, url: str, body: str, dummy: None = ...) -> DAVResponse: ...
def report(self, url: str, query: str = ..., depth: int = ...) -> DAVResponse: ...
def mkcol(self, url: str, body: str, dummy: None = ...) -> DAVResponse: ...
def mkcalendar(self, url: str, body: str = ..., dummy: None = ...) -> DAVResponse: ...
def put(self, url: str, body: str, headers: Mapping[str, str] = ...) -> DAVResponse: ...
def post(self, url: str, body: str, headers: Mapping[str, str] = ...) -> DAVResponse: ...
def delete(self, url: str) -> DAVResponse: ...
def options(self, url: str) -> DAVResponse: ...
def request(self, url: str, method: str = ..., body: str = ..., headers: Mapping[str, str] = ...) -> DAVResponse: ...

View File

@@ -0,0 +1,23 @@
from _typeshed import Self
from collections.abc import Iterable
from typing import Any, ClassVar
_Element = Any # actually lxml.etree._Element
class BaseElement:
tag: ClassVar[str | None]
children: list[BaseElement]
value: str | None
attributes: Any | None
caldav_class: Any | None
def __init__(self, name: str | None = ..., value: str | bytes | None = ...) -> None: ...
def __add__(self: Self, other: BaseElement) -> Self: ...
def xmlelement(self) -> _Element: ...
def xmlchildren(self, root: _Element) -> None: ...
def append(self: Self, element: BaseElement | Iterable[BaseElement]) -> Self: ...
class NamedBaseElement(BaseElement):
def __init__(self, name: str | None = ...) -> None: ...
class ValuedBaseElement(BaseElement):
def __init__(self, value: str | bytes | None = ...) -> None: ...

View File

@@ -0,0 +1,100 @@
import datetime
from typing import ClassVar
from .base import BaseElement, NamedBaseElement, ValuedBaseElement
class CalendarQuery(BaseElement):
tag: ClassVar[str]
class FreeBusyQuery(BaseElement):
tag: ClassVar[str]
class Mkcalendar(BaseElement):
tag: ClassVar[str]
class CalendarMultiGet(BaseElement):
tag: ClassVar[str]
class ScheduleInboxURL(BaseElement):
tag: ClassVar[str]
class ScheduleOutboxURL(BaseElement):
tag: ClassVar[str]
class Filter(BaseElement):
tag: ClassVar[str]
class CompFilter(NamedBaseElement):
tag: ClassVar[str]
class PropFilter(NamedBaseElement):
tag: ClassVar[str]
class ParamFilter(NamedBaseElement):
tag: ClassVar[str]
class TextMatch(ValuedBaseElement):
tag: ClassVar[str]
def __init__(self, value, collation: str = ..., negate: bool = ...) -> None: ...
class TimeRange(BaseElement):
tag: ClassVar[str]
def __init__(self, start: datetime.datetime | None = ..., end: datetime.datetime | None = ...) -> None: ...
class NotDefined(BaseElement):
tag: ClassVar[str]
class CalendarData(BaseElement):
tag: ClassVar[str]
class Expand(BaseElement):
tag: ClassVar[str]
def __init__(self, start: datetime.datetime | None, end: datetime.datetime | None = ...) -> None: ...
class Comp(NamedBaseElement):
tag: ClassVar[str]
class CalendarUserAddressSet(BaseElement):
tag: ClassVar[str]
class CalendarUserType(BaseElement):
tag: ClassVar[str]
class CalendarHomeSet(BaseElement):
tag: ClassVar[str]
class Calendar(BaseElement):
tag: ClassVar[str]
class CalendarDescription(ValuedBaseElement):
tag: ClassVar[str]
class CalendarTimeZone(ValuedBaseElement):
tag: ClassVar[str]
class SupportedCalendarComponentSet(ValuedBaseElement):
tag: ClassVar[str]
class SupportedCalendarData(ValuedBaseElement):
tag: ClassVar[str]
class MaxResourceSize(ValuedBaseElement):
tag: ClassVar[str]
class MinDateTime(ValuedBaseElement):
tag: ClassVar[str]
class MaxDateTime(ValuedBaseElement):
tag: ClassVar[str]
class MaxInstances(ValuedBaseElement):
tag: ClassVar[str]
class MaxAttendeesPerInstance(ValuedBaseElement):
tag: ClassVar[str]
class Allprop(BaseElement):
tag: ClassVar[str]
class ScheduleTag(BaseElement):
tag: ClassVar[str]

View File

@@ -0,0 +1,63 @@
from typing import ClassVar
from .base import BaseElement, ValuedBaseElement
class Propfind(BaseElement):
tag: ClassVar[str]
class PropertyUpdate(BaseElement):
tag: ClassVar[str]
class Mkcol(BaseElement):
tag: ClassVar[str]
class SyncCollection(BaseElement):
tag: ClassVar[str]
class SyncToken(BaseElement):
tag: ClassVar[str]
class SyncLevel(BaseElement):
tag: ClassVar[str]
class Prop(BaseElement):
tag: ClassVar[str]
class Collection(BaseElement):
tag: ClassVar[str]
class Set(BaseElement):
tag: ClassVar[str]
class ResourceType(BaseElement):
tag: ClassVar[str]
class DisplayName(ValuedBaseElement):
tag: ClassVar[str]
class GetEtag(ValuedBaseElement):
tag: ClassVar[str]
class Href(BaseElement):
tag: ClassVar[str]
class Response(BaseElement):
tag: ClassVar[str]
class Status(BaseElement):
tag: ClassVar[str]
class PropStat(BaseElement):
tag: ClassVar[str]
class MultiStatus(BaseElement):
tag: ClassVar[str]
class CurrentUserPrincipal(BaseElement):
tag: ClassVar[str]
class PrincipalCollectionSet(BaseElement):
tag: ClassVar[str]
class Allprop(BaseElement):
tag: ClassVar[str]

View File

@@ -0,0 +1,9 @@
from typing import ClassVar
from .base import ValuedBaseElement
class CalendarColor(ValuedBaseElement):
tag: ClassVar[str]
class CalendarOrder(ValuedBaseElement):
tag: ClassVar[str]

View File

View File

@@ -0,0 +1,24 @@
from typing import Any, Type
def assert_(condition: object) -> None: ...
ERR_FRAGMENT: str
class AuthorizationError(Exception):
url: Any
reason: str
class DAVError(Exception): ...
class PropsetError(DAVError): ...
class ProppatchError(DAVError): ...
class PropfindError(DAVError): ...
class ReportError(DAVError): ...
class MkcolError(DAVError): ...
class MkcalendarError(DAVError): ...
class PutError(DAVError): ...
class DeleteError(DAVError): ...
class NotFoundError(DAVError): ...
class ConsistencyError(DAVError): ...
class ReponseError(DAVError): ...
exception_by_method: dict[str, Type[DAVError]]

View File

@@ -0,0 +1,4 @@
nsmap: dict[str, str]
nsmap2: dict[str, str]
def ns(prefix: str, tag: str | None = ...) -> str: ...

View File

@@ -0,0 +1,27 @@
from typing import overload
from urllib.parse import ParseResult, SplitResult
class URL:
def __init__(self, url: str | ParseResult | SplitResult) -> None: ...
def __bool__(self) -> bool: ...
def __ne__(self, other: object) -> bool: ...
def __eq__(self, other: object) -> bool: ...
def __hash__(self) -> int: ...
@overload
@classmethod
def objectify(cls, url: None) -> None: ...
@overload
@classmethod
def objectify(cls, url: URL | str | ParseResult | SplitResult) -> URL: ...
def __getattr__(self, attr: str): ...
def __unicode__(self) -> str: ...
def strip_trailing_slash(self) -> URL: ...
def is_auth(self) -> bool: ...
def unauth(self) -> URL: ...
def canonical(self) -> URL: ...
def join(self, path: object) -> URL: ...
@overload
def make(url: None) -> None: ...
@overload
def make(url: URL | str | ParseResult | SplitResult) -> URL: ...

View File

@@ -0,0 +1 @@
def fix(event): ...

View File

@@ -0,0 +1,174 @@
import datetime
from _typeshed import Self
from collections.abc import Iterable, Iterator, Mapping
from typing import Any, Type, TypeVar, overload
from typing_extensions import Literal
from urllib.parse import ParseResult, SplitResult
from .davclient import DAVClient
from .elements.cdav import CompFilter, ScheduleInboxURL, ScheduleOutboxURL
from .lib.url import URL
_CC = TypeVar("_CC", bound=CalendarObjectResource)
_VBase = Any # actually vobject.base.VBase
_vCalAddress = Any # actually icalendar.vCalAddress
class DAVObject:
id: str | None
url: URL | None
client: DAVClient | None
parent: DAVObject | None
name: str | None
props: Mapping[Any, Any]
extra_init_options: dict[str, Any]
def __init__(
self,
client: DAVClient | None = ...,
url: str | ParseResult | SplitResult | URL | None = ...,
parent: DAVObject | None = ...,
name: str | None = ...,
id: str | None = ...,
props: Mapping[Any, Any] | None = ...,
**extra: Any,
) -> None: ...
@property
def canonical_url(self) -> str: ...
def children(self, type: str | None = ...) -> list[tuple[URL, Any, Any]]: ...
def get_property(self, prop, use_cached: bool = ..., **passthrough) -> Any | None: ...
def get_properties(
self, props: Any | None = ..., depth: int = ..., parse_response_xml: bool = ..., parse_props: bool = ...
): ...
def set_properties(self: Self, props: Any | None = ...) -> Self: ...
def save(self: Self) -> Self: ...
def delete(self) -> None: ...
class CalendarSet(DAVObject):
def calendars(self) -> list[Calendar]: ...
def make_calendar(
self, name: str | None = ..., cal_id: str | None = ..., supported_calendar_component_set: Any | None = ...
) -> Calendar: ...
def calendar(self, name: str | None = ..., cal_id: str | None = ...) -> Calendar: ...
class Principal(DAVObject):
def __init__(self, client: DAVClient | None = ..., url: str | ParseResult | SplitResult | URL | None = ...) -> None: ...
def calendars(self) -> list[Calendar]: ...
def make_calendar(
self, name: str | None = ..., cal_id: str | None = ..., supported_calendar_component_set: Any | None = ...
) -> Calendar: ...
def calendar(self, name: str | None = ..., cal_id: str | None = ...) -> Calendar: ...
def get_vcal_address(self) -> _vCalAddress: ...
calendar_home_set: CalendarSet # can also be set to anything URL.objectify() accepts
def freebusy_request(self, dtstart, dtend, attendees): ...
def calendar_user_address_set(self) -> list[str]: ...
def schedule_inbox(self) -> ScheduleInbox: ...
def schedule_outbox(self) -> ScheduleOutbox: ...
class Calendar(DAVObject):
def get_supported_components(self) -> list[Any]: ...
def save_with_invites(self, ical: str, attendees, **attendeeoptions) -> None: ...
def save_event(self, ical: str, no_overwrite: bool = ..., no_create: bool = ...) -> Event: ...
def save_todo(self, ical: str, no_overwrite: bool = ..., no_create: bool = ...) -> Todo: ...
def save_journal(self, ical: str, no_overwrite: bool = ..., no_create: bool = ...) -> Journal: ...
add_event = save_event
add_todo = save_todo
add_journal = save_journal
def calendar_multiget(self, event_urls: Iterable[URL]) -> list[Event]: ...
def build_date_search_query(
self,
start,
end: datetime.datetime | None = ...,
compfilter: Literal["VEVENT"] | None = ...,
expand: bool | Literal["maybe"] = ...,
): ...
@overload
def date_search(
self,
start: datetime.datetime,
end: datetime.datetime | None = ...,
compfilter: Literal["VEVENT"] = ...,
expand: bool | Literal["maybe"] = ...,
) -> list[Event]: ...
@overload
def date_search(
self, start: datetime.datetime, *, compfilter: None, expand: bool | Literal["maybe"] = ...
) -> list[CalendarObjectResource]: ...
@overload
def date_search(
self, start: datetime.datetime, end: datetime.datetime | None, compfilter: None, expand: bool | Literal["maybe"] = ...
) -> list[CalendarObjectResource]: ...
@overload
def search(self, xml, comp_class: None = ...) -> list[CalendarObjectResource]: ...
@overload
def search(self, xml, comp_class: Type[_CC]) -> list[_CC]: ...
def freebusy_request(self, start: datetime.datetime, end: datetime.datetime) -> FreeBusy: ...
def todos(self, sort_keys: Iterable[str] = ..., include_completed: bool = ..., sort_key: str | None = ...) -> list[Todo]: ...
def event_by_url(self, href, data: Any | None = ...) -> Event: ...
def object_by_uid(self, uid: str, comp_filter: CompFilter | None = ...) -> Event: ...
def todo_by_uid(self, uid: str) -> CalendarObjectResource: ...
def event_by_uid(self, uid: str) -> CalendarObjectResource: ...
def journal_by_uid(self, uid: str) -> CalendarObjectResource: ...
event = event_by_uid
def events(self) -> list[Event]: ...
def objects_by_sync_token(
self, sync_token: Any | None = ..., load_objects: bool = ...
) -> SynchronizableCalendarObjectCollection: ...
objects = objects_by_sync_token
def journals(self) -> list[Journal]: ...
class ScheduleMailbox(Calendar):
def __init__(
self,
client: DAVClient | None = ...,
principal: Principal | None = ...,
url: str | ParseResult | SplitResult | URL | None = ...,
) -> None: ...
def get_items(self): ...
class ScheduleInbox(ScheduleMailbox):
findprop = ScheduleInboxURL
class ScheduleOutbox(ScheduleMailbox):
findprop = ScheduleOutboxURL
class SynchronizableCalendarObjectCollection:
def __init__(self, calendar, objects, sync_token) -> None: ...
def __iter__(self) -> Iterator[Any]: ...
def objects_by_url(self): ...
def sync(self) -> tuple[Any, Any]: ...
class CalendarObjectResource(DAVObject):
def __init__(
self,
client: DAVClient | None = ...,
url: str | ParseResult | SplitResult | URL | None = ...,
data: Any | None = ...,
parent: Any | None = ...,
id: Any | None = ...,
props: Any | None = ...,
) -> None: ...
def add_organizer(self) -> None: ...
def add_attendee(self, attendee, no_default_parameters: bool = ..., **parameters) -> None: ...
def is_invite_request(self) -> bool: ...
def accept_invite(self, calendar: Any | None = ...) -> None: ...
def decline_invite(self, calendar: Any | None = ...) -> None: ...
def tentatively_accept_invite(self, calendar: Any | None = ...) -> None: ...
def copy(self: Self, keep_uid: bool = ..., new_parent: Any | None = ...) -> Self: ...
def load(self: Self) -> Self: ...
def change_attendee_status(self, attendee: Any | None = ..., **kwargs) -> None: ...
def save(
self: Self, no_overwrite: bool = ..., no_create: bool = ..., obj_type: Any | None = ..., if_schedule_tag_match: bool = ...
) -> Self: ...
data: Any
vobject_instance: _VBase
icalendar_instance: Any
instance: _VBase
class Event(CalendarObjectResource): ...
class Journal(CalendarObjectResource): ...
class FreeBusy(CalendarObjectResource):
def __init__(self, parent, data, url: str | ParseResult | SplitResult | URL | None = ..., id: Any | None = ...) -> None: ...
class Todo(CalendarObjectResource):
def complete(self, completion_timestamp: datetime.datetime | None = ...) -> None: ...