Skip to content

Commit

Permalink
Raise proper exceptions if an ExtendedProperty class definition is in…
Browse files Browse the repository at this point in the history
…valid. Check when Item.register() is called. Refs #282
  • Loading branch information
ecederstrand committed Nov 7, 2017
1 parent 4732ef7 commit 21d93eb
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 21 deletions.
70 changes: 49 additions & 21 deletions exchangelib/extended_properties.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,30 +79,58 @@ def __init__(self, *args, **kwargs):
self.value = kwargs.pop('value')
super(ExtendedProperty, self).__init__(**kwargs)

def clean(self, version=None):
if self.distinguished_property_set_id:
assert not any([self.property_set_id, self.property_tag])
assert any([self.property_id, self.property_name])
assert self.distinguished_property_set_id in self.DISTINGUISHED_SETS
if self.property_set_id:
assert not any([self.distinguished_property_set_id, self.property_tag])
assert any([self.property_id, self.property_name])
if self.property_tag:
assert not any([
self.distinguished_property_set_id, self.property_set_id, self.property_name, self.property_id
])
if 0x8000 <= self.property_tag_as_int() <= 0xFFFE:
@classmethod
def validate_cls(cls):
# Validate values of class attributes and their inter-dependencies
if cls.distinguished_property_set_id:
if any([cls.property_set_id, cls.property_tag]):
raise ValueError(
"When 'distinguished_property_set_id' is set, 'property_set_id' and 'property_tag' must be None"
)
if not any([cls.property_id, cls.property_name]):
raise ValueError(
"When 'distinguished_property_set_id' is set, 'property_id' or 'property_name' must also be set"
)
assert cls.distinguished_property_set_id in cls.DISTINGUISHED_SETS
if cls.property_set_id:
if any([cls.distinguished_property_set_id, cls.property_tag]):
raise ValueError(
"When 'property_set_id' is set, 'distinguished_property_set_id' and 'property_tag' must be None"
)
if not any([cls.property_id, cls.property_name]):
raise ValueError(
"'property_tag' value '%s' is reserved for custom properties" % self.property_tag_as_hex()
"When 'property_set_id' is set, 'property_id' or 'property_name' must also be set"
)
if self.property_name:
assert not any([self.property_id, self.property_tag])
assert any([self.distinguished_property_set_id, self.property_set_id])
if self.property_id:
assert not any([self.property_name, self.property_tag])
assert any([self.distinguished_property_set_id, self.property_set_id])
assert self.property_type in self.PROPERTY_TYPES
if cls.property_tag:
if any([
cls.distinguished_property_set_id, cls.property_set_id, cls.property_name, cls.property_id
]):
raise ValueError("When 'property_tag' is set, only 'property_type' must be set")
if 0x8000 <= cls.property_tag_as_int() <= 0xFFFE:
raise ValueError(
"'property_tag' value '%s' is reserved for custom properties" % cls.property_tag_as_hex()
)
if cls.property_name:
if any([cls.property_id, cls.property_tag]):
raise ValueError("When 'property_name' is set, 'property_id' and 'property_tag' must be None")
if not any([cls.distinguished_property_set_id, cls.property_set_id]):
raise ValueError(
"When 'property_name' is set, 'distinguished_property_set_id' or 'property_set_id' must also be set"
)
if cls.property_id:
if any([cls.property_name, cls.property_tag]):
raise ValueError("When 'property_id' is set, 'property_name' and 'property_tag' must be None")
if not any([cls.distinguished_property_set_id, cls.property_set_id]):
raise ValueError(
"When 'property_id' is set, 'distinguished_property_set_id' or 'property_set_id' must also be set"
)
if cls.property_type not in cls.PROPERTY_TYPES:
raise ValueError(
"'property_type' value '%s' must be one of %s" % (cls.property_type, sorted(cls.PROPERTY_TYPES))
)

def clean(self, version=None):
self.validate_cls()
python_type = self.python_type()
if self.is_array_type():
if not is_iterable(self.value):
Expand Down
2 changes: 2 additions & 0 deletions exchangelib/items.py
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,8 @@ def register(cls, attr_name, attr_cls):
raise ValueError("'%s' is already registered" % attr_name)
if not issubclass(attr_cls, ExtendedProperty):
raise ValueError("'%s' must be a subclass of ExtendedProperty" % attr_cls)
# Check if class attributes are properly defined
attr_cls.validate_cls()
# ExtendedProperty is not a real field, but a placeholder in the fields list. See
# https://msdn.microsoft.com/en-us/library/office/aa580790(v=exchg.150).aspx
#
Expand Down

0 comments on commit 21d93eb

Please sign in to comment.