/gdata/calendar/__init__.py

http://radioappz.googlecode.com/ · Python · 1044 lines · 775 code · 169 blank · 100 comment · 75 complexity · aebdd96ddb094b4b7061eb56909b042a MD5 · raw file

  1. #!/usr/bin/python
  2. #
  3. # Copyright (C) 2006 Google Inc.
  4. #
  5. # Licensed under the Apache License, Version 2.0 (the "License");
  6. # you may not use this file except in compliance with the License.
  7. # You may obtain a copy of the License at
  8. #
  9. # http://www.apache.org/licenses/LICENSE-2.0
  10. #
  11. # Unless required by applicable law or agreed to in writing, software
  12. # distributed under the License is distributed on an "AS IS" BASIS,
  13. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14. # See the License for the specific language governing permissions and
  15. # limitations under the License.
  16. """Contains extensions to ElementWrapper objects used with Google Calendar."""
  17. __author__ = 'api.vli (Vivian Li), api.rboyd (Ryan Boyd)'
  18. try:
  19. from xml.etree import cElementTree as ElementTree
  20. except ImportError:
  21. try:
  22. import cElementTree as ElementTree
  23. except ImportError:
  24. try:
  25. from xml.etree import ElementTree
  26. except ImportError:
  27. from elementtree import ElementTree
  28. import atom
  29. import gdata
  30. # XML namespaces which are often used in Google Calendar entities.
  31. GCAL_NAMESPACE = 'http://schemas.google.com/gCal/2005'
  32. GCAL_TEMPLATE = '{http://schemas.google.com/gCal/2005}%s'
  33. WEB_CONTENT_LINK_REL = '%s/%s' % (GCAL_NAMESPACE, 'webContent')
  34. GACL_NAMESPACE = gdata.GACL_NAMESPACE
  35. GACL_TEMPLATE = gdata.GACL_TEMPLATE
  36. class ValueAttributeContainer(atom.AtomBase):
  37. """A parent class for all Calendar classes which have a value attribute.
  38. Children include Color, AccessLevel, Hidden
  39. """
  40. _children = atom.AtomBase._children.copy()
  41. _attributes = atom.AtomBase._attributes.copy()
  42. _attributes['value'] = 'value'
  43. def __init__(self, value=None, extension_elements=None,
  44. extension_attributes=None, text=None):
  45. self.value = value
  46. self.text = text
  47. self.extension_elements = extension_elements or []
  48. self.extension_attributes = extension_attributes or {}
  49. class Color(ValueAttributeContainer):
  50. """The Google Calendar color element"""
  51. _tag = 'color'
  52. _namespace = GCAL_NAMESPACE
  53. _children = ValueAttributeContainer._children.copy()
  54. _attributes = ValueAttributeContainer._attributes.copy()
  55. class AccessLevel(ValueAttributeContainer):
  56. """The Google Calendar accesslevel element"""
  57. _tag = 'accesslevel'
  58. _namespace = GCAL_NAMESPACE
  59. _children = ValueAttributeContainer._children.copy()
  60. _attributes = ValueAttributeContainer._attributes.copy()
  61. class Hidden(ValueAttributeContainer):
  62. """The Google Calendar hidden element"""
  63. _tag = 'hidden'
  64. _namespace = GCAL_NAMESPACE
  65. _children = ValueAttributeContainer._children.copy()
  66. _attributes = ValueAttributeContainer._attributes.copy()
  67. class Selected(ValueAttributeContainer):
  68. """The Google Calendar selected element"""
  69. _tag = 'selected'
  70. _namespace = GCAL_NAMESPACE
  71. _children = ValueAttributeContainer._children.copy()
  72. _attributes = ValueAttributeContainer._attributes.copy()
  73. class Timezone(ValueAttributeContainer):
  74. """The Google Calendar timezone element"""
  75. _tag = 'timezone'
  76. _namespace = GCAL_NAMESPACE
  77. _children = ValueAttributeContainer._children.copy()
  78. _attributes = ValueAttributeContainer._attributes.copy()
  79. class Where(atom.AtomBase):
  80. """The Google Calendar Where element"""
  81. _tag = 'where'
  82. _namespace = gdata.GDATA_NAMESPACE
  83. _children = atom.AtomBase._children.copy()
  84. _attributes = atom.AtomBase._attributes.copy()
  85. _attributes['valueString'] = 'value_string'
  86. def __init__(self, value_string=None, extension_elements=None,
  87. extension_attributes=None, text=None):
  88. self.value_string = value_string
  89. self.text = text
  90. self.extension_elements = extension_elements or []
  91. self.extension_attributes = extension_attributes or {}
  92. class CalendarListEntry(gdata.GDataEntry, gdata.LinkFinder):
  93. """A Google Calendar meta Entry flavor of an Atom Entry """
  94. _tag = gdata.GDataEntry._tag
  95. _namespace = gdata.GDataEntry._namespace
  96. _children = gdata.GDataEntry._children.copy()
  97. _attributes = gdata.GDataEntry._attributes.copy()
  98. _children['{%s}color' % GCAL_NAMESPACE] = ('color', Color)
  99. _children['{%s}accesslevel' % GCAL_NAMESPACE] = ('access_level',
  100. AccessLevel)
  101. _children['{%s}hidden' % GCAL_NAMESPACE] = ('hidden', Hidden)
  102. _children['{%s}selected' % GCAL_NAMESPACE] = ('selected', Selected)
  103. _children['{%s}timezone' % GCAL_NAMESPACE] = ('timezone', Timezone)
  104. _children['{%s}where' % gdata.GDATA_NAMESPACE] = ('where', Where)
  105. def __init__(self, author=None, category=None, content=None,
  106. atom_id=None, link=None, published=None,
  107. title=None, updated=None,
  108. color=None, access_level=None, hidden=None, timezone=None,
  109. selected=None,
  110. where=None,
  111. extension_elements=None, extension_attributes=None, text=None):
  112. gdata.GDataEntry.__init__(self, author=author, category=category,
  113. content=content, atom_id=atom_id, link=link,
  114. published=published, title=title,
  115. updated=updated, text=None)
  116. self.color = color
  117. self.access_level = access_level
  118. self.hidden = hidden
  119. self.selected = selected
  120. self.timezone = timezone
  121. self.where = where
  122. class CalendarListFeed(gdata.GDataFeed, gdata.LinkFinder):
  123. """A Google Calendar meta feed flavor of an Atom Feed"""
  124. _tag = gdata.GDataFeed._tag
  125. _namespace = gdata.GDataFeed._namespace
  126. _children = gdata.GDataFeed._children.copy()
  127. _attributes = gdata.GDataFeed._attributes.copy()
  128. _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [CalendarListEntry])
  129. class Scope(atom.AtomBase):
  130. """The Google ACL scope element"""
  131. _tag = 'scope'
  132. _namespace = GACL_NAMESPACE
  133. _children = atom.AtomBase._children.copy()
  134. _attributes = atom.AtomBase._attributes.copy()
  135. _attributes['value'] = 'value'
  136. _attributes['type'] = 'type'
  137. def __init__(self, extension_elements=None, value=None, scope_type=None,
  138. extension_attributes=None, text=None):
  139. self.value = value
  140. self.type = scope_type
  141. self.text = text
  142. self.extension_elements = extension_elements or []
  143. self.extension_attributes = extension_attributes or {}
  144. class Role(ValueAttributeContainer):
  145. """The Google Calendar timezone element"""
  146. _tag = 'role'
  147. _namespace = GACL_NAMESPACE
  148. _children = ValueAttributeContainer._children.copy()
  149. _attributes = ValueAttributeContainer._attributes.copy()
  150. class CalendarAclEntry(gdata.GDataEntry, gdata.LinkFinder):
  151. """A Google Calendar ACL Entry flavor of an Atom Entry """
  152. _tag = gdata.GDataEntry._tag
  153. _namespace = gdata.GDataEntry._namespace
  154. _children = gdata.GDataEntry._children.copy()
  155. _attributes = gdata.GDataEntry._attributes.copy()
  156. _children['{%s}scope' % GACL_NAMESPACE] = ('scope', Scope)
  157. _children['{%s}role' % GACL_NAMESPACE] = ('role', Role)
  158. def __init__(self, author=None, category=None, content=None,
  159. atom_id=None, link=None, published=None,
  160. title=None, updated=None,
  161. scope=None, role=None,
  162. extension_elements=None, extension_attributes=None, text=None):
  163. gdata.GDataEntry.__init__(self, author=author, category=category,
  164. content=content, atom_id=atom_id, link=link,
  165. published=published, title=title,
  166. updated=updated, text=None)
  167. self.scope = scope
  168. self.role = role
  169. class CalendarAclFeed(gdata.GDataFeed, gdata.LinkFinder):
  170. """A Google Calendar ACL feed flavor of an Atom Feed"""
  171. _tag = gdata.GDataFeed._tag
  172. _namespace = gdata.GDataFeed._namespace
  173. _children = gdata.GDataFeed._children.copy()
  174. _attributes = gdata.GDataFeed._attributes.copy()
  175. _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry', [CalendarAclEntry])
  176. class CalendarEventCommentEntry(gdata.GDataEntry, gdata.LinkFinder):
  177. """A Google Calendar event comments entry flavor of an Atom Entry"""
  178. _tag = gdata.GDataEntry._tag
  179. _namespace = gdata.GDataEntry._namespace
  180. _children = gdata.GDataEntry._children.copy()
  181. _attributes = gdata.GDataEntry._attributes.copy()
  182. class CalendarEventCommentFeed(gdata.GDataFeed, gdata.LinkFinder):
  183. """A Google Calendar event comments feed flavor of an Atom Feed"""
  184. _tag = gdata.GDataFeed._tag
  185. _namespace = gdata.GDataFeed._namespace
  186. _children = gdata.GDataFeed._children.copy()
  187. _attributes = gdata.GDataFeed._attributes.copy()
  188. _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry',
  189. [CalendarEventCommentEntry])
  190. class ExtendedProperty(gdata.ExtendedProperty):
  191. """A transparent subclass of gdata.ExtendedProperty added to this module
  192. for backwards compatibility."""
  193. class Reminder(atom.AtomBase):
  194. """The Google Calendar reminder element"""
  195. _tag = 'reminder'
  196. _namespace = gdata.GDATA_NAMESPACE
  197. _children = atom.AtomBase._children.copy()
  198. _attributes = atom.AtomBase._attributes.copy()
  199. _attributes['absoluteTime'] = 'absolute_time'
  200. _attributes['days'] = 'days'
  201. _attributes['hours'] = 'hours'
  202. _attributes['minutes'] = 'minutes'
  203. _attributes['method'] = 'method'
  204. def __init__(self, absolute_time=None,
  205. days=None, hours=None, minutes=None, method=None,
  206. extension_elements=None,
  207. extension_attributes=None, text=None):
  208. self.absolute_time = absolute_time
  209. if days is not None:
  210. self.days = str(days)
  211. else:
  212. self.days = None
  213. if hours is not None:
  214. self.hours = str(hours)
  215. else:
  216. self.hours = None
  217. if minutes is not None:
  218. self.minutes = str(minutes)
  219. else:
  220. self.minutes = None
  221. self.method = method
  222. self.text = text
  223. self.extension_elements = extension_elements or []
  224. self.extension_attributes = extension_attributes or {}
  225. class When(atom.AtomBase):
  226. """The Google Calendar When element"""
  227. _tag = 'when'
  228. _namespace = gdata.GDATA_NAMESPACE
  229. _children = atom.AtomBase._children.copy()
  230. _attributes = atom.AtomBase._attributes.copy()
  231. _children['{%s}reminder' % gdata.GDATA_NAMESPACE] = ('reminder', [Reminder])
  232. _attributes['startTime'] = 'start_time'
  233. _attributes['endTime'] = 'end_time'
  234. def __init__(self, start_time=None, end_time=None, reminder=None,
  235. extension_elements=None, extension_attributes=None, text=None):
  236. self.start_time = start_time
  237. self.end_time = end_time
  238. self.reminder = reminder or []
  239. self.text = text
  240. self.extension_elements = extension_elements or []
  241. self.extension_attributes = extension_attributes or {}
  242. class Recurrence(atom.AtomBase):
  243. """The Google Calendar Recurrence element"""
  244. _tag = 'recurrence'
  245. _namespace = gdata.GDATA_NAMESPACE
  246. _children = atom.AtomBase._children.copy()
  247. _attributes = atom.AtomBase._attributes.copy()
  248. class UriEnumElement(atom.AtomBase):
  249. _children = atom.AtomBase._children.copy()
  250. _attributes = atom.AtomBase._attributes.copy()
  251. def __init__(self, tag, enum_map, attrib_name='value',
  252. extension_elements=None, extension_attributes=None, text=None):
  253. self.tag=tag
  254. self.enum_map=enum_map
  255. self.attrib_name=attrib_name
  256. self.value=None
  257. self.text=text
  258. self.extension_elements = extension_elements or []
  259. self.extension_attributes = extension_attributes or {}
  260. def findKey(self, value):
  261. res=[item[0] for item in self.enum_map.items() if item[1] == value]
  262. if res is None or len(res) == 0:
  263. return None
  264. return res[0]
  265. def _ConvertElementAttributeToMember(self, attribute, value):
  266. # Special logic to use the enum_map to set the value of the object's value member.
  267. if attribute == self.attrib_name and value != '':
  268. self.value = self.enum_map[value]
  269. return
  270. # Find the attribute in this class's list of attributes.
  271. if self.__class__._attributes.has_key(attribute):
  272. # Find the member of this class which corresponds to the XML attribute
  273. # (lookup in current_class._attributes) and set this member to the
  274. # desired value (using self.__dict__).
  275. setattr(self, self.__class__._attributes[attribute], value)
  276. else:
  277. # The current class doesn't map this attribute, so try to parent class.
  278. atom.ExtensionContainer._ConvertElementAttributeToMember(self,
  279. attribute,
  280. value)
  281. def _AddMembersToElementTree(self, tree):
  282. # Convert the members of this class which are XML child nodes.
  283. # This uses the class's _children dictionary to find the members which
  284. # should become XML child nodes.
  285. member_node_names = [values[0] for tag, values in
  286. self.__class__._children.iteritems()]
  287. for member_name in member_node_names:
  288. member = getattr(self, member_name)
  289. if member is None:
  290. pass
  291. elif isinstance(member, list):
  292. for instance in member:
  293. instance._BecomeChildElement(tree)
  294. else:
  295. member._BecomeChildElement(tree)
  296. # Special logic to set the desired XML attribute.
  297. key = self.findKey(self.value)
  298. if key is not None:
  299. tree.attrib[self.attrib_name]=key
  300. # Convert the members of this class which are XML attributes.
  301. for xml_attribute, member_name in self.__class__._attributes.iteritems():
  302. member = getattr(self, member_name)
  303. if member is not None:
  304. tree.attrib[xml_attribute] = member
  305. # Lastly, call the parent's _AddMembersToElementTree to get any
  306. # extension elements.
  307. atom.ExtensionContainer._AddMembersToElementTree(self, tree)
  308. class AttendeeStatus(UriEnumElement):
  309. """The Google Calendar attendeeStatus element"""
  310. _tag = 'attendeeStatus'
  311. _namespace = gdata.GDATA_NAMESPACE
  312. _children = UriEnumElement._children.copy()
  313. _attributes = UriEnumElement._attributes.copy()
  314. attendee_enum = {
  315. 'http://schemas.google.com/g/2005#event.accepted' : 'ACCEPTED',
  316. 'http://schemas.google.com/g/2005#event.declined' : 'DECLINED',
  317. 'http://schemas.google.com/g/2005#event.invited' : 'INVITED',
  318. 'http://schemas.google.com/g/2005#event.tentative' : 'TENTATIVE'}
  319. def __init__(self, extension_elements=None,
  320. extension_attributes=None, text=None):
  321. UriEnumElement.__init__(self, 'attendeeStatus', AttendeeStatus.attendee_enum,
  322. extension_elements=extension_elements,
  323. extension_attributes=extension_attributes,
  324. text=text)
  325. class AttendeeType(UriEnumElement):
  326. """The Google Calendar attendeeType element"""
  327. _tag = 'attendeeType'
  328. _namespace = gdata.GDATA_NAMESPACE
  329. _children = UriEnumElement._children.copy()
  330. _attributes = UriEnumElement._attributes.copy()
  331. attendee_type_enum = {
  332. 'http://schemas.google.com/g/2005#event.optional' : 'OPTIONAL',
  333. 'http://schemas.google.com/g/2005#event.required' : 'REQUIRED' }
  334. def __init__(self, extension_elements=None,
  335. extension_attributes=None, text=None):
  336. UriEnumElement.__init__(self, 'attendeeType',
  337. AttendeeType.attendee_type_enum,
  338. extension_elements=extension_elements,
  339. extension_attributes=extension_attributes,text=text)
  340. class Visibility(UriEnumElement):
  341. """The Google Calendar Visibility element"""
  342. _tag = 'visibility'
  343. _namespace = gdata.GDATA_NAMESPACE
  344. _children = UriEnumElement._children.copy()
  345. _attributes = UriEnumElement._attributes.copy()
  346. visibility_enum = {
  347. 'http://schemas.google.com/g/2005#event.confidential' : 'CONFIDENTIAL',
  348. 'http://schemas.google.com/g/2005#event.default' : 'DEFAULT',
  349. 'http://schemas.google.com/g/2005#event.private' : 'PRIVATE',
  350. 'http://schemas.google.com/g/2005#event.public' : 'PUBLIC' }
  351. def __init__(self, extension_elements=None,
  352. extension_attributes=None, text=None):
  353. UriEnumElement.__init__(self, 'visibility', Visibility.visibility_enum,
  354. extension_elements=extension_elements,
  355. extension_attributes=extension_attributes,
  356. text=text)
  357. class Transparency(UriEnumElement):
  358. """The Google Calendar Transparency element"""
  359. _tag = 'transparency'
  360. _namespace = gdata.GDATA_NAMESPACE
  361. _children = UriEnumElement._children.copy()
  362. _attributes = UriEnumElement._attributes.copy()
  363. transparency_enum = {
  364. 'http://schemas.google.com/g/2005#event.opaque' : 'OPAQUE',
  365. 'http://schemas.google.com/g/2005#event.transparent' : 'TRANSPARENT' }
  366. def __init__(self, extension_elements=None,
  367. extension_attributes=None, text=None):
  368. UriEnumElement.__init__(self, tag='transparency',
  369. enum_map=Transparency.transparency_enum,
  370. extension_elements=extension_elements,
  371. extension_attributes=extension_attributes,
  372. text=text)
  373. class Comments(atom.AtomBase):
  374. """The Google Calendar comments element"""
  375. _tag = 'comments'
  376. _namespace = gdata.GDATA_NAMESPACE
  377. _children = atom.AtomBase._children.copy()
  378. _attributes = atom.AtomBase._attributes.copy()
  379. _children['{%s}feedLink' % gdata.GDATA_NAMESPACE] = ('feed_link',
  380. gdata.FeedLink)
  381. _attributes['rel'] = 'rel'
  382. def __init__(self, rel=None, feed_link=None, extension_elements=None,
  383. extension_attributes=None, text=None):
  384. self.rel = rel
  385. self.feed_link = feed_link
  386. self.text = text
  387. self.extension_elements = extension_elements or []
  388. self.extension_attributes = extension_attributes or {}
  389. class EventStatus(UriEnumElement):
  390. """The Google Calendar eventStatus element"""
  391. _tag = 'eventStatus'
  392. _namespace = gdata.GDATA_NAMESPACE
  393. _children = UriEnumElement._children.copy()
  394. _attributes = UriEnumElement._attributes.copy()
  395. status_enum = { 'http://schemas.google.com/g/2005#event.canceled' : 'CANCELED',
  396. 'http://schemas.google.com/g/2005#event.confirmed' : 'CONFIRMED',
  397. 'http://schemas.google.com/g/2005#event.tentative' : 'TENTATIVE'}
  398. def __init__(self, extension_elements=None,
  399. extension_attributes=None, text=None):
  400. UriEnumElement.__init__(self, tag='eventStatus',
  401. enum_map=EventStatus.status_enum,
  402. extension_elements=extension_elements,
  403. extension_attributes=extension_attributes,
  404. text=text)
  405. class Who(UriEnumElement):
  406. """The Google Calendar Who element"""
  407. _tag = 'who'
  408. _namespace = gdata.GDATA_NAMESPACE
  409. _children = UriEnumElement._children.copy()
  410. _attributes = UriEnumElement._attributes.copy()
  411. _children['{%s}attendeeStatus' % gdata.GDATA_NAMESPACE] = (
  412. 'attendee_status', AttendeeStatus)
  413. _children['{%s}attendeeType' % gdata.GDATA_NAMESPACE] = ('attendee_type',
  414. AttendeeType)
  415. _attributes['valueString'] = 'name'
  416. _attributes['email'] = 'email'
  417. relEnum = { 'http://schemas.google.com/g/2005#event.attendee' : 'ATTENDEE',
  418. 'http://schemas.google.com/g/2005#event.organizer' : 'ORGANIZER',
  419. 'http://schemas.google.com/g/2005#event.performer' : 'PERFORMER',
  420. 'http://schemas.google.com/g/2005#event.speaker' : 'SPEAKER',
  421. 'http://schemas.google.com/g/2005#message.bcc' : 'BCC',
  422. 'http://schemas.google.com/g/2005#message.cc' : 'CC',
  423. 'http://schemas.google.com/g/2005#message.from' : 'FROM',
  424. 'http://schemas.google.com/g/2005#message.reply-to' : 'REPLY_TO',
  425. 'http://schemas.google.com/g/2005#message.to' : 'TO' }
  426. def __init__(self, name=None, email=None, attendee_status=None,
  427. attendee_type=None, rel=None, extension_elements=None,
  428. extension_attributes=None, text=None):
  429. UriEnumElement.__init__(self, 'who', Who.relEnum, attrib_name='rel',
  430. extension_elements=extension_elements,
  431. extension_attributes=extension_attributes,
  432. text=text)
  433. self.name = name
  434. self.email = email
  435. self.attendee_status = attendee_status
  436. self.attendee_type = attendee_type
  437. self.rel = rel
  438. class OriginalEvent(atom.AtomBase):
  439. """The Google Calendar OriginalEvent element"""
  440. _tag = 'originalEvent'
  441. _namespace = gdata.GDATA_NAMESPACE
  442. _children = atom.AtomBase._children.copy()
  443. _attributes = atom.AtomBase._attributes.copy()
  444. # TODO: The when tag used to map to a EntryLink, make sure it should really be a When.
  445. _children['{%s}when' % gdata.GDATA_NAMESPACE] = ('when', When)
  446. _attributes['id'] = 'id'
  447. _attributes['href'] = 'href'
  448. def __init__(self, id=None, href=None, when=None,
  449. extension_elements=None, extension_attributes=None, text=None):
  450. self.id = id
  451. self.href = href
  452. self.when = when
  453. self.text = text
  454. self.extension_elements = extension_elements or []
  455. self.extension_attributes = extension_attributes or {}
  456. def GetCalendarEventEntryClass():
  457. return CalendarEventEntry
  458. # This class is not completely defined here, because of a circular reference
  459. # in which CalendarEventEntryLink and CalendarEventEntry refer to one another.
  460. class CalendarEventEntryLink(gdata.EntryLink):
  461. """An entryLink which contains a calendar event entry
  462. Within an event's recurranceExceptions, an entry link
  463. points to a calendar event entry. This class exists
  464. to capture the calendar specific extensions in the entry.
  465. """
  466. _tag = 'entryLink'
  467. _namespace = gdata.GDATA_NAMESPACE
  468. _children = gdata.EntryLink._children.copy()
  469. _attributes = gdata.EntryLink._attributes.copy()
  470. # The CalendarEventEntryLink should like CalendarEventEntry as a child but
  471. # that class hasn't been defined yet, so we will wait until after defining
  472. # CalendarEventEntry to list it in _children.
  473. class RecurrenceException(atom.AtomBase):
  474. """The Google Calendar RecurrenceException element"""
  475. _tag = 'recurrenceException'
  476. _namespace = gdata.GDATA_NAMESPACE
  477. _children = atom.AtomBase._children.copy()
  478. _attributes = atom.AtomBase._attributes.copy()
  479. _children['{%s}entryLink' % gdata.GDATA_NAMESPACE] = ('entry_link',
  480. CalendarEventEntryLink)
  481. _children['{%s}originalEvent' % gdata.GDATA_NAMESPACE] = ('original_event',
  482. OriginalEvent)
  483. _attributes['specialized'] = 'specialized'
  484. def __init__(self, specialized=None, entry_link=None,
  485. original_event=None, extension_elements=None,
  486. extension_attributes=None, text=None):
  487. self.specialized = specialized
  488. self.entry_link = entry_link
  489. self.original_event = original_event
  490. self.text = text
  491. self.extension_elements = extension_elements or []
  492. self.extension_attributes = extension_attributes or {}
  493. class SendEventNotifications(atom.AtomBase):
  494. """The Google Calendar sendEventNotifications element"""
  495. _tag = 'sendEventNotifications'
  496. _namespace = GCAL_NAMESPACE
  497. _children = atom.AtomBase._children.copy()
  498. _attributes = atom.AtomBase._attributes.copy()
  499. _attributes['value'] = 'value'
  500. def __init__(self, extension_elements=None,
  501. value=None, extension_attributes=None, text=None):
  502. self.value = value
  503. self.text = text
  504. self.extension_elements = extension_elements or []
  505. self.extension_attributes = extension_attributes or {}
  506. class QuickAdd(atom.AtomBase):
  507. """The Google Calendar quickadd element"""
  508. _tag = 'quickadd'
  509. _namespace = GCAL_NAMESPACE
  510. _children = atom.AtomBase._children.copy()
  511. _attributes = atom.AtomBase._attributes.copy()
  512. _attributes['value'] = 'value'
  513. def __init__(self, extension_elements=None,
  514. value=None, extension_attributes=None, text=None):
  515. self.value = value
  516. self.text = text
  517. self.extension_elements = extension_elements or []
  518. self.extension_attributes = extension_attributes or {}
  519. def _TransferToElementTree(self, element_tree):
  520. if self.value:
  521. element_tree.attrib['value'] = self.value
  522. element_tree.tag = GCAL_TEMPLATE % 'quickadd'
  523. atom.AtomBase._TransferToElementTree(self, element_tree)
  524. return element_tree
  525. def _TakeAttributeFromElementTree(self, attribute, element_tree):
  526. if attribute == 'value':
  527. self.value = element_tree.attrib[attribute]
  528. del element_tree.attrib[attribute]
  529. else:
  530. atom.AtomBase._TakeAttributeFromElementTree(self, attribute,
  531. element_tree)
  532. class SyncEvent(atom.AtomBase):
  533. _tag = 'syncEvent'
  534. _namespace = GCAL_NAMESPACE
  535. _children = atom.AtomBase._children.copy()
  536. _attributes = atom.AtomBase._attributes.copy()
  537. _attributes['value'] = 'value'
  538. def __init__(self, value='false', extension_elements=None,
  539. extension_attributes=None, text=None):
  540. self.value = value
  541. self.text = text
  542. self.extension_elements = extension_elements or []
  543. self.extension_attributes = extension_attributes or {}
  544. class UID(atom.AtomBase):
  545. _tag = 'uid'
  546. _namespace = GCAL_NAMESPACE
  547. _children = atom.AtomBase._children.copy()
  548. _attributes = atom.AtomBase._attributes.copy()
  549. _attributes['value'] = 'value'
  550. def __init__(self, value=None, extension_elements=None,
  551. extension_attributes=None, text=None):
  552. self.value = value
  553. self.text = text
  554. self.extension_elements = extension_elements or []
  555. self.extension_attributes = extension_attributes or {}
  556. class Sequence(atom.AtomBase):
  557. _tag = 'sequence'
  558. _namespace = GCAL_NAMESPACE
  559. _children = atom.AtomBase._children.copy()
  560. _attributes = atom.AtomBase._attributes.copy()
  561. _attributes['value'] = 'value'
  562. def __init__(self, value=None, extension_elements=None,
  563. extension_attributes=None, text=None):
  564. self.value = value
  565. self.text = text
  566. self.extension_elements = extension_elements or []
  567. self.extension_attributes = extension_attributes or {}
  568. class WebContentGadgetPref(atom.AtomBase):
  569. _tag = 'webContentGadgetPref'
  570. _namespace = GCAL_NAMESPACE
  571. _children = atom.AtomBase._children.copy()
  572. _attributes = atom.AtomBase._attributes.copy()
  573. _attributes['name'] = 'name'
  574. _attributes['value'] = 'value'
  575. """The Google Calendar Web Content Gadget Preferences element"""
  576. def __init__(self, name=None, value=None, extension_elements=None,
  577. extension_attributes=None, text=None):
  578. self.name = name
  579. self.value = value
  580. self.text = text
  581. self.extension_elements = extension_elements or []
  582. self.extension_attributes = extension_attributes or {}
  583. class WebContent(atom.AtomBase):
  584. _tag = 'webContent'
  585. _namespace = GCAL_NAMESPACE
  586. _children = atom.AtomBase._children.copy()
  587. _attributes = atom.AtomBase._attributes.copy()
  588. _children['{%s}webContentGadgetPref' % GCAL_NAMESPACE] = ('gadget_pref',
  589. [WebContentGadgetPref])
  590. _attributes['url'] = 'url'
  591. _attributes['width'] = 'width'
  592. _attributes['height'] = 'height'
  593. def __init__(self, url=None, width=None, height=None, text=None,
  594. gadget_pref=None, extension_elements=None, extension_attributes=None):
  595. self.url = url
  596. self.width = width
  597. self.height = height
  598. self.text = text
  599. self.gadget_pref = gadget_pref or []
  600. self.extension_elements = extension_elements or []
  601. self.extension_attributes = extension_attributes or {}
  602. class WebContentLink(atom.Link):
  603. _tag = 'link'
  604. _namespace = atom.ATOM_NAMESPACE
  605. _children = atom.Link._children.copy()
  606. _attributes = atom.Link._attributes.copy()
  607. _children['{%s}webContent' % GCAL_NAMESPACE] = ('web_content', WebContent)
  608. def __init__(self, title=None, href=None, link_type=None,
  609. web_content=None):
  610. atom.Link.__init__(self, rel=WEB_CONTENT_LINK_REL, title=title, href=href,
  611. link_type=link_type)
  612. self.web_content = web_content
  613. class GuestsCanInviteOthers(atom.AtomBase):
  614. """Indicates whether event attendees may invite others to the event.
  615. This element may only be changed by the organizer of the event. If not
  616. included as part of the event entry, this element will default to true
  617. during a POST request, and will inherit its previous value during a PUT
  618. request.
  619. """
  620. _tag = 'guestsCanInviteOthers'
  621. _namespace = GCAL_NAMESPACE
  622. _attributes = atom.AtomBase._attributes.copy()
  623. _attributes['value'] = 'value'
  624. def __init__(self, value='true', *args, **kwargs):
  625. atom.AtomBase.__init__(self, *args, **kwargs)
  626. self.value = value
  627. class GuestsCanSeeGuests(atom.AtomBase):
  628. """Indicates whether attendees can see other people invited to the event.
  629. The organizer always sees all attendees. Guests always see themselves. This
  630. property affects what attendees see in the event's guest list via both the
  631. Calendar UI and API feeds.
  632. This element may only be changed by the organizer of the event.
  633. If not included as part of the event entry, this element will default to
  634. true during a POST request, and will inherit its previous value during a
  635. PUT request.
  636. """
  637. _tag = 'guestsCanSeeGuests'
  638. _namespace = GCAL_NAMESPACE
  639. _attributes = atom.AtomBase._attributes.copy()
  640. _attributes['value'] = 'value'
  641. def __init__(self, value='true', *args, **kwargs):
  642. atom.AtomBase.__init__(self, *args, **kwargs)
  643. self.value = value
  644. class GuestsCanModify(atom.AtomBase):
  645. """Indicates whether event attendees may modify the original event.
  646. If yes, changes are visible to organizer and other attendees. Otherwise,
  647. any changes made by attendees will be restricted to that attendee's
  648. calendar.
  649. This element may only be changed by the organizer of the event, and may
  650. be set to 'true' only if both gCal:guestsCanInviteOthers and
  651. gCal:guestsCanSeeGuests are set to true in the same PUT/POST request.
  652. Otherwise, request fails with HTTP error code 400 (Bad Request).
  653. If not included as part of the event entry, this element will default to
  654. false during a POST request, and will inherit its previous value during a
  655. PUT request."""
  656. _tag = 'guestsCanModify'
  657. _namespace = GCAL_NAMESPACE
  658. _attributes = atom.AtomBase._attributes.copy()
  659. _attributes['value'] = 'value'
  660. def __init__(self, value='false', *args, **kwargs):
  661. atom.AtomBase.__init__(self, *args, **kwargs)
  662. self.value = value
  663. class CalendarEventEntry(gdata.BatchEntry):
  664. """A Google Calendar flavor of an Atom Entry """
  665. _tag = gdata.BatchEntry._tag
  666. _namespace = gdata.BatchEntry._namespace
  667. _children = gdata.BatchEntry._children.copy()
  668. _attributes = gdata.BatchEntry._attributes.copy()
  669. # This class also contains WebContentLinks but converting those members
  670. # is handled in a special version of _ConvertElementTreeToMember.
  671. _children['{%s}where' % gdata.GDATA_NAMESPACE] = ('where', [Where])
  672. _children['{%s}when' % gdata.GDATA_NAMESPACE] = ('when', [When])
  673. _children['{%s}who' % gdata.GDATA_NAMESPACE] = ('who', [Who])
  674. _children['{%s}extendedProperty' % gdata.GDATA_NAMESPACE] = (
  675. 'extended_property', [ExtendedProperty])
  676. _children['{%s}visibility' % gdata.GDATA_NAMESPACE] = ('visibility',
  677. Visibility)
  678. _children['{%s}transparency' % gdata.GDATA_NAMESPACE] = ('transparency',
  679. Transparency)
  680. _children['{%s}eventStatus' % gdata.GDATA_NAMESPACE] = ('event_status',
  681. EventStatus)
  682. _children['{%s}recurrence' % gdata.GDATA_NAMESPACE] = ('recurrence',
  683. Recurrence)
  684. _children['{%s}recurrenceException' % gdata.GDATA_NAMESPACE] = (
  685. 'recurrence_exception', [RecurrenceException])
  686. _children['{%s}sendEventNotifications' % GCAL_NAMESPACE] = (
  687. 'send_event_notifications', SendEventNotifications)
  688. _children['{%s}quickadd' % GCAL_NAMESPACE] = ('quick_add', QuickAdd)
  689. _children['{%s}comments' % gdata.GDATA_NAMESPACE] = ('comments', Comments)
  690. _children['{%s}originalEvent' % gdata.GDATA_NAMESPACE] = ('original_event',
  691. OriginalEvent)
  692. _children['{%s}sequence' % GCAL_NAMESPACE] = ('sequence', Sequence)
  693. _children['{%s}reminder' % gdata.GDATA_NAMESPACE] = ('reminder', [Reminder])
  694. _children['{%s}syncEvent' % GCAL_NAMESPACE] = ('sync_event', SyncEvent)
  695. _children['{%s}uid' % GCAL_NAMESPACE] = ('uid', UID)
  696. _children['{%s}guestsCanInviteOthers' % GCAL_NAMESPACE] = (
  697. 'guests_can_invite_others', GuestsCanInviteOthers)
  698. _children['{%s}guestsCanModify' % GCAL_NAMESPACE] = (
  699. 'guests_can_modify', GuestsCanModify)
  700. _children['{%s}guestsCanSeeGuests' % GCAL_NAMESPACE] = (
  701. 'guests_can_see_guests', GuestsCanSeeGuests)
  702. def __init__(self, author=None, category=None, content=None,
  703. atom_id=None, link=None, published=None,
  704. title=None, updated=None,
  705. transparency=None, comments=None, event_status=None,
  706. send_event_notifications=None, visibility=None,
  707. recurrence=None, recurrence_exception=None,
  708. where=None, when=None, who=None, quick_add=None,
  709. extended_property=None, original_event=None,
  710. batch_operation=None, batch_id=None, batch_status=None,
  711. sequence=None, reminder=None, sync_event=None, uid=None,
  712. guests_can_invite_others=None, guests_can_modify=None,
  713. guests_can_see_guests=None,
  714. extension_elements=None, extension_attributes=None, text=None):
  715. gdata.BatchEntry.__init__(self, author=author, category=category,
  716. content=content,
  717. atom_id=atom_id, link=link, published=published,
  718. batch_operation=batch_operation, batch_id=batch_id,
  719. batch_status=batch_status,
  720. title=title, updated=updated)
  721. self.transparency = transparency
  722. self.comments = comments
  723. self.event_status = event_status
  724. self.send_event_notifications = send_event_notifications
  725. self.visibility = visibility
  726. self.recurrence = recurrence
  727. self.recurrence_exception = recurrence_exception or []
  728. self.where = where or []
  729. self.when = when or []
  730. self.who = who or []
  731. self.quick_add = quick_add
  732. self.extended_property = extended_property or []
  733. self.original_event = original_event
  734. self.sequence = sequence
  735. self.reminder = reminder or []
  736. self.sync_event = sync_event
  737. self.uid = uid
  738. self.text = text
  739. self.guests_can_invite_others = guests_can_invite_others
  740. self.guests_can_modify = guests_can_modify
  741. self.guests_can_see_guests = guests_can_see_guests
  742. self.extension_elements = extension_elements or []
  743. self.extension_attributes = extension_attributes or {}
  744. # We needed to add special logic to _ConvertElementTreeToMember because we
  745. # want to make links with a rel of WEB_CONTENT_LINK_REL into a
  746. # WebContentLink
  747. def _ConvertElementTreeToMember(self, child_tree):
  748. # Special logic to handle Web Content links
  749. if (child_tree.tag == '{%s}link' % atom.ATOM_NAMESPACE and
  750. child_tree.attrib['rel'] == WEB_CONTENT_LINK_REL):
  751. if self.link is None:
  752. self.link = []
  753. self.link.append(atom._CreateClassFromElementTree(WebContentLink,
  754. child_tree))
  755. return
  756. # Find the element's tag in this class's list of child members
  757. if self.__class__._children.has_key(child_tree.tag):
  758. member_name = self.__class__._children[child_tree.tag][0]
  759. member_class = self.__class__._children[child_tree.tag][1]
  760. # If the class member is supposed to contain a list, make sure the
  761. # matching member is set to a list, then append the new member
  762. # instance to the list.
  763. if isinstance(member_class, list):
  764. if getattr(self, member_name) is None:
  765. setattr(self, member_name, [])
  766. getattr(self, member_name).append(atom._CreateClassFromElementTree(
  767. member_class[0], child_tree))
  768. else:
  769. setattr(self, member_name,
  770. atom._CreateClassFromElementTree(member_class, child_tree))
  771. else:
  772. atom.ExtensionContainer._ConvertElementTreeToMember(self, child_tree)
  773. def GetWebContentLink(self):
  774. """Finds the first link with rel set to WEB_CONTENT_REL
  775. Returns:
  776. A gdata.calendar.WebContentLink or none if none of the links had rel
  777. equal to WEB_CONTENT_REL
  778. """
  779. for a_link in self.link:
  780. if a_link.rel == WEB_CONTENT_LINK_REL:
  781. return a_link
  782. return None
  783. def CalendarEventEntryFromString(xml_string):
  784. return atom.CreateClassFromXMLString(CalendarEventEntry, xml_string)
  785. def CalendarEventCommentEntryFromString(xml_string):
  786. return atom.CreateClassFromXMLString(CalendarEventCommentEntry, xml_string)
  787. CalendarEventEntryLink._children = {'{%s}entry' % atom.ATOM_NAMESPACE:
  788. ('entry', CalendarEventEntry)}
  789. def CalendarEventEntryLinkFromString(xml_string):
  790. return atom.CreateClassFromXMLString(CalendarEventEntryLink, xml_string)
  791. class CalendarEventFeed(gdata.BatchFeed, gdata.LinkFinder):
  792. """A Google Calendar event feed flavor of an Atom Feed"""
  793. _tag = gdata.BatchFeed._tag
  794. _namespace = gdata.BatchFeed._namespace
  795. _children = gdata.BatchFeed._children.copy()
  796. _attributes = gdata.BatchFeed._attributes.copy()
  797. _children['{%s}entry' % atom.ATOM_NAMESPACE] = ('entry',
  798. [CalendarEventEntry])
  799. _children['{%s}timezone' % GCAL_NAMESPACE] = ('timezone', Timezone)
  800. def __init__(self, author=None, category=None, contributor=None,
  801. generator=None, icon=None, atom_id=None, link=None, logo=None,
  802. rights=None, subtitle=None, title=None, updated=None, entry=None,
  803. total_results=None, start_index=None, items_per_page=None,
  804. interrupted=None, timezone=None,
  805. extension_elements=None, extension_attributes=None, text=None):
  806. gdata.BatchFeed.__init__(self, author=author, category=category,
  807. contributor=contributor, generator=generator,
  808. icon=icon, atom_id=atom_id, link=link,
  809. logo=logo, rights=rights, subtitle=subtitle,
  810. title=title, updated=updated, entry=entry,
  811. total_results=total_results,
  812. start_index=start_index,
  813. items_per_page=items_per_page,
  814. interrupted=interrupted,
  815. extension_elements=extension_elements,
  816. extension_attributes=extension_attributes,
  817. text=text)
  818. self.timezone = timezone
  819. def CalendarListEntryFromString(xml_string):
  820. return atom.CreateClassFromXMLString(CalendarListEntry, xml_string)
  821. def CalendarAclEntryFromString(xml_string):
  822. return atom.CreateClassFromXMLString(CalendarAclEntry, xml_string)
  823. def CalendarListFeedFromString(xml_string):
  824. return atom.CreateClassFromXMLString(CalendarListFeed, xml_string)
  825. def CalendarAclFeedFromString(xml_string):
  826. return atom.CreateClassFromXMLString(CalendarAclFeed, xml_string)
  827. def CalendarEventFeedFromString(xml_string):
  828. return atom.CreateClassFromXMLString(CalendarEventFeed, xml_string)
  829. def CalendarEventCommentFeedFromString(xml_string):
  830. return atom.CreateClassFromXMLString(CalendarEventCommentFeed, xml_string)