Updated presence stanza with documentation and PEP8 style.

This commit is contained in:
Lance Stout 2010-08-03 17:30:34 -04:00
parent 939ae298c2
commit 41ab2b8460
2 changed files with 178 additions and 87 deletions

View file

@ -6,54 +6,141 @@
See the file LICENSE for copying permission. See the file LICENSE for copying permission.
""" """
from . error import Error from sleekxmpp.stanza import Error
from . rootstanza import RootStanza from sleekxmpp.stanza.rootstanza import RootStanza
from .. xmlstream.stanzabase import StanzaBase, ET from sleekxmpp.xmlstream.stanzabase import StanzaBase, ET
class Presence(RootStanza): class Presence(RootStanza):
interfaces = set(('type', 'to', 'from', 'id', 'show', 'status', 'priority'))
types = set(('available', 'unavailable', 'error', 'probe', 'subscribe', 'subscribed', 'unsubscribe', 'unsubscribed'))
showtypes = set(('dnd', 'chat', 'xa', 'away'))
sub_interfaces = set(('show', 'status', 'priority'))
name = 'presence'
plugin_attrib = name
namespace = 'jabber:client'
def setShow(self, show): """
if show in self.showtypes: XMPP's <presence> stanza allows entities to know the status of other
self._setSubText('show', text=show) clients and components. Since it is currently the only multi-cast
return self stanza in XMPP, many extensions add more information to <presence>
stanzas to broadcast to every entry in the roster, such as
capabilities, music choices, or locations (XEP-0115: Entity Capabilities
and XEP-0163: Personal Eventing Protocol).
def setType(self, value): Since <presence> stanzas are broadcast when an XMPP entity changes
if value in self.types: its status, the bulk of the traffic in an XMPP network will be from
self['show'] = None <presence> stanzas. Therefore, do not include more information than
if value == 'available': necessary in a status message or within a <presence> stanza in order
value = '' to help keep the network running smoothly.
self._setAttr('type', value)
elif value in self.showtypes:
self['show'] = value
return self
def setPriority(self, value): Example <presence> stanzas:
self._setSubText('priority', text = str(value)) <presence />
def getPriority(self): <presence from="user@example.com">
p = self._getSubText('priority') <show>away</show>
if not p: p = 0 <status>Getting lunch.</status>
return int(p) <priority>5</priority>
</presence>
def getType(self):
out = self._getAttr('type') <presence type="unavailable" />
if not out:
out = self['show'] <presence to="user@otherhost.com" type="subscribe" />
if not out or out is None:
out = 'available' Stanza Interface:
return out priority -- A value used by servers to determine message routing.
show -- The type of status, such as away or available for chat.
def reply(self): status -- Custom, human readable status message.
if self['type'] == 'unsubscribe':
self['type'] = 'unsubscribed' Attributes:
elif self['type'] == 'subscribe': types -- One of: available, unavailable, error, probe,
self['type'] = 'subscribed' subscribe, subscribed, unsubscribe,
return StanzaBase.reply(self) and unsubscribed.
showtypes -- One of: away, chat, dnd, and xa.
Methods:
reply -- Overrides StanzaBase.reply
setShow -- Set the value of the <show> element.
getType -- Get the value of the type attribute or <show> element.
setType -- Set the value of the type attribute or <show> element.
getPriority -- Get the value of the <priority> element.
setPriority -- Set the value of the <priority> element.
"""
namespace = 'jabber:client'
name = 'presence'
interfaces = set(('type', 'to', 'from', 'id', 'show',
'status', 'priority'))
sub_interfaces = set(('show', 'status', 'priority'))
plugin_attrib = name
types = set(('available', 'unavailable', 'error', 'probe', 'subscribe',
'subscribed', 'unsubscribe', 'unsubscribed'))
showtypes = set(('dnd', 'chat', 'xa', 'away'))
def setShow(self, show):
"""
Set the value of the <show> element.
Arguments:
show -- Must be one of: away, chat, dnd, or xa.
"""
if show in self.showtypes:
self._setSubText('show', text=show)
return self
def setType(self, value):
"""
Set the type attribute's value, and the <show> element
if applicable.
Arguments:
value -- Must be in either self.types or self.showtypes.
"""
if value in self.types:
self['show'] = None
if value == 'available':
value = ''
self._setAttr('type', value)
elif value in self.showtypes:
self['show'] = value
return self
def setPriority(self, value):
"""
Set the entity's priority value. Some server use priority to
determine message routing behavior.
Bot clients should typically use a priority of 0 if the same
JID is used elsewhere by a human-interacting client.
Arguments:
value -- An integer value greater than or equal to 0.
"""
self._setSubText('priority', text=str(value))
def getPriority(self):
"""
Return the value of the <presence> element as an integer.
"""
p = self._getSubText('priority')
if not p:
p = 0
return int(p)
def getType(self):
"""
Return the value of the <presence> stanza's type attribute, or
the value of the <show> element.
"""
out = self._getAttr('type')
if not out:
out = self['show']
if not out or out is None:
out = 'available'
return out
def reply(self):
"""
Set the appropriate presence reply type.
Overrides StanzaBase.reply.
"""
if self['type'] == 'unsubscribe':
self['type'] = 'unsubscribed'
elif self['type'] == 'subscribe':
self['type'] = 'subscribed'
return StanzaBase.reply(self)

