From 1371649cc1fec6f61ed13ed968eceb79a88f028d Mon Sep 17 00:00:00 2001 From: ecederstrand Date: Thu, 25 Apr 2024 13:16:23 +0200 Subject: [PATCH] docs: Update docs --- docs/exchangelib/fields.html | 295 ++++++++++++------ docs/exchangelib/folders/base.html | 129 ++++---- docs/exchangelib/folders/index.html | 186 ++++++----- docs/exchangelib/folders/queryset.html | 42 ++- docs/exchangelib/folders/roots.html | 129 ++++---- docs/exchangelib/index.html | 138 ++++---- docs/exchangelib/indexed_properties.html | 86 ++++- docs/exchangelib/items/contact.html | 5 +- docs/exchangelib/items/index.html | 2 +- docs/exchangelib/properties.html | 10 +- docs/exchangelib/services/common.html | 95 ++---- docs/exchangelib/services/create_folder.html | 4 +- docs/exchangelib/services/get_folder.html | 4 +- .../services/get_user_settings.html | 4 +- docs/exchangelib/services/index.html | 22 +- .../services/sync_folder_hierarchy.html | 4 +- docs/exchangelib/services/update_folder.html | 4 +- docs/exchangelib/util.html | 32 +- pyproject.toml | 2 +- 19 files changed, 726 insertions(+), 467 deletions(-) diff --git a/docs/exchangelib/fields.html b/docs/exchangelib/fields.html index 252253d4..0ef39cd5 100644 --- a/docs/exchangelib/fields.html +++ b/docs/exchangelib/fields.html @@ -1358,6 +1358,9 @@

Module exchangelib.fields

class IndexedField(EWSElementField, metaclass=abc.ABCMeta): """A base class for all indexed fields.""" + is_list = True + is_complex = True + PARENT_ELEMENT_NAME = None def __init__(self, *args, **kwargs): @@ -1378,16 +1381,15 @@

Module exchangelib.fields

return hash(self.field_uri) -class EmailAddressesField(IndexedField): - is_list = True - is_complex = True - - PARENT_ELEMENT_NAME = "EmailAddresses" +class SingleFieldIndexedField(IndexedField): + """A base class for all single-field indexed fields.""" def __init__(self, *args, **kwargs): - from .indexed_properties import EmailAddress + from .indexed_properties import SingleFieldIndexedElement - kwargs["value_cls"] = EmailAddress + value_cls = kwargs["value_cls"] + if not issubclass(value_cls, SingleFieldIndexedElement): + raise TypeError(f"'value_cls' {value_cls!r} must be a subclass of type {SingleFieldIndexedElement}") super().__init__(*args, **kwargs) def clean(self, value, version=None): @@ -1396,19 +1398,37 @@

Module exchangelib.fields

if len(value) > len(default_labels): raise ValueError(f"This field can handle at most {len(default_labels)} values (value: {value})") tmp = [] + value_field_name = self.value_cls.value_field(version=version).name for s, default_label in zip(value, default_labels): if not isinstance(s, str): tmp.append(s) continue - tmp.append(self.value_cls(email=s, label=default_label)) + tmp.append(self.value_cls(**{"label": default_label, value_field_name: s})) value = tmp return super().clean(value, version=version) -class PhoneNumberField(IndexedField): - is_list = True - is_complex = True +class EmailAddressesField(SingleFieldIndexedField): + PARENT_ELEMENT_NAME = "EmailAddresses" + def __init__(self, *args, **kwargs): + from .indexed_properties import EmailAddress + + kwargs["value_cls"] = EmailAddress + super().__init__(*args, **kwargs) + + +class ImAddressField(SingleFieldIndexedField): + PARENT_ELEMENT_NAME = "ImAddresses" + + def __init__(self, *args, **kwargs): + from .indexed_properties import ImAddress + + kwargs["value_cls"] = ImAddress + super().__init__(*args, **kwargs) + + +class PhoneNumberField(SingleFieldIndexedField): PARENT_ELEMENT_NAME = "PhoneNumbers" def __init__(self, *args, **kwargs): @@ -3599,39 +3619,23 @@

Inherited members

(*args, **kwargs)
-

A base class for all indexed fields.

+

A base class for all single-field indexed fields.

Expand source code -
class EmailAddressesField(IndexedField):
-    is_list = True
-    is_complex = True
-
+
class EmailAddressesField(SingleFieldIndexedField):
     PARENT_ELEMENT_NAME = "EmailAddresses"
 
     def __init__(self, *args, **kwargs):
         from .indexed_properties import EmailAddress
 
         kwargs["value_cls"] = EmailAddress
-        super().__init__(*args, **kwargs)
-
-    def clean(self, value, version=None):
-        if value is not None:
-            default_labels = self.value_cls.LABEL_CHOICES
-            if len(value) > len(default_labels):
-                raise ValueError(f"This field can handle at most {len(default_labels)} values (value: {value})")
-            tmp = []
-            for s, default_label in zip(value, default_labels):
-                if not isinstance(s, str):
-                    tmp.append(s)
-                    continue
-                tmp.append(self.value_cls(email=s, label=default_label))
-            value = tmp
-        return super().clean(value, version=version)
+ super().__init__(*args, **kwargs)

Ancestors

+
+class ImAddressField +(*args, **kwargs) +
+
+

A base class for all single-field indexed fields.

+
+ +Expand source code + +
class ImAddressField(SingleFieldIndexedField):
+    PARENT_ELEMENT_NAME = "ImAddresses"
+
+    def __init__(self, *args, **kwargs):
+        from .indexed_properties import ImAddress
+
+        kwargs["value_cls"] = ImAddress
+        super().__init__(*args, **kwargs)
+
+

Ancestors

+ +

Class variables

+
+
var PARENT_ELEMENT_NAME
+
+
+
+
+

Inherited members

+ +
class ImportanceField (*args, **kwargs) @@ -5155,6 +5169,9 @@

Inherited members

class IndexedField(EWSElementField, metaclass=abc.ABCMeta):
     """A base class for all indexed fields."""
 
+    is_list = True
+    is_complex = True
+
     PARENT_ELEMENT_NAME = None
 
     def __init__(self, *args, **kwargs):
@@ -5183,9 +5200,8 @@ 

Ancestors

Subclasses

Class variables

@@ -5193,6 +5209,14 @@

Class variables

+
var is_complex
+
+
+
+
var is_list
+
+
+

Methods

@@ -6083,15 +6107,12 @@

Inherited members

(*args, **kwargs)
-

A base class for all indexed fields.

+

A base class for all single-field indexed fields.

Expand source code -
class PhoneNumberField(IndexedField):
-    is_list = True
-    is_complex = True
-
+
class PhoneNumberField(SingleFieldIndexedField):
     PARENT_ELEMENT_NAME = "PhoneNumbers"
 
     def __init__(self, *args, **kwargs):
@@ -6102,6 +6123,7 @@ 

Inherited members

Ancestors

+
+class SingleFieldIndexedField +(*args, **kwargs) +
+
+

A base class for all single-field indexed fields.

+
+ +Expand source code + +
class SingleFieldIndexedField(IndexedField):
+    """A base class for all single-field indexed fields."""
+
+    def __init__(self, *args, **kwargs):
+        from .indexed_properties import SingleFieldIndexedElement
+
+        value_cls = kwargs["value_cls"]
+        if not issubclass(value_cls, SingleFieldIndexedElement):
+            raise TypeError(f"'value_cls' {value_cls!r} must be a subclass of type {SingleFieldIndexedElement}")
+        super().__init__(*args, **kwargs)
+
+    def clean(self, value, version=None):
+        if value is not None:
+            default_labels = self.value_cls.LABEL_CHOICES
+            if len(value) > len(default_labels):
+                raise ValueError(f"This field can handle at most {len(default_labels)} values (value: {value})")
+            tmp = []
+            value_field_name = self.value_cls.value_field(version=version).name
+            for s, default_label in zip(value, default_labels):
+                if not isinstance(s, str):
+                    tmp.append(s)
+                    continue
+                tmp.append(self.value_cls(**{"label": default_label, value_field_name: s}))
+            value = tmp
+        return super().clean(value, version=version)
+
+

Ancestors

+ +

Subclasses

+ +

Methods

