# `DAVClient` – A simple DAV client

class caldav.davclient.DAVClient(url: str, proxy: str | None = None, username: str | None = None, password: str | None = None, auth: AuthBase | None = None, timeout: int | None = None, ssl_verify_cert: bool | str = True, ssl_cert: str | Tuple[str, str] | None = None, headers: Dict[str, str] = None, huge_tree: bool = False)

  Basic client for webdav, uses the requests lib; gives access to low-level operations towards the caldav server.

  Unless you have special needs, you should probably care most about the constructor (__init__), the principal method and the calendar method.

  calendar(**kwargs)

    Returns a calendar object.

    Typically, a URL should be given as a named parameter (url)

    No network traffic will be initiated by this method.

    If you don’t know the URL of the calendar, use client.principal().calendar(…) instead, or client.principal().calendars()

  close() → None

    Closes the DAVClient’s session object

  delete(url: str) → DAVResponse

    Send a delete request.

  mkcalendar(url: str, body: str = '', dummy: None = None) → DAVResponse

    Send a mkcalendar request.

    Parameters:

      - url: url for the root of the mkcalendar

      - body: XML request

      - dummy: compatibility parameter

    Returns

      - DAVResponse

  mkcol(url: str, body: str, dummy: None = None) → DAVResponse

    Send a MKCOL request.

    MKCOL is basically not used with caldav, one should use MKCALENDAR instead. However, some calendar servers MAY allow “subcollections” to be made in a calendar, by using the MKCOL query. As for 2020-05, this method is not exercised by test code or referenced anywhere else in the caldav library, it’s included just for the sake of completeness. And, perhaps this DAVClient class can be used for vCards and other WebDAV purposes.

    Parameters:

      - url: url for the root of the mkcol

      - body: XML request

      - dummy: compatibility parameter

    Returns

      - DAVResponse

  post(url: str, body: str, headers: Mapping[str, str] = None) → DAVResponse

    Send a POST request.

  principal(*largs, **kwargs)

    Convenience method, it gives a bit more object-oriented feel to write client.principal() than Principal(client).

    This method returns a `caldav.Principal` object, with higher-level methods for dealing with the principals calendars.

  propfind(url: str | None = None, props: str = '', depth: int = 0) → DAVResponse

    Send a propfind request.

    Parameters:

      - url: url for the root of the propfind.

      - props = (xml request), properties we want

      - depth: maximum recursion depth

    Returns

      - DAVResponse

  proppatch(url: str, body: str, dummy: None = None) → DAVResponse

    Send a proppatch request.

    Parameters:

      - url: url for the root of the propfind.

      - body: XML propertyupdate request

      - dummy: compatibility parameter

    Returns

      - DAVResponse

  put(url: str, body: str, headers: Mapping[str, str] = None) → DAVResponse

    Send a put request.

  report(url: str, query: str = '', depth: int = 0) → DAVResponse

    Send a report request.

    Parameters:

      - url: url for the root of the propfind.

      - query: XML request

      - depth: maximum recursion depth

    Returns

      - DAVResponse

  request(url: str, method: str = 'GET', body: str = '', headers: Mapping[str, str] = None) → DAVResponse

    Actually sends the request, and does the authentication

class caldav.davclient.DAVResponse(response: Response, davclient: DAVClient | None = None)

  This class is a response from a DAV request. It is instantiated from the DAVClient class. End users of the library should not need to know anything about this class. Since we often get XML responses, it tries to parse it into self.tree

  expand_simple_props(props: Iterable[BaseElement] = None, multi_value_props: Iterable[Any] = None, xpath: str | None = None) → Dict[str, Dict[str, str]]

    The find_objects_and_props() will stop at the xml element below the prop tag. This method will expand those props into text.

    Executes find_objects_and_props if not run already, then modifies and returns self.objects.

  find_objects_and_props() → Dict[str, Dict[str, _Element]]

    Check the response from the server, check that it is on an expected format, find hrefs and props from it and check statuses delivered.

    The parsed data will be put into self.objects, a dict {href: {proptag: prop_element}}. Further parsing of the prop_element has to be done by the caller.

    self.sync_token will be populated if found, self.objects will be populated.

  validate_status(status: str) → None

    status is a string like “HTTP/1.1 404 Not Found”. 200, 207 and 404 are considered good statuses. The SOGo caldav server even returns “201 created” when doing a sync-report, to indicate that a resource was created after the last sync-token. This makes sense to me, but I’ve only seen it from SOGo, and it’s not in accordance with the examples in rfc6578.