View file

@ -2,52 +2,56 @@ import sleekxmpp
from sleektest import * from sleektest import *
from sleekxmpp.stanza.presence import Presence from sleekxmpp.stanza.presence import Presence
class TestPresenceStanzas(SleekTest): class TestPresenceStanzas(SleekTest):
def testPresenceShowRegression(self):
"""Regression check presence['type'] = 'dnd' show value working"""
p = self.Presence()
p['type'] = 'dnd'
self.checkPresence(p, """
<presence><show>dnd</show></presence>
""")
def testPresenceType(self): def testPresenceShowRegression(self):
"""Test manipulating presence['type']""" """Regression check presence['type'] = 'dnd' show value working"""
p = self.Presence() p = self.Presence()
p['type'] = 'available' p['type'] = 'dnd'
self.checkPresence(p, """ self.checkPresence(p, "<presence><show>dnd</show></presence>")
<presence />
""")
self.failUnless(p['type'] == 'available', "Incorrect presence['type'] for type 'available'")
for showtype in ['away', 'chat', 'dnd', 'xa']: def testPresenceType(self):
p['type'] = showtype """Test manipulating presence['type']"""
self.checkPresence(p, """ p = self.Presence()
<presence><show>%s</show></presence> p['type'] = 'available'
""" % showtype) self.checkPresence(p, "<presence />")
self.failUnless(p['type'] == showtype, "Incorrect presence['type'] for type '%s'" % showtype) self.failUnless(p['type'] == 'available',
"Incorrect presence['type'] for type 'available'")
p['type'] = None for showtype in ['away', 'chat', 'dnd', 'xa']:
self.checkPresence(p, """ p['type'] = showtype
<presence /> self.checkPresence(p, """
""") <presence><show>%s</show></presence>
""" % showtype)
self.failUnless(p['type'] == showtype,
"Incorrect presence['type'] for type '%s'" % showtype)
p['type'] = None
self.checkPresence(p, "<presence />")
def testPresenceUnsolicitedOffline(self):
"""
Unsolicted offline presence does not spawn changed_status
or update the roster.
"""
p = self.Presence()
p['type'] = 'unavailable'
p['from'] = 'bill@chadmore.com/gmail15af'
c = sleekxmpp.ClientXMPP('crap@wherever', 'password')
happened = []
def handlechangedpresence(event):
happened.append(True)
c.add_event_handler("changed_status", handlechangedpresence)
c._handlePresence(p)
self.failUnless(happened == [],
"changed_status event triggered for extra unavailable presence")
self.failUnless(c.roster == {},
"Roster updated for superfulous unavailable presence")
def testPresenceUnsolicitedOffline(self):
"""Unsolicted offline presence does not spawn changed_status or update roster"""
p = self.Presence()
p['type'] = 'unavailable'
p['from'] = 'bill@chadmore.com/gmail15af'
c = sleekxmpp.ClientXMPP('crap@wherever', 'password')
happened = []
def handlechangedpresence(event):
happened.append(True)
c.add_event_handler("changed_status", handlechangedpresence)
c._handlePresence(p)
self.failUnless(happened == [], "changed_status event triggered for superfulous unavailable presence")
self.failUnless(c.roster == {}, "Roster updated for superfulous unavailable presence")
suite = unittest.TestLoader().loadTestsFromTestCase(TestPresenceStanzas) suite = unittest.TestLoader().loadTestsFromTestCase(TestPresenceStanzas)