+
+
+def clean(self, value, version=None) +
+
+
+
+ +Expand source code + +
def clean(self, value, version=None):
+    if value is not None:
+        default_labels = self.value_cls.LABEL_CHOICES
+        if len(value) > len(default_labels):
+            raise ValueError(f"This field can handle at most {len(default_labels)} values (value: {value})")
+        tmp = []
+        value_field_name = self.value_cls.value_field(version=version).name
+        for s, default_label in zip(value, default_labels):
+            if not isinstance(s, str):
+                tmp.append(s)
+                continue
+            tmp.append(self.value_cls(**{"label": default_label, value_field_name: s}))
+        value = tmp
+    return super().clean(value, version=version)
+
+
+
+

Inherited members

+ +
class StringAttributedValueField (*args, **kwargs) @@ -7528,9 +7630,6 @@

EmailAddressesField

  • @@ -7631,12 +7730,20 @@

    IdField

  • +

    ImAddressField

    + +
  • +
  • ImportanceField

  • IndexedField

  • @@ -7731,8 +7838,6 @@

    PhoneNumberField

  • @@ -7768,6 +7873,12 @@

    SensitivityField

  • +

    SingleFieldIndexedField

    + +
  • +
  • StringAttributedValueField

  • diff --git a/docs/exchangelib/folders/base.html b/docs/exchangelib/folders/base.html index 9ba89d1b..8c39d417 100644 --- a/docs/exchangelib/folders/base.html +++ b/docs/exchangelib/folders/base.html @@ -122,6 +122,8 @@

    Module exchangelib.folders.base

    self.item_sync_state = kwargs.pop("item_sync_state", None) self.folder_sync_state = kwargs.pop("folder_sync_state", None) super().__init__(**kwargs) + if self._distinguished_id and self.account: + self._distinguished_id.mailbox = Mailbox(email_address=self.account.primary_smtp_address) @property @abc.abstractmethod @@ -241,6 +243,15 @@

    Module exchangelib.folders.base

    tree += f" {node}\n" return tree.strip() + @classmethod + def _get_distinguished(cls, folder): + if not cls.DISTINGUISHED_FOLDER_ID: + raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") + try: + return cls.resolve(account=folder.account, folder=folder) + except MISSING_FOLDER_ERRORS as e: + raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r} ({e})") + @property def has_distinguished_name(self): return self.name and self.DISTINGUISHED_FOLDER_ID and self.name.lower() == self.DISTINGUISHED_FOLDER_ID.lower() @@ -852,7 +863,7 @@

    Module exchangelib.folders.base

    if parent.root != self.root: raise ValueError("'parent.root' must match 'root'") else: - self.root = parent.root + self._root = parent.root if "parent_folder_id" in kwargs and parent.id != kwargs["parent_folder_id"]: raise ValueError("'parent_folder_id' must match 'parent' ID") kwargs["parent_folder_id"] = ParentFolderId(id=parent.id, changekey=parent.changekey) @@ -868,10 +879,6 @@

    Module exchangelib.folders.base

    def root(self): return self._root - @root.setter - def root(self, value): - self._root = value - @classmethod def register(cls, *args, **kwargs): if cls is not Folder: @@ -884,24 +891,6 @@

    Module exchangelib.folders.base

    raise TypeError("For folders, custom fields must be registered on the Folder class") return super().deregister(*args, **kwargs) - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - :return: - """ - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r}") - @property def parent(self): if not self.parent_folder_id: @@ -918,7 +907,7 @@

    Module exchangelib.folders.base

    else: if not isinstance(value, BaseFolder): raise InvalidTypeError("value", value, BaseFolder) - self.root = value.root + self._root = value.root self.parent_folder_id = ParentFolderId(id=value.id, changekey=value.changekey) def clean(self, version=None): @@ -928,6 +917,23 @@

    Module exchangelib.folders.base

    if self.root and not isinstance(self.root, RootOfHierarchy): raise InvalidTypeError("root", self.root, RootOfHierarchy) + @classmethod + def get_distinguished(cls, root): + """Get the distinguished folder for this folder class. + + :param root: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=root.account.primary_smtp_address), + ), + root=root, + ) + ) + @classmethod def from_xml_with_root(cls, elem, root): folder = cls.from_xml(elem=elem, account=root.account) @@ -1025,6 +1031,8 @@

    Classes

    self.item_sync_state = kwargs.pop("item_sync_state", None) self.folder_sync_state = kwargs.pop("folder_sync_state", None) super().__init__(**kwargs) + if self._distinguished_id and self.account: + self._distinguished_id.mailbox = Mailbox(email_address=self.account.primary_smtp_address) @property @abc.abstractmethod @@ -1144,6 +1152,15 @@

    Classes

    tree += f" {node}\n" return tree.strip() + @classmethod + def _get_distinguished(cls, folder): + if not cls.DISTINGUISHED_FOLDER_ID: + raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") + try: + return cls.resolve(account=folder.account, folder=folder) + except MISSING_FOLDER_ERRORS as e: + raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r} ({e})") + @property def has_distinguished_name(self): return self.name and self.DISTINGUISHED_FOLDER_ID and self.name.lower() == self.DISTINGUISHED_FOLDER_ID.lower() @@ -2975,7 +2992,7 @@

    Inherited members

    if parent.root != self.root: raise ValueError("'parent.root' must match 'root'") else: - self.root = parent.root + self._root = parent.root if "parent_folder_id" in kwargs and parent.id != kwargs["parent_folder_id"]: raise ValueError("'parent_folder_id' must match 'parent' ID") kwargs["parent_folder_id"] = ParentFolderId(id=parent.id, changekey=parent.changekey) @@ -2991,10 +3008,6 @@

    Inherited members

    def root(self): return self._root - @root.setter - def root(self, value): - self._root = value - @classmethod def register(cls, *args, **kwargs): if cls is not Folder: @@ -3007,24 +3020,6 @@

    Inherited members

    raise TypeError("For folders, custom fields must be registered on the Folder class") return super().deregister(*args, **kwargs) - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - :return: - """ - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r}") - @property def parent(self): if not self.parent_folder_id: @@ -3041,7 +3036,7 @@

    Inherited members

    else: if not isinstance(value, BaseFolder): raise InvalidTypeError("value", value, BaseFolder) - self.root = value.root + self._root = value.root self.parent_folder_id = ParentFolderId(id=value.id, changekey=value.changekey) def clean(self, version=None): @@ -3051,6 +3046,23 @@

    Inherited members

    if self.root and not isinstance(self.root, RootOfHierarchy): raise InvalidTypeError("root", self.root, RootOfHierarchy) + @classmethod + def get_distinguished(cls, root): + """Get the distinguished folder for this folder class. + + :param root: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=root.account.primary_smtp_address), + ), + root=root, + ) + ) + @classmethod def from_xml_with_root(cls, elem, root): folder = cls.from_xml(elem=elem, account=root.account) @@ -3173,33 +3185,32 @@

    Static methods

    -def get_distinguished(account) +def get_distinguished(root)

    Get the distinguished folder for this folder class.

    -

    :param account: +

    :param root: :return:

    Expand source code
    @classmethod
    -def get_distinguished(cls, account):
    +def get_distinguished(cls, root):
         """Get the distinguished folder for this folder class.
     
    -    :param account:
    +    :param root:
         :return:
         """
    -    try:
    -        return cls.resolve(
    -            account=account,
    -            folder=DistinguishedFolderId(
    +    return cls._get_distinguished(
    +        folder=cls(
    +            _distinguished_id=DistinguishedFolderId(
                     id=cls.DISTINGUISHED_FOLDER_ID,
    -                mailbox=Mailbox(email_address=account.primary_smtp_address),
    +                mailbox=Mailbox(email_address=root.account.primary_smtp_address),
                 ),
    +            root=root,
             )
    -    except MISSING_FOLDER_ERRORS:
    -        raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r}")
    + )
    diff --git a/docs/exchangelib/folders/index.html b/docs/exchangelib/folders/index.html index 44e7b377..556e1f7c 100644 --- a/docs/exchangelib/folders/index.html +++ b/docs/exchangelib/folders/index.html @@ -1545,6 +1545,8 @@

    Inherited members

    self.item_sync_state = kwargs.pop("item_sync_state", None) self.folder_sync_state = kwargs.pop("folder_sync_state", None) super().__init__(**kwargs) + if self._distinguished_id and self.account: + self._distinguished_id.mailbox = Mailbox(email_address=self.account.primary_smtp_address) @property @abc.abstractmethod @@ -1664,6 +1666,15 @@

    Inherited members

    tree += f" {node}\n" return tree.strip() + @classmethod + def _get_distinguished(cls, folder): + if not cls.DISTINGUISHED_FOLDER_ID: + raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") + try: + return cls.resolve(account=folder.account, folder=folder) + except MISSING_FOLDER_ERRORS as e: + raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r} ({e})") + @property def has_distinguished_name(self): return self.name and self.DISTINGUISHED_FOLDER_ID and self.name.lower() == self.DISTINGUISHED_FOLDER_ID.lower() @@ -4611,7 +4622,9 @@

    Inherited members

    super().clean(version=version) if self.id == PublicFoldersRoot.DISTINGUISHED_FOLDER_ID: # Avoid "ErrorInvalidOperation: It is not valid to specify a mailbox with the public folder root" from EWS - self.mailbox = None
    + self.mailbox = None + elif not self.mailbox: + raise ValueError(f"DistinguishedFolderId {self.id} must have a mailbox")

    Ancestors

      @@ -4672,7 +4685,9 @@

      Methods

      super().clean(version=version) if self.id == PublicFoldersRoot.DISTINGUISHED_FOLDER_ID: # Avoid "ErrorInvalidOperation: It is not valid to specify a mailbox with the public folder root" from EWS - self.mailbox = None
      + self.mailbox = None + elif not self.mailbox: + raise ValueError(f"DistinguishedFolderId {self.id} must have a mailbox") @@ -5246,7 +5261,7 @@

      Inherited members

      if parent.root != self.root: raise ValueError("'parent.root' must match 'root'") else: - self.root = parent.root + self._root = parent.root if "parent_folder_id" in kwargs and parent.id != kwargs["parent_folder_id"]: raise ValueError("'parent_folder_id' must match 'parent' ID") kwargs["parent_folder_id"] = ParentFolderId(id=parent.id, changekey=parent.changekey) @@ -5262,10 +5277,6 @@

      Inherited members

      def root(self): return self._root - @root.setter - def root(self, value): - self._root = value - @classmethod def register(cls, *args, **kwargs): if cls is not Folder: @@ -5278,24 +5289,6 @@

      Inherited members

      raise TypeError("For folders, custom fields must be registered on the Folder class") return super().deregister(*args, **kwargs) - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - :return: - """ - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r}") - @property def parent(self): if not self.parent_folder_id: @@ -5312,7 +5305,7 @@

      Inherited members

      else: if not isinstance(value, BaseFolder): raise InvalidTypeError("value", value, BaseFolder) - self.root = value.root + self._root = value.root self.parent_folder_id = ParentFolderId(id=value.id, changekey=value.changekey) def clean(self, version=None): @@ -5322,6 +5315,23 @@

      Inherited members

      if self.root and not isinstance(self.root, RootOfHierarchy): raise InvalidTypeError("root", self.root, RootOfHierarchy) + @classmethod + def get_distinguished(cls, root): + """Get the distinguished folder for this folder class. + + :param root: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=root.account.primary_smtp_address), + ), + root=root, + ) + ) + @classmethod def from_xml_with_root(cls, elem, root): folder = cls.from_xml(elem=elem, account=root.account) @@ -5444,33 +5454,32 @@

      Static methods

      -def get_distinguished(account) +def get_distinguished(root)

      Get the distinguished folder for this folder class.

      -

      :param account: +

      :param root: :return:

      Expand source code
      @classmethod
      -def get_distinguished(cls, account):
      +def get_distinguished(cls, root):
           """Get the distinguished folder for this folder class.
       
      -    :param account:
      +    :param root:
           :return:
           """
      -    try:
      -        return cls.resolve(
      -            account=account,
      -            folder=DistinguishedFolderId(
      +    return cls._get_distinguished(
      +        folder=cls(
      +            _distinguished_id=DistinguishedFolderId(
                       id=cls.DISTINGUISHED_FOLDER_ID,
      -                mailbox=Mailbox(email_address=account.primary_smtp_address),
      +                mailbox=Mailbox(email_address=root.account.primary_smtp_address),
                   ),
      +            root=root,
               )
      -    except MISSING_FOLDER_ERRORS:
      -        raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r}")
      + )
      @@ -6972,11 +6981,23 @@

      Inherited members

      """Return the query result as exactly one item. Raises DoesNotExist if there are no results, and MultipleObjectsReturned if there are multiple results. """ + from .base import Folder from .collections import FolderCollection if not args and set(kwargs) in ({"id"}, {"id", "changekey"}): + roots = {f.root for f in self.folder_collection.folders} + if len(roots) != 1: + raise ValueError(f"All folders must have the same root hierarchy ({roots})") folders = list( - FolderCollection(account=self.folder_collection.account, folders=[FolderId(**kwargs)]).resolve() + FolderCollection( + account=self.folder_collection.account, + folders=[ + Folder( + _id=FolderId(**kwargs), + root=roots.pop(), + ) + ], + ).resolve() ) elif args or kwargs: folders = list(self.filter(*args, **kwargs)) @@ -7128,11 +7149,23 @@

      Methods

      """Return the query result as exactly one item. Raises DoesNotExist if there are no results, and MultipleObjectsReturned if there are multiple results. """ + from .base import Folder from .collections import FolderCollection if not args and set(kwargs) in ({"id"}, {"id", "changekey"}): + roots = {f.root for f in self.folder_collection.folders} + if len(roots) != 1: + raise ValueError(f"All folders must have the same root hierarchy ({roots})") folders = list( - FolderCollection(account=self.folder_collection.account, folders=[FolderId(**kwargs)]).resolve() + FolderCollection( + account=self.folder_collection.account, + folders=[ + Folder( + _id=FolderId(**kwargs), + root=roots.pop(), + ) + ], + ).resolve() ) elif args or kwargs: folders = list(self.filter(*args, **kwargs)) @@ -9354,6 +9387,11 @@

      Inherited members

      DEFAULT_FOLDER_TRAVERSAL_DEPTH = SHALLOW supported_from = EXCHANGE_2007_SP1 + def __init__(self, **kwargs): + super().__init__(**kwargs) + if self._distinguished_id: + self._distinguished_id.mailbox = None # See DistinguishedFolderId.clean() + def get_children(self, folder): # EWS does not allow deep traversal of public folders, so self._folders_map will only populate the top-level # subfolders. To traverse public folders at arbitrary depth, we need to get child folders on demand. @@ -10998,25 +11036,6 @@

      Inherited members

      if f.parent.id == folder.id: yield f - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - """ - if not cls.DISTINGUISHED_FOLDER_ID: - raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}") - def get_default_folder(self, folder_cls): """Return the distinguished folder instance of type folder_cls belonging to this account. If no distinguished folder was found, try as best we can to return the default folder of type 'folder_cls' @@ -11033,16 +11052,16 @@

      Inherited members

      return f try: log.debug("Requesting distinguished %s folder explicitly", folder_cls) - return folder_cls.get_distinguished(account=self.account) + return folder_cls.get_distinguished(root=self) except ErrorAccessDenied: # Maybe we just don't have GetFolder access? Try FindItem instead log.debug("Testing default %s folder with FindItem", folder_cls) fld = folder_cls( - root=self, _distinguished_id=DistinguishedFolderId( id=folder_cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=self.account.primary_smtp_address), ), + root=self, ) fld.test_access() return self._folders_map.get(fld.id, fld) # Use cached instance if available @@ -11051,6 +11070,23 @@

      Inherited members

      pass raise ErrorFolderNotFound(f"No usable default {folder_cls} folders") + @classmethod + def get_distinguished(cls, account): + """Get the distinguished folder for this folder class. + + :param account: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=account.primary_smtp_address), + ), + account=account, + ) + ) + @property def _folders_map(self): if self._subfolders is not None: @@ -11061,9 +11097,12 @@

      Inherited members

      # so we are sure to apply the correct Folder class, then fetch all sub-folders of this root. folders_map = {self.id: self} distinguished_folders = [ - DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=self.account.primary_smtp_address), + cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=self.account.primary_smtp_address), + ), + root=self, ) for cls in self.WELLKNOWN_FOLDERS if cls.get_folder_allowed and cls.supports_version(self.account.version) @@ -11243,7 +11282,8 @@

      Static methods

  • Get the distinguished folder for this folder class.

    -

    :param account:

    +

    :param account: +:return:

    Expand source code @@ -11253,19 +11293,17 @@

    Static methods

    """Get the distinguished folder for this folder class. :param account: + :return: """ - if not cls.DISTINGUISHED_FOLDER_ID: - raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( id=cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=account.primary_smtp_address), ), + account=account, ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}") + )
    @@ -11350,16 +11388,16 @@

    Methods

    return f try: log.debug("Requesting distinguished %s folder explicitly", folder_cls) - return folder_cls.get_distinguished(account=self.account) + return folder_cls.get_distinguished(root=self) except ErrorAccessDenied: # Maybe we just don't have GetFolder access? Try FindItem instead log.debug("Testing default %s folder with FindItem", folder_cls) fld = folder_cls( - root=self, _distinguished_id=DistinguishedFolderId( id=folder_cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=self.account.primary_smtp_address), ), + root=self, ) fld.test_access() return self._folders_map.get(fld.id, fld) # Use cached instance if available diff --git a/docs/exchangelib/folders/queryset.html b/docs/exchangelib/folders/queryset.html index 4098679d..17aa4796 100644 --- a/docs/exchangelib/folders/queryset.html +++ b/docs/exchangelib/folders/queryset.html @@ -102,11 +102,23 @@

    Module exchangelib.folders.queryset

    """Return the query result as exactly one item. Raises DoesNotExist if there are no results, and MultipleObjectsReturned if there are multiple results. """ + from .base import Folder from .collections import FolderCollection if not args and set(kwargs) in ({"id"}, {"id", "changekey"}): + roots = {f.root for f in self.folder_collection.folders} + if len(roots) != 1: + raise ValueError(f"All folders must have the same root hierarchy ({roots})") folders = list( - FolderCollection(account=self.folder_collection.account, folders=[FolderId(**kwargs)]).resolve() + FolderCollection( + account=self.folder_collection.account, + folders=[ + Folder( + _id=FolderId(**kwargs), + root=roots.pop(), + ) + ], + ).resolve() ) elif args or kwargs: folders = list(self.filter(*args, **kwargs)) @@ -278,11 +290,23 @@

    Classes

    """Return the query result as exactly one item. Raises DoesNotExist if there are no results, and MultipleObjectsReturned if there are multiple results. """ + from .base import Folder from .collections import FolderCollection if not args and set(kwargs) in ({"id"}, {"id", "changekey"}): + roots = {f.root for f in self.folder_collection.folders} + if len(roots) != 1: + raise ValueError(f"All folders must have the same root hierarchy ({roots})") folders = list( - FolderCollection(account=self.folder_collection.account, folders=[FolderId(**kwargs)]).resolve() + FolderCollection( + account=self.folder_collection.account, + folders=[ + Folder( + _id=FolderId(**kwargs), + root=roots.pop(), + ) + ], + ).resolve() ) elif args or kwargs: folders = list(self.filter(*args, **kwargs)) @@ -434,11 +458,23 @@

    Methods

    """Return the query result as exactly one item. Raises DoesNotExist if there are no results, and MultipleObjectsReturned if there are multiple results. """ + from .base import Folder from .collections import FolderCollection if not args and set(kwargs) in ({"id"}, {"id", "changekey"}): + roots = {f.root for f in self.folder_collection.folders} + if len(roots) != 1: + raise ValueError(f"All folders must have the same root hierarchy ({roots})") folders = list( - FolderCollection(account=self.folder_collection.account, folders=[FolderId(**kwargs)]).resolve() + FolderCollection( + account=self.folder_collection.account, + folders=[ + Folder( + _id=FolderId(**kwargs), + root=roots.pop(), + ) + ], + ).resolve() ) elif args or kwargs: folders = list(self.filter(*args, **kwargs)) diff --git a/docs/exchangelib/folders/roots.html b/docs/exchangelib/folders/roots.html index e4e8957a..089b61cd 100644 --- a/docs/exchangelib/folders/roots.html +++ b/docs/exchangelib/folders/roots.html @@ -129,25 +129,6 @@

    Module exchangelib.folders.roots

    if f.parent.id == folder.id: yield f - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - """ - if not cls.DISTINGUISHED_FOLDER_ID: - raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}") - def get_default_folder(self, folder_cls): """Return the distinguished folder instance of type folder_cls belonging to this account. If no distinguished folder was found, try as best we can to return the default folder of type 'folder_cls' @@ -164,16 +145,16 @@

    Module exchangelib.folders.roots

    return f try: log.debug("Requesting distinguished %s folder explicitly", folder_cls) - return folder_cls.get_distinguished(account=self.account) + return folder_cls.get_distinguished(root=self) except ErrorAccessDenied: # Maybe we just don't have GetFolder access? Try FindItem instead log.debug("Testing default %s folder with FindItem", folder_cls) fld = folder_cls( - root=self, _distinguished_id=DistinguishedFolderId( id=folder_cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=self.account.primary_smtp_address), ), + root=self, ) fld.test_access() return self._folders_map.get(fld.id, fld) # Use cached instance if available @@ -182,6 +163,23 @@

    Module exchangelib.folders.roots

    pass raise ErrorFolderNotFound(f"No usable default {folder_cls} folders") + @classmethod + def get_distinguished(cls, account): + """Get the distinguished folder for this folder class. + + :param account: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=account.primary_smtp_address), + ), + account=account, + ) + ) + @property def _folders_map(self): if self._subfolders is not None: @@ -192,9 +190,12 @@

    Module exchangelib.folders.roots

    # so we are sure to apply the correct Folder class, then fetch all sub-folders of this root. folders_map = {self.id: self} distinguished_folders = [ - DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=self.account.primary_smtp_address), + cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=self.account.primary_smtp_address), + ), + root=self, ) for cls in self.WELLKNOWN_FOLDERS if cls.get_folder_allowed and cls.supports_version(self.account.version) @@ -354,6 +355,11 @@

    Module exchangelib.folders.roots

    DEFAULT_FOLDER_TRAVERSAL_DEPTH = SHALLOW supported_from = EXCHANGE_2007_SP1 + def __init__(self, **kwargs): + super().__init__(**kwargs) + if self._distinguished_id: + self._distinguished_id.mailbox = None # See DistinguishedFolderId.clean() + def get_children(self, folder): # EWS does not allow deep traversal of public folders, so self._folders_map will only populate the top-level # subfolders. To traverse public folders at arbitrary depth, we need to get child folders on demand. @@ -507,6 +513,11 @@

    Inherited members

    DEFAULT_FOLDER_TRAVERSAL_DEPTH = SHALLOW supported_from = EXCHANGE_2007_SP1 + def __init__(self, **kwargs): + super().__init__(**kwargs) + if self._distinguished_id: + self._distinguished_id.mailbox = None # See DistinguishedFolderId.clean() + def get_children(self, folder): # EWS does not allow deep traversal of public folders, so self._folders_map will only populate the top-level # subfolders. To traverse public folders at arbitrary depth, we need to get child folders on demand. @@ -894,25 +905,6 @@

    Inherited members

    if f.parent.id == folder.id: yield f - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - """ - if not cls.DISTINGUISHED_FOLDER_ID: - raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}") - def get_default_folder(self, folder_cls): """Return the distinguished folder instance of type folder_cls belonging to this account. If no distinguished folder was found, try as best we can to return the default folder of type 'folder_cls' @@ -929,16 +921,16 @@

    Inherited members

    return f try: log.debug("Requesting distinguished %s folder explicitly", folder_cls) - return folder_cls.get_distinguished(account=self.account) + return folder_cls.get_distinguished(root=self) except ErrorAccessDenied: # Maybe we just don't have GetFolder access? Try FindItem instead log.debug("Testing default %s folder with FindItem", folder_cls) fld = folder_cls( - root=self, _distinguished_id=DistinguishedFolderId( id=folder_cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=self.account.primary_smtp_address), ), + root=self, ) fld.test_access() return self._folders_map.get(fld.id, fld) # Use cached instance if available @@ -947,6 +939,23 @@

    Inherited members

    pass raise ErrorFolderNotFound(f"No usable default {folder_cls} folders") + @classmethod + def get_distinguished(cls, account): + """Get the distinguished folder for this folder class. + + :param account: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=account.primary_smtp_address), + ), + account=account, + ) + ) + @property def _folders_map(self): if self._subfolders is not None: @@ -957,9 +966,12 @@

    Inherited members

    # so we are sure to apply the correct Folder class, then fetch all sub-folders of this root. folders_map = {self.id: self} distinguished_folders = [ - DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=self.account.primary_smtp_address), + cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=self.account.primary_smtp_address), + ), + root=self, ) for cls in self.WELLKNOWN_FOLDERS if cls.get_folder_allowed and cls.supports_version(self.account.version) @@ -1139,7 +1151,8 @@

    Static methods

    Get the distinguished folder for this folder class.

    -

    :param account:

    +

    :param account: +:return:

    Expand source code @@ -1149,19 +1162,17 @@

    Static methods

    """Get the distinguished folder for this folder class. :param account: + :return: """ - if not cls.DISTINGUISHED_FOLDER_ID: - raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( id=cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=account.primary_smtp_address), ), + account=account, ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}") + )
    @@ -1246,16 +1257,16 @@

    Methods

    return f try: log.debug("Requesting distinguished %s folder explicitly", folder_cls) - return folder_cls.get_distinguished(account=self.account) + return folder_cls.get_distinguished(root=self) except ErrorAccessDenied: # Maybe we just don't have GetFolder access? Try FindItem instead log.debug("Testing default %s folder with FindItem", folder_cls) fld = folder_cls( - root=self, _distinguished_id=DistinguishedFolderId( id=folder_cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=self.account.primary_smtp_address), ), + root=self, ) fld.test_access() return self._folders_map.get(fld.id, fld) # Use cached instance if available diff --git a/docs/exchangelib/index.html b/docs/exchangelib/index.html index 6d8252d1..f1539a2f 100644 --- a/docs/exchangelib/index.html +++ b/docs/exchangelib/index.html @@ -64,7 +64,7 @@

    Package exchangelib

    from .transport import BASIC, CBA, DIGEST, GSSAPI, NTLM, OAUTH2, SSPI from .version import Build, Version -__version__ = "5.2.1" +__version__ = "5.3.0" __all__ = [ "__version__", @@ -5018,7 +5018,7 @@

    Instance variables

    ) department = TextField(field_uri="contacts:Department") generation = TextField(field_uri="contacts:Generation") - im_addresses = CharField(field_uri="contacts:ImAddresses", is_read_only=True) + im_addresses = ImAddressField(field_uri="contacts:ImAddress") job_title = TextField(field_uri="contacts:JobTitle") manager = TextField(field_uri="contacts:Manager") mileage = TextField(field_uri="contacts:Mileage") @@ -7292,7 +7292,7 @@

    Inherited members

    if parent.root != self.root: raise ValueError("'parent.root' must match 'root'") else: - self.root = parent.root + self._root = parent.root if "parent_folder_id" in kwargs and parent.id != kwargs["parent_folder_id"]: raise ValueError("'parent_folder_id' must match 'parent' ID") kwargs["parent_folder_id"] = ParentFolderId(id=parent.id, changekey=parent.changekey) @@ -7308,10 +7308,6 @@

    Inherited members

    def root(self): return self._root - @root.setter - def root(self, value): - self._root = value - @classmethod def register(cls, *args, **kwargs): if cls is not Folder: @@ -7324,24 +7320,6 @@

    Inherited members

    raise TypeError("For folders, custom fields must be registered on the Folder class") return super().deregister(*args, **kwargs) - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - :return: - """ - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r}") - @property def parent(self): if not self.parent_folder_id: @@ -7358,7 +7336,7 @@

    Inherited members

    else: if not isinstance(value, BaseFolder): raise InvalidTypeError("value", value, BaseFolder) - self.root = value.root + self._root = value.root self.parent_folder_id = ParentFolderId(id=value.id, changekey=value.changekey) def clean(self, version=None): @@ -7368,6 +7346,23 @@

    Inherited members

    if self.root and not isinstance(self.root, RootOfHierarchy): raise InvalidTypeError("root", self.root, RootOfHierarchy) + @classmethod + def get_distinguished(cls, root): + """Get the distinguished folder for this folder class. + + :param root: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=root.account.primary_smtp_address), + ), + root=root, + ) + ) + @classmethod def from_xml_with_root(cls, elem, root): folder = cls.from_xml(elem=elem, account=root.account) @@ -7490,33 +7485,32 @@

    Static methods

    -def get_distinguished(account) +def get_distinguished(root)

    Get the distinguished folder for this folder class.

    -

    :param account: +

    :param root: :return:

    Expand source code
    @classmethod
    -def get_distinguished(cls, account):
    +def get_distinguished(cls, root):
         """Get the distinguished folder for this folder class.
     
    -    :param account:
    +    :param root:
         :return:
         """
    -    try:
    -        return cls.resolve(
    -            account=account,
    -            folder=DistinguishedFolderId(
    +    return cls._get_distinguished(
    +        folder=cls(
    +            _distinguished_id=DistinguishedFolderId(
                     id=cls.DISTINGUISHED_FOLDER_ID,
    -                mailbox=Mailbox(email_address=account.primary_smtp_address),
    +                mailbox=Mailbox(email_address=root.account.primary_smtp_address),
                 ),
    +            root=root,
             )
    -    except MISSING_FOLDER_ERRORS:
    -        raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID!r}")
    + )
    @@ -11865,25 +11859,6 @@

    Inherited members

    if f.parent.id == folder.id: yield f - @classmethod - def get_distinguished(cls, account): - """Get the distinguished folder for this folder class. - - :param account: - """ - if not cls.DISTINGUISHED_FOLDER_ID: - raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=account.primary_smtp_address), - ), - ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}") - def get_default_folder(self, folder_cls): """Return the distinguished folder instance of type folder_cls belonging to this account. If no distinguished folder was found, try as best we can to return the default folder of type 'folder_cls' @@ -11900,16 +11875,16 @@

    Inherited members

    return f try: log.debug("Requesting distinguished %s folder explicitly", folder_cls) - return folder_cls.get_distinguished(account=self.account) + return folder_cls.get_distinguished(root=self) except ErrorAccessDenied: # Maybe we just don't have GetFolder access? Try FindItem instead log.debug("Testing default %s folder with FindItem", folder_cls) fld = folder_cls( - root=self, _distinguished_id=DistinguishedFolderId( id=folder_cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=self.account.primary_smtp_address), ), + root=self, ) fld.test_access() return self._folders_map.get(fld.id, fld) # Use cached instance if available @@ -11918,6 +11893,23 @@

    Inherited members

    pass raise ErrorFolderNotFound(f"No usable default {folder_cls} folders") + @classmethod + def get_distinguished(cls, account): + """Get the distinguished folder for this folder class. + + :param account: + :return: + """ + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=account.primary_smtp_address), + ), + account=account, + ) + ) + @property def _folders_map(self): if self._subfolders is not None: @@ -11928,9 +11920,12 @@

    Inherited members

    # so we are sure to apply the correct Folder class, then fetch all sub-folders of this root. folders_map = {self.id: self} distinguished_folders = [ - DistinguishedFolderId( - id=cls.DISTINGUISHED_FOLDER_ID, - mailbox=Mailbox(email_address=self.account.primary_smtp_address), + cls( + _distinguished_id=DistinguishedFolderId( + id=cls.DISTINGUISHED_FOLDER_ID, + mailbox=Mailbox(email_address=self.account.primary_smtp_address), + ), + root=self, ) for cls in self.WELLKNOWN_FOLDERS if cls.get_folder_allowed and cls.supports_version(self.account.version) @@ -12110,7 +12105,8 @@

    Static methods

    Get the distinguished folder for this folder class.

    -

    :param account:

    +

    :param account: +:return:

    Expand source code @@ -12120,19 +12116,17 @@

    Static methods

    """Get the distinguished folder for this folder class. :param account: + :return: """ - if not cls.DISTINGUISHED_FOLDER_ID: - raise ValueError(f"Class {cls} must have a DISTINGUISHED_FOLDER_ID value") - try: - return cls.resolve( - account=account, - folder=DistinguishedFolderId( + return cls._get_distinguished( + folder=cls( + _distinguished_id=DistinguishedFolderId( id=cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=account.primary_smtp_address), ), + account=account, ) - except MISSING_FOLDER_ERRORS: - raise ErrorFolderNotFound(f"Could not find distinguished folder {cls.DISTINGUISHED_FOLDER_ID}") + )
    @@ -12217,16 +12211,16 @@

    Methods

    return f try: log.debug("Requesting distinguished %s folder explicitly", folder_cls) - return folder_cls.get_distinguished(account=self.account) + return folder_cls.get_distinguished(root=self) except ErrorAccessDenied: # Maybe we just don't have GetFolder access? Try FindItem instead log.debug("Testing default %s folder with FindItem", folder_cls) fld = folder_cls( - root=self, _distinguished_id=DistinguishedFolderId( id=folder_cls.DISTINGUISHED_FOLDER_ID, mailbox=Mailbox(email_address=self.account.primary_smtp_address), ), + root=self, ) fld.test_access() return self._folders_map.get(fld.id, fld) # Use cached instance if available diff --git a/docs/exchangelib/indexed_properties.html b/docs/exchangelib/indexed_properties.html index 797430b5..201fef0a 100644 --- a/docs/exchangelib/indexed_properties.html +++ b/docs/exchangelib/indexed_properties.html @@ -61,6 +61,16 @@

    Module exchangelib.indexed_properties

    email = EmailSubField(is_required=True) +class ImAddress(SingleFieldIndexedElement): + """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/entry-imaddress""" + + ELEMENT_NAME = "Entry" + LABEL_CHOICES = ("ImAddress1", "ImAddress2", "ImAddress3") + + label = LabelField(field_uri="Key", choices={Choice(c) for c in LABEL_CHOICES}, default=LABEL_CHOICES[0]) + im_address = SubField(is_required=True) + + class PhoneNumber(SingleFieldIndexedElement): """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/entry-phonenumber""" @@ -186,6 +196,69 @@

    Inherited members

    +
    +class ImAddress +(**kwargs) +
    +
    + +
    + +Expand source code + +
    class ImAddress(SingleFieldIndexedElement):
    +    """MSDN: https://docs.microsoft.com/en-us/exchange/client-developer/web-service-reference/entry-imaddress"""
    +
    +    ELEMENT_NAME = "Entry"
    +    LABEL_CHOICES = ("ImAddress1", "ImAddress2", "ImAddress3")
    +
    +    label = LabelField(field_uri="Key", choices={Choice(c) for c in LABEL_CHOICES}, default=LABEL_CHOICES[0])
    +    im_address = SubField(is_required=True)
    +
    +

    Ancestors

    + +

    Class variables

    +
    +
    var ELEMENT_NAME
    +
    +
    +
    +
    var FIELDS
    +
    +
    +
    +
    var LABEL_CHOICES
    +
    +
    +
    +
    +

    Instance variables

    +
    +
    var im_address
    +
    +
    +
    +
    var label
    +
    +
    +
    +
    +

    Inherited members

    + +
    class IndexedElement (**kwargs) @@ -480,6 +553,7 @@

    Ancestors

    Subclasses

    Static methods

    @@ -541,6 +615,16 @@

    ImAddress

    + + +
  • IndexedElement

    • LABEL_CHOICES
    • @@ -589,4 +673,4 @@

      Generated by pdoc 0.10.0.

      - \ No newline at end of file + diff --git a/docs/exchangelib/items/contact.html b/docs/exchangelib/items/contact.html index 5af9f3b9..03769056 100644 --- a/docs/exchangelib/items/contact.html +++ b/docs/exchangelib/items/contact.html @@ -44,6 +44,7 @@

      Module exchangelib.items.contact

      EWSElementField, EWSElementListField, IdElementField, + ImAddressField, MailboxField, MailboxListField, MemberListField, @@ -114,7 +115,7 @@

      Module exchangelib.items.contact

      ) department = TextField(field_uri="contacts:Department") generation = TextField(field_uri="contacts:Generation") - im_addresses = CharField(field_uri="contacts:ImAddresses", is_read_only=True) + im_addresses = ImAddressField(field_uri="contacts:ImAddress") job_title = TextField(field_uri="contacts:JobTitle") manager = TextField(field_uri="contacts:Manager") mileage = TextField(field_uri="contacts:Mileage") @@ -363,7 +364,7 @@

      Classes

      ) department = TextField(field_uri="contacts:Department") generation = TextField(field_uri="contacts:Generation") - im_addresses = CharField(field_uri="contacts:ImAddresses", is_read_only=True) + im_addresses = ImAddressField(field_uri="contacts:ImAddress") job_title = TextField(field_uri="contacts:JobTitle") manager = TextField(field_uri="contacts:Manager") mileage = TextField(field_uri="contacts:Mileage") diff --git a/docs/exchangelib/items/index.html b/docs/exchangelib/items/index.html index 008cc1f0..bed3b10f 100644 --- a/docs/exchangelib/items/index.html +++ b/docs/exchangelib/items/index.html @@ -1236,7 +1236,7 @@

      Inherited members

      ) department = TextField(field_uri="contacts:Department") generation = TextField(field_uri="contacts:Generation") - im_addresses = CharField(field_uri="contacts:ImAddresses", is_read_only=True) + im_addresses = ImAddressField(field_uri="contacts:ImAddress") job_title = TextField(field_uri="contacts:JobTitle") manager = TextField(field_uri="contacts:Manager") mileage = TextField(field_uri="contacts:Mileage") diff --git a/docs/exchangelib/properties.html b/docs/exchangelib/properties.html index a181f509..97ded4ff 100644 --- a/docs/exchangelib/properties.html +++ b/docs/exchangelib/properties.html @@ -790,6 +790,8 @@

      Module exchangelib.properties

      if self.id == PublicFoldersRoot.DISTINGUISHED_FOLDER_ID: # Avoid "ErrorInvalidOperation: It is not valid to specify a mailbox with the public folder root" from EWS self.mailbox = None + elif not self.mailbox: + raise ValueError(f"DistinguishedFolderId {self.id} must have a mailbox") class TimeWindow(EWSElement): @@ -4903,7 +4905,9 @@

      Inherited members

      super().clean(version=version) if self.id == PublicFoldersRoot.DISTINGUISHED_FOLDER_ID: # Avoid "ErrorInvalidOperation: It is not valid to specify a mailbox with the public folder root" from EWS - self.mailbox = None
      + self.mailbox = None + elif not self.mailbox: + raise ValueError(f"DistinguishedFolderId {self.id} must have a mailbox")

      Ancestors

        @@ -4964,7 +4968,9 @@

        Methods

        super().clean(version=version) if self.id == PublicFoldersRoot.DISTINGUISHED_FOLDER_ID: # Avoid "ErrorInvalidOperation: It is not valid to specify a mailbox with the public folder root" from EWS - self.mailbox = None + self.mailbox = None + elif not self.mailbox: + raise ValueError(f"DistinguishedFolderId {self.id} must have a mailbox") diff --git a/docs/exchangelib/services/common.html b/docs/exchangelib/services/common.html index 05ba0f22..1d22fc85 100644 --- a/docs/exchangelib/services/common.html +++ b/docs/exchangelib/services/common.html @@ -66,18 +66,9 @@

        Module exchangelib.services.common

        SOAPError, TransportError, ) -from ..folders import ArchiveRoot, BaseFolder, Folder, PublicFoldersRoot, Root, RootOfHierarchy +from ..folders import BaseFolder, Folder, RootOfHierarchy from ..items import BaseItem -from ..properties import ( - BaseItemId, - DistinguishedFolderId, - ExceptionFieldURI, - ExtendedFieldURI, - FieldURI, - FolderId, - IndexedFieldURI, - ItemId, -) +from ..properties import BaseItemId, ExceptionFieldURI, ExtendedFieldURI, FieldURI, FolderId, IndexedFieldURI, ItemId from ..transport import DEFAULT_ENCODING from ..util import ( ENS, @@ -618,6 +609,7 @@

        Module exchangelib.services.common

        # Raise any non-acceptable errors in the container, or return the container or the acceptable exception instance msg_text = get_xml_attr(message, f"{{{MNS}}}MessageText") msg_xml = message.find(f"{{{MNS}}}MessageXml") + rule_errors = message.find(f"{{{MNS}}}RuleOperationErrors") if response_class == "Warning": try: raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml) @@ -631,12 +623,12 @@

        Module exchangelib.services.common

        return container # response_class == 'Error', or 'Success' and not 'NoError' try: - raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml) + raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml, rule_errors=rule_errors) except self.ERRORS_TO_CATCH_IN_RESPONSE as e: return e @staticmethod - def _get_exception(code, text, msg_xml): + def _get_exception(code, text, msg_xml=None, rule_errors=None): """Parse error messages contained in EWS responses and raise as exceptions defined in this package.""" if not code: return TransportError(f"Empty ResponseCode in ResponseMessage (MessageText: {text}, MessageXml: {msg_xml})") @@ -674,6 +666,13 @@

        Module exchangelib.services.common

        except KeyError: # Inner code is unknown to us. Just append to the original text text += f" (inner error: {inner_code}({inner_text!r}))" + if rule_errors is not None: + for rule_error in rule_errors.findall(f"{{{TNS}}}RuleOperationError"): + for error in rule_error.find(f"{{{TNS}}}ValidationErrors").findall(f"{{{TNS}}}Error"): + field_uri = get_xml_attr(error, f"{{{TNS}}}FieldURI") + error_code = get_xml_attr(error, f"{{{TNS}}}ErrorCode") + error_message = get_xml_attr(error, f"{{{TNS}}}ErrorMessage") + text += f" ({error_code} on field {field_uri}: {error_message})" try: # Raise the error corresponding to the ResponseCode return vars(errors)[code](text) @@ -998,30 +997,12 @@

        Module exchangelib.services.common

        return _ids_element(items, AttachmentId, version, tag) -def parse_folder_elem(elem, folder, account): +def parse_folder_elem(elem, folder): if isinstance(folder, RootOfHierarchy): - f = folder.from_xml(elem=elem, account=folder.account) - elif isinstance(folder, Folder): - f = folder.from_xml_with_root(elem=elem, root=folder.root) - elif isinstance(folder, DistinguishedFolderId): - # We don't know the root or even account, but we need to attach the folder to something if we want to make - # future requests with this folder. Use 'account' but make sure to always use the distinguished folder ID going - # forward, instead of referencing anything connected to 'account'. - roots = (Root, ArchiveRoot, PublicFoldersRoot) - for cls in roots + tuple(chain(*(r.WELLKNOWN_FOLDERS for r in roots))): - if cls.DISTINGUISHED_FOLDER_ID == folder.id: - folder_cls = cls - break - else: - raise ValueError(f"Unknown distinguished folder ID: {folder.id}") - if folder_cls in roots: - f = folder_cls.from_xml(elem=elem, account=account) - else: - f = folder_cls.from_xml_with_root(elem=elem, root=account.root) - else: - # 'folder' is a generic FolderId instance. We don't know the root so assume account.root. - f = Folder.from_xml_with_root(elem=elem, root=account.root) - return f + return folder.from_xml(elem=elem, account=folder.account) + if isinstance(folder, Folder): + return folder.from_xml_with_root(elem=elem, root=folder.root) + raise ValueError(f"Unsupported folder class: {folder}")
        @@ -1071,7 +1052,7 @@

        Functions

        -def parse_folder_elem(elem, folder, account) +def parse_folder_elem(elem, folder)
        @@ -1079,30 +1060,12 @@

        Functions

        Expand source code -
        def parse_folder_elem(elem, folder, account):
        +
        def parse_folder_elem(elem, folder):
             if isinstance(folder, RootOfHierarchy):
        -        f = folder.from_xml(elem=elem, account=folder.account)
        -    elif isinstance(folder, Folder):
        -        f = folder.from_xml_with_root(elem=elem, root=folder.root)
        -    elif isinstance(folder, DistinguishedFolderId):
        -        # We don't know the root or even account, but we need to attach the folder to something if we want to make
        -        # future requests with this folder. Use 'account' but make sure to always use the distinguished folder ID going
        -        # forward, instead of referencing anything connected to 'account'.
        -        roots = (Root, ArchiveRoot, PublicFoldersRoot)
        -        for cls in roots + tuple(chain(*(r.WELLKNOWN_FOLDERS for r in roots))):
        -            if cls.DISTINGUISHED_FOLDER_ID == folder.id:
        -                folder_cls = cls
        -                break
        -        else:
        -            raise ValueError(f"Unknown distinguished folder ID: {folder.id}")
        -        if folder_cls in roots:
        -            f = folder_cls.from_xml(elem=elem, account=account)
        -        else:
        -            f = folder_cls.from_xml_with_root(elem=elem, root=account.root)
        -    else:
        -        # 'folder' is a generic FolderId instance. We don't know the root so assume account.root.
        -        f = Folder.from_xml_with_root(elem=elem, root=account.root)
        -    return f
        + return folder.from_xml(elem=elem, account=folder.account) + if isinstance(folder, Folder): + return folder.from_xml_with_root(elem=elem, root=folder.root) + raise ValueError(f"Unsupported folder class: {folder}")
        @@ -2017,6 +1980,7 @@

        Inherited members

        # Raise any non-acceptable errors in the container, or return the container or the acceptable exception instance msg_text = get_xml_attr(message, f"{{{MNS}}}MessageText") msg_xml = message.find(f"{{{MNS}}}MessageXml") + rule_errors = message.find(f"{{{MNS}}}RuleOperationErrors") if response_class == "Warning": try: raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml) @@ -2030,12 +1994,12 @@

        Inherited members

        return container # response_class == 'Error', or 'Success' and not 'NoError' try: - raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml) + raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml, rule_errors=rule_errors) except self.ERRORS_TO_CATCH_IN_RESPONSE as e: return e @staticmethod - def _get_exception(code, text, msg_xml): + def _get_exception(code, text, msg_xml=None, rule_errors=None): """Parse error messages contained in EWS responses and raise as exceptions defined in this package.""" if not code: return TransportError(f"Empty ResponseCode in ResponseMessage (MessageText: {text}, MessageXml: {msg_xml})") @@ -2073,6 +2037,13 @@

        Inherited members

        except KeyError: # Inner code is unknown to us. Just append to the original text text += f" (inner error: {inner_code}({inner_text!r}))" + if rule_errors is not None: + for rule_error in rule_errors.findall(f"{{{TNS}}}RuleOperationError"): + for error in rule_error.find(f"{{{TNS}}}ValidationErrors").findall(f"{{{TNS}}}Error"): + field_uri = get_xml_attr(error, f"{{{TNS}}}FieldURI") + error_code = get_xml_attr(error, f"{{{TNS}}}ErrorCode") + error_message = get_xml_attr(error, f"{{{TNS}}}ErrorMessage") + text += f" ({error_code} on field {field_uri}: {error_message})" try: # Raise the error corresponding to the ResponseCode return vars(errors)[code](text) diff --git a/docs/exchangelib/services/create_folder.html b/docs/exchangelib/services/create_folder.html index 887cfbda..3f40c723 100644 --- a/docs/exchangelib/services/create_folder.html +++ b/docs/exchangelib/services/create_folder.html @@ -59,7 +59,7 @@

        Module exchangelib.services.create_folder

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) def get_payload(self, folders, parent_folder): payload = create_element(f"m:{self.SERVICE_NAME}") @@ -120,7 +120,7 @@

        Classes

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) def get_payload(self, folders, parent_folder): payload = create_element(f"m:{self.SERVICE_NAME}") diff --git a/docs/exchangelib/services/get_folder.html b/docs/exchangelib/services/get_folder.html index 33454a4a..b9afda0e 100644 --- a/docs/exchangelib/services/get_folder.html +++ b/docs/exchangelib/services/get_folder.html @@ -80,7 +80,7 @@

        Module exchangelib.services.get_folder

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) def get_payload(self, folders, additional_fields, shape): payload = create_element(f"m:{self.SERVICE_NAME}") @@ -155,7 +155,7 @@

        Classes

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) def get_payload(self, folders, additional_fields, shape): payload = create_element(f"m:{self.SERVICE_NAME}") diff --git a/docs/exchangelib/services/get_user_settings.html b/docs/exchangelib/services/get_user_settings.html index 339f8d40..83745e5d 100644 --- a/docs/exchangelib/services/get_user_settings.html +++ b/docs/exchangelib/services/get_user_settings.html @@ -114,7 +114,7 @@

        Module exchangelib.services.get_user_settings

        @@ -216,7 +216,7 @@

        Classes

        return container # Raise any non-acceptable errors in the container, or return the acceptable exception instance try: - raise self._get_exception(code=res.error_code, text=res.error_message, msg_xml=None) + raise self._get_exception(code=res.error_code, text=res.error_message) except self.ERRORS_TO_CATCH_IN_RESPONSE as e: return e
        diff --git a/docs/exchangelib/services/index.html b/docs/exchangelib/services/index.html index 53555cf9..7d9aa443 100644 --- a/docs/exchangelib/services/index.html +++ b/docs/exchangelib/services/index.html @@ -797,7 +797,7 @@

        Inherited members

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) def get_payload(self, folders, parent_folder): payload = create_element(f"m:{self.SERVICE_NAME}") @@ -2234,6 +2234,7 @@

        Inherited members

        # Raise any non-acceptable errors in the container, or return the container or the acceptable exception instance msg_text = get_xml_attr(message, f"{{{MNS}}}MessageText") msg_xml = message.find(f"{{{MNS}}}MessageXml") + rule_errors = message.find(f"{{{MNS}}}RuleOperationErrors") if response_class == "Warning": try: raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml) @@ -2247,12 +2248,12 @@

        Inherited members

        return container # response_class == 'Error', or 'Success' and not 'NoError' try: - raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml) + raise self._get_exception(code=response_code, text=msg_text, msg_xml=msg_xml, rule_errors=rule_errors) except self.ERRORS_TO_CATCH_IN_RESPONSE as e: return e @staticmethod - def _get_exception(code, text, msg_xml): + def _get_exception(code, text, msg_xml=None, rule_errors=None): """Parse error messages contained in EWS responses and raise as exceptions defined in this package.""" if not code: return TransportError(f"Empty ResponseCode in ResponseMessage (MessageText: {text}, MessageXml: {msg_xml})") @@ -2290,6 +2291,13 @@

        Inherited members

        except KeyError: # Inner code is unknown to us. Just append to the original text text += f" (inner error: {inner_code}({inner_text!r}))" + if rule_errors is not None: + for rule_error in rule_errors.findall(f"{{{TNS}}}RuleOperationError"): + for error in rule_error.find(f"{{{TNS}}}ValidationErrors").findall(f"{{{TNS}}}Error"): + field_uri = get_xml_attr(error, f"{{{TNS}}}FieldURI") + error_code = get_xml_attr(error, f"{{{TNS}}}ErrorCode") + error_message = get_xml_attr(error, f"{{{TNS}}}ErrorMessage") + text += f" ({error_code} on field {field_uri}: {error_message})" try: # Raise the error corresponding to the ResponseCode return vars(errors)[code](text) @@ -4103,7 +4111,7 @@

        Inherited members

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) def get_payload(self, folders, additional_fields, shape): payload = create_element(f"m:{self.SERVICE_NAME}") @@ -5750,7 +5758,7 @@

        Inherited members

        return container # Raise any non-acceptable errors in the container, or return the acceptable exception instance try: - raise self._get_exception(code=res.error_code, text=res.error_message, msg_xml=None) + raise self._get_exception(code=res.error_code, text=res.error_message) except self.ERRORS_TO_CATCH_IN_RESPONSE as e: return e @@ -7079,7 +7087,7 @@

        Inherited members

        # We can't find() the element because we don't know which tag to look for. The change element can # contain multiple folder types, each with their own tag. folder_elem = elem[0] - folder = parse_folder_elem(elem=folder_elem, folder=self.folder, account=self.account) + folder = parse_folder_elem(elem=folder_elem, folder=self.folder) return change_type, folder def get_payload(self, folder, shape, additional_fields, sync_state): @@ -7487,7 +7495,7 @@

        Inherited members

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) @staticmethod def _target_elem(target): diff --git a/docs/exchangelib/services/sync_folder_hierarchy.html b/docs/exchangelib/services/sync_folder_hierarchy.html index d487a96b..4661aa43 100644 --- a/docs/exchangelib/services/sync_folder_hierarchy.html +++ b/docs/exchangelib/services/sync_folder_hierarchy.html @@ -114,7 +114,7 @@

        Module exchangelib.services.sync_folder_hierarchy # We can't find() the element because we don't know which tag to look for. The change element can # contain multiple folder types, each with their own tag. folder_elem = elem[0] - folder = parse_folder_elem(elem=folder_elem, folder=self.folder, account=self.account) + folder = parse_folder_elem(elem=folder_elem, folder=self.folder) return change_type, folder def get_payload(self, folder, shape, additional_fields, sync_state): @@ -290,7 +290,7 @@

        Inherited members

        # We can't find() the element because we don't know which tag to look for. The change element can # contain multiple folder types, each with their own tag. folder_elem = elem[0] - folder = parse_folder_elem(elem=folder_elem, folder=self.folder, account=self.account) + folder = parse_folder_elem(elem=folder_elem, folder=self.folder) return change_type, folder def get_payload(self, folder, shape, additional_fields, sync_state): diff --git a/docs/exchangelib/services/update_folder.html b/docs/exchangelib/services/update_folder.html index 8dae3d15..6323aaac 100644 --- a/docs/exchangelib/services/update_folder.html +++ b/docs/exchangelib/services/update_folder.html @@ -172,7 +172,7 @@

        Module exchangelib.services.update_folder

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) @staticmethod def _target_elem(target): @@ -396,7 +396,7 @@

        Inherited members

        if isinstance(elem, Exception): yield elem continue - yield parse_folder_elem(elem=elem, folder=folder, account=self.account) + yield parse_folder_elem(elem=elem, folder=folder) @staticmethod def _target_elem(target): diff --git a/docs/exchangelib/util.html b/docs/exchangelib/util.html index f0df38d6..666efd08 100644 --- a/docs/exchangelib/util.html +++ b/docs/exchangelib/util.html @@ -212,7 +212,7 @@

        Module exchangelib.util

        def value_to_xml_text(value): from .ewsdatetime import EWSDate, EWSDateTime, EWSTimeZone - from .indexed_properties import EmailAddress, PhoneNumber + from .indexed_properties import SingleFieldIndexedElement from .properties import AssociatedCalendarItemId, Attendee, ConversationId, Mailbox # We can't just create a map and look up with type(value) because we want to support subtypes @@ -228,21 +228,15 @@

        Module exchangelib.util

        return value.isoformat() if isinstance(value, EWSTimeZone): return value.ms_id - if isinstance(value, EWSDateTime): + if isinstance(value, (EWSDate, EWSDateTime)): return value.ewsformat() - if isinstance(value, EWSDate): - return value.ewsformat() - if isinstance(value, PhoneNumber): - return value.phone_number - if isinstance(value, EmailAddress): - return value.email + if isinstance(value, SingleFieldIndexedElement): + return getattr(value, value.value_field(version=None).name) if isinstance(value, Mailbox): return value.email_address if isinstance(value, Attendee): return value.mailbox.email_address - if isinstance(value, ConversationId): - return value.id - if isinstance(value, AssociatedCalendarItemId): + if isinstance(value, (ConversationId, AssociatedCalendarItemId)): return value.id raise TypeError(f"Unsupported type: {type(value)} ({value})") @@ -1580,7 +1574,7 @@

        Functions

        def value_to_xml_text(value):
             from .ewsdatetime import EWSDate, EWSDateTime, EWSTimeZone
        -    from .indexed_properties import EmailAddress, PhoneNumber
        +    from .indexed_properties import SingleFieldIndexedElement
             from .properties import AssociatedCalendarItemId, Attendee, ConversationId, Mailbox
         
             # We can't just create a map and look up with type(value) because we want to support subtypes
        @@ -1596,21 +1590,15 @@ 

        Functions

        return value.isoformat() if isinstance(value, EWSTimeZone): return value.ms_id - if isinstance(value, EWSDateTime): + if isinstance(value, (EWSDate, EWSDateTime)): return value.ewsformat() - if isinstance(value, EWSDate): - return value.ewsformat() - if isinstance(value, PhoneNumber): - return value.phone_number - if isinstance(value, EmailAddress): - return value.email + if isinstance(value, SingleFieldIndexedElement): + return getattr(value, value.value_field(version=None).name) if isinstance(value, Mailbox): return value.email_address if isinstance(value, Attendee): return value.mailbox.email_address - if isinstance(value, ConversationId): - return value.id - if isinstance(value, AssociatedCalendarItemId): + if isinstance(value, (ConversationId, AssociatedCalendarItemId)): return value.id raise TypeError(f"Unsupported type: {type(value)} ({value})")
        diff --git a/pyproject.toml b/pyproject.toml index e391c9b3..0064c682 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,7 +3,7 @@ # * Bump version in exchangelib/__init__.py # * Bump version in CHANGELOG.md # * Generate documentation: -# rm -r docs/exchangelib && pdoc3 --html exchangelib -o docs --force && pre-commit run end-of-file-fixer +# rm -r docs/exchangelib && pdoc3 --html exchangelib -o docs --force && git add docs && pre-commit run end-of-file-fixer # * Commit and push changes # * Build package: # rm -rf build dist exchangelib.egg-info && python -m build