Skip to content

Commit

Permalink
Retrieve "details" within a single GetItem request
Browse files Browse the repository at this point in the history
Thanks to @got-root for this suggestion!
  • Loading branch information
Eric Matthews committed Oct 15, 2014
1 parent abf312b commit d8bdf1d
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 17 deletions.
7 changes: 4 additions & 3 deletions docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -181,8 +181,9 @@ Listing events
To list events between two dates, simply do:

events = my_calendar.list_events(
start=datetime(2014,10,1,11,0,0, tzinfo=timezone("US/Eastern")),
end=datetime(2014,10,29,11,0,0, tzinfo=timezone("US/Eastern"))
start=datetime(2014, 10, 1, 11, 0, 0, tzinfo=timezone("US/Eastern")),
end=datetime(2014, 10, 29, 11, 0, 0, tzinfo=timezone("US/Eastern")),
details=True
)

This will return a list of Event objects that are between start and end. If no results are found, it will return an empty list (it intentionally will not throw an Exception.)
Expand All @@ -194,7 +195,7 @@ This will return a list of Event objects that are between start and end. If no r
subject=event.subject
)

The default response will have most of the data populated in the Event object. It will not have full details for Organizer or Attendees, due to the response provided by Exchange. If you would like to populate all of these details, call the load_all_details() function, such as:
The third argument, 'details', is optional. By default (if details is not specified, or details=False), it will return most of the fields within an event. The full details for the Organizer or Attendees field are not populated by default by Exchange. If these fields are required in your usage, then pass details=True with the request to make a second lookup for these values. The further details can also be loaded after the fact using the load_all_details() function, as below:

events = my_calendar.list_events(start, end)
events.load_all_details()
Expand Down
49 changes: 37 additions & 12 deletions pyexchange/exchange2010/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -88,25 +88,37 @@ def get_event(self, id):
def new_event(self, **properties):
return Exchange2010CalendarEvent(service=self.service, calendar_id=self.calendar_id, **properties)

def list_events(self, start=None, end=None):
return Exchange2010CalendarEventList(service=self.service, start=start, end=end)
def list_events(self, start=None, end=None, details=False):
return Exchange2010CalendarEventList(service=self.service, start=start, end=end, details=details)


class Exchange2010CalendarEventList(object):
"""
Creates & Stores a list of Exchange2010CalendarEvent items in the "self.events" variable.
"""
def __init__(self, service=None, start=None, end=None):
def __init__(self, service=None, start=None, end=None, details=False):
self.service = service
self.count = 0
self.start = start
self.end = end
self.events = list()
self.event_ids = list()
self.details = details

body = soap_request.get_items(format=u'AllProperties', start=self.start, end=self.end)
# This request uses a Calendar-specific query between two dates.
body = soap_request.get_calendar_items(format=u'AllProperties', start=self.start, end=self.end)
response_xml = self.service.send(body)

self._parse_response_for_all_events(response_xml)

# Populate the event ID list, for convenience reasons.
for event in self.events:
self.event_ids.append(event._id)

# If we have requested all the details, basically repeat the previous 3 steps,
# but instead of start/stop, we have a list of ID fields.
if self.details:
log.debug(u'Received request for all details, retrieving now!')
self.load_all_details()
return

def _parse_response_for_all_events(self, response):
Expand All @@ -120,6 +132,11 @@ def _parse_response_for_all_events(self, response):
log.debug(u'Found %s items' % self.count)

for item in calendar_items:
# Skip matches of CalendarItem that are contained within other CalenderItems, particularly
# the fact that "<CalendarItem>" tags are located within "<ConflictingMeetings>"
if item.getparent().tag.endswith('ConflictingMeetings'):
continue

self._add_event(xml=item)
else:
log.debug(u'No calendar items found with search parameters.')
Expand All @@ -140,13 +157,19 @@ def load_all_details(self):
This is intended for use when you want to have a completely populated event entry, including
Organizer & Attendee details.
"""
log.debug(u"Loading all details")
if self.count > 0:
new_event_list = list()
for event in self.events:
new_event_list.append(Exchange2010CalendarEvent(service=self.service, id=event._id))

self.events = new_event_list

# Now, empty out the events to prevent duplicates!
del(self.events[:])

# Send the SOAP request with the list of exchange ID values.
log.debug(u"Requesting all event details for events: {event_list}".format(event_list=str(self.event_ids)))
body = soap_request.get_item(exchange_id=self.event_ids, format=u'AllProperties')
response_xml = self.service.send(body)

# Re-parse the results for all the details!
self._parse_response_for_all_events(response_xml)

return self


Expand All @@ -171,8 +194,10 @@ def _init_from_xml(self, xml=None):
log.debug(u'Creating new Exchange2010CalendarEvent object from XML')
self.xpath_root = u'.'
properties = self._parse_event_properties(xml)

self._update_properties(properties)
self._id = xml.xpath(u'//t:ItemId/@Id', namespaces=soap_request.NAMESPACES)[0]
self._id = xml.xpath(u'./t:ItemId/@Id', namespaces=soap_request.NAMESPACES)[0]

log.debug(u'Created new event object with ID: %s' % self._id)
self._reset_dirty_attributes()

Expand Down
11 changes: 9 additions & 2 deletions pyexchange/exchange2010/soap_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -97,17 +97,24 @@ def get_item(exchange_id, format=u"Default"):
"""

elements = list()
if type(exchange_id) == list:
for item in exchange_id:
elements.append(T.ItemId(Id=item))
else:
elements = [T.ItemId(Id=exchange_id)]

root = M.GetItem(
M.ItemShape(
T.BaseShape(format)
),
M.ItemIds(
T.ItemId(Id=exchange_id)
*elements
)
)
return root

def get_items(format=u"Default", start=None, end=None, max_entries=999999):
def get_calendar_items(format=u"Default", start=None, end=None, max_entries=999999):
start = start.strftime(EXCHANGE_DATE_FORMAT)
end = end.strftime(EXCHANGE_DATE_FORMAT)

Expand Down

0 comments on commit d8bdf1d

Please sign in to comment.