Skip to content

Commit

Permalink
Clear elem after parsing. Improves memory usage
Browse files Browse the repository at this point in the history
  • Loading branch information
Erik Cederstrand authored and Erik Cederstrand committed Dec 15, 2016
1 parent 644e557 commit 638995b
Showing 1 changed file with 28 additions and 9 deletions.
37 changes: 28 additions & 9 deletions exchangelib/folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,8 +156,9 @@ def from_xml(cls, elem):
if elem is None:
return None
assert elem.tag == cls.response_tag(), (cls, elem.tag, cls.response_tag())
return cls(name=elem.get(cls.NAME_ATTR), value=elem.text)

res = cls(name=elem.get(cls.NAME_ATTR), value=elem.text)
elem.clear()
return res

class ItemId(EWSElement):
# 'id' and 'changekey' are UUIDs generated by Exchange
Expand Down Expand Up @@ -188,7 +189,9 @@ def from_xml(cls, elem):
if elem is None:
return None
assert elem.tag == cls.response_tag(), (cls, elem.tag, cls.response_tag())
return cls(id=elem.get(cls.ID_ATTR), changekey=elem.get(cls.CHANGEKEY_ATTR))
res = cls(id=elem.get(cls.ID_ATTR), changekey=elem.get(cls.CHANGEKEY_ATTR))
elem.clear()
return res

def __eq__(self, other):
# A more efficient version of super().__eq__
Expand Down Expand Up @@ -266,11 +269,13 @@ def from_xml(cls, elem):
if elem is None:
return None
assert elem.tag == cls.response_tag(), (cls, elem.tag, cls.response_tag())
return cls(
res = cls(
id=elem.get(cls.ID_ATTR),
root_id=elem.get(cls.ROOT_ID_ATTR),
root_changekey=elem.get(cls.ROOT_CHANGEKEY_ATTR)
)
elem.clear()
return res


class Attachment(EWSElement):
Expand Down Expand Up @@ -360,6 +365,7 @@ def from_xml(cls, elem, parent_item=None):
# UTC, so mark them as such so EWSDateTime can still interpret the timestamps.
val += 'Z'
kwargs[field_name] = xml_text_to_value(value=val, field_type=field_type)
elem.clear()
return cls(parent_item=parent_item, **kwargs)

def attach(self):
Expand Down Expand Up @@ -452,10 +458,12 @@ def from_xml(cls, elem):
if elem is None:
return None
assert elem.tag == cls.response_tag(), (cls, elem.tag, cls.response_tag())
return cls(
res = cls(
label=elem.get('Key'),
email=elem.text or elem.get('Name'), # Sometimes elem.text is empty. Exchange saves the same in 'Name' attr
)
elem.clear()
return res


class PhoneNumber(IndexedField):
Expand Down Expand Up @@ -487,10 +495,12 @@ def from_xml(cls, elem):
if elem is None:
return None
assert elem.tag == cls.response_tag(), (cls, elem.tag, cls.response_tag())
return cls(
res = cls(
label=elem.get('Key'),
phone_number=elem.text,
)
elem.clear()
return res


class PhysicalAddress(IndexedField):
Expand Down Expand Up @@ -546,6 +556,7 @@ def from_xml(cls, elem):
kwargs = dict(label=elem.get('Key'))
for k, v in cls.SUB_FIELD_ELEMENT_NAMES.items():
kwargs[k] = get_xml_attr(elem, '{%s}%s' % (TNS, v))
elem.clear()
return cls(**kwargs)


Expand Down Expand Up @@ -590,12 +601,14 @@ def from_xml(cls, elem):
if elem is None:
return None
assert elem.tag == cls.response_tag(), (elem.tag, cls.response_tag())
return cls(
res = cls(
name=get_xml_attr(elem, '{%s}Name' % TNS),
email_address=get_xml_attr(elem, '{%s}EmailAddress' % TNS),
mailbox_type=get_xml_attr(elem, '{%s}MailboxType' % TNS),
item_id=ItemId.from_xml(elem=elem.find(ItemId.response_tag())),
)
elem.clear()
return res

def __hash__(self):
# Exchange may add 'mailbox_type' and 'name' on insert. We're satisfied if the item_id or email address matches.
Expand Down Expand Up @@ -625,12 +638,14 @@ def from_xml(cls, elem):
return None
assert elem.tag == cls.response_tag(), (elem.tag, cls.response_tag())
id_elem = elem.find('{%s}Id' % TNS)
return cls(
res = cls(
name=get_xml_attr(id_elem, '{%s}Name' % TNS),
email_address=get_xml_attr(id_elem, '{%s}EmailAddress' % TNS),
mailbox_type=get_xml_attr(id_elem, '{%s}MailboxType' % TNS),
item_id=ItemId.from_xml(elem=id_elem.find(ItemId.response_tag())),
)
elem.clear()
return res


class ExtendedProperty(EWSElement):
Expand Down Expand Up @@ -813,11 +828,13 @@ def from_xml(cls, elem):
return None
assert elem.tag == cls.response_tag(), (cls, elem.tag, cls.response_tag())
last_response_time = get_xml_attr(elem, '{%s}LastResponseTime' % TNS)
return cls(
res = cls(
mailbox=Mailbox.from_xml(elem=elem.find(Mailbox.response_tag())),
response_type=get_xml_attr(elem, '{%s}ResponseType' % TNS) or 'Unknown',
last_response_time=EWSDateTime.from_string(last_response_time) if last_response_time else None,
)
elem.clear()
return res

@classmethod
def set_field_xml(cls, field_elem, items, version):
Expand Down Expand Up @@ -1256,6 +1273,7 @@ def from_xml(cls, elem, account=None, folder=None):
kwargs[fieldname] = field_type.from_xml(sub_elem)
else:
assert False, 'Field %s type %s not supported' % (fieldname, field_type)
elem.clear()
return cls(item_id=item_id, changekey=changekey, account=account, folder=folder, **kwargs)

def __eq__(self, other):
Expand Down Expand Up @@ -2125,6 +2143,7 @@ def from_xml(cls, elem, account=None):
changekey = fld_id_elem.get(FolderId.CHANGEKEY_ATTR)
display_name = get_xml_attr(elem, '{%s}DisplayName' % TNS)
folder_class = get_xml_attr(elem, '{%s}FolderClass' % TNS)
elem.clear()
return cls(account=account, name=display_name, folder_class=folder_class, folder_id=fld_id, changekey=changekey)

def to_xml(self, version):
Expand Down

0 comments on commit 638995b

Please sign in to comment.